mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-21 23:20:20 +00:00
LibWeb: Import a bunch of :has() selector tests from WPT
This commit is contained in:
parent
9e080e197c
commit
a640fcc693
Notes:
github-actions[bot]
2024-10-27 12:34:43 +00:00
Author: https://github.com/awesomekling Commit: https://github.com/LadybirdBrowser/ladybird/commit/a640fcc693c Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/1997
44 changed files with 4493 additions and 0 deletions
|
@ -0,0 +1,24 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 13 tests
|
||||||
|
|
||||||
|
12 Pass
|
||||||
|
1 Fail
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass :has(:scope) matches expected elements on scope1
|
||||||
|
Pass :has(:scope .c) matches expected elements on scope1
|
||||||
|
Pass :has(.a :scope) matches expected elements on scope1
|
||||||
|
Fail .a:has(:scope) .c matches expected elements on scope1 assert_equals: expected "d02,d03" but got ""
|
||||||
|
Pass .a:has(:scope) .c and :is(.a :scope .c) returns same elements on scope1
|
||||||
|
Pass .a:has(:scope) .c matches expected elements on scope2
|
||||||
|
Pass .a:has(:scope) .c and :is(.a :scope .c) returns same elements on scope2
|
||||||
|
Pass .c:has(:is(:scope .d)) matches expected elements on scope1
|
||||||
|
Pass .c:has(:is(:scope .d)) and :scope .c:has(.d) returns same elements on scope1
|
||||||
|
Pass .c:has(:is(:scope .d)) and .c:has(.d) returns same elements on scope1
|
||||||
|
Pass .c:has(:is(:scope .d)) matches expected elements on scope2
|
||||||
|
Pass .c:has(:is(:scope .d)) and :scope .c:has(.d) returns same elements on scope2
|
||||||
|
Pass .c:has(:is(:scope .d)) and .c:has(.d) returns same elements on scope2
|
|
@ -0,0 +1,28 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 18 tests
|
||||||
|
|
||||||
|
18 Pass
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass :has(#a) matches expected elements
|
||||||
|
Pass :has(.ancestor) matches expected elements
|
||||||
|
Pass :has(.target) matches expected elements
|
||||||
|
Pass :has(.descendant) matches expected elements
|
||||||
|
Pass .parent:has(.target) matches expected elements
|
||||||
|
Pass :has(.sibling ~ .target) matches expected elements
|
||||||
|
Pass .parent:has(.sibling ~ .target) matches expected elements
|
||||||
|
Pass :has(:is(.target ~ .sibling .descendant)) matches expected elements
|
||||||
|
Pass .parent:has(:is(.target ~ .sibling .descendant)) matches expected elements
|
||||||
|
Pass .sibling:has(.descendant) ~ .target matches expected elements
|
||||||
|
Pass :has(> .parent) matches expected elements
|
||||||
|
Pass :has(> .target) matches expected elements
|
||||||
|
Pass :has(> .parent, > .target) matches expected elements
|
||||||
|
Pass :has(+ #h) matches expected elements
|
||||||
|
Pass .parent:has(~ #h) matches expected elements
|
||||||
|
Pass .sibling:has(.descendant) matches expected element
|
||||||
|
Pass closest(.ancestor:has(.descendant)) returns expected element
|
||||||
|
Pass :has(.target ~ .sibling .descendant) matches expectedly
|
|
@ -0,0 +1,22 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 12 tests
|
||||||
|
|
||||||
|
12 Pass
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass :has(child) matches expectedly
|
||||||
|
Pass :has(> child) matches expectedly
|
||||||
|
Pass :has(descendant) matches expectedly
|
||||||
|
Pass :has(> descendant) matches expectedly
|
||||||
|
Pass :has(~ direct_sibling) matches expectedly
|
||||||
|
Pass :has(+ direct_sibling) matches expectedly
|
||||||
|
Pass :has(~ indirect_sibling) matches expectedly
|
||||||
|
Pass :has(+ indirect_sibling) matches expectedly
|
||||||
|
Pass :has(*) matches expectedly
|
||||||
|
Pass :has(> *) matches expectedly
|
||||||
|
Pass :has(~ *) matches expectedly
|
||||||
|
Pass :has(+ *) matches expectedly
|
|
@ -0,0 +1,45 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 35 tests
|
||||||
|
|
||||||
|
35 Pass
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass .x:has(.a) matches expected elements
|
||||||
|
Pass .x:has(.a > .b) matches expected elements
|
||||||
|
Pass .x:has(.a .b) matches expected elements
|
||||||
|
Pass .x:has(.a + .b) matches expected elements
|
||||||
|
Pass .x:has(.a ~ .b) matches expected elements
|
||||||
|
Pass .x:has(> .a) matches expected elements
|
||||||
|
Pass .x:has(> .a > .b) matches expected elements
|
||||||
|
Pass .x:has(> .a .b) matches expected elements
|
||||||
|
Pass .x:has(> .a + .b) matches expected elements
|
||||||
|
Pass .x:has(> .a ~ .b) matches expected elements
|
||||||
|
Pass .x:has(+ .a) matches expected elements
|
||||||
|
Pass .x:has(+ .a > .b) matches expected elements
|
||||||
|
Pass .x:has(+ .a .b) matches expected elements
|
||||||
|
Pass .x:has(+ .a + .b) matches expected elements
|
||||||
|
Pass .x:has(+ .a ~ .b) matches expected elements
|
||||||
|
Pass .x:has(~ .a) matches expected elements
|
||||||
|
Pass .x:has(~ .a > .b) matches expected elements
|
||||||
|
Pass .x:has(~ .a .b) matches expected elements
|
||||||
|
Pass .x:has(~ .a + .b) matches expected elements
|
||||||
|
Pass .x:has(~ .a + .b > .c) matches expected elements
|
||||||
|
Pass .x:has(~ .a + .b .c) matches expected elements
|
||||||
|
Pass .x:has(.d .e) matches expected elements
|
||||||
|
Pass .x:has(.d .e) .f matches expected elements
|
||||||
|
Pass .x:has(> .d) matches expected elements
|
||||||
|
Pass .x:has(> .d) .f matches expected elements
|
||||||
|
Pass .x:has(~ .d ~ .e) matches expected elements
|
||||||
|
Pass .x:has(~ .d ~ .e) ~ .f matches expected elements
|
||||||
|
Pass .x:has(+ .d ~ .e) matches expected elements
|
||||||
|
Pass .x:has(+ .d ~ .e) ~ .f matches expected elements
|
||||||
|
Pass .y:has(> .g .h) matches expected elements
|
||||||
|
Pass .y:has(.g .h) matches expected elements
|
||||||
|
Pass .y:has(> .g .h) .i matches expected elements
|
||||||
|
Pass .y:has(.g .h) .i matches expected elements
|
||||||
|
Pass .d .x:has(.e) matches expected elements
|
||||||
|
Pass .d ~ .x:has(~ .e) matches expected elements
|
|
@ -0,0 +1 @@
|
||||||
|
PASS
|
|
@ -0,0 +1,18 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 8 tests
|
||||||
|
|
||||||
|
8 Fail
|
||||||
|
Details
|
||||||
|
Result Test Name MessageFail :has(#foo) wins over :has(.foo) assert_equals: expected "PASS" but got ""
|
||||||
|
Fail :has(span#foo) wins over :has(#foo) assert_equals: expected "PASS" but got ""
|
||||||
|
Fail :has(.bar, #foo) has same specificity as :has(#foo, .bar) assert_equals: expected "PASS" but got ""
|
||||||
|
Fail :has(.bar, #foo) wins over :has(.foo, .bar) assert_equals: expected "PASS" but got ""
|
||||||
|
Fail :has(span + span) wins over :has(span) assert_equals: expected "PASS" but got ""
|
||||||
|
Fail :has(span, li, p) wins over :has(span, lo, p) assert_equals: expected "PASS" but got ""
|
||||||
|
Fail latter .baz wins over :has(.foo) assert_equals: expected "PASS" but got ""
|
||||||
|
Fail latter :has(.foo) wins over .baz assert_equals: expected "PASS" but got ""
|
|
@ -0,0 +1,22 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 12 tests
|
||||||
|
|
||||||
|
12 Pass
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass add .test to trigger1 - check subject1_1
|
||||||
|
Pass add .test to trigger1 - check subject1_2
|
||||||
|
Pass remove .test from trigger1 - check subject1_1
|
||||||
|
Pass remove .test from trigger1 - check subject1_2
|
||||||
|
Pass add .test to trigger2 - check subject2_1
|
||||||
|
Pass add .test to trigger2 - check subject2_2
|
||||||
|
Pass remove .test from trigger2 - check subject2_1
|
||||||
|
Pass remove .test from trigger2 - check subject2_2
|
||||||
|
Pass add .test to trigger3 - check subject3_1
|
||||||
|
Pass add .test to trigger3 - check subject3_2
|
||||||
|
Pass remove .test from trigger3 - check subject3_1
|
||||||
|
Pass remove .test from trigger3 - check subject3_2
|
|
@ -0,0 +1,305 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 295 tests
|
||||||
|
|
||||||
|
295 Pass
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass Initial color
|
||||||
|
Pass add .test to previous_sibling
|
||||||
|
Pass remove .test from previous_sibling
|
||||||
|
Pass add .test to previous_sibling_child
|
||||||
|
Pass remove .test from previous_sibling_child
|
||||||
|
Pass add .test to previous_sibling_descendant
|
||||||
|
Pass remove .test from previous_sibling_descendant
|
||||||
|
Pass add .test to subject
|
||||||
|
Pass remove .test from subject
|
||||||
|
Pass add .test to next_sibling
|
||||||
|
Pass remove .test from next_sibling
|
||||||
|
Pass add .test to next_sibling_child
|
||||||
|
Pass remove .test from next_sibling_child
|
||||||
|
Pass add .test to next_sibling_descendant
|
||||||
|
Pass remove .test from next_sibling_descendant
|
||||||
|
Pass insert element div.test before previous_sibling
|
||||||
|
Pass remove the class 'test' from the element inserted before previous_sibling
|
||||||
|
Pass add the class 'test' again to the element inserted before previous_sibling
|
||||||
|
Pass remove element div.test before previous_sibling
|
||||||
|
Pass insert element div before previous_sibling
|
||||||
|
Pass add the class 'test' to the element inserted again before previous_sibling
|
||||||
|
Pass remove the class 'test' from the element inserted again before previous_sibling
|
||||||
|
Pass remove element div before previous_sibling
|
||||||
|
Pass insert element div[test_attr] before previous_sibling
|
||||||
|
Pass remove element div[test_attr] before previous_sibling
|
||||||
|
Pass insert element div.test before previous_sibling_child
|
||||||
|
Pass remove the class 'test' from the element inserted before previous_sibling_child
|
||||||
|
Pass add the class 'test' again to the element inserted before previous_sibling_child
|
||||||
|
Pass remove element div.test before previous_sibling_child
|
||||||
|
Pass insert element div before previous_sibling_child
|
||||||
|
Pass add the class 'test' to the element inserted again before previous_sibling_child
|
||||||
|
Pass remove the class 'test' from the element inserted again before previous_sibling_child
|
||||||
|
Pass remove element div before previous_sibling_child
|
||||||
|
Pass insert element div[test_attr] before previous_sibling_child
|
||||||
|
Pass remove element div[test_attr] before previous_sibling_child
|
||||||
|
Pass insert element div.test before previous_sibling_descendant
|
||||||
|
Pass remove the class 'test' from the element inserted before previous_sibling_descendant
|
||||||
|
Pass add the class 'test' again to the element inserted before previous_sibling_descendant
|
||||||
|
Pass remove element div.test before previous_sibling_descendant
|
||||||
|
Pass insert element div before previous_sibling_descendant
|
||||||
|
Pass add the class 'test' to the element inserted again before previous_sibling_descendant
|
||||||
|
Pass remove the class 'test' from the element inserted again before previous_sibling_descendant
|
||||||
|
Pass remove element div before previous_sibling_descendant
|
||||||
|
Pass insert element div[test_attr] before previous_sibling_descendant
|
||||||
|
Pass remove element div[test_attr] before previous_sibling_descendant
|
||||||
|
Pass insert element div.test before subject
|
||||||
|
Pass remove the class 'test' from the element inserted before subject
|
||||||
|
Pass add the class 'test' again to the element inserted before subject
|
||||||
|
Pass remove element div.test before subject
|
||||||
|
Pass insert element div before subject
|
||||||
|
Pass add the class 'test' to the element inserted again before subject
|
||||||
|
Pass remove the class 'test' from the element inserted again before subject
|
||||||
|
Pass remove element div before subject
|
||||||
|
Pass insert element div[test_attr] before subject
|
||||||
|
Pass remove element div[test_attr] before subject
|
||||||
|
Pass insert element div.test before next_sibling
|
||||||
|
Pass remove the class 'test' from the element inserted before next_sibling
|
||||||
|
Pass add the class 'test' again to the element inserted before next_sibling
|
||||||
|
Pass remove element div.test before next_sibling
|
||||||
|
Pass insert element div before next_sibling
|
||||||
|
Pass add the class 'test' to the element inserted again before next_sibling
|
||||||
|
Pass remove the class 'test' from the element inserted again before next_sibling
|
||||||
|
Pass remove element div before next_sibling
|
||||||
|
Pass insert element div[test_attr] before next_sibling
|
||||||
|
Pass remove element div[test_attr] before next_sibling
|
||||||
|
Pass insert element div.test before next_sibling_child
|
||||||
|
Pass remove the class 'test' from the element inserted before next_sibling_child
|
||||||
|
Pass add the class 'test' again to the element inserted before next_sibling_child
|
||||||
|
Pass remove element div.test before next_sibling_child
|
||||||
|
Pass insert element div before next_sibling_child
|
||||||
|
Pass add the class 'test' to the element inserted again before next_sibling_child
|
||||||
|
Pass remove the class 'test' from the element inserted again before next_sibling_child
|
||||||
|
Pass remove element div before next_sibling_child
|
||||||
|
Pass insert element div[test_attr] before next_sibling_child
|
||||||
|
Pass remove element div[test_attr] before next_sibling_child
|
||||||
|
Pass insert element div.test before next_sibling_descendant
|
||||||
|
Pass remove the class 'test' from the element inserted before next_sibling_descendant
|
||||||
|
Pass add the class 'test' again to the element inserted before next_sibling_descendant
|
||||||
|
Pass remove element div.test before next_sibling_descendant
|
||||||
|
Pass insert element div before next_sibling_descendant
|
||||||
|
Pass add the class 'test' to the element inserted again before next_sibling_descendant
|
||||||
|
Pass remove the class 'test' from the element inserted again before next_sibling_descendant
|
||||||
|
Pass remove element div before next_sibling_descendant
|
||||||
|
Pass insert element div[test_attr] before next_sibling_descendant
|
||||||
|
Pass remove element div[test_attr] before next_sibling_descendant
|
||||||
|
Pass insert element div.test after previous_sibling
|
||||||
|
Pass remove the class 'test' from the element inserted after previous_sibling
|
||||||
|
Pass add the class 'test' again to the element inserted after previous_sibling
|
||||||
|
Pass remove element div.test after previous_sibling
|
||||||
|
Pass insert element div after previous_sibling
|
||||||
|
Pass add the class 'test' to the element inserted again after previous_sibling
|
||||||
|
Pass remove the class 'test' from the element inserted again after previous_sibling
|
||||||
|
Pass remove element div after previous_sibling
|
||||||
|
Pass insert element div[test_attr] after previous_sibling
|
||||||
|
Pass remove element div[test_attr] after previous_sibling
|
||||||
|
Pass insert element div.test after previous_sibling_child
|
||||||
|
Pass remove the class 'test' from the element inserted after previous_sibling_child
|
||||||
|
Pass add the class 'test' again to the element inserted after previous_sibling_child
|
||||||
|
Pass remove element div.test after previous_sibling_child
|
||||||
|
Pass insert element div after previous_sibling_child
|
||||||
|
Pass add the class 'test' to the element inserted again after previous_sibling_child
|
||||||
|
Pass remove the class 'test' from the element inserted again after previous_sibling_child
|
||||||
|
Pass remove element div after previous_sibling_child
|
||||||
|
Pass insert element div[test_attr] after previous_sibling_child
|
||||||
|
Pass remove element div[test_attr] after previous_sibling_child
|
||||||
|
Pass insert element div.test after previous_sibling_descendant
|
||||||
|
Pass remove the class 'test' from the element inserted after previous_sibling_descendant
|
||||||
|
Pass add the class 'test' again to the element inserted after previous_sibling_descendant
|
||||||
|
Pass remove element div.test after previous_sibling_descendant
|
||||||
|
Pass insert element div after previous_sibling_descendant
|
||||||
|
Pass add the class 'test' to the element inserted again after previous_sibling_descendant
|
||||||
|
Pass remove the class 'test' from the element inserted again after previous_sibling_descendant
|
||||||
|
Pass remove element div after previous_sibling_descendant
|
||||||
|
Pass insert element div[test_attr] after previous_sibling_descendant
|
||||||
|
Pass remove element div[test_attr] after previous_sibling_descendant
|
||||||
|
Pass insert element div.test after subject
|
||||||
|
Pass remove the class 'test' from the element inserted after subject
|
||||||
|
Pass add the class 'test' again to the element inserted after subject
|
||||||
|
Pass remove element div.test after subject
|
||||||
|
Pass insert element div after subject
|
||||||
|
Pass add the class 'test' to the element inserted again after subject
|
||||||
|
Pass remove the class 'test' from the element inserted again after subject
|
||||||
|
Pass remove element div after subject
|
||||||
|
Pass insert element div[test_attr] after subject
|
||||||
|
Pass remove element div[test_attr] after subject
|
||||||
|
Pass insert element div.test after next_sibling
|
||||||
|
Pass remove the class 'test' from the element inserted after next_sibling
|
||||||
|
Pass add the class 'test' again to the element inserted after next_sibling
|
||||||
|
Pass remove element div.test after next_sibling
|
||||||
|
Pass insert element div after next_sibling
|
||||||
|
Pass add the class 'test' to the element inserted again after next_sibling
|
||||||
|
Pass remove the class 'test' from the element inserted again after next_sibling
|
||||||
|
Pass remove element div after next_sibling
|
||||||
|
Pass insert element div[test_attr] after next_sibling
|
||||||
|
Pass remove element div[test_attr] after next_sibling
|
||||||
|
Pass insert element div.test after next_sibling_child
|
||||||
|
Pass remove the class 'test' from the element inserted after next_sibling_child
|
||||||
|
Pass add the class 'test' again to the element inserted after next_sibling_child
|
||||||
|
Pass remove element div.test after next_sibling_child
|
||||||
|
Pass insert element div after next_sibling_child
|
||||||
|
Pass add the class 'test' to the element inserted again after next_sibling_child
|
||||||
|
Pass remove the class 'test' from the element inserted again after next_sibling_child
|
||||||
|
Pass remove element div after next_sibling_child
|
||||||
|
Pass insert element div[test_attr] after next_sibling_child
|
||||||
|
Pass remove element div[test_attr] after next_sibling_child
|
||||||
|
Pass insert element div.test after next_sibling_descendant
|
||||||
|
Pass remove the class 'test' from the element inserted after next_sibling_descendant
|
||||||
|
Pass add the class 'test' again to the element inserted after next_sibling_descendant
|
||||||
|
Pass remove element div.test after next_sibling_descendant
|
||||||
|
Pass insert element div after next_sibling_descendant
|
||||||
|
Pass add the class 'test' to the element inserted again after next_sibling_descendant
|
||||||
|
Pass remove the class 'test' from the element inserted again after next_sibling_descendant
|
||||||
|
Pass remove element div after next_sibling_descendant
|
||||||
|
Pass insert element div[test_attr] after next_sibling_descendant
|
||||||
|
Pass remove element div[test_attr] after next_sibling_descendant
|
||||||
|
Pass insert tree div>div.test before previous_sibling
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted before previous_sibling
|
||||||
|
Pass add the class 'test' again to the element in the tree inserted before previous_sibling
|
||||||
|
Pass remove tree div>div.test before previous_sibling
|
||||||
|
Pass insert tree div>div before previous_sibling
|
||||||
|
Pass add the class 'test' to the element in the tree inserted again before previous_sibling
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted again before previous_sibling
|
||||||
|
Pass remove tree div>div before previous_sibling
|
||||||
|
Pass insert element div>div[test_attr] before previous_sibling
|
||||||
|
Pass remove element div>div[test_attr] before previous_sibling
|
||||||
|
Pass insert tree div>div.test before previous_sibling_child
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted before previous_sibling_child
|
||||||
|
Pass add the class 'test' again to the element in the tree inserted before previous_sibling_child
|
||||||
|
Pass remove tree div>div.test before previous_sibling_child
|
||||||
|
Pass insert tree div>div before previous_sibling_child
|
||||||
|
Pass add the class 'test' to the element in the tree inserted again before previous_sibling_child
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted again before previous_sibling_child
|
||||||
|
Pass remove tree div>div before previous_sibling_child
|
||||||
|
Pass insert element div>div[test_attr] before previous_sibling_child
|
||||||
|
Pass remove element div>div[test_attr] before previous_sibling_child
|
||||||
|
Pass insert tree div>div.test before previous_sibling_descendant
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted before previous_sibling_descendant
|
||||||
|
Pass add the class 'test' again to the element in the tree inserted before previous_sibling_descendant
|
||||||
|
Pass remove tree div>div.test before previous_sibling_descendant
|
||||||
|
Pass insert tree div>div before previous_sibling_descendant
|
||||||
|
Pass add the class 'test' to the element in the tree inserted again before previous_sibling_descendant
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted again before previous_sibling_descendant
|
||||||
|
Pass remove tree div>div before previous_sibling_descendant
|
||||||
|
Pass insert element div>div[test_attr] before previous_sibling_descendant
|
||||||
|
Pass remove element div>div[test_attr] before previous_sibling_descendant
|
||||||
|
Pass insert tree div>div.test before subject
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted before subject
|
||||||
|
Pass add the class 'test' again to the element in the tree inserted before subject
|
||||||
|
Pass remove tree div>div.test before subject
|
||||||
|
Pass insert tree div>div before subject
|
||||||
|
Pass add the class 'test' to the element in the tree inserted again before subject
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted again before subject
|
||||||
|
Pass remove tree div>div before subject
|
||||||
|
Pass insert element div>div[test_attr] before subject
|
||||||
|
Pass remove element div>div[test_attr] before subject
|
||||||
|
Pass insert tree div>div.test before next_sibling
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted before next_sibling
|
||||||
|
Pass add the class 'test' again to the element in the tree inserted before next_sibling
|
||||||
|
Pass remove tree div>div.test before next_sibling
|
||||||
|
Pass insert tree div>div before next_sibling
|
||||||
|
Pass add the class 'test' to the element in the tree inserted again before next_sibling
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted again before next_sibling
|
||||||
|
Pass remove tree div>div before next_sibling
|
||||||
|
Pass insert element div>div[test_attr] before next_sibling
|
||||||
|
Pass remove element div>div[test_attr] before next_sibling
|
||||||
|
Pass insert tree div>div.test before next_sibling_child
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted before next_sibling_child
|
||||||
|
Pass add the class 'test' again to the element in the tree inserted before next_sibling_child
|
||||||
|
Pass remove tree div>div.test before next_sibling_child
|
||||||
|
Pass insert tree div>div before next_sibling_child
|
||||||
|
Pass add the class 'test' to the element in the tree inserted again before next_sibling_child
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted again before next_sibling_child
|
||||||
|
Pass remove tree div>div before next_sibling_child
|
||||||
|
Pass insert element div>div[test_attr] before next_sibling_child
|
||||||
|
Pass remove element div>div[test_attr] before next_sibling_child
|
||||||
|
Pass insert tree div>div.test before next_sibling_descendant
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted before next_sibling_descendant
|
||||||
|
Pass add the class 'test' again to the element in the tree inserted before next_sibling_descendant
|
||||||
|
Pass remove tree div>div.test before next_sibling_descendant
|
||||||
|
Pass insert tree div>div before next_sibling_descendant
|
||||||
|
Pass add the class 'test' to the element in the tree inserted again before next_sibling_descendant
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted again before next_sibling_descendant
|
||||||
|
Pass remove tree div>div before next_sibling_descendant
|
||||||
|
Pass insert element div>div[test_attr] before next_sibling_descendant
|
||||||
|
Pass remove element div>div[test_attr] before next_sibling_descendant
|
||||||
|
Pass insert tree div>div.test after previous_sibling
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted after previous_sibling
|
||||||
|
Pass add the class 'test' again to the element in the tree inserted after previous_sibling
|
||||||
|
Pass remove tree div>div.test after previous_sibling
|
||||||
|
Pass insert tree div>div after previous_sibling
|
||||||
|
Pass add the class 'test' to the element in the tree inserted again after previous_sibling
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted again after previous_sibling
|
||||||
|
Pass remove tree div>div after previous_sibling
|
||||||
|
Pass insert element div>div[test_attr] after previous_sibling
|
||||||
|
Pass remove element div>div[test_attr] after previous_sibling
|
||||||
|
Pass insert tree div>div.test after previous_sibling_child
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted after previous_sibling_child
|
||||||
|
Pass add the class 'test' again to the element in the tree inserted after previous_sibling_child
|
||||||
|
Pass remove tree div>div.test after previous_sibling_child
|
||||||
|
Pass insert tree div>div after previous_sibling_child
|
||||||
|
Pass add the class 'test' to the element in the tree inserted again after previous_sibling_child
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted again after previous_sibling_child
|
||||||
|
Pass remove tree div>div after previous_sibling_child
|
||||||
|
Pass insert element div>div[test_attr] after previous_sibling_child
|
||||||
|
Pass remove element div>div[test_attr] after previous_sibling_child
|
||||||
|
Pass insert tree div>div.test after previous_sibling_descendant
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted after previous_sibling_descendant
|
||||||
|
Pass add the class 'test' again to the element in the tree inserted after previous_sibling_descendant
|
||||||
|
Pass remove tree div>div.test after previous_sibling_descendant
|
||||||
|
Pass insert tree div>div after previous_sibling_descendant
|
||||||
|
Pass add the class 'test' to the element in the tree inserted again after previous_sibling_descendant
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted again after previous_sibling_descendant
|
||||||
|
Pass remove tree div>div after previous_sibling_descendant
|
||||||
|
Pass insert element div>div[test_attr] after previous_sibling_descendant
|
||||||
|
Pass remove element div>div[test_attr] after previous_sibling_descendant
|
||||||
|
Pass insert tree div>div.test after subject
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted after subject
|
||||||
|
Pass add the class 'test' again to the element in the tree inserted after subject
|
||||||
|
Pass remove tree div>div.test after subject
|
||||||
|
Pass insert tree div>div after subject
|
||||||
|
Pass add the class 'test' to the element in the tree inserted again after subject
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted again after subject
|
||||||
|
Pass remove tree div>div after subject
|
||||||
|
Pass insert element div>div[test_attr] after subject
|
||||||
|
Pass remove element div>div[test_attr] after subject
|
||||||
|
Pass insert tree div>div.test after next_sibling
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted after next_sibling
|
||||||
|
Pass add the class 'test' again to the element in the tree inserted after next_sibling
|
||||||
|
Pass remove tree div>div.test after next_sibling
|
||||||
|
Pass insert tree div>div after next_sibling
|
||||||
|
Pass add the class 'test' to the element in the tree inserted again after next_sibling
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted again after next_sibling
|
||||||
|
Pass remove tree div>div after next_sibling
|
||||||
|
Pass insert element div>div[test_attr] after next_sibling
|
||||||
|
Pass remove element div>div[test_attr] after next_sibling
|
||||||
|
Pass insert tree div>div.test after next_sibling_child
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted after next_sibling_child
|
||||||
|
Pass add the class 'test' again to the element in the tree inserted after next_sibling_child
|
||||||
|
Pass remove tree div>div.test after next_sibling_child
|
||||||
|
Pass insert tree div>div after next_sibling_child
|
||||||
|
Pass add the class 'test' to the element in the tree inserted again after next_sibling_child
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted again after next_sibling_child
|
||||||
|
Pass remove tree div>div after next_sibling_child
|
||||||
|
Pass insert element div>div[test_attr] after next_sibling_child
|
||||||
|
Pass remove element div>div[test_attr] after next_sibling_child
|
||||||
|
Pass insert tree div>div.test after next_sibling_descendant
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted after next_sibling_descendant
|
||||||
|
Pass add the class 'test' again to the element in the tree inserted after next_sibling_descendant
|
||||||
|
Pass remove tree div>div.test after next_sibling_descendant
|
||||||
|
Pass insert tree div>div after next_sibling_descendant
|
||||||
|
Pass add the class 'test' to the element in the tree inserted again after next_sibling_descendant
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted again after next_sibling_descendant
|
||||||
|
Pass remove tree div>div after next_sibling_descendant
|
||||||
|
Pass insert element div>div[test_attr] after next_sibling_descendant
|
||||||
|
Pass remove element div>div[test_attr] after next_sibling_descendant
|
|
@ -0,0 +1,347 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 337 tests
|
||||||
|
|
||||||
|
337 Pass
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass Initial color
|
||||||
|
Pass add .test to subject_ancestor
|
||||||
|
Pass remove .test from subject_ancestor
|
||||||
|
Pass add .test to subject_parent
|
||||||
|
Pass remove .test from subject_parent
|
||||||
|
Pass add .test to subject
|
||||||
|
Pass remove .test from subject
|
||||||
|
Pass add .test to subject_child
|
||||||
|
Pass remove .test from subject_child
|
||||||
|
Pass add .test to subject_descendant
|
||||||
|
Pass remove .test from subject_descendant
|
||||||
|
Pass add .test to next_sibling
|
||||||
|
Pass remove .test from next_sibling
|
||||||
|
Pass add .test to next_sibling_child
|
||||||
|
Pass remove .test from next_sibling_child
|
||||||
|
Pass add .test to next_sibling_descendant
|
||||||
|
Pass remove .test from next_sibling_descendant
|
||||||
|
Pass insert element div.test before subject_ancestor
|
||||||
|
Pass remove the class 'test' from the element inserted before subject_ancestor
|
||||||
|
Pass add the class 'test' again to the element inserted before subject_ancestor
|
||||||
|
Pass remove element div.test before subject_ancestor
|
||||||
|
Pass insert element div before subject_ancestor
|
||||||
|
Pass add the class 'test' to the element inserted again before subject_ancestor
|
||||||
|
Pass remove the class 'test' from the element inserted again before subject_ancestor
|
||||||
|
Pass remove element div before subject_ancestor
|
||||||
|
Pass insert element div[test_attr] before subject_ancestor
|
||||||
|
Pass remove element div[test_attr] before subject_ancestor
|
||||||
|
Pass insert element div.test before subject_parent
|
||||||
|
Pass remove the class 'test' from the element inserted before subject_parent
|
||||||
|
Pass add the class 'test' again to the element inserted before subject_parent
|
||||||
|
Pass remove element div.test before subject_parent
|
||||||
|
Pass insert element div before subject_parent
|
||||||
|
Pass add the class 'test' to the element inserted again before subject_parent
|
||||||
|
Pass remove the class 'test' from the element inserted again before subject_parent
|
||||||
|
Pass remove element div before subject_parent
|
||||||
|
Pass insert element div[test_attr] before subject_parent
|
||||||
|
Pass remove element div[test_attr] before subject_parent
|
||||||
|
Pass insert element div.test before subject
|
||||||
|
Pass remove the class 'test' from the element inserted before subject
|
||||||
|
Pass add the class 'test' again to the element inserted before subject
|
||||||
|
Pass remove element div.test before subject
|
||||||
|
Pass insert element div before subject
|
||||||
|
Pass add the class 'test' to the element inserted again before subject
|
||||||
|
Pass remove the class 'test' from the element inserted again before subject
|
||||||
|
Pass remove element div before subject
|
||||||
|
Pass insert element div[test_attr] before subject
|
||||||
|
Pass remove element div[test_attr] before subject
|
||||||
|
Pass insert element div.test before subject_child
|
||||||
|
Pass remove the class 'test' from the element inserted before subject_child
|
||||||
|
Pass add the class 'test' again to the element inserted before subject_child
|
||||||
|
Pass remove element div.test before subject_child
|
||||||
|
Pass insert element div before subject_child
|
||||||
|
Pass add the class 'test' to the element inserted again before subject_child
|
||||||
|
Pass remove the class 'test' from the element inserted again before subject_child
|
||||||
|
Pass remove element div before subject_child
|
||||||
|
Pass insert element div[test_attr] before subject_child
|
||||||
|
Pass remove element div[test_attr] before subject_child
|
||||||
|
Pass insert element div.test before subject_descendant
|
||||||
|
Pass remove the class 'test' from the element inserted before subject_descendant
|
||||||
|
Pass add the class 'test' again to the element inserted before subject_descendant
|
||||||
|
Pass remove element div.test before subject_descendant
|
||||||
|
Pass insert element div before subject_descendant
|
||||||
|
Pass add the class 'test' to the element inserted again before subject_descendant
|
||||||
|
Pass remove the class 'test' from the element inserted again before subject_descendant
|
||||||
|
Pass remove element div before subject_descendant
|
||||||
|
Pass insert element div[test_attr] before subject_descendant
|
||||||
|
Pass remove element div[test_attr] before subject_descendant
|
||||||
|
Pass insert element div.test before next_sibling
|
||||||
|
Pass remove the class 'test' from the element inserted before next_sibling
|
||||||
|
Pass add the class 'test' again to the element inserted before next_sibling
|
||||||
|
Pass remove element div.test before next_sibling
|
||||||
|
Pass insert element div before next_sibling
|
||||||
|
Pass add the class 'test' to the element inserted again before next_sibling
|
||||||
|
Pass remove the class 'test' from the element inserted again before next_sibling
|
||||||
|
Pass remove element div before next_sibling
|
||||||
|
Pass insert element div[test_attr] before next_sibling
|
||||||
|
Pass remove element div[test_attr] before next_sibling
|
||||||
|
Pass insert element div.test before next_sibling_child
|
||||||
|
Pass remove the class 'test' from the element inserted before next_sibling_child
|
||||||
|
Pass add the class 'test' again to the element inserted before next_sibling_child
|
||||||
|
Pass remove element div.test before next_sibling_child
|
||||||
|
Pass insert element div before next_sibling_child
|
||||||
|
Pass add the class 'test' to the element inserted again before next_sibling_child
|
||||||
|
Pass remove the class 'test' from the element inserted again before next_sibling_child
|
||||||
|
Pass remove element div before next_sibling_child
|
||||||
|
Pass insert element div[test_attr] before next_sibling_child
|
||||||
|
Pass remove element div[test_attr] before next_sibling_child
|
||||||
|
Pass insert element div.test before next_sibling_descendant
|
||||||
|
Pass remove the class 'test' from the element inserted before next_sibling_descendant
|
||||||
|
Pass add the class 'test' again to the element inserted before next_sibling_descendant
|
||||||
|
Pass remove element div.test before next_sibling_descendant
|
||||||
|
Pass insert element div before next_sibling_descendant
|
||||||
|
Pass add the class 'test' to the element inserted again before next_sibling_descendant
|
||||||
|
Pass remove the class 'test' from the element inserted again before next_sibling_descendant
|
||||||
|
Pass remove element div before next_sibling_descendant
|
||||||
|
Pass insert element div[test_attr] before next_sibling_descendant
|
||||||
|
Pass remove element div[test_attr] before next_sibling_descendant
|
||||||
|
Pass insert element div.test after subject_ancestor
|
||||||
|
Pass remove the class 'test' from the element inserted after subject_ancestor
|
||||||
|
Pass add the class 'test' again to the element inserted after subject_ancestor
|
||||||
|
Pass remove element div.test after subject_ancestor
|
||||||
|
Pass insert element div after subject_ancestor
|
||||||
|
Pass add the class 'test' to the element inserted again after subject_ancestor
|
||||||
|
Pass remove the class 'test' from the element inserted again after subject_ancestor
|
||||||
|
Pass remove element div after subject_ancestor
|
||||||
|
Pass insert element div[test_attr] after subject_ancestor
|
||||||
|
Pass remove element div[test_attr] after subject_ancestor
|
||||||
|
Pass insert element div.test after subject_parent
|
||||||
|
Pass remove the class 'test' from the element inserted after subject_parent
|
||||||
|
Pass add the class 'test' again to the element inserted after subject_parent
|
||||||
|
Pass remove element div.test after subject_parent
|
||||||
|
Pass insert element div after subject_parent
|
||||||
|
Pass add the class 'test' to the element inserted again after subject_parent
|
||||||
|
Pass remove the class 'test' from the element inserted again after subject_parent
|
||||||
|
Pass remove element div after subject_parent
|
||||||
|
Pass insert element div[test_attr] after subject_parent
|
||||||
|
Pass remove element div[test_attr] after subject_parent
|
||||||
|
Pass insert element div.test after subject
|
||||||
|
Pass remove the class 'test' from the element inserted after subject
|
||||||
|
Pass add the class 'test' again to the element inserted after subject
|
||||||
|
Pass remove element div.test after subject
|
||||||
|
Pass insert element div after subject
|
||||||
|
Pass add the class 'test' to the element inserted again after subject
|
||||||
|
Pass remove the class 'test' from the element inserted again after subject
|
||||||
|
Pass remove element div after subject
|
||||||
|
Pass insert element div[test_attr] after subject
|
||||||
|
Pass remove element div[test_attr] after subject
|
||||||
|
Pass insert element div.test after subject_child
|
||||||
|
Pass remove the class 'test' from the element inserted after subject_child
|
||||||
|
Pass add the class 'test' again to the element inserted after subject_child
|
||||||
|
Pass remove element div.test after subject_child
|
||||||
|
Pass insert element div after subject_child
|
||||||
|
Pass add the class 'test' to the element inserted again after subject_child
|
||||||
|
Pass remove the class 'test' from the element inserted again after subject_child
|
||||||
|
Pass remove element div after subject_child
|
||||||
|
Pass insert element div[test_attr] after subject_child
|
||||||
|
Pass remove element div[test_attr] after subject_child
|
||||||
|
Pass insert element div.test after subject_descendant
|
||||||
|
Pass remove the class 'test' from the element inserted after subject_descendant
|
||||||
|
Pass add the class 'test' again to the element inserted after subject_descendant
|
||||||
|
Pass remove element div.test after subject_descendant
|
||||||
|
Pass insert element div after subject_descendant
|
||||||
|
Pass add the class 'test' to the element inserted again after subject_descendant
|
||||||
|
Pass remove the class 'test' from the element inserted again after subject_descendant
|
||||||
|
Pass remove element div after subject_descendant
|
||||||
|
Pass insert element div[test_attr] after subject_descendant
|
||||||
|
Pass remove element div[test_attr] after subject_descendant
|
||||||
|
Pass insert element div.test after next_sibling
|
||||||
|
Pass remove the class 'test' from the element inserted after next_sibling
|
||||||
|
Pass add the class 'test' again to the element inserted after next_sibling
|
||||||
|
Pass remove element div.test after next_sibling
|
||||||
|
Pass insert element div after next_sibling
|
||||||
|
Pass add the class 'test' to the element inserted again after next_sibling
|
||||||
|
Pass remove the class 'test' from the element inserted again after next_sibling
|
||||||
|
Pass remove element div after next_sibling
|
||||||
|
Pass insert element div[test_attr] after next_sibling
|
||||||
|
Pass remove element div[test_attr] after next_sibling
|
||||||
|
Pass insert element div.test after next_sibling_child
|
||||||
|
Pass remove the class 'test' from the element inserted after next_sibling_child
|
||||||
|
Pass add the class 'test' again to the element inserted after next_sibling_child
|
||||||
|
Pass remove element div.test after next_sibling_child
|
||||||
|
Pass insert element div after next_sibling_child
|
||||||
|
Pass add the class 'test' to the element inserted again after next_sibling_child
|
||||||
|
Pass remove the class 'test' from the element inserted again after next_sibling_child
|
||||||
|
Pass remove element div after next_sibling_child
|
||||||
|
Pass insert element div[test_attr] after next_sibling_child
|
||||||
|
Pass remove element div[test_attr] after next_sibling_child
|
||||||
|
Pass insert element div.test after next_sibling_descendant
|
||||||
|
Pass remove the class 'test' from the element inserted after next_sibling_descendant
|
||||||
|
Pass add the class 'test' again to the element inserted after next_sibling_descendant
|
||||||
|
Pass remove element div.test after next_sibling_descendant
|
||||||
|
Pass insert element div after next_sibling_descendant
|
||||||
|
Pass add the class 'test' to the element inserted again after next_sibling_descendant
|
||||||
|
Pass remove the class 'test' from the element inserted again after next_sibling_descendant
|
||||||
|
Pass remove element div after next_sibling_descendant
|
||||||
|
Pass insert element div[test_attr] after next_sibling_descendant
|
||||||
|
Pass remove element div[test_attr] after next_sibling_descendant
|
||||||
|
Pass insert tree div>div.test before subject_ancestor
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted before subject_ancestor
|
||||||
|
Pass add the class 'test' again to the element in the tree inserted before subject_ancestor
|
||||||
|
Pass remove tree div>div.test before subject_ancestor
|
||||||
|
Pass insert tree div>div before subject_ancestor
|
||||||
|
Pass add the class 'test' to the element in the tree inserted again before subject_ancestor
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted again before subject_ancestor
|
||||||
|
Pass remove tree div>div before subject_ancestor
|
||||||
|
Pass insert element div>div[test_attr] before subject_ancestor
|
||||||
|
Pass remove element div>div[test_attr] before subject_ancestor
|
||||||
|
Pass insert tree div>div.test before subject_parent
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted before subject_parent
|
||||||
|
Pass add the class 'test' again to the element in the tree inserted before subject_parent
|
||||||
|
Pass remove tree div>div.test before subject_parent
|
||||||
|
Pass insert tree div>div before subject_parent
|
||||||
|
Pass add the class 'test' to the element in the tree inserted again before subject_parent
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted again before subject_parent
|
||||||
|
Pass remove tree div>div before subject_parent
|
||||||
|
Pass insert element div>div[test_attr] before subject_parent
|
||||||
|
Pass remove element div>div[test_attr] before subject_parent
|
||||||
|
Pass insert tree div>div.test before subject
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted before subject
|
||||||
|
Pass add the class 'test' again to the element in the tree inserted before subject
|
||||||
|
Pass remove tree div>div.test before subject
|
||||||
|
Pass insert tree div>div before subject
|
||||||
|
Pass add the class 'test' to the element in the tree inserted again before subject
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted again before subject
|
||||||
|
Pass remove tree div>div before subject
|
||||||
|
Pass insert element div>div[test_attr] before subject
|
||||||
|
Pass remove element div>div[test_attr] before subject
|
||||||
|
Pass insert tree div>div.test before subject_child
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted before subject_child
|
||||||
|
Pass add the class 'test' again to the element in the tree inserted before subject_child
|
||||||
|
Pass remove tree div>div.test before subject_child
|
||||||
|
Pass insert tree div>div before subject_child
|
||||||
|
Pass add the class 'test' to the element in the tree inserted again before subject_child
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted again before subject_child
|
||||||
|
Pass remove tree div>div before subject_child
|
||||||
|
Pass insert element div>div[test_attr] before subject_child
|
||||||
|
Pass remove element div>div[test_attr] before subject_child
|
||||||
|
Pass insert tree div>div.test before subject_descendant
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted before subject_descendant
|
||||||
|
Pass add the class 'test' again to the element in the tree inserted before subject_descendant
|
||||||
|
Pass remove tree div>div.test before subject_descendant
|
||||||
|
Pass insert tree div>div before subject_descendant
|
||||||
|
Pass add the class 'test' to the element in the tree inserted again before subject_descendant
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted again before subject_descendant
|
||||||
|
Pass remove tree div>div before subject_descendant
|
||||||
|
Pass insert element div>div[test_attr] before subject_descendant
|
||||||
|
Pass remove element div>div[test_attr] before subject_descendant
|
||||||
|
Pass insert tree div>div.test before next_sibling
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted before next_sibling
|
||||||
|
Pass add the class 'test' again to the element in the tree inserted before next_sibling
|
||||||
|
Pass remove tree div>div.test before next_sibling
|
||||||
|
Pass insert tree div>div before next_sibling
|
||||||
|
Pass add the class 'test' to the element in the tree inserted again before next_sibling
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted again before next_sibling
|
||||||
|
Pass remove tree div>div before next_sibling
|
||||||
|
Pass insert element div>div[test_attr] before next_sibling
|
||||||
|
Pass remove element div>div[test_attr] before next_sibling
|
||||||
|
Pass insert tree div>div.test before next_sibling_child
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted before next_sibling_child
|
||||||
|
Pass add the class 'test' again to the element in the tree inserted before next_sibling_child
|
||||||
|
Pass remove tree div>div.test before next_sibling_child
|
||||||
|
Pass insert tree div>div before next_sibling_child
|
||||||
|
Pass add the class 'test' to the element in the tree inserted again before next_sibling_child
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted again before next_sibling_child
|
||||||
|
Pass remove tree div>div before next_sibling_child
|
||||||
|
Pass insert element div>div[test_attr] before next_sibling_child
|
||||||
|
Pass remove element div>div[test_attr] before next_sibling_child
|
||||||
|
Pass insert tree div>div.test before next_sibling_descendant
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted before next_sibling_descendant
|
||||||
|
Pass add the class 'test' again to the element in the tree inserted before next_sibling_descendant
|
||||||
|
Pass remove tree div>div.test before next_sibling_descendant
|
||||||
|
Pass insert tree div>div before next_sibling_descendant
|
||||||
|
Pass add the class 'test' to the element in the tree inserted again before next_sibling_descendant
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted again before next_sibling_descendant
|
||||||
|
Pass remove tree div>div before next_sibling_descendant
|
||||||
|
Pass insert element div>div[test_attr] before next_sibling_descendant
|
||||||
|
Pass remove element div>div[test_attr] before next_sibling_descendant
|
||||||
|
Pass insert tree div>div.test after subject_ancestor
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted after subject_ancestor
|
||||||
|
Pass add the class 'test' again to the element in the tree inserted after subject_ancestor
|
||||||
|
Pass remove tree div>div.test after subject_ancestor
|
||||||
|
Pass insert tree div>div after subject_ancestor
|
||||||
|
Pass add the class 'test' to the element in the tree inserted again after subject_ancestor
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted again after subject_ancestor
|
||||||
|
Pass remove tree div>div after subject_ancestor
|
||||||
|
Pass insert element div>div[test_attr] after subject_ancestor
|
||||||
|
Pass remove element div>div[test_attr] after subject_ancestor
|
||||||
|
Pass insert tree div>div.test after subject_parent
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted after subject_parent
|
||||||
|
Pass add the class 'test' again to the element in the tree inserted after subject_parent
|
||||||
|
Pass remove tree div>div.test after subject_parent
|
||||||
|
Pass insert tree div>div after subject_parent
|
||||||
|
Pass add the class 'test' to the element in the tree inserted again after subject_parent
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted again after subject_parent
|
||||||
|
Pass remove tree div>div after subject_parent
|
||||||
|
Pass insert element div>div[test_attr] after subject_parent
|
||||||
|
Pass remove element div>div[test_attr] after subject_parent
|
||||||
|
Pass insert tree div>div.test after subject
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted after subject
|
||||||
|
Pass add the class 'test' again to the element in the tree inserted after subject
|
||||||
|
Pass remove tree div>div.test after subject
|
||||||
|
Pass insert tree div>div after subject
|
||||||
|
Pass add the class 'test' to the element in the tree inserted again after subject
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted again after subject
|
||||||
|
Pass remove tree div>div after subject
|
||||||
|
Pass insert element div>div[test_attr] after subject
|
||||||
|
Pass remove element div>div[test_attr] after subject
|
||||||
|
Pass insert tree div>div.test after subject_child
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted after subject_child
|
||||||
|
Pass add the class 'test' again to the element in the tree inserted after subject_child
|
||||||
|
Pass remove tree div>div.test after subject_child
|
||||||
|
Pass insert tree div>div after subject_child
|
||||||
|
Pass add the class 'test' to the element in the tree inserted again after subject_child
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted again after subject_child
|
||||||
|
Pass remove tree div>div after subject_child
|
||||||
|
Pass insert element div>div[test_attr] after subject_child
|
||||||
|
Pass remove element div>div[test_attr] after subject_child
|
||||||
|
Pass insert tree div>div.test after subject_descendant
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted after subject_descendant
|
||||||
|
Pass add the class 'test' again to the element in the tree inserted after subject_descendant
|
||||||
|
Pass remove tree div>div.test after subject_descendant
|
||||||
|
Pass insert tree div>div after subject_descendant
|
||||||
|
Pass add the class 'test' to the element in the tree inserted again after subject_descendant
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted again after subject_descendant
|
||||||
|
Pass remove tree div>div after subject_descendant
|
||||||
|
Pass insert element div>div[test_attr] after subject_descendant
|
||||||
|
Pass remove element div>div[test_attr] after subject_descendant
|
||||||
|
Pass insert tree div>div.test after next_sibling
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted after next_sibling
|
||||||
|
Pass add the class 'test' again to the element in the tree inserted after next_sibling
|
||||||
|
Pass remove tree div>div.test after next_sibling
|
||||||
|
Pass insert tree div>div after next_sibling
|
||||||
|
Pass add the class 'test' to the element in the tree inserted again after next_sibling
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted again after next_sibling
|
||||||
|
Pass remove tree div>div after next_sibling
|
||||||
|
Pass insert element div>div[test_attr] after next_sibling
|
||||||
|
Pass remove element div>div[test_attr] after next_sibling
|
||||||
|
Pass insert tree div>div.test after next_sibling_child
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted after next_sibling_child
|
||||||
|
Pass add the class 'test' again to the element in the tree inserted after next_sibling_child
|
||||||
|
Pass remove tree div>div.test after next_sibling_child
|
||||||
|
Pass insert tree div>div after next_sibling_child
|
||||||
|
Pass add the class 'test' to the element in the tree inserted again after next_sibling_child
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted again after next_sibling_child
|
||||||
|
Pass remove tree div>div after next_sibling_child
|
||||||
|
Pass insert element div>div[test_attr] after next_sibling_child
|
||||||
|
Pass remove element div>div[test_attr] after next_sibling_child
|
||||||
|
Pass insert tree div>div.test after next_sibling_descendant
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted after next_sibling_descendant
|
||||||
|
Pass add the class 'test' again to the element in the tree inserted after next_sibling_descendant
|
||||||
|
Pass remove tree div>div.test after next_sibling_descendant
|
||||||
|
Pass insert tree div>div after next_sibling_descendant
|
||||||
|
Pass add the class 'test' to the element in the tree inserted again after next_sibling_descendant
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted again after next_sibling_descendant
|
||||||
|
Pass remove tree div>div after next_sibling_descendant
|
||||||
|
Pass insert element div>div[test_attr] after next_sibling_descendant
|
||||||
|
Pass remove element div>div[test_attr] after next_sibling_descendant
|
|
@ -0,0 +1,221 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 211 tests
|
||||||
|
|
||||||
|
211 Pass
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass Initial color
|
||||||
|
Pass add .test to subject_ancestor
|
||||||
|
Pass remove .test from subject_ancestor
|
||||||
|
Pass add .test to subject_parent
|
||||||
|
Pass remove .test from subject_parent
|
||||||
|
Pass add .test to subject
|
||||||
|
Pass remove .test from subject
|
||||||
|
Pass add .test to subject_child
|
||||||
|
Pass remove .test from subject_child
|
||||||
|
Pass add .test to subject_descendant
|
||||||
|
Pass remove .test from subject_descendant
|
||||||
|
Pass insert element div.test before subject_ancestor
|
||||||
|
Pass remove the class 'test' from the element inserted before subject_ancestor
|
||||||
|
Pass add the class 'test' again to the element inserted before subject_ancestor
|
||||||
|
Pass remove element div.test before subject_ancestor
|
||||||
|
Pass insert element div before subject_ancestor
|
||||||
|
Pass add the class 'test' to the element inserted again before subject_ancestor
|
||||||
|
Pass remove the class 'test' from the element inserted again before subject_ancestor
|
||||||
|
Pass remove element div before subject_ancestor
|
||||||
|
Pass insert element div[test_attr] before subject_ancestor
|
||||||
|
Pass remove element div[test_attr] before subject_ancestor
|
||||||
|
Pass insert element div.test before subject_parent
|
||||||
|
Pass remove the class 'test' from the element inserted before subject_parent
|
||||||
|
Pass add the class 'test' again to the element inserted before subject_parent
|
||||||
|
Pass remove element div.test before subject_parent
|
||||||
|
Pass insert element div before subject_parent
|
||||||
|
Pass add the class 'test' to the element inserted again before subject_parent
|
||||||
|
Pass remove the class 'test' from the element inserted again before subject_parent
|
||||||
|
Pass remove element div before subject_parent
|
||||||
|
Pass insert element div[test_attr] before subject_parent
|
||||||
|
Pass remove element div[test_attr] before subject_parent
|
||||||
|
Pass insert element div.test before subject
|
||||||
|
Pass remove the class 'test' from the element inserted before subject
|
||||||
|
Pass add the class 'test' again to the element inserted before subject
|
||||||
|
Pass remove element div.test before subject
|
||||||
|
Pass insert element div before subject
|
||||||
|
Pass add the class 'test' to the element inserted again before subject
|
||||||
|
Pass remove the class 'test' from the element inserted again before subject
|
||||||
|
Pass remove element div before subject
|
||||||
|
Pass insert element div[test_attr] before subject
|
||||||
|
Pass remove element div[test_attr] before subject
|
||||||
|
Pass insert element div.test before subject_child
|
||||||
|
Pass remove the class 'test' from the element inserted before subject_child
|
||||||
|
Pass add the class 'test' again to the element inserted before subject_child
|
||||||
|
Pass remove element div.test before subject_child
|
||||||
|
Pass insert element div before subject_child
|
||||||
|
Pass add the class 'test' to the element inserted again before subject_child
|
||||||
|
Pass remove the class 'test' from the element inserted again before subject_child
|
||||||
|
Pass remove element div before subject_child
|
||||||
|
Pass insert element div[test_attr] before subject_child
|
||||||
|
Pass remove element div[test_attr] before subject_child
|
||||||
|
Pass insert element div.test before subject_descendant
|
||||||
|
Pass remove the class 'test' from the element inserted before subject_descendant
|
||||||
|
Pass add the class 'test' again to the element inserted before subject_descendant
|
||||||
|
Pass remove element div.test before subject_descendant
|
||||||
|
Pass insert element div before subject_descendant
|
||||||
|
Pass add the class 'test' to the element inserted again before subject_descendant
|
||||||
|
Pass remove the class 'test' from the element inserted again before subject_descendant
|
||||||
|
Pass remove element div before subject_descendant
|
||||||
|
Pass insert element div[test_attr] before subject_descendant
|
||||||
|
Pass remove element div[test_attr] before subject_descendant
|
||||||
|
Pass insert element div.test after subject_ancestor
|
||||||
|
Pass remove the class 'test' from the element inserted after subject_ancestor
|
||||||
|
Pass add the class 'test' again to the element inserted after subject_ancestor
|
||||||
|
Pass remove element div.test after subject_ancestor
|
||||||
|
Pass insert element div after subject_ancestor
|
||||||
|
Pass add the class 'test' to the element inserted again after subject_ancestor
|
||||||
|
Pass remove the class 'test' from the element inserted again after subject_ancestor
|
||||||
|
Pass remove element div after subject_ancestor
|
||||||
|
Pass insert element div[test_attr] after subject_ancestor
|
||||||
|
Pass remove element div[test_attr] after subject_ancestor
|
||||||
|
Pass insert element div.test after subject_parent
|
||||||
|
Pass remove the class 'test' from the element inserted after subject_parent
|
||||||
|
Pass add the class 'test' again to the element inserted after subject_parent
|
||||||
|
Pass remove element div.test after subject_parent
|
||||||
|
Pass insert element div after subject_parent
|
||||||
|
Pass add the class 'test' to the element inserted again after subject_parent
|
||||||
|
Pass remove the class 'test' from the element inserted again after subject_parent
|
||||||
|
Pass remove element div after subject_parent
|
||||||
|
Pass insert element div[test_attr] after subject_parent
|
||||||
|
Pass remove element div[test_attr] after subject_parent
|
||||||
|
Pass insert element div.test after subject
|
||||||
|
Pass remove the class 'test' from the element inserted after subject
|
||||||
|
Pass add the class 'test' again to the element inserted after subject
|
||||||
|
Pass remove element div.test after subject
|
||||||
|
Pass insert element div after subject
|
||||||
|
Pass add the class 'test' to the element inserted again after subject
|
||||||
|
Pass remove the class 'test' from the element inserted again after subject
|
||||||
|
Pass remove element div after subject
|
||||||
|
Pass insert element div[test_attr] after subject
|
||||||
|
Pass remove element div[test_attr] after subject
|
||||||
|
Pass insert element div.test after subject_child
|
||||||
|
Pass remove the class 'test' from the element inserted after subject_child
|
||||||
|
Pass add the class 'test' again to the element inserted after subject_child
|
||||||
|
Pass remove element div.test after subject_child
|
||||||
|
Pass insert element div after subject_child
|
||||||
|
Pass add the class 'test' to the element inserted again after subject_child
|
||||||
|
Pass remove the class 'test' from the element inserted again after subject_child
|
||||||
|
Pass remove element div after subject_child
|
||||||
|
Pass insert element div[test_attr] after subject_child
|
||||||
|
Pass remove element div[test_attr] after subject_child
|
||||||
|
Pass insert element div.test after subject_descendant
|
||||||
|
Pass remove the class 'test' from the element inserted after subject_descendant
|
||||||
|
Pass add the class 'test' again to the element inserted after subject_descendant
|
||||||
|
Pass remove element div.test after subject_descendant
|
||||||
|
Pass insert element div after subject_descendant
|
||||||
|
Pass add the class 'test' to the element inserted again after subject_descendant
|
||||||
|
Pass remove the class 'test' from the element inserted again after subject_descendant
|
||||||
|
Pass remove element div after subject_descendant
|
||||||
|
Pass insert element div[test_attr] after subject_descendant
|
||||||
|
Pass remove element div[test_attr] after subject_descendant
|
||||||
|
Pass insert tree div>div.test before subject_ancestor
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted before subject_ancestor
|
||||||
|
Pass add the class 'test' again to the element in the tree inserted before subject_ancestor
|
||||||
|
Pass remove tree div>div.test before subject_ancestor
|
||||||
|
Pass insert tree div>div before subject_ancestor
|
||||||
|
Pass add the class 'test' to the element in the tree inserted again before subject_ancestor
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted again before subject_ancestor
|
||||||
|
Pass remove tree div>div before subject_ancestor
|
||||||
|
Pass insert element div>div[test_attr] before subject_ancestor
|
||||||
|
Pass remove element div>div[test_attr] before subject_ancestor
|
||||||
|
Pass insert tree div>div.test before subject_parent
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted before subject_parent
|
||||||
|
Pass add the class 'test' again to the element in the tree inserted before subject_parent
|
||||||
|
Pass remove tree div>div.test before subject_parent
|
||||||
|
Pass insert tree div>div before subject_parent
|
||||||
|
Pass add the class 'test' to the element in the tree inserted again before subject_parent
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted again before subject_parent
|
||||||
|
Pass remove tree div>div before subject_parent
|
||||||
|
Pass insert element div>div[test_attr] before subject_parent
|
||||||
|
Pass remove element div>div[test_attr] before subject_parent
|
||||||
|
Pass insert tree div>div.test before subject
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted before subject
|
||||||
|
Pass add the class 'test' again to the element in the tree inserted before subject
|
||||||
|
Pass remove tree div>div.test before subject
|
||||||
|
Pass insert tree div>div before subject
|
||||||
|
Pass add the class 'test' to the element in the tree inserted again before subject
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted again before subject
|
||||||
|
Pass remove tree div>div before subject
|
||||||
|
Pass insert element div>div[test_attr] before subject
|
||||||
|
Pass remove element div>div[test_attr] before subject
|
||||||
|
Pass insert tree div>div.test before subject_child
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted before subject_child
|
||||||
|
Pass add the class 'test' again to the element in the tree inserted before subject_child
|
||||||
|
Pass remove tree div>div.test before subject_child
|
||||||
|
Pass insert tree div>div before subject_child
|
||||||
|
Pass add the class 'test' to the element in the tree inserted again before subject_child
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted again before subject_child
|
||||||
|
Pass remove tree div>div before subject_child
|
||||||
|
Pass insert element div>div[test_attr] before subject_child
|
||||||
|
Pass remove element div>div[test_attr] before subject_child
|
||||||
|
Pass insert tree div>div.test before subject_descendant
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted before subject_descendant
|
||||||
|
Pass add the class 'test' again to the element in the tree inserted before subject_descendant
|
||||||
|
Pass remove tree div>div.test before subject_descendant
|
||||||
|
Pass insert tree div>div before subject_descendant
|
||||||
|
Pass add the class 'test' to the element in the tree inserted again before subject_descendant
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted again before subject_descendant
|
||||||
|
Pass remove tree div>div before subject_descendant
|
||||||
|
Pass insert element div>div[test_attr] before subject_descendant
|
||||||
|
Pass remove element div>div[test_attr] before subject_descendant
|
||||||
|
Pass insert tree div>div.test after subject_ancestor
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted after subject_ancestor
|
||||||
|
Pass add the class 'test' again to the element in the tree inserted after subject_ancestor
|
||||||
|
Pass remove tree div>div.test after subject_ancestor
|
||||||
|
Pass insert tree div>div after subject_ancestor
|
||||||
|
Pass add the class 'test' to the element in the tree inserted again after subject_ancestor
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted again after subject_ancestor
|
||||||
|
Pass remove tree div>div after subject_ancestor
|
||||||
|
Pass insert element div>div[test_attr] after subject_ancestor
|
||||||
|
Pass remove element div>div[test_attr] after subject_ancestor
|
||||||
|
Pass insert tree div>div.test after subject_parent
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted after subject_parent
|
||||||
|
Pass add the class 'test' again to the element in the tree inserted after subject_parent
|
||||||
|
Pass remove tree div>div.test after subject_parent
|
||||||
|
Pass insert tree div>div after subject_parent
|
||||||
|
Pass add the class 'test' to the element in the tree inserted again after subject_parent
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted again after subject_parent
|
||||||
|
Pass remove tree div>div after subject_parent
|
||||||
|
Pass insert element div>div[test_attr] after subject_parent
|
||||||
|
Pass remove element div>div[test_attr] after subject_parent
|
||||||
|
Pass insert tree div>div.test after subject
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted after subject
|
||||||
|
Pass add the class 'test' again to the element in the tree inserted after subject
|
||||||
|
Pass remove tree div>div.test after subject
|
||||||
|
Pass insert tree div>div after subject
|
||||||
|
Pass add the class 'test' to the element in the tree inserted again after subject
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted again after subject
|
||||||
|
Pass remove tree div>div after subject
|
||||||
|
Pass insert element div>div[test_attr] after subject
|
||||||
|
Pass remove element div>div[test_attr] after subject
|
||||||
|
Pass insert tree div>div.test after subject_child
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted after subject_child
|
||||||
|
Pass add the class 'test' again to the element in the tree inserted after subject_child
|
||||||
|
Pass remove tree div>div.test after subject_child
|
||||||
|
Pass insert tree div>div after subject_child
|
||||||
|
Pass add the class 'test' to the element in the tree inserted again after subject_child
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted again after subject_child
|
||||||
|
Pass remove tree div>div after subject_child
|
||||||
|
Pass insert element div>div[test_attr] after subject_child
|
||||||
|
Pass remove element div>div[test_attr] after subject_child
|
||||||
|
Pass insert tree div>div.test after subject_descendant
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted after subject_descendant
|
||||||
|
Pass add the class 'test' again to the element in the tree inserted after subject_descendant
|
||||||
|
Pass remove tree div>div.test after subject_descendant
|
||||||
|
Pass insert tree div>div after subject_descendant
|
||||||
|
Pass add the class 'test' to the element in the tree inserted again after subject_descendant
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted again after subject_descendant
|
||||||
|
Pass remove tree div>div after subject_descendant
|
||||||
|
Pass insert element div>div[test_attr] after subject_descendant
|
||||||
|
Pass remove element div>div[test_attr] after subject_descendant
|
|
@ -0,0 +1,305 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 295 tests
|
||||||
|
|
||||||
|
295 Pass
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass Initial color
|
||||||
|
Pass add .test to previous_sibling
|
||||||
|
Pass remove .test from previous_sibling
|
||||||
|
Pass add .test to previous_sibling_child
|
||||||
|
Pass remove .test from previous_sibling_child
|
||||||
|
Pass add .test to previous_sibling_descendant
|
||||||
|
Pass remove .test from previous_sibling_descendant
|
||||||
|
Pass add .test to subject
|
||||||
|
Pass remove .test from subject
|
||||||
|
Pass add .test to next_sibling
|
||||||
|
Pass remove .test from next_sibling
|
||||||
|
Pass add .test to next_sibling_child
|
||||||
|
Pass remove .test from next_sibling_child
|
||||||
|
Pass add .test to next_sibling_descendant
|
||||||
|
Pass remove .test from next_sibling_descendant
|
||||||
|
Pass insert element div.test before previous_sibling
|
||||||
|
Pass remove the class 'test' from the element inserted before previous_sibling
|
||||||
|
Pass add the class 'test' again to the element inserted before previous_sibling
|
||||||
|
Pass remove element div.test before previous_sibling
|
||||||
|
Pass insert element div before previous_sibling
|
||||||
|
Pass add the class 'test' to the element inserted again before previous_sibling
|
||||||
|
Pass remove the class 'test' from the element inserted again before previous_sibling
|
||||||
|
Pass remove element div before previous_sibling
|
||||||
|
Pass insert element div[test_attr] before previous_sibling
|
||||||
|
Pass remove element div[test_attr] before previous_sibling
|
||||||
|
Pass insert element div.test before previous_sibling_child
|
||||||
|
Pass remove the class 'test' from the element inserted before previous_sibling_child
|
||||||
|
Pass add the class 'test' again to the element inserted before previous_sibling_child
|
||||||
|
Pass remove element div.test before previous_sibling_child
|
||||||
|
Pass insert element div before previous_sibling_child
|
||||||
|
Pass add the class 'test' to the element inserted again before previous_sibling_child
|
||||||
|
Pass remove the class 'test' from the element inserted again before previous_sibling_child
|
||||||
|
Pass remove element div before previous_sibling_child
|
||||||
|
Pass insert element div[test_attr] before previous_sibling_child
|
||||||
|
Pass remove element div[test_attr] before previous_sibling_child
|
||||||
|
Pass insert element div.test before previous_sibling_descendant
|
||||||
|
Pass remove the class 'test' from the element inserted before previous_sibling_descendant
|
||||||
|
Pass add the class 'test' again to the element inserted before previous_sibling_descendant
|
||||||
|
Pass remove element div.test before previous_sibling_descendant
|
||||||
|
Pass insert element div before previous_sibling_descendant
|
||||||
|
Pass add the class 'test' to the element inserted again before previous_sibling_descendant
|
||||||
|
Pass remove the class 'test' from the element inserted again before previous_sibling_descendant
|
||||||
|
Pass remove element div before previous_sibling_descendant
|
||||||
|
Pass insert element div[test_attr] before previous_sibling_descendant
|
||||||
|
Pass remove element div[test_attr] before previous_sibling_descendant
|
||||||
|
Pass insert element div.test before subject
|
||||||
|
Pass remove the class 'test' from the element inserted before subject
|
||||||
|
Pass add the class 'test' again to the element inserted before subject
|
||||||
|
Pass remove element div.test before subject
|
||||||
|
Pass insert element div before subject
|
||||||
|
Pass add the class 'test' to the element inserted again before subject
|
||||||
|
Pass remove the class 'test' from the element inserted again before subject
|
||||||
|
Pass remove element div before subject
|
||||||
|
Pass insert element div[test_attr] before subject
|
||||||
|
Pass remove element div[test_attr] before subject
|
||||||
|
Pass insert element div.test before next_sibling
|
||||||
|
Pass remove the class 'test' from the element inserted before next_sibling
|
||||||
|
Pass add the class 'test' again to the element inserted before next_sibling
|
||||||
|
Pass remove element div.test before next_sibling
|
||||||
|
Pass insert element div before next_sibling
|
||||||
|
Pass add the class 'test' to the element inserted again before next_sibling
|
||||||
|
Pass remove the class 'test' from the element inserted again before next_sibling
|
||||||
|
Pass remove element div before next_sibling
|
||||||
|
Pass insert element div[test_attr] before next_sibling
|
||||||
|
Pass remove element div[test_attr] before next_sibling
|
||||||
|
Pass insert element div.test before next_sibling_child
|
||||||
|
Pass remove the class 'test' from the element inserted before next_sibling_child
|
||||||
|
Pass add the class 'test' again to the element inserted before next_sibling_child
|
||||||
|
Pass remove element div.test before next_sibling_child
|
||||||
|
Pass insert element div before next_sibling_child
|
||||||
|
Pass add the class 'test' to the element inserted again before next_sibling_child
|
||||||
|
Pass remove the class 'test' from the element inserted again before next_sibling_child
|
||||||
|
Pass remove element div before next_sibling_child
|
||||||
|
Pass insert element div[test_attr] before next_sibling_child
|
||||||
|
Pass remove element div[test_attr] before next_sibling_child
|
||||||
|
Pass insert element div.test before next_sibling_descendant
|
||||||
|
Pass remove the class 'test' from the element inserted before next_sibling_descendant
|
||||||
|
Pass add the class 'test' again to the element inserted before next_sibling_descendant
|
||||||
|
Pass remove element div.test before next_sibling_descendant
|
||||||
|
Pass insert element div before next_sibling_descendant
|
||||||
|
Pass add the class 'test' to the element inserted again before next_sibling_descendant
|
||||||
|
Pass remove the class 'test' from the element inserted again before next_sibling_descendant
|
||||||
|
Pass remove element div before next_sibling_descendant
|
||||||
|
Pass insert element div[test_attr] before next_sibling_descendant
|
||||||
|
Pass remove element div[test_attr] before next_sibling_descendant
|
||||||
|
Pass insert element div.test after previous_sibling
|
||||||
|
Pass remove the class 'test' from the element inserted after previous_sibling
|
||||||
|
Pass add the class 'test' again to the element inserted after previous_sibling
|
||||||
|
Pass remove element div.test after previous_sibling
|
||||||
|
Pass insert element div after previous_sibling
|
||||||
|
Pass add the class 'test' to the element inserted again after previous_sibling
|
||||||
|
Pass remove the class 'test' from the element inserted again after previous_sibling
|
||||||
|
Pass remove element div after previous_sibling
|
||||||
|
Pass insert element div[test_attr] after previous_sibling
|
||||||
|
Pass remove element div[test_attr] after previous_sibling
|
||||||
|
Pass insert element div.test after previous_sibling_child
|
||||||
|
Pass remove the class 'test' from the element inserted after previous_sibling_child
|
||||||
|
Pass add the class 'test' again to the element inserted after previous_sibling_child
|
||||||
|
Pass remove element div.test after previous_sibling_child
|
||||||
|
Pass insert element div after previous_sibling_child
|
||||||
|
Pass add the class 'test' to the element inserted again after previous_sibling_child
|
||||||
|
Pass remove the class 'test' from the element inserted again after previous_sibling_child
|
||||||
|
Pass remove element div after previous_sibling_child
|
||||||
|
Pass insert element div[test_attr] after previous_sibling_child
|
||||||
|
Pass remove element div[test_attr] after previous_sibling_child
|
||||||
|
Pass insert element div.test after previous_sibling_descendant
|
||||||
|
Pass remove the class 'test' from the element inserted after previous_sibling_descendant
|
||||||
|
Pass add the class 'test' again to the element inserted after previous_sibling_descendant
|
||||||
|
Pass remove element div.test after previous_sibling_descendant
|
||||||
|
Pass insert element div after previous_sibling_descendant
|
||||||
|
Pass add the class 'test' to the element inserted again after previous_sibling_descendant
|
||||||
|
Pass remove the class 'test' from the element inserted again after previous_sibling_descendant
|
||||||
|
Pass remove element div after previous_sibling_descendant
|
||||||
|
Pass insert element div[test_attr] after previous_sibling_descendant
|
||||||
|
Pass remove element div[test_attr] after previous_sibling_descendant
|
||||||
|
Pass insert element div.test after subject
|
||||||
|
Pass remove the class 'test' from the element inserted after subject
|
||||||
|
Pass add the class 'test' again to the element inserted after subject
|
||||||
|
Pass remove element div.test after subject
|
||||||
|
Pass insert element div after subject
|
||||||
|
Pass add the class 'test' to the element inserted again after subject
|
||||||
|
Pass remove the class 'test' from the element inserted again after subject
|
||||||
|
Pass remove element div after subject
|
||||||
|
Pass insert element div[test_attr] after subject
|
||||||
|
Pass remove element div[test_attr] after subject
|
||||||
|
Pass insert element div.test after next_sibling
|
||||||
|
Pass remove the class 'test' from the element inserted after next_sibling
|
||||||
|
Pass add the class 'test' again to the element inserted after next_sibling
|
||||||
|
Pass remove element div.test after next_sibling
|
||||||
|
Pass insert element div after next_sibling
|
||||||
|
Pass add the class 'test' to the element inserted again after next_sibling
|
||||||
|
Pass remove the class 'test' from the element inserted again after next_sibling
|
||||||
|
Pass remove element div after next_sibling
|
||||||
|
Pass insert element div[test_attr] after next_sibling
|
||||||
|
Pass remove element div[test_attr] after next_sibling
|
||||||
|
Pass insert element div.test after next_sibling_child
|
||||||
|
Pass remove the class 'test' from the element inserted after next_sibling_child
|
||||||
|
Pass add the class 'test' again to the element inserted after next_sibling_child
|
||||||
|
Pass remove element div.test after next_sibling_child
|
||||||
|
Pass insert element div after next_sibling_child
|
||||||
|
Pass add the class 'test' to the element inserted again after next_sibling_child
|
||||||
|
Pass remove the class 'test' from the element inserted again after next_sibling_child
|
||||||
|
Pass remove element div after next_sibling_child
|
||||||
|
Pass insert element div[test_attr] after next_sibling_child
|
||||||
|
Pass remove element div[test_attr] after next_sibling_child
|
||||||
|
Pass insert element div.test after next_sibling_descendant
|
||||||
|
Pass remove the class 'test' from the element inserted after next_sibling_descendant
|
||||||
|
Pass add the class 'test' again to the element inserted after next_sibling_descendant
|
||||||
|
Pass remove element div.test after next_sibling_descendant
|
||||||
|
Pass insert element div after next_sibling_descendant
|
||||||
|
Pass add the class 'test' to the element inserted again after next_sibling_descendant
|
||||||
|
Pass remove the class 'test' from the element inserted again after next_sibling_descendant
|
||||||
|
Pass remove element div after next_sibling_descendant
|
||||||
|
Pass insert element div[test_attr] after next_sibling_descendant
|
||||||
|
Pass remove element div[test_attr] after next_sibling_descendant
|
||||||
|
Pass insert tree div>div.test before previous_sibling
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted before previous_sibling
|
||||||
|
Pass add the class 'test' again to the element in the tree inserted before previous_sibling
|
||||||
|
Pass remove tree div>div.test before previous_sibling
|
||||||
|
Pass insert tree div>div before previous_sibling
|
||||||
|
Pass add the class 'test' to the element in the tree inserted again before previous_sibling
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted again before previous_sibling
|
||||||
|
Pass remove tree div>div before previous_sibling
|
||||||
|
Pass insert element div>div[test_attr] before previous_sibling
|
||||||
|
Pass remove element div>div[test_attr] before previous_sibling
|
||||||
|
Pass insert tree div>div.test before previous_sibling_child
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted before previous_sibling_child
|
||||||
|
Pass add the class 'test' again to the element in the tree inserted before previous_sibling_child
|
||||||
|
Pass remove tree div>div.test before previous_sibling_child
|
||||||
|
Pass insert tree div>div before previous_sibling_child
|
||||||
|
Pass add the class 'test' to the element in the tree inserted again before previous_sibling_child
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted again before previous_sibling_child
|
||||||
|
Pass remove tree div>div before previous_sibling_child
|
||||||
|
Pass insert element div>div[test_attr] before previous_sibling_child
|
||||||
|
Pass remove element div>div[test_attr] before previous_sibling_child
|
||||||
|
Pass insert tree div>div.test before previous_sibling_descendant
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted before previous_sibling_descendant
|
||||||
|
Pass add the class 'test' again to the element in the tree inserted before previous_sibling_descendant
|
||||||
|
Pass remove tree div>div.test before previous_sibling_descendant
|
||||||
|
Pass insert tree div>div before previous_sibling_descendant
|
||||||
|
Pass add the class 'test' to the element in the tree inserted again before previous_sibling_descendant
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted again before previous_sibling_descendant
|
||||||
|
Pass remove tree div>div before previous_sibling_descendant
|
||||||
|
Pass insert element div>div[test_attr] before previous_sibling_descendant
|
||||||
|
Pass remove element div>div[test_attr] before previous_sibling_descendant
|
||||||
|
Pass insert tree div>div.test before subject
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted before subject
|
||||||
|
Pass add the class 'test' again to the element in the tree inserted before subject
|
||||||
|
Pass remove tree div>div.test before subject
|
||||||
|
Pass insert tree div>div before subject
|
||||||
|
Pass add the class 'test' to the element in the tree inserted again before subject
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted again before subject
|
||||||
|
Pass remove tree div>div before subject
|
||||||
|
Pass insert element div>div[test_attr] before subject
|
||||||
|
Pass remove element div>div[test_attr] before subject
|
||||||
|
Pass insert tree div>div.test before next_sibling
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted before next_sibling
|
||||||
|
Pass add the class 'test' again to the element in the tree inserted before next_sibling
|
||||||
|
Pass remove tree div>div.test before next_sibling
|
||||||
|
Pass insert tree div>div before next_sibling
|
||||||
|
Pass add the class 'test' to the element in the tree inserted again before next_sibling
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted again before next_sibling
|
||||||
|
Pass remove tree div>div before next_sibling
|
||||||
|
Pass insert element div>div[test_attr] before next_sibling
|
||||||
|
Pass remove element div>div[test_attr] before next_sibling
|
||||||
|
Pass insert tree div>div.test before next_sibling_child
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted before next_sibling_child
|
||||||
|
Pass add the class 'test' again to the element in the tree inserted before next_sibling_child
|
||||||
|
Pass remove tree div>div.test before next_sibling_child
|
||||||
|
Pass insert tree div>div before next_sibling_child
|
||||||
|
Pass add the class 'test' to the element in the tree inserted again before next_sibling_child
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted again before next_sibling_child
|
||||||
|
Pass remove tree div>div before next_sibling_child
|
||||||
|
Pass insert element div>div[test_attr] before next_sibling_child
|
||||||
|
Pass remove element div>div[test_attr] before next_sibling_child
|
||||||
|
Pass insert tree div>div.test before next_sibling_descendant
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted before next_sibling_descendant
|
||||||
|
Pass add the class 'test' again to the element in the tree inserted before next_sibling_descendant
|
||||||
|
Pass remove tree div>div.test before next_sibling_descendant
|
||||||
|
Pass insert tree div>div before next_sibling_descendant
|
||||||
|
Pass add the class 'test' to the element in the tree inserted again before next_sibling_descendant
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted again before next_sibling_descendant
|
||||||
|
Pass remove tree div>div before next_sibling_descendant
|
||||||
|
Pass insert element div>div[test_attr] before next_sibling_descendant
|
||||||
|
Pass remove element div>div[test_attr] before next_sibling_descendant
|
||||||
|
Pass insert tree div>div.test after previous_sibling
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted after previous_sibling
|
||||||
|
Pass add the class 'test' again to the element in the tree inserted after previous_sibling
|
||||||
|
Pass remove tree div>div.test after previous_sibling
|
||||||
|
Pass insert tree div>div after previous_sibling
|
||||||
|
Pass add the class 'test' to the element in the tree inserted again after previous_sibling
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted again after previous_sibling
|
||||||
|
Pass remove tree div>div after previous_sibling
|
||||||
|
Pass insert element div>div[test_attr] after previous_sibling
|
||||||
|
Pass remove element div>div[test_attr] after previous_sibling
|
||||||
|
Pass insert tree div>div.test after previous_sibling_child
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted after previous_sibling_child
|
||||||
|
Pass add the class 'test' again to the element in the tree inserted after previous_sibling_child
|
||||||
|
Pass remove tree div>div.test after previous_sibling_child
|
||||||
|
Pass insert tree div>div after previous_sibling_child
|
||||||
|
Pass add the class 'test' to the element in the tree inserted again after previous_sibling_child
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted again after previous_sibling_child
|
||||||
|
Pass remove tree div>div after previous_sibling_child
|
||||||
|
Pass insert element div>div[test_attr] after previous_sibling_child
|
||||||
|
Pass remove element div>div[test_attr] after previous_sibling_child
|
||||||
|
Pass insert tree div>div.test after previous_sibling_descendant
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted after previous_sibling_descendant
|
||||||
|
Pass add the class 'test' again to the element in the tree inserted after previous_sibling_descendant
|
||||||
|
Pass remove tree div>div.test after previous_sibling_descendant
|
||||||
|
Pass insert tree div>div after previous_sibling_descendant
|
||||||
|
Pass add the class 'test' to the element in the tree inserted again after previous_sibling_descendant
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted again after previous_sibling_descendant
|
||||||
|
Pass remove tree div>div after previous_sibling_descendant
|
||||||
|
Pass insert element div>div[test_attr] after previous_sibling_descendant
|
||||||
|
Pass remove element div>div[test_attr] after previous_sibling_descendant
|
||||||
|
Pass insert tree div>div.test after subject
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted after subject
|
||||||
|
Pass add the class 'test' again to the element in the tree inserted after subject
|
||||||
|
Pass remove tree div>div.test after subject
|
||||||
|
Pass insert tree div>div after subject
|
||||||
|
Pass add the class 'test' to the element in the tree inserted again after subject
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted again after subject
|
||||||
|
Pass remove tree div>div after subject
|
||||||
|
Pass insert element div>div[test_attr] after subject
|
||||||
|
Pass remove element div>div[test_attr] after subject
|
||||||
|
Pass insert tree div>div.test after next_sibling
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted after next_sibling
|
||||||
|
Pass add the class 'test' again to the element in the tree inserted after next_sibling
|
||||||
|
Pass remove tree div>div.test after next_sibling
|
||||||
|
Pass insert tree div>div after next_sibling
|
||||||
|
Pass add the class 'test' to the element in the tree inserted again after next_sibling
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted again after next_sibling
|
||||||
|
Pass remove tree div>div after next_sibling
|
||||||
|
Pass insert element div>div[test_attr] after next_sibling
|
||||||
|
Pass remove element div>div[test_attr] after next_sibling
|
||||||
|
Pass insert tree div>div.test after next_sibling_child
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted after next_sibling_child
|
||||||
|
Pass add the class 'test' again to the element in the tree inserted after next_sibling_child
|
||||||
|
Pass remove tree div>div.test after next_sibling_child
|
||||||
|
Pass insert tree div>div after next_sibling_child
|
||||||
|
Pass add the class 'test' to the element in the tree inserted again after next_sibling_child
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted again after next_sibling_child
|
||||||
|
Pass remove tree div>div after next_sibling_child
|
||||||
|
Pass insert element div>div[test_attr] after next_sibling_child
|
||||||
|
Pass remove element div>div[test_attr] after next_sibling_child
|
||||||
|
Pass insert tree div>div.test after next_sibling_descendant
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted after next_sibling_descendant
|
||||||
|
Pass add the class 'test' again to the element in the tree inserted after next_sibling_descendant
|
||||||
|
Pass remove tree div>div.test after next_sibling_descendant
|
||||||
|
Pass insert tree div>div after next_sibling_descendant
|
||||||
|
Pass add the class 'test' to the element in the tree inserted again after next_sibling_descendant
|
||||||
|
Pass remove the class 'test' from the element in the tree inserted again after next_sibling_descendant
|
||||||
|
Pass remove tree div>div after next_sibling_descendant
|
||||||
|
Pass insert element div>div[test_attr] after next_sibling_descendant
|
||||||
|
Pass remove element div>div[test_attr] after next_sibling_descendant
|
|
@ -0,0 +1,12 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 2 tests
|
||||||
|
|
||||||
|
2 Pass
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass initial_color: div#subject.color
|
||||||
|
Pass remove descendant: div#subject.color
|
|
@ -0,0 +1,15 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 5 tests
|
||||||
|
|
||||||
|
5 Pass
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass initial color: div#subject.color
|
||||||
|
Pass color after inserting text and div > .descendant: div#subject.color
|
||||||
|
Pass color after wiping #child to remove div > .descendant: div#subject.color
|
||||||
|
Pass color after inserting text and #child > .descendant: div#subject.color
|
||||||
|
Pass color after wiping #child to remove .descendant: div#subject.color
|
|
@ -0,0 +1,38 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 28 tests
|
||||||
|
|
||||||
|
28 Pass
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass subject1: initial color should be rgb(128, 128, 128)
|
||||||
|
Pass subject1: color after #sibling1_1 inserted should be rgb(255, 0, 0)
|
||||||
|
Pass subject2: initial color should be rgb(128, 128, 128)
|
||||||
|
Pass subject2: color after #sibling2_1 removed should be rgb(0, 128, 0)
|
||||||
|
Pass subject3: initial color should be rgb(128, 128, 128)
|
||||||
|
Pass subject3: color after #sibling3_1 inserted should be rgb(0, 0, 255)
|
||||||
|
Pass subject4: initial color should be rgb(128, 128, 128)
|
||||||
|
Pass subject4: color after #sibling4_1 removed should be rgb(255, 255, 0)
|
||||||
|
Pass subject5: initial color should be rgb(255, 0, 0)
|
||||||
|
Pass subject5: color after #sibling5_1 removed should be rgb(128, 128, 128)
|
||||||
|
Pass subject6: initial color should be rgb(0, 128, 0)
|
||||||
|
Pass subject6: color after #sibling6_1 inserted should be rgb(128, 128, 128)
|
||||||
|
Pass subject7: initial color should be rgb(0, 0, 255)
|
||||||
|
Pass subject7: color after #sibling7_1 removed should be rgb(128, 128, 128)
|
||||||
|
Pass subject8: initial color should be rgb(255, 255, 0)
|
||||||
|
Pass subject8: color after #sibling8_1 inserted should be rgb(128, 128, 128)
|
||||||
|
Pass subject9: initial color should be rgb(128, 128, 128)
|
||||||
|
Pass subject9: color after #sibling9_1 inserted should be rgb(255, 0, 0)
|
||||||
|
Pass subject10: initial color should be rgb(128, 128, 128)
|
||||||
|
Pass subject10: color after #sibling10_1 removed should be rgb(0, 128, 0)
|
||||||
|
Pass subject11: initial color should be rgb(128, 128, 128)
|
||||||
|
Pass subject11: color after #sibling11_1 inserted should be rgb(0, 0, 255)
|
||||||
|
Pass subject12: initial color should be rgb(128, 128, 128)
|
||||||
|
Pass subject12: color after #sibling12_1 removed should be rgb(255, 255, 0)
|
||||||
|
Pass subject13: initial color should be rgb(128, 128, 128)
|
||||||
|
Pass subject13: color after #sibling12_1 removed should be rgb(0, 128, 0)
|
||||||
|
Pass subject14: initial color should be rgb(0, 128, 0)
|
||||||
|
Pass subject14: color after #sibling14_2 removed should be rgb(128, 128, 128)
|
|
@ -0,0 +1,81 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 71 tests
|
||||||
|
|
||||||
|
71 Pass
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass initial_color
|
||||||
|
Pass add .test to first_sibling
|
||||||
|
Pass remove .test from first_sibling
|
||||||
|
Pass add .test to second_sibling
|
||||||
|
Pass remove .test from second_sibling
|
||||||
|
Pass add .test to third_sibling
|
||||||
|
Pass remove .test from third_sibling
|
||||||
|
Pass add .test to first_sibling_child
|
||||||
|
Pass remove .test from first_sibling_child
|
||||||
|
Pass add .test to first_sibling_descendant
|
||||||
|
Pass remove .test from first_sibling_descendant
|
||||||
|
Pass add .test to third_sibling_child
|
||||||
|
Pass remove .test from third_sibling_child
|
||||||
|
Pass add .test to third_sibling_descendant
|
||||||
|
Pass remove .test from third_sibling_descendant
|
||||||
|
Pass insert element div.test before first_sibling
|
||||||
|
Pass remove element div.test before first_sibling
|
||||||
|
Pass insert element div.test before second_sibling
|
||||||
|
Pass remove element div.test before second_sibling
|
||||||
|
Pass insert element div.test before third_sibling
|
||||||
|
Pass remove element div.test before third_sibling
|
||||||
|
Pass insert element div.test before first_sibling_child
|
||||||
|
Pass remove element div.test before first_sibling_child
|
||||||
|
Pass insert element div.test before first_sibling_descendant
|
||||||
|
Pass remove element div.test before first_sibling_descendant
|
||||||
|
Pass insert element div.test before third_sibling_child
|
||||||
|
Pass remove element div.test before third_sibling_child
|
||||||
|
Pass insert element div.test before third_sibling_descendant
|
||||||
|
Pass remove element div.test before third_sibling_descendant
|
||||||
|
Pass insert element div.test after first_sibling
|
||||||
|
Pass remove element div.test after first_sibling
|
||||||
|
Pass insert element div.test after second_sibling
|
||||||
|
Pass remove element div.test after second_sibling
|
||||||
|
Pass insert element div.test after third_sibling
|
||||||
|
Pass remove element div.test after third_sibling
|
||||||
|
Pass insert element div.test after first_sibling_child
|
||||||
|
Pass remove element div.test after first_sibling_child
|
||||||
|
Pass insert element div.test after first_sibling_descendant
|
||||||
|
Pass remove element div.test after first_sibling_descendant
|
||||||
|
Pass insert element div.test after third_sibling_child
|
||||||
|
Pass remove element div.test after third_sibling_child
|
||||||
|
Pass insert element div.test after third_sibling_descendant
|
||||||
|
Pass remove element div.test after third_sibling_descendant
|
||||||
|
Pass insert tree div>div.test before first_sibling
|
||||||
|
Pass remove tree div>div.test before first_sibling
|
||||||
|
Pass insert tree div>div.test before second_sibling
|
||||||
|
Pass remove tree div>div.test before second_sibling
|
||||||
|
Pass insert tree div>div.test before third_sibling
|
||||||
|
Pass remove tree div>div.test before third_sibling
|
||||||
|
Pass insert tree div>div.test before first_sibling_child
|
||||||
|
Pass remove tree div>div.test before first_sibling_child
|
||||||
|
Pass insert tree div>div.test before first_sibling_descendant
|
||||||
|
Pass remove tree div>div.test before first_sibling_descendant
|
||||||
|
Pass insert tree div>div.test before third_sibling_child
|
||||||
|
Pass remove tree div>div.test before third_sibling_child
|
||||||
|
Pass insert tree div>div.test before third_sibling_descendant
|
||||||
|
Pass remove tree div>div.test before third_sibling_descendant
|
||||||
|
Pass insert tree div>div.test after first_sibling
|
||||||
|
Pass remove tree div>div.test after first_sibling
|
||||||
|
Pass insert tree div>div.test after second_sibling
|
||||||
|
Pass remove tree div>div.test after second_sibling
|
||||||
|
Pass insert tree div>div.test after third_sibling
|
||||||
|
Pass remove tree div>div.test after third_sibling
|
||||||
|
Pass insert tree div>div.test after first_sibling_child
|
||||||
|
Pass remove tree div>div.test after first_sibling_child
|
||||||
|
Pass insert tree div>div.test after first_sibling_descendant
|
||||||
|
Pass remove tree div>div.test after first_sibling_descendant
|
||||||
|
Pass insert tree div>div.test after third_sibling_child
|
||||||
|
Pass remove tree div>div.test after third_sibling_child
|
||||||
|
Pass insert tree div>div.test after third_sibling_descendant
|
||||||
|
Pass remove tree div>div.test after third_sibling_descendant
|
|
@ -0,0 +1,13 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 3 tests
|
||||||
|
|
||||||
|
3 Pass
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass Initial colors
|
||||||
|
Pass Matches after #blocks_match removed
|
||||||
|
Pass Does not match after #blocks_match added
|
|
@ -0,0 +1,19 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 9 tests
|
||||||
|
|
||||||
|
9 Pass
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass Initial color
|
||||||
|
Pass add test to subject_descendant
|
||||||
|
Pass remove test from subject_descendant
|
||||||
|
Pass add test to sibling_descendant
|
||||||
|
Pass remove test from sibling_descendant
|
||||||
|
Pass add test_inner to subject_child
|
||||||
|
Pass remove test_inner from subject_child
|
||||||
|
Pass add test_inner to sibling_child
|
||||||
|
Pass remove test_inner from sibling_child
|
|
@ -0,0 +1,47 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 37 tests
|
||||||
|
|
||||||
|
37 Pass
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass #anchor1 initially white
|
||||||
|
Pass #anchor1 becomes rgb(0, 0, 255) after adding .ancestor to #grand_parent1
|
||||||
|
Pass #anchor1 becomes rgb(255, 255, 255) after removing .ancestor from #grand_parent1
|
||||||
|
Pass #anchor1 becomes rgb(0, 0, 255) after adding .ancestor to #parent1
|
||||||
|
Pass #anchor1 becomes rgb(255, 255, 255) after removing .ancestor from #parent1
|
||||||
|
Pass #anchor2 initially white
|
||||||
|
Pass #anchor2 becomes rgb(173, 216, 230) after adding .ancestor to #grand_parent2
|
||||||
|
Pass #anchor2 becomes rgb(255, 255, 255) after removing .ancestor from #grand_parent2
|
||||||
|
Pass #anchor2 becomes rgb(173, 216, 230) after adding .ancestor to #parent2
|
||||||
|
Pass #anchor2 becomes rgb(255, 255, 255) after removing .ancestor from #parent2
|
||||||
|
Pass #anchor3 initially white
|
||||||
|
Pass #anchor3 becomes rgb(255, 255, 0) after adding .ancestor_prev to #grand_parent_indirect_prev3
|
||||||
|
Pass #anchor3 becomes rgb(154, 205, 50) after adding .ancestor to #grand_parent3
|
||||||
|
Pass #anchor3 becomes rgb(255, 255, 0) after removing .ancestor from #grand_parent3
|
||||||
|
Pass #anchor3 becomes rgb(255, 255, 255) after removing .ancestor_prev from #grand_parent_indirect_prev3
|
||||||
|
Pass #anchor3 becomes rgb(255, 255, 0) after adding .ancestor_prev to #grand_parent_direct_prev3
|
||||||
|
Pass #anchor3 becomes rgb(255, 255, 255) after removing .ancestor_prev from #grand_parent_direct_prev3
|
||||||
|
Pass #anchor3 becomes rgb(255, 255, 0) after adding .ancestor_prev to #parent_indirect_prev3
|
||||||
|
Pass #anchor3 becomes rgb(154, 205, 50) after adding .ancestor to #parent3
|
||||||
|
Pass #anchor3 becomes rgb(255, 255, 0) after removing .ancestor from #parent3
|
||||||
|
Pass #anchor3 becomes rgb(255, 255, 255) after removing .ancestor_prev from #parent_indirect_prev3
|
||||||
|
Pass #anchor3 becomes rgb(255, 255, 0) after adding .ancestor_prev to #parent_direct_prev3
|
||||||
|
Pass #anchor3 becomes rgb(255, 255, 255) after removing .ancestor_prev from #parent_direct_prev3
|
||||||
|
Pass #anchor3 becomes rgb(255, 255, 0) after adding .ancestor_prev to #anchor_indirect_prev3
|
||||||
|
Pass #anchor3 becomes rgb(255, 255, 255) after removing .ancestor_prev from #anchor_indirect_prev3
|
||||||
|
Pass #anchor3 becomes rgb(255, 255, 0) after adding .ancestor_prev to #anchor_direct_prev3
|
||||||
|
Pass #anchor3 becomes rgb(255, 255, 255) after removing .ancestor_prev from #anchor_direct_prev3
|
||||||
|
Pass #anchor4 initially white
|
||||||
|
Pass #anchor4 becomes rgb(0, 128, 0) after adding .prev to #indirect_prev4
|
||||||
|
Pass #anchor4 becomes rgb(255, 255, 255) after removing .prev from #indirect_prev4
|
||||||
|
Pass #anchor4 becomes rgb(0, 128, 0) after adding .prev to #direct_prev4
|
||||||
|
Pass #anchor4 becomes rgb(255, 255, 255) after removing .prev from #direct_prev4
|
||||||
|
Pass #anchor5 initially white
|
||||||
|
Pass #anchor5 becomes rgb(144, 238, 144) after adding .prev to #indirect_prev5
|
||||||
|
Pass #anchor5 becomes rgb(255, 255, 255) after removing .prev from #indirect_prev5
|
||||||
|
Pass #anchor5 becomes rgb(144, 238, 144) after adding .prev to #direct_prev5
|
||||||
|
Pass #anchor5 becomes rgb(255, 255, 255) after removing .prev from #direct_prev5
|
|
@ -0,0 +1,11 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 1 tests
|
||||||
|
|
||||||
|
1 Fail
|
||||||
|
Details
|
||||||
|
Result Test Name MessageFail CSS Selector Invalidation: :has() with nesting parent containing :hover promise_test: Unhandled rejection with value: object "ReferenceError: 'test_driver' is not defined"
|
|
@ -0,0 +1,31 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 21 tests
|
||||||
|
|
||||||
|
21 Pass
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass Initial color
|
||||||
|
Pass remove .test to subject_child
|
||||||
|
Pass add .test from subject_child
|
||||||
|
Pass remove .test to subject_descendant
|
||||||
|
Pass add .test from subject_descendant
|
||||||
|
Pass insert element div before subject_child
|
||||||
|
Pass remove element div before subject_child
|
||||||
|
Pass insert element div before subject_descendant
|
||||||
|
Pass remove element div before subject_descendant
|
||||||
|
Pass insert element div after subject_child
|
||||||
|
Pass remove element div after subject_child
|
||||||
|
Pass insert element div after subject_descendant
|
||||||
|
Pass remove element div after subject_descendant
|
||||||
|
Pass insert tree div>div before subject_child
|
||||||
|
Pass remove tree div>div before subject_child
|
||||||
|
Pass insert tree div>div before subject_descendant
|
||||||
|
Pass remove tree div>div before subject_descendant
|
||||||
|
Pass insert tree div.test after subject_child
|
||||||
|
Pass remove tree div.test after subject_child
|
||||||
|
Pass insert tree div.test after subject_descendant
|
||||||
|
Pass remove tree div.test after subject_descendant
|
|
@ -0,0 +1,15 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 5 tests
|
||||||
|
|
||||||
|
5 Pass
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass Initially red
|
||||||
|
Pass :nth-child() no longer matching after removal
|
||||||
|
Pass :nth-last-child() no longer matching after removal
|
||||||
|
Pass :nth-child() in non-subject no longer matching after removal
|
||||||
|
Pass :nth-last-child() in non-subject no longer matching after removal
|
|
@ -0,0 +1,52 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 41 tests
|
||||||
|
|
||||||
|
22 Pass
|
||||||
|
19 Fail
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass Before set checked on checkbox, testing subject
|
||||||
|
Fail Set checked on checkbox, testing subject assert_equals: expected "rgb(255, 0, 0)" but got "rgb(128, 128, 128)"
|
||||||
|
Pass Unset checked on checkbox, testing subject
|
||||||
|
Fail Set select on option assert_equals: expected "rgb(255, 0, 0)" but got "rgb(128, 128, 128)"
|
||||||
|
Pass Reset select
|
||||||
|
Pass Before set disabled on checkbox, testing subject
|
||||||
|
Pass Set disabled on checkbox, testing subject
|
||||||
|
Fail Unset disabled on checkbox, testing subject assert_equals: expected "rgb(128, 128, 128)" but got "rgb(255, 0, 0)"
|
||||||
|
Pass Before set disabled on checkbox, testing subject3
|
||||||
|
Pass Set disabled on checkbox, testing subject3
|
||||||
|
Pass Unset disabled on checkbox, testing subject3
|
||||||
|
Fail Before set disabled on option, testing subject assert_equals: expected "rgb(128, 128, 128)" but got "rgb(255, 0, 0)"
|
||||||
|
Pass Set disabled on option, testing subject
|
||||||
|
Fail Unset disabled on option, testing subject assert_equals: expected "rgb(128, 128, 128)" but got "rgb(255, 0, 0)"
|
||||||
|
Pass Before set disabled on option, testing subject3
|
||||||
|
Pass Set disabled on option, testing subject3
|
||||||
|
Pass Unset disabled on option, testing subject3
|
||||||
|
Fail Before set disabled on optgroup, testing subject assert_equals: expected "rgb(128, 128, 128)" but got "rgb(255, 0, 0)"
|
||||||
|
Pass Set disabled on optgroup, testing subject
|
||||||
|
Fail Unset disabled on optgroup, testing subject assert_equals: expected "rgb(128, 128, 128)" but got "rgb(255, 0, 0)"
|
||||||
|
Fail Before set disabled on optgroup, testing subject2 assert_equals: expected "rgb(128, 128, 128)" but got "rgb(255, 255, 0)"
|
||||||
|
Pass Set disabled on optgroup, testing subject2
|
||||||
|
Fail Unset disabled on optgroup, testing subject2 assert_equals: expected "rgb(128, 128, 128)" but got "rgb(255, 255, 0)"
|
||||||
|
Pass Before set disabled on optgroup, testing subject3
|
||||||
|
Pass Set disabled on optgroup, testing subject3
|
||||||
|
Pass Unset disabled on optgroup, testing subject3
|
||||||
|
Fail Before set disabled on optgroup, testing subject4 assert_equals: expected "rgb(128, 128, 128)" but got "rgb(255, 255, 0)"
|
||||||
|
Pass Set disabled on optgroup, testing subject4
|
||||||
|
Fail Unset disabled on optgroup, testing subject4 assert_equals: expected "rgb(128, 128, 128)" but got "rgb(255, 255, 0)"
|
||||||
|
Fail Before setting value of text_input, testing subject assert_equals: expected "rgb(128, 128, 128)" but got "rgb(255, 0, 0)"
|
||||||
|
Fail Set value of text_input, testing subject assert_equals: expected "rgb(255, 255, 0)" but got "rgb(255, 0, 0)"
|
||||||
|
Fail Clear value of text_input, testing subject assert_equals: expected "rgb(128, 128, 128)" but got "rgb(255, 0, 0)"
|
||||||
|
Fail Before setting value of text_input, testing subject2 assert_equals: expected "rgb(128, 128, 128)" but got "rgb(255, 255, 0)"
|
||||||
|
Pass Set value of text_input, testing subject2
|
||||||
|
Fail Clear value of text_input, testing subject2 assert_equals: expected "rgb(128, 128, 128)" but got "rgb(255, 255, 0)"
|
||||||
|
Pass Before setting value of text_input, testing subject3
|
||||||
|
Fail Set value of text_input, testing subject3 assert_equals: expected "rgb(255, 255, 0)" but got "rgb(128, 128, 128)"
|
||||||
|
Pass Clear value of text_input, testing subject3
|
||||||
|
Fail Before setting value of text_input, testing subject4 assert_equals: expected "rgb(128, 128, 128)" but got "rgb(255, 255, 0)"
|
||||||
|
Pass Set value of text_input, testing subject4
|
||||||
|
Fail Clear value of text_input, testing subject4 assert_equals: expected "rgb(128, 128, 128)" but got "rgb(255, 255, 0)"
|
|
@ -0,0 +1,69 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>:has pseudo class behavior with explicit ':scope' in its argument</title>
|
||||||
|
<link rel="author" title="Byungwoo Lee" href="mailto:blee@igalia.com">
|
||||||
|
<link rel="help" href="https://drafts.csswg.org/selectors/#relational">
|
||||||
|
<script src="../../resources/testharness.js"></script>
|
||||||
|
<script src="../../resources/testharnessreport.js"></script>
|
||||||
|
|
||||||
|
<main>
|
||||||
|
<div id=d01 class="a">
|
||||||
|
<div id=scope1 class="b">
|
||||||
|
<div id=d02 class="c">
|
||||||
|
<div id=d03 class="c">
|
||||||
|
<div id=d04 class="d"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id=d05 class="e"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id=d06>
|
||||||
|
<div id=scope2 class="b">
|
||||||
|
<div id=d07 class="c">
|
||||||
|
<div id=d08 class="c">
|
||||||
|
<div id=d09></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function formatElements(elements) {
|
||||||
|
return elements.map(e => e.id).sort().join();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that |selector| returns the given elements in the given scope element
|
||||||
|
function test_selector_all(scope, selector, expected) {
|
||||||
|
test(function() {
|
||||||
|
let actual = Array.from(scope.querySelectorAll(selector));
|
||||||
|
assert_equals(formatElements(actual), formatElements(expected));
|
||||||
|
}, `${selector} matches expected elements on ${scope.id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that |selector1| and |selector2| returns same elements in the given scope element
|
||||||
|
function compare_selector_all(scope, selector1, selector2) {
|
||||||
|
test(function() {
|
||||||
|
let result1 = Array.from(scope.querySelectorAll(selector1));
|
||||||
|
let result2 = Array.from(scope.querySelectorAll(selector2));
|
||||||
|
assert_equals(formatElements(result1), formatElements(result2));
|
||||||
|
}, `${selector1} and ${selector2} returns same elements on ${scope.id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// descendants of a scope element cannot have the scope element as its descendant
|
||||||
|
test_selector_all(scope1, ':has(:scope)', []);
|
||||||
|
test_selector_all(scope1, ':has(:scope .c)', []);
|
||||||
|
test_selector_all(scope1, ':has(.a :scope)', []);
|
||||||
|
|
||||||
|
// there can be more simple and efficient alternative for a ':scope' in ':has'
|
||||||
|
test_selector_all(scope1, '.a:has(:scope) .c', [d02, d03]);
|
||||||
|
compare_selector_all(scope1, '.a:has(:scope) .c', ':is(.a :scope .c)');
|
||||||
|
test_selector_all(scope2, '.a:has(:scope) .c', []);
|
||||||
|
compare_selector_all(scope2, '.a:has(:scope) .c', ':is(.a :scope .c)');
|
||||||
|
test_selector_all(scope1, '.c:has(:is(:scope .d))', [d02, d03]);
|
||||||
|
compare_selector_all(scope1, '.c:has(:is(:scope .d))', ':scope .c:has(.d)');
|
||||||
|
compare_selector_all(scope1, '.c:has(:is(:scope .d))', '.c:has(.d)');
|
||||||
|
test_selector_all(scope2, '.c:has(:is(:scope .d))', []);
|
||||||
|
compare_selector_all(scope2, '.c:has(:is(:scope .d))', ':scope .c:has(.d)');
|
||||||
|
compare_selector_all(scope2, '.c:has(:is(:scope .d))', '.c:has(.d)');
|
||||||
|
</script>
|
|
@ -0,0 +1,81 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Basic matching behavior of :has pseudo class</title>
|
||||||
|
<link rel="author" title="Byungwoo Lee" href="mailto:blee@igalia.com">
|
||||||
|
<script src="../../resources/testharness.js"></script>
|
||||||
|
<script src="../../resources/testharnessreport.js"></script>
|
||||||
|
<link rel="help" href="https://drafts.csswg.org/selectors/#relational">
|
||||||
|
|
||||||
|
<main id=main>
|
||||||
|
<div id=a class="ancestor">
|
||||||
|
<div id=b class="parent ancestor">
|
||||||
|
<div id=c class="sibling descendant">
|
||||||
|
<div id=d class="descendant"></div>
|
||||||
|
</div>
|
||||||
|
<div id=e class="target descendant"></div>
|
||||||
|
</div>
|
||||||
|
<div id=f class="parent ancestor">
|
||||||
|
<div id=g class="target descendant"></div>
|
||||||
|
</div>
|
||||||
|
<div id=h class="parent ancestor">
|
||||||
|
<div id=i class="target descendant"></div>
|
||||||
|
<div id=j class="sibling descendant">
|
||||||
|
<div id=k class="descendant"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function formatElements(elements) {
|
||||||
|
return elements.map(e => e.id).sort().join();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that |selector| returns the given elements in #main.
|
||||||
|
function test_selector_all(selector, expected) {
|
||||||
|
test(function() {
|
||||||
|
let actual = Array.from(main.querySelectorAll(selector));
|
||||||
|
assert_equals(formatElements(actual), formatElements(expected));
|
||||||
|
}, `${selector} matches expected elements`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that |selector| returns the given element in #main.
|
||||||
|
function test_selector(selector, expected) {
|
||||||
|
test(function() {
|
||||||
|
assert_equals(main.querySelector(selector), expected);
|
||||||
|
}, `${selector} matches expected element`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that |selector| returns the given closest element.
|
||||||
|
function test_closest(node, selector, expected) {
|
||||||
|
test(function() {
|
||||||
|
assert_equals(node.closest(selector), expected);
|
||||||
|
}, `closest(${selector}) returns expected element`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that |selector| returns matching status.
|
||||||
|
function test_matches(node, selector, expected) {
|
||||||
|
test(function() {
|
||||||
|
assert_equals(node.matches(selector), expected);
|
||||||
|
}, `${selector} matches expectedly`);
|
||||||
|
}
|
||||||
|
|
||||||
|
test_selector_all(':has(#a)', []);
|
||||||
|
test_selector_all(':has(.ancestor)', [a]);
|
||||||
|
test_selector_all(':has(.target)', [a, b, f, h]);
|
||||||
|
test_selector_all(':has(.descendant)', [a, b, c, f, h, j]);
|
||||||
|
test_selector_all('.parent:has(.target)', [b, f, h]);
|
||||||
|
test_selector_all(':has(.sibling ~ .target)', [a, b]);
|
||||||
|
test_selector_all('.parent:has(.sibling ~ .target)', [b]);
|
||||||
|
test_selector_all(':has(:is(.target ~ .sibling .descendant))', [a, h, j]);
|
||||||
|
test_selector_all('.parent:has(:is(.target ~ .sibling .descendant))', [h]);
|
||||||
|
test_selector_all('.sibling:has(.descendant) ~ .target', [e]);
|
||||||
|
test_selector_all(':has(> .parent)', [a]);
|
||||||
|
test_selector_all(':has(> .target)', [b, f, h]);
|
||||||
|
test_selector_all(':has(> .parent, > .target)', [a, b, f, h]);
|
||||||
|
test_selector_all(':has(+ #h)', [f]);
|
||||||
|
test_selector_all('.parent:has(~ #h)', [b, f]);
|
||||||
|
test_selector('.sibling:has(.descendant)', c);
|
||||||
|
test_closest(k, '.ancestor:has(.descendant)', h);
|
||||||
|
test_matches(h, ':has(.target ~ .sibling .descendant)', true);
|
||||||
|
</script>
|
|
@ -0,0 +1,37 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Matches :has pseudo class to uninserted elements</title>
|
||||||
|
<link rel="author" title="Byungwoo Lee" href="mailto:blee@igalia.com">
|
||||||
|
<script src="../../resources/testharness.js"></script>
|
||||||
|
<script src="../../resources/testharnessreport.js"></script>
|
||||||
|
<link rel="help" href="https://drafts.csswg.org/selectors/#relational">
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// Test that |selector| returns matching status.
|
||||||
|
function test_matches(node, selector, expected) {
|
||||||
|
test(function() {
|
||||||
|
assert_equals(node.matches(selector), expected);
|
||||||
|
}, `${selector} matches expectedly`);
|
||||||
|
}
|
||||||
|
|
||||||
|
subject = document.createElement('subject');
|
||||||
|
|
||||||
|
subject.innerHTML = '<child></child>';
|
||||||
|
test_matches(subject, ':has(child)', true);
|
||||||
|
test_matches(subject, ':has(> child)', true);
|
||||||
|
|
||||||
|
subject.innerHTML = '<child><descendant></descendant></child>';
|
||||||
|
test_matches(subject, ':has(descendant)', true);
|
||||||
|
test_matches(subject, ':has(> descendant)', false);
|
||||||
|
|
||||||
|
subject.innerHTML = '<child></child><direct_sibling></direct_sibling><indirect_sibling></indirect_sibling>';
|
||||||
|
test_matches(subject.firstChild, ':has(~ direct_sibling)', true);
|
||||||
|
test_matches(subject.firstChild, ':has(+ direct_sibling)', true);
|
||||||
|
test_matches(subject.firstChild, ':has(~ indirect_sibling)', true);
|
||||||
|
test_matches(subject.firstChild, ':has(+ indirect_sibling)', false);
|
||||||
|
|
||||||
|
test_matches(subject, ':has(*)', true);
|
||||||
|
test_matches(subject, ':has(> *)', true);
|
||||||
|
test_matches(subject, ':has(~ *)', false);
|
||||||
|
test_matches(subject, ':has(+ *)', false);
|
||||||
|
</script>
|
|
@ -0,0 +1,184 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>:has pseudo class behavior with various relative arguments</title>
|
||||||
|
<link rel="author" title="Byungwoo Lee" href="mailto:blee@igalia.com">
|
||||||
|
<script src="../../resources/testharness.js"></script>
|
||||||
|
<script src="../../resources/testharnessreport.js"></script>
|
||||||
|
<link rel="help" href="https://drafts.csswg.org/selectors/#relational">
|
||||||
|
|
||||||
|
<main id=main>
|
||||||
|
<div id=d01>
|
||||||
|
<div id=d02 class="x">
|
||||||
|
<div id=d03 class="a"></div>
|
||||||
|
<div id=d04></div>
|
||||||
|
<div id=d05 class="b"></div>
|
||||||
|
</div>
|
||||||
|
<div id=d06 class="x">
|
||||||
|
<div id=d07 class="x">
|
||||||
|
<div id=d08 class="a"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id=d09 class="x">
|
||||||
|
<div id=d10 class="a">
|
||||||
|
<div id=d11 class="b"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id=d12 class="x">
|
||||||
|
<div id=d13 class="a">
|
||||||
|
<div id=d14>
|
||||||
|
<div id=d15 class="b"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id=d16 class="b"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id=d17>
|
||||||
|
<div id=d18 class="x"></div>
|
||||||
|
<div id=d19 class="x"></div>
|
||||||
|
<div id=d20 class="a"></div>
|
||||||
|
<div id=d21 class="x"></div>
|
||||||
|
<div id=d22 class="a">
|
||||||
|
<div id=d23 class="b"></div>
|
||||||
|
</div>
|
||||||
|
<div id=d24 class="x"></div>
|
||||||
|
<div id=d25 class="a">
|
||||||
|
<div id=d26>
|
||||||
|
<div id=d27 class="b"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id=d28 class="x"></div>
|
||||||
|
<div id=d29 class="a"></div>
|
||||||
|
<div id=d30 class="b">
|
||||||
|
<div id=d31 class="c"></div>
|
||||||
|
</div>
|
||||||
|
<div id=d32 class="x"></div>
|
||||||
|
<div id=d33 class="a"></div>
|
||||||
|
<div id=d34 class="b">
|
||||||
|
<div id=d35>
|
||||||
|
<div id=d36 class="c"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id=d37 class="x"></div>
|
||||||
|
<div id=d38 class="a"></div>
|
||||||
|
<div id=d39 class="b"></div>
|
||||||
|
<div id=d40 class="x"></div>
|
||||||
|
<div id=d41 class="a"></div>
|
||||||
|
<div id=d42></div>
|
||||||
|
<div id=d43 class="b">
|
||||||
|
<div id=d44 class="x">
|
||||||
|
<div id=d45 class="c"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id=d46 class="x"></div>
|
||||||
|
<div id=d47 class="a">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div id=d48 class="x">
|
||||||
|
<div id=d49 class="x">
|
||||||
|
<div id=d50 class="x d">
|
||||||
|
<div id=d51 class="x d">
|
||||||
|
<div id=d52 class="x">
|
||||||
|
<div id=d53 class="x e">
|
||||||
|
<div id=d54 class="f"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id=d55 class="x"></div>
|
||||||
|
<div id=d56 class="x d"></div>
|
||||||
|
<div id=d57 class="x d"></div>
|
||||||
|
<div id=d58 class="x"></div>
|
||||||
|
<div id=d59 class="x e"></div>
|
||||||
|
<div id=d60 class="f"></div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div id=d61 class="x"></div>
|
||||||
|
<div id=d62 class="x y"></div>
|
||||||
|
<div id=d63 class="x y">
|
||||||
|
<div id=d64 class="y g">
|
||||||
|
<div id=d65 class="y">
|
||||||
|
<div id=d66 class="y h">
|
||||||
|
<div id=d67 class="i"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id=d68 class="x y">
|
||||||
|
<div id=d69 class="x"></div>
|
||||||
|
<div id=d70 class="x"></div>
|
||||||
|
<div id=d71 class="x y">
|
||||||
|
<div id=d72 class="y g">
|
||||||
|
<div id=d73 class="y">
|
||||||
|
<div id=d74 class="y h">
|
||||||
|
<div id=d75 class="i"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id=d76 class="x"></div>
|
||||||
|
<div id=d77 class="j"><div id=d78><div id=d79></div></div></div>
|
||||||
|
</div>
|
||||||
|
<div id=d80 class="j"></div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function formatElements(elements) {
|
||||||
|
return elements.map(e => e.id).sort().join();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that |selector| returns the given elements in #main.
|
||||||
|
function test_selector_all(selector, expected) {
|
||||||
|
test(function() {
|
||||||
|
let actual = Array.from(main.querySelectorAll(selector));
|
||||||
|
assert_equals(formatElements(actual), formatElements(expected));
|
||||||
|
}, `${selector} matches expected elements`);
|
||||||
|
}
|
||||||
|
|
||||||
|
test_selector_all('.x:has(.a)', [d02, d06, d07, d09, d12]);
|
||||||
|
test_selector_all('.x:has(.a > .b)', [d09]);
|
||||||
|
test_selector_all('.x:has(.a .b)', [d09, d12]);
|
||||||
|
test_selector_all('.x:has(.a + .b)', [d12]);
|
||||||
|
test_selector_all('.x:has(.a ~ .b)', [d02, d12]);
|
||||||
|
|
||||||
|
test_selector_all('.x:has(> .a)', [d02, d07, d09, d12]);
|
||||||
|
test_selector_all('.x:has(> .a > .b)', [d09]);
|
||||||
|
test_selector_all('.x:has(> .a .b)', [d09, d12]);
|
||||||
|
test_selector_all('.x:has(> .a + .b)', [d12]);
|
||||||
|
test_selector_all('.x:has(> .a ~ .b)', [d02, d12]);
|
||||||
|
|
||||||
|
test_selector_all('.x:has(+ .a)', [d19, d21, d24, d28, d32, d37, d40, d46]);
|
||||||
|
test_selector_all('.x:has(+ .a > .b)', [d21]);
|
||||||
|
test_selector_all('.x:has(+ .a .b)', [d21, d24]);
|
||||||
|
test_selector_all('.x:has(+ .a + .b)', [d28, d32, d37]);
|
||||||
|
test_selector_all('.x:has(+ .a ~ .b)', [d19, d21, d24, d28, d32, d37, d40]);
|
||||||
|
|
||||||
|
test_selector_all('.x:has(~ .a)', [d18, d19, d21, d24, d28, d32, d37, d40, d46]);
|
||||||
|
test_selector_all('.x:has(~ .a > .b)', [d18, d19, d21]);
|
||||||
|
test_selector_all('.x:has(~ .a .b)', [d18, d19, d21, d24]);
|
||||||
|
test_selector_all('.x:has(~ .a + .b)', [d18, d19, d21, d24, d28, d32, d37]);
|
||||||
|
test_selector_all('.x:has(~ .a + .b > .c)', [d18, d19, d21, d24, d28]);
|
||||||
|
test_selector_all('.x:has(~ .a + .b .c)', [d18, d19, d21, d24, d28, d32]);
|
||||||
|
|
||||||
|
test_selector_all('.x:has(.d .e)', [d48, d49, d50]);
|
||||||
|
test_selector_all('.x:has(.d .e) .f', [d54]);
|
||||||
|
test_selector_all('.x:has(> .d)', [d49, d50]);
|
||||||
|
test_selector_all('.x:has(> .d) .f', [d54]);
|
||||||
|
test_selector_all('.x:has(~ .d ~ .e)', [d48, d55, d56]);
|
||||||
|
test_selector_all('.x:has(~ .d ~ .e) ~ .f', [d60]);
|
||||||
|
test_selector_all('.x:has(+ .d ~ .e)', [d55, d56]);
|
||||||
|
test_selector_all('.x:has(+ .d ~ .e) ~ .f', [d60]);
|
||||||
|
|
||||||
|
test_selector_all('.y:has(> .g .h)', [d63, d71])
|
||||||
|
test_selector_all('.y:has(.g .h)', [d63, d68, d71])
|
||||||
|
test_selector_all('.y:has(> .g .h) .i', [d67, d75])
|
||||||
|
test_selector_all('.y:has(.g .h) .i', [d67, d75])
|
||||||
|
|
||||||
|
test_selector_all('.d .x:has(.e)', [d51, d52])
|
||||||
|
|
||||||
|
test_selector_all('.d ~ .x:has(~ .e)', [d57, d58])
|
||||||
|
|
||||||
|
</script>
|
|
@ -0,0 +1,14 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<title>CSS Selectors Test: Chrome crash issue 1470477</title>
|
||||||
|
<link rel="help" href="https://crbug.com/1470477">
|
||||||
|
<style>
|
||||||
|
:has(> :where(label:first-child + [a="a"]:only-of-type,
|
||||||
|
[a="a"]:only-of-type + label:last-child)) label:last-child {
|
||||||
|
margin-inline: 1em;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<p>PASS if this tests does not crash</p>
|
||||||
|
<script>
|
||||||
|
if (window.internals)
|
||||||
|
window.internals.signalTextTestIsDone("PASS");
|
||||||
|
</script>
|
|
@ -0,0 +1,50 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<title>Specificity for complex :has selectors</title>
|
||||||
|
<script src="../../resources/testharness.js"></script>
|
||||||
|
<script src="../../resources/testharnessreport.js"></script>
|
||||||
|
<link rel="help" href="https://drafts.csswg.org/selectors/#specificity-rules">
|
||||||
|
<style>
|
||||||
|
main :has(#foo) { --t0:PASS; }
|
||||||
|
main :has(.foo) { --t0:FAIL; }
|
||||||
|
|
||||||
|
main :has(span#foo) { --t1:PASS; }
|
||||||
|
main :has(#foo) { --t1:FAIL; }
|
||||||
|
|
||||||
|
main :has(.bar, #foo) { --t2:FAIL; }
|
||||||
|
main :has(#foo, .bar) { --t2:PASS; }
|
||||||
|
|
||||||
|
main :has(.bar, #foo) { --t3:PASS; }
|
||||||
|
main :has(.foo, .bar) { --t3:FAIL; }
|
||||||
|
|
||||||
|
main :has(span + span) { --t4:PASS; }
|
||||||
|
main :has(span) { --t4:FAIL; }
|
||||||
|
|
||||||
|
main :has(span, li, #foo) { --t5:PASS; }
|
||||||
|
main :has(span, li, p) { --t5:FAIL; }
|
||||||
|
|
||||||
|
main div:has(.foo) { --t6:FAIL; }
|
||||||
|
main div.baz { --t6:PASS; }
|
||||||
|
|
||||||
|
main div.baz { --t7:FAIL; }
|
||||||
|
main div:has(.foo) { --t7:PASS; }
|
||||||
|
</style>
|
||||||
|
<main id=main>
|
||||||
|
<div id=div class=baz><p><span id=foo class=foo></span><span class=bar></span><li></li></p></div>
|
||||||
|
</main>
|
||||||
|
<script>
|
||||||
|
function test_value(name, description) {
|
||||||
|
test(function() {
|
||||||
|
let actual = getComputedStyle(div).getPropertyValue(name);
|
||||||
|
assert_equals(actual, 'PASS');
|
||||||
|
}, description);
|
||||||
|
}
|
||||||
|
|
||||||
|
test_value('--t0', ':has(#foo) wins over :has(.foo)');
|
||||||
|
test_value('--t1', ':has(span#foo) wins over :has(#foo)');
|
||||||
|
test_value('--t2', ':has(.bar, #foo) has same specificity as :has(#foo, .bar)');
|
||||||
|
test_value('--t3', ':has(.bar, #foo) wins over :has(.foo, .bar)');
|
||||||
|
test_value('--t4', ':has(span + span) wins over :has(span)');
|
||||||
|
test_value('--t5', ':has(span, li, p) wins over :has(span, lo, p)');
|
||||||
|
test_value('--t6', 'latter .baz wins over :has(.foo)');
|
||||||
|
test_value('--t7', 'latter :has(.foo) wins over .baz');
|
||||||
|
</script>
|
|
@ -0,0 +1,105 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>:has() invalidation with nesting where the selector is shared</title>
|
||||||
|
<link rel="author" title="David Shin" href="mailto:dshin@mozilla.com">
|
||||||
|
<script src="../../../resources/testharness.js"></script>
|
||||||
|
<script src="../../../resources/testharnessreport.js"></script>
|
||||||
|
<link rel="help" href="https://drafts.csswg.org/selectors/#relational">
|
||||||
|
<style>
|
||||||
|
div, main { color: grey }
|
||||||
|
#outer1:has(.test) {
|
||||||
|
& #subject1_1 {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
& + #subject1_2 {
|
||||||
|
color: orangered;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#outer2:has(.test) {
|
||||||
|
& .ancestor {
|
||||||
|
& #subject2_1 {
|
||||||
|
color: green;
|
||||||
|
}
|
||||||
|
& + #subject2_2 {
|
||||||
|
color: lightgreen;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#outer3:is(:has(.test) .outer) {
|
||||||
|
& #subject3_1 {
|
||||||
|
color: blue;
|
||||||
|
}
|
||||||
|
& + #subject3_2 {
|
||||||
|
color: skyblue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<main id="main">
|
||||||
|
<div>
|
||||||
|
<div id="outer1">
|
||||||
|
<div id="trigger1"></div>
|
||||||
|
<div id="subject1_1"></div>
|
||||||
|
</div>
|
||||||
|
<div id="subject1_2"></div>
|
||||||
|
</div>
|
||||||
|
<div id="outer2">
|
||||||
|
<div id="trigger2"></div>
|
||||||
|
<div class="ancestor">
|
||||||
|
<div id="subject2_1"></div>
|
||||||
|
</div>
|
||||||
|
<div id="subject2_2"></div>
|
||||||
|
</div>
|
||||||
|
<div id="trigger3">
|
||||||
|
<div id="outer3" class="outer">
|
||||||
|
<div id="subject3_1"></div>
|
||||||
|
</div>
|
||||||
|
<div id="subject3_2"></div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
<script>
|
||||||
|
const grey = 'rgb(128, 128, 128)';
|
||||||
|
const red = 'rgb(255, 0, 0)';
|
||||||
|
const orangered = 'rgb(255, 69, 0)';
|
||||||
|
const green = 'rgb(0, 128, 0)';
|
||||||
|
const lightgreen = 'rgb(144, 238, 144)';
|
||||||
|
const blue = 'rgb(0, 0, 255)';
|
||||||
|
const skyblue = 'rgb(135, 206, 235)';
|
||||||
|
|
||||||
|
const colors = {
|
||||||
|
red: {
|
||||||
|
descendant: red,
|
||||||
|
sibling: orangered,
|
||||||
|
},
|
||||||
|
green: {
|
||||||
|
descendant: green,
|
||||||
|
sibling: lightgreen,
|
||||||
|
},
|
||||||
|
blue: {
|
||||||
|
descendant: blue,
|
||||||
|
sibling: skyblue,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
function testColor(testName, element, color) {
|
||||||
|
test(function() {
|
||||||
|
assert_equals(getComputedStyle(element).color, color);
|
||||||
|
}, testName);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testClassChange(trigger, targetDescendant, targetSibling, expected)
|
||||||
|
{
|
||||||
|
trigger.classList.add('test');
|
||||||
|
testColor(`add .test to ${trigger.id} - check ${targetDescendant.id}`, targetDescendant, colors[expected].descendant);
|
||||||
|
testColor(`add .test to ${trigger.id} - check ${targetSibling.id}`, targetSibling, colors[expected].sibling);
|
||||||
|
trigger.classList.remove('test');
|
||||||
|
testColor(`remove .test from ${trigger.id} - check ${targetDescendant.id}`, targetDescendant, grey);
|
||||||
|
testColor(`remove .test from ${trigger.id} - check ${targetSibling.id}`, targetSibling, grey);
|
||||||
|
}
|
||||||
|
|
||||||
|
testClassChange(trigger1, subject1_1, subject1_2, 'red');
|
||||||
|
testClassChange(trigger2, subject2_1, subject2_2, 'green');
|
||||||
|
testClassChange(trigger3, subject3_1, subject3_2, 'blue');
|
||||||
|
|
||||||
|
</script>
|
|
@ -0,0 +1,312 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>CSS Selector Invalidation: :has() in adjacent position</title>
|
||||||
|
<link rel="author" title="Antti Koivisto" href="mailto:antti@apple.com">
|
||||||
|
<script src="../../../resources/testharness.js"></script>
|
||||||
|
<script src="../../../resources/testharnessreport.js"></script>
|
||||||
|
<link rel="help" href="https://drafts.csswg.org/selectors/#relational">
|
||||||
|
<style>
|
||||||
|
div, main { color: grey }
|
||||||
|
div:has(.test) + #subject { color: red }
|
||||||
|
div:has([test_attr]) + #subject { color: orangered }
|
||||||
|
div:has(> .test) + #subject { color: green }
|
||||||
|
div:has(> [test_attr]) + #subject { color: lightgreen }
|
||||||
|
div:has(~ .test) + #subject { color: yellow }
|
||||||
|
div:has(~ [test_attr]) + #subject { color: ivory }
|
||||||
|
div:has(+ .test) + #subject { color: blue }
|
||||||
|
div:has(+ [test_attr]) + #subject { color: skyblue }
|
||||||
|
div:has(~ div .test) + #subject { color: purple }
|
||||||
|
div:has(~ div [test_attr]) + #subject { color: violet }
|
||||||
|
div:has(+ div .test) + #subject { color: pink }
|
||||||
|
div:has(+ div [test_attr]) + #subject { color: lightpink }
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<main id=main>
|
||||||
|
<div id=previous_sibling>
|
||||||
|
<div id=previous_sibling_child>
|
||||||
|
<div id=previous_sibling_descendant></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id=subject></div>
|
||||||
|
<div id=next_sibling>
|
||||||
|
<div id=next_sibling_child>
|
||||||
|
<div id=next_sibling_descendant></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const grey = 'rgb(128, 128, 128)';
|
||||||
|
const red = 'rgb(255, 0, 0)';
|
||||||
|
const orangered = 'rgb(255, 69, 0)';
|
||||||
|
const green = 'rgb(0, 128, 0)';
|
||||||
|
const lightgreen = 'rgb(144, 238, 144)';
|
||||||
|
const blue = 'rgb(0, 0, 255)';
|
||||||
|
const skyblue = 'rgb(135, 206, 235)';
|
||||||
|
const yellow = 'rgb(255, 255, 0)';
|
||||||
|
const ivory = 'rgb(255, 255, 240)';
|
||||||
|
const purple = 'rgb(128, 0, 128)';
|
||||||
|
const violet = 'rgb(238, 130, 238)';
|
||||||
|
const pink = 'rgb(255, 192, 203)';
|
||||||
|
const lightpink = 'rgb(255, 182, 193)';
|
||||||
|
const colors = {
|
||||||
|
grey: {
|
||||||
|
classTest: grey,
|
||||||
|
attributeTest: grey,
|
||||||
|
},
|
||||||
|
red: {
|
||||||
|
classTest: red,
|
||||||
|
attributeTest: orangered,
|
||||||
|
},
|
||||||
|
green: {
|
||||||
|
classTest: green,
|
||||||
|
attributeTest: lightgreen,
|
||||||
|
},
|
||||||
|
blue: {
|
||||||
|
classTest: blue,
|
||||||
|
attributeTest: skyblue,
|
||||||
|
},
|
||||||
|
yellow: {
|
||||||
|
classTest: yellow,
|
||||||
|
attributeTest: ivory,
|
||||||
|
},
|
||||||
|
purple: {
|
||||||
|
classTest: purple,
|
||||||
|
attributeTest: violet,
|
||||||
|
},
|
||||||
|
pink: {
|
||||||
|
classTest: pink,
|
||||||
|
attributeTest: lightpink,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
function testColor(test_name, color) {
|
||||||
|
test(function() {
|
||||||
|
assert_equals(getComputedStyle(subject).color, color);
|
||||||
|
}, test_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testClassChange(element, expectedColorName)
|
||||||
|
{
|
||||||
|
const expectedColorForClassTest = colors[expectedColorName].classTest;
|
||||||
|
element.classList.add('test');
|
||||||
|
testColor(`add .test to ${element.id}`, expectedColorForClassTest);
|
||||||
|
element.classList.remove('test');
|
||||||
|
testColor(`remove .test from ${element.id}`, grey);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testElementInsertionBefore(beforeElement, expectedColorName)
|
||||||
|
{
|
||||||
|
const expectedColorForClassTest = colors[expectedColorName].classTest;
|
||||||
|
const expectedColorForAttributeTest = colors[expectedColorName].attributeTest;
|
||||||
|
const newElement = document.createElement('div');
|
||||||
|
newElement.classList.add('test')
|
||||||
|
|
||||||
|
beforeElement.before(newElement);
|
||||||
|
testColor(`insert element div.test before ${beforeElement.id}`, expectedColorForClassTest);
|
||||||
|
|
||||||
|
newElement.classList.remove('test');
|
||||||
|
testColor(`remove the class 'test' from the element inserted before ${beforeElement.id}`, grey);
|
||||||
|
|
||||||
|
newElement.classList.add('test');
|
||||||
|
testColor(`add the class 'test' again to the element inserted before ${beforeElement.id}`, expectedColorForClassTest);
|
||||||
|
|
||||||
|
newElement.remove();
|
||||||
|
testColor(`remove element div.test before ${beforeElement.id}`, grey);
|
||||||
|
|
||||||
|
newElement.classList.remove('test');
|
||||||
|
|
||||||
|
beforeElement.before(newElement);
|
||||||
|
testColor(`insert element div before ${beforeElement.id}`, grey);
|
||||||
|
|
||||||
|
newElement.classList.add('test');
|
||||||
|
testColor(`add the class 'test' to the element inserted again before ${beforeElement.id}`, expectedColorForClassTest);
|
||||||
|
|
||||||
|
newElement.classList.remove('test');
|
||||||
|
testColor(`remove the class 'test' from the element inserted again before ${beforeElement.id}`, grey);
|
||||||
|
|
||||||
|
newElement.remove();
|
||||||
|
testColor(`remove element div before ${beforeElement.id}`, grey);
|
||||||
|
|
||||||
|
newElement.setAttribute('test_attr', '');
|
||||||
|
|
||||||
|
beforeElement.before(newElement);
|
||||||
|
testColor(`insert element div[test_attr] before ${beforeElement.id}`, expectedColorForAttributeTest);
|
||||||
|
|
||||||
|
newElement.remove();
|
||||||
|
testColor(`remove element div[test_attr] before ${beforeElement.id}`, grey);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testElementInsertionAfter(afterElement, expectedColorName)
|
||||||
|
{
|
||||||
|
const expectedColorForClassTest = colors[expectedColorName].classTest;
|
||||||
|
const expectedColorForAttributeTest = colors[expectedColorName].attributeTest;
|
||||||
|
const newElement = document.createElement('div');
|
||||||
|
newElement.classList.add('test')
|
||||||
|
|
||||||
|
afterElement.after(newElement);
|
||||||
|
testColor(`insert element div.test after ${afterElement.id}`, expectedColorForClassTest);
|
||||||
|
|
||||||
|
newElement.classList.remove('test');
|
||||||
|
testColor(`remove the class 'test' from the element inserted after ${afterElement.id}`, grey);
|
||||||
|
|
||||||
|
newElement.classList.add('test');
|
||||||
|
testColor(`add the class 'test' again to the element inserted after ${afterElement.id}`, expectedColorForClassTest);
|
||||||
|
|
||||||
|
newElement.remove();
|
||||||
|
testColor(`remove element div.test after ${afterElement.id}`, grey);
|
||||||
|
|
||||||
|
newElement.classList.remove('test');
|
||||||
|
|
||||||
|
afterElement.after(newElement);
|
||||||
|
testColor(`insert element div after ${afterElement.id}`, grey);
|
||||||
|
|
||||||
|
newElement.classList.add('test');
|
||||||
|
testColor(`add the class 'test' to the element inserted again after ${afterElement.id}`, expectedColorForClassTest);
|
||||||
|
|
||||||
|
newElement.classList.remove('test');
|
||||||
|
testColor(`remove the class 'test' from the element inserted again after ${afterElement.id}`, grey);
|
||||||
|
|
||||||
|
newElement.remove();
|
||||||
|
testColor(`remove element div after ${afterElement.id}`, grey);
|
||||||
|
|
||||||
|
newElement.setAttribute('test_attr', '');
|
||||||
|
|
||||||
|
afterElement.after(newElement);
|
||||||
|
testColor(`insert element div[test_attr] after ${afterElement.id}`, expectedColorForAttributeTest);
|
||||||
|
|
||||||
|
newElement.remove();
|
||||||
|
testColor(`remove element div[test_attr] after ${afterElement.id}`, grey);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testTreeInsertionBefore(beforeElement, expectedColorName)
|
||||||
|
{
|
||||||
|
const expectedColorForClassTest = colors[expectedColorName].classTest;
|
||||||
|
const expectedColorForAttributeTest = colors[expectedColorName].attributeTest;
|
||||||
|
const newElement = document.createElement('div');
|
||||||
|
const newChild = document.createElement('div');
|
||||||
|
newChild.classList.add('test');
|
||||||
|
newElement.appendChild(newChild);
|
||||||
|
|
||||||
|
beforeElement.before(newElement);
|
||||||
|
testColor(`insert tree div>div.test before ${beforeElement.id}`, expectedColorForClassTest);
|
||||||
|
|
||||||
|
newChild.classList.remove('test');
|
||||||
|
testColor(`remove the class 'test' from the element in the tree inserted before ${beforeElement.id}`, grey);
|
||||||
|
|
||||||
|
newChild.classList.add('test');
|
||||||
|
testColor(`add the class 'test' again to the element in the tree inserted before ${beforeElement.id}`, expectedColorForClassTest);
|
||||||
|
|
||||||
|
newElement.remove();
|
||||||
|
testColor(`remove tree div>div.test before ${beforeElement.id}`, grey);
|
||||||
|
|
||||||
|
newChild.classList.remove('test');
|
||||||
|
|
||||||
|
beforeElement.before(newElement);
|
||||||
|
testColor(`insert tree div>div before ${beforeElement.id}`, grey);
|
||||||
|
|
||||||
|
newChild.classList.add('test');
|
||||||
|
testColor(`add the class 'test' to the element in the tree inserted again before ${beforeElement.id}`, expectedColorForClassTest);
|
||||||
|
|
||||||
|
newChild.classList.remove('test');
|
||||||
|
testColor(`remove the class 'test' from the element in the tree inserted again before ${beforeElement.id}`, grey);
|
||||||
|
|
||||||
|
newElement.remove();
|
||||||
|
testColor(`remove tree div>div before ${beforeElement.id}`, grey);
|
||||||
|
|
||||||
|
newChild.setAttribute('test_attr', '');
|
||||||
|
|
||||||
|
beforeElement.before(newElement);
|
||||||
|
testColor(`insert element div>div[test_attr] before ${beforeElement.id}`, expectedColorForAttributeTest);
|
||||||
|
|
||||||
|
newElement.remove();
|
||||||
|
testColor(`remove element div>div[test_attr] before ${beforeElement.id}`, grey);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testTreeInsertionAfter(afterElement, expectedColorName)
|
||||||
|
{
|
||||||
|
const expectedColorForClassTest = colors[expectedColorName].classTest;
|
||||||
|
const expectedColorForAttributeTest = colors[expectedColorName].attributeTest;
|
||||||
|
const newElement = document.createElement('div');
|
||||||
|
const newChild = document.createElement('div');
|
||||||
|
newChild.classList.add('test');
|
||||||
|
newElement.appendChild(newChild);
|
||||||
|
|
||||||
|
afterElement.after(newElement);
|
||||||
|
testColor(`insert tree div>div.test after ${afterElement.id}`, expectedColorForClassTest);
|
||||||
|
|
||||||
|
newChild.classList.remove('test');
|
||||||
|
testColor(`remove the class 'test' from the element in the tree inserted after ${afterElement.id}`, grey);
|
||||||
|
|
||||||
|
newChild.classList.add('test');
|
||||||
|
testColor(`add the class 'test' again to the element in the tree inserted after ${afterElement.id}`, expectedColorForClassTest);
|
||||||
|
|
||||||
|
newElement.remove();
|
||||||
|
testColor(`remove tree div>div.test after ${afterElement.id}`, grey);
|
||||||
|
|
||||||
|
newChild.classList.remove('test');
|
||||||
|
|
||||||
|
afterElement.after(newElement);
|
||||||
|
testColor(`insert tree div>div after ${afterElement.id}`, grey);
|
||||||
|
|
||||||
|
newChild.classList.add('test');
|
||||||
|
testColor(`add the class 'test' to the element in the tree inserted again after ${afterElement.id}`, expectedColorForClassTest);
|
||||||
|
|
||||||
|
newChild.classList.remove('test');
|
||||||
|
testColor(`remove the class 'test' from the element in the tree inserted again after ${afterElement.id}`, grey);
|
||||||
|
|
||||||
|
newElement.remove();
|
||||||
|
testColor(`remove tree div>div after ${afterElement.id}`, grey);
|
||||||
|
|
||||||
|
newChild.setAttribute('test_attr', '');
|
||||||
|
|
||||||
|
afterElement.after(newElement);
|
||||||
|
testColor(`insert element div>div[test_attr] after ${afterElement.id}`, expectedColorForAttributeTest);
|
||||||
|
|
||||||
|
newElement.remove();
|
||||||
|
testColor(`remove element div>div[test_attr] after ${afterElement.id}`, grey);
|
||||||
|
}
|
||||||
|
|
||||||
|
testColor('Initial color', grey);
|
||||||
|
|
||||||
|
testClassChange(previous_sibling, "grey");
|
||||||
|
testClassChange(previous_sibling_child, "green");
|
||||||
|
testClassChange(previous_sibling_descendant, "red");
|
||||||
|
testClassChange(subject, "blue");
|
||||||
|
testClassChange(next_sibling, "yellow");
|
||||||
|
testClassChange(next_sibling_child, "purple");
|
||||||
|
testClassChange(next_sibling_descendant, "purple");
|
||||||
|
|
||||||
|
testElementInsertionBefore(previous_sibling, "grey");
|
||||||
|
testElementInsertionBefore(previous_sibling_child, "green");
|
||||||
|
testElementInsertionBefore(previous_sibling_descendant, "red");
|
||||||
|
testElementInsertionBefore(subject, "grey");
|
||||||
|
testElementInsertionBefore(next_sibling, "yellow");
|
||||||
|
testElementInsertionBefore(next_sibling_child, "purple");
|
||||||
|
testElementInsertionBefore(next_sibling_descendant, "purple");
|
||||||
|
|
||||||
|
testElementInsertionAfter(previous_sibling, "grey");
|
||||||
|
testElementInsertionAfter(previous_sibling_child, "green");
|
||||||
|
testElementInsertionAfter(previous_sibling_descendant, "red");
|
||||||
|
testElementInsertionAfter(subject, "yellow");
|
||||||
|
testElementInsertionAfter(next_sibling, "yellow");
|
||||||
|
testElementInsertionAfter(next_sibling_child, "purple");
|
||||||
|
testElementInsertionAfter(next_sibling_descendant, "purple");
|
||||||
|
|
||||||
|
testTreeInsertionBefore(previous_sibling, "grey");
|
||||||
|
testTreeInsertionBefore(previous_sibling_child, "red");
|
||||||
|
testTreeInsertionBefore(previous_sibling_descendant, "red");
|
||||||
|
testTreeInsertionBefore(subject, "green");
|
||||||
|
testTreeInsertionBefore(next_sibling, "purple");
|
||||||
|
testTreeInsertionBefore(next_sibling_child, "purple");
|
||||||
|
testTreeInsertionBefore(next_sibling_descendant, "purple");
|
||||||
|
|
||||||
|
testTreeInsertionAfter(previous_sibling, "green");
|
||||||
|
testTreeInsertionAfter(previous_sibling_child, "red");
|
||||||
|
testTreeInsertionAfter(previous_sibling_descendant, "red");
|
||||||
|
testTreeInsertionAfter(subject, "purple");
|
||||||
|
testTreeInsertionAfter(next_sibling, "purple");
|
||||||
|
testTreeInsertionAfter(next_sibling_child, "purple");
|
||||||
|
testTreeInsertionAfter(next_sibling_descendant, "purple");
|
||||||
|
|
||||||
|
</script>
|
|
@ -0,0 +1,320 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>CSS Selector Invalidation: :has() in ancestor position</title>
|
||||||
|
<link rel="author" title="Antti Koivisto" href="mailto:antti@apple.com">
|
||||||
|
<script src="../../../resources/testharness.js"></script>
|
||||||
|
<script src="../../../resources/testharnessreport.js"></script>
|
||||||
|
<link rel="help" href="https://drafts.csswg.org/selectors/#relational">
|
||||||
|
<style>
|
||||||
|
div, main { color: grey }
|
||||||
|
div:has(.test) #subject { color: red }
|
||||||
|
div:has([test_attr]) #subject { color: orangered }
|
||||||
|
div:has(> .test) #subject { color: green }
|
||||||
|
div:has(> [test_attr]) #subject { color: lightgreen }
|
||||||
|
div:has(~ .test) #subject { color: yellow }
|
||||||
|
div:has(~ [test_attr]) #subject { color: ivory }
|
||||||
|
div:has(+ .test) #subject { color: blue }
|
||||||
|
div:has(+ [test_attr]) #subject { color: skyblue }
|
||||||
|
div:has(~ div .test) #subject { color: purple }
|
||||||
|
div:has(~ div [test_attr]) #subject { color: violet }
|
||||||
|
div:has(+ div .test) #subject { color: pink }
|
||||||
|
div:has(+ div [test_attr]) #subject { color: lightpink }
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<main id=main>
|
||||||
|
<div id=subject_ancestor>
|
||||||
|
<div id=subject_parent>
|
||||||
|
<div id=subject>
|
||||||
|
<div id=subject_child>
|
||||||
|
<div id=subject_descendant></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id=next_sibling>
|
||||||
|
<div id=next_sibling_child>
|
||||||
|
<div id=next_sibling_descendant></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const grey = 'rgb(128, 128, 128)';
|
||||||
|
const red = 'rgb(255, 0, 0)';
|
||||||
|
const orangered = 'rgb(255, 69, 0)';
|
||||||
|
const green = 'rgb(0, 128, 0)';
|
||||||
|
const lightgreen = 'rgb(144, 238, 144)';
|
||||||
|
const blue = 'rgb(0, 0, 255)';
|
||||||
|
const skyblue = 'rgb(135, 206, 235)';
|
||||||
|
const yellow = 'rgb(255, 255, 0)';
|
||||||
|
const ivory = 'rgb(255, 255, 240)';
|
||||||
|
const purple = 'rgb(128, 0, 128)';
|
||||||
|
const violet = 'rgb(238, 130, 238)';
|
||||||
|
const pink = 'rgb(255, 192, 203)';
|
||||||
|
const lightpink = 'rgb(255, 182, 193)';
|
||||||
|
const colors = {
|
||||||
|
grey: {
|
||||||
|
classTest: grey,
|
||||||
|
attributeTest: grey,
|
||||||
|
},
|
||||||
|
red: {
|
||||||
|
classTest: red,
|
||||||
|
attributeTest: orangered,
|
||||||
|
},
|
||||||
|
green: {
|
||||||
|
classTest: green,
|
||||||
|
attributeTest: lightgreen,
|
||||||
|
},
|
||||||
|
blue: {
|
||||||
|
classTest: blue,
|
||||||
|
attributeTest: skyblue,
|
||||||
|
},
|
||||||
|
yellow: {
|
||||||
|
classTest: yellow,
|
||||||
|
attributeTest: ivory,
|
||||||
|
},
|
||||||
|
purple: {
|
||||||
|
classTest: purple,
|
||||||
|
attributeTest: violet,
|
||||||
|
},
|
||||||
|
pink: {
|
||||||
|
classTest: pink,
|
||||||
|
attributeTest: lightpink,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
function testColor(test_name, color) {
|
||||||
|
test(function() {
|
||||||
|
assert_equals(getComputedStyle(subject).color, color);
|
||||||
|
}, test_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testClassChange(element, expectedColorName)
|
||||||
|
{
|
||||||
|
const expectedColorForClassTest = colors[expectedColorName].classTest;
|
||||||
|
element.classList.add('test');
|
||||||
|
testColor(`add .test to ${element.id}`, expectedColorForClassTest);
|
||||||
|
element.classList.remove('test');
|
||||||
|
testColor(`remove .test from ${element.id}`, grey);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testElementInsertionBefore(beforeElement, expectedColorName)
|
||||||
|
{
|
||||||
|
const expectedColorForClassTest = colors[expectedColorName].classTest;
|
||||||
|
const expectedColorForAttributeTest = colors[expectedColorName].attributeTest;
|
||||||
|
const newElement = document.createElement('div');
|
||||||
|
newElement.classList.add('test')
|
||||||
|
|
||||||
|
beforeElement.before(newElement);
|
||||||
|
testColor(`insert element div.test before ${beforeElement.id}`, expectedColorForClassTest);
|
||||||
|
|
||||||
|
newElement.classList.remove('test');
|
||||||
|
testColor(`remove the class 'test' from the element inserted before ${beforeElement.id}`, grey);
|
||||||
|
|
||||||
|
newElement.classList.add('test');
|
||||||
|
testColor(`add the class 'test' again to the element inserted before ${beforeElement.id}`, expectedColorForClassTest);
|
||||||
|
|
||||||
|
newElement.remove();
|
||||||
|
testColor(`remove element div.test before ${beforeElement.id}`, grey);
|
||||||
|
|
||||||
|
newElement.classList.remove('test');
|
||||||
|
|
||||||
|
beforeElement.before(newElement);
|
||||||
|
testColor(`insert element div before ${beforeElement.id}`, grey);
|
||||||
|
|
||||||
|
newElement.classList.add('test');
|
||||||
|
testColor(`add the class 'test' to the element inserted again before ${beforeElement.id}`, expectedColorForClassTest);
|
||||||
|
|
||||||
|
newElement.classList.remove('test');
|
||||||
|
testColor(`remove the class 'test' from the element inserted again before ${beforeElement.id}`, grey);
|
||||||
|
|
||||||
|
newElement.remove();
|
||||||
|
testColor(`remove element div before ${beforeElement.id}`, grey);
|
||||||
|
|
||||||
|
newElement.setAttribute('test_attr', '');
|
||||||
|
|
||||||
|
beforeElement.before(newElement);
|
||||||
|
testColor(`insert element div[test_attr] before ${beforeElement.id}`, expectedColorForAttributeTest);
|
||||||
|
|
||||||
|
newElement.remove();
|
||||||
|
testColor(`remove element div[test_attr] before ${beforeElement.id}`, grey);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testElementInsertionAfter(afterElement, expectedColorName)
|
||||||
|
{
|
||||||
|
const expectedColorForClassTest = colors[expectedColorName].classTest;
|
||||||
|
const expectedColorForAttributeTest = colors[expectedColorName].attributeTest;
|
||||||
|
const newElement = document.createElement('div');
|
||||||
|
newElement.classList.add('test')
|
||||||
|
|
||||||
|
afterElement.after(newElement);
|
||||||
|
testColor(`insert element div.test after ${afterElement.id}`, expectedColorForClassTest);
|
||||||
|
|
||||||
|
newElement.classList.remove('test');
|
||||||
|
testColor(`remove the class 'test' from the element inserted after ${afterElement.id}`, grey);
|
||||||
|
|
||||||
|
newElement.classList.add('test');
|
||||||
|
testColor(`add the class 'test' again to the element inserted after ${afterElement.id}`, expectedColorForClassTest);
|
||||||
|
|
||||||
|
newElement.remove();
|
||||||
|
testColor(`remove element div.test after ${afterElement.id}`, grey);
|
||||||
|
|
||||||
|
newElement.classList.remove('test');
|
||||||
|
|
||||||
|
afterElement.after(newElement);
|
||||||
|
testColor(`insert element div after ${afterElement.id}`, grey);
|
||||||
|
|
||||||
|
newElement.classList.add('test');
|
||||||
|
testColor(`add the class 'test' to the element inserted again after ${afterElement.id}`, expectedColorForClassTest);
|
||||||
|
|
||||||
|
newElement.classList.remove('test');
|
||||||
|
testColor(`remove the class 'test' from the element inserted again after ${afterElement.id}`, grey);
|
||||||
|
|
||||||
|
newElement.remove();
|
||||||
|
testColor(`remove element div after ${afterElement.id}`, grey);
|
||||||
|
|
||||||
|
newElement.setAttribute('test_attr', '');
|
||||||
|
|
||||||
|
afterElement.after(newElement);
|
||||||
|
testColor(`insert element div[test_attr] after ${afterElement.id}`, expectedColorForAttributeTest);
|
||||||
|
|
||||||
|
newElement.remove();
|
||||||
|
testColor(`remove element div[test_attr] after ${afterElement.id}`, grey);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testTreeInsertionBefore(beforeElement, expectedColorName)
|
||||||
|
{
|
||||||
|
const expectedColorForClassTest = colors[expectedColorName].classTest;
|
||||||
|
const expectedColorForAttributeTest = colors[expectedColorName].attributeTest;
|
||||||
|
const newElement = document.createElement('div');
|
||||||
|
const newChild = document.createElement('div');
|
||||||
|
newChild.classList.add('test');
|
||||||
|
newElement.appendChild(newChild);
|
||||||
|
|
||||||
|
beforeElement.before(newElement);
|
||||||
|
testColor(`insert tree div>div.test before ${beforeElement.id}`, expectedColorForClassTest);
|
||||||
|
|
||||||
|
newChild.classList.remove('test');
|
||||||
|
testColor(`remove the class 'test' from the element in the tree inserted before ${beforeElement.id}`, grey);
|
||||||
|
|
||||||
|
newChild.classList.add('test');
|
||||||
|
testColor(`add the class 'test' again to the element in the tree inserted before ${beforeElement.id}`, expectedColorForClassTest);
|
||||||
|
|
||||||
|
newElement.remove();
|
||||||
|
testColor(`remove tree div>div.test before ${beforeElement.id}`, grey);
|
||||||
|
|
||||||
|
newChild.classList.remove('test');
|
||||||
|
|
||||||
|
beforeElement.before(newElement);
|
||||||
|
testColor(`insert tree div>div before ${beforeElement.id}`, grey);
|
||||||
|
|
||||||
|
newChild.classList.add('test');
|
||||||
|
testColor(`add the class 'test' to the element in the tree inserted again before ${beforeElement.id}`, expectedColorForClassTest);
|
||||||
|
|
||||||
|
newChild.classList.remove('test');
|
||||||
|
testColor(`remove the class 'test' from the element in the tree inserted again before ${beforeElement.id}`, grey);
|
||||||
|
|
||||||
|
newElement.remove();
|
||||||
|
testColor(`remove tree div>div before ${beforeElement.id}`, grey);
|
||||||
|
|
||||||
|
newChild.setAttribute('test_attr', '');
|
||||||
|
|
||||||
|
beforeElement.before(newElement);
|
||||||
|
testColor(`insert element div>div[test_attr] before ${beforeElement.id}`, expectedColorForAttributeTest);
|
||||||
|
|
||||||
|
newElement.remove();
|
||||||
|
testColor(`remove element div>div[test_attr] before ${beforeElement.id}`, grey);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testTreeInsertionAfter(afterElement, expectedColorName)
|
||||||
|
{
|
||||||
|
const expectedColorForClassTest = colors[expectedColorName].classTest;
|
||||||
|
const expectedColorForAttributeTest = colors[expectedColorName].attributeTest;
|
||||||
|
const newElement = document.createElement('div');
|
||||||
|
const newChild = document.createElement('div');
|
||||||
|
newChild.classList.add('test');
|
||||||
|
newElement.appendChild(newChild);
|
||||||
|
|
||||||
|
afterElement.after(newElement);
|
||||||
|
testColor(`insert tree div>div.test after ${afterElement.id}`, expectedColorForClassTest);
|
||||||
|
|
||||||
|
newChild.classList.remove('test');
|
||||||
|
testColor(`remove the class 'test' from the element in the tree inserted after ${afterElement.id}`, grey);
|
||||||
|
|
||||||
|
newChild.classList.add('test');
|
||||||
|
testColor(`add the class 'test' again to the element in the tree inserted after ${afterElement.id}`, expectedColorForClassTest);
|
||||||
|
|
||||||
|
newElement.remove();
|
||||||
|
testColor(`remove tree div>div.test after ${afterElement.id}`, grey);
|
||||||
|
|
||||||
|
newChild.classList.remove('test');
|
||||||
|
|
||||||
|
afterElement.after(newElement);
|
||||||
|
testColor(`insert tree div>div after ${afterElement.id}`, grey);
|
||||||
|
|
||||||
|
newChild.classList.add('test');
|
||||||
|
testColor(`add the class 'test' to the element in the tree inserted again after ${afterElement.id}`, expectedColorForClassTest);
|
||||||
|
|
||||||
|
newChild.classList.remove('test');
|
||||||
|
testColor(`remove the class 'test' from the element in the tree inserted again after ${afterElement.id}`, grey);
|
||||||
|
|
||||||
|
newElement.remove();
|
||||||
|
testColor(`remove tree div>div after ${afterElement.id}`, grey);
|
||||||
|
|
||||||
|
newChild.setAttribute('test_attr', '');
|
||||||
|
|
||||||
|
afterElement.after(newElement);
|
||||||
|
testColor(`insert element div>div[test_attr] after ${afterElement.id}`, expectedColorForAttributeTest);
|
||||||
|
|
||||||
|
newElement.remove();
|
||||||
|
testColor(`remove element div>div[test_attr] after ${afterElement.id}`, grey);
|
||||||
|
}
|
||||||
|
|
||||||
|
testColor('Initial color', grey);
|
||||||
|
|
||||||
|
testClassChange(subject_ancestor, "grey");
|
||||||
|
testClassChange(subject_parent, "green");
|
||||||
|
testClassChange(subject, "green");
|
||||||
|
testClassChange(subject_child, "red");
|
||||||
|
testClassChange(subject_descendant, "red");
|
||||||
|
testClassChange(next_sibling, "blue");
|
||||||
|
testClassChange(next_sibling_child, "pink");
|
||||||
|
testClassChange(next_sibling_descendant, "pink");
|
||||||
|
|
||||||
|
testElementInsertionBefore(subject_ancestor, "grey");
|
||||||
|
testElementInsertionBefore(subject_parent, "green");
|
||||||
|
testElementInsertionBefore(subject, "green");
|
||||||
|
testElementInsertionBefore(subject_child, "red");
|
||||||
|
testElementInsertionBefore(subject_descendant, "red");
|
||||||
|
testElementInsertionBefore(next_sibling, "blue");
|
||||||
|
testElementInsertionBefore(next_sibling_child, "pink");
|
||||||
|
testElementInsertionBefore(next_sibling_descendant, "pink");
|
||||||
|
|
||||||
|
testElementInsertionAfter(subject_ancestor, "blue");
|
||||||
|
testElementInsertionAfter(subject_parent, "blue");
|
||||||
|
testElementInsertionAfter(subject, "green");
|
||||||
|
testElementInsertionAfter(subject_child, "red");
|
||||||
|
testElementInsertionAfter(subject_descendant, "red");
|
||||||
|
testElementInsertionAfter(next_sibling, "yellow");
|
||||||
|
testElementInsertionAfter(next_sibling_child, "pink");
|
||||||
|
testElementInsertionAfter(next_sibling_descendant, "pink");
|
||||||
|
|
||||||
|
testTreeInsertionBefore(subject_ancestor, "grey");
|
||||||
|
testTreeInsertionBefore(subject_parent, "red");
|
||||||
|
testTreeInsertionBefore(subject, "red");
|
||||||
|
testTreeInsertionBefore(subject_child, "red");
|
||||||
|
testTreeInsertionBefore(subject_descendant, "red");
|
||||||
|
testTreeInsertionBefore(next_sibling, "pink");
|
||||||
|
testTreeInsertionBefore(next_sibling_child, "pink");
|
||||||
|
testTreeInsertionBefore(next_sibling_descendant, "pink");
|
||||||
|
|
||||||
|
testTreeInsertionAfter(subject_ancestor, "pink");
|
||||||
|
testTreeInsertionAfter(subject_parent, "pink");
|
||||||
|
testTreeInsertionAfter(subject, "red");
|
||||||
|
testTreeInsertionAfter(subject_child, "red");
|
||||||
|
testTreeInsertionAfter(subject_descendant, "red");
|
||||||
|
testTreeInsertionAfter(next_sibling, "purple");
|
||||||
|
testTreeInsertionAfter(next_sibling_child, "pink");
|
||||||
|
testTreeInsertionAfter(next_sibling_descendant, "pink");
|
||||||
|
|
||||||
|
</script>
|
|
@ -0,0 +1,300 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>CSS Selector Invalidation: :has() in parent position</title>
|
||||||
|
<link rel="author" title="Antti Koivisto" href="mailto:antti@apple.com">
|
||||||
|
<script src="../../../resources/testharness.js"></script>
|
||||||
|
<script src="../../../resources/testharnessreport.js"></script>
|
||||||
|
<link rel="help" href="https://drafts.csswg.org/selectors/#relational">
|
||||||
|
<style>
|
||||||
|
div, main { color: grey }
|
||||||
|
div:has(.test) > #subject { color: red }
|
||||||
|
div:has([test_attr]) > #subject { color: orangered }
|
||||||
|
div:has(> .test) > #subject { color: green }
|
||||||
|
div:has(> [test_attr]) > #subject { color: lightgreen }
|
||||||
|
div:has(~ .test) > #subject { color: yellow }
|
||||||
|
div:has(~ [test_attr]) > #subject { color: ivory }
|
||||||
|
div:has(+ .test) > #subject { color: blue }
|
||||||
|
div:has(+ [test_attr]) > #subject { color: skyblue }
|
||||||
|
div:has(~ div .test) > #subject { color: purple }
|
||||||
|
div:has(~ div [test_attr]) > #subject { color: violet }
|
||||||
|
div:has(+ div .test) > #subject { color: pink }
|
||||||
|
div:has(+ div [test_attr]) > #subject { color: lightpink }
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<main id=main>
|
||||||
|
<div id=subject_ancestor>
|
||||||
|
<div id=subject_parent>
|
||||||
|
<div id=subject>
|
||||||
|
<div id=subject_child>
|
||||||
|
<div id=subject_descendant></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const grey = 'rgb(128, 128, 128)';
|
||||||
|
const red = 'rgb(255, 0, 0)';
|
||||||
|
const orangered = 'rgb(255, 69, 0)';
|
||||||
|
const green = 'rgb(0, 128, 0)';
|
||||||
|
const lightgreen = 'rgb(144, 238, 144)';
|
||||||
|
const blue = 'rgb(0, 0, 255)';
|
||||||
|
const skyblue = 'rgb(135, 206, 235)';
|
||||||
|
const yellow = 'rgb(255, 255, 0)';
|
||||||
|
const ivory = 'rgb(255, 255, 240)';
|
||||||
|
const purple = 'rgb(128, 0, 128)';
|
||||||
|
const violet = 'rgb(238, 130, 238)';
|
||||||
|
const pink = 'rgb(255, 192, 203)';
|
||||||
|
const lightpink = 'rgb(255, 182, 193)';
|
||||||
|
const colors = {
|
||||||
|
grey: {
|
||||||
|
classTest: grey,
|
||||||
|
attributeTest: grey,
|
||||||
|
},
|
||||||
|
red: {
|
||||||
|
classTest: red,
|
||||||
|
attributeTest: orangered,
|
||||||
|
},
|
||||||
|
green: {
|
||||||
|
classTest: green,
|
||||||
|
attributeTest: lightgreen,
|
||||||
|
},
|
||||||
|
blue: {
|
||||||
|
classTest: blue,
|
||||||
|
attributeTest: skyblue,
|
||||||
|
},
|
||||||
|
yellow: {
|
||||||
|
classTest: yellow,
|
||||||
|
attributeTest: ivory,
|
||||||
|
},
|
||||||
|
purple: {
|
||||||
|
classTest: purple,
|
||||||
|
attributeTest: violet,
|
||||||
|
},
|
||||||
|
pink: {
|
||||||
|
classTest: pink,
|
||||||
|
attributeTest: lightpink,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
function testColor(test_name, color) {
|
||||||
|
test(function() {
|
||||||
|
assert_equals(getComputedStyle(subject).color, color);
|
||||||
|
}, test_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testClassChange(element, expectedColorName)
|
||||||
|
{
|
||||||
|
const expectedColorForClassTest = colors[expectedColorName].classTest;
|
||||||
|
element.classList.add('test');
|
||||||
|
testColor(`add .test to ${element.id}`, expectedColorForClassTest);
|
||||||
|
element.classList.remove('test');
|
||||||
|
testColor(`remove .test from ${element.id}`, grey);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testElementInsertionBefore(beforeElement, expectedColorName)
|
||||||
|
{
|
||||||
|
const expectedColorForClassTest = colors[expectedColorName].classTest;
|
||||||
|
const expectedColorForAttributeTest = colors[expectedColorName].attributeTest;
|
||||||
|
const newElement = document.createElement('div');
|
||||||
|
newElement.classList.add('test');
|
||||||
|
|
||||||
|
beforeElement.before(newElement);
|
||||||
|
testColor(`insert element div.test before ${beforeElement.id}`, expectedColorForClassTest);
|
||||||
|
|
||||||
|
newElement.classList.remove('test');
|
||||||
|
testColor(`remove the class 'test' from the element inserted before ${beforeElement.id}`, grey);
|
||||||
|
|
||||||
|
newElement.classList.add('test');
|
||||||
|
testColor(`add the class 'test' again to the element inserted before ${beforeElement.id}`, expectedColorForClassTest);
|
||||||
|
|
||||||
|
newElement.remove();
|
||||||
|
testColor(`remove element div.test before ${beforeElement.id}`, grey);
|
||||||
|
|
||||||
|
newElement.classList.remove('test');
|
||||||
|
|
||||||
|
beforeElement.before(newElement);
|
||||||
|
testColor(`insert element div before ${beforeElement.id}`, grey);
|
||||||
|
|
||||||
|
newElement.classList.add('test');
|
||||||
|
testColor(`add the class 'test' to the element inserted again before ${beforeElement.id}`, expectedColorForClassTest);
|
||||||
|
|
||||||
|
newElement.classList.remove('test');
|
||||||
|
testColor(`remove the class 'test' from the element inserted again before ${beforeElement.id}`, grey);
|
||||||
|
|
||||||
|
newElement.remove();
|
||||||
|
testColor(`remove element div before ${beforeElement.id}`, grey);
|
||||||
|
|
||||||
|
newElement.setAttribute('test_attr', '');
|
||||||
|
|
||||||
|
beforeElement.before(newElement);
|
||||||
|
testColor(`insert element div[test_attr] before ${beforeElement.id}`, expectedColorForAttributeTest);
|
||||||
|
|
||||||
|
newElement.remove();
|
||||||
|
testColor(`remove element div[test_attr] before ${beforeElement.id}`, grey);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testElementInsertionAfter(afterElement, expectedColorName)
|
||||||
|
{
|
||||||
|
const expectedColorForClassTest = colors[expectedColorName].classTest;
|
||||||
|
const expectedColorForAttributeTest = colors[expectedColorName].attributeTest;
|
||||||
|
const newElement = document.createElement('div');
|
||||||
|
newElement.classList.add('test');
|
||||||
|
|
||||||
|
afterElement.after(newElement);
|
||||||
|
testColor(`insert element div.test after ${afterElement.id}`, expectedColorForClassTest);
|
||||||
|
|
||||||
|
newElement.classList.remove('test');
|
||||||
|
testColor(`remove the class 'test' from the element inserted after ${afterElement.id}`, grey);
|
||||||
|
|
||||||
|
newElement.classList.add('test');
|
||||||
|
testColor(`add the class 'test' again to the element inserted after ${afterElement.id}`, expectedColorForClassTest);
|
||||||
|
|
||||||
|
newElement.remove();
|
||||||
|
testColor(`remove element div.test after ${afterElement.id}`, grey);
|
||||||
|
|
||||||
|
newElement.classList.remove('test');
|
||||||
|
|
||||||
|
afterElement.after(newElement);
|
||||||
|
testColor(`insert element div after ${afterElement.id}`, grey);
|
||||||
|
|
||||||
|
newElement.classList.add('test');
|
||||||
|
testColor(`add the class 'test' to the element inserted again after ${afterElement.id}`, expectedColorForClassTest);
|
||||||
|
|
||||||
|
newElement.classList.remove('test');
|
||||||
|
testColor(`remove the class 'test' from the element inserted again after ${afterElement.id}`, grey);
|
||||||
|
|
||||||
|
newElement.remove();
|
||||||
|
testColor(`remove element div after ${afterElement.id}`, grey);
|
||||||
|
|
||||||
|
newElement.setAttribute('test_attr', '');
|
||||||
|
|
||||||
|
afterElement.after(newElement);
|
||||||
|
testColor(`insert element div[test_attr] after ${afterElement.id}`, expectedColorForAttributeTest);
|
||||||
|
|
||||||
|
newElement.remove();
|
||||||
|
testColor(`remove element div[test_attr] after ${afterElement.id}`, grey);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testTreeInsertionBefore(beforeElement, expectedColorName)
|
||||||
|
{
|
||||||
|
const expectedColorForClassTest = colors[expectedColorName].classTest;
|
||||||
|
const expectedColorForAttributeTest = colors[expectedColorName].attributeTest;
|
||||||
|
const newElement = document.createElement('div');
|
||||||
|
const newChild = document.createElement('div');
|
||||||
|
newChild.classList.add('test');
|
||||||
|
newElement.appendChild(newChild);
|
||||||
|
|
||||||
|
beforeElement.before(newElement);
|
||||||
|
testColor(`insert tree div>div.test before ${beforeElement.id}`, expectedColorForClassTest);
|
||||||
|
|
||||||
|
newChild.classList.remove('test');
|
||||||
|
testColor(`remove the class 'test' from the element in the tree inserted before ${beforeElement.id}`, grey);
|
||||||
|
|
||||||
|
newChild.classList.add('test');
|
||||||
|
testColor(`add the class 'test' again to the element in the tree inserted before ${beforeElement.id}`, expectedColorForClassTest);
|
||||||
|
|
||||||
|
newElement.remove();
|
||||||
|
testColor(`remove tree div>div.test before ${beforeElement.id}`, grey);
|
||||||
|
|
||||||
|
newChild.classList.remove('test');
|
||||||
|
|
||||||
|
beforeElement.before(newElement);
|
||||||
|
testColor(`insert tree div>div before ${beforeElement.id}`, grey);
|
||||||
|
|
||||||
|
newChild.classList.add('test');
|
||||||
|
testColor(`add the class 'test' to the element in the tree inserted again before ${beforeElement.id}`, expectedColorForClassTest);
|
||||||
|
|
||||||
|
newChild.classList.remove('test');
|
||||||
|
testColor(`remove the class 'test' from the element in the tree inserted again before ${beforeElement.id}`, grey);
|
||||||
|
|
||||||
|
newElement.remove();
|
||||||
|
testColor(`remove tree div>div before ${beforeElement.id}`, grey);
|
||||||
|
|
||||||
|
newChild.setAttribute('test_attr', '');
|
||||||
|
|
||||||
|
beforeElement.before(newElement);
|
||||||
|
testColor(`insert element div>div[test_attr] before ${beforeElement.id}`, expectedColorForAttributeTest);
|
||||||
|
|
||||||
|
newElement.remove();
|
||||||
|
testColor(`remove element div>div[test_attr] before ${beforeElement.id}`, grey);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testTreeInsertionAfter(afterElement, expectedColorName)
|
||||||
|
{
|
||||||
|
const expectedColorForClassTest = colors[expectedColorName].classTest;
|
||||||
|
const expectedColorForAttributeTest = colors[expectedColorName].attributeTest;
|
||||||
|
const newElement = document.createElement('div');
|
||||||
|
const newChild = document.createElement('div');
|
||||||
|
newChild.classList.add('test');
|
||||||
|
newElement.appendChild(newChild);
|
||||||
|
|
||||||
|
afterElement.after(newElement);
|
||||||
|
testColor(`insert tree div>div.test after ${afterElement.id}`, expectedColorForClassTest);
|
||||||
|
|
||||||
|
newChild.classList.remove('test');
|
||||||
|
testColor(`remove the class 'test' from the element in the tree inserted after ${afterElement.id}`, grey);
|
||||||
|
|
||||||
|
newChild.classList.add('test');
|
||||||
|
testColor(`add the class 'test' again to the element in the tree inserted after ${afterElement.id}`, expectedColorForClassTest);
|
||||||
|
|
||||||
|
newElement.remove();
|
||||||
|
testColor(`remove tree div>div.test after ${afterElement.id}`, grey);
|
||||||
|
|
||||||
|
newChild.classList.remove('test');
|
||||||
|
|
||||||
|
afterElement.after(newElement);
|
||||||
|
testColor(`insert tree div>div after ${afterElement.id}`, grey);
|
||||||
|
|
||||||
|
newChild.classList.add('test');
|
||||||
|
testColor(`add the class 'test' to the element in the tree inserted again after ${afterElement.id}`, expectedColorForClassTest);
|
||||||
|
|
||||||
|
newChild.classList.remove('test');
|
||||||
|
testColor(`remove the class 'test' from the element in the tree inserted again after ${afterElement.id}`, grey);
|
||||||
|
|
||||||
|
newElement.remove();
|
||||||
|
testColor(`remove tree div>div after ${afterElement.id}`, grey);
|
||||||
|
|
||||||
|
newChild.setAttribute('test_attr', '');
|
||||||
|
|
||||||
|
afterElement.after(newElement);
|
||||||
|
testColor(`insert element div>div[test_attr] after ${afterElement.id}`, expectedColorForAttributeTest);
|
||||||
|
|
||||||
|
newElement.remove();
|
||||||
|
testColor(`remove element div>div[test_attr] after ${afterElement.id}`, grey);
|
||||||
|
}
|
||||||
|
|
||||||
|
testColor('Initial color', grey);
|
||||||
|
|
||||||
|
testClassChange(subject_ancestor, "grey");
|
||||||
|
testClassChange(subject_parent, "grey");
|
||||||
|
testClassChange(subject, "green");
|
||||||
|
testClassChange(subject_child, "red");
|
||||||
|
testClassChange(subject_descendant, "red");
|
||||||
|
|
||||||
|
testElementInsertionBefore(subject_ancestor, "grey");
|
||||||
|
testElementInsertionBefore(subject_parent, "grey");
|
||||||
|
testElementInsertionBefore(subject, "green");
|
||||||
|
testElementInsertionBefore(subject_child, "red");
|
||||||
|
testElementInsertionBefore(subject_descendant, "red");
|
||||||
|
|
||||||
|
testElementInsertionAfter(subject_ancestor, "grey");
|
||||||
|
testElementInsertionAfter(subject_parent, "blue");
|
||||||
|
testElementInsertionAfter(subject, "green");
|
||||||
|
testElementInsertionAfter(subject_child, "red");
|
||||||
|
testElementInsertionAfter(subject_descendant, "red");
|
||||||
|
|
||||||
|
testTreeInsertionBefore(subject_ancestor, "grey");
|
||||||
|
testTreeInsertionBefore(subject_parent, "grey");
|
||||||
|
testTreeInsertionBefore(subject, "red");
|
||||||
|
testTreeInsertionBefore(subject_child, "red");
|
||||||
|
testTreeInsertionBefore(subject_descendant, "red");
|
||||||
|
|
||||||
|
testTreeInsertionAfter(subject_ancestor, "grey");
|
||||||
|
testTreeInsertionAfter(subject_parent, "pink");
|
||||||
|
testTreeInsertionAfter(subject, "red");
|
||||||
|
testTreeInsertionAfter(subject_child, "red");
|
||||||
|
testTreeInsertionAfter(subject_descendant, "red");
|
||||||
|
|
||||||
|
</script>
|
|
@ -0,0 +1,312 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>CSS Selector Invalidation: :has() in sibling position</title>
|
||||||
|
<link rel="author" title="Antti Koivisto" href="mailto:antti@apple.com">
|
||||||
|
<script src="../../../resources/testharness.js"></script>
|
||||||
|
<script src="../../../resources/testharnessreport.js"></script>
|
||||||
|
<link rel="help" href="https://drafts.csswg.org/selectors/#relational">
|
||||||
|
<style>
|
||||||
|
div, main { color: grey }
|
||||||
|
div:has(.test) ~ #subject { color: red }
|
||||||
|
div:has([test_attr]) ~ #subject { color: orangered }
|
||||||
|
div:has(> .test) ~ #subject { color: green }
|
||||||
|
div:has(> [test_attr]) ~ #subject { color: lightgreen }
|
||||||
|
div:has(~ .test) ~ #subject { color: yellow }
|
||||||
|
div:has(~ [test_attr]) ~ #subject { color: ivory }
|
||||||
|
div:has(+ .test) ~ #subject { color: blue }
|
||||||
|
div:has(+ [test_attr]) ~ #subject { color: skyblue }
|
||||||
|
div:has(~ div .test) ~ #subject { color: purple }
|
||||||
|
div:has(~ div [test_attr]) ~ #subject { color: violet }
|
||||||
|
div:has(+ div .test) ~ #subject { color: pink }
|
||||||
|
div:has(+ div [test_attr]) ~ #subject { color: lightpink }
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<main id=main>
|
||||||
|
<div id=previous_sibling>
|
||||||
|
<div id=previous_sibling_child>
|
||||||
|
<div id=previous_sibling_descendant></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id=subject></div>
|
||||||
|
<div id=next_sibling>
|
||||||
|
<div id=next_sibling_child>
|
||||||
|
<div id=next_sibling_descendant></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const grey = 'rgb(128, 128, 128)';
|
||||||
|
const red = 'rgb(255, 0, 0)';
|
||||||
|
const orangered = 'rgb(255, 69, 0)';
|
||||||
|
const green = 'rgb(0, 128, 0)';
|
||||||
|
const lightgreen = 'rgb(144, 238, 144)';
|
||||||
|
const blue = 'rgb(0, 0, 255)';
|
||||||
|
const skyblue = 'rgb(135, 206, 235)';
|
||||||
|
const yellow = 'rgb(255, 255, 0)';
|
||||||
|
const ivory = 'rgb(255, 255, 240)';
|
||||||
|
const purple = 'rgb(128, 0, 128)';
|
||||||
|
const violet = 'rgb(238, 130, 238)';
|
||||||
|
const pink = 'rgb(255, 192, 203)';
|
||||||
|
const lightpink = 'rgb(255, 182, 193)';
|
||||||
|
const colors = {
|
||||||
|
grey: {
|
||||||
|
classTest: grey,
|
||||||
|
attributeTest: grey,
|
||||||
|
},
|
||||||
|
red: {
|
||||||
|
classTest: red,
|
||||||
|
attributeTest: orangered,
|
||||||
|
},
|
||||||
|
green: {
|
||||||
|
classTest: green,
|
||||||
|
attributeTest: lightgreen,
|
||||||
|
},
|
||||||
|
blue: {
|
||||||
|
classTest: blue,
|
||||||
|
attributeTest: skyblue,
|
||||||
|
},
|
||||||
|
yellow: {
|
||||||
|
classTest: yellow,
|
||||||
|
attributeTest: ivory,
|
||||||
|
},
|
||||||
|
purple: {
|
||||||
|
classTest: purple,
|
||||||
|
attributeTest: violet,
|
||||||
|
},
|
||||||
|
pink: {
|
||||||
|
classTest: pink,
|
||||||
|
attributeTest: lightpink,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
function testColor(test_name, color) {
|
||||||
|
test(function() {
|
||||||
|
assert_equals(getComputedStyle(subject).color, color);
|
||||||
|
}, test_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testClassChange(element, expectedColorName)
|
||||||
|
{
|
||||||
|
const expectedColorForClassTest = colors[expectedColorName].classTest;
|
||||||
|
element.classList.add('test');
|
||||||
|
testColor(`add .test to ${element.id}`, expectedColorForClassTest);
|
||||||
|
element.classList.remove('test');
|
||||||
|
testColor(`remove .test from ${element.id}`, grey);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testElementInsertionBefore(beforeElement, expectedColorName)
|
||||||
|
{
|
||||||
|
const expectedColorForClassTest = colors[expectedColorName].classTest;
|
||||||
|
const expectedColorForAttributeTest = colors[expectedColorName].attributeTest;
|
||||||
|
const newElement = document.createElement('div');
|
||||||
|
newElement.classList.add('test')
|
||||||
|
|
||||||
|
beforeElement.before(newElement);
|
||||||
|
testColor(`insert element div.test before ${beforeElement.id}`, expectedColorForClassTest);
|
||||||
|
|
||||||
|
newElement.classList.remove('test');
|
||||||
|
testColor(`remove the class 'test' from the element inserted before ${beforeElement.id}`, grey);
|
||||||
|
|
||||||
|
newElement.classList.add('test');
|
||||||
|
testColor(`add the class 'test' again to the element inserted before ${beforeElement.id}`, expectedColorForClassTest);
|
||||||
|
|
||||||
|
newElement.remove();
|
||||||
|
testColor(`remove element div.test before ${beforeElement.id}`, grey);
|
||||||
|
|
||||||
|
newElement.classList.remove('test')
|
||||||
|
|
||||||
|
beforeElement.before(newElement);
|
||||||
|
testColor(`insert element div before ${beforeElement.id}`, grey);
|
||||||
|
|
||||||
|
newElement.classList.add('test');
|
||||||
|
testColor(`add the class 'test' to the element inserted again before ${beforeElement.id}`, expectedColorForClassTest);
|
||||||
|
|
||||||
|
newElement.classList.remove('test');
|
||||||
|
testColor(`remove the class 'test' from the element inserted again before ${beforeElement.id}`, grey);
|
||||||
|
|
||||||
|
newElement.remove();
|
||||||
|
testColor(`remove element div before ${beforeElement.id}`, grey);
|
||||||
|
|
||||||
|
newElement.setAttribute('test_attr', '');
|
||||||
|
|
||||||
|
beforeElement.before(newElement);
|
||||||
|
testColor(`insert element div[test_attr] before ${beforeElement.id}`, expectedColorForAttributeTest);
|
||||||
|
|
||||||
|
newElement.remove();
|
||||||
|
testColor(`remove element div[test_attr] before ${beforeElement.id}`, grey);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testElementInsertionAfter(afterElement, expectedColorName)
|
||||||
|
{
|
||||||
|
const expectedColorForClassTest = colors[expectedColorName].classTest;
|
||||||
|
const expectedColorForAttributeTest = colors[expectedColorName].attributeTest;
|
||||||
|
const newElement = document.createElement('div');
|
||||||
|
newElement.classList.add('test')
|
||||||
|
|
||||||
|
afterElement.after(newElement);
|
||||||
|
testColor(`insert element div.test after ${afterElement.id}`, expectedColorForClassTest);
|
||||||
|
|
||||||
|
newElement.classList.remove('test');
|
||||||
|
testColor(`remove the class 'test' from the element inserted after ${afterElement.id}`, grey);
|
||||||
|
|
||||||
|
newElement.classList.add('test');
|
||||||
|
testColor(`add the class 'test' again to the element inserted after ${afterElement.id}`, expectedColorForClassTest);
|
||||||
|
|
||||||
|
newElement.remove();
|
||||||
|
testColor(`remove element div.test after ${afterElement.id}`, grey);
|
||||||
|
|
||||||
|
newElement.classList.remove('test');
|
||||||
|
|
||||||
|
afterElement.after(newElement);
|
||||||
|
testColor(`insert element div after ${afterElement.id}`, grey);
|
||||||
|
|
||||||
|
newElement.classList.add('test');
|
||||||
|
testColor(`add the class 'test' to the element inserted again after ${afterElement.id}`, expectedColorForClassTest);
|
||||||
|
|
||||||
|
newElement.classList.remove('test');
|
||||||
|
testColor(`remove the class 'test' from the element inserted again after ${afterElement.id}`, grey);
|
||||||
|
|
||||||
|
newElement.remove();
|
||||||
|
testColor(`remove element div after ${afterElement.id}`, grey);
|
||||||
|
|
||||||
|
newElement.setAttribute('test_attr', '');
|
||||||
|
|
||||||
|
afterElement.after(newElement);
|
||||||
|
testColor(`insert element div[test_attr] after ${afterElement.id}`, expectedColorForAttributeTest);
|
||||||
|
|
||||||
|
newElement.remove();
|
||||||
|
testColor(`remove element div[test_attr] after ${afterElement.id}`, grey);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testTreeInsertionBefore(beforeElement, expectedColorName)
|
||||||
|
{
|
||||||
|
const expectedColorForClassTest = colors[expectedColorName].classTest;
|
||||||
|
const expectedColorForAttributeTest = colors[expectedColorName].attributeTest;
|
||||||
|
const newElement = document.createElement('div');
|
||||||
|
const newChild = document.createElement('div');
|
||||||
|
newChild.classList.add('test');
|
||||||
|
newElement.appendChild(newChild);
|
||||||
|
|
||||||
|
beforeElement.before(newElement);
|
||||||
|
testColor(`insert tree div>div.test before ${beforeElement.id}`, expectedColorForClassTest);
|
||||||
|
|
||||||
|
newChild.classList.remove('test');
|
||||||
|
testColor(`remove the class 'test' from the element in the tree inserted before ${beforeElement.id}`, grey);
|
||||||
|
|
||||||
|
newChild.classList.add('test');
|
||||||
|
testColor(`add the class 'test' again to the element in the tree inserted before ${beforeElement.id}`, expectedColorForClassTest);
|
||||||
|
|
||||||
|
newElement.remove();
|
||||||
|
testColor(`remove tree div>div.test before ${beforeElement.id}`, grey);
|
||||||
|
|
||||||
|
newChild.classList.remove('test');
|
||||||
|
|
||||||
|
beforeElement.before(newElement);
|
||||||
|
testColor(`insert tree div>div before ${beforeElement.id}`, grey);
|
||||||
|
|
||||||
|
newChild.classList.add('test');
|
||||||
|
testColor(`add the class 'test' to the element in the tree inserted again before ${beforeElement.id}`, expectedColorForClassTest);
|
||||||
|
|
||||||
|
newChild.classList.remove('test');
|
||||||
|
testColor(`remove the class 'test' from the element in the tree inserted again before ${beforeElement.id}`, grey);
|
||||||
|
|
||||||
|
newElement.remove();
|
||||||
|
testColor(`remove tree div>div before ${beforeElement.id}`, grey);
|
||||||
|
|
||||||
|
newChild.setAttribute('test_attr', '');
|
||||||
|
|
||||||
|
beforeElement.before(newElement);
|
||||||
|
testColor(`insert element div>div[test_attr] before ${beforeElement.id}`, expectedColorForAttributeTest);
|
||||||
|
|
||||||
|
newElement.remove();
|
||||||
|
testColor(`remove element div>div[test_attr] before ${beforeElement.id}`, grey);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testTreeInsertionAfter(afterElement, expectedColorName)
|
||||||
|
{
|
||||||
|
const expectedColorForClassTest = colors[expectedColorName].classTest;
|
||||||
|
const expectedColorForAttributeTest = colors[expectedColorName].attributeTest;
|
||||||
|
const newElement = document.createElement('div');
|
||||||
|
const newChild = document.createElement('div');
|
||||||
|
newChild.classList.add('test');
|
||||||
|
newElement.appendChild(newChild);
|
||||||
|
|
||||||
|
afterElement.after(newElement);
|
||||||
|
testColor(`insert tree div>div.test after ${afterElement.id}`, expectedColorForClassTest);
|
||||||
|
|
||||||
|
newChild.classList.remove('test');
|
||||||
|
testColor(`remove the class 'test' from the element in the tree inserted after ${afterElement.id}`, grey);
|
||||||
|
|
||||||
|
newChild.classList.add('test');
|
||||||
|
testColor(`add the class 'test' again to the element in the tree inserted after ${afterElement.id}`, expectedColorForClassTest);
|
||||||
|
|
||||||
|
newElement.remove();
|
||||||
|
testColor(`remove tree div>div.test after ${afterElement.id}`, grey);
|
||||||
|
|
||||||
|
newChild.classList.remove('test');
|
||||||
|
|
||||||
|
afterElement.after(newElement);
|
||||||
|
testColor(`insert tree div>div after ${afterElement.id}`, grey);
|
||||||
|
|
||||||
|
newChild.classList.add('test');
|
||||||
|
testColor(`add the class 'test' to the element in the tree inserted again after ${afterElement.id}`, expectedColorForClassTest);
|
||||||
|
|
||||||
|
newChild.classList.remove('test');
|
||||||
|
testColor(`remove the class 'test' from the element in the tree inserted again after ${afterElement.id}`, grey);
|
||||||
|
|
||||||
|
newElement.remove();
|
||||||
|
testColor(`remove tree div>div after ${afterElement.id}`, grey);
|
||||||
|
|
||||||
|
newChild.setAttribute('test_attr', '');
|
||||||
|
|
||||||
|
afterElement.after(newElement);
|
||||||
|
testColor(`insert element div>div[test_attr] after ${afterElement.id}`, expectedColorForAttributeTest);
|
||||||
|
|
||||||
|
newElement.remove();
|
||||||
|
testColor(`remove element div>div[test_attr] after ${afterElement.id}`, grey);
|
||||||
|
}
|
||||||
|
|
||||||
|
testColor('Initial color', grey);
|
||||||
|
|
||||||
|
testClassChange(previous_sibling, "grey");
|
||||||
|
testClassChange(previous_sibling_child, "green");
|
||||||
|
testClassChange(previous_sibling_descendant, "red");
|
||||||
|
testClassChange(subject, "blue");
|
||||||
|
testClassChange(next_sibling, "yellow");
|
||||||
|
testClassChange(next_sibling_child, "purple");
|
||||||
|
testClassChange(next_sibling_descendant, "purple");
|
||||||
|
|
||||||
|
testElementInsertionBefore(previous_sibling, "grey");
|
||||||
|
testElementInsertionBefore(previous_sibling_child, "green");
|
||||||
|
testElementInsertionBefore(previous_sibling_descendant, "red");
|
||||||
|
testElementInsertionBefore(subject, "blue");
|
||||||
|
testElementInsertionBefore(next_sibling, "yellow");
|
||||||
|
testElementInsertionBefore(next_sibling_child, "purple");
|
||||||
|
testElementInsertionBefore(next_sibling_descendant, "purple");
|
||||||
|
|
||||||
|
testElementInsertionAfter(previous_sibling, "blue");
|
||||||
|
testElementInsertionAfter(previous_sibling_child, "green");
|
||||||
|
testElementInsertionAfter(previous_sibling_descendant, "red");
|
||||||
|
testElementInsertionAfter(subject, "yellow");
|
||||||
|
testElementInsertionAfter(next_sibling, "yellow");
|
||||||
|
testElementInsertionAfter(next_sibling_child, "purple");
|
||||||
|
testElementInsertionAfter(next_sibling_descendant, "purple");
|
||||||
|
|
||||||
|
testTreeInsertionBefore(previous_sibling, "green");
|
||||||
|
testTreeInsertionBefore(previous_sibling_child, "red");
|
||||||
|
testTreeInsertionBefore(previous_sibling_descendant, "red");
|
||||||
|
testTreeInsertionBefore(subject, "pink");
|
||||||
|
testTreeInsertionBefore(next_sibling, "purple");
|
||||||
|
testTreeInsertionBefore(next_sibling_child, "purple");
|
||||||
|
testTreeInsertionBefore(next_sibling_descendant, "purple");
|
||||||
|
|
||||||
|
testTreeInsertionAfter(previous_sibling, "pink");
|
||||||
|
testTreeInsertionAfter(previous_sibling_child, "red");
|
||||||
|
testTreeInsertionAfter(previous_sibling_descendant, "red");
|
||||||
|
testTreeInsertionAfter(subject, "purple");
|
||||||
|
testTreeInsertionAfter(next_sibling, "purple");
|
||||||
|
testTreeInsertionAfter(next_sibling_child, "purple");
|
||||||
|
testTreeInsertionAfter(next_sibling_descendant, "purple");
|
||||||
|
|
||||||
|
</script>
|
|
@ -0,0 +1,31 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>:has() invalidation after removing non-first element</title>
|
||||||
|
<link rel="author" title="Byungwoo Lee" href="mailto:blee@igalia.com">
|
||||||
|
<script src="../../../resources/testharness.js"></script>
|
||||||
|
<script src="../../../resources/testharnessreport.js"></script>
|
||||||
|
<link rel="help" href="https://drafts.csswg.org/selectors/#relational">
|
||||||
|
<style>
|
||||||
|
div, main { color: grey }
|
||||||
|
#subject:has(descendant) { color: red }
|
||||||
|
</style>
|
||||||
|
<main id="main">
|
||||||
|
<div id="subject">
|
||||||
|
<div></div>
|
||||||
|
<descendant id="descendant"></descendant>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
<script>
|
||||||
|
let grey = 'rgb(128, 128, 128)';
|
||||||
|
let red = 'rgb(255, 0, 0)';
|
||||||
|
|
||||||
|
function test_div(test_name, el, color) {
|
||||||
|
test(function() {
|
||||||
|
assert_equals(getComputedStyle(el).color, color);
|
||||||
|
}, test_name + ': div#' + el.id + '.color');
|
||||||
|
}
|
||||||
|
|
||||||
|
test_div('initial_color', subject, red);
|
||||||
|
subject.removeChild(descendant);
|
||||||
|
test_div('remove descendant', subject, grey);
|
||||||
|
</script>
|
|
@ -0,0 +1,42 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>:has() invalidation for wiping an element by means of innerHTML</title>
|
||||||
|
<link rel="author" title="Byungwoo Lee" href="mailto:blee@igalia.com">
|
||||||
|
<script src="../../../resources/testharness.js"></script>
|
||||||
|
<script src="../../../resources/testharnessreport.js"></script>
|
||||||
|
<link rel="help" href="https://drafts.csswg.org/selectors/#relational">
|
||||||
|
<style>
|
||||||
|
div, main { color: grey }
|
||||||
|
.subject:has(.descendant) { color: green}
|
||||||
|
</style>
|
||||||
|
<main id=main>
|
||||||
|
<div id="subject" class="subject"></div>
|
||||||
|
</main>
|
||||||
|
<script>
|
||||||
|
let grey = 'rgb(128, 128, 128)';
|
||||||
|
let green = 'rgb(0, 128, 0)';
|
||||||
|
|
||||||
|
function test_div(test_name, el, color) {
|
||||||
|
test(function() {
|
||||||
|
assert_equals(getComputedStyle(el).color, color);
|
||||||
|
}, test_name + ': div#' + el.id + '.color');
|
||||||
|
}
|
||||||
|
|
||||||
|
test_div('initial color', subject, grey);
|
||||||
|
|
||||||
|
subject.innerHTML = "This is a text <div><div class='descendant'></div></div>";
|
||||||
|
|
||||||
|
test_div('color after inserting text and div > .descendant', subject, green);
|
||||||
|
|
||||||
|
subject.innerHTML = "This is a text";
|
||||||
|
|
||||||
|
test_div('color after wiping #child to remove div > .descendant', subject, grey);
|
||||||
|
|
||||||
|
subject.innerHTML = "<div id='child'> This is a text <div class='descendant'></div></div>";
|
||||||
|
|
||||||
|
test_div('color after inserting text and #child > .descendant', subject, green);
|
||||||
|
|
||||||
|
child.innerHTML = "This is a text";
|
||||||
|
|
||||||
|
test_div('color after wiping #child to remove .descendant', subject, grey);
|
||||||
|
</script>
|
|
@ -0,0 +1,209 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>:has() invalidation for sibling insertion and removal</title>
|
||||||
|
<link rel="author" title="Byungwoo Lee" href="mailto:blee@igalia.com">
|
||||||
|
<script src="../../../resources/testharness.js"></script>
|
||||||
|
<script src="../../../resources/testharnessreport.js"></script>
|
||||||
|
<link rel="help" href="https://drafts.csswg.org/selectors/#relational">
|
||||||
|
<style>
|
||||||
|
div, main { color: grey }
|
||||||
|
#subject1:has(+ #sibling1_1 + #sibling1_2) { color: red }
|
||||||
|
#subject2:has(+ #sibling2_2) { color: green }
|
||||||
|
#subject3:has(+ #sibling3_1 + #sibling3_2 > #siblingchild3_2_1) { color: blue }
|
||||||
|
#subject4:has(+ #sibling4_2 > #siblingchild4_2_1) { color: yellow }
|
||||||
|
#subject5:has(+ #sibling5_1 + #sibling5_2) { color: red }
|
||||||
|
#subject6:has(+ #sibling6_2) { color: green }
|
||||||
|
#subject7:has(+ #sibling7_1 + #sibling7_2 > #siblingchild7_2_1) { color: blue }
|
||||||
|
#subject8:has(+ #sibling8_2 > #siblingchild8_2_1) { color: yellow }
|
||||||
|
#subject9:has(+ #sibling9_1 + #sibling9_2 ~ #sibling9_3) { color: red }
|
||||||
|
#subject10:has(+ #sibling10_2 ~ #sibling10_3) { color: green }
|
||||||
|
#subject11:has(+ #sibling11_1 + #sibling11_2 ~ #sibling11_3 > #siblingchild11_3_1) { color: blue }
|
||||||
|
#subject12:has(+ #sibling12_2 ~ #sibling12_3 > #siblingchild12_3_1) { color: yellow }
|
||||||
|
.sibling13:has(~ .sibling13) { color: green }
|
||||||
|
#subject14:has(~ #sibling14_1 ~ #sibling14_2 ~ #sibling14_3) { color: green }
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<main id="main">
|
||||||
|
<div id="parent1">
|
||||||
|
<div id="subject1"></div>
|
||||||
|
<div id="sibling1_2"></div>
|
||||||
|
<div id="sibling1_3"></div>
|
||||||
|
</div>
|
||||||
|
<div id="parent2">
|
||||||
|
<div id="subject2"></div>
|
||||||
|
<div id="sibling2_1"></div>
|
||||||
|
<div id="sibling2_2"></div>
|
||||||
|
<div id="sibling2_3""></div>
|
||||||
|
</div>
|
||||||
|
<div id="parent3">
|
||||||
|
<div id="subject3"></div>
|
||||||
|
<div id="sibling3_2">
|
||||||
|
<div id="siblingchild3_2_1"></div>
|
||||||
|
</div>
|
||||||
|
<div id="sibling3_3"></div>
|
||||||
|
</div>
|
||||||
|
<div id="parent4">
|
||||||
|
<div id="subject4"></div>
|
||||||
|
<div id="sibling4_1"></div>
|
||||||
|
<div id="sibling4_2">
|
||||||
|
<div id="siblingchild4_2_1"></div>
|
||||||
|
</div>
|
||||||
|
<div id="sibling4_3"></div>
|
||||||
|
</div>
|
||||||
|
<div id="parent5">
|
||||||
|
<div id="subject5"></div>
|
||||||
|
<div id="sibling5_1"></div>
|
||||||
|
<div id="sibling5_2"></div>
|
||||||
|
<div id="sibling5_3""></div>
|
||||||
|
</div>
|
||||||
|
<div id="parent6">
|
||||||
|
<div id="subject6"></div>
|
||||||
|
<div id="sibling6_2"></div>
|
||||||
|
<div id="sibling6_3"></div>
|
||||||
|
</div>
|
||||||
|
<div id="parent7">
|
||||||
|
<div id="subject7"></div>
|
||||||
|
<div id="sibling7_1"></div>
|
||||||
|
<div id="sibling7_2">
|
||||||
|
<div id="siblingchild7_2_1"></div>
|
||||||
|
</div>
|
||||||
|
<div id="sibling7_3"></div>
|
||||||
|
<div id="parent8">
|
||||||
|
<div id="subject8"></div>
|
||||||
|
<div id="sibling8_2">
|
||||||
|
<div id="siblingchild8_2_1"></div>
|
||||||
|
</div>
|
||||||
|
<div id="sibling8_3"></div>
|
||||||
|
</div>
|
||||||
|
<div id="parent9">
|
||||||
|
<div id="subject9"></div>
|
||||||
|
<div id="sibling9_2"></div>
|
||||||
|
<div id="sibling9_3"></div>
|
||||||
|
<div id="sibling9_4"></div>
|
||||||
|
</div>
|
||||||
|
<div id="parent10">
|
||||||
|
<div id="subject10"></div>
|
||||||
|
<div id="sibling10_1"></div>
|
||||||
|
<div id="sibling10_2"></div>
|
||||||
|
<div id="sibling10_3""></div>
|
||||||
|
<div id="sibling10_4""></div>
|
||||||
|
</div>
|
||||||
|
<div id="parent11">
|
||||||
|
<div id="subject11"></div>
|
||||||
|
<div id="sibling11_2"></div>
|
||||||
|
<div id="sibling11_3">
|
||||||
|
<div id="siblingchild11_3_1"></div>
|
||||||
|
</div>
|
||||||
|
<div id="sibling11_4"></div>
|
||||||
|
</div>
|
||||||
|
<div id="parent12">
|
||||||
|
<div id="subject12"></div>
|
||||||
|
<div id="sibling12_1"></div>
|
||||||
|
<div id="sibling12_2"></div>
|
||||||
|
<div id="sibling12_3">
|
||||||
|
<div id="siblingchild12_3_1"></div>
|
||||||
|
</div>
|
||||||
|
<div id="sibling12_4"></div>
|
||||||
|
</div>
|
||||||
|
<div id="parent13">
|
||||||
|
<div class="sibling13"></div>
|
||||||
|
<div id="subject13" class="sibling13"></div>
|
||||||
|
</div>
|
||||||
|
<div id="parent14">
|
||||||
|
<div id="subject14"></div>
|
||||||
|
<div id="sibling14_1"></div>
|
||||||
|
<div id="sibling14_2"></div>
|
||||||
|
<div id="sibling14_3"></div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
<script>
|
||||||
|
|
||||||
|
const grey = 'rgb(128, 128, 128)';
|
||||||
|
const red = 'rgb(255, 0, 0)';
|
||||||
|
const green = 'rgb(0, 128, 0)';
|
||||||
|
const blue = 'rgb(0, 0, 255)';
|
||||||
|
const yellow = 'rgb(255, 255, 0)';
|
||||||
|
|
||||||
|
function testColor(test_name, element, color) {
|
||||||
|
test(function() {
|
||||||
|
assert_equals(getComputedStyle(element).color, color);
|
||||||
|
}, test_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
function insertBefore(parent, reference, child_id) {
|
||||||
|
var child = document.createElement("div");
|
||||||
|
child.id = child_id;
|
||||||
|
parent.insertBefore(child, reference);
|
||||||
|
}
|
||||||
|
|
||||||
|
testColor(`subject1: initial color should be ${grey}`, subject1, grey);
|
||||||
|
insertBefore(parent1, sibling1_2, "sibling1_1");
|
||||||
|
testColor(`subject1: color after #sibling1_1 inserted should be ${red}`,
|
||||||
|
subject1, red);
|
||||||
|
|
||||||
|
testColor(`subject2: initial color should be ${grey}`, subject2, grey);
|
||||||
|
sibling2_1.remove();
|
||||||
|
testColor(`subject2: color after #sibling2_1 removed should be ${green}`,
|
||||||
|
subject2, green);
|
||||||
|
|
||||||
|
testColor(`subject3: initial color should be ${grey}`, subject3, grey);
|
||||||
|
insertBefore(parent3, sibling3_2, "sibling3_1");
|
||||||
|
testColor(`subject3: color after #sibling3_1 inserted should be ${blue}`,
|
||||||
|
subject3, blue);
|
||||||
|
|
||||||
|
testColor(`subject4: initial color should be ${grey}`, subject4, grey);
|
||||||
|
sibling4_1.remove();
|
||||||
|
testColor(`subject4: color after #sibling4_1 removed should be ${yellow}`,
|
||||||
|
subject4, yellow);
|
||||||
|
|
||||||
|
testColor(`subject5: initial color should be ${red}`, subject5, red);
|
||||||
|
sibling5_1.remove();
|
||||||
|
testColor(`subject5: color after #sibling5_1 removed should be ${grey}`,
|
||||||
|
subject5, grey);
|
||||||
|
|
||||||
|
testColor(`subject6: initial color should be ${green}`, subject6, green);
|
||||||
|
insertBefore(parent6, sibling6_2, "sibling6_1");
|
||||||
|
testColor(`subject6: color after #sibling6_1 inserted should be ${grey}`,
|
||||||
|
subject6, grey);
|
||||||
|
|
||||||
|
testColor(`subject7: initial color should be ${blue}`, subject7, blue);
|
||||||
|
sibling7_1.remove();
|
||||||
|
testColor(`subject7: color after #sibling7_1 removed should be ${grey}`,
|
||||||
|
subject7, grey);
|
||||||
|
|
||||||
|
testColor(`subject8: initial color should be ${yellow}`, subject8, yellow);
|
||||||
|
insertBefore(parent8, sibling8_2, "sibling8_1");
|
||||||
|
testColor(`subject8: color after #sibling8_1 inserted should be ${grey}`,
|
||||||
|
subject8, grey);
|
||||||
|
|
||||||
|
testColor(`subject9: initial color should be ${grey}`, subject9, grey);
|
||||||
|
insertBefore(parent9, sibling9_2, "sibling9_1");
|
||||||
|
testColor(`subject9: color after #sibling9_1 inserted should be ${red}`,
|
||||||
|
subject1, red);
|
||||||
|
|
||||||
|
testColor(`subject10: initial color should be ${grey}`, subject10, grey);
|
||||||
|
sibling10_1.remove();
|
||||||
|
testColor(`subject10: color after #sibling10_1 removed should be ${green}`,
|
||||||
|
subject10, green);
|
||||||
|
|
||||||
|
testColor(`subject11: initial color should be ${grey}`, subject11, grey);
|
||||||
|
insertBefore(parent11, sibling11_2, "sibling11_1");
|
||||||
|
testColor(`subject11: color after #sibling11_1 inserted should be ${blue}`,
|
||||||
|
subject11, blue);
|
||||||
|
|
||||||
|
testColor(`subject12: initial color should be ${grey}`, subject12, grey);
|
||||||
|
sibling12_1.remove();
|
||||||
|
testColor(`subject12: color after #sibling12_1 removed should be ${yellow}`,
|
||||||
|
subject12, yellow);
|
||||||
|
|
||||||
|
testColor(`subject13: initial color should be ${grey}`, subject13, grey);
|
||||||
|
const d = document.createElement("div");
|
||||||
|
d.classList.add("sibling13");
|
||||||
|
parent13.appendChild(d);
|
||||||
|
testColor(`subject13: color after #sibling12_1 removed should be ${green}`,
|
||||||
|
subject13, green);
|
||||||
|
|
||||||
|
testColor(`subject14: initial color should be ${green}`, subject14, green);
|
||||||
|
sibling14_2.remove();
|
||||||
|
testColor(`subject14: color after #sibling14_2 removed should be ${grey}`, subject14, grey);
|
||||||
|
</script>
|
|
@ -0,0 +1,149 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>CSS Selector Invalidation: :has() with sibling combinator argument</title>
|
||||||
|
<link rel="author" title="Antti Koivisto" href="mailto:antti@apple.com">
|
||||||
|
<script src="../../../resources/testharness.js"></script>
|
||||||
|
<script src="../../../resources/testharnessreport.js"></script>
|
||||||
|
<link rel="help" href="https://drafts.csswg.org/selectors/#relational">
|
||||||
|
<style>
|
||||||
|
div, main { color: grey }
|
||||||
|
#subject:has(~ .test) { color: red }
|
||||||
|
#subject:has(+ .test) { color: green }
|
||||||
|
#subject:has(~ div .test) { color: blue }
|
||||||
|
#subject:has(~ div > .test) { color: purple }
|
||||||
|
#subject:has(+ div .test) { color: yellow }
|
||||||
|
#subject:has(+ div > .test) { color: pink }
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<main id=main>
|
||||||
|
<div id=subject></div>
|
||||||
|
<div id=first_sibling>
|
||||||
|
<div id=first_sibling_child>
|
||||||
|
<div id=first_sibling_descendant></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id=second_sibling></div>
|
||||||
|
<div id=third_sibling>
|
||||||
|
<div id=third_sibling_child>
|
||||||
|
<div id=third_sibling_descendant></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
<script>
|
||||||
|
|
||||||
|
const grey = 'rgb(128, 128, 128)';
|
||||||
|
const red = 'rgb(255, 0, 0)';
|
||||||
|
const green = 'rgb(0, 128, 0)';
|
||||||
|
const blue = 'rgb(0, 0, 255)';
|
||||||
|
const yellow = 'rgb(255, 255, 0)';
|
||||||
|
const purple = 'rgb(128, 0, 128)';
|
||||||
|
const pink = 'rgb(255, 192, 203)';
|
||||||
|
|
||||||
|
function testColor(test_name, color) {
|
||||||
|
test(function() {
|
||||||
|
assert_equals(getComputedStyle(subject).color, color);
|
||||||
|
}, test_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testClassChange(element, expectedColor)
|
||||||
|
{
|
||||||
|
element.classList.add('test');
|
||||||
|
testColor(`add .test to ${element.id}`, expectedColor);
|
||||||
|
element.classList.remove('test');
|
||||||
|
testColor(`remove .test from ${element.id}`, grey);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testElementInsertionBefore(beforeElement, expectedColor)
|
||||||
|
{
|
||||||
|
const newElement = document.createElement('div');
|
||||||
|
newElement.classList.add('test')
|
||||||
|
|
||||||
|
beforeElement.before(newElement);
|
||||||
|
testColor(`insert element div.test before ${beforeElement.id}`, expectedColor);
|
||||||
|
|
||||||
|
newElement.remove();
|
||||||
|
testColor(`remove element div.test before ${beforeElement.id}`, grey);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testElementInsertionAfter(afterElement, expectedColor)
|
||||||
|
{
|
||||||
|
const newElement = document.createElement('div');
|
||||||
|
newElement.classList.add('test')
|
||||||
|
|
||||||
|
afterElement.after(newElement);
|
||||||
|
testColor(`insert element div.test after ${afterElement.id}`, expectedColor);
|
||||||
|
|
||||||
|
newElement.remove();
|
||||||
|
testColor(`remove element div.test after ${afterElement.id}`, grey);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testTreeInsertionBefore(beforeElement, expectedColor)
|
||||||
|
{
|
||||||
|
const newElement = document.createElement('div');
|
||||||
|
const newChild = document.createElement('div');
|
||||||
|
newChild.classList.add('test');
|
||||||
|
newElement.appendChild(newChild);
|
||||||
|
|
||||||
|
beforeElement.before(newElement);
|
||||||
|
testColor(`insert tree div>div.test before ${beforeElement.id}`, expectedColor);
|
||||||
|
|
||||||
|
newElement.remove();
|
||||||
|
testColor(`remove tree div>div.test before ${beforeElement.id}`, grey);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testTreeInsertionAfter(afterElement, expectedColor)
|
||||||
|
{
|
||||||
|
const newElement = document.createElement('div');
|
||||||
|
const newChild = document.createElement('div');
|
||||||
|
newChild.classList.add('test');
|
||||||
|
newElement.appendChild(newChild);
|
||||||
|
|
||||||
|
afterElement.after(newElement);
|
||||||
|
testColor(`insert tree div>div.test after ${afterElement.id}`, expectedColor);
|
||||||
|
|
||||||
|
newElement.remove();
|
||||||
|
testColor(`remove tree div>div.test after ${afterElement.id}`, grey);
|
||||||
|
}
|
||||||
|
|
||||||
|
testColor('initial_color', grey);
|
||||||
|
|
||||||
|
testClassChange(first_sibling, green);
|
||||||
|
testClassChange(second_sibling, red);
|
||||||
|
testClassChange(third_sibling, red);
|
||||||
|
testClassChange(first_sibling_child, pink);
|
||||||
|
testClassChange(first_sibling_descendant, yellow);
|
||||||
|
testClassChange(third_sibling_child, purple);
|
||||||
|
testClassChange(third_sibling_descendant, blue);
|
||||||
|
|
||||||
|
testElementInsertionBefore(first_sibling, green);
|
||||||
|
testElementInsertionBefore(second_sibling, red);
|
||||||
|
testElementInsertionBefore(third_sibling, red);
|
||||||
|
testElementInsertionBefore(first_sibling_child, pink);
|
||||||
|
testElementInsertionBefore(first_sibling_descendant, yellow);
|
||||||
|
testElementInsertionBefore(third_sibling_child, purple);
|
||||||
|
testElementInsertionBefore(third_sibling_descendant, blue);
|
||||||
|
|
||||||
|
testElementInsertionAfter(first_sibling, red);
|
||||||
|
testElementInsertionAfter(second_sibling, red);
|
||||||
|
testElementInsertionAfter(third_sibling, red);
|
||||||
|
testElementInsertionAfter(first_sibling_child, pink);
|
||||||
|
testElementInsertionAfter(first_sibling_descendant, yellow);
|
||||||
|
testElementInsertionAfter(third_sibling_child, purple);
|
||||||
|
testElementInsertionAfter(third_sibling_descendant, blue);
|
||||||
|
|
||||||
|
testTreeInsertionBefore(first_sibling, pink);
|
||||||
|
testTreeInsertionBefore(second_sibling, purple);
|
||||||
|
testTreeInsertionBefore(third_sibling, purple);
|
||||||
|
testTreeInsertionBefore(first_sibling_child, yellow);
|
||||||
|
testTreeInsertionBefore(first_sibling_descendant, yellow);
|
||||||
|
testTreeInsertionBefore(third_sibling_child, blue);
|
||||||
|
testTreeInsertionBefore(third_sibling_descendant, blue);
|
||||||
|
|
||||||
|
testTreeInsertionAfter(first_sibling, purple);
|
||||||
|
testTreeInsertionAfter(second_sibling, purple);
|
||||||
|
testTreeInsertionAfter(third_sibling, purple);
|
||||||
|
testTreeInsertionAfter(first_sibling_child, yellow);
|
||||||
|
testTreeInsertionAfter(first_sibling_descendant, yellow);
|
||||||
|
testTreeInsertionAfter(third_sibling_child, blue);
|
||||||
|
testTreeInsertionAfter(third_sibling_descendant, blue);
|
||||||
|
</script>
|
|
@ -0,0 +1,43 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>CSS Selector Invalidation: Invalidate :has() as result of insertion/removal</title>
|
||||||
|
<link rel="author" title="David Shin" href="mailto:dshin@mozilla.com">
|
||||||
|
<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
|
||||||
|
<script src="../../../resources/testharness.js"></script>
|
||||||
|
<script src="../../../resources/testharnessreport.js"></script>
|
||||||
|
<link rel="help" href="https://drafts.csswg.org/selectors/#relational">
|
||||||
|
<style>
|
||||||
|
div, main { color: grey }
|
||||||
|
#subject:has(+ #next_sibling) { color: red; }
|
||||||
|
#prev_sibling:has(+ #subject + #next_sibling) { color: green; }
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<main id=main>
|
||||||
|
<div id=prev_sibling></div>
|
||||||
|
<div id=subject></div>
|
||||||
|
<div id=blocks_match></div>
|
||||||
|
<div id=next_sibling></div>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const grey = 'rgb(128, 128, 128)';
|
||||||
|
const red = 'rgb(255, 0, 0)';
|
||||||
|
const green = 'rgb(0, 128, 0)';
|
||||||
|
|
||||||
|
function testColors(test_name, subject_color, prev_sibling_color) {
|
||||||
|
test(function() {
|
||||||
|
assert_equals(getComputedStyle(subject).color, subject_color);
|
||||||
|
assert_equals(getComputedStyle(prev_sibling).color, prev_sibling_color);
|
||||||
|
}, test_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
testColors('Initial colors', grey, grey);
|
||||||
|
|
||||||
|
const d = blocks_match;
|
||||||
|
d.remove();
|
||||||
|
|
||||||
|
testColors('Matches after #blocks_match removed', red, green);
|
||||||
|
subject.after(d);
|
||||||
|
|
||||||
|
testColors('Does not match after #blocks_match added', grey, grey);
|
||||||
|
</script>
|
|
@ -0,0 +1,77 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>CSS Selector Invalidation: :has() affected by unstyled elements</title>
|
||||||
|
<link rel="author" title="David Shin" href="mailto:dshin@mozilla.com">
|
||||||
|
<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
|
||||||
|
<script src="../../../resources/testharness.js"></script>
|
||||||
|
<script src="../../../resources/testharnessreport.js"></script>
|
||||||
|
<link rel="help" href="https://drafts.csswg.org/selectors/#relational">
|
||||||
|
<style>
|
||||||
|
div, main { color: grey }
|
||||||
|
.none { display: none; }
|
||||||
|
#subject:has(.test) { color: red; }
|
||||||
|
#subject:has(~ #sibling .test) { color: green; }
|
||||||
|
#subject:has(:is(.test_inner #subject_descendant)) { color: blue; }
|
||||||
|
#subject:has(~ #sibling :is(.test_inner #sibling_descendant)) { color: yellow; }
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<main id=main>
|
||||||
|
<div id=subject>
|
||||||
|
<div id=subject_child class="none">
|
||||||
|
<div id=subject_descendant></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id=sibling class="none">
|
||||||
|
<div id=sibling_child>
|
||||||
|
<div id=sibling_descendant></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const grey = 'rgb(128, 128, 128)';
|
||||||
|
const red = 'rgb(255, 0, 0)';
|
||||||
|
const green = 'rgb(0, 128, 0)';
|
||||||
|
const blue = 'rgb(0, 0, 255)';
|
||||||
|
const yellow = "rgb(255, 255, 0)";
|
||||||
|
const colors = {
|
||||||
|
grey: {
|
||||||
|
classTest: grey,
|
||||||
|
},
|
||||||
|
red: {
|
||||||
|
classTest: red,
|
||||||
|
},
|
||||||
|
green: {
|
||||||
|
classTest: green,
|
||||||
|
},
|
||||||
|
blue: {
|
||||||
|
classTest: blue,
|
||||||
|
},
|
||||||
|
yellow: {
|
||||||
|
classTest: yellow,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
function testColor(test_name, color) {
|
||||||
|
test(function() {
|
||||||
|
assert_equals(getComputedStyle(subject).color, color);
|
||||||
|
}, test_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testClassChange(element, cls, expectedColorName)
|
||||||
|
{
|
||||||
|
const expectedColorForClassTest = colors[expectedColorName].classTest;
|
||||||
|
element.classList.add(cls);
|
||||||
|
testColor(`add ${cls} to ${element.id}`, expectedColorForClassTest);
|
||||||
|
element.classList.remove(cls);
|
||||||
|
testColor(`remove ${cls} from ${element.id}`, grey);
|
||||||
|
}
|
||||||
|
|
||||||
|
testColor('Initial color', grey);
|
||||||
|
|
||||||
|
testClassChange(subject_descendant, 'test', 'red');
|
||||||
|
testClassChange(sibling_descendant, 'test', 'green');
|
||||||
|
testClassChange(subject_child, 'test_inner', 'blue');
|
||||||
|
testClassChange(sibling_child, 'test_inner', 'yellow');
|
||||||
|
|
||||||
|
</script>
|
|
@ -0,0 +1,158 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>CSS Selector Invalidation: :has() with nesting parent containing complex selector</title>
|
||||||
|
<link rel="help" href="https://drafts.csswg.org/selectors/#relational">
|
||||||
|
<script src="../../../resources/testharness.js"></script>
|
||||||
|
<script src="../../../resources/testharnessreport.js"></script>
|
||||||
|
<script src="../../../resources/testdriver.js"></script>
|
||||||
|
<script src="../../../resources/testdriver-actions.js"></script>
|
||||||
|
<script src="../../../resources/testdriver-vendor.js"></script>
|
||||||
|
<style>
|
||||||
|
.anchor { background-color: white; }
|
||||||
|
|
||||||
|
.ancestor .descendant {
|
||||||
|
.anchor:has(&) { background-color: blue; }
|
||||||
|
}
|
||||||
|
|
||||||
|
.ancestor .child {
|
||||||
|
.anchor:has(> &) { background-color: lightblue; }
|
||||||
|
}
|
||||||
|
|
||||||
|
.ancestor_prev ~ div .descendant {
|
||||||
|
.anchor:has(&) { background-color: yellow; }
|
||||||
|
}
|
||||||
|
|
||||||
|
.ancestor_prev ~ div.ancestor .descendant {
|
||||||
|
.anchor:has(&) { background-color: yellowgreen; }
|
||||||
|
}
|
||||||
|
|
||||||
|
.prev ~ .indirect_next {
|
||||||
|
.anchor:has(~ &) { background-color: green; }
|
||||||
|
}
|
||||||
|
|
||||||
|
.prev ~ .direct_next {
|
||||||
|
.anchor:has(+ &) { background-color: lightgreen; }
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<div><div id="grand_parent1">
|
||||||
|
<div id="parent1">
|
||||||
|
<div id="anchor1" class="anchor">
|
||||||
|
<div><div class="descendant"></div></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div></div>
|
||||||
|
<div><div id="grand_parent2">
|
||||||
|
<div id="parent2">
|
||||||
|
<div id="anchor2" class="anchor">
|
||||||
|
<div class="child"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div></div>
|
||||||
|
<div><div id="grand_parent_indirect_prev3"></div>
|
||||||
|
<div id="grand_parent_direct_prev3"></div>
|
||||||
|
<div id="grand_parent3">
|
||||||
|
<div id="parent_indirect_prev3"></div>
|
||||||
|
<div id="parent_direct_prev3"></div>
|
||||||
|
<div id="parent3">
|
||||||
|
<div id="anchor_indirect_prev3"></div>
|
||||||
|
<div id="anchor_direct_prev3"></div>
|
||||||
|
<div id="anchor3" class="anchor">
|
||||||
|
<div><div class="descendant"></div></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div></div>
|
||||||
|
<div><div id="indirect_prev4"></div>
|
||||||
|
<div id="direct_prev4"></div>
|
||||||
|
<div id="anchor4" class="anchor"></div>
|
||||||
|
<div></div><div class="indirect_next">
|
||||||
|
</div></div>
|
||||||
|
<div><div id="indirect_prev5"></div>
|
||||||
|
<div id="direct_prev5"></div>
|
||||||
|
<div id="anchor5" class="anchor"></div>
|
||||||
|
<div class="direct_next">
|
||||||
|
</div></div>
|
||||||
|
<script>
|
||||||
|
const white = "rgb(255, 255, 255)";
|
||||||
|
const blue = "rgb(0, 0, 255)";
|
||||||
|
const lightblue = "rgb(173, 216, 230)";
|
||||||
|
const yellow = "rgb(255, 255, 0)";
|
||||||
|
const yellowgreen = "rgb(154, 205, 50)";
|
||||||
|
const green = "rgb(0, 128, 0)";
|
||||||
|
const lightgreen = "rgb(144, 238, 144)";
|
||||||
|
|
||||||
|
function bg_color(element, color, message) {
|
||||||
|
promise_test(async () => {
|
||||||
|
assert_equals(getComputedStyle(element)['background-color'], color);
|
||||||
|
}, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
function add_class_and_check_bg_color(
|
||||||
|
element_to_add, class_name, has_anchor, color) {
|
||||||
|
promise_test(async () => {
|
||||||
|
element_to_add.classList.add(class_name);
|
||||||
|
assert_equals(getComputedStyle(has_anchor)['background-color'], color);
|
||||||
|
}, `#${has_anchor.id} becomes ${color} after adding .${class_name} to #${element_to_add.id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
function remove_class_and_check_bg_color(
|
||||||
|
element_to_remove, class_name, has_anchor, color) {
|
||||||
|
promise_test(async () => {
|
||||||
|
element_to_remove.classList.remove(class_name);
|
||||||
|
assert_equals(getComputedStyle(has_anchor)['background-color'], color);
|
||||||
|
}, `#${has_anchor.id} becomes ${color} after removing .${class_name} from #${element_to_remove.id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
bg_color(anchor1, white, "#anchor1 initially white");
|
||||||
|
add_class_and_check_bg_color(grand_parent1, "ancestor", anchor1, blue);
|
||||||
|
remove_class_and_check_bg_color(grand_parent1, "ancestor", anchor1, white);
|
||||||
|
add_class_and_check_bg_color(parent1, "ancestor", anchor1, blue);
|
||||||
|
remove_class_and_check_bg_color(parent1, "ancestor", anchor1, white);
|
||||||
|
|
||||||
|
bg_color(anchor2, white, "#anchor2 initially white");
|
||||||
|
add_class_and_check_bg_color(grand_parent2, "ancestor", anchor2, lightblue);
|
||||||
|
remove_class_and_check_bg_color(grand_parent2, "ancestor", anchor2, white);
|
||||||
|
add_class_and_check_bg_color(parent2, "ancestor", anchor2, lightblue);
|
||||||
|
remove_class_and_check_bg_color(parent2, "ancestor", anchor2, white);
|
||||||
|
|
||||||
|
bg_color(anchor3, white, "#anchor3 initially white");
|
||||||
|
add_class_and_check_bg_color(grand_parent_indirect_prev3, "ancestor_prev",
|
||||||
|
anchor3, yellow);
|
||||||
|
add_class_and_check_bg_color(grand_parent3, "ancestor", anchor3, yellowgreen);
|
||||||
|
remove_class_and_check_bg_color(grand_parent3, "ancestor", anchor3, yellow);
|
||||||
|
remove_class_and_check_bg_color(grand_parent_indirect_prev3, "ancestor_prev",
|
||||||
|
anchor3, white);
|
||||||
|
add_class_and_check_bg_color(grand_parent_direct_prev3, "ancestor_prev",
|
||||||
|
anchor3, yellow);
|
||||||
|
remove_class_and_check_bg_color(grand_parent_direct_prev3, "ancestor_prev",
|
||||||
|
anchor3, white);
|
||||||
|
add_class_and_check_bg_color(parent_indirect_prev3, "ancestor_prev",
|
||||||
|
anchor3, yellow);
|
||||||
|
add_class_and_check_bg_color(parent3, "ancestor", anchor3, yellowgreen);
|
||||||
|
remove_class_and_check_bg_color(parent3, "ancestor", anchor3, yellow);
|
||||||
|
remove_class_and_check_bg_color(parent_indirect_prev3, "ancestor_prev",
|
||||||
|
anchor3, white);
|
||||||
|
add_class_and_check_bg_color(parent_direct_prev3, "ancestor_prev",
|
||||||
|
anchor3, yellow);
|
||||||
|
remove_class_and_check_bg_color(parent_direct_prev3, "ancestor_prev",
|
||||||
|
anchor3, white);
|
||||||
|
add_class_and_check_bg_color(anchor_indirect_prev3, "ancestor_prev",
|
||||||
|
anchor3, yellow);
|
||||||
|
remove_class_and_check_bg_color(anchor_indirect_prev3, "ancestor_prev",
|
||||||
|
anchor3, white);
|
||||||
|
add_class_and_check_bg_color(anchor_direct_prev3, "ancestor_prev",
|
||||||
|
anchor3, yellow);
|
||||||
|
remove_class_and_check_bg_color(anchor_direct_prev3, "ancestor_prev",
|
||||||
|
anchor3, white);
|
||||||
|
|
||||||
|
bg_color(anchor4, white, "#anchor4 initially white");
|
||||||
|
add_class_and_check_bg_color(indirect_prev4, "prev", anchor4, green);
|
||||||
|
remove_class_and_check_bg_color(indirect_prev4, "prev", anchor4, white);
|
||||||
|
add_class_and_check_bg_color(direct_prev4, "prev", anchor4, green);
|
||||||
|
remove_class_and_check_bg_color(direct_prev4, "prev", anchor4, white);
|
||||||
|
|
||||||
|
bg_color(anchor5, white, "#anchor5 initially white");
|
||||||
|
add_class_and_check_bg_color(indirect_prev5, "prev", anchor5, lightgreen);
|
||||||
|
remove_class_and_check_bg_color(indirect_prev5, "prev", anchor5, white);
|
||||||
|
add_class_and_check_bg_color(direct_prev5, "prev", anchor5, lightgreen);
|
||||||
|
remove_class_and_check_bg_color(direct_prev5, "prev", anchor5, white);
|
||||||
|
</script>
|
|
@ -0,0 +1,55 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>CSS Selector Invalidation: :has() with nesting parent containing :hover</title>
|
||||||
|
<link rel="help" href="https://drafts.csswg.org/selectors/#relational">
|
||||||
|
<script src="../../../resources/testharness.js"></script>
|
||||||
|
<script src="../../../resources/testharnessreport.js"></script>
|
||||||
|
<script src="../../../resources/testdriver.js"></script>
|
||||||
|
<script src="../../../resources/testdriver-actions.js"></script>
|
||||||
|
<script src="../../../resources/testdriver-vendor.js"></script>
|
||||||
|
<style>
|
||||||
|
dd, dt { background: white; }
|
||||||
|
dd:hover {
|
||||||
|
dt:has(~ &) { background: lime; }
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<dt id=dt1>#dt1</dt>
|
||||||
|
<dd id=dd1>#dd1, Hover me, the DT above should go lime</dd>
|
||||||
|
<dt id=dt2>#dt2</dt>
|
||||||
|
<dd id=dd2>#dd2, Hover me, both DTs above should go lime</dd>
|
||||||
|
<script>
|
||||||
|
const white = 'rgb(255, 255, 255)';
|
||||||
|
const lime = 'rgb(0, 255, 0)';
|
||||||
|
|
||||||
|
function bg_color(element, color, message) {
|
||||||
|
assert_equals(getComputedStyle(element)['background-color'], color, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
promise_test(async () => {
|
||||||
|
bg_color(dt1, white, "#dt1 initially white");
|
||||||
|
bg_color(dd1, white, "#dd1 initially white");
|
||||||
|
bg_color(dt2, white, "#dt2 initially white");
|
||||||
|
bg_color(dd2, white, "#dd2 initially white");
|
||||||
|
|
||||||
|
await new test_driver.Actions().pointerMove(0, 0, {origin: dd1}).send();
|
||||||
|
|
||||||
|
bg_color(dt1, lime, "#dt1 should go lime when hover #dd1");
|
||||||
|
bg_color(dd1, white, "#dd1 doesn't change when hover #dd1");
|
||||||
|
bg_color(dt2, white, "#dt2 doesn't change when hover #dd1");
|
||||||
|
bg_color(dd2, white, "#dd2 doesn't change when hover #dd1");
|
||||||
|
|
||||||
|
await new test_driver.Actions().pointerMove(0, 0, {origin: dt1}).send();
|
||||||
|
|
||||||
|
bg_color(dt1, white, "#dt1 should go white when hover #dt2");
|
||||||
|
bg_color(dd1, white, "#dd1 doesn't change when hover #dt2");
|
||||||
|
bg_color(dt2, white, "#dt2 doesn't change when hover #dt2");
|
||||||
|
bg_color(dd2, white, "#dd2 doesn't change when hover #dt2");
|
||||||
|
|
||||||
|
await new test_driver.Actions().pointerMove(0, 0, {origin: dd2}).send();
|
||||||
|
|
||||||
|
bg_color(dt1, lime, "#dt1 should go lime when hover #dd2");
|
||||||
|
bg_color(dd1, white, "#dd1 doesn't change when hover #dd2");
|
||||||
|
bg_color(dt2, lime, "#dt2 should go lime when hover #dd2");
|
||||||
|
bg_color(dd2, white, "#dd2 doesn't change when hover #dd2");
|
||||||
|
});
|
||||||
|
</script>
|
|
@ -0,0 +1,107 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>CSS Selector Invalidation: :has() with :not()</title>
|
||||||
|
<link rel="author" title="Antti Koivisto" href="mailto:antti@apple.com">
|
||||||
|
<script src="../../../resources/testharness.js"></script>
|
||||||
|
<script src="../../../resources/testharnessreport.js"></script>
|
||||||
|
<link rel="help" href="https://drafts.csswg.org/selectors/#relational">
|
||||||
|
<style>
|
||||||
|
div, main { color: grey }
|
||||||
|
#subject:has(:not(.test)) { color: green }
|
||||||
|
#subject:has(.test :not(.test)) { color: red }
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<main id=main>
|
||||||
|
<div id=subject>
|
||||||
|
<div id=subject_child class=test>
|
||||||
|
<div id=subject_descendant class=test></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const grey = 'rgb(128, 128, 128)';
|
||||||
|
const red = 'rgb(255, 0, 0)';
|
||||||
|
const green = 'rgb(0, 128, 0)';
|
||||||
|
const blue = 'rgb(0, 0, 255)';
|
||||||
|
|
||||||
|
function testColor(test_name, color) {
|
||||||
|
test(function() {
|
||||||
|
assert_equals(getComputedStyle(subject).color, color);
|
||||||
|
}, test_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testClassChange(element, expectedColor)
|
||||||
|
{
|
||||||
|
element.classList.remove('test');
|
||||||
|
testColor(`remove .test to ${element.id}`, expectedColor);
|
||||||
|
element.classList.add('test');
|
||||||
|
testColor(`add .test from ${element.id}`, grey);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testElementInsertionBefore(beforeElement, expectedColor)
|
||||||
|
{
|
||||||
|
const newElement = document.createElement('div');
|
||||||
|
|
||||||
|
beforeElement.before(newElement);
|
||||||
|
testColor(`insert element div before ${beforeElement.id}`, expectedColor);
|
||||||
|
|
||||||
|
newElement.remove();
|
||||||
|
testColor(`remove element div before ${beforeElement.id}`, grey);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testElementInsertionAfter(afterElement, expectedColor)
|
||||||
|
{
|
||||||
|
const newElement = document.createElement('div');
|
||||||
|
|
||||||
|
afterElement.after(newElement);
|
||||||
|
testColor(`insert element div after ${afterElement.id}`, expectedColor);
|
||||||
|
|
||||||
|
newElement.remove();
|
||||||
|
testColor(`remove element div after ${afterElement.id}`, grey);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testTreeInsertionBefore(beforeElement, expectedColor)
|
||||||
|
{
|
||||||
|
const newElement = document.createElement('div');
|
||||||
|
const newChild = document.createElement('div');
|
||||||
|
newElement.appendChild(newChild);
|
||||||
|
|
||||||
|
beforeElement.before(newElement);
|
||||||
|
testColor(`insert tree div>div before ${beforeElement.id}`, expectedColor);
|
||||||
|
|
||||||
|
newElement.remove();
|
||||||
|
testColor(`remove tree div>div before ${beforeElement.id}`, grey);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testTreeInsertionAfter(afterElement, expectedColor)
|
||||||
|
{
|
||||||
|
const newElement = document.createElement('div');
|
||||||
|
const newChild = document.createElement('div');
|
||||||
|
newElement.appendChild(newChild);
|
||||||
|
|
||||||
|
afterElement.after(newElement);
|
||||||
|
testColor(`insert tree div.test after ${afterElement.id}`, expectedColor);
|
||||||
|
|
||||||
|
newElement.remove();
|
||||||
|
testColor(`remove tree div.test after ${afterElement.id}`, grey);
|
||||||
|
}
|
||||||
|
|
||||||
|
testColor('Initial color', grey);
|
||||||
|
|
||||||
|
testClassChange(subject_child, green);
|
||||||
|
testClassChange(subject_descendant, red);
|
||||||
|
|
||||||
|
testElementInsertionBefore(subject_child, green);
|
||||||
|
testElementInsertionBefore(subject_descendant, red);
|
||||||
|
|
||||||
|
testElementInsertionAfter(subject_child, green);
|
||||||
|
testElementInsertionAfter(subject_descendant, red);
|
||||||
|
|
||||||
|
testTreeInsertionBefore(subject_child, green);
|
||||||
|
testTreeInsertionBefore(subject_descendant, red);
|
||||||
|
|
||||||
|
testTreeInsertionAfter(subject_child, green);
|
||||||
|
testTreeInsertionAfter(subject_descendant, red);
|
||||||
|
|
||||||
|
</script>
|
|
@ -0,0 +1,67 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>CSS Selectors Test: :has(:nth-child()) invalidation for sibling change</title>
|
||||||
|
<script src="../../../resources/testharness.js"></script>
|
||||||
|
<script src="../../../resources/testharnessreport.js"></script>
|
||||||
|
<link rel="help" href="https://drafts.csswg.org/selectors/#relational">
|
||||||
|
<style>
|
||||||
|
#test-container > div { background-color: green; }
|
||||||
|
#target1:has(.item:nth-child(3)) { background-color: red; }
|
||||||
|
#target2:has(.item:nth-last-child(3)) { background-color: red; }
|
||||||
|
#target3:has(.item:nth-child(3) > .child) { background-color: red; }
|
||||||
|
#target4:has(.item:nth-last-child(3) > .child) { background-color: red; }
|
||||||
|
</style>
|
||||||
|
<div id="test-container">
|
||||||
|
<div id="target1">
|
||||||
|
<div class="item" id="item1">FAIL if you see this text</div>
|
||||||
|
<div class="item"></div>
|
||||||
|
<div class="item">This text should have a green background</div>
|
||||||
|
</div>
|
||||||
|
<div id="target2">
|
||||||
|
<div class="item">This text should have a green background</div>
|
||||||
|
<div class="item"></div>
|
||||||
|
<div class="item" id="item2">FAIL if you see this text</div>
|
||||||
|
</div>
|
||||||
|
<div id="target3">
|
||||||
|
<div class="item" id="item3">FAIL if you see this text</div>
|
||||||
|
<div class="item"></div>
|
||||||
|
<div class="item">
|
||||||
|
<span class="child">This text should have a green background<span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="target4">
|
||||||
|
<div class="item">
|
||||||
|
<span class="child">This text should have a green background<span>
|
||||||
|
</div>
|
||||||
|
<div class="item"></div>
|
||||||
|
<div class="item" id="item4">FAIL if you see this text</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
test(() => {
|
||||||
|
assert_equals(getComputedStyle(target1).backgroundColor, "rgb(255, 0, 0)");
|
||||||
|
assert_equals(getComputedStyle(target2).backgroundColor, "rgb(255, 0, 0)");
|
||||||
|
assert_equals(getComputedStyle(target3).backgroundColor, "rgb(255, 0, 0)");
|
||||||
|
assert_equals(getComputedStyle(target4).backgroundColor, "rgb(255, 0, 0)");
|
||||||
|
}, "Initially red");
|
||||||
|
|
||||||
|
test(() => {
|
||||||
|
item1.remove();
|
||||||
|
assert_equals(getComputedStyle(target1).backgroundColor, "rgb(0, 128, 0)");
|
||||||
|
}, ":nth-child() no longer matching after removal");
|
||||||
|
|
||||||
|
test(() => {
|
||||||
|
item2.remove();
|
||||||
|
assert_equals(getComputedStyle(target2).backgroundColor, "rgb(0, 128, 0)");
|
||||||
|
}, ":nth-last-child() no longer matching after removal");
|
||||||
|
|
||||||
|
test(() => {
|
||||||
|
item3.remove();
|
||||||
|
assert_equals(getComputedStyle(target3).backgroundColor, "rgb(0, 128, 0)");
|
||||||
|
}, ":nth-child() in non-subject no longer matching after removal");
|
||||||
|
|
||||||
|
test(() => {
|
||||||
|
item4.remove();
|
||||||
|
assert_equals(getComputedStyle(target4).backgroundColor, "rgb(0, 128, 0)");
|
||||||
|
}, ":nth-last-child() in non-subject no longer matching after removal");
|
||||||
|
</script>
|
|
@ -0,0 +1,99 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>CSS Selector Invalidation: :has() with pseudo-classes</title>
|
||||||
|
<link rel="author" title="Antti Koivisto" href="mailto:antti@apple.com">
|
||||||
|
<script src="../../../resources/testharness.js"></script>
|
||||||
|
<script src="../../../resources/testharnessreport.js"></script>
|
||||||
|
<link rel="help" href="https://drafts.csswg.org/selectors/#relational">
|
||||||
|
<style>
|
||||||
|
main:has(input) div { color: grey }
|
||||||
|
main:has(#checkbox:checked) > #subject { color: red }
|
||||||
|
main:has(#option:checked) > #subject { color: red }
|
||||||
|
main:has(#checkbox:disabled) > #subject { color: green }
|
||||||
|
main:has(#option:disabled) > :is(#subject, #subject2) { color: green }
|
||||||
|
main:has(#optgroup:disabled) > #subject { color: blue }
|
||||||
|
main:not(:has(#checkbox:enabled)) > #subject3 { color: green }
|
||||||
|
main:not(:has(#option:enabled)) :is(#subject3, #subject4) { color: green }
|
||||||
|
main:not(:has(#optgroup:enabled)) > #subject3 { color: blue }
|
||||||
|
main:has(#text_input:valid) > #subject { color: yellow }
|
||||||
|
main:not(:has(#text_input:invalid)) > #subject2 { color: yellow }
|
||||||
|
main:has(#form:valid) > #subject3 { color: yellow }
|
||||||
|
main:not(:has(#form:invalid)) > #subject4 { color: yellow }
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<main id=main>
|
||||||
|
<form id=form>
|
||||||
|
<input type=checkbox id=checkbox></input>
|
||||||
|
<select id=select><optgroup id=optgroup><option>a</option><option id=option>b</option></optgroup></select>
|
||||||
|
<input id=text_input type=text required></input>
|
||||||
|
</form>
|
||||||
|
<div id=subject></div>
|
||||||
|
<div id=subject2></div>
|
||||||
|
<div id=subject3></div>
|
||||||
|
<div id=subject4></div>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const grey = 'rgb(128, 128, 128)';
|
||||||
|
const red = 'rgb(255, 0, 0)';
|
||||||
|
const green = 'rgb(0, 128, 0)';
|
||||||
|
const blue = 'rgb(0, 0, 255)';
|
||||||
|
const yellow = 'rgb(255, 255, 0)';
|
||||||
|
const purple = 'rgb(128, 0, 128)';
|
||||||
|
const pink = 'rgb(255, 192, 203)';
|
||||||
|
|
||||||
|
function testColor(test_name, subject_element, color) {
|
||||||
|
test(function() {
|
||||||
|
assert_equals(getComputedStyle(subject_element).color, color);
|
||||||
|
}, test_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testPseudoClassChange(element, property, subject_element, expectedColor)
|
||||||
|
{
|
||||||
|
testColor(`Before set ${property} on ${element.id}, testing ${subject_element.id}`, subject_element, grey);
|
||||||
|
|
||||||
|
element[property] = true;
|
||||||
|
testColor(`Set ${property} on ${element.id}, testing ${subject_element.id}`, subject_element, expectedColor);
|
||||||
|
|
||||||
|
element[property] = false;
|
||||||
|
testColor(`Unset ${property} on ${element.id}, testing ${subject_element.id}`, subject_element, grey);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testSelectedChange(option, subject_element, expectedColor)
|
||||||
|
{
|
||||||
|
const oldOption = select.selectedOptions[0];
|
||||||
|
option.selected = true;
|
||||||
|
testColor(`Set select on ${option.id}`, subject_element, expectedColor);
|
||||||
|
oldOption.selected = true;
|
||||||
|
testColor(`Reset select`, subject, grey);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testValueChange(input, subject_element, expectedColor)
|
||||||
|
{
|
||||||
|
testColor(`Before setting value of ${input.id}, testing ${subject_element.id}`, subject_element, grey);
|
||||||
|
|
||||||
|
input.value = "value";
|
||||||
|
testColor(`Set value of ${input.id}, testing ${subject_element.id}`, subject_element, expectedColor);
|
||||||
|
|
||||||
|
input.value = "";
|
||||||
|
testColor(`Clear value of ${input.id}, testing ${subject_element.id}`, subject_element, grey);
|
||||||
|
}
|
||||||
|
|
||||||
|
testPseudoClassChange(checkbox, "checked", subject, red);
|
||||||
|
testSelectedChange(option, subject, red);
|
||||||
|
|
||||||
|
testPseudoClassChange(checkbox, "disabled", subject, green);
|
||||||
|
testPseudoClassChange(checkbox, "disabled", subject3, green);
|
||||||
|
testPseudoClassChange(option, "disabled", subject, green);
|
||||||
|
testPseudoClassChange(option, "disabled", subject3, green);
|
||||||
|
|
||||||
|
testPseudoClassChange(optgroup, "disabled", subject, blue);
|
||||||
|
testPseudoClassChange(optgroup, "disabled", subject2, green);
|
||||||
|
testPseudoClassChange(optgroup, "disabled", subject3, blue);
|
||||||
|
testPseudoClassChange(optgroup, "disabled", subject4, green);
|
||||||
|
|
||||||
|
testValueChange(text_input, subject, yellow);
|
||||||
|
testValueChange(text_input, subject2, yellow);
|
||||||
|
testValueChange(text_input, subject3, yellow);
|
||||||
|
testValueChange(text_input, subject4, yellow);
|
||||||
|
</script>
|
Loading…
Reference in a new issue