at-position-try-cssom.html (6970B)
1 <!DOCTYPE html> 2 <title>Tests the CSSOM interfaces of @position-try rules</title> 3 <link rel="help" href="https://drafts.csswg.org/css-anchor-position-1/#interfaces"> 4 <link rel="author" href="mailto:xiaochengh@chromium.org"> 5 <script src="/resources/testharness.js"></script> 6 <script src="/resources/testharnessreport.js"></script> 7 8 <div id="anchor"></div> 9 <div id="other-anchor"></div> 10 <div id="target"></div> 11 12 <script> 13 function createStyle(t, text) { 14 const style = document.createElement('style'); 15 style.textContent = text; 16 t.add_cleanup(() => style.remove()); 17 document.head.appendChild(style); 18 return style; 19 } 20 21 test(t => { 22 const style = createStyle( 23 t, '@position-try --pf { left: anchor(right); }'); 24 const positionTryRule = style.sheet.cssRules[0]; 25 assert_true(positionTryRule instanceof CSSPositionTryRule); 26 assert_equals(positionTryRule.name, '--pf'); 27 assert_true(positionTryRule.style instanceof CSSPositionTryDescriptors); 28 assert_equals(positionTryRule.style.length, 1); 29 assert_equals(positionTryRule.style.left, 'anchor(right)'); 30 }, 'CSSPositionTryRule attribute values'); 31 32 test(t => { 33 const style = createStyle(t, ` 34 @position-try --pf { top: anchor(top); left: 0; } 35 #anchor, #other-anchor, #target { 36 position: absolute; width: 100px; height: 100px; 37 } 38 #anchor { top: 100px; left: 0; anchor-name: --a; } 39 #other-anchor { top: 200px; left: 0; anchor-name: --b; } 40 #target { position-try-fallbacks: --pf; position-anchor: --a; left: 999999px; } 41 `); 42 const positionTryRule = style.sheet.cssRules[0]; 43 44 // Check the initial position fallback result 45 assert_equals(target.getBoundingClientRect().left, 0); 46 assert_equals(target.getBoundingClientRect().top, 100); 47 48 // `left` is an allowed property in `@position-try` and should affect position fallback. 49 positionTryRule.style.setProperty('left', 'anchor(right)'); 50 assert_equals(target.getBoundingClientRect().left, 100); 51 assert_equals(target.getBoundingClientRect().top, 100); 52 53 // This property are disallowed in `@position-try` rule, and hence should not affect 54 // position fallback. 55 positionTryRule.style.setProperty('position', 'static'); 56 assert_equals(target.getBoundingClientRect().left, 100); 57 assert_equals(target.getBoundingClientRect().top, 100); 58 59 // `position-anchor` is an allowed property in `@position-try` and should affect position fallback. 60 positionTryRule.style.setProperty('position-anchor', '--b'); 61 assert_equals(target.getBoundingClientRect().left, 100); 62 assert_equals(target.getBoundingClientRect().top, 200); 63 64 }, 'CSSPositionTryRule.style.setProperty setting allowed and disallowed properties'); 65 66 test(t => { 67 const style = createStyle(t, ` 68 @position-try --pf { 69 top: 10px; 70 left: 20px; 71 --x: 200px; 72 color: red; 73 } 74 `); 75 let declarations = style.sheet.cssRules[0].style; 76 assert_equals(declarations.length, 2); 77 assert_equals(declarations.item(0), 'top'); 78 assert_equals(declarations.item(1), 'left'); 79 }, 'CSSPositionTryDescriptors.item'); 80 81 test(t => { 82 const style = createStyle(t, '@position-try --pf {}'); 83 let declarations = style.sheet.cssRules[0].style; 84 assert_equals(declarations.length, 0); 85 declarations.cssText = `color:red;top:10px;`; 86 assert_equals(declarations.length, 1); 87 }, 'CSSPositionTryDescriptors.cssText'); 88 89 let supported_properties = [ 90 'margin', 91 'margin-top', 92 'margin-right', 93 'margin-bottom', 94 'margin-left', 95 'margin-block', 96 'margin-block-start', 97 'margin-block-end', 98 'margin-inline', 99 'margin-inline-start', 100 'margin-inline-end', 101 'inset', 102 'top', 103 'left', 104 'right', 105 'bottom', 106 'inset-block', 107 'inset-block-start', 108 'inset-block-end', 109 'inset-inline', 110 'inset-inline-start', 111 'inset-inline-end', 112 'width', 113 'height', 114 'min-width', 115 'max-width', 116 'min-height', 117 'max-height', 118 'block-size', 119 'min-block-size', 120 'max-block-size', 121 'inline-size', 122 'min-inline-size', 123 'max-inline-size', 124 'place-self', 125 'align-self', 126 'justify-self', 127 'position-anchor', 128 'position-area', 129 ]; 130 131 // A selection of unsupported properties. 132 let unsupported_properties = [ 133 'color', 134 'align-items', 135 'align-content', 136 'background', 137 'display', 138 'position', 139 'writing-mode', 140 'direction', 141 'syntax', // @property 142 ]; 143 144 let upperFirst = (x) => x[0].toUpperCase() + x.slice(1); 145 let lowerFirst = (x) => x[0].toLowerCase() + x.slice(1); 146 let toLowerCamelCase = (x) => lowerFirst(x.split('-').map(upperFirst).join('')); 147 148 // Test getting/setting the specified property on a CSSPositionTryDescriptors 149 // object. The property can either be supported or not supported, 150 // which determines the expected results. 151 function test_property(prop, supported) { 152 test(t => { 153 let decls = supported_properties.map(x => `${x}:unset;`).join(''); 154 let style = createStyle(t, `@position-try --pf { ${decls} }`); 155 let declarations = style.sheet.cssRules[0].style; 156 assert_equals(declarations.getPropertyValue(prop), supported ? 'unset' : ''); 157 }, `CSSPositionTryDescriptors.getPropertyValue(${prop})`); 158 159 test(t => { 160 let style = createStyle(t, '@position-try --pf {}'); 161 let declarations = style.sheet.cssRules[0].style; 162 declarations.setProperty(prop, 'unset'); 163 assert_equals(declarations.getPropertyValue(prop), supported ? 'unset' : ''); 164 }, `CSSPositionTryDescriptors.setProperty(${prop})`); 165 166 test(t => { 167 let decls = supported_properties.map(x => `${x}:unset;`).join(''); 168 let style = createStyle(t, `@position-try --pf { ${decls} }`); 169 let declarations = style.sheet.cssRules[0].style; 170 assert_equals(declarations[prop], supported ? 'unset' : undefined); 171 }, `CSSPositionTryDescriptors[${prop}] (set)`); 172 173 test(t => { 174 let style = createStyle(t, '@position-try --pf {}'); 175 let declarations = style.sheet.cssRules[0].style; 176 declarations[prop] = 'unset'; 177 assert_equals(declarations.getPropertyValue(prop), supported ? 'unset' : ''); 178 }, `CSSPositionTryDescriptors[${prop}] (get)`); 179 180 let camelCaseAttr = toLowerCamelCase(prop); 181 if (camelCaseAttr != prop) { 182 // Also test the camelCase version of the attribute. 183 test(t => { 184 let decls = supported_properties.map(x => `${x}:unset;`).join(''); 185 let style = createStyle(t, `@position-try --pf { ${decls} }`); 186 let declarations = style.sheet.cssRules[0].style; 187 assert_equals(declarations[camelCaseAttr], supported ? 'unset' : undefined); 188 }, `CSSPositionTryDescriptors[${camelCaseAttr}] (get)`); 189 190 test(t => { 191 let style = createStyle(t, '@position-try --pf {}'); 192 let declarations = style.sheet.cssRules[0].style; 193 declarations[camelCaseAttr] = 'unset'; 194 assert_equals(declarations.getPropertyValue(prop), supported ? 'unset' : ''); 195 }, `CSSPositionTryDescriptors[${camelCaseAttr}] (set)`); 196 } 197 } 198 199 supported_properties.forEach(x => { test_property(x, /* supported */ true); }); 200 unsupported_properties.forEach(x => { test_property(x, /* supported */ false); }); 201 202 </script>