summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/html/rendering/pixel-length-attributes.html
blob: 888e6d0a3ff7ade1f9f3c5849f94cdcd4f13b231 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
<!doctype html>
<meta charset=utf-8>
<!-- Creating iframes is slow in browsers -->
<meta name=timeout content=long>
<title>Test handling of attributes that map to pixel length properties</title>
<link rel="help"
      href="https://html.spec.whatwg.org/multipage/rendering.html#maps-to-the-pixel-length-property">
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<body>
  <div id="container" style="display: none">
    <img id="defaultImg">
    <object id="defaultObject"></object>
    <input type="image" id="defaultInput"></input>
  </div>
<script>
 /*
  * This test tests
  * https://html.spec.whatwg.org/multipage/rendering.html#maps-to-the-pixel-length-property
  * for various elements and various values.
  */

 /*
  * Array of input/output pairs.  The input is the string to use as the
  * attribute value.  The output is the string expected as the computed style
  * for the relevant CSS property.
  */
const valid_values = [
  [ "200", "200px" ],
  [ "1007", "1007px" ],
  [ "   00523   ", "523px" ],
  [ "200.", "200px" ],
  [ "200.25", "200px" ],
  [ "200.7", "200px" ],
  [ "0", "0px" ],
  [ "-0", "0px" ],
  [ "+0", "0px" ],
  [ "+200", "200px" ],
  [ "200in", "200px" ],
  [ "200.25in", "200px" ],
  [ "   +200in    ", "200px" ],
  [ "200%", "200px" ],
  [ "200.%", "200px" ],
  [ "200.25%", "200px" ],
];

 /*
  * Array of invalid values.  These should lead to the default value of the
  * relevant CSS property.
  */
const invalid_values = [
  "-200",
  "-200px",
  "   -200",
  "+-200",
  "-+200",
];

/*
 * Array of tests.  Each test consists of the following information:
 *
 * 1) A function to call to create the element to test.  This returns a
 *    3-element array: The element to set the attribute on, the element to
 *    compute style on, and a cleanup function to call when done.
 * 2) The name of the attribute to set.
 * 3) The name of the computed style property to get.
 * 4) An element that can be used to determine the fallback style value for
 *    invalid values.
 */
const tests = [
  [ createIframe, "marginwidth", "marginLeft", document.body ],
  [ createIframe, "marginwidth", "marginRight", document.body ],
  [ createIframe, "marginheight", "marginTop", document.body ],
  [ createIframe, "marginheight", "marginBottom", document.body ],
  [ createFrame, "marginwidth", "marginLeft", document.body ],
  [ createFrame, "marginwidth", "marginRight", document.body ],
  [ createFrame, "marginheight", "marginTop", document.body ],
  [ createFrame, "marginheight", "marginBottom", document.body ],
  [ createBody, "marginwidth", "marginLeft", document.body ],
  [ createBody, "marginwidth", "marginRight", document.body ],
  [ createBody, "leftmargin", "marginLeft", document.body ],
  [ createBody, "rightmargin", "marginRight", document.body ],
  [ createBody, "marginheight", "marginTop", document.body ],
  [ createBody, "marginheight", "marginBottom", document.body ],
  [ createBody, "topmargin", "marginTop", document.body ],
  [ createBody, "bottommargin", "marginBottom", document.body ],
  [ newElem("img"), "border", "borderTopWidth", defaultImg ],
  [ newElem("img"), "border", "borderRightWidth", defaultImg ],
  [ newElem("img"), "border", "borderBottomWidth", defaultImg ],
  [ newElem("img"), "border", "borderLeftWidth", defaultImg ],
  [ newElem("object"), "border", "borderTopWidth", defaultObject ],
  [ newElem("object"), "border", "borderRightWidth", defaultObject ],
  [ newElem("object"), "border", "borderBottomWidth", defaultObject ],
  [ newElem("object"), "border", "borderLeftWidth", defaultObject ],
  [ newImageInput, "border", "borderTopWidth", defaultInput ],
  [ newImageInput, "border", "borderRightWidth", defaultInput ],
  [ newImageInput, "border", "borderBottomWidth", defaultInput ],
  [ newImageInput, "border", "borderLeftWidth", defaultInput ],
];

function newElem(name) {
  return () => {
    var elem = document.createElement(name);
    document.getElementById("container").appendChild(elem);
    return [ elem, elem, () => elem.remove() ];
  }
}

function newImageInput() {
  var elem = document.createElement("input");
  elem.type = "image";
  document.getElementById("container").appendChild(elem);
  return [ elem, elem, () => elem.remove() ];
}

function createIframe() {
  let ifr = document.createElement("iframe");
  document.body.appendChild(ifr);
  return [ ifr, ifr.contentDocument.body, () => ifr.remove() ];
 }

function createBody() {
  let ifr = document.createElement("iframe");
  document.body.appendChild(ifr);
  return [ ifr.contentDocument.body, ifr.contentDocument.body, () => ifr.remove() ];
}

function createFrame() {
  // We need to create a separate iframe to put our frameset into.
  let ifr = document.createElement("iframe");
  document.body.appendChild(ifr);
  let doc = ifr.contentDocument;
  let root = doc.documentElement;
  while (root.firstChild) {
    root.firstChild.remove();
  }
  let frameset = doc.createElement("frameset");
  frameset.setAttribute("rows", "*");
  frameset.setAttribute("cols", "*");
  let frame = doc.createElement("frame");
  frameset.appendChild(frame);
  root.appendChild(frameset);
  return [ frame, frame.contentDocument.body, () => ifr.remove() ];
}

function style(element) {
  return element.ownerDocument.defaultView.getComputedStyle(element);
}

for (let [setup, attr, prop, default_elem] of tests) {
  for (let [value, result] of valid_values) {
    let [ attr_elem, prop_elem, cleanup ] = setup();
    test(function() {
      this.add_cleanup(cleanup);
      attr_elem.setAttribute(attr, value);
      assert_equals(attr_elem.getAttribute(attr), value);
      assert_equals(style(prop_elem)[prop], result);
    }, `<${attr_elem.localName} ${attr}="${value}"> mapping to ${prop}`);
  }

  let defaultVal = style(default_elem)[prop];
  for (let value of invalid_values) {
    let [ attr_elem, prop_elem, cleanup ] = setup();
    test(function() {
      this.add_cleanup(cleanup);
      attr_elem.setAttribute(attr, value);
      assert_equals(attr_elem.getAttribute(attr), value);
      assert_equals(style(prop_elem)[prop], defaultVal);
    }, `<${attr_elem.localName} ${attr}="${value}"> mapping to ${prop}`);
  }
}
</script>
</body>