@bernierllc/event-emitter 1.0.8 → 1.2.0
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/dist/errors.d.ts +16 -0
- package/dist/errors.js +28 -0
- package/dist/event-emitter.js +9 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +3 -1
- package/package.json +7 -2
- package/.eslintrc.js +0 -29
- package/CHANGELOG.md +0 -73
- package/__tests__/async-handlers.test.ts +0 -260
- package/__tests__/error-handling.test.ts +0 -310
- package/__tests__/event-emitter.test.ts +0 -281
- package/__tests__/logger-integration.test.ts +0 -132
- package/__tests__/wildcard.test.ts +0 -151
- package/jest.config.cjs +0 -30
- package/src/event-emitter.ts +0 -190
- package/src/factory.ts +0 -17
- package/src/index.ts +0 -11
- package/src/types.ts +0 -46
- package/tsconfig.json +0 -22
|
@@ -1,310 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
Copyright (c) 2025 Bernier LLC
|
|
3
|
-
|
|
4
|
-
This file is licensed to the client under a limited-use license.
|
|
5
|
-
The client may use and modify this code *only within the scope of the project it was delivered for*.
|
|
6
|
-
Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import { EventEmitter } from '../src';
|
|
10
|
-
|
|
11
|
-
describe('EventEmitter - Error Handling', () => {
|
|
12
|
-
let emitter: EventEmitter;
|
|
13
|
-
|
|
14
|
-
beforeEach(() => {
|
|
15
|
-
emitter = new EventEmitter();
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
describe('handler error handling with captureErrors enabled', () => {
|
|
19
|
-
beforeEach(() => {
|
|
20
|
-
emitter = new EventEmitter({ captureErrors: true });
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
it('should capture and suppress handler errors', async () => {
|
|
24
|
-
const errorHandler = jest.fn(() => {
|
|
25
|
-
throw new Error('Handler error');
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
const successHandler = jest.fn();
|
|
29
|
-
|
|
30
|
-
emitter.on('test', errorHandler);
|
|
31
|
-
emitter.on('test', successHandler);
|
|
32
|
-
|
|
33
|
-
await expect(emitter.emit('test', {})).resolves.toBeUndefined();
|
|
34
|
-
|
|
35
|
-
expect(errorHandler).toHaveBeenCalled();
|
|
36
|
-
expect(successHandler).toHaveBeenCalled();
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
it('should continue executing other handlers after error', async () => {
|
|
40
|
-
const handler1 = jest.fn(() => {
|
|
41
|
-
throw new Error('Error in handler 1');
|
|
42
|
-
});
|
|
43
|
-
const handler2 = jest.fn();
|
|
44
|
-
const handler3 = jest.fn(() => {
|
|
45
|
-
throw new Error('Error in handler 3');
|
|
46
|
-
});
|
|
47
|
-
const handler4 = jest.fn();
|
|
48
|
-
|
|
49
|
-
emitter.on('test', handler1);
|
|
50
|
-
emitter.on('test', handler2);
|
|
51
|
-
emitter.on('test', handler3);
|
|
52
|
-
emitter.on('test', handler4);
|
|
53
|
-
|
|
54
|
-
await emitter.emit('test', {});
|
|
55
|
-
|
|
56
|
-
expect(handler1).toHaveBeenCalled();
|
|
57
|
-
expect(handler2).toHaveBeenCalled();
|
|
58
|
-
expect(handler3).toHaveBeenCalled();
|
|
59
|
-
expect(handler4).toHaveBeenCalled();
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
it('should capture async handler errors', async () => {
|
|
63
|
-
const asyncErrorHandler = jest.fn(async () => {
|
|
64
|
-
await new Promise(resolve => setTimeout(resolve, 10));
|
|
65
|
-
throw new Error('Async error');
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
const successHandler = jest.fn();
|
|
69
|
-
|
|
70
|
-
emitter.on('test', asyncErrorHandler);
|
|
71
|
-
emitter.on('test', successHandler);
|
|
72
|
-
|
|
73
|
-
await expect(emitter.emit('test', {})).resolves.toBeUndefined();
|
|
74
|
-
|
|
75
|
-
expect(asyncErrorHandler).toHaveBeenCalled();
|
|
76
|
-
expect(successHandler).toHaveBeenCalled();
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
it('should handle errors in wildcard listeners', async () => {
|
|
80
|
-
const wildcardError = jest.fn(() => {
|
|
81
|
-
throw new Error('Wildcard error');
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
const specificHandler = jest.fn();
|
|
85
|
-
|
|
86
|
-
emitter.on('*', wildcardError);
|
|
87
|
-
emitter.on('test', specificHandler);
|
|
88
|
-
|
|
89
|
-
await expect(emitter.emit('test', {})).resolves.toBeUndefined();
|
|
90
|
-
|
|
91
|
-
expect(wildcardError).toHaveBeenCalled();
|
|
92
|
-
expect(specificHandler).toHaveBeenCalled();
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
it('should handle errors in once listeners', async () => {
|
|
96
|
-
const onceError = jest.fn(() => {
|
|
97
|
-
throw new Error('Once error');
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
emitter.once('test', onceError);
|
|
101
|
-
|
|
102
|
-
await expect(emitter.emit('test', {})).resolves.toBeUndefined();
|
|
103
|
-
|
|
104
|
-
expect(onceError).toHaveBeenCalled();
|
|
105
|
-
expect(emitter.listenerCount('test')).toBe(0);
|
|
106
|
-
});
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
describe('handler error handling with captureErrors disabled', () => {
|
|
110
|
-
beforeEach(() => {
|
|
111
|
-
emitter = new EventEmitter({ captureErrors: false });
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
it('should throw handler errors when captureErrors is false', async () => {
|
|
115
|
-
const errorHandler = jest.fn(() => {
|
|
116
|
-
throw new Error('Handler error');
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
emitter.on('test', errorHandler);
|
|
120
|
-
|
|
121
|
-
await expect(emitter.emit('test', {})).rejects.toThrow('Handler error');
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
it('should throw async handler errors when captureErrors is false', async () => {
|
|
125
|
-
const asyncErrorHandler = jest.fn(async () => {
|
|
126
|
-
await new Promise(resolve => setTimeout(resolve, 10));
|
|
127
|
-
throw new Error('Async handler error');
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
emitter.on('test', asyncErrorHandler);
|
|
131
|
-
|
|
132
|
-
await expect(emitter.emit('test', {})).rejects.toThrow('Async handler error');
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
it('should throw first error when multiple handlers fail', async () => {
|
|
136
|
-
const handler1 = jest.fn(async () => {
|
|
137
|
-
await new Promise(resolve => setTimeout(resolve, 20));
|
|
138
|
-
throw new Error('Error 1');
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
const handler2 = jest.fn(async () => {
|
|
142
|
-
await new Promise(resolve => setTimeout(resolve, 10));
|
|
143
|
-
throw new Error('Error 2');
|
|
144
|
-
});
|
|
145
|
-
|
|
146
|
-
emitter.on('test', handler1);
|
|
147
|
-
emitter.on('test', handler2);
|
|
148
|
-
|
|
149
|
-
// With Promise.all, the first rejection is thrown
|
|
150
|
-
await expect(emitter.emit('test', {})).rejects.toThrow();
|
|
151
|
-
});
|
|
152
|
-
});
|
|
153
|
-
|
|
154
|
-
describe('error types', () => {
|
|
155
|
-
beforeEach(() => {
|
|
156
|
-
emitter = new EventEmitter({ captureErrors: true });
|
|
157
|
-
});
|
|
158
|
-
|
|
159
|
-
it('should handle Error objects', async () => {
|
|
160
|
-
const handler = jest.fn(() => {
|
|
161
|
-
throw new Error('Standard error');
|
|
162
|
-
});
|
|
163
|
-
|
|
164
|
-
emitter.on('test', handler);
|
|
165
|
-
await expect(emitter.emit('test', {})).resolves.toBeUndefined();
|
|
166
|
-
});
|
|
167
|
-
|
|
168
|
-
it('should handle string errors', async () => {
|
|
169
|
-
const handler = jest.fn(() => {
|
|
170
|
-
throw 'String error';
|
|
171
|
-
});
|
|
172
|
-
|
|
173
|
-
emitter.on('test', handler);
|
|
174
|
-
await expect(emitter.emit('test', {})).resolves.toBeUndefined();
|
|
175
|
-
});
|
|
176
|
-
|
|
177
|
-
it('should handle custom error types', async () => {
|
|
178
|
-
class CustomError extends Error {
|
|
179
|
-
constructor(message: string, public code: number) {
|
|
180
|
-
super(message);
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
const handler = jest.fn(() => {
|
|
185
|
-
throw new CustomError('Custom error', 500);
|
|
186
|
-
});
|
|
187
|
-
|
|
188
|
-
emitter.on('test', handler);
|
|
189
|
-
await expect(emitter.emit('test', {})).resolves.toBeUndefined();
|
|
190
|
-
});
|
|
191
|
-
|
|
192
|
-
it('should handle null/undefined errors', async () => {
|
|
193
|
-
const handler1 = jest.fn(() => {
|
|
194
|
-
throw null;
|
|
195
|
-
});
|
|
196
|
-
|
|
197
|
-
const handler2 = jest.fn(() => {
|
|
198
|
-
throw undefined;
|
|
199
|
-
});
|
|
200
|
-
|
|
201
|
-
emitter.on('test1', handler1);
|
|
202
|
-
emitter.on('test2', handler2);
|
|
203
|
-
|
|
204
|
-
await expect(emitter.emit('test1', {})).resolves.toBeUndefined();
|
|
205
|
-
await expect(emitter.emit('test2', {})).resolves.toBeUndefined();
|
|
206
|
-
});
|
|
207
|
-
});
|
|
208
|
-
|
|
209
|
-
describe('error handling edge cases', () => {
|
|
210
|
-
it('should handle errors during listener removal', async () => {
|
|
211
|
-
const errorHandler = jest.fn(() => {
|
|
212
|
-
throw new Error('Handler error');
|
|
213
|
-
});
|
|
214
|
-
|
|
215
|
-
emitter.once('test', errorHandler);
|
|
216
|
-
|
|
217
|
-
// Error occurs but once listener should still be removed
|
|
218
|
-
await emitter.emit('test', {});
|
|
219
|
-
|
|
220
|
-
expect(emitter.listenerCount('test')).toBe(0);
|
|
221
|
-
});
|
|
222
|
-
|
|
223
|
-
it('should handle simultaneous errors from multiple listeners', async () => {
|
|
224
|
-
emitter = new EventEmitter({ captureErrors: true });
|
|
225
|
-
|
|
226
|
-
const error1 = jest.fn(() => {
|
|
227
|
-
throw new Error('Error 1');
|
|
228
|
-
});
|
|
229
|
-
const error2 = jest.fn(() => {
|
|
230
|
-
throw new Error('Error 2');
|
|
231
|
-
});
|
|
232
|
-
const error3 = jest.fn(() => {
|
|
233
|
-
throw new Error('Error 3');
|
|
234
|
-
});
|
|
235
|
-
|
|
236
|
-
emitter.on('test', error1);
|
|
237
|
-
emitter.on('test', error2);
|
|
238
|
-
emitter.on('test', error3);
|
|
239
|
-
|
|
240
|
-
await expect(emitter.emit('test', {})).resolves.toBeUndefined();
|
|
241
|
-
|
|
242
|
-
expect(error1).toHaveBeenCalled();
|
|
243
|
-
expect(error2).toHaveBeenCalled();
|
|
244
|
-
expect(error3).toHaveBeenCalled();
|
|
245
|
-
});
|
|
246
|
-
|
|
247
|
-
it('should handle errors in mix of sync and async handlers', async () => {
|
|
248
|
-
emitter = new EventEmitter({ captureErrors: true });
|
|
249
|
-
|
|
250
|
-
const syncError = jest.fn(() => {
|
|
251
|
-
throw new Error('Sync error');
|
|
252
|
-
});
|
|
253
|
-
|
|
254
|
-
const asyncError = jest.fn(async () => {
|
|
255
|
-
await new Promise(resolve => setTimeout(resolve, 10));
|
|
256
|
-
throw new Error('Async error');
|
|
257
|
-
});
|
|
258
|
-
|
|
259
|
-
const success = jest.fn();
|
|
260
|
-
|
|
261
|
-
emitter.on('test', syncError);
|
|
262
|
-
emitter.on('test', asyncError);
|
|
263
|
-
emitter.on('test', success);
|
|
264
|
-
|
|
265
|
-
await expect(emitter.emit('test', {})).resolves.toBeUndefined();
|
|
266
|
-
|
|
267
|
-
expect(syncError).toHaveBeenCalled();
|
|
268
|
-
expect(asyncError).toHaveBeenCalled();
|
|
269
|
-
expect(success).toHaveBeenCalled();
|
|
270
|
-
});
|
|
271
|
-
});
|
|
272
|
-
|
|
273
|
-
describe('error recovery', () => {
|
|
274
|
-
it('should allow re-emitting after error', async () => {
|
|
275
|
-
emitter = new EventEmitter({ captureErrors: true });
|
|
276
|
-
|
|
277
|
-
const handler = jest.fn((data: { shouldError: boolean }) => {
|
|
278
|
-
if (data.shouldError) {
|
|
279
|
-
throw new Error('Expected error');
|
|
280
|
-
}
|
|
281
|
-
});
|
|
282
|
-
|
|
283
|
-
emitter.on('test', handler);
|
|
284
|
-
|
|
285
|
-
// First emit with error
|
|
286
|
-
await emitter.emit('test', { shouldError: true });
|
|
287
|
-
expect(handler).toHaveBeenCalledTimes(1);
|
|
288
|
-
|
|
289
|
-
// Second emit without error
|
|
290
|
-
await emitter.emit('test', { shouldError: false });
|
|
291
|
-
expect(handler).toHaveBeenCalledTimes(2);
|
|
292
|
-
});
|
|
293
|
-
|
|
294
|
-
it('should maintain listeners after error', async () => {
|
|
295
|
-
emitter = new EventEmitter({ captureErrors: true });
|
|
296
|
-
|
|
297
|
-
const handler = jest.fn(() => {
|
|
298
|
-
throw new Error('Error');
|
|
299
|
-
});
|
|
300
|
-
|
|
301
|
-
emitter.on('test', handler);
|
|
302
|
-
|
|
303
|
-
await emitter.emit('test', {});
|
|
304
|
-
expect(emitter.listenerCount('test')).toBe(1);
|
|
305
|
-
|
|
306
|
-
await emitter.emit('test', {});
|
|
307
|
-
expect(emitter.listenerCount('test')).toBe(1);
|
|
308
|
-
});
|
|
309
|
-
});
|
|
310
|
-
});
|
|
@@ -1,281 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
Copyright (c) 2025 Bernier LLC
|
|
3
|
-
|
|
4
|
-
This file is licensed to the client under a limited-use license.
|
|
5
|
-
The client may use and modify this code *only within the scope of the project it was delivered for*.
|
|
6
|
-
Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import { EventEmitter, createEventEmitter } from '../src';
|
|
10
|
-
|
|
11
|
-
describe('EventEmitter', () => {
|
|
12
|
-
let emitter: EventEmitter;
|
|
13
|
-
|
|
14
|
-
beforeEach(() => {
|
|
15
|
-
emitter = new EventEmitter();
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
describe('constructor', () => {
|
|
19
|
-
it('should create event emitter with default options', () => {
|
|
20
|
-
expect(emitter).toBeInstanceOf(EventEmitter);
|
|
21
|
-
expect(emitter.listenerCount('test')).toBe(0);
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
it('should create event emitter with custom options', () => {
|
|
25
|
-
const customEmitter = new EventEmitter({
|
|
26
|
-
maxListeners: 10,
|
|
27
|
-
logEvents: true,
|
|
28
|
-
captureErrors: false
|
|
29
|
-
});
|
|
30
|
-
expect(customEmitter).toBeInstanceOf(EventEmitter);
|
|
31
|
-
});
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
describe('on', () => {
|
|
35
|
-
it('should add event listener', () => {
|
|
36
|
-
const handler = jest.fn();
|
|
37
|
-
const subscription = emitter.on('test', handler);
|
|
38
|
-
|
|
39
|
-
expect(subscription).toMatchObject({
|
|
40
|
-
eventType: 'test',
|
|
41
|
-
once: false
|
|
42
|
-
});
|
|
43
|
-
expect(subscription.id).toBeDefined();
|
|
44
|
-
expect(subscription.unsubscribe).toBeInstanceOf(Function);
|
|
45
|
-
expect(emitter.listenerCount('test')).toBe(1);
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
it('should add multiple listeners to same event', () => {
|
|
49
|
-
emitter.on('test', jest.fn());
|
|
50
|
-
emitter.on('test', jest.fn());
|
|
51
|
-
emitter.on('test', jest.fn());
|
|
52
|
-
|
|
53
|
-
expect(emitter.listenerCount('test')).toBe(3);
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
it('should enforce max listeners limit', () => {
|
|
57
|
-
const limitedEmitter = new EventEmitter({ maxListeners: 2 });
|
|
58
|
-
|
|
59
|
-
limitedEmitter.on('test', jest.fn());
|
|
60
|
-
limitedEmitter.on('test', jest.fn());
|
|
61
|
-
|
|
62
|
-
expect(() => {
|
|
63
|
-
limitedEmitter.on('test', jest.fn());
|
|
64
|
-
}).toThrow('Max listeners (2) exceeded for event type: test');
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
it('should allow unlimited listeners when maxListeners is 0', () => {
|
|
68
|
-
const unlimitedEmitter = new EventEmitter({ maxListeners: 0 });
|
|
69
|
-
|
|
70
|
-
for (let i = 0; i < 100; i++) {
|
|
71
|
-
unlimitedEmitter.on('test', jest.fn());
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
expect(unlimitedEmitter.listenerCount('test')).toBe(100);
|
|
75
|
-
});
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
describe('once', () => {
|
|
79
|
-
it('should add one-time listener', () => {
|
|
80
|
-
const handler = jest.fn();
|
|
81
|
-
const subscription = emitter.once('test', handler);
|
|
82
|
-
|
|
83
|
-
expect(subscription.once).toBe(true);
|
|
84
|
-
expect(emitter.listenerCount('test')).toBe(1);
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
it('should remove listener after first emission', async () => {
|
|
88
|
-
const handler = jest.fn();
|
|
89
|
-
emitter.once('test', handler);
|
|
90
|
-
|
|
91
|
-
await emitter.emit('test', { data: 'first' });
|
|
92
|
-
expect(handler).toHaveBeenCalledTimes(1);
|
|
93
|
-
expect(emitter.listenerCount('test')).toBe(0);
|
|
94
|
-
|
|
95
|
-
await emitter.emit('test', { data: 'second' });
|
|
96
|
-
expect(handler).toHaveBeenCalledTimes(1); // Still only called once
|
|
97
|
-
});
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
describe('off', () => {
|
|
101
|
-
it('should remove event listener', () => {
|
|
102
|
-
const handler = jest.fn();
|
|
103
|
-
const subscription = emitter.on('test', handler);
|
|
104
|
-
|
|
105
|
-
expect(emitter.listenerCount('test')).toBe(1);
|
|
106
|
-
|
|
107
|
-
emitter.off(subscription);
|
|
108
|
-
expect(emitter.listenerCount('test')).toBe(0);
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
it('should remove specific listener only', () => {
|
|
112
|
-
const handler1 = jest.fn();
|
|
113
|
-
const handler2 = jest.fn();
|
|
114
|
-
const sub1 = emitter.on('test', handler1);
|
|
115
|
-
emitter.on('test', handler2);
|
|
116
|
-
|
|
117
|
-
expect(emitter.listenerCount('test')).toBe(2);
|
|
118
|
-
|
|
119
|
-
emitter.off(sub1);
|
|
120
|
-
expect(emitter.listenerCount('test')).toBe(1);
|
|
121
|
-
});
|
|
122
|
-
|
|
123
|
-
it('should handle removing non-existent listener', () => {
|
|
124
|
-
const subscription = emitter.on('test', jest.fn());
|
|
125
|
-
emitter.off(subscription);
|
|
126
|
-
|
|
127
|
-
// Should not throw when removing again
|
|
128
|
-
expect(() => emitter.off(subscription)).not.toThrow();
|
|
129
|
-
});
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
describe('emit', () => {
|
|
133
|
-
it('should call event handler with data', async () => {
|
|
134
|
-
const handler = jest.fn();
|
|
135
|
-
emitter.on('test', handler);
|
|
136
|
-
|
|
137
|
-
await emitter.emit('test', { message: 'hello' });
|
|
138
|
-
|
|
139
|
-
expect(handler).toHaveBeenCalledTimes(1);
|
|
140
|
-
expect(handler).toHaveBeenCalledWith({ message: 'hello' });
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
it('should call multiple handlers for same event', async () => {
|
|
144
|
-
const handler1 = jest.fn();
|
|
145
|
-
const handler2 = jest.fn();
|
|
146
|
-
const handler3 = jest.fn();
|
|
147
|
-
|
|
148
|
-
emitter.on('test', handler1);
|
|
149
|
-
emitter.on('test', handler2);
|
|
150
|
-
emitter.on('test', handler3);
|
|
151
|
-
|
|
152
|
-
await emitter.emit('test', { data: 'test' });
|
|
153
|
-
|
|
154
|
-
expect(handler1).toHaveBeenCalledTimes(1);
|
|
155
|
-
expect(handler2).toHaveBeenCalledTimes(1);
|
|
156
|
-
expect(handler3).toHaveBeenCalledTimes(1);
|
|
157
|
-
});
|
|
158
|
-
|
|
159
|
-
it('should not call handlers for different event types', async () => {
|
|
160
|
-
const handler1 = jest.fn();
|
|
161
|
-
const handler2 = jest.fn();
|
|
162
|
-
|
|
163
|
-
emitter.on('event1', handler1);
|
|
164
|
-
emitter.on('event2', handler2);
|
|
165
|
-
|
|
166
|
-
await emitter.emit('event1', { data: 'test' });
|
|
167
|
-
|
|
168
|
-
expect(handler1).toHaveBeenCalledTimes(1);
|
|
169
|
-
expect(handler2).not.toHaveBeenCalled();
|
|
170
|
-
});
|
|
171
|
-
|
|
172
|
-
it('should handle emit with no listeners', async () => {
|
|
173
|
-
await expect(emitter.emit('nonexistent', { data: 'test' })).resolves.toBeUndefined();
|
|
174
|
-
});
|
|
175
|
-
});
|
|
176
|
-
|
|
177
|
-
describe('removeAllListeners', () => {
|
|
178
|
-
it('should remove all listeners for specific event type', () => {
|
|
179
|
-
emitter.on('test', jest.fn());
|
|
180
|
-
emitter.on('test', jest.fn());
|
|
181
|
-
emitter.on('other', jest.fn());
|
|
182
|
-
|
|
183
|
-
expect(emitter.listenerCount('test')).toBe(2);
|
|
184
|
-
expect(emitter.listenerCount('other')).toBe(1);
|
|
185
|
-
|
|
186
|
-
emitter.removeAllListeners('test');
|
|
187
|
-
|
|
188
|
-
expect(emitter.listenerCount('test')).toBe(0);
|
|
189
|
-
expect(emitter.listenerCount('other')).toBe(1);
|
|
190
|
-
});
|
|
191
|
-
|
|
192
|
-
it('should remove all listeners for all events', () => {
|
|
193
|
-
emitter.on('test1', jest.fn());
|
|
194
|
-
emitter.on('test2', jest.fn());
|
|
195
|
-
emitter.on('test3', jest.fn());
|
|
196
|
-
|
|
197
|
-
emitter.removeAllListeners();
|
|
198
|
-
|
|
199
|
-
expect(emitter.listenerCount('test1')).toBe(0);
|
|
200
|
-
expect(emitter.listenerCount('test2')).toBe(0);
|
|
201
|
-
expect(emitter.listenerCount('test3')).toBe(0);
|
|
202
|
-
});
|
|
203
|
-
});
|
|
204
|
-
|
|
205
|
-
describe('listenerCount', () => {
|
|
206
|
-
it('should return 0 for event with no listeners', () => {
|
|
207
|
-
expect(emitter.listenerCount('nonexistent')).toBe(0);
|
|
208
|
-
});
|
|
209
|
-
|
|
210
|
-
it('should return correct count for event with listeners', () => {
|
|
211
|
-
emitter.on('test', jest.fn());
|
|
212
|
-
emitter.on('test', jest.fn());
|
|
213
|
-
|
|
214
|
-
expect(emitter.listenerCount('test')).toBe(2);
|
|
215
|
-
});
|
|
216
|
-
|
|
217
|
-
it('should update count after adding/removing listeners', () => {
|
|
218
|
-
const sub1 = emitter.on('test', jest.fn());
|
|
219
|
-
const sub2 = emitter.on('test', jest.fn());
|
|
220
|
-
|
|
221
|
-
expect(emitter.listenerCount('test')).toBe(2);
|
|
222
|
-
|
|
223
|
-
emitter.off(sub1);
|
|
224
|
-
expect(emitter.listenerCount('test')).toBe(1);
|
|
225
|
-
|
|
226
|
-
emitter.off(sub2);
|
|
227
|
-
expect(emitter.listenerCount('test')).toBe(0);
|
|
228
|
-
});
|
|
229
|
-
});
|
|
230
|
-
|
|
231
|
-
describe('eventNames', () => {
|
|
232
|
-
it('should return empty array when no listeners', () => {
|
|
233
|
-
expect(emitter.eventNames()).toEqual([]);
|
|
234
|
-
});
|
|
235
|
-
|
|
236
|
-
it('should return array of event types', () => {
|
|
237
|
-
emitter.on('event1', jest.fn());
|
|
238
|
-
emitter.on('event2', jest.fn());
|
|
239
|
-
emitter.on('event3', jest.fn());
|
|
240
|
-
|
|
241
|
-
const names = emitter.eventNames();
|
|
242
|
-
expect(names).toContain('event1');
|
|
243
|
-
expect(names).toContain('event2');
|
|
244
|
-
expect(names).toContain('event3');
|
|
245
|
-
});
|
|
246
|
-
|
|
247
|
-
it('should include wildcard in event names', () => {
|
|
248
|
-
emitter.on('test', jest.fn());
|
|
249
|
-
emitter.on('*', jest.fn());
|
|
250
|
-
|
|
251
|
-
const names = emitter.eventNames();
|
|
252
|
-
expect(names).toContain('test');
|
|
253
|
-
expect(names).toContain('*');
|
|
254
|
-
});
|
|
255
|
-
});
|
|
256
|
-
|
|
257
|
-
describe('unsubscribe', () => {
|
|
258
|
-
it('should allow unsubscribing via subscription object', () => {
|
|
259
|
-
const handler = jest.fn();
|
|
260
|
-
const subscription = emitter.on('test', handler);
|
|
261
|
-
|
|
262
|
-
expect(emitter.listenerCount('test')).toBe(1);
|
|
263
|
-
|
|
264
|
-
subscription.unsubscribe();
|
|
265
|
-
|
|
266
|
-
expect(emitter.listenerCount('test')).toBe(0);
|
|
267
|
-
});
|
|
268
|
-
});
|
|
269
|
-
|
|
270
|
-
describe('factory function', () => {
|
|
271
|
-
it('should create event emitter via factory', () => {
|
|
272
|
-
const created = createEventEmitter();
|
|
273
|
-
expect(created).toBeInstanceOf(EventEmitter);
|
|
274
|
-
});
|
|
275
|
-
|
|
276
|
-
it('should pass options to factory', () => {
|
|
277
|
-
const created = createEventEmitter({ maxListeners: 5 });
|
|
278
|
-
expect(created).toBeInstanceOf(EventEmitter);
|
|
279
|
-
});
|
|
280
|
-
});
|
|
281
|
-
});
|