pixel-length-attributes.html (6242B)
1 <!doctype html> 2 <meta charset=utf-8> 3 <!-- Creating iframes is slow in browsers --> 4 <meta name=timeout content=long> 5 <title>Test handling of attributes that map to pixel length properties</title> 6 <link rel="help" 7 href="https://html.spec.whatwg.org/multipage/rendering.html#maps-to-the-pixel-length-property"> 8 <script src=/resources/testharness.js></script> 9 <script src=/resources/testharnessreport.js></script> 10 <body> 11 <div id="container" style="display: none"> 12 <img id="defaultImg"> 13 <object id="defaultObject"></object> 14 <input type="image" id="defaultInput"></input> 15 </div> 16 <script> 17 /* 18 * This test tests 19 * https://html.spec.whatwg.org/multipage/rendering.html#maps-to-the-pixel-length-property 20 * for various elements and various values. 21 */ 22 23 /* 24 * Array of input/output pairs. The input is the string to use as the 25 * attribute value. The output is the string expected as the computed style 26 * for the relevant CSS property. 27 */ 28 const valid_values = [ 29 [ "200", "200px" ], 30 [ "1007", "1007px" ], 31 [ " 00523 ", "523px" ], 32 [ "200.", "200px" ], 33 [ "200.25", "200px" ], 34 [ "200.7", "200px" ], 35 [ "0", "0px" ], 36 [ "-0", "0px" ], 37 [ "+0", "0px" ], 38 [ "+200", "200px" ], 39 [ "200in", "200px" ], 40 [ "200.25in", "200px" ], 41 [ " +200in ", "200px" ], 42 [ "200%", "200px" ], 43 [ "200.%", "200px" ], 44 [ "200.25%", "200px" ], 45 ]; 46 47 /* 48 * Array of invalid values. These should lead to the default value of the 49 * relevant CSS property. 50 */ 51 const invalid_values = [ 52 "-200", 53 "-200px", 54 " -200", 55 "+-200", 56 "-+200", 57 ]; 58 59 /* 60 * Array of tests. Each test consists of the following information: 61 * 62 * 1) A function to call to create the element to test. This returns a 63 * 3-element array: The element to set the attribute on, the element to 64 * compute style on, and a cleanup function to call when done. 65 * 2) The name of the attribute to set. 66 * 3) The name of the computed style property to get. 67 * 4) An element that can be used to determine the fallback style value for 68 * invalid values. 69 */ 70 const tests = [ 71 [ createIframe, "marginwidth", "marginLeft", document.body ], 72 [ createIframe, "marginwidth", "marginRight", document.body ], 73 [ createIframe, "marginheight", "marginTop", document.body ], 74 [ createIframe, "marginheight", "marginBottom", document.body ], 75 [ createFrame, "marginwidth", "marginLeft", document.body ], 76 [ createFrame, "marginwidth", "marginRight", document.body ], 77 [ createFrame, "marginheight", "marginTop", document.body ], 78 [ createFrame, "marginheight", "marginBottom", document.body ], 79 [ createBody, "marginwidth", "marginLeft", document.body ], 80 [ createBody, "marginwidth", "marginRight", document.body ], 81 [ createBody, "leftmargin", "marginLeft", document.body ], 82 [ createBody, "rightmargin", "marginRight", document.body ], 83 [ createBody, "marginheight", "marginTop", document.body ], 84 [ createBody, "marginheight", "marginBottom", document.body ], 85 [ createBody, "topmargin", "marginTop", document.body ], 86 [ createBody, "bottommargin", "marginBottom", document.body ], 87 [ newElem("img"), "border", "borderTopWidth", defaultImg ], 88 [ newElem("img"), "border", "borderRightWidth", defaultImg ], 89 [ newElem("img"), "border", "borderBottomWidth", defaultImg ], 90 [ newElem("img"), "border", "borderLeftWidth", defaultImg ], 91 [ newElem("object"), "border", "borderTopWidth", defaultObject ], 92 [ newElem("object"), "border", "borderRightWidth", defaultObject ], 93 [ newElem("object"), "border", "borderBottomWidth", defaultObject ], 94 [ newElem("object"), "border", "borderLeftWidth", defaultObject ], 95 [ newImageInput, "border", "borderTopWidth", defaultInput ], 96 [ newImageInput, "border", "borderRightWidth", defaultInput ], 97 [ newImageInput, "border", "borderBottomWidth", defaultInput ], 98 [ newImageInput, "border", "borderLeftWidth", defaultInput ], 99 ]; 100 101 function newElem(name) { 102 return () => { 103 var elem = document.createElement(name); 104 document.getElementById("container").appendChild(elem); 105 return [ elem, elem, () => elem.remove() ]; 106 } 107 } 108 109 function newImageInput() { 110 var elem = document.createElement("input"); 111 elem.type = "image"; 112 document.getElementById("container").appendChild(elem); 113 return [ elem, elem, () => elem.remove() ]; 114 } 115 116 function createIframe() { 117 let ifr = document.createElement("iframe"); 118 document.body.appendChild(ifr); 119 return [ ifr, ifr.contentDocument.body, () => ifr.remove() ]; 120 } 121 122 function createBody() { 123 let ifr = document.createElement("iframe"); 124 document.body.appendChild(ifr); 125 return [ ifr.contentDocument.body, ifr.contentDocument.body, () => ifr.remove() ]; 126 } 127 128 function createFrame() { 129 // We need to create a separate iframe to put our frameset into. 130 let ifr = document.createElement("iframe"); 131 document.body.appendChild(ifr); 132 let doc = ifr.contentDocument; 133 let root = doc.documentElement; 134 while (root.firstChild) { 135 root.firstChild.remove(); 136 } 137 let frameset = doc.createElement("frameset"); 138 frameset.setAttribute("rows", "*"); 139 frameset.setAttribute("cols", "*"); 140 let frame = doc.createElement("frame"); 141 frameset.appendChild(frame); 142 root.appendChild(frameset); 143 return [ frame, frame.contentDocument.body, () => ifr.remove() ]; 144 } 145 146 function style(element) { 147 return element.ownerDocument.defaultView.getComputedStyle(element); 148 } 149 150 for (let [setup, attr, prop, default_elem] of tests) { 151 for (let [value, result] of valid_values) { 152 let [ attr_elem, prop_elem, cleanup ] = setup(); 153 test(function() { 154 this.add_cleanup(cleanup); 155 attr_elem.setAttribute(attr, value); 156 assert_equals(attr_elem.getAttribute(attr), value); 157 assert_equals(style(prop_elem)[prop], result); 158 }, `<${attr_elem.localName} ${attr}="${value}"> mapping to ${prop}`); 159 } 160 161 let defaultVal = style(default_elem)[prop]; 162 for (let value of invalid_values) { 163 let [ attr_elem, prop_elem, cleanup ] = setup(); 164 test(function() { 165 this.add_cleanup(cleanup); 166 attr_elem.setAttribute(attr, value); 167 assert_equals(attr_elem.getAttribute(attr), value); 168 assert_equals(style(prop_elem)[prop], defaultVal); 169 }, `<${attr_elem.localName} ${attr}="${value}"> mapping to ${prop}`); 170 } 171 } 172 </script> 173 </body>