summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/shadow-dom/imperative-slot-api.html
diff options
context:
space:
mode:
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.html303
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>