parsing-testcommon.js (7396B)
1 'use strict'; 2 3 /** 4 * Create test that a CSS property computes to the expected value. 5 * The document element #target is used to perform the test. 6 * 7 * @param {string} property The name of the CSS property being tested. 8 * @param {string} value A specified value for the property. 9 * @param {string|array} serializedValue The expected serialized value, 10 * or an array of permitted serializations. 11 * If omitted, defaults to the specified value. 12 * @param {object} options Additional test information, such as a custom 13 * comparison function required for color tests. 14 * comparisonFunction is a function that takes two 15 * arguments, actual and expected and contains asserts. 16 */ 17 function test_valid_value(property, value, serializedValue, options = {}) { 18 if (arguments.length < 3) 19 serializedValue = value; 20 21 var stringifiedValue = JSON.stringify(value); 22 23 test(function(){ 24 var div = document.getElementById('target') || document.createElement('div'); 25 div.style[property] = ""; 26 div.style[property] = value; 27 var readValue = div.style.getPropertyValue(property); 28 assert_not_equals(readValue, "", "property should be set"); 29 if (options.comparisonFunction) 30 options.comparisonFunction(readValue, serializedValue); 31 else if (Array.isArray(serializedValue)) 32 assert_in_array(readValue, serializedValue, "serialization should be sound"); 33 else 34 assert_equals(readValue, serializedValue, "serialization should be canonical"); 35 36 div.style[property] = readValue; 37 assert_equals(div.style.getPropertyValue(property), readValue, "serialization should round-trip"); 38 39 }, "e.style['" + property + "'] = " + stringifiedValue + " should set the property value"); 40 } 41 42 function test_invalid_value(property, value) { 43 var stringifiedValue = JSON.stringify(value); 44 45 test(function(){ 46 var div = document.getElementById('target') || document.createElement('div'); 47 div.style[property] = ""; 48 div.style[property] = value; 49 assert_equals(div.style.getPropertyValue(property), ""); 50 }, "e.style['" + property + "'] = " + stringifiedValue + " should not set the property value"); 51 } 52 53 function test_valid_forgiving_selector(selector) { 54 test_valid_selector(selector, selector, { onlyWhenForgiving: true }); 55 } 56 57 // serializedSelector can be the expected serialization of selector, 58 // or an array of permitted serializations, 59 // or omitted if value should serialize as selector. 60 function test_valid_selector(selector, serializedSelector, options) { 61 if (arguments.length < 2) 62 serializedSelector = selector; 63 64 const stringifiedSelector = JSON.stringify(selector); 65 66 test(function(){ 67 document.querySelector(selector); 68 assert_true(true, stringifiedSelector + " should not throw in querySelector"); 69 70 const style = document.createElement("style"); 71 document.head.append(style); 72 const {sheet} = style; 73 document.head.removeChild(style); 74 const {cssRules} = sheet; 75 76 assert_equals(cssRules.length, 0, "Sheet should have no rule"); 77 sheet.insertRule(selector + "{}"); 78 assert_equals(cssRules.length, 1, "Sheet should have 1 rule"); 79 80 const readSelector = cssRules[0].selectorText; 81 if (Array.isArray(serializedSelector)) 82 assert_in_array(readSelector, serializedSelector, "serialization should be sound"); 83 else 84 assert_equals(readSelector, serializedSelector, "serialization should be canonical"); 85 86 sheet.deleteRule(0); 87 assert_equals(cssRules.length, 0, "Sheet should have no rule"); 88 sheet.insertRule(readSelector + "{}"); 89 assert_equals(cssRules.length, 1, "Sheet should have 1 rule"); 90 91 assert_equals(cssRules[0].selectorText, readSelector, "serialization should round-trip"); 92 93 let supports = !options?.onlyWhenForgiving; 94 assert_equals(CSS.supports(`selector(${selector})`), supports, "CSS.supports() reports the expected value"); 95 }, stringifiedSelector + " should be a valid selector"); 96 } 97 98 function test_invalid_selector(selector) { 99 const stringifiedSelector = JSON.stringify(selector); 100 101 test(function(){ 102 assert_throws_dom( 103 DOMException.SYNTAX_ERR, 104 () => document.querySelector(selector), 105 stringifiedSelector + " should throw in querySelector"); 106 107 const style = document.createElement("style"); 108 document.head.append(style); 109 const {sheet} = style; 110 document.head.removeChild(style); 111 112 assert_throws_dom( 113 DOMException.SYNTAX_ERR, 114 () => sheet.insertRule(selector + "{}"), 115 stringifiedSelector + " should throw in insertRule"); 116 }, stringifiedSelector + " should be an invalid selector"); 117 } 118 119 // serialized can be the expected serialization of rule, or an array of 120 // permitted serializations, or omitted if value should serialize as rule. 121 function test_valid_rule(rule, serialized) { 122 if (serialized === undefined) 123 serialized = rule; 124 125 test(function(){ 126 const style = document.createElement("style"); 127 document.head.append(style); 128 const {sheet} = style; 129 document.head.removeChild(style); 130 const {cssRules} = sheet; 131 132 assert_equals(cssRules.length, 0, "Sheet should have no rules"); 133 sheet.insertRule(rule); 134 assert_equals(cssRules.length, 1, "Sheet should have 1 rule"); 135 136 const serialization = cssRules[0].cssText; 137 if (Array.isArray(serialized)) 138 assert_in_array(serialization, serialized, "serialization should be sound"); 139 else 140 assert_equals(serialization, serialized, "serialization should be canonical"); 141 142 sheet.deleteRule(0); 143 assert_equals(cssRules.length, 0, "Sheet should have no rule"); 144 sheet.insertRule(serialization); 145 assert_equals(cssRules.length, 1, "Sheet should have 1 rule"); 146 147 assert_equals(cssRules[0].cssText, serialization, "serialization should round-trip"); 148 }, rule + " should be a valid rule"); 149 } 150 151 function test_invalid_rule(rule) { 152 test(function(){ 153 const style = document.createElement("style"); 154 document.head.append(style); 155 const {sheet} = style; 156 document.head.removeChild(style); 157 158 assert_throws_dom( 159 DOMException.SYNTAX_ERR, 160 () => sheet.insertRule(rule), 161 rule + " should throw in insertRule"); 162 }, rule + " should be an invalid rule"); 163 } 164 165 function _set_style(rule) { 166 const style = document.createElement('style'); 167 style.innerText = rule; 168 document.head.append(style); 169 const { sheet } = style; 170 document.head.removeChild(style); 171 return sheet; 172 } 173 174 function test_keyframes_name_valid(keyframes_name) { 175 test(t => { 176 const sheet = _set_style(`@keyframes ${keyframes_name} {}`); 177 assert_equals(sheet.cssRules.length, 1); 178 }, `valid: @keyframes ${keyframes_name} { }`); 179 } 180 181 function test_keyframes_name_invalid(keyframes_name) { 182 test(t => { 183 const sheet = _set_style(`@keyframes ${keyframes_name} {}`); 184 assert_equals(sheet.cssRules.length, 0); 185 }, `invalid: @keyframes ${keyframes_name} { }`); 186 }