pseudo-class-defined.html (4532B)
1 <!DOCTYPE html> 2 <link rel="help" href="https://html.spec.whatwg.org/multipage/semantics-other.html#selector-defined"> 3 <script src="/resources/testharness.js"></script> 4 <script src="/resources/testharnessreport.js"></script> 5 <iframe id="iframe"></iframe> 6 <script> 7 const testList = [ 8 { tag_name: 'div', defined: true }, 9 { tag_name: 'a-a', defined: false }, 10 { tag_name: 'font-face', defined: true }, 11 ]; 12 13 // Setup iframe to test the parser. 14 const neither = 'rgb(255, 0, 0)'; 15 const defined = 'rgb(255, 165, 0)'; 16 const not_defined = 'rgb(0, 0, 255)'; 17 const iframe = document.getElementById("iframe"); 18 iframe.srcdoc = `<style> 19 * { color:${neither}; } 20 :defined { color:${defined}; } 21 :not(:defined) { color:${not_defined}; } 22 </style>` 23 + testList.map(d => `<${d.tag_name}></${d.tag_name}>`).join(''); 24 setup({ explicit_done: true }); 25 iframe.onload = () => { 26 const doc = iframe.contentDocument; 27 const doc_without_browsing_context = doc.implementation.createHTMLDocument(); 28 for (const data of testList) { 29 // Test elements inserted by parser. 30 test_defined(data.defined, doc.getElementsByTagName(data.tag_name)[0], `<${data.tag_name}>`); 31 32 // Test DOM createElement() methods. 33 let try_upgrade = !data.defined; 34 test_defined_for_createElement(data.defined, try_upgrade, doc, data.tag_name); 35 36 // Documents without browsing context should behave the same. 37 test_defined_for_createElement(data.defined, false, doc_without_browsing_context, data.tag_name, data.is, 'Without browsing context: '); 38 } 39 40 done(); 41 }; 42 43 function test_defined_for_createElement(defined, should_test_change, doc, tag_name, is, description = '') { 44 // Test document.createElement(). 45 let element = doc.createElement(tag_name); 46 doc.body.appendChild(element); 47 test_defined(defined, element, `${description}createElement("${tag_name}")`); 48 49 // Test document.createElementNS(). 50 let html_element = doc.createElementNS('http://www.w3.org/1999/xhtml', tag_name); 51 doc.body.appendChild(html_element); 52 test_defined(defined, html_element, `${description}createElementNS("http://www.w3.org/1999/xhtml", "${tag_name}")`); 53 54 // If the element namespace is not HTML, it should be "uncustomized"; i.e., "defined". 55 let svg_element = doc.createElementNS('http://www.w3.org/2000/svg', tag_name); 56 doc.body.appendChild(svg_element); 57 test_defined(true, svg_element, `${description}createElementNS("http://www.w3.org/2000/svg", "${tag_name}")`); 58 59 // Test ":defined" changes when the custom element was defined. 60 if (should_test_change) { 61 let w = doc.defaultView; 62 assert_false(!w, 'defaultView required to test change'); 63 w.customElements.define(tag_name, class extends w.HTMLElement { 64 constructor() { super(); } 65 }); 66 test_defined(true, element, `Upgraded ${description}createElement("${tag_name}")`); 67 test_defined(true, html_element, `Upgraded ${description}createElementNS("http://www.w3.org/1999/xhtml", "${tag_name}")`); 68 } 69 } 70 71 function test_defined(expected, element, description) { 72 test(() => { 73 assert_equals(element.matches(':defined'), expected, 'matches(":defined")'); 74 assert_equals(element.matches(':not(:defined)'), !expected, 'matches(":not(:defined")'); 75 const view = element.ownerDocument.defaultView; 76 if (!view) 77 return; 78 const style = view.getComputedStyle(element); 79 assert_equals(style.color, expected ? defined : not_defined, 'getComputedStyle'); 80 }, `${description} should ${expected ? 'be' : 'not be'} :defined`); 81 } 82 83 test(function () { 84 var log = []; 85 var instance = document.createElement('my-custom-element-2'); 86 document.body.appendChild(instance); 87 assert_false(instance.matches(":defined"), "Prior to definition, instance should not match :defined"); 88 customElements.define('my-custom-element-2',class extends HTMLElement { 89 constructor() { 90 assert_false(instance.matches(":defined"), "During construction, prior to super(), instance should not match :defined"); 91 super(); 92 log.push([this, 'begin']); 93 assert_false(this.matches(":defined"), "During construction, after super(), this should not match :defined"); 94 log.push([this, 'end']); 95 } 96 }); 97 assert_true(instance.matches(":defined"), "After construction, instance should match :defined"); 98 assert_equals(log.length, 2); 99 assert_array_equals(log[0], [instance, 'begin']); 100 assert_array_equals(log[1], [instance, 'end']); 101 }, 'this.matches(:defined) should not match during an upgrade'); 102 103 </script>