4 <script src="../../../resources/js-test.js"></script>
5 <script src="resources/shadow-dom.js"></script>
8 <p>This tests that pressing Tab key should traverse into shadow DOM subtrees, and pressing Shift-Tab should reverse the order.</p>
9 <pre id="console"></pre>
12 function prepareDOMTree(parent)
15 // FIXME: Use more descriptive ids for each elements.
16 createDOM('div', {'id': 'top-div'},
17 createDOM('input', {'id': 'input-A-1', 'tabindex': 1}),
18 createDOM('input', {'id': 'input-B-1', 'tabindex': 1}),
19 createDOM('div'), // Should not be selected.
20 createDOM('input', {'id': 'input-A-0', 'tabindex': 0}),
21 createDOM('div', {'id': 'host-A', 'tabindex': -1},
23 createDOM('input', {'id': 'input-1', 'tabindex': 1}),
24 createDOM('div', {'tabindex': 2, 'style': 'visibility:hidden;'},
26 createDOM('input', {'tabindex': 3, 'type': 'date', 'disabled': ''}),
27 createDOM('select', {'tabindex': 4, 'multiple': '', 'disabled': ''}),
28 createDOM('div', {'id': 'nested-host', 'tabindex': 30},
30 createDOM('input', {'tabindex': -1}),
31 createDOM('input', {'id': 'input-15', 'tabindex': 15}),
32 createDOM('input', {'id': 'input-25', 'tabindex': 25}))),
33 createDOM('input', {'id': 'input-20', 'tabindex': 20}))),
34 createDOM('input', {'id': 'input-C-1', 'tabindex': 1}),
35 createDOM('input', {'id': 'input-B-0', 'tabindex': 0}),
36 createDOM('div', {'id': 'host-B', 'tabindex': 1},
38 createDOM('input', {'id': 'older-input-A-0', 'tabindex': 0}),
39 createDOM('input', {'id': 'older-input-A-1', 'tabindex': 1}),
40 createDOM('content', {'select': '#light-child-selected-0, #light-child-selected-1'}),
41 createDOM('input', {'id': 'older-input-B-0', 'tabindex': 0}),
42 createDOM('input', {'id': 'older-input-B-1', 'tabindex': 1})),
44 createDOM('input', {'id': 'younger-input-A-0', 'tabindex': 0}),
45 createDOM('input', {'id': 'younger-input-A-1', 'tabindex': 1}), // The first node in the focusScope
46 createDOM('shadow', {}),
47 createDOM('input', {'id': 'younger-input-B-0', 'tabindex': 0}), // The last node in the focusScope
48 createDOM('input', {'id': 'younger-input-B-1', 'tabindex': 1})),
49 createDOM('input', {'id': 'light-child-selected-0', 'tabindex': 0}),
50 createDOM('input', {'id': 'light-child-selected-1', 'tabindex': 1}),
51 createDOM('input', {'id': 'light-child-non-selected-1', 'tabindex': 1})),
52 createDOM('input', {'id': 'input-D-1', 'tabindex': 1}),
53 createDOM('input', {'id': 'input-C-0', 'tabindex': 0}),
54 createDOM('div', {'id': 'host-C', 'tabindex': -1},
56 createDOM('input', {'tabindex': -1}))),
57 createDOM('input', {'id': 'input-D-0', 'tabindex': 0}),
59 createDOM('div', {'id': 'host-D', 'tabindex': 0},
61 createDOM('input', {'id': 'input-E-0', 'tabindex': 0})));
66 if (window.testRunner)
67 testRunner.dumpAsText();
69 if (!window.eventSender) {
74 prepareDOMTree(document.body);
76 // FIXME: Output inserted comments in this array to expected.txt for readability of the result.
77 var elementsInFocusNavigationOrder = [
78 'input-A-1', 'input-B-1',
79 // Traverse elements which have tabindex=1.
80 // Should skip every elements, even though they have the same tabindex, in the non-focusable shadow host (id=host-A)
81 // since a non-focusable shadow host should act as if they were assinged to tabindex=0 so it was skipped in this turn.
84 // Traverse a focusable shadow host.
87 // Enter the focus scope of the youngest shadow root in the shadow host and travese the first focusable node in the shadow DOM navigation.
88 'host-B//younger-input-A-1',
89 'host-B//younger-input-B-1',
90 'host-B//younger-input-A-0',
92 // Visits a shadow insertion point. Entering the focus scope of the older shadow root.
93 'host-B/older-input-A-1',
94 'host-B/older-input-B-1',
95 'host-B/older-input-A-0',
96 'host-B/older-input-B-0',
98 // Exits the focus scope of the older sahdow root. Visits the next focusable element which follows the shadow insertion point.
99 'host-B//younger-input-B-0',
101 // Exits the focus scope of the youngest sahdow root.
102 'light-child-selected-1',
104 // 'light-child-non-selected-1' should be skipped since it doesn't participate in the composed tree.
107 // All elements with tabindex=1 had been traversed in the outermost scope.
108 // So traverse elements with tabindex=0 in next.
111 // // A non-focusable shadow host (id=host-A) will be "replaced" with its shadow DOM navigation.
114 'host-A/nested-host',
116 // Enter a nested focus scope inside of a shadow host (id=nested-host).
117 'host-A/nested-host/input-15',
118 'host-A/nested-host/input-25',
120 // Exit a nested shadow host.
123 'light-child-selected-0',
127 // A non-focusable shadow host (id=host-C), which does not have focusable elements, should be skipped entirely.
132 // Wraps to the first element in the outermost focus scope.
136 testFocusNavigationFowrad(elementsInFocusNavigationOrder);
137 elementsInFocusNavigationOrder.reverse();
138 testFocusNavigationBackward(elementsInFocusNavigationOrder);
140 debug('Test finished.');