test_inspector-inactive-property-helper.html (5542B)
1 <!DOCTYPE HTML> 2 <html> 3 <head> 4 <meta charset="utf-8"> 5 <title>Test for InactivePropertyHelper</title> 6 <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> 7 <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"> 8 <script type="application/javascript"> 9 "use strict"; 10 SimpleTest.waitForExplicitFinish(); 11 12 (async function() { 13 const { require } = ChromeUtils.importESModule("resource://devtools/shared/loader/Loader.sys.mjs"); 14 const { getInactiveCssDataForProperty } = require("devtools/server/actors/utils/inactive-property-helper"); 15 const { DocumentWalker } = require("devtools/server/actors/inspector/document-walker"); 16 17 const CUSTOM_HIGHLIGHT_API = "dom.customHighlightAPI.enabled"; 18 const TEXT_FRAGMENTS = "dom.text_fragments.enabled"; 19 20 Services.prefs.setBoolPref(CUSTOM_HIGHLIGHT_API, true); 21 Services.prefs.setBoolPref(TEXT_FRAGMENTS, true); 22 23 SimpleTest.registerCleanupFunction(() => { 24 Services.prefs.clearUserPref(CUSTOM_HIGHLIGHT_API); 25 Services.prefs.clearUserPref(TEXT_FRAGMENTS); 26 }); 27 28 const FOLDER = "./inactive-property-helper"; 29 30 // Each file should `export default` an array of objects, representing each test case. 31 // A single test case is an object of the following shape: 32 // - {String} info: a summary of the test case 33 // - {String} property: the CSS property that should be tested 34 // - {String|undefined} tagName: the tagName of the element we're going to test. 35 // Optional only if there's a createTestElement property. 36 // - {Function|undefined} createTestElement: A function that takes a node as a parameter 37 // where elements used for the test case will 38 // be appended. The function should return the 39 // element that will be passed to 40 // getInactiveCssDataForProperty. 41 // Optional only if there's a tagName property 42 // - {Array<String>} rules: An array of the rules that will be applied on the element. 43 // This can't be empty as getInactiveCssDataForProperty needs a rule. 44 // - {Integer|undefined} ruleIndex: If there are multiples rules in `rules`, the index 45 // of the one that should be tested in getInactiveCssDataForProperty. 46 // - {Boolean} isActive: should the property be active (e.g. getInactiveCssDataForProperty returns null). 47 const testFiles = [ 48 "align-content.mjs", 49 "at-position-try-rules.mjs", 50 "anchor-name.mjs", 51 "block-container-properties.mjs", 52 "block-flex-grid-container-properties.mjs", 53 "border-image.mjs", 54 "border-spacing.mjs", 55 "box-sizing.mjs", 56 "column-span.mjs", 57 "content-visibility.mjs", 58 "cue-pseudo-element.mjs", 59 "first-letter-pseudo-element.mjs", 60 "first-line-pseudo-element.mjs", 61 "flex-grid-item-properties.mjs", 62 "float.mjs", 63 "gap.mjs", 64 "grid-container-properties.mjs", 65 "grid-with-absolute-properties.mjs", 66 "multicol-container-properties.mjs", 67 "highlight-pseudo-elements.mjs", 68 "margin-padding.mjs", 69 "max-min-width-height.mjs", 70 "place-items-content.mjs", 71 "placeholder-pseudo-element.mjs", 72 "positioned.mjs", 73 "replaced-element-properties.mjs", 74 "resize.mjs", 75 "scroll-padding.mjs", 76 "self-position-properties.mjs", 77 "vertical-align.mjs", 78 "table.mjs", 79 "table-cell.mjs", 80 "text-overflow.mjs", 81 "text-wrap.mjs", 82 "width-height-ruby.mjs", 83 ].map(file => `${FOLDER}/${file}`); 84 85 // Import all the test cases 86 const tests = 87 (await Promise.all(testFiles.map(f => import(f).then(data => data.default)))).flat(); 88 89 for (const { 90 info: summary, 91 property, 92 tagName, 93 createTestElement, 94 pseudoElement, 95 rules, 96 ruleIndex, 97 isActive, 98 expectedMsgId, 99 } of tests) { 100 // Create an element which will contain the test elements. 101 const main = document.createElement("main"); 102 document.firstElementChild.appendChild(main); 103 104 // Apply the CSS rules to the document. 105 const style = document.createElement("style"); 106 main.append(style); 107 for (const dataRule of rules) { 108 style.sheet.insertRule(dataRule); 109 } 110 const rule = style.sheet.cssRules[ruleIndex || 0]; 111 112 // Create the test elements 113 let el; 114 if (createTestElement) { 115 el = createTestElement(main); 116 } else { 117 el = document.createElement(tagName); 118 main.append(el); 119 120 // When checking a pseudo element, we need to retrieve it, walking the DOM from 121 // its "real" node. 122 if (pseudoElement) { 123 const walker = new DocumentWalker( 124 el, 125 el.ownerGlobal 126 ); 127 128 const pseudoNodeName = `_moz_generated_content_${pseudoElement.replaceAll(":", "")}`; 129 for (let next = walker.firstChild(); next; next = walker.nextSibling()) { 130 if (next.nodeName === pseudoNodeName) { 131 el = next; 132 break; 133 } 134 } 135 } 136 } 137 138 const inactiveCssData = getInactiveCssDataForProperty(el, getComputedStyle(el, pseudoElement), rule, property); 139 is(inactiveCssData === null, isActive, summary); 140 if (expectedMsgId) { 141 is(inactiveCssData.msgId, expectedMsgId, `${summary} - returned expected msgId`); 142 } 143 144 main.remove(); 145 } 146 SimpleTest.finish(); 147 })(); 148 </script> 149 </head> 150 <body></body> 151 </html>