Commit b9ad36b6 authored by Yu Han's avatar Yu Han Committed by Commit Bot

Adds WPT tests for Imperative Shadow DOM Slot API.

Previous to this CL, Imperative shadow DOM Slot API was put on hold.
A previous implementation is still in place but disabled. Since then,
in 2019 TPAC F2F, the Imperative Slotting API behavior has been updated.

This CL adds new test cases which reflects this new behavior for
Imperative Shadow DOM API. They are turned off for now, but will be
enabled one by one as its functionality gets implemented.

This is the post for I2P:
https://groups.google.com/a/chromium.org/forum/#!topic/blink-dev/TNYIAu5E_M4



Bug: 869308
Change-Id: Ie875a3eb2b349942b6aa51af387460c470572491
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2083742
Commit-Queue: Yu Han <yuzhehan@chromium.org>
Reviewed-by: default avatarMason Freed <masonfreed@chromium.org>
Cr-Commit-Position: refs/heads/master@{#748099}
parent 78ac5c8b
......@@ -6584,6 +6584,10 @@ crbug.com/944449 external/wpt/scroll-animations/scroll-animation.html [ Pass Cra
# Sheriff 2020-02-10
crbug.com/1050306 [ Fuchsia ] virtual/gpu/fast/canvas/canvas-filter-frameless-document.html [ Crash Pass Timeout ]
# Imperative Shadow DOM Slot API - WIP
crbug.com/869308 external/wpt/shadow-dom/slots-imperative-slot-api.tentative.html [ Failure ]
crbug.com/869308 virtual/web-components-v0-disabled/external/wpt/shadow-dom/slots-imperative-slot-api.tentative.html [ Failure ]
# Swiftshader issue.
crbug.com/1048149 external/wpt/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-non-integer-innerwidth.html [ Crash Timeout ]
crbug.com/1048149 external/wpt/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-non-integer-screeny.html [ Crash Timeout ]
......
......@@ -21,7 +21,15 @@ function createTestTree(node) {
function attachShadowFromTemplate(template) {
let parent = template.parentNode;
parent.removeChild(template);
let shadowRoot = parent.attachShadow({mode: template.getAttribute('data-mode')});
let shadowRoot;
if (template.getAttribute('data-slot-assignment') === 'manual') {
shadowRoot =
parent.attachShadow({mode: template.getAttribute('data-mode'),
slotAssignment: 'manual'});
} else {
shadowRoot = parent.attachShadow(
{mode: template.getAttribute('data-mode')});
}
let id = template.id;
if (id) {
shadowRoot.id = id;
......
This is a testharness.js-based test.
FAIL attachShadow can take slotAssignment parameter. assert_throws_js: others should throw exception function "() => {
tTree.host3.attachShadow({ mode: 'open', slotAssignment: 'exceptional' })}" did not throw
FAIL Imperative slot API throws exception when not slotAssignment != 'manual'. assert_throws_dom: function "() => { tTree.s1.assign([]); }" did not throw
FAIL Imperative slot API throws exception when slotable parentNode != slot's host. assert_throws_dom: function "() => { tTree.s2.assign([tTree.c1]); }" did not throw
FAIL Imperative slot API can assign nodes in manual slot assignment. assert_equals: expected null but got Element node <slot id="s1"></slot>
FAIL Order of slotables is preserved in manual slot assignment. assert_array_equals: lengths differ, expected array [Element node <div id="c2"></div>, Element node <div id="c3"></div>, Element node <div id="c1"></div>] length 3, got [Text node "
FAIL Previously assigned slotable is moved to new slot when it's reassigned. assert_array_equals: lengths differ, expected array [Element node <div id="c2"></div>, Element node <div id="c3"></div>, Element node <div id="c1"></div>] length 3, got [Text node "
FAIL Assigning invalid nodes causes exception and slot returns to its previous state. assert_equals: expected "NotAllowedError" but got "Error"
FAIL Moving a slot to a new host, the slot looses its previously assigned slotables. assert_array_equals: lengths differ, expected array [Element node <div id="c1"></div>, Element node <div id="c2"></div>, Element node <div id="c3"></div>] length 3, got [Text node "
FAIL Moving a slot's tree order position within a shadow host has no impact on its assigned slotables. assert_array_equals: lengths differ, expected array [Element node <div id="c1"></div>, Element node <div id="c2"></div>, Element node <div id="c3"></div>] length 3, got [Text node "
FAIL Appending slotable to different host, it looses slot assignment. It can be re-assigned within a new host. assert_array_equals: lengths differ, expected array [Element node <div id="c1"></div>, Element node <div id="c2"></div>, Element node <div id="c3"></div>] length 3, got [Text node "
FAIL Assignment with the same node in parameters should be ignored, last one wins. assert_array_equals: lengths differ, expected array [Element node <div id="c1"></div>] length 1, got [Text node "
FAIL Removing a slot from DOM resets its slotable's slot assignment. assert_equals: expected null but got Element node <slot id="s2"></slot>
Harness: the test ran to completion.
<!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);
assert_not_equals(tTree.host1.attachShadow({ mode: 'open', slotAssignment: 'manual'}),
null, 'slot assignment manual should work');
assert_not_equals(tTree.host2.attachShadow({ mode: 'open', slotAssignment: 'auto'}),
null, 'slot assignment auto should work');
assert_throws_js(TypeError, () => {
tTree.host3.attachShadow({ mode: 'open', slotAssignment: 'exceptional' })},
'others should throw exception');
}, 'attachShadow can take slotAssignment parameter.');
</script>
<div id="test_errors">
<div id="host1">
<template data-mode="open" data-slot-assignment="auto">
<slot id="s1"></slot>
</template>
</div>
<div id="host2">
<template data-mode="open" data-slot-assignment="manual">
<slot id="s2"></slot>
</template>
</div>
<div id="c1" slot="slot1"></div>
</div>
<script>
test(() => {
let tTree = createTestTree(test_errors);
assert_throws_dom('NotAllowedError', () => { tTree.s1.assign([]); });
}, 'Imperative slot API throws exception when not slotAssignment != \'manual\'.');
test(() => {
let tTree = createTestTree(test_errors);
assert_throws_dom('NotAllowedError', () => { tTree.s2.assign([tTree.c1]); });
assert_throws_dom('NotAllowedError', () => { tTree.s2.assign([tTree.host1]); });
}, 'Imperative slot API throws exception when slotable parentNode != slot\'s host.');
</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);
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 slotables 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 slotable is moved to new slot when it\'s reassigned.');
test(() => {
let tTree = createTestTree(test_assign);
// tTree.c4 is invalid for tTree.host slot assignment.
try {
tTree.s1.assign([tTree.c1, tTree.c2, tTree.c4]);
assert_unreached('assign() should have failed) ');
} catch (err) {
assert_equals(err.name, 'NotAllowedError');
}
assert_array_equals(tTree.s1.assignedNodes(), []);
assert_equals(tTree.c1.assignedSlot, null);
assert_equals(tTree.c2.assignedSlot, null);
assert_equals(tTree.c4.assignedSlot, null);
tTree.s1.assign([tTree.c2, tTree.c3, tTree.c1]);
assert_array_equals(tTree.s1.assignedNodes(), [tTree.c2, tTree.c3, tTree.c1]);
try {
tTree.s1.assign([tTree.c4]);
assert_unreached('assign() should have failed) ');
} catch (err) {
assert_equals(err.name, 'NotAllowedError');
}
// Previous state is preserved.
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);
}, 'Assigning invalid nodes causes exception and slot returns to its previous state.');
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 slotables.');
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(), [tTree.c1, tTree.c2, tTree.c3]);
}, 'Moving a slot\'s tree order position within a shadow host has no impact on its assigned slotables.');
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(), []);
tTree.s4.assign(tTree.c1);
assert_array_equals(tTree.s4.assignedNodes(), [tTree.c1]);
assert_equals(tTree.c1.assignedSlot, tTree.s4);
}, 'Appending slotable 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, 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.c2, tTree.c1]);
}, 'Assignment with the same node in parameters should be ignored, last 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 slotable\'s slot assignment.');
</script>
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment