7575b67821089f95f522bc6837dc5b5156382614
[WebKit-https.git] / LayoutTests / fast / shadow-dom / Extensions-to-Event-Interface.html
1 <!DOCTYPE html>
2 <html>
3 <head>
4 <title>Shadow DOM: Extensions to Event Interface</title>
5 <meta name="author" title="Ryosuke Niwa" href="mailto:rniwa@webkit.org">
6 <meta name="assert" content="Event interface must have deepPath() as a method">
7 <link rel="help" href="http://w3c.github.io/webcomponents/spec/shadow/#extensions-to-event-interface">
8 <script src="../../resources/testharness.js"></script>
9 <script src="../../resources/testharnessreport.js"></script>
10 <script src="resources/event-path-test-helpers.js"></script>
11 <link rel='stylesheet' href='../../resources/testharness.css'>
12 </head>
13 <body>
14 <div id="log"></div>
15 <script>
16
17 test(function () {
18     assert_true('deepPath' in Event.prototype);
19     assert_true('deepPath' in new Event('my-event'));
20 }, 'deepPath() must exist on Event');
21
22 test(function () {
23     var event = new Event('my-event');
24     assert_array_equals(event.deepPath(), []);
25 }, 'deepPath() must return an empty array when the event has not been dispatched');
26
27 test(function () {
28     var event = new Event('my-event');
29     document.body.dispatchEvent(event);
30     assert_array_equals(event.deepPath(), []);
31 }, 'deepPath() must return an empty array when the event is no longer dispatched');
32
33 test(function () {
34     assert_true('scoped' in Event.prototype);
35     assert_true('scoped' in new Event('my-event'));
36 }, 'scoped must exist on Event');
37
38 test(function () {
39     var event = new Event('my-event');
40     assert_false(event.scoped);
41 }, 'scoped on EventInit must default to false');
42
43 test(function () {
44     var event = new Event('my-event', {scoped: true});
45     assert_true(event.scoped);
46
47     event = new Event('my-event', {scoped: false});
48     assert_false(event.scoped);
49 }, 'scoped on EventInit must set the scoped flag');
50
51 test(function () {
52     assert_true('relatedTargetScoped' in Event.prototype);
53     assert_true('relatedTargetScoped' in new Event('my-event'));
54 }, 'relatedTargetScoped must exist on Event');
55
56 test(function () {
57     var event = new Event('my-event');
58     assert_false(event.relatedTargetScoped);
59 }, 'relatedTargetScoped on EventInit must default to false');
60
61 test(function () {
62     var event = new Event('my-event', {relatedTargetScoped: true});
63     assert_true(event.relatedTargetScoped);
64
65     event = new Event('my-event', {relatedTargetScoped: false});
66     assert_false(event.relatedTargetScoped);
67 }, 'relatedTargetScoped on EventInit must set the scoped flag');
68
69 /*
70 -SR: ShadowRoot  -S: Slot  target: (~)  *: indicates start  digit: event path order
71 A (4) --------------------------- A-SR (3)
72 + B ------------ B-SR             + A1 (2) --- A1-SR (1)
73   + C            + B1 --- B1-SR   + A2-S       + A1a (*; 0)
74   + D --- D-SR     + B1a    + B1b --- B1b-SR
75           + D1              + B1c-S   + B1b1
76                                       + B1b2
77 */
78
79 function testUnscopedEvent(mode) {
80     test(function () {
81         var nodes = createTestTree(mode);
82         var log = dispatchEventWithLog(nodes, nodes.A1a, new Event('my-event', {scoped: false, bubbles: true}));
83
84         var expectedPath = ['A1a', 'A1-SR', 'A1', 'A-SR', 'A'];
85         assert_array_equals(log.eventPath, expectedPath);
86         assert_array_equals(log.eventPath.length, log.pathAtTargets.length);
87         assert_array_equals(log.pathAtTargets[0], expectedPath);
88         assert_array_equals(log.pathAtTargets[1], expectedPath);
89         assert_array_equals(log.pathAtTargets[2], mode == 'open' ? expectedPath : ['A1', 'A-SR', 'A'],
90             'deepPath must only contain unclosed nodes of the current target.');
91     }, 'The event must propagate out of ' + mode + ' mode shadow boundaries when the scoped flag is unset');
92 }
93
94 testUnscopedEvent('open');
95 testUnscopedEvent('closed');
96
97 /*
98 -SR: ShadowRoot  -S: Slot  target: (~)  *: indicates start  digit: event path order
99 A ------------------------------- A-SR
100 + B ------------ B-SR             + A1 --- A1-SR (1)
101   + C            + B1 --- B1-SR   + A2-S   + A1a (*; 0)
102   + D --- D-SR     + B1a  + B1b --- B1b-SR
103           + D1            + B1c-S   + B1b1
104                                     + B1b2
105 */
106
107 function testScopedEvent(mode) {
108     test(function () {
109         var nodes = createTestTree(mode);
110         var log = dispatchEventWithLog(nodes, nodes.A1a, new Event('my-event', {scoped: true, bubbles: true}));
111
112         var expectedPath = ['A1a', 'A1-SR'];
113         assert_array_equals(log.eventPath, expectedPath);
114         assert_array_equals(log.eventPath.length, log.pathAtTargets.length);
115         assert_array_equals(log.pathAtTargets[0], expectedPath);
116         assert_array_equals(log.pathAtTargets[1], expectedPath);
117     }, 'The event must not propagate out of ' + mode + ' mode shadow boundaries when the scoped flag is set');
118 }
119
120 testScopedEvent('open');
121 testScopedEvent('closed');
122
123 /*
124 -SR: ShadowRoot  -S: Slot  target: (~)  relatedTarget: [~]  *: indicates start  digit: event path order
125 A (4) [4] ----------------------- A-SR (3)
126 + B ------------ B-SR             + A1 (2) ------- A1-SR (1)
127   + C            + B1 --- B1-SR   + A2-S [*; 0-3]  + A1a (*; 0)
128   + D --- D-SR     + B1a  + B1b --- B1b-SR
129           + D1            + B1c-S   + B1b1
130                                     + B1b2
131 */
132
133 function testUnscopedEventWithUnscopedRelatedTarget(mode) {
134     test(function () {
135         var nodes = createTestTree(mode);
136         var log = dispatchEventWithLog(nodes, nodes.A1a, new MouseEvent('foo', {scoped: false, relatedTargetScoped: false, bubbles: true, relatedTarget: nodes['A2-S']}));
137
138         var expectedPath = ['A1a', 'A1-SR', 'A1', 'A-SR', 'A'];
139         var pathExposedToA1 = ['A1', 'A-SR', 'A'];
140         var pathExposedToA = ['A'];
141         assert_array_equals(log.eventPath, expectedPath);
142         assert_array_equals(log.eventPath.length, log.pathAtTargets.length);
143         assert_array_equals(log.pathAtTargets[0], expectedPath);
144         assert_array_equals(log.pathAtTargets[1], expectedPath);
145         assert_array_equals(log.pathAtTargets[2], mode == 'open' ? expectedPath : pathExposedToA1);
146         assert_array_equals(log.pathAtTargets[3], mode == 'open' ? expectedPath : pathExposedToA1);
147         assert_array_equals(log.pathAtTargets[4], mode == 'open' ? expectedPath : pathExposedToA);
148         assert_array_equals(log.relatedTargets, ['A2-S', 'A2-S', 'A2-S', 'A2-S', 'A']);
149     }, 'The event must propagate out of ' + mode + ' mode shadow boundaries when the scoped flag is unset on an event with relatedTarget');
150 }
151
152 testUnscopedEventWithUnscopedRelatedTarget('open');
153 testUnscopedEventWithUnscopedRelatedTarget('closed');
154
155 /*
156 -SR: ShadowRoot  -S: Slot  target: (~)  relatedTarget: [~]  *: indicates start  digit: event path order
157 A ------------------------------- A-SR
158 + B ------------ B-SR             + A1 ----------- A1-SR (1)
159   + C            + B1 --- B1-SR   + A2-S [*; 0-1]  + A1a (*; 0)
160   + D --- D-SR     + B1a  + B1b --- B1b-SR
161           + D1            + B1c-S   + B1b1
162                                     + B1b2
163 */
164
165 function testScopedEventWithUnscopedRelatedTarget(mode) {
166     test(function () {
167         var nodes = createTestTree(mode);
168         var log = dispatchEventWithLog(nodes, nodes.A1a, new MouseEvent('foo', {scoped: true, relatedTargetScoped: false, bubbles: true, relatedTarget: nodes['A2-S']}));
169
170         var expectedPath = ['A1a', 'A1-SR'];
171         assert_array_equals(log.eventPath, expectedPath);
172         assert_array_equals(log.eventPath.length, log.pathAtTargets.length);
173         assert_array_equals(log.pathAtTargets[0], expectedPath);
174         assert_array_equals(log.pathAtTargets[1], expectedPath);
175         assert_array_equals(log.relatedTargets, ['A2-S', 'A2-S']);
176     }, 'The event must not propagate out of ' + mode + ' mode shadow boundaries when the scoped flag is set on an event with relatedTarget');
177 }
178
179 testScopedEventWithUnscopedRelatedTarget('open');
180 testScopedEventWithUnscopedRelatedTarget('closed');
181
182 /*
183 -SR: ShadowRoot  -S: Slot  target: (~)  relatedTarget: [~]  *: indicates start  digit: event path order
184 A ------------------------------------------------ A-SR
185 + B ------------ B-SR (4)                          + A1 --- A1-SR
186   + C            + B1 (3) [0,3-4] --- B1-SR (2)    + A2-S   + A1a
187   + D --- D-SR     + B1a (*; 0)       + B1b [1-2] --- B1b-SR
188           + D1                        + B1c-S (1)     + B1b1
189                                                       + B1b2 [*]
190 */
191
192 function testScopedEventWithUnscopedRelatedTargetThroughSlot(mode) {
193     test(function () {
194         var nodes = createTestTree(mode);
195         var log = dispatchEventWithLog(nodes, nodes.B1a, new MouseEvent('foo', {scoped: true, relatedTargetScoped: false, bubbles: true, relatedTarget: nodes['B1b2']}));
196
197         var expectedPath = ['B1a', 'B1c-S', 'B1-SR', 'B1', 'B-SR'];
198         var pathExposedToB1a = ['B1a', 'B1', 'B-SR'];
199         assert_array_equals(log.eventPath, expectedPath);
200         assert_array_equals(log.eventPath.length, log.pathAtTargets.length);
201         assert_array_equals(log.pathAtTargets[0], mode == 'open' ? expectedPath : pathExposedToB1a);
202         assert_array_equals(log.pathAtTargets[1], expectedPath);
203         assert_array_equals(log.pathAtTargets[2], expectedPath);
204         assert_array_equals(log.pathAtTargets[3], mode == 'open' ? expectedPath : pathExposedToB1a);
205         assert_array_equals(log.pathAtTargets[4], mode == 'open' ? expectedPath : pathExposedToB1a);
206         assert_array_equals(log.relatedTargets, ['B1', 'B1b', 'B1b', 'B1', 'B1']);
207     }, 'The event must not propagate out of ' + mode + ' mode shadow tree of the target but must propagate out of inner shadow trees when the scoped flag is set');
208 }
209
210 testScopedEventWithUnscopedRelatedTargetThroughSlot('open');
211 testScopedEventWithUnscopedRelatedTargetThroughSlot('closed');
212
213 /*
214 -SR: ShadowRoot  -S: Slot  target: (~)  relatedTarget: [~]  *: indicates start  digit: event path order
215 A ------------------------------- A-SR (3)
216 + B ------------ B-SR             + A1 (2) ------- A1-SR (1)
217   + C            + B1 --- B1-SR   + A2-S [*; 0-3]  + A1a (*; 0)
218   + D --- D-SR     + B1a  + B1b --- B1b-SR
219           + D1            + B1c-S   + B1b1
220                                     + B1b2
221 */
222
223 function testUnscopedEventWithScopedRelatedTarget(mode) {
224     test(function () {
225         var nodes = createTestTree(mode);
226         log = dispatchEventWithLog(nodes, nodes.A1a, new MouseEvent('foo', {scoped: false, relatedTargetScoped: true, bubbles: true, relatedTarget: nodes['A2-S']}));
227
228         var expectedPath = ['A1a', 'A1-SR', 'A1', 'A-SR'];
229         var pathExposedToA1 = ['A1', 'A-SR'];
230         assert_array_equals(log.eventPath, expectedPath);
231         assert_array_equals(log.eventPath.length, log.pathAtTargets.length);
232         assert_array_equals(log.pathAtTargets[0], expectedPath);
233         assert_array_equals(log.pathAtTargets[1], expectedPath);
234         assert_array_equals(log.pathAtTargets[2], mode == 'open' ? expectedPath : pathExposedToA1);
235         assert_array_equals(log.pathAtTargets[3], mode == 'open' ? expectedPath : pathExposedToA1);
236         assert_array_equals(log.relatedTargets, ['A2-S', 'A2-S', 'A2-S', 'A2-S']);
237     }, 'The event must propagate out of ' + mode + ' mode shadow tree in which the relative target and the relative related target are the same');
238 }
239
240 testUnscopedEventWithScopedRelatedTarget('open');
241 testUnscopedEventWithScopedRelatedTarget('closed');
242
243 /*
244 -SR: ShadowRoot  -S: Slot  target: (~)  relatedTarget: [~]  *: indicates start  digit: event path order
245 A (8) [0-5,8] ---------------------------------------- A-SR (7)
246 + B (5)  ------- B-SR (4)                              + A1 [6,7] --- A1-SR
247   + C            + B1 (3) ------- B1-SR (2)            + A2-S (6)     + A1a [*]
248   + D --- D-SR     + B1a (*; 0)   + B1b ------- B1b-SR
249           + D1                    + B1c-S (1)   + B1b1
250                                                 + B1b2
251 */
252
253 function testUnscopedEventWithScopedRelatedTargetThroughSlot(mode) {
254     test(function () {
255         var nodes = createTestTree(mode);
256         log = dispatchEventWithLog(nodes, nodes.B1a, new MouseEvent('foo', {scoped: false, relatedTargetScoped: true, bubbles: true, relatedTarget: nodes.A1a}));
257
258         var expectedPath =          ['B1a', 'B1c-S', 'B1-SR', 'B1', 'B-SR', 'B', 'A2-S', 'A-SR', 'A'];
259         var expectedRelatedTarget = ['A',   'A',     'A',     'A',   'A',   'A', 'A1',   'A1',   'A'];
260         var pathExposedToB1a =      ['B1a',                   'B1', 'B-SR', 'B',                 'A'];
261         var pathExposedToB1cS =     ['B1a', 'B1c-S', 'B1-SR', 'B1', 'B-SR', 'B',                 'A'];
262         var pathExposedToB =        [                                       'B',                 'A'];
263         var pathExposedToA1 =       [                                       'B', 'A2-S', 'A-SR', 'A'];
264
265         assert_array_equals(log.eventPath, expectedPath);
266         assert_array_equals(log.eventPath.length, log.pathAtTargets.length);
267         assert_array_equals(log.pathAtTargets[0], mode == 'open' ? expectedPath : pathExposedToB1a);
268         assert_array_equals(log.pathAtTargets[1], mode == 'open' ? expectedPath : pathExposedToB1cS);
269         assert_array_equals(log.pathAtTargets[2], mode == 'open' ? expectedPath : pathExposedToB1cS);
270         assert_array_equals(log.pathAtTargets[3], mode == 'open' ? expectedPath : pathExposedToB1a);
271         assert_array_equals(log.pathAtTargets[4], mode == 'open' ? expectedPath : pathExposedToB1a);
272         assert_array_equals(log.pathAtTargets[5], mode == 'open' ? expectedPath : pathExposedToB);
273         assert_array_equals(log.pathAtTargets[6], mode == 'open' ? expectedPath : pathExposedToA1);
274         assert_array_equals(log.pathAtTargets[7], mode == 'open' ? expectedPath : pathExposedToA1);
275         assert_array_equals(log.pathAtTargets[8], mode == 'open' ? expectedPath : pathExposedToB);
276         assert_array_equals(log.relatedTargets, expectedRelatedTarget);
277     }, 'deepPath() must contain and only contain the unclosed nodes of target in ' + mode + ' mode shadow trees');
278 }
279
280 testUnscopedEventWithScopedRelatedTargetThroughSlot('open');
281 testUnscopedEventWithScopedRelatedTargetThroughSlot('closed');
282
283 </script>
284 </body>
285 </html>