| <!DOCTYPE html> |
| <script src="/resources/testharness.js"></script> |
| <script src="/resources/testharnessreport.js"></script> |
| <style> |
| #state-and-part::part(inner) { |
| opacity: 0; |
| } |
| #state-and-part::part(inner):state(innerFoo) { |
| opacity: 0.5; |
| } |
| #state-and-part:state(outerFoo)::part(inner) { |
| opacity: 0.25; |
| } |
| :state( \(escaped\ state ) {} |
| </style> |
| <body> |
| <script> |
| class TestElement extends HTMLElement { |
| constructor() { |
| super(); |
| this._internals = this.attachInternals(); |
| } |
| |
| get i() { |
| return this._internals; |
| } |
| } |
| customElements.define('test-element', TestElement); |
| |
| class ContainerElement extends HTMLElement { |
| constructor() { |
| super(); |
| this._internals = this.attachInternals(); |
| this._shadow = this.attachShadow({mode:'open'}); |
| this._shadow.innerHTML = ` |
| <style> |
| :host { |
| border-style: solid; |
| } |
| :host(:state(dotted)) { |
| border-style: dotted; |
| } |
| </style> |
| <test-element part="inner"></test-element>`; |
| } |
| |
| get i() { |
| return this._internals; |
| } |
| get innerElement() { |
| return this._shadow.querySelector('test-element'); |
| } |
| } |
| customElements.define('container-element', ContainerElement); |
| |
| test(() => { |
| assert_throws_dom('SyntaxError', () => { document.querySelector(':state'); }); |
| assert_throws_dom('SyntaxError', () => { document.querySelector(':state('); }); |
| assert_throws_dom('SyntaxError', () => { document.querySelector(':state()'); }); |
| assert_throws_dom('SyntaxError', () => { document.querySelector(':state(=)'); }); |
| assert_throws_dom('SyntaxError', () => { document.querySelector(':state(name=value)'); }); |
| assert_throws_dom('SyntaxError', () => { document.querySelector(':state( foo bar)'); }); |
| assert_throws_dom('SyntaxError', () => { document.querySelector(':state(16px)'); }); |
| }, ':state() parsing failures'); |
| |
| test(() => { |
| assert_equals(document.styleSheets[0].cssRules[1].cssText, |
| '#state-and-part::part(inner):state(innerFoo) { opacity: 0.5; }'); |
| assert_equals(document.styleSheets[0].cssRules[3].selectorText, |
| ':state(\\(escaped\\ state)'); |
| }, ':state() serialization'); |
| |
| test(() => { |
| let element = new TestElement(); |
| let states = element.i.states; |
| |
| assert_false(element.matches(':state(foo)')); |
| assert_true(element.matches(':not(:state(foo))')); |
| states.add('foo'); |
| assert_true(element.matches(':state(foo)')); |
| assert_true(element.matches(':is(:state(foo))')); |
| element.classList.add('c1', 'c2'); |
| assert_true(element.matches('.c1:state(foo)')); |
| assert_true(element.matches(':state(foo).c1')); |
| assert_true(element.matches('.c2:state(foo).c1')); |
| }, ':state() in simple cases'); |
| |
| test(() => { |
| let element = new TestElement(); |
| element.tabIndex = 0; |
| document.body.appendChild(element); |
| element.focus(); |
| let states = element.i.states; |
| |
| states.value = 'foo'; |
| assert_true(element.matches(':focus:state(foo)')); |
| assert_true(element.matches(':state(foo):focus')); |
| }, ':state() and other pseudo classes'); |
| |
| test(() => { |
| let outer = new ContainerElement(); |
| outer.id = 'state-and-part'; |
| document.body.appendChild(outer); |
| let inner = outer.innerElement; |
| let innerStates = inner.i.states; |
| |
| innerStates.add('innerFoo'); |
| assert_equals(getComputedStyle(inner).opacity, '0.5', |
| '::part() followed by :state()'); |
| innerStates.replace('innerFoo', 'innerfoo'); |
| assert_equals(getComputedStyle(inner).opacity, '0', |
| ':state() matching should be case-sensitive'); |
| innerStates.remove('innerfoo'); |
| |
| outer.i.states.add('outerFoo'); |
| assert_equals(getComputedStyle(inner).opacity, '0.25', |
| ':state() followed by ::part()'); |
| }, ':state() and ::part()'); |
| |
| test(() => { |
| let outer = new ContainerElement(); |
| document.body.appendChild(outer); |
| |
| assert_equals(getComputedStyle(outer).borderStyle, 'solid'); |
| outer.i.states.toggle('dotted'); |
| assert_equals(getComputedStyle(outer).borderStyle, 'dotted'); |
| }, ':state() and :host()'); |
| </script> |
| </body> |