cssstyledeclaration-setter-declarations.html (6192B)
1 <!DOCTYPE html> 2 <title>CSSOM test: declaration block after setting via CSSOM</title> 3 <link rel="help" href="https://drafts.csswg.org/cssom/#set-a-css-declaration-value"> 4 <script src="/resources/testharness.js"></script> 5 <script src="/resources/testharnessreport.js"></script> 6 <div id="log"></div> 7 <script> 8 function generateCSSDeclBlock(props) { 9 let elem = document.createElement("div"); 10 let cssText = props.map(({name, value, priority}) => { 11 let longhand = `${name}: ${value}`; 12 if (priority) { 13 longhand += "!" + priority; 14 } 15 return longhand + ";"; 16 }).join(" "); 17 elem.setAttribute("style", cssText); 18 return elem.style; 19 } 20 function compareByName(a, b) { 21 if (a.name < b.name) return -1; 22 if (a.name > b.name) return 1; 23 return 0; 24 } 25 function checkDeclarationsAnyOrder(block, props, msg) { 26 let actual = []; 27 for (let name of block) { 28 let value = block.getPropertyValue(name); 29 let priority = block.getPropertyPriority(name); 30 actual.push({name, value, priority}); 31 } 32 actual.sort(compareByName); 33 let expected = Array.from(props); 34 expected.sort(compareByName); 35 assert_object_equals(actual, expected, "Declaration block content should match " + msg); 36 } 37 function longhand(name, value, priority="") { 38 return {name, value, priority}; 39 } 40 function* shorthand(name, value, priority="") { 41 for (let subprop of SUBPROPS[name]) { 42 yield longhand(subprop, value, priority); 43 } 44 } 45 46 const SUBPROPS = { 47 "margin": ["margin-top", "margin-right", "margin-bottom", "margin-left"], 48 "padding": ["padding-top", "padding-right", "padding-bottom", "padding-left"], 49 }; 50 51 test(function() { 52 let expectedDecls = [ 53 longhand("top", "1px"), 54 longhand("bottom", "2px"), 55 longhand("left", "3px", "important"), 56 longhand("right", "4px"), 57 ]; 58 let block = generateCSSDeclBlock(expectedDecls); 59 checkDeclarationsAnyOrder(block, expectedDecls, "in initial block"); 60 61 block.setProperty("top", "5px", "important"); 62 expectedDecls[0] = longhand("top", "5px", "important"); 63 checkDeclarationsAnyOrder(block, expectedDecls, "after setting existing property"); 64 65 block.setProperty("bottom", "2px"); 66 checkDeclarationsAnyOrder(block, expectedDecls, "after setting existing property with identical value"); 67 68 block.setProperty("left", "3px"); 69 expectedDecls[2].priority = ""; 70 checkDeclarationsAnyOrder(block, expectedDecls, "after setting existing property with different priority"); 71 72 block.setProperty("float", "none"); 73 expectedDecls.push(longhand("float", "none")); 74 checkDeclarationsAnyOrder(block, expectedDecls, "after setting non-existing property"); 75 }, "setProperty with longhand should update only the declaration being set"); 76 77 test(function() { 78 let expectedDecls = [ 79 longhand("top", "1px"), 80 longhand("bottom", "2px"), 81 longhand("left", "3px", "important"), 82 longhand("right", "4px"), 83 ]; 84 let block = generateCSSDeclBlock(expectedDecls); 85 checkDeclarationsAnyOrder(block, expectedDecls, "in initial block"); 86 87 block.top = "5px"; 88 expectedDecls[0] = longhand("top", "5px"); 89 checkDeclarationsAnyOrder(block, expectedDecls, "after setting existing property"); 90 91 block.bottom = "2px"; 92 checkDeclarationsAnyOrder(block, expectedDecls, "after setting existing property with identical value"); 93 94 block.left = "3px"; 95 expectedDecls[2].priority = ""; 96 checkDeclarationsAnyOrder(block, expectedDecls, "after setting existing property with different priority"); 97 98 block.float = "none"; 99 expectedDecls.push(longhand("float", "none")); 100 checkDeclarationsAnyOrder(block, expectedDecls, "after setting non-existing property"); 101 }, "property setter should update only the declaration being set"); 102 103 test(function() { 104 let expectedDecls = [ 105 ...shorthand("margin", "1px"), 106 longhand("top", "2px"), 107 ...shorthand("padding", "3px", "important"), 108 ]; 109 let block = generateCSSDeclBlock(expectedDecls); 110 checkDeclarationsAnyOrder(block, expectedDecls, "in initial block"); 111 112 block.setProperty("margin", "4px"); 113 for (let i = 0; i < 4; i++) { 114 expectedDecls[i].value = "4px"; 115 } 116 checkDeclarationsAnyOrder(block, expectedDecls, "after setting an existing shorthand"); 117 118 block.setProperty("margin", "4px"); 119 checkDeclarationsAnyOrder(block, expectedDecls, "after setting an existing shorthand with identical value"); 120 121 block.setProperty("padding", "3px"); 122 for (let i = 5; i < 9; i++) { 123 expectedDecls[i].priority = ""; 124 } 125 checkDeclarationsAnyOrder(block, expectedDecls, "after setting an existing shorthand with different priority"); 126 127 block.setProperty("margin-bottom", "5px", "important"); 128 expectedDecls[2] = longhand("margin-bottom", "5px", "important"); 129 checkDeclarationsAnyOrder(block, expectedDecls, "after setting a longhand in an existing shorthand"); 130 }, "setProperty with shorthand should update only the declarations being set"); 131 132 test(function() { 133 let expectedDecls = [ 134 ...shorthand("margin", "1px"), 135 longhand("top", "2px"), 136 ...shorthand("padding", "3px", "important"), 137 ]; 138 let block = generateCSSDeclBlock(expectedDecls); 139 checkDeclarationsAnyOrder(block, expectedDecls, "in initial block"); 140 141 block.margin = "4px"; 142 for (let i = 0; i < 4; i++) { 143 expectedDecls[i].value = "4px"; 144 } 145 checkDeclarationsAnyOrder(block, expectedDecls, "after setting an existing shorthand"); 146 147 block.margin = "4px"; 148 checkDeclarationsAnyOrder(block, expectedDecls, "after setting an existing shorthand with identical value"); 149 150 block.padding = "3px"; 151 for (let i = 5; i < 9; i++) { 152 expectedDecls[i].priority = ""; 153 } 154 checkDeclarationsAnyOrder(block, expectedDecls, "after setting an existing shorthand with different priority"); 155 156 block.marginBottom = "5px"; 157 expectedDecls[2] = longhand("margin-bottom", "5px"); 158 checkDeclarationsAnyOrder(block, expectedDecls, "after setting a longhand in an existing shorthand"); 159 }, "longhand property setter should update only the decoarations being set"); 160 </script>