@dangao/bun-server 1.8.0 → 1.8.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.
Files changed (62) hide show
  1. package/docs/api.md +194 -81
  2. package/docs/extensions.md +53 -0
  3. package/docs/guide.md +243 -1
  4. package/docs/microservice-config-center.md +73 -74
  5. package/docs/microservice-nacos.md +89 -90
  6. package/docs/microservice-service-registry.md +85 -86
  7. package/docs/microservice.md +142 -137
  8. package/docs/request-lifecycle.md +45 -4
  9. package/docs/symbol-interface-pattern.md +106 -106
  10. package/docs/zh/api.md +458 -18
  11. package/docs/zh/extensions.md +53 -0
  12. package/docs/zh/guide.md +251 -4
  13. package/docs/zh/microservice-config-center.md +258 -0
  14. package/docs/zh/microservice-nacos.md +346 -0
  15. package/docs/zh/microservice-service-registry.md +306 -0
  16. package/docs/zh/microservice.md +680 -0
  17. package/docs/zh/request-lifecycle.md +43 -5
  18. package/package.json +1 -1
  19. package/tests/auth/auth-decorators.test.ts +241 -0
  20. package/tests/auth/oauth2-service.test.ts +318 -0
  21. package/tests/cache/cache-decorators-extended.test.ts +272 -0
  22. package/tests/cache/cache-interceptors.test.ts +534 -0
  23. package/tests/cache/cache-service-proxy.test.ts +246 -0
  24. package/tests/cache/memory-cache-store.test.ts +155 -0
  25. package/tests/cache/redis-cache-store.test.ts +199 -0
  26. package/tests/config/config-center-integration.test.ts +334 -0
  27. package/tests/config/config-module-extended.test.ts +165 -0
  28. package/tests/controller/param-binder.test.ts +333 -0
  29. package/tests/error/error-handler.test.ts +166 -57
  30. package/tests/error/i18n-extended.test.ts +105 -0
  31. package/tests/events/event-listener-scanner.test.ts +114 -0
  32. package/tests/events/event-module.test.ts +133 -302
  33. package/tests/extensions/logger-module.test.ts +158 -0
  34. package/tests/files/file-storage.test.ts +136 -0
  35. package/tests/interceptor/base-interceptor.test.ts +605 -0
  36. package/tests/interceptor/builtin/cache-interceptor.test.ts +233 -86
  37. package/tests/interceptor/builtin/log-interceptor.test.ts +469 -0
  38. package/tests/interceptor/builtin/permission-interceptor.test.ts +219 -120
  39. package/tests/interceptor/interceptor-chain.test.ts +241 -189
  40. package/tests/interceptor/interceptor-metadata.test.ts +221 -0
  41. package/tests/microservice/circuit-breaker.test.ts +221 -0
  42. package/tests/microservice/service-client-decorators.test.ts +86 -0
  43. package/tests/microservice/service-client-interceptors.test.ts +274 -0
  44. package/tests/microservice/service-registry-decorators.test.ts +147 -0
  45. package/tests/microservice/tracer.test.ts +213 -0
  46. package/tests/microservice/tracing-collectors.test.ts +168 -0
  47. package/tests/middleware/builtin/middleware-builtin-extended.test.ts +237 -0
  48. package/tests/middleware/builtin/rate-limit.test.ts +257 -0
  49. package/tests/middleware/middleware-decorators.test.ts +222 -0
  50. package/tests/middleware/middleware-pipeline.test.ts +160 -0
  51. package/tests/queue/queue-decorators.test.ts +139 -0
  52. package/tests/queue/queue-service.test.ts +191 -0
  53. package/tests/request/body-parser-extended.test.ts +291 -0
  54. package/tests/request/request-wrapper.test.ts +319 -0
  55. package/tests/router/router-decorators.test.ts +260 -0
  56. package/tests/router/router-extended.test.ts +298 -0
  57. package/tests/security/guards/reflector.test.ts +188 -0
  58. package/tests/security/security-filter.test.ts +182 -0
  59. package/tests/security/security-module-extended.test.ts +133 -0
  60. package/tests/session/memory-session-store.test.ts +172 -0
  61. package/tests/session/session-decorators.test.ts +163 -0
  62. package/tests/swagger/ui.test.ts +212 -0
