| <!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> |