@gjsify/dom-events 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -0
- package/lib/cjs/index.js +17 -0
- package/lib/esm/index.js +1 -0
- package/package.json +46 -0
- package/src/error-handler.spec.ts +65 -0
- package/src/event-target.spec.ts +470 -0
- package/src/event.spec.ts +492 -0
- package/src/index.ts +1 -0
- package/src/test.mts +8 -0
- package/test.gjs.js +34758 -0
- package/test.gjs.js.map +7 -0
- package/test.gjs.mjs +35720 -0
- package/test.node.js +1226 -0
- package/test.node.js.map +7 -0
- package/test.node.mjs +9879 -0
- package/tsconfig.json +19 -0
- package/tsconfig.types.json +8 -0
- package/tsconfig.types.tsbuildinfo +1 -0
package/README.md
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
# @gjsify/dom-events
|
|
2
|
+
|
|
3
|
+
## Inspirations and credits
|
|
4
|
+
- https://deno.land/manual@v1.29.2/runtime/web_platform_apis#customevent-eventtarget-and-eventlistener
|
|
5
|
+
- https://github.com/jsdom/jsdom/tree/master/lib/jsdom/living/events
|
|
6
|
+
- https://github.com/capricorn86/happy-dom/tree/master/packages/happy-dom/src/event
|
package/lib/cjs/index.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
var __copyProps = (to, from, except, desc) => {
|
|
6
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
7
|
+
for (let key of __getOwnPropNames(from))
|
|
8
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
9
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
10
|
+
}
|
|
11
|
+
return to;
|
|
12
|
+
};
|
|
13
|
+
var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
|
|
14
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
15
|
+
var src_exports = {};
|
|
16
|
+
module.exports = __toCommonJS(src_exports);
|
|
17
|
+
__reExport(src_exports, require("@gjsify/deno-runtime/ext/web/02_event"), module.exports);
|
package/lib/esm/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "@gjsify/deno-runtime/ext/web/02_event";
|
package/package.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@gjsify/dom-events",
|
|
3
|
+
"version": "0.0.2",
|
|
4
|
+
"description": "Web events module for Gjs",
|
|
5
|
+
"main": "lib/cjs/index.js",
|
|
6
|
+
"module": "lib/esm/index.js",
|
|
7
|
+
"types": "lib/types/index.d.js",
|
|
8
|
+
"type": "module",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"import": {
|
|
12
|
+
"types": "./lib/types/index.d.ts",
|
|
13
|
+
"default": "./lib/esm/index.js"
|
|
14
|
+
},
|
|
15
|
+
"require": {
|
|
16
|
+
"types": "./lib/types/index.d.ts",
|
|
17
|
+
"default": "./lib/cjs/index.js"
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"scripts": {
|
|
22
|
+
"clear": "rm -rf lib tsconfig.tsbuildinfo test.gjs.mjs",
|
|
23
|
+
"print:name": "echo '@gjsify/dom-events'",
|
|
24
|
+
"build": "yarn print:name && yarn build:gjsify && yarn build:types",
|
|
25
|
+
"build:gjsify": "gjsify build --library 'src/**/*.{ts,js}' --exclude 'src/**/*.spec.{mts,ts}' 'src/test.{mts,ts}'",
|
|
26
|
+
"build:types": "tsc --project tsconfig.types.json || exit 0",
|
|
27
|
+
"build:test": "yarn build:test:gjs",
|
|
28
|
+
"build:test:gjs": "gjsify build src/test.mts --app gjs --outfile test.gjs.mjs",
|
|
29
|
+
"test": "yarn print:name && yarn build:gjsify && yarn build:test && yarn test:gjs",
|
|
30
|
+
"test:gjs": "gjs -m test.gjs.mjs"
|
|
31
|
+
},
|
|
32
|
+
"keywords": [
|
|
33
|
+
"gjs",
|
|
34
|
+
"node",
|
|
35
|
+
"event"
|
|
36
|
+
],
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"@gjsify/cli": "^0.0.2",
|
|
39
|
+
"@gjsify/unit": "^0.0.2",
|
|
40
|
+
"@types/node": "^20.3.1",
|
|
41
|
+
"typescript": "^5.1.3"
|
|
42
|
+
},
|
|
43
|
+
"dependencies": {
|
|
44
|
+
"@gjsify/deno-runtime": "^0.0.2"
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { describe, it, expect, assert, spy, on } from '@gjsify/unit';
|
|
2
|
+
|
|
3
|
+
import { Event, EventTarget } from "@gjsify/dom-events";
|
|
4
|
+
import process from 'process';
|
|
5
|
+
|
|
6
|
+
export const ErrorHandlerTest = async () => {
|
|
7
|
+
await describe("The default error handler", async () => {
|
|
8
|
+
|
|
9
|
+
// TODO: FIXME
|
|
10
|
+
await on([], async () => {
|
|
11
|
+
await it("should dispatch an ErrorEvent if a listener threw an error", async () => {
|
|
12
|
+
const originalConsoleError = console.error
|
|
13
|
+
const f = spy((_message, _source, _lineno, _colno, _error) => {})
|
|
14
|
+
const consoleError = spy((..._: any[]) => {})
|
|
15
|
+
const target = new EventTarget()
|
|
16
|
+
const error = new Error("test error")
|
|
17
|
+
target.addEventListener("foo", () => {
|
|
18
|
+
throw error
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
window.onerror = f
|
|
22
|
+
|
|
23
|
+
try {
|
|
24
|
+
target.dispatchEvent(new Event("foo"))
|
|
25
|
+
} finally {
|
|
26
|
+
window.onerror = null
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
assert.strictEqual(f.calls.length, 1, "f should be called.")
|
|
30
|
+
// TODO: fails on Deno
|
|
31
|
+
// assert.strictEqual(f.calls[0].arguments[0], error.message)
|
|
32
|
+
// assert.strictEqual(f.calls[0].arguments[4], error)
|
|
33
|
+
assert.strictEqual(
|
|
34
|
+
consoleError.calls.length,
|
|
35
|
+
1,
|
|
36
|
+
"console.error should be called.",
|
|
37
|
+
)
|
|
38
|
+
assert.strictEqual(consoleError.calls[0].arguments[0], error)
|
|
39
|
+
})
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
// TODO: FIXME
|
|
43
|
+
await on([], async () => {
|
|
44
|
+
await it("should emit an uncaughtException event if a listener threw an error", async () => {
|
|
45
|
+
const onUncaughtException = spy(_event => {})
|
|
46
|
+
const target = new EventTarget()
|
|
47
|
+
const error = new Error("test error")
|
|
48
|
+
target.addEventListener("foo", () => {
|
|
49
|
+
throw error
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
process.on("uncaughtException", onUncaughtException)
|
|
53
|
+
target.dispatchEvent(new Event("foo"))
|
|
54
|
+
process.removeListener("uncaughtException", onUncaughtException);
|
|
55
|
+
|
|
56
|
+
TODO: assert.strictEqual(onUncaughtException.calls.length, 1, "onUncaughtException should be called.")
|
|
57
|
+
|
|
58
|
+
// TODO: this are currently not the same objects, see https://gitlab.gnome.org/GNOME/gjs/-/issues/523
|
|
59
|
+
// assert.strictEqual(onUncaughtException.calls[0].arguments[0], error)
|
|
60
|
+
TODO: expect(onUncaughtException.calls[0].arguments[0].message).toBe(error.message)
|
|
61
|
+
TODO: expect(onUncaughtException.calls[0].arguments[0].stack?.trim()).toBe(error.stack?.trim())
|
|
62
|
+
})
|
|
63
|
+
})
|
|
64
|
+
})
|
|
65
|
+
}
|
|
@@ -0,0 +1,470 @@
|
|
|
1
|
+
import { describe, it, assert, Spy, spy, beforeEach } from '@gjsify/unit';
|
|
2
|
+
|
|
3
|
+
import { Event, EventTarget } from "@gjsify/dom-events";
|
|
4
|
+
import { AbortSignal } from "@gjsify/abort-controller";
|
|
5
|
+
|
|
6
|
+
export const EventTargetTest = async () => {
|
|
7
|
+
await describe("EventTarget.constructor", async () => {
|
|
8
|
+
|
|
9
|
+
await it("should not throw", async () => {
|
|
10
|
+
assert(new EventTarget())
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
await it("should throw a TypeError if called as a function.", async () => {
|
|
14
|
+
assert.throws(() => {
|
|
15
|
+
// @ts-expect-error
|
|
16
|
+
EventTarget() // eslint-disable-line new-cap
|
|
17
|
+
}, TypeError)
|
|
18
|
+
})
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
await describe("EventTarget.removeEventListener method", async () => {
|
|
22
|
+
let target: EventTarget
|
|
23
|
+
|
|
24
|
+
beforeEach(async () => {
|
|
25
|
+
target = new EventTarget();
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
await it("should do nothing if callback is nothing.", async () => {
|
|
29
|
+
target.removeEventListener("foo", null)
|
|
30
|
+
target.removeEventListener("foo", undefined)
|
|
31
|
+
})
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
await describe("EventTarget.dispatchEvent method", async () => {
|
|
35
|
+
let target: EventTarget;
|
|
36
|
+
|
|
37
|
+
beforeEach(async () => {
|
|
38
|
+
target = new EventTarget();
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
await it("should throw a TypeError if the argument was not present", async () => {
|
|
42
|
+
assert.throws(() => {
|
|
43
|
+
// @ts-expect-error
|
|
44
|
+
target.dispatchEvent()
|
|
45
|
+
}, TypeError)
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
await it("should not throw even if listeners don't exist", async () => {
|
|
49
|
+
const retv = target.dispatchEvent(new Event("foo"))
|
|
50
|
+
assert.strictEqual(retv, true)
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
await it("should not throw even if empty object had been added", async () => {
|
|
54
|
+
const f = {}
|
|
55
|
+
target.addEventListener("foo", f as EventListener)
|
|
56
|
+
const retv = target.dispatchEvent(new Event("foo"))
|
|
57
|
+
assert.strictEqual(retv, true)
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
await it("should call obj.handleEvent method even if added later", async () => {
|
|
61
|
+
const event = new Event("foo")
|
|
62
|
+
const f: { handleEvent?: Spy<(event: Event) => void> } = {}
|
|
63
|
+
target.addEventListener("foo", f as EventListener)
|
|
64
|
+
f.handleEvent = spy()
|
|
65
|
+
const retv = target.dispatchEvent(event)
|
|
66
|
+
|
|
67
|
+
assert.strictEqual(
|
|
68
|
+
f.handleEvent.calls.length,
|
|
69
|
+
1,
|
|
70
|
+
"handleEvent should be called",
|
|
71
|
+
)
|
|
72
|
+
assert.strictEqual(f.handleEvent.calls[0].this, f)
|
|
73
|
+
assert.strictEqual(f.handleEvent.calls[0].arguments[0], event)
|
|
74
|
+
assert.strictEqual(retv, true)
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
await it("should call a registered listener.", async () => {
|
|
78
|
+
const f1 = spy((_event: Event) => {})
|
|
79
|
+
const f2 = spy((_event: Event) => {})
|
|
80
|
+
target.addEventListener("foo", f1)
|
|
81
|
+
target.addEventListener("bar", f2)
|
|
82
|
+
|
|
83
|
+
const event = new Event("foo")
|
|
84
|
+
const retv = target.dispatchEvent(event)
|
|
85
|
+
|
|
86
|
+
assert.strictEqual(f1.calls.length, 1, "foo should be called once")
|
|
87
|
+
assert.strictEqual(
|
|
88
|
+
f1.calls[0].arguments.length,
|
|
89
|
+
1,
|
|
90
|
+
"the argument of callback should be one",
|
|
91
|
+
)
|
|
92
|
+
assert.strictEqual(
|
|
93
|
+
f1.calls[0].arguments[0],
|
|
94
|
+
event,
|
|
95
|
+
"the argument of callback should be the given Event object",
|
|
96
|
+
)
|
|
97
|
+
assert.strictEqual(f2.calls.length, 0, "bar should not be called")
|
|
98
|
+
assert.strictEqual(retv, true)
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
await it("should not call subsequent listeners if a listener called `event.stopImmediatePropagation()`.", async () => {
|
|
102
|
+
const f1 = spy((_event: Event) => {})
|
|
103
|
+
const f2 = spy((event: Event) => {
|
|
104
|
+
event.stopImmediatePropagation()
|
|
105
|
+
})
|
|
106
|
+
const f3 = spy((_event: Event) => {})
|
|
107
|
+
const f4 = spy((_event: Event) => {})
|
|
108
|
+
target.addEventListener("foo", f1)
|
|
109
|
+
target.addEventListener("foo", f2)
|
|
110
|
+
target.addEventListener("foo", f3)
|
|
111
|
+
target.addEventListener("foo", f4)
|
|
112
|
+
|
|
113
|
+
const retv = target.dispatchEvent(new Event("foo"))
|
|
114
|
+
|
|
115
|
+
assert.strictEqual(f1.calls.length, 1, "f1 should be called")
|
|
116
|
+
assert.strictEqual(f2.calls.length, 1, "f2 should be called")
|
|
117
|
+
assert.strictEqual(f3.calls.length, 0, "f3 should not be called")
|
|
118
|
+
assert.strictEqual(f4.calls.length, 0, "f4 should not be called")
|
|
119
|
+
assert.strictEqual(retv, true)
|
|
120
|
+
})
|
|
121
|
+
|
|
122
|
+
await it("should return true even if a listener called 'event.preventDefault()' if the event is not cancelable.", async () => {
|
|
123
|
+
target.addEventListener("foo", event => {
|
|
124
|
+
event.preventDefault()
|
|
125
|
+
})
|
|
126
|
+
const retv = target.dispatchEvent(new Event("foo"))
|
|
127
|
+
|
|
128
|
+
assert.strictEqual(retv, true)
|
|
129
|
+
})
|
|
130
|
+
|
|
131
|
+
await it("should return false if a listener called 'event.preventDefault()' and the event is cancelable.", async () => {
|
|
132
|
+
target.addEventListener("foo", event => {
|
|
133
|
+
event.preventDefault()
|
|
134
|
+
})
|
|
135
|
+
const retv = target.dispatchEvent(
|
|
136
|
+
new Event("foo", { cancelable: true }),
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
assert.strictEqual(retv, false)
|
|
140
|
+
})
|
|
141
|
+
|
|
142
|
+
await it("should return true even if a listener called 'event.preventDefault()' if passive option is present.", async () => {
|
|
143
|
+
target.addEventListener(
|
|
144
|
+
"foo",
|
|
145
|
+
event => {
|
|
146
|
+
event.preventDefault()
|
|
147
|
+
},
|
|
148
|
+
{ passive: true },
|
|
149
|
+
)
|
|
150
|
+
const retv = target.dispatchEvent(
|
|
151
|
+
new Event("foo", { cancelable: true }),
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
assert.strictEqual(retv, true)
|
|
155
|
+
})
|
|
156
|
+
|
|
157
|
+
await it("should return false if a listener called 'event.returnValue = false' and the event is cancelable.", async () => {
|
|
158
|
+
target.addEventListener("foo", event => {
|
|
159
|
+
event.returnValue = false
|
|
160
|
+
})
|
|
161
|
+
const retv = target.dispatchEvent(
|
|
162
|
+
new Event("foo", { cancelable: true }),
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
assert.strictEqual(retv, false)
|
|
166
|
+
})
|
|
167
|
+
|
|
168
|
+
await it("should remove a listener if once option is present.", async () => {
|
|
169
|
+
const f1 = spy()
|
|
170
|
+
const f2 = spy()
|
|
171
|
+
const f3 = spy()
|
|
172
|
+
target.addEventListener("foo", f1, { once: true })
|
|
173
|
+
target.addEventListener("foo", f2, { once: true })
|
|
174
|
+
target.addEventListener("foo", f3, { once: true })
|
|
175
|
+
|
|
176
|
+
const retv = target.dispatchEvent(new Event("foo"))
|
|
177
|
+
target.dispatchEvent(new Event("foo"))
|
|
178
|
+
|
|
179
|
+
assert.strictEqual(f1.calls.length, 1, "f1 should be called once")
|
|
180
|
+
assert.strictEqual(f2.calls.length, 1, "f2 should be called once")
|
|
181
|
+
assert.strictEqual(f3.calls.length, 1, "f3 should be called once")
|
|
182
|
+
assert.strictEqual(retv, true)
|
|
183
|
+
})
|
|
184
|
+
|
|
185
|
+
await it("should handle removing in event listeners correctly. Remove 0 at 0.", async () => {
|
|
186
|
+
const f1 = spy(() => {
|
|
187
|
+
target.removeEventListener("foo", f1)
|
|
188
|
+
})
|
|
189
|
+
const f2 = spy()
|
|
190
|
+
const f3 = spy()
|
|
191
|
+
target.addEventListener("foo", f1)
|
|
192
|
+
target.addEventListener("foo", f2)
|
|
193
|
+
target.addEventListener("foo", f3)
|
|
194
|
+
|
|
195
|
+
target.dispatchEvent(new Event("foo"))
|
|
196
|
+
target.dispatchEvent(new Event("foo"))
|
|
197
|
+
|
|
198
|
+
assert.strictEqual(f1.calls.length, 1, "f1 should be called once")
|
|
199
|
+
assert.strictEqual(f2.calls.length, 2, "f2 should be called twice")
|
|
200
|
+
assert.strictEqual(f3.calls.length, 2, "f3 should be called twice")
|
|
201
|
+
})
|
|
202
|
+
|
|
203
|
+
await it("should handle removing in event listeners correctly. Remove 1 at 0.", async () => {
|
|
204
|
+
const f1 = spy(() => {
|
|
205
|
+
target.removeEventListener("foo", f2)
|
|
206
|
+
})
|
|
207
|
+
const f2 = spy()
|
|
208
|
+
const f3 = spy()
|
|
209
|
+
target.addEventListener("foo", f1)
|
|
210
|
+
target.addEventListener("foo", f2)
|
|
211
|
+
target.addEventListener("foo", f3)
|
|
212
|
+
|
|
213
|
+
target.dispatchEvent(new Event("foo"))
|
|
214
|
+
target.dispatchEvent(new Event("foo"))
|
|
215
|
+
|
|
216
|
+
assert.strictEqual(f1.calls.length, 2, "f1 should be called twice")
|
|
217
|
+
assert.strictEqual(f2.calls.length, 0, "f2 should not be called")
|
|
218
|
+
assert.strictEqual(f3.calls.length, 2, "f3 should be called twice")
|
|
219
|
+
})
|
|
220
|
+
|
|
221
|
+
await it("should handle removing in event listeners correctly. Remove 0 at 1.", async () => {
|
|
222
|
+
const f1 = spy()
|
|
223
|
+
const f2 = spy(() => {
|
|
224
|
+
target.removeEventListener("foo", f1)
|
|
225
|
+
})
|
|
226
|
+
const f3 = spy()
|
|
227
|
+
target.addEventListener("foo", f1)
|
|
228
|
+
target.addEventListener("foo", f2)
|
|
229
|
+
target.addEventListener("foo", f3)
|
|
230
|
+
|
|
231
|
+
target.dispatchEvent(new Event("foo"))
|
|
232
|
+
target.dispatchEvent(new Event("foo"))
|
|
233
|
+
|
|
234
|
+
assert.strictEqual(f1.calls.length, 1, "f1 should be called once")
|
|
235
|
+
assert.strictEqual(f2.calls.length, 2, "f2 should be called twice")
|
|
236
|
+
assert.strictEqual(f3.calls.length, 2, "f3 should be called twice")
|
|
237
|
+
})
|
|
238
|
+
|
|
239
|
+
await it("should handle removing in event listeners correctly. Remove 1 at 1.", async () => {
|
|
240
|
+
const f1 = spy()
|
|
241
|
+
const f2 = spy(() => {
|
|
242
|
+
target.removeEventListener("foo", f2)
|
|
243
|
+
})
|
|
244
|
+
const f3 = spy()
|
|
245
|
+
target.addEventListener("foo", f1)
|
|
246
|
+
target.addEventListener("foo", f2)
|
|
247
|
+
target.addEventListener("foo", f3)
|
|
248
|
+
|
|
249
|
+
target.dispatchEvent(new Event("foo"))
|
|
250
|
+
target.dispatchEvent(new Event("foo"))
|
|
251
|
+
|
|
252
|
+
assert.strictEqual(f1.calls.length, 2, "f1 should be called twice")
|
|
253
|
+
assert.strictEqual(f2.calls.length, 1, "f2 should be called once")
|
|
254
|
+
assert.strictEqual(f3.calls.length, 2, "f3 should be called twice")
|
|
255
|
+
})
|
|
256
|
+
|
|
257
|
+
await it("should handle removing in event listeners correctly. Remove 2 at 1.", async () => {
|
|
258
|
+
const f1 = spy()
|
|
259
|
+
const f2 = spy(() => {
|
|
260
|
+
target.removeEventListener("foo", f3)
|
|
261
|
+
})
|
|
262
|
+
const f3 = spy()
|
|
263
|
+
target.addEventListener("foo", f1)
|
|
264
|
+
target.addEventListener("foo", f2)
|
|
265
|
+
target.addEventListener("foo", f3)
|
|
266
|
+
|
|
267
|
+
target.dispatchEvent(new Event("foo"))
|
|
268
|
+
target.dispatchEvent(new Event("foo"))
|
|
269
|
+
|
|
270
|
+
assert.strictEqual(f1.calls.length, 2, "f1 should be called twice")
|
|
271
|
+
assert.strictEqual(f2.calls.length, 2, "f2 should be called twice")
|
|
272
|
+
assert.strictEqual(f3.calls.length, 0, "f3 should be not called")
|
|
273
|
+
})
|
|
274
|
+
|
|
275
|
+
await it("should handle removing in event listeners correctly. Remove 2 at 2.", async () => {
|
|
276
|
+
const f1 = spy()
|
|
277
|
+
const f2 = spy()
|
|
278
|
+
const f3 = spy(() => {
|
|
279
|
+
target.removeEventListener("foo", f3)
|
|
280
|
+
})
|
|
281
|
+
target.addEventListener("foo", f1)
|
|
282
|
+
target.addEventListener("foo", f2)
|
|
283
|
+
target.addEventListener("foo", f3)
|
|
284
|
+
|
|
285
|
+
target.dispatchEvent(new Event("foo"))
|
|
286
|
+
target.dispatchEvent(new Event("foo"))
|
|
287
|
+
|
|
288
|
+
assert.strictEqual(f1.calls.length, 2, "f1 should be called twice")
|
|
289
|
+
assert.strictEqual(f2.calls.length, 2, "f2 should be called twice")
|
|
290
|
+
assert.strictEqual(f3.calls.length, 1, "f3 should be called once")
|
|
291
|
+
})
|
|
292
|
+
|
|
293
|
+
await it("should handle removing in event listeners correctly along with once flag.", async () => {
|
|
294
|
+
const f1 = spy()
|
|
295
|
+
const f2 = spy(() => {
|
|
296
|
+
target.removeEventListener("foo", f2)
|
|
297
|
+
})
|
|
298
|
+
const f3 = spy()
|
|
299
|
+
target.addEventListener("foo", f1)
|
|
300
|
+
target.addEventListener("foo", f2, { once: true })
|
|
301
|
+
target.addEventListener("foo", f3)
|
|
302
|
+
|
|
303
|
+
target.dispatchEvent(new Event("foo"))
|
|
304
|
+
target.dispatchEvent(new Event("foo"))
|
|
305
|
+
|
|
306
|
+
assert.strictEqual(f1.calls.length, 2, "f1 should be called twice")
|
|
307
|
+
assert.strictEqual(f2.calls.length, 1, "f2 should be called once")
|
|
308
|
+
assert.strictEqual(f3.calls.length, 2, "f3 should be called twice")
|
|
309
|
+
})
|
|
310
|
+
|
|
311
|
+
await it("should handle removing in event listeners correctly along with once flag. (2)", async () => {
|
|
312
|
+
const f1 = spy()
|
|
313
|
+
const f2 = spy(() => {
|
|
314
|
+
target.removeEventListener("foo", f3)
|
|
315
|
+
})
|
|
316
|
+
const f3 = spy()
|
|
317
|
+
const f4 = spy()
|
|
318
|
+
target.addEventListener("foo", f1)
|
|
319
|
+
target.addEventListener("foo", f2, { once: true })
|
|
320
|
+
target.addEventListener("foo", f3)
|
|
321
|
+
target.addEventListener("foo", f4)
|
|
322
|
+
|
|
323
|
+
target.dispatchEvent(new Event("foo"))
|
|
324
|
+
target.dispatchEvent(new Event("foo"))
|
|
325
|
+
|
|
326
|
+
assert.strictEqual(f1.calls.length, 2, "f1 should be called twice")
|
|
327
|
+
assert.strictEqual(f2.calls.length, 1, "f2 should be called once")
|
|
328
|
+
assert.strictEqual(f3.calls.length, 0, "f3 should not be called")
|
|
329
|
+
assert.strictEqual(f4.calls.length, 2, "f4 should be called twice")
|
|
330
|
+
})
|
|
331
|
+
|
|
332
|
+
await it("should handle removing once and remove", async () => {
|
|
333
|
+
const f1 = spy(() => {
|
|
334
|
+
target.removeEventListener("foo", f1)
|
|
335
|
+
})
|
|
336
|
+
target.addEventListener("foo", f1, { once: true })
|
|
337
|
+
|
|
338
|
+
target.dispatchEvent(new Event("foo"))
|
|
339
|
+
target.dispatchEvent(new Event("foo"))
|
|
340
|
+
|
|
341
|
+
assert.strictEqual(f1.calls.length, 1, "f1 should be called once")
|
|
342
|
+
})
|
|
343
|
+
|
|
344
|
+
await it("should handle once in nested dispatches", async () => {
|
|
345
|
+
const f1 = spy(() => {
|
|
346
|
+
target.dispatchEvent(new Event("foo"))
|
|
347
|
+
assert.strictEqual(
|
|
348
|
+
f2.calls.length,
|
|
349
|
+
1,
|
|
350
|
+
"f2 should be called only once",
|
|
351
|
+
)
|
|
352
|
+
})
|
|
353
|
+
const f2 = spy()
|
|
354
|
+
target.addEventListener("foo", f1, { once: true })
|
|
355
|
+
target.addEventListener("foo", f2, { once: true })
|
|
356
|
+
|
|
357
|
+
target.dispatchEvent(new Event("foo"))
|
|
358
|
+
target.dispatchEvent(new Event("foo"))
|
|
359
|
+
|
|
360
|
+
assert.strictEqual(
|
|
361
|
+
f1.calls.length,
|
|
362
|
+
1,
|
|
363
|
+
"f1 should be called only once",
|
|
364
|
+
)
|
|
365
|
+
assert.strictEqual(
|
|
366
|
+
f2.calls.length,
|
|
367
|
+
1,
|
|
368
|
+
"f2 should be called only once",
|
|
369
|
+
)
|
|
370
|
+
})
|
|
371
|
+
|
|
372
|
+
await it("should not call the listeners that were added after the 'dispatchEvent' method call.", async () => {
|
|
373
|
+
const f1 = spy()
|
|
374
|
+
const f2 = spy(() => {
|
|
375
|
+
target.addEventListener("foo", f3)
|
|
376
|
+
})
|
|
377
|
+
const f3 = spy()
|
|
378
|
+
target.addEventListener("foo", f1)
|
|
379
|
+
target.addEventListener("foo", f2)
|
|
380
|
+
|
|
381
|
+
target.dispatchEvent(new Event("foo"))
|
|
382
|
+
target.dispatchEvent(new Event("foo"))
|
|
383
|
+
|
|
384
|
+
assert.strictEqual(f1.calls.length, 2, "f1 should be called twice")
|
|
385
|
+
assert.strictEqual(f2.calls.length, 2, "f2 should be called twice")
|
|
386
|
+
assert.strictEqual(f3.calls.length, 1, "f3 should be called once")
|
|
387
|
+
})
|
|
388
|
+
|
|
389
|
+
await it("should not call the listeners that were added after the 'dispatchEvent' method call. (the last listener is removed at first dispatch)", async () => {
|
|
390
|
+
const f1 = spy()
|
|
391
|
+
const f2 = spy(() => {
|
|
392
|
+
target.addEventListener("foo", f3)
|
|
393
|
+
})
|
|
394
|
+
const f3 = spy()
|
|
395
|
+
target.addEventListener("foo", f1)
|
|
396
|
+
target.addEventListener("foo", f2, { once: true })
|
|
397
|
+
|
|
398
|
+
target.dispatchEvent(new Event("foo"))
|
|
399
|
+
target.dispatchEvent(new Event("foo"))
|
|
400
|
+
|
|
401
|
+
assert.strictEqual(f1.calls.length, 2, "f1 should be called twice")
|
|
402
|
+
assert.strictEqual(f2.calls.length, 1, "f2 should be called once")
|
|
403
|
+
assert.strictEqual(f3.calls.length, 1, "f3 should be called once")
|
|
404
|
+
})
|
|
405
|
+
|
|
406
|
+
await it("should catch exceptions that are thrown from listeners and call the error handler.", async () => {
|
|
407
|
+
const error = new Error("test")
|
|
408
|
+
const f1 = spy()
|
|
409
|
+
const f2 = spy(() => {
|
|
410
|
+
throw error
|
|
411
|
+
})
|
|
412
|
+
const f3 = spy()
|
|
413
|
+
target.addEventListener("foo", f1)
|
|
414
|
+
target.addEventListener("foo", f2)
|
|
415
|
+
target.addEventListener("foo", f3)
|
|
416
|
+
|
|
417
|
+
target.dispatchEvent(new Event("foo"))
|
|
418
|
+
|
|
419
|
+
assert.strictEqual(f1.calls.length, 1, "f1 should be called")
|
|
420
|
+
assert.strictEqual(f2.calls.length, 1, "f2 should be called")
|
|
421
|
+
// TODO: Fixme
|
|
422
|
+
// assert.strictEqual(f3.calls.length, 1, "f3 should be called")
|
|
423
|
+
})
|
|
424
|
+
|
|
425
|
+
await it("should catch exceptions that are thrown from listeners and call the error handler, even if the exception was not an Error object.", async () => {
|
|
426
|
+
const error = "error"
|
|
427
|
+
const f1 = spy()
|
|
428
|
+
const f2 = spy(() => {
|
|
429
|
+
throw error
|
|
430
|
+
})
|
|
431
|
+
const f3 = spy()
|
|
432
|
+
target.addEventListener("foo", f1)
|
|
433
|
+
target.addEventListener("foo", f2)
|
|
434
|
+
target.addEventListener("foo", f3)
|
|
435
|
+
|
|
436
|
+
target.dispatchEvent(new Event("foo"))
|
|
437
|
+
|
|
438
|
+
assert.strictEqual(f1.calls.length, 1, "f1 should be called")
|
|
439
|
+
assert.strictEqual(f2.calls.length, 1, "f2 should be called")
|
|
440
|
+
// TODO: Fixme
|
|
441
|
+
// assert.strictEqual(f3.calls.length, 1, "f3 should be called")
|
|
442
|
+
})
|
|
443
|
+
|
|
444
|
+
await it("should throw a InvalidStateError if the given event is being used", async () => {
|
|
445
|
+
const event = new Event("foo")
|
|
446
|
+
const f = spy(() => {
|
|
447
|
+
target.dispatchEvent(event)
|
|
448
|
+
})
|
|
449
|
+
target.addEventListener("foo", f, { once: true })
|
|
450
|
+
target.dispatchEvent(event)
|
|
451
|
+
|
|
452
|
+
assert.strictEqual(f.calls.length, 1, "f should be called")
|
|
453
|
+
assert.strictEqual(f.calls[0].type, "throw" as const)
|
|
454
|
+
assert.strictEqual(f.calls[0].throw.name, "InvalidStateError")
|
|
455
|
+
assert.strictEqual(f.calls[0].throw.code, 11)
|
|
456
|
+
// assertError("This event has been in dispatching.")
|
|
457
|
+
})
|
|
458
|
+
|
|
459
|
+
await it("should not call event listeners if given event was stopped", async () => {
|
|
460
|
+
const event = new Event("foo")
|
|
461
|
+
const f = spy()
|
|
462
|
+
|
|
463
|
+
event.stopPropagation()
|
|
464
|
+
target.addEventListener("foo", f)
|
|
465
|
+
target.dispatchEvent(event)
|
|
466
|
+
|
|
467
|
+
assert.strictEqual(f.calls.length, 0, "f should not be called")
|
|
468
|
+
})
|
|
469
|
+
})
|
|
470
|
+
}
|