@@ -0,0 +1,114 @@
1
+ import { describe, expect, test, beforeEach } from 'bun:test';
2
+ import 'reflect-metadata';
3
+
4
+ import { EventListenerScanner, EVENT_LISTENER_SCANNER_TOKEN } from '../../src/events/event-module';
5
+ import { EventEmitterService } from '../../src/events/service';
6
+ import { OnEvent } from '../../src/events/decorators';
7
+ import { EVENT_LISTENER_CLASS_METADATA_KEY } from '../../src/events/types';
8
+ import { Container } from '../../src/di/container';
9
+ import { Injectable } from '../../src/di/decorators';
10
+
11
+ describe('EventListenerScanner', () => {
12
+ let emitter: EventEmitterService;
13
+ let container: Container;
14
+ let scanner: EventListenerScanner;
15
+
16
+ beforeEach(() => {
17
+ emitter = new EventEmitterService();
18
+ container = new Container();
19
+ scanner = new EventListenerScanner(emitter, container);
20
+ });
21
+
22
+ describe('scanAndRegister', () => {
23
+ test('should register listeners from class with OnEvent decorator', () => {
24
+ @Injectable()
25
+ class TestListener {
26
+ public receivedPayload: any = null;
27
+
28
+ @OnEvent('test-event')
29
+ public handleTestEvent(payload: any): void {
30
+ this.receivedPayload = payload;
31
+ }
32
+ }
33
+
34
+ // Mark as event listener class
35
+ Reflect.defineMetadata(EVENT_LISTENER_CLASS_METADATA_KEY, true, TestListener);
36
+
37
+ container.register(TestListener);
38
+ scanner.scanAndRegister([TestListener]);
39
+
40
+ expect(emitter.listenerCount('test-event')).toBe(1);
41
+ });
42
+
43
+ test('should skip non-listener classes', () => {
44
+ class NotAListener {
45
+ public someMethod(): void {}
46
+ }
47
+
48
+ scanner.scanAndRegister([NotAListener]);
49
+
50
+ // No listeners registered
51
+ expect(emitter.listenerCount('some-event')).toBe(0);
52
+ });
53
+
54
+ test('should handle multiple listeners', () => {
55
+ @Injectable()
56
+ class MultiListener {
57
+ @OnEvent('event1')
58
+ public handleEvent1(): void {}
59
+
60
+ @OnEvent('event2')
61
+ public handleEvent2(): void {}
62
+ }
63
+
64
+ Reflect.defineMetadata(EVENT_LISTENER_CLASS_METADATA_KEY, true, MultiListener);
65
+
66
+ container.register(MultiListener);
67
+ scanner.scanAndRegister([MultiListener]);
68
+
69
+ expect(emitter.listenerCount('event1')).toBe(1);
70
+ expect(emitter.listenerCount('event2')).toBe(1);
71
+ });
72
+ });
73
+
74
+ describe('registerListenerClass', () => {
75
+ test('should register single listener class', () => {
76
+ @Injectable()
77
+ class SingleListener {
78
+ @OnEvent('single-event')
79
+ public handle(): void {}
80
+ }
81
+
82
+ Reflect.defineMetadata(EVENT_LISTENER_CLASS_METADATA_KEY, true, SingleListener);
83
+ container.register(SingleListener);
84
+
85
+ scanner.registerListenerClass(SingleListener);
86
+
87
+ expect(emitter.listenerCount('single-event')).toBe(1);
88
+ });
89
+
90
+ test('should skip class without metadata', () => {
91
+ class NoMetadata {
92
+ public handle(): void {}
93
+ }
94
+
95
+ scanner.registerListenerClass(NoMetadata);
96
+
97
+ expect(emitter.eventNames().length).toBe(0);
98
+ });
99
+
100
+ test('should handle class not registered in container', () => {
101
+ @Injectable()
102
+ class UnregisteredListener {
103
+ @OnEvent('unreg-event')
104
+ public handle(): void {}
105
+ }
106
+
107
+ Reflect.defineMetadata(EVENT_LISTENER_CLASS_METADATA_KEY, true, UnregisteredListener);
108
+ // Not registering in container
109
+
110
+ // Should not throw, just warn
111
+ expect(() => scanner.registerListenerClass(UnregisteredListener)).not.toThrow();
112
+ });
113
+ });
114
+ });
@@ -1,373 +1,204 @@
1
- import { describe, expect, test, beforeEach, mock } from 'bun:test';
1
+ import { describe, expect, test, beforeEach, afterEach } from 'bun:test';
2
2
  import 'reflect-metadata';
