Skip to content

Commit eece34c

Browse files
nissy-devtargos
authored andcommitted
test: add WPT tests for dom/events
PR-URL: #43151 Refs: #40678 Reviewed-By: Masashi Hirano <shisama07@gmail.com> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: James M Snell <jasnell@gmail.com>
1 parent 70d297c commit eece34c

File tree

106 files changed

+6906
-1
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

106 files changed

+6906
-1
lines changed

test/fixtures/wpt/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ Last update:
1313
- common: https://github.com/web-platform-tests/wpt/tree/03c5072aff/common
1414
- console: https://github.com/web-platform-tests/wpt/tree/3b1f72e99a/console
1515
- dom/abort: https://github.com/web-platform-tests/wpt/tree/c49cafb491/dom/abort
16+
- dom/events: https://github.com/web-platform-tests/wpt/tree/f8821adb28/dom/events
1617
- encoding: https://github.com/web-platform-tests/wpt/tree/35f70910d3/encoding
1718
- FileAPI: https://github.com/web-platform-tests/wpt/tree/3b279420d4/FileAPI
1819
- hr-time: https://github.com/web-platform-tests/wpt/tree/9910784394/hr-time
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
// META: title=AddEventListenerOptions.once
2+
3+
"use strict";
4+
5+
test(function() {
6+
var invoked_once = false;
7+
var invoked_normal = false;
8+
function handler_once() {
9+
invoked_once = true;
10+
}
11+
function handler_normal() {
12+
invoked_normal = true;
13+
}
14+
15+
const et = new EventTarget();
16+
et.addEventListener('test', handler_once, {once: true});
17+
et.addEventListener('test', handler_normal);
18+
et.dispatchEvent(new Event('test'));
19+
assert_equals(invoked_once, true, "Once handler should be invoked");
20+
assert_equals(invoked_normal, true, "Normal handler should be invoked");
21+
22+
invoked_once = false;
23+
invoked_normal = false;
24+
et.dispatchEvent(new Event('test'));
25+
assert_equals(invoked_once, false, "Once handler shouldn't be invoked again");
26+
assert_equals(invoked_normal, true, "Normal handler should be invoked again");
27+
et.removeEventListener('test', handler_normal);
28+
}, "Once listener should be invoked only once");
29+
30+
test(function() {
31+
const et = new EventTarget();
32+
var invoked_count = 0;
33+
function handler() {
34+
invoked_count++;
35+
if (invoked_count == 1)
36+
et.dispatchEvent(new Event('test'));
37+
}
38+
et.addEventListener('test', handler, {once: true});
39+
et.dispatchEvent(new Event('test'));
40+
assert_equals(invoked_count, 1, "Once handler should only be invoked once");
41+
42+
invoked_count = 0;
43+
function handler2() {
44+
invoked_count++;
45+
if (invoked_count == 1)
46+
et.addEventListener('test', handler2, {once: true});
47+
if (invoked_count <= 2)
48+
et.dispatchEvent(new Event('test'));
49+
}
50+
et.addEventListener('test', handler2, {once: true});
51+
et.dispatchEvent(new Event('test'));
52+
assert_equals(invoked_count, 2, "Once handler should only be invoked once after each adding");
53+
}, "Once listener should be invoked only once even if the event is nested");
54+
55+
test(function() {
56+
var invoked_count = 0;
57+
function handler() {
58+
invoked_count++;
59+
}
60+
61+
const et = new EventTarget();
62+
63+
et.addEventListener('test', handler, {once: true});
64+
et.addEventListener('test', handler);
65+
et.dispatchEvent(new Event('test'));
66+
assert_equals(invoked_count, 1, "The handler should only be added once");
67+
68+
invoked_count = 0;
69+
et.dispatchEvent(new Event('test'));
70+
assert_equals(invoked_count, 0, "The handler was added as a once listener");
71+
72+
invoked_count = 0;
73+
et.addEventListener('test', handler, {once: true});
74+
et.removeEventListener('test', handler);
75+
et.dispatchEvent(new Event('test'));
76+
assert_equals(invoked_count, 0, "The handler should have been removed");
77+
}, "Once listener should be added / removed like normal listeners");
78+
79+
test(function() {
80+
const et = new EventTarget();
81+
82+
var invoked_count = 0;
83+
84+
for (let n = 4; n > 0; n--) {
85+
et.addEventListener('test', (e) => {
86+
invoked_count++;
87+
e.stopImmediatePropagation();
88+
}, {once: true});
89+
}
90+
91+
for (let n = 4; n > 0; n--) {
92+
et.dispatchEvent(new Event('test'));
93+
}
94+
95+
assert_equals(invoked_count, 4, "The listeners should be invoked");
96+
}, "Multiple once listeners should be invoked even if the stopImmediatePropagation is set");
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
// META: title=AddEventListenerOptions.passive
2+
3+
test(function() {
4+
var supportsPassive = false;
5+
var query_options = {
6+
get passive() {
7+
supportsPassive = true;
8+
return false;
9+
},
10+
get dummy() {
11+
assert_unreached("dummy value getter invoked");
12+
return false;
13+
}
14+
};
15+
16+
const et = new EventTarget();
17+
et.addEventListener('test_event', null, query_options);
18+
assert_true(supportsPassive, "addEventListener doesn't support the passive option");
19+
20+
supportsPassive = false;
21+
et.removeEventListener('test_event', null, query_options);
22+
assert_false(supportsPassive, "removeEventListener supports the passive option when it should not");
23+
}, "Supports passive option on addEventListener only");
24+
25+
function testPassiveValue(optionsValue, expectedDefaultPrevented, existingEventTarget) {
26+
var defaultPrevented = undefined;
27+
var handler = function handler(e) {
28+
assert_false(e.defaultPrevented, "Event prematurely marked defaultPrevented");
29+
e.preventDefault();
30+
defaultPrevented = e.defaultPrevented;
31+
}
32+
const et = existingEventTarget || new EventTarget();
33+
et.addEventListener('test', handler, optionsValue);
34+
var uncanceled = et.dispatchEvent(new Event('test', {bubbles: true, cancelable: true}));
35+
36+
assert_equals(defaultPrevented, expectedDefaultPrevented, "Incorrect defaultPrevented for options: " + JSON.stringify(optionsValue));
37+
assert_equals(uncanceled, !expectedDefaultPrevented, "Incorrect return value from dispatchEvent");
38+
39+
et.removeEventListener('test', handler, optionsValue);
40+
}
41+
42+
test(function() {
43+
testPassiveValue(undefined, true);
44+
testPassiveValue({}, true);
45+
testPassiveValue({passive: false}, true);
46+
testPassiveValue({passive: true}, false);
47+
testPassiveValue({passive: 0}, true);
48+
testPassiveValue({passive: 1}, false);
49+
}, "preventDefault should be ignored if-and-only-if the passive option is true");
50+
51+
function testPassiveValueOnReturnValue(test, optionsValue, expectedDefaultPrevented) {
52+
var defaultPrevented = undefined;
53+
var handler = test.step_func(e => {
54+
assert_false(e.defaultPrevented, "Event prematurely marked defaultPrevented");
55+
e.returnValue = false;
56+
defaultPrevented = e.defaultPrevented;
57+
});
58+
const et = new EventTarget();
59+
et.addEventListener('test', handler, optionsValue);
60+
var uncanceled = et.dispatchEvent(new Event('test', {bubbles: true, cancelable: true}));
61+
62+
assert_equals(defaultPrevented, expectedDefaultPrevented, "Incorrect defaultPrevented for options: " + JSON.stringify(optionsValue));
63+
assert_equals(uncanceled, !expectedDefaultPrevented, "Incorrect return value from dispatchEvent");
64+
65+
et.removeEventListener('test', handler, optionsValue);
66+
}
67+
68+
async_test(t => {
69+
testPassiveValueOnReturnValue(t, undefined, true);
70+
testPassiveValueOnReturnValue(t, {}, true);
71+
testPassiveValueOnReturnValue(t, {passive: false}, true);
72+
testPassiveValueOnReturnValue(t, {passive: true}, false);
73+
testPassiveValueOnReturnValue(t, {passive: 0}, true);
74+
testPassiveValueOnReturnValue(t, {passive: 1}, false);
75+
t.done();
76+
}, "returnValue should be ignored if-and-only-if the passive option is true");
77+
78+
function testPassiveWithOtherHandlers(optionsValue, expectedDefaultPrevented) {
79+
var handlerInvoked1 = false;
80+
var dummyHandler1 = function() {
81+
handlerInvoked1 = true;
82+
};
83+
var handlerInvoked2 = false;
84+
var dummyHandler2 = function() {
85+
handlerInvoked2 = true;
86+
};
87+
88+
const et = new EventTarget();
89+
et.addEventListener('test', dummyHandler1, {passive:true});
90+
et.addEventListener('test', dummyHandler2);
91+
92+
testPassiveValue(optionsValue, expectedDefaultPrevented, et);
93+
94+
assert_true(handlerInvoked1, "Extra passive handler not invoked");
95+
assert_true(handlerInvoked2, "Extra non-passive handler not invoked");
96+
97+
et.removeEventListener('test', dummyHandler1);
98+
et.removeEventListener('test', dummyHandler2);
99+
}
100+
101+
test(function() {
102+
testPassiveWithOtherHandlers({}, true);
103+
testPassiveWithOtherHandlers({passive: false}, true);
104+
testPassiveWithOtherHandlers({passive: true}, false);
105+
}, "passive behavior of one listener should be unaffected by the presence of other listeners");
106+
107+
function testOptionEquivalence(optionValue1, optionValue2, expectedEquality) {
108+
var invocationCount = 0;
109+
var handler = function handler(e) {
110+
invocationCount++;
111+
}
112+
const et = new EventTarget();
113+
et.addEventListener('test', handler, optionValue1);
114+
et.addEventListener('test', handler, optionValue2);
115+
et.dispatchEvent(new Event('test', {bubbles: true}));
116+
assert_equals(invocationCount, expectedEquality ? 1 : 2, "equivalence of options " +
117+
JSON.stringify(optionValue1) + " and " + JSON.stringify(optionValue2));
118+
et.removeEventListener('test', handler, optionValue1);
119+
et.removeEventListener('test', handler, optionValue2);
120+
}
121+
122+
test(function() {
123+
// Sanity check options that should be treated as distinct handlers
124+
testOptionEquivalence({capture:true}, {capture:false, passive:false}, false);
125+
testOptionEquivalence({capture:true}, {passive:true}, false);
126+
127+
// Option values that should be treated as equivalent
128+
testOptionEquivalence({}, {passive:false}, true);
129+
testOptionEquivalence({passive:true}, {passive:false}, true);
130+
testOptionEquivalence(undefined, {passive:true}, true);
131+
testOptionEquivalence({capture: true, passive: false}, {capture: true, passive: true}, true);
132+
133+
}, "Equivalence of option values");
134+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
'use strict';
2+
3+
test(function() {
4+
let count = 0;
5+
function handler() {
6+
count++;
7+
}
8+
const et = new EventTarget();
9+
const controller = new AbortController();
10+
et.addEventListener('test', handler, { signal: controller.signal });
11+
et.dispatchEvent(new Event('test'));
12+
assert_equals(count, 1, "Adding a signal still adds a listener");
13+
et.dispatchEvent(new Event('test'));
14+
assert_equals(count, 2, "The listener was not added with the once flag");
15+
controller.abort();
16+
et.dispatchEvent(new Event('test'));
17+
assert_equals(count, 2, "Aborting on the controller removes the listener");
18+
et.addEventListener('test', handler, { signal: controller.signal });
19+
et.dispatchEvent(new Event('test'));
20+
assert_equals(count, 2, "Passing an aborted signal never adds the handler");
21+
}, "Passing an AbortSignal to addEventListener options should allow removing a listener");
22+
23+
test(function() {
24+
let count = 0;
25+
function handler() {
26+
count++;
27+
}
28+
const et = new EventTarget();
29+
const controller = new AbortController();
30+
et.addEventListener('test', handler, { signal: controller.signal });
31+
et.removeEventListener('test', handler);
32+
et.dispatchEvent(new Event('test'));
33+
assert_equals(count, 0, "The listener was still removed");
34+
}, "Passing an AbortSignal to addEventListener does not prevent removeEventListener");
35+
36+
test(function() {
37+
let count = 0;
38+
function handler() {
39+
count++;
40+
}
41+
const et = new EventTarget();
42+
const controller = new AbortController();
43+
et.addEventListener('test', handler, { signal: controller.signal, once: true });
44+
controller.abort();
45+
et.dispatchEvent(new Event('test'));
46+
assert_equals(count, 0, "The listener was still removed");
47+
}, "Passing an AbortSignal to addEventListener works with the once flag");
48+
49+
test(function() {
50+
let count = 0;
51+
function handler() {
52+
count++;
53+
}
54+
const et = new EventTarget();
55+
const controller = new AbortController();
56+
et.addEventListener('test', handler, { signal: controller.signal, once: true });
57+
et.removeEventListener('test', handler);
58+
et.dispatchEvent(new Event('test'));
59+
assert_equals(count, 0, "The listener was still removed");
60+
}, "Removing a once listener works with a passed signal");
61+
62+
test(function() {
63+
let count = 0;
64+
function handler() {
65+
count++;
66+
}
67+
const et = new EventTarget();
68+
const controller = new AbortController();
69+
et.addEventListener('first', handler, { signal: controller.signal, once: true });
70+
et.addEventListener('second', handler, { signal: controller.signal, once: true });
71+
controller.abort();
72+
et.dispatchEvent(new Event('first'));
73+
et.dispatchEvent(new Event('second'));
74+
assert_equals(count, 0, "The listener was still removed");
75+
}, "Passing an AbortSignal to multiple listeners");
76+
77+
test(function() {
78+
let count = 0;
79+
function handler() {
80+
count++;
81+
}
82+
const et = new EventTarget();
83+
const controller = new AbortController();
84+
et.addEventListener('test', handler, { signal: controller.signal, capture: true });
85+
controller.abort();
86+
et.dispatchEvent(new Event('test'));
87+
assert_equals(count, 0, "The listener was still removed");
88+
}, "Passing an AbortSignal to addEventListener works with the capture flag");
89+
90+
test(function() {
91+
let count = 0;
92+
function handler() {
93+
count++;
94+
}
95+
const et = new EventTarget();
96+
const controller = new AbortController();
97+
et.addEventListener('test', () => {
98+
controller.abort();
99+
}, { signal: controller.signal });
100+
et.addEventListener('test', handler, { signal: controller.signal });
101+
et.dispatchEvent(new Event('test'));
102+
assert_equals(count, 0, "The listener was still removed");
103+
}, "Aborting from a listener does not call future listeners");
104+
105+
test(function() {
106+
let count = 0;
107+
function handler() {
108+
count++;
109+
}
110+
const et = new EventTarget();
111+
const controller = new AbortController();
112+
et.addEventListener('test', () => {
113+
et.addEventListener('test', handler, { signal: controller.signal });
114+
controller.abort();
115+
}, { signal: controller.signal });
116+
et.dispatchEvent(new Event('test'));
117+
assert_equals(count, 0, "The listener was still removed");
118+
}, "Adding then aborting a listener in another listener does not call it");
119+
120+
test(function() {
121+
const et = new EventTarget();
122+
const ac = new AbortController();
123+
let count = 0;
124+
et.addEventListener('foo', () => {
125+
et.addEventListener('foo', () => {
126+
count++;
127+
if (count > 5) ac.abort();
128+
et.dispatchEvent(new Event('foo'));
129+
}, { signal: ac.signal });
130+
et.dispatchEvent(new Event('foo'));
131+
}, { once: true });
132+
et.dispatchEvent(new Event('foo'));
133+
}, "Aborting from a nested listener should remove it");
134+
135+
test(function() {
136+
const et = new EventTarget();
137+
assert_throws_js(TypeError, () => { et.addEventListener("foo", () => {}, { signal: null }); });
138+
}, "Passing null as the signal should throw");
139+
140+
test(function() {
141+
const et = new EventTarget();
142+
assert_throws_js(TypeError, () => { et.addEventListener("foo", null, { signal: null }); });
143+
}, "Passing null as the signal should throw (listener is also null)");

0 commit comments

Comments
 (0)