// META: script=/resources/test-only-api.js // META: script=/serial/resources/common.js // META: script=resources/automation.js serial_test(async (t, fake) => { const {port, fakePort} = await getFakeSerialPort(fake); const targets = [navigator.serial, port]; const expectedTargets = [navigator.serial]; const actualTargets = []; function eventHandler(evt) { actualTargets.push(evt.currentTarget); if (evt.currentTarget == navigator.serial) { evt.stopPropagation(); } } targets.forEach((target) => { target.addEventListener('foo', eventHandler, {capture: true}); // stopPropagation() during capturing prevents bubbling. target.addEventListener('foo', eventHandler); t.add_cleanup(() => { target.removeEventListener('foo', eventHandler, {capture: true}); target.removeEventListener('foo', eventHandler); }); }); port.dispatchEvent(new CustomEvent('foo', {bubbles: true})); assert_array_equals(actualTargets, expectedTargets, 'actualTargets'); }, 'stopPropagation() during capturing'); serial_test(async (t, fake) => { const {port, fakePort} = await getFakeSerialPort(fake); const targets = [navigator.serial, port]; const expectedTargets = [navigator.serial]; const actualTargets = []; function eventHandler(evt) { actualTargets.push(evt.currentTarget); if (evt.currentTarget == navigator.serial) { evt.cancelBubble = true; } } targets.forEach((target) => { target.addEventListener('foo', eventHandler, {capture: true}); // Setting cancelBubble during capturing prevents bubbling. target.addEventListener('foo', eventHandler); t.add_cleanup(() => { target.removeEventListener('foo', eventHandler, {capture: true}); target.removeEventListener('foo', eventHandler); }); }); port.dispatchEvent(new CustomEvent('foo', {bubbles: true})); assert_array_equals(actualTargets, expectedTargets, 'actualTargets'); }, 'Set cancelBubble during capturing'); serial_test(async (t, fake) => { const {port, fakePort} = await getFakeSerialPort(fake); const targets = [navigator.serial, port]; const expectedTargets = [port]; const actualTargets = []; function eventHandler(evt) { actualTargets.push(evt.currentTarget); if (evt.currentTarget == port) { evt.stopPropagation(); } } targets.forEach((target) => { target.addEventListener('foo', eventHandler); t.add_cleanup(() => { target.removeEventListener('foo', eventHandler); }); }); port.dispatchEvent(new CustomEvent('foo', {bubbles: true})); assert_array_equals(actualTargets, expectedTargets, 'actualTargets'); }, 'stopPropagation() during bubbling'); serial_test(async (t, fake) => { const {port, fakePort} = await getFakeSerialPort(fake); const targets = [navigator.serial, port]; const expectedTargets = [port]; const actualTargets = []; function eventHandler(evt) { actualTargets.push(evt.currentTarget); if (evt.currentTarget == port) { evt.cancelBubble = true; } } targets.forEach((target) => { target.addEventListener('foo', eventHandler); t.add_cleanup(() => { target.removeEventListener('foo', eventHandler); }); }); port.dispatchEvent(new CustomEvent('foo', {bubbles: true})); assert_array_equals(actualTargets, expectedTargets, 'actualTargets'); }, 'Set cancelBubble during bubbling'); serial_test(async (t, fake) => { const {port, fakePort} = await getFakeSerialPort(fake); const targets = [navigator.serial, port]; const expectedTargets = [ navigator.serial, port, navigator.serial, port, ]; const expectedTypes = [ 'foo', 'bar', 'bar', 'foo', ]; const actualTargets = []; const actualTypes = []; function eventHandler(evt) { actualTargets.push(evt.currentTarget); actualTypes.push(evt.type); if (evt.currentTarget == navigator.serial && evt.type == 'foo') { port.dispatchEvent(new CustomEvent('bar', {bubbles: true})); } } targets.forEach((target) => { target.addEventListener('foo', eventHandler, {capture: true}); target.addEventListener('bar', eventHandler); t.add_cleanup(() => { target.removeEventListener('foo', eventHandler, {capture: true}); target.removeEventListener('bar', eventHandler); }); }); port.dispatchEvent(new CustomEvent('foo', {bubbles: true})); assert_array_equals(actualTargets, expectedTargets, 'actualTargets'); assert_array_equals(actualTypes, expectedTypes, 'actualTypes'); }, 'An event dispatched in an event handler is propagated before continuing'); serial_test(async (t, fake) => { const {port, fakePort} = await getFakeSerialPort(fake); const targets = [navigator.serial, port]; const expected = [ 'capturing Serial', 'capturing SerialPort', 'bubbling SerialPort', 'bubbling Serial', ]; const actual = []; targets.forEach((target) => { const bubblingEventHandler = () => { actual.push(`bubbling ${target.constructor.name}`); }; target.addEventListener('foo', bubblingEventHandler); const capturingEventHandler = () => { actual.push(`capturing ${target.constructor.name}`); }; target.addEventListener('foo', capturingEventHandler, {capture: true}); t.add_cleanup(() => { target.removeEventListener('foo', bubblingEventHandler, {capture: true}); target.removeEventListener('foo', capturingEventHandler); }); }); port.dispatchEvent(new CustomEvent('foo', {bubbles: true})); assert_array_equals(actual, expected); }, 'Capturing and bubbling events delivered to listeners in the expected order');