3
- import { EventModule, EventListenerScanner } from '../../src/events/event-module';
3
+
4
+ import { EventModule } from '../../src/events/event-module';
4
5
  import { EventEmitterService } from '../../src/events/service';
5
- import { OnEvent, getOnEventMetadata, isEventListenerClass } from '../../src/events/decorators';
6
- import { Container } from '../../src/di/container';
7
- import { Injectable } from '../../src/di/decorators';
6
+ import { EVENT_EMITTER_TOKEN, EVENT_OPTIONS_TOKEN } from '../../src/events/types';
8
7
  import { MODULE_METADATA_KEY } from '../../src/di/module';
9
- import { ModuleRegistry } from '../../src/di/module-registry';
10
- import {
11
- EVENT_EMITTER_TOKEN,
12
- EVENT_OPTIONS_TOKEN,
13
- type EventEmitter,
14
- } from '../../src/events/types';
15
8
 
16
9
  describe('EventModule', () => {
17
10
  beforeEach(() => {
18
- // 清除模块元数据
19
11
  Reflect.deleteMetadata(MODULE_METADATA_KEY, EventModule);
20
12
  });
21
13
 
22
- describe('forRoot()', () => {
23
- test('should register event emitter service', () => {
14
+ describe('forRoot', () => {
15
+ test('should create module with default options', () => {
24
16
  EventModule.forRoot();
25
17
 
26
18
  const metadata = Reflect.getMetadata(MODULE_METADATA_KEY, EventModule);
27
19
  expect(metadata.providers).toBeDefined();
28
- expect(metadata.providers.length).toBeGreaterThanOrEqual(2);
29
-
30
- const emitterProvider = metadata.providers.find(
31
- (p: any) => p.provide === EVENT_EMITTER_TOKEN,
32
- );
33
- expect(emitterProvider).toBeDefined();
34
- expect(emitterProvider.useValue).toBeInstanceOf(EventEmitterService);
20
+ expect(metadata.exports).toContain(EVENT_EMITTER_TOKEN);
35
21
  });
36
22
 
37
- test('should register options', () => {
38
- const options = { wildcard: true, maxListeners: 50 };
39
- EventModule.forRoot(options);
23
+ test('should create module with custom options', () => {
24
+ EventModule.forRoot({
25
+ maxListeners: 50,
26
+ async: true,
27
+ errorHandler: (event, error) => {
28
+ console.error(`Event ${event} error:`, error);
29
+ },
30
+ });
40
31
 
41
32
  const metadata = Reflect.getMetadata(MODULE_METADATA_KEY, EventModule);
33
+ expect(metadata.providers).toBeDefined();
34
+
35
+ // Find options provider
42
36
  const optionsProvider = metadata.providers.find(
43
37
  (p: any) => p.provide === EVENT_OPTIONS_TOKEN,
44
38
  );
45
-
46
- expect(optionsProvider).toBeDefined();
47
- expect(optionsProvider.useValue).toEqual(options);
39
+ expect(optionsProvider?.useValue?.maxListeners).toBe(50);
40
+ expect(optionsProvider?.useValue?.async).toBe(true);
48
41
  });
49
42
 
50
- test('should export event emitter token', () => {
43
+ test('should export EventService', () => {
51
44
  EventModule.forRoot();
52
45
 
53
46
  const metadata = Reflect.getMetadata(MODULE_METADATA_KEY, EventModule);
54
47
  expect(metadata.exports).toContain(EVENT_EMITTER_TOKEN);
55
48
  });
56
-
57
- test('should apply options to event emitter', () => {
58
- EventModule.forRoot({ wildcard: true, globalPrefix: 'test' });
59
-
60
- const metadata = Reflect.getMetadata(MODULE_METADATA_KEY, EventModule);
61
- const emitterProvider = metadata.providers.find(
62
- (p: any) => p.provide === EVENT_EMITTER_TOKEN,
63
- );
64
-
65
- // EventEmitterService 内部存储了选项
66
- expect(emitterProvider.useValue).toBeInstanceOf(EventEmitterService);
67
- });
68
- });
69
-
70
- describe('getEventEmitter()', () => {
71
- test('should return event emitter from container', () => {
72
- EventModule.forRoot();
73
-
74
- const container = new Container();
75
- const emitterService = new EventEmitterService();
76
- // 使用 registerInstance 方法注册实例(对应 useValue)
77
- container.registerInstance(EVENT_EMITTER_TOKEN, emitterService);
78
-
79
- const result = EventModule.getEventEmitter(container);
80
- expect(result).toBe(emitterService);
81
- });
82
-
83
- test('should return undefined when not registered', () => {
84
- const container = new Container();
85
- // getEventEmitter 现在会捕获错误并返回 undefined
86
- const result = EventModule.getEventEmitter(container);
87
- expect(result).toBeUndefined();
88
- });
89
49
  });
90
50
  });
91
51
 
92
- describe('EventListenerScanner', () => {
93
- let container: Container;
94
- let eventEmitter: EventEmitterService;
95
- let scanner: EventListenerScanner;
52
+ describe('EventEmitterService', () => {
53
+ let service: EventEmitterService;
96
54
 
97
55
  beforeEach(() => {
98
- container = new Container();
99
- eventEmitter = new EventEmitterService();
100
- scanner = new EventListenerScanner(eventEmitter, container);
56
+ service = new EventEmitterService({ maxListeners: 10 });
101
57
  });
102
58
 
103
- test('should scan and register event listeners', () => {
104
- const handler = mock(() => {});
105
-
106
- @Injectable()
107
- class TestService {
108
- @OnEvent('test.event')
109
- public handleEvent(payload: unknown): void {
110
- handler(payload);
111
- }
112
- }
113
-
114
- // 注册服务到容器
115
- container.register(TestService, { useClass: TestService });
116
-
117
- // 扫描并注册监听器
118
- scanner.scanAndRegister([TestService]);
119
-
120
- // 触发事件
121
- eventEmitter.emit('test.event', { data: 'test' });
122
-
123
- expect(handler).toHaveBeenCalledTimes(1);
124
- expect(handler).toHaveBeenCalledWith({ data: 'test' });
59
+ afterEach(() => {
60
+ service.removeAllListeners();
125
61
  });
126
62
 
127
- test('should register multiple listeners from same class', () => {
128
- const handler1 = mock(() => {});
129
- const handler2 = mock(() => {});
63
+ describe('on', () => {
64
+ test('should register listener', () => {
65
+ const handler = () => {};
66
+ service.on('test-event', handler);
130
67
 
131
- @Injectable()
132
- class TestService {
133
- @OnEvent('event1')
134
- public handleEvent1(payload: unknown): void {
135
- handler1(payload);
136
- }
68
+ expect(service.listenerCount('test-event')).toBe(1);
69
+ });
137
70
 
138
- @OnEvent('event2')
139
- public handleEvent2(payload: unknown): void {
140
- handler2(payload);
141
- }
142
- }
71
+ test('should return unsubscribe function', () => {
72
+ const handler = () => {};
73
+ const unsubscribe = service.on('test-event', handler);
143
74
 
144
- container.register(TestService, { useClass: TestService });
145
- scanner.scanAndRegister([TestService]);
75
+ expect(typeof unsubscribe).toBe('function');
76
+ unsubscribe();
77
+ expect(service.listenerCount('test-event')).toBe(0);
78
+ });
146
79
 
147
- eventEmitter.emit('event1', 'payload1');
148
- eventEmitter.emit('event2', 'payload2');
80
+ test('should support multiple listeners', () => {
81
+ service.on('event', () => {});
82
+ service.on('event', () => {});
83
+ service.on('event', () => {});
149
84
 
150
- expect(handler1).toHaveBeenCalledWith('payload1');
151
- expect(handler2).toHaveBeenCalledWith('payload2');
85
+ expect(service.listenerCount('event')).toBe(3);
86
+ });
152
87
  });
153
88
 
154
- test('should respect listener priority', () => {
155
- const order: number[] = [];
89
+ describe('once', () => {
90
+ test('should register one-time listener', async () => {
91
+ let callCount = 0;
92
+ service.once('one-time', () => {
93
+ callCount++;
94
+ });
156
95
 
157
- @Injectable()
158
- class TestService {
159
- @OnEvent('test.event', { priority: 1 })
160
- public lowPriority(): void {
161
- order.push(1);
162
- }
96
+ await service.emit('one-time');
97
+ await service.emit('one-time');
163
98
 
164
- @OnEvent('test.event', { priority: 10 })
165
- public highPriority(): void {
166
- order.push(10);
167
- }
168
- }
169
-
170
- container.register(TestService, { useClass: TestService });
171
- scanner.scanAndRegister([TestService]);
172
-
173
- eventEmitter.emit('test.event', null);
174
-
175
- expect(order).toEqual([10, 1]);
99
+ expect(callCount).toBe(1);
100
+ });
176
101
  });
177
102
 
178
- test('should skip non-listener classes', () => {
179
- @Injectable()
180
- class RegularService {
181
- public doSomething(): void {}
182
- }
103
+ describe('emit', () => {
104
+ test('should call listeners with payload', () => {
105
+ let receivedData: any;
106
+ service.on('data-event', (data) => {
107
+ receivedData = data;
108
+ });
183
109
 
184
- container.register(RegularService, { useClass: RegularService });
110
+ service.emit('data-event', { value: 42 });
185
111
 
186
- // 不应该抛出错误
187
- expect(() => scanner.scanAndRegister([RegularService])).not.toThrow();
188
- });
112
+ expect(receivedData).toEqual({ value: 42 });
113
+ });
189
114
 
190
- test('should handle unregistered listener class gracefully', () => {
191
- @Injectable()
192
- class UnregisteredService {
193
- @OnEvent('test.event')
194
- public handleEvent(): void {}
195
- }
115
+ test('should not throw when no listeners', () => {
116
+ // emit returns void, not boolean
117
+ expect(() => service.emit('no-listeners', null)).not.toThrow();
118
+ });
196
119
 
197
- // 容器会尝试解析未注册的类,这里会自动创建实例(无参数构造函数)
198
- // 所以不会抛出错误,也不会触发警告
199
- expect(() => scanner.scanAndRegister([UnregisteredService])).not.toThrow();
200
- });
201
- });
120
+ test('should call listener when registered', () => {
121
+ let called = false;
122
+ service.on('has-listeners', () => { called = true; });
123
+ service.emit('has-listeners', null);
124
+ expect(called).toBe(true);
125
+ });
202
126
 
203
- describe('EventModule integration', () => {
204
- beforeEach(() => {
205
- Reflect.deleteMetadata(MODULE_METADATA_KEY, EventModule);
206
- });
127
+ test('should call multiple listeners in order', () => {
128
+ const order: number[] = [];
129
+ service.on('ordered', () => order.push(1));
130
+ service.on('ordered', () => order.push(2));
131
+ service.on('ordered', () => order.push(3));
207
132
 
208
- test('should work with initializeListeners via ModuleRegistry', () => {
209
- const handler = mock(() => {});
210
-
211
- @Injectable()
212
- class NotificationService {
213
- @OnEvent('user.created')
214
- public sendWelcomeEmail(payload: { email: string }): void {
215
- handler(payload);
216
- }
217
- }
218
-
219
- // 配置模块
220
- EventModule.forRoot();
221
-
222
- // 模拟模块注册流程
223
- const registry = ModuleRegistry.getInstance();
224
- const rootContainer = new Container();
225
-
226
- // 手动创建 EventModule 的模块引用
227
- const eventModuleContainer = new Container({ parent: rootContainer });
228
- const emitter = new EventEmitterService();
229
- eventModuleContainer.registerInstance(EVENT_EMITTER_TOKEN, emitter);
230
-
231
- // 注册 NotificationService 到同一个容器
232
- eventModuleContainer.register(NotificationService, { implementation: NotificationService });
233
-
234
- // 模拟 ModuleRegistry 的 getModuleRef 返回
235
- const originalGetModuleRef = registry.getModuleRef.bind(registry);
236
- registry.getModuleRef = (moduleClass: any) => {
237
- if (moduleClass === EventModule) {
238
- return {
239
- moduleClass: EventModule,
240
- container: eventModuleContainer,
241
- metadata: { providers: [], exports: [], imports: [], controllers: [] },
242
- controllersRegistered: false,
243
- attachedParents: new Set(),
244
- extensions: [],
245
- middlewares: [],
246
- isGlobal: false,
247
- } as any;
248
- }
249
- return originalGetModuleRef(moduleClass);
250
- };
251
-
252
- // 初始化监听器
253
- EventModule.initializeListeners(eventModuleContainer, [NotificationService]);
254
-
255
- // 发布事件
256
- emitter.emit('user.created', { email: 'test@example.com' });
257
-
258
- expect(handler).toHaveBeenCalledWith({ email: 'test@example.com' });
259
-
260
- // 恢复原始方法
261
- registry.getModuleRef = originalGetModuleRef;
262
- });
133
+ service.emit('ordered', null);
263
134
 
264
- test('should support async event handlers', async () => {
265
- const results: string[] = [];
135
+ expect(order).toEqual([1, 2, 3]);
136
+ });
137
+ });
266
138
 
267
- @Injectable()
268
- class AsyncService {
269
- @OnEvent('async.event', { async: true })
270
- public async handleAsync(payload: string): Promise<void> {
271
- await new Promise((resolve) => setTimeout(resolve, 10));
272
- results.push(payload);
273
- }
274
- }
139
+ describe('off', () => {
140
+ test('should remove specific listener', () => {
141
+ const handler = () => {};
142
+ service.on('removable', handler);
143
+ service.off('removable', handler);
275
144
 
276
- const container = new Container();
277
- const emitter = new EventEmitterService();
278
- container.register(EVENT_EMITTER_TOKEN, { useValue: emitter });
279
- container.register(AsyncService, { useClass: AsyncService });
145
+ expect(service.listenerCount('removable')).toBe(0);
146
+ });
280
147
 
281
- const scanner = new EventListenerScanner(emitter, container);
282
- scanner.scanAndRegister([AsyncService]);
148
+ test('should not affect other listeners', () => {
149
+ const handler1 = () => {};
150
+ const handler2 = () => {};
283
151
 
284
- await emitter.emitAsync('async.event', 'async-payload');
152
+ service.on('event', handler1);
153
+ service.on('event', handler2);
154
+ service.off('event', handler1);
285
155
 
286
- expect(results).toContain('async-payload');
156
+ expect(service.listenerCount('event')).toBe(1);
157
+ });
287
158
  });
288
159
 
289
- test('should handle Symbol events with decorators', () => {
290
- const USER_UPDATED = Symbol('user.updated');
291
- const handler = mock(() => {});
160
+ describe('removeAllListeners', () => {
161
+ test('should remove all listeners for event', () => {
162
+ service.on('event', () => {});
163
+ service.on('event', () => {});
164
+ service.removeAllListeners('event');
292
165
 
293
- @Injectable()
294
- class UserEventService {
295
- @OnEvent(USER_UPDATED)
296
- public handleUserUpdated(payload: unknown): void {
297
- handler(payload);
298
- }
299
- }
166
+ expect(service.listenerCount('event')).toBe(0);
167
+ });
300
168
 
301
- const container = new Container();
302
- const emitter = new EventEmitterService();
303
- container.register(EVENT_EMITTER_TOKEN, { useValue: emitter });
304
- container.register(UserEventService, { useClass: UserEventService });
169
+ test('should remove all listeners when no event specified', () => {
170
+ service.on('event1', () => {});
171
+ service.on('event2', () => {});
172
+ service.removeAllListeners();
305
173
 
306
- const scanner = new EventListenerScanner(emitter, container);
307
- scanner.scanAndRegister([UserEventService]);
174
+ expect(service.listenerCount('event1')).toBe(0);
175
+ expect(service.listenerCount('event2')).toBe(0);
176
+ });
177
+ });
308
178
 
309
- emitter.emit(USER_UPDATED, { userId: '123' });
179
+ describe('eventNames', () => {
180
+ test('should return all event names', () => {
181
+ service.on('event1', () => {});
182
+ service.on('event2', () => {});
183
+ service.on('event3', () => {});
310
184
 
311
- expect(handler).toHaveBeenCalledWith({ userId: '123' });
185
+ const names = service.eventNames();
186
+ expect(names).toContain('event1');
187
+ expect(names).toContain('event2');
188
+ expect(names).toContain('event3');
189
+ });
312
190
  });
313
- });
314
191
 
315
- describe('EventModule with registerListeners', () => {
316
- beforeEach(() => {
317
- Reflect.deleteMetadata(MODULE_METADATA_KEY, EventModule);
318
- ModuleRegistry.getInstance().clear();
319
- });
192
+ describe('getListeners', () => {
193
+ test('should return listeners count via listenerCount', () => {
194
+ const handler1 = () => {};
195
+ const handler2 = () => {};
196
+
197
+ service.on('event', handler1);
198
+ service.on('event', handler2);
320
199
 
321
- test('should collect listeners via registerListeners', () => {
322
- const handler = mock(() => {});
323
-
324
- @Injectable()
325
- class CollectedService {
326
- @OnEvent('collected.event')
327
- public handleEvent(payload: unknown): void {
328
- handler(payload);
329
- }
330
- }
331
-
332
- EventModule.forRoot();
333
- EventModule.registerListeners([CollectedService]);
334
-
335
- // 模拟模块注册流程
336
- const registry = ModuleRegistry.getInstance();
337
- const rootContainer = new Container();
338
-
339
- // 手动创建 EventModule 的模块引用
340
- const eventModuleContainer = new Container({ parent: rootContainer });
341
- const emitter = new EventEmitterService();
342
- eventModuleContainer.registerInstance(EVENT_EMITTER_TOKEN, emitter);
343
- eventModuleContainer.register(CollectedService, { implementation: CollectedService });
344
-
345
- // 模拟 ModuleRegistry 的 getModuleRef 返回
346
- const originalGetModuleRef = registry.getModuleRef.bind(registry);
347
- registry.getModuleRef = (moduleClass: any) => {
348
- if (moduleClass === EventModule) {
349
- return {
350
- moduleClass: EventModule,
351
- container: eventModuleContainer,
352
- metadata: { providers: [], exports: [], imports: [], controllers: [] },
353
- controllersRegistered: false,
354
- attachedParents: new Set(),
355
- extensions: [],
356
- middlewares: [],
357
- isGlobal: false,
358
- } as any;
359
- }
360
- return originalGetModuleRef(moduleClass);
361
- };
362
-
363
- // initializeListeners 会包含通过 registerListeners 注册的类
364
- EventModule.initializeListeners(eventModuleContainer);
365
-
366
- emitter.emit('collected.event', 'test');
367
-
368
- expect(handler).toHaveBeenCalledWith('test');
369
-
370
- // 恢复原始方法
371
- registry.getModuleRef = originalGetModuleRef;
200
+ // Use listenerCount method instead
201
+ expect(service.listenerCount('event')).toBe(2);
202
+ });
372
203
  });
373
204
  });