diff options
Diffstat (limited to 'testing/web-platform/tests/shadow-dom/imperative-slot-api.html')
-rw-r--r-- | testing/web-platform/tests/shadow-dom/imperative-slot-api.html | 303 |
1 files changed, 303 insertions, 0 deletions
diff --git a/testing/web-platform/tests/shadow-dom/imperative-slot-api.html b/testing/web-platform/tests/shadow-dom/imperative-slot-api.html new file mode 100644 index 0000000000..bcf052bbab --- /dev/null +++ b/testing/web-platform/tests/shadow-dom/imperative-slot-api.html @@ -0,0 +1,303 @@ +<!DOCTYPE html> +<title>Shadow DOM: Imperative Slot API</title> +<meta name="author" title="Yu Han" href="mailto:yuzhehan@chromium.org"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/shadow-dom.js"></script> + +<div id="test_basic"> + <div id="host1"></div> + <div id="host2"></div> + <div id="host3"></div> +</div> +<script> +test(() => { + let tTree = createTestTree(test_basic); + const shadow1 = tTree.host1.attachShadow({ mode: 'open', slotAssignment: 'manual'}); + assert_not_equals(shadow1, null, 'slot assignment manual should work'); + assert_equals(shadow1.slotAssignment, "manual", 'slotAssignment should return "manual"'); + const shadow2 = tTree.host2.attachShadow({ mode: 'open', slotAssignment: 'named'}); + assert_not_equals(shadow2, null, 'slot assignment named should work'); + assert_equals(shadow2.slotAssignment, "named", 'slotAssignment should return "named"'); + assert_throws_js(TypeError, () => { + tTree.host3.attachShadow({ mode: 'open', slotAssignment: 'exceptional' })}, + 'others should throw exception'); +}, 'attachShadow can take slotAssignment parameter.'); +</script> + +<div id="test_assign"> + <div id="host"> + <template id="shadow_root" data-mode="open" data-slot-assignment="manual"> + <slot id="s1"></slot> + <slot id="s2"></slot> + <slot id="s3"></slot> + </template> + <div id="c1"></div> + <div id="c2"></div> + <div id="c3"></div> + <div id="nested"> + <div id="ns1"></div> + </div> + </div> + <div id="c4"></div> + <div id="host4"> + <template id="shadow_root4" data-mode="open" data-slot-assignment="manual"> + <slot id="s4" name="s4"></slot> + </template> + </div> +</div> +<script> +test(() => { + let tTree = createTestTree(test_assign); + tTree.s1.assign(c1,c2); // Should work + assert_throws_js(TypeError, () => { + tTree.s1.assign([c1,c2]) + }, 'sequence not allowed'); + assert_throws_js(TypeError, () => { + tTree.s1.assign([]) + }, 'including empty sequences'); +}, 'slot.attach() should take variadic not sequence.'); + +test(() => { + let tTree = createTestTree(test_assign); + assert_array_equals(tTree.s2.assignedElements(), []); + assert_equals(tTree.c1.assignedSlot, null); + + tTree.s1.assign(tTree.c1); + assert_array_equals(tTree.s1.assignedNodes(), [tTree.c1]); + assert_equals(tTree.c1.assignedSlot, tTree.s1); + + tTree.s2.assign(tTree.c2, tTree.c3); + assert_array_equals(tTree.s1.assignedNodes(), [tTree.c1]); + assert_array_equals(tTree.s2.assignedNodes(), [tTree.c2, tTree.c3]); +}, 'Imperative slot API can assign nodes in manual slot assignment.'); + +test(() => { + let tTree = createTestTree(test_assign); + + tTree.s1.assign(tTree.c2, tTree.c3, tTree.c1); + assert_array_equals(tTree.s1.assignedNodes(), [tTree.c2, tTree.c3, tTree.c1]); + assert_equals(tTree.c1.assignedSlot, tTree.s1); + assert_equals(tTree.c2.assignedSlot, tTree.s1); + assert_equals(tTree.c3.assignedSlot, tTree.s1); + + tTree.s1.assign(tTree.c1, tTree.c2); + assert_array_equals(tTree.s1.assignedNodes(), [tTree.c1, tTree.c2]); + assert_equals(tTree.c1.assignedSlot, tTree.s1); + assert_equals(tTree.c2.assignedSlot, tTree.s1); + assert_equals(tTree.c3.assignedSlot, null); + + tTree.s1.assign(tTree.c3, tTree.c2, tTree.c1); + assert_array_equals(tTree.s1.assignedNodes(), [tTree.c3, tTree.c2, tTree.c1]); + assert_equals(tTree.c1.assignedSlot, tTree.s1); + assert_equals(tTree.c2.assignedSlot, tTree.s1); + assert_equals(tTree.c3.assignedSlot, tTree.s1); +}, 'Order of slottables is preserved in manual slot assignment.'); + +test(() => { + let tTree = createTestTree(test_assign); + + tTree.s1.assign(tTree.c2, tTree.c3, tTree.c1); + assert_array_equals(tTree.s1.assignedNodes(), [tTree.c2, tTree.c3, tTree.c1]); + + tTree.s2.assign(tTree.c2); + assert_array_equals(tTree.s1.assignedNodes(), [tTree.c3, tTree.c1]); + assert_array_equals(tTree.s2.assignedNodes(), [tTree.c2]); + assert_equals(tTree.c1.assignedSlot, tTree.s1); + assert_equals(tTree.c2.assignedSlot, tTree.s2); + assert_equals(tTree.c3.assignedSlot, tTree.s1); + + tTree.s3.assign(tTree.c3); + assert_array_equals(tTree.s1.assignedNodes(), [tTree.c1]); + assert_array_equals(tTree.s2.assignedNodes(), [tTree.c2]); + assert_array_equals(tTree.s3.assignedNodes(), [tTree.c3]); + assert_equals(tTree.c1.assignedSlot, tTree.s1); + assert_equals(tTree.c2.assignedSlot, tTree.s2); + assert_equals(tTree.c3.assignedSlot, tTree.s3); +}, 'Previously assigned slottable is moved to new slot when it\'s reassigned.'); + +test(() => { + let tTree = createTestTree(test_assign); + + tTree.s1.assign(tTree.c1); + tTree.s2.assign(tTree.c2, tTree.c1); + tTree.s3.assign(tTree.c1, tTree.c3); + + assert_array_equals(tTree.s1.assignedNodes(), []); + assert_array_equals(tTree.s2.assignedNodes(), [tTree.c2]); + assert_array_equals(tTree.s3.assignedNodes(), [tTree.c1, tTree.c3]); + assert_equals(tTree.c1.assignedSlot, tTree.s3); + assert_equals(tTree.c2.assignedSlot, tTree.s2); + assert_equals(tTree.c3.assignedSlot, tTree.s3); +}, 'Order and assignment of nodes are preserved during multiple assignment in a row.'); + +test(() => { + let tTree = createTestTree(test_assign); + + // tTree.c4 is invalid for tTree.host slot assignment. + // No exception should be thrown here. + tTree.s1.assign(tTree.c1, tTree.c4, tTree.c2); + + // All observable assignments should skip c4. + assert_array_equals(tTree.s1.assignedNodes(), [tTree.c1, tTree.c2]); + assert_equals(tTree.c1.assignedSlot, tTree.s1); + assert_equals(tTree.c2.assignedSlot, tTree.s1); + assert_equals(tTree.c4.assignedSlot, null); + + // Moving c4 into place should reveal the assignment. + tTree.host.append(tTree.c4); + assert_array_equals(tTree.s1.assignedNodes(), [tTree.c1, tTree.c4, tTree.c2]); + assert_equals(tTree.c1.assignedSlot, tTree.s1); + assert_equals(tTree.c2.assignedSlot, tTree.s1); + assert_equals(tTree.c4.assignedSlot, tTree.s1); + + // Moving c4 into a different shadow host and back should + // also not break the assignment. + tTree.host4.append(tTree.c4) + assert_array_equals(tTree.s1.assignedNodes(), [tTree.c1, tTree.c2]); + assert_equals(tTree.c4.assignedSlot, null); + tTree.host.append(tTree.c4); + assert_array_equals(tTree.s1.assignedNodes(), [tTree.c1, tTree.c4, tTree.c2]); + assert_equals(tTree.c4.assignedSlot, tTree.s1); +}, 'Assigning invalid nodes should be allowed.'); + +test(() => { + let tTree = createTestTree(test_assign); + + tTree.s1.assign(tTree.c1, tTree.c2, tTree.c3); + assert_array_equals(tTree.s1.assignedNodes(), [tTree.c1, tTree.c2, tTree.c3]); + + tTree.host4.append(tTree.s1); + assert_array_equals(tTree.s1.assignedNodes(), []); +}, 'Moving a slot to a new host, the slot loses its previously assigned slottables.'); + +test(() => { + let tTree = createTestTree(test_assign); + + tTree.s1.assign(tTree.c1, tTree.c2, tTree.c3); + assert_array_equals(tTree.s1.assignedNodes(), [tTree.c1, tTree.c2, tTree.c3]); + + tTree.shadow_root.insertBefore(tTree.s2, tTree.s1); + assert_array_equals(tTree.s1.assignedNodes(), [tTree.c1, tTree.c2, tTree.c3]); + assert_array_equals(tTree.s2.assignedNodes(), []); + + tTree.shadow_root.insertBefore(tTree.s4, tTree.s1); + assert_array_equals(tTree.s1.assignedNodes(), [tTree.c1, tTree.c2, tTree.c3]); + assert_array_equals(tTree.s4.assignedNodes(), []); + + tTree.ns1.append(tTree.s1); + assert_array_equals(tTree.s1.assignedNodes(), []); +}, 'Moving a slot\'s tree order position within a shadow host has no impact on its assigned slottables.'); + +test(() => { + let tTree = createTestTree(test_assign); + + tTree.s1.assign(tTree.c1, tTree.c2, tTree.c3); + assert_array_equals(tTree.s1.assignedNodes(), [tTree.c1, tTree.c2, tTree.c3]); + + tTree.host4.append(tTree.c1); + assert_array_equals(tTree.s1.assignedNodes(), [tTree.c2, tTree.c3]); + assert_array_equals(tTree.s4.assignedNodes(), []); + assert_equals(tTree.c1.assignedSlot, null); + + tTree.s4.assign(tTree.c1); + assert_array_equals(tTree.s4.assignedNodes(), [tTree.c1]); + assert_equals(tTree.c1.assignedSlot, tTree.s4); +}, 'Appending slottable to different host, it loses slot assignment. It can be re-assigned within a new host.'); + +test(() => { + let tTree = createTestTree(test_assign); + + tTree.s1.assign(tTree.c1); + assert_array_equals(tTree.s1.assignedNodes(), [tTree.c1]); + + tTree.shadow_root4.insertBefore(tTree.s1, tTree.s4); + assert_array_equals(tTree.s1.assignedNodes(), []); + // Trigger slot assignment on previous shadow root. + assert_array_equals(tTree.s2.assignedNodes(), []); + + tTree.shadow_root.insertBefore(tTree.s1, tTree.s2); + assert_array_equals(tTree.s1.assignedNodes(), [tTree.c1]); +}, 'Previously assigned node should not be assigned if slot moved to a new shadow root. The node is re-assigned when moved back.'); + +test(() => { + let tTree = createTestTree(test_assign); + + tTree.s1.assign(tTree.c1, tTree.c1, tTree.c1); + assert_array_equals(tTree.s1.assignedNodes(), [tTree.c1]); + + tTree.s1.assign(tTree.c1, tTree.c1, tTree.c2, tTree.c2, tTree.c1); + assert_array_equals(tTree.s1.assignedNodes(), [tTree.c1, tTree.c2]); +}, 'Assignment with the same node in parameters should be ignored, first one wins.'); + +test(() => { + let tTree = createTestTree(test_assign); + + tTree.s1.assign(tTree.c1, tTree.c2, tTree.c3); + tTree.s1.remove(); + + assert_equals(tTree.c1.assignedSlot, null); + assert_equals(tTree.c2.assignedSlot, null); + assert_equals(tTree.c3.assignedSlot, null); +}, 'Removing a slot from DOM resets its slottable\'s slot assignment.'); + +test(() => { + let tTree = createTestTree(test_assign); + + const isolatedDocNode = document.implementation.createHTMLDocument("").body; + isolatedDocNode.appendChild(tTree.c1); + const isolatedDocNode2 = document.implementation.createHTMLDocument("").body; + isolatedDocNode2.appendChild(tTree.s1); + + tTree.s1.assign(tTree.c1, tTree.c2); + assert_array_equals(tTree.s1.assignedNodes(), [], 's1 not inside shadow root'); + assert_equals(tTree.c1.assignedSlot, null); + assert_equals(tTree.c2.assignedSlot, null); + + tTree.shadow_root.appendChild(tTree.s1); + tTree.host.appendChild(tTree.c1); + assert_array_equals(tTree.s1.assignedNodes(), [tTree.c1, tTree.c2]); + assert_equals(tTree.c1.assignedSlot, tTree.s1); + assert_equals(tTree.c2.assignedSlot, tTree.s1); +}, 'Nodes can be assigned even if slots or nodes aren\'t in the same tree.'); + +test(() => { + let tTree = createTestTree(test_assign); + + tTree.s1.assign(tTree.c1, tTree.c2); + assert_array_equals(tTree.s1.assignedNodes(), [tTree.c1, tTree.c2]); + assert_equals(tTree.c1.assignedSlot, tTree.s1); + assert_equals(tTree.c2.assignedSlot, tTree.s1); + + const isolatedDocNode = document.implementation.createHTMLDocument("").body; + isolatedDocNode.appendChild(tTree.c1); + const isolatedDocNode2 = document.implementation.createHTMLDocument("").body; + isolatedDocNode2.appendChild(tTree.s1); + + assert_array_equals(tTree.s1.assignedNodes(), [], 's1 not inside shadow root'); + assert_equals(tTree.c1.assignedSlot, null); + assert_equals(tTree.c2.assignedSlot, null); + + tTree.shadow_root.appendChild(tTree.s1); + tTree.host.appendChild(tTree.c1); + assert_array_equals(tTree.s1.assignedNodes(), [tTree.c1, tTree.c2]); + assert_equals(tTree.c1.assignedSlot, tTree.s1); + assert_equals(tTree.c2.assignedSlot, tTree.s1); +}, 'Removing a node from the document does not break manually assigned slot linkage.'); + +test(() => { + const inputValues = [ + ['Attr', document.createAttribute('bar')], + ['Comment', document.createComment('bar')], + ['DocumentFragment', document.createDocumentFragment()], + ['DocumentType', document.implementation.createDocumentType('html', '', '')] + ]; + for (const [label, input] of inputValues) { + assert_throws_js(TypeError, () => { + const slot = document.createElement('slot'); + slot.assign(input); + }, label); + } +}, 'throw TypeError if the passed values are neither Element nor Text'); + +</script> |