| <!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(() => { |
| document.querySelector(':state(foo)'); |
| document.querySelector(':state(--foo)'); |
| document.querySelector(':state(--)'); |
| document.querySelector(':state(--16px)'); |
| }, ':state() parsing passes'); |
| |
| test(() => { |
| assert_throws_dom('SyntaxError', () => { document.querySelector(':--('); }); |
| assert_throws_dom('SyntaxError', () => { document.querySelector(':--()'); }); |
| assert_throws_dom('SyntaxError', () => { document.querySelector(':state()'); }); |
| assert_throws_dom('SyntaxError', () => { document.querySelector(':--)'); }); |
| assert_throws_dom('SyntaxError', () => { document.querySelector(':--='); }); |
| assert_throws_dom('SyntaxError', () => { document.querySelector(':--name=value'); }); |
| assert_throws_dom('SyntaxError', () => { document.querySelector(':state(--name=value'); }); |
| assert_throws_dom('SyntaxError', () => { document.querySelector(':state(--name=value)'); }); |
| }, ':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(foo) 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(foo) in simple cases'); |
| |
| test(() => { |
| let element = new TestElement(); |
| element.tabIndex = 0; |
| document.body.appendChild(element); |
| element.focus(); |
| let states = element.i.states; |
| |
| states.add('foo'); |
| assert_true(element.matches(':focus:state(foo)')); |
| assert_true(element.matches(':state(foo):focus')); |
| }, ':state(foo) 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(':state(innerFoo)'); |
| assert_equals(getComputedStyle(inner).opacity, '0.5', |
| '::part() followed by :state(innerFoo)'); |
| innerStates.delete('innerFoo'); |
| innerStates.add('innerfoo'); |
| assert_equals(getComputedStyle(inner).opacity, '0', |
| ':state(foo) matching should be case-sensitive'); |
| innerStates.delete('innerfoo'); |
| |
| outer.i.states.add('outerFoo'); |
| assert_equals(getComputedStyle(inner).opacity, '0.25', |
| ':state(foo) followed by ::part()'); |
| }, ':state(foo) and ::part()'); |
| |
| test(() => { |
| let outer = new ContainerElement(); |
| document.body.appendChild(outer); |
| |
| assert_equals(getComputedStyle(outer).borderStyle, 'solid'); |
| outer.i.states.add('dotted'); |
| assert_equals(getComputedStyle(outer).borderStyle, 'dotted'); |
| }, ':state(foo) and :host()'); |
| </script> |
| </body> |