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