Extensions-to-Event-Interface.html (11195B)
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 composedPath() 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 </head> 12 <body> 13 <div id="log"></div> 14 <script> 15 16 test(function () { 17 var event = new Event('my-event'); 18 assert_array_equals(event.composedPath(), []); 19 }, 'composedPath() must return an empty array when the event has not been dispatched'); 20 21 test(function () { 22 var event = new Event('my-event'); 23 document.body.dispatchEvent(event); 24 assert_array_equals(event.composedPath(), []); 25 }, 'composedPath() must return an empty array when the event is no longer dispatched'); 26 27 test(function () { 28 var event = new Event('my-event'); 29 assert_false(event.composed); 30 }, 'composed on EventInit must default to false'); 31 32 test(function () { 33 var event = new Event('my-event', {composed: true}); 34 assert_true(event.composed); 35 36 event = new Event('my-event', {composed: false}); 37 assert_false(event.composed); 38 }, 'composed on EventInit must set the composed flag'); 39 40 /* 41 -SR: ShadowRoot -S: Slot target: (~) *: indicates start digit: event path order 42 A (4) --------------------------- A-SR (3) 43 + B ------------ B-SR + A1 (2) --- A1-SR (1) 44 + C + B1 --- B1-SR + A2-S + A1a (*; 0) 45 + D --- D-SR + B1a + B1b --- B1b-SR 46 + D1 + B1c-S + B1b1 47 + B1b2 48 */ 49 50 function testComposedEvent(mode) { 51 test(function () { 52 var nodes = createFixedTestTree(mode); 53 var log = dispatchEventWithEventLog(nodes, nodes.A1a, new Event('my-event', {composed: true, bubbles: true})); 54 55 var expectedPath = ['A1a', 'A1-SR', 'A1', 'A-SR', 'A']; 56 assert_array_equals(log.eventPath, expectedPath); 57 assert_equals(log.eventPath.length, log.pathAtTargets.length); 58 assert_array_equals(log.pathAtTargets[0], expectedPath); 59 assert_array_equals(log.pathAtTargets[1], expectedPath); 60 assert_array_equals(log.pathAtTargets[2], mode == 'open' ? expectedPath : ['A1', 'A-SR', 'A'], 61 'composedPath must only contain unclosed nodes of the current target.'); 62 }, 'The event must propagate out of ' + mode + ' mode shadow boundaries when the composed flag is set'); 63 } 64 65 testComposedEvent('open'); 66 testComposedEvent('closed'); 67 68 /* 69 -SR: ShadowRoot -S: Slot target: (~) *: indicates start digit: event path order 70 A ------------------------------- A-SR 71 + B ------------ B-SR + A1 --- A1-SR (1) 72 + C + B1 --- B1-SR + A2-S + A1a (*; 0) 73 + D --- D-SR + B1a + B1b --- B1b-SR 74 + D1 + B1c-S + B1b1 75 + B1b2 76 */ 77 78 function testNonComposedEvent(mode) { 79 test(function () { 80 var nodes = createFixedTestTree(mode); 81 var log = dispatchEventWithEventLog(nodes, nodes.A1a, new Event('my-event', {composed: false, bubbles: true})); 82 83 var expectedPath = ['A1a', 'A1-SR']; 84 assert_array_equals(log.eventPath, expectedPath); 85 assert_equals(log.eventPath.length, log.pathAtTargets.length); 86 assert_array_equals(log.pathAtTargets[0], expectedPath); 87 assert_array_equals(log.pathAtTargets[1], expectedPath); 88 }, 'The event must not propagate out of ' + mode + ' mode shadow boundaries when the composed flag is unset'); 89 } 90 91 testNonComposedEvent('open'); 92 testNonComposedEvent('closed'); 93 94 /* 95 -SR: ShadowRoot -S: Slot target: (~) relatedTarget: [~] *: indicates start digit: event path order 96 A ------------------------------- A-SR 97 + B ------------ B-SR + A1 ----------- A1-SR (1) 98 + C + B1 --- B1-SR + A2-S [*; 0-1] + A1a (*; 0) 99 + D --- D-SR + B1a + B1b --- B1b-SR 100 + D1 + B1c-S + B1b1 101 + B1b2 102 */ 103 104 function testNonComposedEventWithRelatedTarget(mode) { 105 test(function () { 106 var nodes = createFixedTestTree(mode); 107 var log = dispatchEventWithEventLog(nodes, nodes.A1a, new MouseEvent('foo', {composed: false, bubbles: true, relatedTarget: nodes['A2-S']})); 108 109 var expectedPath = ['A1a', 'A1-SR']; 110 assert_array_equals(log.eventPath, expectedPath); 111 assert_equals(log.eventPath.length, log.pathAtTargets.length); 112 assert_array_equals(log.pathAtTargets[0], expectedPath); 113 assert_array_equals(log.pathAtTargets[1], expectedPath); 114 assert_array_equals(log.relatedTargets, ['A2-S', 'A2-S']); 115 }, 'The event must not propagate out of ' + mode + ' mode shadow boundaries when the composed flag is unset on an event with relatedTarget'); 116 } 117 118 testNonComposedEventWithRelatedTarget('open'); 119 testNonComposedEventWithRelatedTarget('closed'); 120 121 /* 122 -SR: ShadowRoot -S: Slot target: (~) relatedTarget: [~] *: indicates start digit: event path order 123 A ------------------------------------------------ A-SR 124 + B ------------ B-SR (4) + A1 --- A1-SR 125 + C + B1 (3) [0,3-4] --- B1-SR (2) + A2-S + A1a 126 + D --- D-SR + B1a (*; 0) + B1b [1-2] --- B1b-SR 127 + D1 + B1c-S (1) + B1b1 128 + B1b2 [*] 129 */ 130 131 function testScopedEventWithUnscopedRelatedTargetThroughSlot(mode) { 132 test(function () { 133 var nodes = createFixedTestTree(mode); 134 var log = dispatchEventWithEventLog(nodes, nodes.B1a, new MouseEvent('foo', {scoped: true, relatedTargetScoped: false, bubbles: true, relatedTarget: nodes['B1b2']})); 135 136 var expectedPath = ['B1a', 'B1c-S', 'B1-SR', 'B1', 'B-SR']; 137 var pathExposedToB1a = ['B1a', 'B1', 'B-SR']; 138 assert_array_equals(log.eventPath, expectedPath); 139 assert_equals(log.eventPath.length, log.pathAtTargets.length); 140 assert_array_equals(log.pathAtTargets[0], mode == 'open' ? expectedPath : pathExposedToB1a); 141 assert_array_equals(log.pathAtTargets[1], expectedPath); 142 assert_array_equals(log.pathAtTargets[2], expectedPath); 143 assert_array_equals(log.pathAtTargets[3], mode == 'open' ? expectedPath : pathExposedToB1a); 144 assert_array_equals(log.pathAtTargets[4], mode == 'open' ? expectedPath : pathExposedToB1a); 145 assert_array_equals(log.relatedTargets, ['B1', 'B1b', 'B1b', 'B1', 'B1']); 146 }, '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'); 147 } 148 149 testScopedEventWithUnscopedRelatedTargetThroughSlot('open'); 150 testScopedEventWithUnscopedRelatedTargetThroughSlot('closed'); 151 152 /* 153 -SR: ShadowRoot -S: Slot target: (~) relatedTarget: [~] *: indicates start digit: event path order 154 A ------------------------------- A-SR (3) 155 + B ------------ B-SR + A1 (2) ------- A1-SR (1) 156 + C + B1 --- B1-SR + A2-S [*; 0-3] + A1a (*; 0) 157 + D --- D-SR + B1a + B1b --- B1b-SR 158 + D1 + B1c-S + B1b1 159 + B1b2 160 */ 161 162 function testComposedEventWithRelatedTarget(mode) { 163 test(function () { 164 var nodes = createFixedTestTree(mode); 165 log = dispatchEventWithEventLog(nodes, nodes.A1a, new MouseEvent('foo', {composed: true, bubbles: true, relatedTarget: nodes['A2-S']})); 166 167 var expectedPath = ['A1a', 'A1-SR', 'A1', 'A-SR']; 168 var pathExposedToA1 = ['A1', 'A-SR']; 169 assert_array_equals(log.eventPath, expectedPath); 170 assert_equals(log.eventPath.length, log.pathAtTargets.length); 171 assert_array_equals(log.pathAtTargets[0], expectedPath); 172 assert_array_equals(log.pathAtTargets[1], expectedPath); 173 assert_array_equals(log.pathAtTargets[2], mode == 'open' ? expectedPath : pathExposedToA1); 174 assert_array_equals(log.pathAtTargets[3], mode == 'open' ? expectedPath : pathExposedToA1); 175 assert_array_equals(log.relatedTargets, ['A2-S', 'A2-S', 'A2-S', 'A2-S']); 176 }, 'The event must propagate out of ' + mode + ' mode shadow tree in which the relative target and the relative related target are the same'); 177 } 178 179 testComposedEventWithRelatedTarget('open'); 180 testComposedEventWithRelatedTarget('closed'); 181 182 /* 183 -SR: ShadowRoot -S: Slot target: (~) relatedTarget: [~] *: indicates start digit: event path order 184 A (8) [0-5,8] ---------------------------------------- A-SR (7) 185 + B (5) ------- B-SR (4) + A1 [6,7] --- A1-SR 186 + C + B1 (3) ------- B1-SR (2) + A2-S (6) + A1a [*] 187 + D --- D-SR + B1a (*; 0) + B1b ------- B1b-SR 188 + D1 + B1c-S (1) + B1b1 189 + B1b2 190 */ 191 192 function testComposedEventThroughSlot(mode) { 193 test(function () { 194 var nodes = createFixedTestTree(mode); 195 log = dispatchEventWithEventLog(nodes, nodes.B1a, new MouseEvent('foo', {composed: true, bubbles: true, relatedTarget: nodes.A1a})); 196 197 var expectedPath = ['B1a', 'B1c-S', 'B1-SR', 'B1', 'B-SR', 'B', 'A2-S', 'A-SR', 'A']; 198 var expectedRelatedTarget = ['A', 'A', 'A', 'A', 'A', 'A', 'A1', 'A1', 'A']; 199 var pathExposedToB1a = ['B1a', 'B1', 'B-SR', 'B', 'A']; 200 var pathExposedToB1cS = ['B1a', 'B1c-S', 'B1-SR', 'B1', 'B-SR', 'B', 'A']; 201 var pathExposedToB = [ 'B', 'A']; 202 var pathExposedToA1 = [ 'B', 'A2-S', 'A-SR', 'A']; 203 204 assert_array_equals(log.eventPath, expectedPath); 205 assert_equals(log.eventPath.length, log.pathAtTargets.length); 206 assert_array_equals(log.pathAtTargets[0], mode == 'open' ? expectedPath : pathExposedToB1a); 207 assert_array_equals(log.pathAtTargets[1], mode == 'open' ? expectedPath : pathExposedToB1cS); 208 assert_array_equals(log.pathAtTargets[2], mode == 'open' ? expectedPath : pathExposedToB1cS); 209 assert_array_equals(log.pathAtTargets[3], mode == 'open' ? expectedPath : pathExposedToB1a); 210 assert_array_equals(log.pathAtTargets[4], mode == 'open' ? expectedPath : pathExposedToB1a); 211 assert_array_equals(log.pathAtTargets[5], mode == 'open' ? expectedPath : pathExposedToB); 212 assert_array_equals(log.pathAtTargets[6], mode == 'open' ? expectedPath : pathExposedToA1); 213 assert_array_equals(log.pathAtTargets[7], mode == 'open' ? expectedPath : pathExposedToA1); 214 assert_array_equals(log.pathAtTargets[8], mode == 'open' ? expectedPath : pathExposedToB); 215 assert_array_equals(log.relatedTargets, expectedRelatedTarget); 216 }, 'composedPath() must contain and only contain the unclosed nodes of target in ' + mode + ' mode shadow trees'); 217 } 218 219 testComposedEventThroughSlot('open'); 220 testComposedEventThroughSlot('closed'); 221 222 </script> 223 </body> 224 </html>