@gjsify/events 0.0.4 → 0.1.1

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.
@@ -1,15 +1,531 @@
1
+ // Ported from refs/node-test/parallel/test-events-*.js
2
+ // Original: MIT license, Node.js contributors
3
+
1
4
  import { describe, it, expect } from '@gjsify/unit';
5
+ import 'abort-controller'; // Registers AbortController/AbortSignal globals on GJS; no-op on Node.js
2
6
 
3
- import { EventEmitter } from 'events';
7
+ import { EventEmitter } from 'node:events';
4
8
 
5
9
  export default async () => {
6
10
 
7
- // Credits https://github.com/EventEmitter2/EventEmitter2/blob/master/test/simple/emit.js
8
- // TODO port more tests
11
+ await describe('EventEmitter: constructor', async () => {
12
+ await it('should create an instance', async () => {
13
+ const emitter = new EventEmitter();
14
+ expect(emitter).toBeDefined();
15
+ expect(emitter instanceof EventEmitter).toBeTruthy();
16
+ });
17
+
18
+ await it('should have default max listeners of 10', async () => {
19
+ const emitter = new EventEmitter();
20
+ expect(emitter.getMaxListeners()).toBe(10);
21
+ });
22
+ });
23
+
24
+ await describe('EventEmitter: emit', async () => {
25
+ await it('should call listeners when event is emitted', async () => {
26
+ const emitter = new EventEmitter();
27
+ let called = false;
28
+ emitter.on('test', () => { called = true; });
29
+ emitter.emit('test');
30
+ expect(called).toBeTruthy();
31
+ });
32
+
33
+ await it('should call multiple listeners in order', async () => {
34
+ const emitter = new EventEmitter();
35
+ const order: number[] = [];
36
+ emitter.on('test', () => order.push(1));
37
+ emitter.on('test', () => order.push(2));
38
+ emitter.emit('test');
39
+ expect(order.length).toBe(2);
40
+ expect(order[0]).toBe(1);
41
+ expect(order[1]).toBe(2);
42
+ });
43
+
44
+ await it('should pass arguments to listeners', async () => {
45
+ const emitter = new EventEmitter();
46
+ let received: any[] = [];
47
+ emitter.on('test', (...args) => { received = args; });
48
+ emitter.emit('test', 'a', 'b', 'c');
49
+ expect(received.length).toBe(3);
50
+ expect(received[0]).toBe('a');
51
+ expect(received[1]).toBe('b');
52
+ expect(received[2]).toBe('c');
53
+ });
54
+
55
+ await it('should return true when listeners exist', async () => {
56
+ const emitter = new EventEmitter();
57
+ emitter.on('test', () => {});
58
+ expect(emitter.emit('test')).toBeTruthy();
59
+ });
60
+
61
+ await it('should return false when no listeners exist', async () => {
62
+ const emitter = new EventEmitter();
63
+ expect(emitter.emit('test')).toBeFalsy();
64
+ });
65
+
66
+ await it('should throw on unhandled error event', async () => {
67
+ const emitter = new EventEmitter();
68
+ expect(() => {
69
+ emitter.emit('error', new Error('test error'));
70
+ }).toThrow();
71
+ });
72
+
73
+ await it('should not throw on error event with listener', async () => {
74
+ const emitter = new EventEmitter();
75
+ let caught = false;
76
+ emitter.on('error', () => { caught = true; });
77
+ emitter.emit('error', new Error('test error'));
78
+ expect(caught).toBeTruthy();
79
+ });
80
+ });
81
+
82
+ await describe('EventEmitter: on / addListener', async () => {
83
+ await it('should add a listener', async () => {
84
+ const emitter = new EventEmitter();
85
+ const fn = () => {};
86
+ emitter.on('test', fn);
87
+ expect(emitter.listenerCount('test')).toBe(1);
88
+ });
89
+
90
+ await it('should return this for chaining', async () => {
91
+ const emitter = new EventEmitter();
92
+ const result = emitter.on('test', () => {});
93
+ expect(result).toBe(emitter);
94
+ });
95
+
96
+ await it('addListener should be an alias for on', async () => {
97
+ const emitter = new EventEmitter();
98
+ let count = 0;
99
+ emitter.addListener('test', () => { count++; });
100
+ emitter.emit('test');
101
+ expect(count).toBe(1);
102
+ });
103
+ });
104
+
105
+ await describe('EventEmitter: once', async () => {
106
+ await it('should fire listener only once', async () => {
107
+ const emitter = new EventEmitter();
108
+ let count = 0;
109
+ emitter.once('test', () => { count++; });
110
+ emitter.emit('test');
111
+ emitter.emit('test');
112
+ expect(count).toBe(1);
113
+ });
114
+
115
+ await it('should remove listener after first call', async () => {
116
+ const emitter = new EventEmitter();
117
+ emitter.once('test', () => {});
118
+ expect(emitter.listenerCount('test')).toBe(1);
119
+ emitter.emit('test');
120
+ expect(emitter.listenerCount('test')).toBe(0);
121
+ });
122
+
123
+ await it('should pass arguments correctly', async () => {
124
+ const emitter = new EventEmitter();
125
+ let received: any;
126
+ emitter.once('test', (val) => { received = val; });
127
+ emitter.emit('test', 42);
128
+ expect(received).toBe(42);
129
+ });
130
+ });
131
+
132
+ await describe('EventEmitter: removeListener / off', async () => {
133
+ await it('should remove a specific listener', async () => {
134
+ const emitter = new EventEmitter();
135
+ const fn = () => {};
136
+ emitter.on('test', fn);
137
+ expect(emitter.listenerCount('test')).toBe(1);
138
+ emitter.removeListener('test', fn);
139
+ expect(emitter.listenerCount('test')).toBe(0);
140
+ });
141
+
142
+ await it('off should be an alias for removeListener', async () => {
143
+ const emitter = new EventEmitter();
144
+ const fn = () => {};
145
+ emitter.on('test', fn);
146
+ emitter.off('test', fn);
147
+ expect(emitter.listenerCount('test')).toBe(0);
148
+ });
149
+
150
+ await it('should return this for chaining', async () => {
151
+ const emitter = new EventEmitter();
152
+ const fn = () => {};
153
+ emitter.on('test', fn);
154
+ const result = emitter.removeListener('test', fn);
155
+ expect(result).toBe(emitter);
156
+ });
157
+
158
+ await it('should not fail when removing non-existent listener', async () => {
159
+ const emitter = new EventEmitter();
160
+ emitter.removeListener('nonexistent', () => {});
161
+ expect(emitter.listenerCount('nonexistent')).toBe(0);
162
+ });
163
+
164
+ await it('should only remove the last matching listener', async () => {
165
+ const emitter = new EventEmitter();
166
+ const fn = () => {};
167
+ emitter.on('test', fn);
168
+ emitter.on('test', fn);
169
+ emitter.removeListener('test', fn);
170
+ expect(emitter.listenerCount('test')).toBe(1);
171
+ });
172
+ });
173
+
174
+ await describe('EventEmitter: removeAllListeners', async () => {
175
+ await it('should remove all listeners for an event', async () => {
176
+ const emitter = new EventEmitter();
177
+ emitter.on('test', () => {});
178
+ emitter.on('test', () => {});
179
+ emitter.removeAllListeners('test');
180
+ expect(emitter.listenerCount('test')).toBe(0);
181
+ });
182
+
183
+ await it('should remove all listeners for all events when no arg', async () => {
184
+ const emitter = new EventEmitter();
185
+ emitter.on('a', () => {});
186
+ emitter.on('b', () => {});
187
+ emitter.removeAllListeners();
188
+ expect(emitter.eventNames().length).toBe(0);
189
+ });
190
+ });
191
+
192
+ await describe('EventEmitter: prependListener', async () => {
193
+ await it('should add listener at the beginning', async () => {
194
+ const emitter = new EventEmitter();
195
+ const order: number[] = [];
196
+ emitter.on('test', () => order.push(1));
197
+ emitter.prependListener('test', () => order.push(0));
198
+ emitter.emit('test');
199
+ expect(order[0]).toBe(0);
200
+ expect(order[1]).toBe(1);
201
+ });
202
+ });
203
+
204
+ await describe('EventEmitter: prependOnceListener', async () => {
205
+ await it('should add once listener at the beginning', async () => {
206
+ const emitter = new EventEmitter();
207
+ const order: number[] = [];
208
+ emitter.on('test', () => order.push(1));
209
+ emitter.prependOnceListener('test', () => order.push(0));
210
+ emitter.emit('test');
211
+ emitter.emit('test');
212
+ expect(order.length).toBe(3);
213
+ expect(order[0]).toBe(0);
214
+ expect(order[1]).toBe(1);
215
+ expect(order[2]).toBe(1);
216
+ });
217
+ });
218
+
219
+ await describe('EventEmitter: listeners', async () => {
220
+ await it('should return array of listeners', async () => {
221
+ const emitter = new EventEmitter();
222
+ const fn1 = () => {};
223
+ const fn2 = () => {};
224
+ emitter.on('test', fn1);
225
+ emitter.on('test', fn2);
226
+ const listeners = emitter.listeners('test');
227
+ expect(listeners.length).toBe(2);
228
+ expect(listeners[0]).toBe(fn1);
229
+ expect(listeners[1]).toBe(fn2);
230
+ });
231
+
232
+ await it('should return empty array for non-existent event', async () => {
233
+ const emitter = new EventEmitter();
234
+ const listeners = emitter.listeners('test');
235
+ expect(listeners.length).toBe(0);
236
+ });
237
+
238
+ await it('should unwrap once listeners', async () => {
239
+ const emitter = new EventEmitter();
240
+ const fn = () => {};
241
+ emitter.once('test', fn);
242
+ const listeners = emitter.listeners('test');
243
+ expect(listeners[0]).toBe(fn);
244
+ });
245
+ });
246
+
247
+ await describe('EventEmitter: rawListeners', async () => {
248
+ await it('should return wrapped once listeners', async () => {
249
+ const emitter = new EventEmitter();
250
+ const fn = () => {};
251
+ emitter.once('test', fn);
252
+ const raw = emitter.rawListeners('test');
253
+ expect(raw.length).toBe(1);
254
+ // Raw listener should have .listener property pointing to original
255
+ expect((raw[0] as any).listener).toBe(fn);
256
+ });
257
+ });
258
+
259
+ await describe('EventEmitter: listenerCount', async () => {
260
+ await it('should return count of listeners', async () => {
261
+ const emitter = new EventEmitter();
262
+ expect(emitter.listenerCount('test')).toBe(0);
263
+ emitter.on('test', () => {});
264
+ expect(emitter.listenerCount('test')).toBe(1);
265
+ emitter.on('test', () => {});
266
+ expect(emitter.listenerCount('test')).toBe(2);
267
+ });
268
+ });
269
+
270
+ await describe('EventEmitter: eventNames', async () => {
271
+ await it('should return array of event names', async () => {
272
+ const emitter = new EventEmitter();
273
+ emitter.on('foo', () => {});
274
+ emitter.on('bar', () => {});
275
+ const names = emitter.eventNames();
276
+ expect(names.length).toBe(2);
277
+ expect(names).toContain('foo');
278
+ expect(names).toContain('bar');
279
+ });
280
+
281
+ await it('should return empty array when no listeners', async () => {
282
+ const emitter = new EventEmitter();
283
+ expect(emitter.eventNames().length).toBe(0);
284
+ });
285
+
286
+ await it('should support symbol event names', async () => {
287
+ const emitter = new EventEmitter();
288
+ const sym = Symbol('test');
289
+ emitter.on(sym, () => {});
290
+ const names = emitter.eventNames();
291
+ expect(names.length).toBe(1);
292
+ // Use typeof check since toBe cannot compare Symbols
293
+ expect(typeof names[0]).toBe('symbol');
294
+ });
295
+ });
296
+
297
+ await describe('EventEmitter: setMaxListeners / getMaxListeners', async () => {
298
+ await it('should set and get max listeners', async () => {
299
+ const emitter = new EventEmitter();
300
+ emitter.setMaxListeners(20);
301
+ expect(emitter.getMaxListeners()).toBe(20);
302
+ });
303
+
304
+ await it('should allow 0 for unlimited', async () => {
305
+ const emitter = new EventEmitter();
306
+ emitter.setMaxListeners(0);
307
+ expect(emitter.getMaxListeners()).toBe(0);
308
+ });
309
+
310
+ await it('should throw for negative values', async () => {
311
+ const emitter = new EventEmitter();
312
+ expect(() => emitter.setMaxListeners(-1)).toThrow();
313
+ });
314
+ });
315
+
316
+ await describe('EventEmitter: newListener event', async () => {
317
+ await it('should emit newListener when adding a listener', async () => {
318
+ const emitter = new EventEmitter();
319
+ let eventName: string | undefined;
320
+ emitter.on('newListener', (name: string) => {
321
+ eventName = name;
322
+ });
323
+ emitter.on('test', () => {});
324
+ expect(eventName).toBe('test');
325
+ });
326
+ });
327
+
328
+ await describe('EventEmitter: removeListener event', async () => {
329
+ await it('should emit removeListener when removing a listener', async () => {
330
+ const emitter = new EventEmitter();
331
+ let eventName: string | undefined;
332
+ emitter.on('removeListener', (name: string) => {
333
+ eventName = name;
334
+ });
335
+ const fn = () => {};
336
+ emitter.on('test', fn);
337
+ emitter.removeListener('test', fn);
338
+ expect(eventName).toBe('test');
339
+ });
340
+ });
341
+
342
+ await describe('EventEmitter.once (static)', async () => {
343
+ await it('should return a promise that resolves on event', async () => {
344
+ const emitter = new EventEmitter();
345
+ const promise = EventEmitter.once(emitter, 'test');
346
+ emitter.emit('test', 'value');
347
+ const result = await promise;
348
+ expect(result.length).toBe(1);
349
+ expect(result[0]).toBe('value');
350
+ });
9
351
 
10
- await describe('events.EventEmitter: emit', async () => {
352
+ await it('should reject on error event', async () => {
353
+ const emitter = new EventEmitter();
354
+ const promise = EventEmitter.once(emitter, 'test');
355
+ const error = new Error('test error');
356
+ emitter.emit('error', error);
357
+ try {
358
+ await promise;
359
+ // Should not reach here
360
+ expect(false).toBeTruthy();
361
+ } catch (err) {
362
+ expect(err).toBe(error);
363
+ }
364
+ });
365
+
366
+ await it('should pass multiple args as array', async () => {
367
+ const emitter = new EventEmitter();
368
+ const promise = EventEmitter.once(emitter, 'test');
369
+ emitter.emit('test', 1, 2, 3);
370
+ const result = await promise;
371
+ expect(result.length).toBe(3);
372
+ expect(result[0]).toBe(1);
373
+ expect(result[1]).toBe(2);
374
+ expect(result[2]).toBe(3);
375
+ });
376
+ });
377
+
378
+ await describe('EventEmitter.on (static)', async () => {
379
+ await it('should return an async iterator', async () => {
380
+ const emitter = new EventEmitter();
381
+ const iterator = EventEmitter.on(emitter, 'data');
382
+ expect(iterator).toBeDefined();
383
+ expect(typeof iterator[Symbol.asyncIterator]).toBe('function');
384
+
385
+ // Emit some data then end iterator
386
+ emitter.emit('data', 1);
387
+ emitter.emit('data', 2);
388
+
389
+ const first = await iterator.next();
390
+ expect(first.done).toBeFalsy();
391
+ expect(first.value[0]).toBe(1);
392
+
393
+ const second = await iterator.next();
394
+ expect(second.done).toBeFalsy();
395
+ expect(second.value[0]).toBe(2);
396
+
397
+ await iterator.return!();
398
+ });
399
+ });
400
+
401
+ await describe('EventEmitter.listenerCount (static)', async () => {
402
+ await it('should return listener count', async () => {
403
+ const emitter = new EventEmitter();
404
+ emitter.on('test', () => {});
405
+ emitter.on('test', () => {});
406
+ expect(EventEmitter.listenerCount(emitter, 'test')).toBe(2);
407
+ });
408
+ });
409
+
410
+ await describe('EventEmitter.getEventListeners (static)', async () => {
411
+ await it('should return listeners array', async () => {
412
+ const emitter = new EventEmitter();
413
+ const fn = () => {};
414
+ emitter.on('test', fn);
415
+ const listeners = EventEmitter.getEventListeners(emitter, 'test');
416
+ expect(listeners.length).toBe(1);
417
+ expect(listeners[0]).toBe(fn);
418
+ });
419
+ });
420
+
421
+ await describe('EventEmitter: error handling', async () => {
422
+ await it('should throw generic error when emitting error with no listener and no Error arg', async () => {
423
+ const emitter = new EventEmitter();
424
+ expect(() => {
425
+ emitter.emit('error', 'string error');
426
+ }).toThrow();
427
+ });
428
+
429
+ await it('should throw with context for non-Error arguments', async () => {
430
+ const emitter = new EventEmitter();
431
+ try {
432
+ emitter.emit('error', 'string error');
433
+ expect(false).toBeTruthy();
434
+ } catch (err: any) {
435
+ expect(err.context).toBe('string error');
436
+ }
437
+ });
438
+ });
439
+
440
+ // ==================== additional tests ported from refs/node ====================
441
+
442
+ await describe('EventEmitter: defaultMaxListeners static', async () => {
443
+ await it('should have defaultMaxListeners property', async () => {
444
+ expect(typeof EventEmitter.defaultMaxListeners).toBe('number');
445
+ expect(EventEmitter.defaultMaxListeners).toBe(10);
446
+ });
447
+ });
448
+
449
+ await describe('EventEmitter: Symbol event names', async () => {
450
+ await it('should support Symbol as event name', async () => {
451
+ const emitter = new EventEmitter();
452
+ const sym = Symbol('myEvent');
453
+ let called = false;
454
+ emitter.on(sym, () => { called = true; });
455
+ emitter.emit(sym);
456
+ expect(called).toBeTruthy();
457
+ });
458
+
459
+ await it('should support removing Symbol listeners', async () => {
460
+ const emitter = new EventEmitter();
461
+ const sym = Symbol('myEvent');
462
+ const fn = () => {};
463
+ emitter.on(sym, fn);
464
+ expect(emitter.listenerCount(sym)).toBe(1);
465
+ emitter.removeListener(sym, fn);
466
+ expect(emitter.listenerCount(sym)).toBe(0);
467
+ });
468
+ });
469
+
470
+ await describe('EventEmitter: removeAllListeners', async () => {
471
+ await it('should remove all listeners for a specific event', async () => {
472
+ const emitter = new EventEmitter();
473
+ emitter.on('test', () => {});
474
+ emitter.on('test', () => {});
475
+ emitter.on('other', () => {});
476
+ emitter.removeAllListeners('test');
477
+ expect(emitter.listenerCount('test')).toBe(0);
478
+ expect(emitter.listenerCount('other')).toBe(1);
479
+ });
480
+
481
+ await it('should remove all listeners when no event specified', async () => {
482
+ const emitter = new EventEmitter();
483
+ emitter.on('test', () => {});
484
+ emitter.on('other', () => {});
485
+ emitter.removeAllListeners();
486
+ expect(emitter.eventNames().length).toBe(0);
487
+ });
488
+
489
+ await it('should return this for chaining', async () => {
490
+ const emitter = new EventEmitter();
491
+ const result = emitter.removeAllListeners();
492
+ expect(result).toBe(emitter);
493
+ });
494
+ });
495
+
496
+ await describe('EventEmitter: listener removal during emit', async () => {
497
+ await it('should not skip listeners when one removes itself', async () => {
498
+ const emitter = new EventEmitter();
499
+ const calls: number[] = [];
500
+ const fn1 = () => {
501
+ calls.push(1);
502
+ emitter.removeListener('test', fn1);
503
+ };
504
+ const fn2 = () => { calls.push(2); };
505
+ emitter.on('test', fn1);
506
+ emitter.on('test', fn2);
507
+ emitter.emit('test');
508
+ expect(calls.length).toBe(2);
509
+ expect(calls[0]).toBe(1);
510
+ expect(calls[1]).toBe(2);
511
+ });
512
+ });
513
+
514
+ await describe('EventEmitter: off alias', async () => {
515
+ await it('off should be an alias for removeListener', async () => {
516
+ const emitter = new EventEmitter();
517
+ const fn = () => {};
518
+ emitter.on('test', fn);
519
+ expect(emitter.listenerCount('test')).toBe(1);
520
+ emitter.off('test', fn);
521
+ expect(emitter.listenerCount('test')).toBe(0);
522
+ });
523
+ });
524
+
525
+ // Keep original tests for backwards compatibility
526
+ await describe('events.EventEmitter: emit (original)', async () => {
11
527
  await it('1. Add two listeners on a single event and emit the event', async () => {
12
- var emitter = new EventEmitter({ verbose: true } as any);
528
+ const emitter = new EventEmitter();
13
529
  let count = 0;
14
530
 
15
531
  function functionA() { count++; }
@@ -24,7 +540,7 @@ export default async () => {
24
540
  });
25
541
 
26
542
  await it('2. Add two listeners on a single event and emit the event twice', async () => {
27
- var emitter = new EventEmitter({ verbose: true } as any);
543
+ const emitter = new EventEmitter();
28
544
  let count = 0;
29
545
 
30
546
  function functionA() { count++ }
@@ -40,7 +556,7 @@ export default async () => {
40
556
  });
41
557
 
42
558
  await it('3. Add two listeners on a single event and emit the event with a parameter', async () => {
43
- var emitter = new EventEmitter({ verbose: true } as any);
559
+ const emitter = new EventEmitter();
44
560
  let count = 0;
45
561
 
46
562
  function functionA(value1: string) {
@@ -62,7 +578,7 @@ export default async () => {
62
578
  });
63
579
 
64
580
  await it(`4. Add two listeners on an single event and emit the event twice with a parameter.`, async () => {
65
- var emitter = new EventEmitter({ verbose: true } as any);
581
+ const emitter = new EventEmitter();
66
582
  let count = 0;
67
583
 
68
584
  function functionA(value1: string) {
@@ -85,13 +601,11 @@ export default async () => {
85
601
  });
86
602
 
87
603
  await it(`5. Add two listeners on an single event and emit the event twice with multiple parameters.`, async () => {
88
-
89
- var emitter = new EventEmitter({ verbose: true } as any);
604
+ const emitter = new EventEmitter();
90
605
  let count = 0;
91
606
 
92
607
  function functionA(value1: string, value2: string, value3: string) {
93
608
  count++;
94
- expect(true).toBeTruthy(); // 'The event was raised';
95
609
  expect(typeof value1).toBe('string');
96
610
  expect(typeof value2).toBe('string');
97
611
  expect(typeof value3).toBe('string');
@@ -99,7 +613,6 @@ export default async () => {
99
613
 
100
614
  function functionB(value1: string, value2: string, value3: string) {
101
615
  count++;
102
- expect(true).toBeTruthy(); // 'The event was raised';
103
616
  expect(typeof value1).toBe('string');
104
617
  expect(typeof value2).toBe('string');
105
618
  expect(typeof value3).toBe('string');
@@ -117,31 +630,23 @@ export default async () => {
117
630
 
118
631
  await it('6. Check return values of emit.', async () => {
119
632
  let count = 0;
120
- var emitter = new EventEmitter({ verbose: true } as any);
633
+ const emitter = new EventEmitter();
121
634
 
122
635
  function functionA() {
123
636
  count++;
124
- expect(true).toBeTruthy(); // 'The event was raised'
125
637
  }
126
638
 
127
639
  emitter.on('test6', functionA);
128
640
 
129
- expect(emitter.emit('test6')).toBeTruthy(); // 'emit should return true after calling a listener'
130
- expect(emitter.emit('other')).toBeFalsy(); // 'emit should return false when no listener was called'
131
-
132
- // The original implementation has no onAny method
133
- expect(() => {
134
- (emitter as any).onAny(functionA);
135
- }).toThrow();
136
-
137
- expect(emitter.emit('other')).toBeFalsy(); // 'emit should return false without the onAny() listener'
641
+ expect(emitter.emit('test6')).toBeTruthy();
642
+ expect(emitter.emit('other')).toBeFalsy();
138
643
 
139
644
  expect(count).toBe(1);
140
645
  });
141
646
 
142
647
  await it('7. Emit event with more than 2 arguments', async () => {
143
648
  let count = 0;
144
- var emitter = new EventEmitter({ verbose: true } as any);
649
+ const emitter = new EventEmitter();
145
650
 
146
651
  emitter.on('test', function (x: number, y: number, z: number) {
147
652
  count++;
@@ -155,4 +660,725 @@ export default async () => {
155
660
  });
156
661
 
157
662
  });
663
+
664
+ // ==================== expanded tests: setMaxListeners / getMaxListeners ====================
665
+
666
+ await describe('EventEmitter: setMaxListeners / getMaxListeners (expanded)', async () => {
667
+ await it('should return this from setMaxListeners for chaining', async () => {
668
+ const emitter = new EventEmitter();
669
+ const result = emitter.setMaxListeners(5);
670
+ expect(result).toBe(emitter);
671
+ });
672
+
673
+ await it('should throw for NaN', async () => {
674
+ const emitter = new EventEmitter();
675
+ expect(() => emitter.setMaxListeners(NaN)).toThrow();
676
+ });
677
+
678
+ await it('should accept Infinity', async () => {
679
+ const emitter = new EventEmitter();
680
+ emitter.setMaxListeners(Infinity);
681
+ expect(emitter.getMaxListeners()).toBe(Infinity);
682
+ });
683
+
684
+ await it('static setMaxListeners should set on multiple emitters', async () => {
685
+ const ee1 = new EventEmitter();
686
+ const ee2 = new EventEmitter();
687
+ EventEmitter.setMaxListeners(42, ee1, ee2);
688
+ expect(ee1.getMaxListeners()).toBe(42);
689
+ expect(ee2.getMaxListeners()).toBe(42);
690
+ });
691
+
692
+ await it('static getMaxListeners should return max listeners for emitter', async () => {
693
+ const ee = new EventEmitter();
694
+ expect(EventEmitter.getMaxListeners(ee)).toBe(EventEmitter.defaultMaxListeners);
695
+ ee.setMaxListeners(101);
696
+ expect(EventEmitter.getMaxListeners(ee)).toBe(101);
697
+ });
698
+
699
+ await it('static setMaxListeners with no emitters should set defaultMaxListeners', async () => {
700
+ const original = EventEmitter.defaultMaxListeners;
701
+ try {
702
+ EventEmitter.setMaxListeners(99);
703
+ expect(EventEmitter.defaultMaxListeners).toBe(99);
704
+ } finally {
705
+ EventEmitter.defaultMaxListeners = original;
706
+ }
707
+ });
708
+ });
709
+
710
+ // ==================== expanded tests: errorMonitor ====================
711
+
712
+ await describe('EventEmitter: errorMonitor symbol', async () => {
713
+ await it('should emit to errorMonitor before throwing', async () => {
714
+ const emitter = new EventEmitter();
715
+ let monitorCalled = false;
716
+ let monitorError: Error | undefined;
717
+ emitter.on(EventEmitter.errorMonitor, (err: Error) => {
718
+ monitorCalled = true;
719
+ monitorError = err;
720
+ });
721
+ const testErr = new Error('monitored');
722
+ try {
723
+ emitter.emit('error', testErr);
724
+ } catch {
725
+ // expected
726
+ }
727
+ expect(monitorCalled).toBeTruthy();
728
+ expect(monitorError).toBe(testErr);
729
+ });
730
+
731
+ await it('should emit to errorMonitor even when error listener exists', async () => {
732
+ const emitter = new EventEmitter();
733
+ let monitorCalled = false;
734
+ let errorCalled = false;
735
+ emitter.on(EventEmitter.errorMonitor, () => { monitorCalled = true; });
736
+ emitter.on('error', () => { errorCalled = true; });
737
+ emitter.emit('error', new Error('test'));
738
+ expect(monitorCalled).toBeTruthy();
739
+ expect(errorCalled).toBeTruthy();
740
+ });
741
+
742
+ await it('errorMonitor should be a symbol', async () => {
743
+ expect(typeof EventEmitter.errorMonitor).toBe('symbol');
744
+ });
745
+ });
746
+
747
+ // ==================== expanded tests: captureRejections ====================
748
+
749
+ await describe('EventEmitter: captureRejections', async () => {
750
+ await it('should have captureRejectionSymbol static property', async () => {
751
+ expect(EventEmitter.captureRejectionSymbol).toBeDefined();
752
+ expect(typeof EventEmitter.captureRejectionSymbol).toBe('symbol');
753
+ });
754
+
755
+ await it('should default captureRejections to false', async () => {
756
+ expect(EventEmitter.captureRejections).toBe(false);
757
+ });
758
+
759
+ await it('should accept captureRejections in constructor options', async () => {
760
+ const emitter = new EventEmitter({ captureRejections: true });
761
+ // The emitter was created with captureRejections enabled
762
+ // (internal state, no public getter — just ensure no error thrown)
763
+ expect(emitter).toBeDefined();
764
+ });
765
+
766
+ await it('captureRejections should route async errors to error event', async () => {
767
+ const emitter = new EventEmitter({ captureRejections: true });
768
+ let caughtErr: Error | undefined;
769
+ const expectedErr = new Error('async failure');
770
+ emitter.on('error', (err: Error) => { caughtErr = err; });
771
+ emitter.on('test', async () => {
772
+ throw expectedErr;
773
+ });
774
+ emitter.emit('test');
775
+ // Wait for the microtask to propagate
776
+ await new Promise(r => setTimeout(r, 50));
777
+ expect(caughtErr).toBe(expectedErr);
778
+ });
779
+ });
780
+
781
+ // ==================== expanded tests: getEventListeners static ====================
782
+
783
+ await describe('EventEmitter.getEventListeners (expanded)', async () => {
784
+ await it('should return empty array for non-existent event', async () => {
785
+ const emitter = new EventEmitter();
786
+ const listeners = EventEmitter.getEventListeners(emitter, 'nonexistent');
787
+ expect(listeners.length).toBe(0);
788
+ });
789
+
790
+ await it('should return correct listeners for multiple events', async () => {
791
+ const emitter = new EventEmitter();
792
+ const fn1 = () => {};
793
+ const fn2 = () => {};
794
+ emitter.on('foo', fn1);
795
+ emitter.on('foo', fn2);
796
+ emitter.on('baz', fn1);
797
+ const fooListeners = EventEmitter.getEventListeners(emitter, 'foo');
798
+ expect(fooListeners.length).toBe(2);
799
+ expect(fooListeners[0]).toBe(fn1);
800
+ expect(fooListeners[1]).toBe(fn2);
801
+ const bazListeners = EventEmitter.getEventListeners(emitter, 'baz');
802
+ expect(bazListeners.length).toBe(1);
803
+ expect(bazListeners[0]).toBe(fn1);
804
+ });
805
+
806
+ await it('should unwrap once listeners', async () => {
807
+ const emitter = new EventEmitter();
808
+ const fn = () => {};
809
+ emitter.once('test', fn);
810
+ const listeners = EventEmitter.getEventListeners(emitter, 'test');
811
+ expect(listeners.length).toBe(1);
812
+ expect(listeners[0]).toBe(fn);
813
+ });
814
+ });
815
+
816
+ // ==================== expanded tests: listenerCount static ====================
817
+
818
+ await describe('EventEmitter.listenerCount static (expanded)', async () => {
819
+ await it('should return 0 for no listeners', async () => {
820
+ const emitter = new EventEmitter();
821
+ expect(EventEmitter.listenerCount(emitter, 'test')).toBe(0);
822
+ });
823
+
824
+ await it('should count once listeners', async () => {
825
+ const emitter = new EventEmitter();
826
+ emitter.once('test', () => {});
827
+ expect(EventEmitter.listenerCount(emitter, 'test')).toBe(1);
828
+ });
829
+
830
+ await it('should count mixed on and once listeners', async () => {
831
+ const emitter = new EventEmitter();
832
+ emitter.on('test', () => {});
833
+ emitter.once('test', () => {});
834
+ emitter.on('test', () => {});
835
+ expect(EventEmitter.listenerCount(emitter, 'test')).toBe(3);
836
+ });
837
+ });
838
+
839
+ // ==================== expanded tests: once static (promise-based) ====================
840
+
841
+ await describe('EventEmitter.once static (expanded)', async () => {
842
+ await it('should resolve with empty array when event has no args', async () => {
843
+ const emitter = new EventEmitter();
844
+ const promise = EventEmitter.once(emitter, 'test');
845
+ emitter.emit('test');
846
+ const result = await promise;
847
+ expect(result.length).toBe(0);
848
+ });
849
+
850
+ await it('should clean up listeners after resolving', async () => {
851
+ const emitter = new EventEmitter();
852
+ const promise = EventEmitter.once(emitter, 'test');
853
+ emitter.emit('test', 'value');
854
+ await promise;
855
+ expect(emitter.listenerCount('test')).toBe(0);
856
+ expect(emitter.listenerCount('error')).toBe(0);
857
+ });
858
+
859
+ await it('should clean up listeners after error rejection', async () => {
860
+ const emitter = new EventEmitter();
861
+ const promise = EventEmitter.once(emitter, 'test');
862
+ emitter.emit('error', new Error('fail'));
863
+ try {
864
+ await promise;
865
+ } catch {
866
+ // expected
867
+ }
868
+ expect(emitter.listenerCount('test')).toBe(0);
869
+ expect(emitter.listenerCount('error')).toBe(0);
870
+ });
871
+
872
+ await it('should resolve when listening for error event itself', async () => {
873
+ const emitter = new EventEmitter();
874
+ const expectedErr = new Error('expected');
875
+ const promise = EventEmitter.once(emitter, 'error');
876
+ emitter.emit('error', expectedErr);
877
+ const [err] = await promise;
878
+ expect(err).toBe(expectedErr);
879
+ });
880
+
881
+ await it('should reject with AbortError when signal is already aborted', async () => {
882
+ const emitter = new EventEmitter();
883
+ const abortedSignal = AbortSignal.abort();
884
+ try {
885
+ await EventEmitter.once(emitter, 'test', { signal: abortedSignal });
886
+ expect(false).toBeTruthy();
887
+ } catch (err: any) {
888
+ expect(err.name).toBe('AbortError');
889
+ }
890
+ });
891
+
892
+ await it('should reject when abort signal fires after call', async () => {
893
+ const emitter = new EventEmitter();
894
+ const ac = new AbortController();
895
+ const promise = EventEmitter.once(emitter, 'test', { signal: ac.signal });
896
+ ac.abort();
897
+ try {
898
+ await promise;
899
+ expect(false).toBeTruthy();
900
+ } catch (err: any) {
901
+ expect(err.name).toBe('AbortError');
902
+ }
903
+ });
904
+ });
905
+
906
+ // ==================== expanded tests: prependListener / prependOnceListener ====================
907
+
908
+ await describe('EventEmitter: prependListener (expanded)', async () => {
909
+ await it('should return this for chaining', async () => {
910
+ const emitter = new EventEmitter();
911
+ const result = emitter.prependListener('test', () => {});
912
+ expect(result).toBe(emitter);
913
+ });
914
+
915
+ await it('should prepend multiple listeners in correct order', async () => {
916
+ const emitter = new EventEmitter();
917
+ const order: number[] = [];
918
+ emitter.on('test', () => order.push(1));
919
+ emitter.prependListener('test', () => order.push(2));
920
+ emitter.prependListener('test', () => order.push(3));
921
+ emitter.emit('test');
922
+ // Last prepended is first
923
+ expect(order[0]).toBe(3);
924
+ expect(order[1]).toBe(2);
925
+ expect(order[2]).toBe(1);
926
+ });
927
+ });
928
+
929
+ await describe('EventEmitter: prependOnceListener (expanded)', async () => {
930
+ await it('should return this for chaining', async () => {
931
+ const emitter = new EventEmitter();
932
+ const result = emitter.prependOnceListener('test', () => {});
933
+ expect(result).toBe(emitter);
934
+ });
935
+
936
+ await it('should only fire once and then be removed', async () => {
937
+ const emitter = new EventEmitter();
938
+ let count = 0;
939
+ emitter.prependOnceListener('test', () => { count++; });
940
+ emitter.emit('test');
941
+ emitter.emit('test');
942
+ expect(count).toBe(1);
943
+ expect(emitter.listenerCount('test')).toBe(0);
944
+ });
945
+ });
946
+
947
+ // ==================== expanded tests: eventNames ====================
948
+
949
+ await describe('EventEmitter: eventNames (expanded)', async () => {
950
+ await it('should reflect removal of events', async () => {
951
+ const emitter = new EventEmitter();
952
+ const fn = () => {};
953
+ emitter.on('foo', () => {});
954
+ emitter.on('bar', fn);
955
+ expect(emitter.eventNames().length).toBe(2);
956
+ emitter.removeListener('bar', fn);
957
+ const names = emitter.eventNames();
958
+ expect(names.length).toBe(1);
959
+ expect(names[0]).toBe('foo');
960
+ });
961
+
962
+ await it('should list symbol event names alongside string names', async () => {
963
+ const emitter = new EventEmitter();
964
+ const sym = Symbol('s');
965
+ emitter.on('foo', () => {});
966
+ emitter.on(sym, () => {});
967
+ const names = emitter.eventNames();
968
+ expect(names.length).toBe(2);
969
+ expect(names[0]).toBe('foo');
970
+ expect(typeof names[1]).toBe('symbol');
971
+ });
972
+ });
973
+
974
+ // ==================== expanded tests: rawListeners ====================
975
+
976
+ await describe('EventEmitter: rawListeners (expanded)', async () => {
977
+ await it('should return unwrapped functions for on listeners', async () => {
978
+ const emitter = new EventEmitter();
979
+ const fn = () => {};
980
+ emitter.on('test', fn);
981
+ const raw = emitter.rawListeners('test');
982
+ expect(raw.length).toBe(1);
983
+ expect(raw[0]).toBe(fn);
984
+ });
985
+
986
+ await it('should return empty array for non-existent event', async () => {
987
+ const emitter = new EventEmitter();
988
+ const raw = emitter.rawListeners('nonexistent');
989
+ expect(raw.length).toBe(0);
990
+ });
991
+
992
+ await it('raw once listeners should be callable and remove themselves', async () => {
993
+ const emitter = new EventEmitter();
994
+ let called = false;
995
+ emitter.once('test', () => { called = true; });
996
+ const raw = emitter.rawListeners('test');
997
+ expect(raw.length).toBe(1);
998
+ // Call the raw (wrapped) listener directly
999
+ raw[0]();
1000
+ expect(called).toBeTruthy();
1001
+ // After calling, the once listener should be removed
1002
+ expect(emitter.listenerCount('test')).toBe(0);
1003
+ });
1004
+ });
1005
+
1006
+ // ==================== expanded tests: removeAllListeners with specific event ====================
1007
+
1008
+ await describe('EventEmitter: removeAllListeners specific (expanded)', async () => {
1009
+ await it('should not affect other events when removing specific event', async () => {
1010
+ const emitter = new EventEmitter();
1011
+ emitter.on('a', () => {});
1012
+ emitter.on('a', () => {});
1013
+ emitter.on('b', () => {});
1014
+ emitter.on('c', () => {});
1015
+ emitter.removeAllListeners('a');
1016
+ expect(emitter.listenerCount('a')).toBe(0);
1017
+ expect(emitter.listenerCount('b')).toBe(1);
1018
+ expect(emitter.listenerCount('c')).toBe(1);
1019
+ });
1020
+
1021
+ await it('should emit removeListener for each removed listener', async () => {
1022
+ const emitter = new EventEmitter();
1023
+ const removed: string[] = [];
1024
+ emitter.on('removeListener', (name: string) => { removed.push(name); });
1025
+ emitter.on('data', () => {});
1026
+ emitter.on('data', () => {});
1027
+ emitter.removeAllListeners('data');
1028
+ expect(removed.length).toBe(2);
1029
+ expect(removed[0]).toBe('data');
1030
+ expect(removed[1]).toBe('data');
1031
+ });
1032
+ });
1033
+
1034
+ // ==================== expanded tests: error handling ====================
1035
+
1036
+ await describe('EventEmitter: error handling (expanded)', async () => {
1037
+ await it('should throw the Error object directly when emitting error', async () => {
1038
+ const emitter = new EventEmitter();
1039
+ const err = new Error('direct throw');
1040
+ try {
1041
+ emitter.emit('error', err);
1042
+ expect(false).toBeTruthy();
1043
+ } catch (caught) {
1044
+ expect(caught).toBe(err);
1045
+ }
1046
+ });
1047
+
1048
+ await it('should throw generic error when emitting error with no args', async () => {
1049
+ const emitter = new EventEmitter();
1050
+ try {
1051
+ emitter.emit('error');
1052
+ expect(false).toBeTruthy();
1053
+ } catch (err: any) {
1054
+ expect(err instanceof Error).toBeTruthy();
1055
+ expect(err.message).toMatch('Unhandled error');
1056
+ }
1057
+ });
1058
+
1059
+ await it('should throw wrapped error when emitting non-Error error arg', async () => {
1060
+ const emitter = new EventEmitter();
1061
+ try {
1062
+ emitter.emit('error', 42);
1063
+ expect(false).toBeTruthy();
1064
+ } catch (err: any) {
1065
+ expect(err.context).toBe(42);
1066
+ }
1067
+ });
1068
+ });
1069
+
1070
+ // ==================== expanded tests: emit returns boolean ====================
1071
+
1072
+ await describe('EventEmitter: emit return value (expanded)', async () => {
1073
+ await it('should return true when once listener exists', async () => {
1074
+ const emitter = new EventEmitter();
1075
+ emitter.once('test', () => {});
1076
+ expect(emitter.emit('test')).toBeTruthy();
1077
+ });
1078
+
1079
+ await it('should return false after once listener consumed', async () => {
1080
+ const emitter = new EventEmitter();
1081
+ emitter.once('test', () => {});
1082
+ emitter.emit('test');
1083
+ expect(emitter.emit('test')).toBeFalsy();
1084
+ });
1085
+
1086
+ await it('should return true for each emit when persistent listener exists', async () => {
1087
+ const emitter = new EventEmitter();
1088
+ emitter.on('test', () => {});
1089
+ expect(emitter.emit('test')).toBeTruthy();
1090
+ expect(emitter.emit('test')).toBeTruthy();
1091
+ });
1092
+ });
1093
+
1094
+ // ==================== expanded tests: Symbol events ====================
1095
+
1096
+ await describe('EventEmitter: Symbol events (expanded)', async () => {
1097
+ await it('should pass arguments with Symbol events', async () => {
1098
+ const emitter = new EventEmitter();
1099
+ const sym = Symbol('data');
1100
+ let received: unknown;
1101
+ emitter.on(sym, (val: unknown) => { received = val; });
1102
+ emitter.emit(sym, 'hello');
1103
+ expect(received).toBe('hello');
1104
+ });
1105
+
1106
+ await it('should support once with Symbol events', async () => {
1107
+ const emitter = new EventEmitter();
1108
+ const sym = Symbol('once');
1109
+ let count = 0;
1110
+ emitter.once(sym, () => { count++; });
1111
+ emitter.emit(sym);
1112
+ emitter.emit(sym);
1113
+ expect(count).toBe(1);
1114
+ });
1115
+
1116
+ await it('should support removeAllListeners with Symbol events', async () => {
1117
+ const emitter = new EventEmitter();
1118
+ const sym = Symbol('rem');
1119
+ emitter.on(sym, () => {});
1120
+ emitter.on(sym, () => {});
1121
+ emitter.removeAllListeners(sym);
1122
+ expect(emitter.listenerCount(sym)).toBe(0);
1123
+ });
1124
+
1125
+ await it('should support prependListener with Symbol events', async () => {
1126
+ const emitter = new EventEmitter();
1127
+ const sym = Symbol('prepend');
1128
+ const order: number[] = [];
1129
+ emitter.on(sym, () => order.push(1));
1130
+ emitter.prependListener(sym, () => order.push(0));
1131
+ emitter.emit(sym);
1132
+ expect(order[0]).toBe(0);
1133
+ expect(order[1]).toBe(1);
1134
+ });
1135
+ });
1136
+
1137
+ // ==================== expanded tests: multiple listeners ordering ====================
1138
+
1139
+ await describe('EventEmitter: multiple listeners ordering (expanded)', async () => {
1140
+ await it('should call listeners in registration order', async () => {
1141
+ const emitter = new EventEmitter();
1142
+ const order: number[] = [];
1143
+ for (let i = 0; i < 5; i++) {
1144
+ const val = i;
1145
+ emitter.on('test', () => order.push(val));
1146
+ }
1147
+ emitter.emit('test');
1148
+ expect(order.length).toBe(5);
1149
+ for (let i = 0; i < 5; i++) {
1150
+ expect(order[i]).toBe(i);
1151
+ }
1152
+ });
1153
+
1154
+ await it('should maintain order with mixed on and once', async () => {
1155
+ const emitter = new EventEmitter();
1156
+ const order: number[] = [];
1157
+ emitter.on('test', () => order.push(1));
1158
+ emitter.once('test', () => order.push(2));
1159
+ emitter.on('test', () => order.push(3));
1160
+ emitter.emit('test');
1161
+ expect(order.length).toBe(3);
1162
+ expect(order[0]).toBe(1);
1163
+ expect(order[1]).toBe(2);
1164
+ expect(order[2]).toBe(3);
1165
+ });
1166
+
1167
+ await it('should maintain order with prepend mixed in', async () => {
1168
+ const emitter = new EventEmitter();
1169
+ const order: number[] = [];
1170
+ emitter.on('test', () => order.push(1));
1171
+ emitter.on('test', () => order.push(2));
1172
+ emitter.prependListener('test', () => order.push(0));
1173
+ emitter.prependOnceListener('test', () => order.push(-1));
1174
+ emitter.emit('test');
1175
+ expect(order.length).toBe(4);
1176
+ expect(order[0]).toBe(-1);
1177
+ expect(order[1]).toBe(0);
1178
+ expect(order[2]).toBe(1);
1179
+ expect(order[3]).toBe(2);
1180
+ });
1181
+ });
1182
+
1183
+ // ==================== expanded tests: on async iterator ====================
1184
+
1185
+ await describe('EventEmitter.on async iterator (expanded)', async () => {
1186
+ await it('should be an async iterable', async () => {
1187
+ const emitter = new EventEmitter();
1188
+ const iterator = EventEmitter.on(emitter, 'data');
1189
+ expect(typeof iterator[Symbol.asyncIterator]).toBe('function');
1190
+ expect(iterator[Symbol.asyncIterator]()).toBe(iterator);
1191
+ await iterator.return!();
1192
+ });
1193
+
1194
+ await it('should buffer events emitted before consumption', async () => {
1195
+ const emitter = new EventEmitter();
1196
+ const iterator = EventEmitter.on(emitter, 'data');
1197
+ emitter.emit('data', 'a');
1198
+ emitter.emit('data', 'b');
1199
+ emitter.emit('data', 'c');
1200
+
1201
+ const r1 = await iterator.next();
1202
+ expect(r1.done).toBeFalsy();
1203
+ expect(r1.value[0]).toBe('a');
1204
+
1205
+ const r2 = await iterator.next();
1206
+ expect(r2.done).toBeFalsy();
1207
+ expect(r2.value[0]).toBe('b');
1208
+
1209
+ const r3 = await iterator.next();
1210
+ expect(r3.done).toBeFalsy();
1211
+ expect(r3.value[0]).toBe('c');
1212
+
1213
+ await iterator.return!();
1214
+ });
1215
+
1216
+ await it('should clean up listeners after return', async () => {
1217
+ const emitter = new EventEmitter();
1218
+ const iterator = EventEmitter.on(emitter, 'data');
1219
+ expect(emitter.listenerCount('data')).toBe(1);
1220
+ await iterator.return!();
1221
+ expect(emitter.listenerCount('data')).toBe(0);
1222
+ });
1223
+
1224
+ await it('should yield multiple arguments as array', async () => {
1225
+ const emitter = new EventEmitter();
1226
+ const iterator = EventEmitter.on(emitter, 'data');
1227
+ emitter.emit('data', 1, 2, 3);
1228
+ const result = await iterator.next();
1229
+ expect(result.value.length).toBe(3);
1230
+ expect(result.value[0]).toBe(1);
1231
+ expect(result.value[1]).toBe(2);
1232
+ expect(result.value[2]).toBe(3);
1233
+ await iterator.return!();
1234
+ });
1235
+
1236
+ await it('return should signal done', async () => {
1237
+ const emitter = new EventEmitter();
1238
+ const iterator = EventEmitter.on(emitter, 'data');
1239
+ const result = await iterator.return!();
1240
+ expect(result.done).toBeTruthy();
1241
+ });
1242
+ });
1243
+
1244
+ // ==================== expanded tests: newListener and removeListener events ====================
1245
+
1246
+ await describe('EventEmitter: newListener event (expanded)', async () => {
1247
+ await it('should receive the listener function as second arg', async () => {
1248
+ const emitter = new EventEmitter();
1249
+ let receivedFn: unknown;
1250
+ const fn = () => {};
1251
+ emitter.on('newListener', (_name: string, listener: unknown) => {
1252
+ receivedFn = listener;
1253
+ });
1254
+ emitter.on('test', fn);
1255
+ expect(receivedFn).toBe(fn);
1256
+ });
1257
+
1258
+ await it('should fire for once listeners with original function', async () => {
1259
+ const emitter = new EventEmitter();
1260
+ let receivedFn: unknown;
1261
+ const fn = () => {};
1262
+ emitter.on('newListener', (_name: string, listener: unknown) => {
1263
+ if (_name === 'test') receivedFn = listener;
1264
+ });
1265
+ emitter.once('test', fn);
1266
+ expect(receivedFn).toBe(fn);
1267
+ });
1268
+
1269
+ await it('should not emit newListener for newListener itself', async () => {
1270
+ const emitter = new EventEmitter();
1271
+ const names: string[] = [];
1272
+ emitter.on('newListener', (name: string) => { names.push(name); });
1273
+ emitter.on('foo', () => {});
1274
+ emitter.on('bar', () => {});
1275
+ expect(names.length).toBe(2);
1276
+ expect(names[0]).toBe('foo');
1277
+ expect(names[1]).toBe('bar');
1278
+ });
1279
+ });
1280
+
1281
+ await describe('EventEmitter: removeListener event (expanded)', async () => {
1282
+ await it('should fire when once listener is removed by emit', async () => {
1283
+ const emitter = new EventEmitter();
1284
+ const removed: string[] = [];
1285
+ emitter.on('removeListener', (name: string) => { removed.push(name); });
1286
+ emitter.once('test', () => {});
1287
+ emitter.emit('test');
1288
+ expect(removed).toContain('test');
1289
+ });
1290
+
1291
+ await it('should fire for each removed listener from removeAllListeners', async () => {
1292
+ const emitter = new EventEmitter();
1293
+ let removeCount = 0;
1294
+ emitter.on('removeListener', () => { removeCount++; });
1295
+ emitter.on('test', () => {});
1296
+ emitter.on('test', () => {});
1297
+ emitter.on('test', () => {});
1298
+ emitter.removeAllListeners('test');
1299
+ expect(removeCount).toBe(3);
1300
+ });
1301
+ });
1302
+
1303
+ // ==================== expanded tests: EventEmitter.EventEmitter backward compat ====================
1304
+
1305
+ await describe('EventEmitter: backward compatibility', async () => {
1306
+ await it('EventEmitter.EventEmitter should reference itself', async () => {
1307
+ expect((EventEmitter as any).EventEmitter).toBe(EventEmitter);
1308
+ });
1309
+ });
1310
+
1311
+ // ==================== expanded tests: listeners copy behavior ====================
1312
+
1313
+ await describe('EventEmitter: listeners returns a copy', async () => {
1314
+ await it('should return a copy, not a reference', async () => {
1315
+ const emitter = new EventEmitter();
1316
+ const fn = () => {};
1317
+ emitter.on('test', fn);
1318
+ const list1 = emitter.listeners('test');
1319
+ const list2 = emitter.listeners('test');
1320
+ // They should be different array objects
1321
+ expect(list1.length).toBe(list2.length);
1322
+ expect(list1[0]).toBe(list2[0]);
1323
+ // Mutating one should not affect the other
1324
+ list1.push(() => {});
1325
+ expect(list2.length).toBe(1);
1326
+ });
1327
+ });
1328
+
1329
+ // ==================== expanded tests: addListener chaining ====================
1330
+
1331
+ await describe('EventEmitter: chaining', async () => {
1332
+ await it('should support fluent chaining of multiple methods', async () => {
1333
+ const emitter = new EventEmitter();
1334
+ let count = 0;
1335
+ emitter
1336
+ .on('a', () => { count++; })
1337
+ .on('b', () => { count++; })
1338
+ .once('c', () => { count++; });
1339
+ emitter.emit('a');
1340
+ emitter.emit('b');
1341
+ emitter.emit('c');
1342
+ expect(count).toBe(3);
1343
+ });
1344
+ });
1345
+
1346
+ // ==================== expanded tests: this binding in listeners ====================
1347
+
1348
+ await describe('EventEmitter: this in listeners', async () => {
1349
+ await it('should bind this to the emitter in on listeners', async () => {
1350
+ const emitter = new EventEmitter();
1351
+ let self: unknown;
1352
+ emitter.on('test', function(this: unknown) { self = this; });
1353
+ emitter.emit('test');
1354
+ expect(self).toBe(emitter);
1355
+ });
1356
+
1357
+ await it('should bind this to the emitter in once listeners', async () => {
1358
+ const emitter = new EventEmitter();
1359
+ let self: unknown;
1360
+ emitter.once('test', function(this: unknown) { self = this; });
1361
+ emitter.emit('test');
1362
+ expect(self).toBe(emitter);
1363
+ });
1364
+ });
1365
+
1366
+ // ==================== expanded tests: listener validation ====================
1367
+
1368
+ await describe('EventEmitter: listener validation', async () => {
1369
+ await it('should throw TypeError for non-function listener on on()', async () => {
1370
+ const emitter = new EventEmitter();
1371
+ expect(() => emitter.on('test', 'notfn' as any)).toThrow();
1372
+ });
1373
+
1374
+ await it('should throw TypeError for non-function listener on once()', async () => {
1375
+ const emitter = new EventEmitter();
1376
+ expect(() => emitter.once('test', 42 as any)).toThrow();
1377
+ });
1378
+
1379
+ await it('should throw TypeError for non-function listener on removeListener()', async () => {
1380
+ const emitter = new EventEmitter();
1381
+ expect(() => emitter.removeListener('test', null as any)).toThrow();
1382
+ });
1383
+ });
158
1384
  }