| 'use strict'; |
| |
| /** |
| * Create test that a CSS property computes to the expected value. |
| * The document element #target is used to perform the test. |
| * |
| * @param {string} property The name of the CSS property being tested. |
| * @param {string} value A specified value for the property. |
| * @param {string|array} serializedValue The expected serialized value, |
| * or an array of permitted serializations. |
| * If omitted, defaults to the specified value. |
| * @param {object} options Additional test information, such as a custom |
| * comparison function required for color tests. |
| * comparisonFunction is a function that takes two |
| * arguments, actual and expected and contains asserts. |
| */ |
| function test_valid_value(property, value, serializedValue, options = {}) { |
| if (arguments.length < 3) |
| serializedValue = value; |
| |
| var stringifiedValue = JSON.stringify(value); |
| |
| test(function(){ |
| var div = document.getElementById('target') || document.createElement('div'); |
| div.style[property] = ""; |
| div.style[property] = value; |
| var readValue = div.style.getPropertyValue(property); |
| assert_not_equals(readValue, "", "property should be set"); |
| if (options.comparisonFunction) |
| options.comparisonFunction(readValue, serializedValue); |
| else if (Array.isArray(serializedValue)) |
| assert_in_array(readValue, serializedValue, "serialization should be sound"); |
| else |
| assert_equals(readValue, serializedValue, "serialization should be canonical"); |
| |
| div.style[property] = readValue; |
| assert_equals(div.style.getPropertyValue(property), readValue, "serialization should round-trip"); |
| |
| }, "e.style['" + property + "'] = " + stringifiedValue + " should set the property value"); |
| } |
| |
| function test_invalid_value(property, value) { |
| var stringifiedValue = JSON.stringify(value); |
| |
| test(function(){ |
| var div = document.getElementById('target') || document.createElement('div'); |
| div.style[property] = ""; |
| div.style[property] = value; |
| assert_equals(div.style.getPropertyValue(property), ""); |
| }, "e.style['" + property + "'] = " + stringifiedValue + " should not set the property value"); |
| } |
| |
| // serializedSelector can be the expected serialization of selector, |
| // or an array of permitted serializations, |
| // or omitted if value should serialize as selector. |
| function test_valid_selector(selector, serializedSelector) { |
| if (arguments.length < 2) |
| serializedSelector = selector; |
| |
| const stringifiedSelector = JSON.stringify(selector); |
| |
| test(function(){ |
| document.querySelector(selector); |
| assert_true(true, stringifiedSelector + " should not throw in querySelector"); |
| |
| const style = document.createElement("style"); |
| document.head.append(style); |
| const {sheet} = style; |
| document.head.removeChild(style); |
| const {cssRules} = sheet; |
| |
| assert_equals(cssRules.length, 0, "Sheet should have no rule"); |
| sheet.insertRule(selector + "{}"); |
| assert_equals(cssRules.length, 1, "Sheet should have 1 rule"); |
| |
| const readSelector = cssRules[0].selectorText; |
| if (Array.isArray(serializedSelector)) |
| assert_in_array(readSelector, serializedSelector, "serialization should be sound"); |
| else |
| assert_equals(readSelector, serializedSelector, "serialization should be canonical"); |
| |
| sheet.deleteRule(0); |
| assert_equals(cssRules.length, 0, "Sheet should have no rule"); |
| sheet.insertRule(readSelector + "{}"); |
| assert_equals(cssRules.length, 1, "Sheet should have 1 rule"); |
| |
| assert_equals(cssRules[0].selectorText, readSelector, "serialization should round-trip"); |
| }, stringifiedSelector + " should be a valid selector"); |
| } |
| |
| function test_invalid_selector(selector) { |
| const stringifiedSelector = JSON.stringify(selector); |
| |
| test(function(){ |
| assert_throws_dom( |
| DOMException.SYNTAX_ERR, |
| () => document.querySelector(selector), |
| stringifiedSelector + " should throw in querySelector"); |
| |
| const style = document.createElement("style"); |
| document.head.append(style); |
| const {sheet} = style; |
| document.head.removeChild(style); |
| |
| assert_throws_dom( |
| DOMException.SYNTAX_ERR, |
| () => sheet.insertRule(selector + "{}"), |
| stringifiedSelector + " should throw in insertRule"); |
| }, stringifiedSelector + " should be an invalid selector"); |
| } |
| |
| // serialized can be the expected serialization of rule, or an array of |
| // permitted serializations, or omitted if value should serialize as rule. |
| function test_valid_rule(rule, serialized) { |
| if (serialized === undefined) |
| serialized = rule; |
| |
| test(function(){ |
| const style = document.createElement("style"); |
| document.head.append(style); |
| const {sheet} = style; |
| document.head.removeChild(style); |
| const {cssRules} = sheet; |
| |
| assert_equals(cssRules.length, 0, "Sheet should have no rules"); |
| sheet.insertRule(rule); |
| assert_equals(cssRules.length, 1, "Sheet should have 1 rule"); |
| |
| const serialization = cssRules[0].cssText; |
| if (Array.isArray(serialized)) |
| assert_in_array(serialization, serialized, "serialization should be sound"); |
| else |
| assert_equals(serialization, serialized, "serialization should be canonical"); |
| |
| sheet.deleteRule(0); |
| assert_equals(cssRules.length, 0, "Sheet should have no rule"); |
| sheet.insertRule(serialization); |
| assert_equals(cssRules.length, 1, "Sheet should have 1 rule"); |
| |
| assert_equals(cssRules[0].cssText, serialization, "serialization should round-trip"); |
| }, rule + " should be a valid rule"); |
| } |
| |
| function test_invalid_rule(rule) { |
| test(function(){ |
| const style = document.createElement("style"); |
| document.head.append(style); |
| const {sheet} = style; |
| document.head.removeChild(style); |
| |
| assert_throws_dom( |
| DOMException.SYNTAX_ERR, |
| () => sheet.insertRule(rule), |
| rule + " should throw in insertRule"); |
| }, rule + " should be an invalid rule"); |
| } |
| |
| function _set_style(rule) { |
| const style = document.createElement('style'); |
| style.innerText = rule; |
| document.head.append(style); |
| const { sheet } = style; |
| document.head.removeChild(style); |
| return sheet; |
| } |
| |
| function test_keyframes_name_valid(keyframes_name) { |
| test(t => { |
| const sheet = _set_style(`@keyframes ${keyframes_name} {}`); |
| assert_equals(sheet.cssRules.length, 1); |
| }, `valid: @keyframes ${keyframes_name} { }`); |
| } |
| |
| function test_keyframes_name_invalid(keyframes_name) { |
| test(t => { |
| const sheet = _set_style(`@keyframes ${keyframes_name} {}`); |
| assert_equals(sheet.cssRules.length, 0); |
| }, `invalid: @keyframes ${keyframes_name} { }`); |
| } |