@flusys/nestjs-notification 7.1.0 → 8.0.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.
Files changed (103) hide show
  1. package/adapters/index.d.ts +1 -1
  2. package/adapters/notification.adapter.d.ts +2 -2
  3. package/config/index.d.ts +3 -3
  4. package/controllers/index.d.ts +1 -1
  5. package/controllers/notification.controller.d.ts +4 -4
  6. package/docs/index.d.ts +1 -1
  7. package/docs/notification-swagger.config.d.ts +2 -2
  8. package/dtos/index.d.ts +1 -1
  9. package/entities/index.d.ts +5 -5
  10. package/entities/notification-with-company.entity.d.ts +1 -1
  11. package/fesm/244.js +816 -0
  12. package/fesm/446.js +939 -0
  13. package/fesm/adapters/index.js +79 -1
  14. package/fesm/config/index.js +84 -3
  15. package/fesm/controllers/index.js +13 -1
  16. package/fesm/docs/index.js +112 -1
  17. package/fesm/dtos/index.js +311 -1
  18. package/fesm/entities/index.js +211 -8
  19. package/fesm/gateways/index.js +286 -1
  20. package/fesm/index.js +467 -10
  21. package/fesm/interfaces/index.js +16 -2
  22. package/fesm/modules/index.js +269 -1
  23. package/fesm/runtime.js +85 -0
  24. package/fesm/services/index.js +357 -4
  25. package/gateways/index.d.ts +1 -1
  26. package/gateways/notification.gateway.d.ts +2 -2
  27. package/index.d.ts +10 -10
  28. package/interfaces/index.d.ts +2 -2
  29. package/interfaces/notification-module.interface.d.ts +3 -3
  30. package/interfaces/notification.interface.d.ts +1 -1
  31. package/modules/index.d.ts +1 -1
  32. package/modules/notification.module.d.ts +2 -2
  33. package/package.json +33 -44
  34. package/services/index.d.ts +4 -4
  35. package/services/notification-config.service.d.ts +3 -3
  36. package/services/notification-datasource.provider.d.ts +3 -3
  37. package/services/notification-helper.service.d.ts +5 -5
  38. package/services/notification.service.d.ts +8 -8
  39. package/cjs/adapters/index.js +0 -18
  40. package/cjs/adapters/notification.adapter.js +0 -62
  41. package/cjs/adapters/notification.adapter.spec.js +0 -73
  42. package/cjs/config/event-actions.js +0 -33
  43. package/cjs/config/index.js +0 -20
  44. package/cjs/config/message-keys.js +0 -19
  45. package/cjs/config/notification.constants.js +0 -11
  46. package/cjs/controllers/index.js +0 -18
  47. package/cjs/controllers/notification.controller.js +0 -299
  48. package/cjs/controllers/notification.controller.spec.js +0 -214
  49. package/cjs/docs/index.js +0 -18
  50. package/cjs/docs/notification-swagger.config.js +0 -97
  51. package/cjs/docs/notification-swagger.config.spec.js +0 -68
  52. package/cjs/dtos/index.js +0 -18
  53. package/cjs/dtos/notification.dto.js +0 -295
  54. package/cjs/entities/index.js +0 -48
  55. package/cjs/entities/index.spec.js +0 -13
  56. package/cjs/entities/notification-with-company.entity.js +0 -57
  57. package/cjs/entities/notification.entity.js +0 -112
  58. package/cjs/gateways/index.js +0 -18
  59. package/cjs/gateways/notification.gateway.js +0 -172
  60. package/cjs/gateways/notification.gateway.spec.js +0 -359
  61. package/cjs/index.js +0 -28
  62. package/cjs/interfaces/index.js +0 -19
  63. package/cjs/interfaces/notification-module.interface.js +0 -4
  64. package/cjs/interfaces/notification.interface.js +0 -4
  65. package/cjs/modules/index.js +0 -18
  66. package/cjs/modules/notification.module.js +0 -139
  67. package/cjs/modules/notification.module.spec.js +0 -152
  68. package/cjs/services/index.js +0 -21
  69. package/cjs/services/notification-config.service.js +0 -69
  70. package/cjs/services/notification-config.service.spec.js +0 -113
  71. package/cjs/services/notification-datasource.provider.js +0 -133
  72. package/cjs/services/notification-datasource.provider.spec.js +0 -136
  73. package/cjs/services/notification-helper.service.js +0 -197
  74. package/cjs/services/notification-helper.service.spec.js +0 -392
  75. package/cjs/services/notification.service.js +0 -281
  76. package/cjs/services/notification.service.spec.js +0 -560
  77. package/fesm/adapters/notification.adapter.js +0 -52
  78. package/fesm/adapters/notification.adapter.spec.js +0 -69
  79. package/fesm/config/event-actions.js +0 -12
  80. package/fesm/config/message-keys.js +0 -9
  81. package/fesm/config/notification.constants.js +0 -1
  82. package/fesm/controllers/notification.controller.js +0 -289
  83. package/fesm/controllers/notification.controller.spec.js +0 -210
  84. package/fesm/docs/notification-swagger.config.js +0 -87
  85. package/fesm/docs/notification-swagger.config.spec.js +0 -64
  86. package/fesm/dtos/notification.dto.js +0 -262
  87. package/fesm/entities/index.spec.js +0 -9
  88. package/fesm/entities/notification-with-company.entity.js +0 -47
  89. package/fesm/entities/notification.entity.js +0 -102
  90. package/fesm/gateways/notification.gateway.js +0 -162
  91. package/fesm/gateways/notification.gateway.spec.js +0 -355
  92. package/fesm/interfaces/notification-module.interface.js +0 -1
  93. package/fesm/interfaces/notification.interface.js +0 -1
  94. package/fesm/modules/notification.module.js +0 -129
  95. package/fesm/modules/notification.module.spec.js +0 -148
  96. package/fesm/services/notification-config.service.js +0 -59
  97. package/fesm/services/notification-config.service.spec.js +0 -109
  98. package/fesm/services/notification-datasource.provider.js +0 -82
  99. package/fesm/services/notification-datasource.provider.spec.js +0 -132
  100. package/fesm/services/notification-helper.service.js +0 -187
  101. package/fesm/services/notification-helper.service.spec.js +0 -388
  102. package/fesm/services/notification.service.js +0 -271
  103. package/fesm/services/notification.service.spec.js +0 -556
@@ -1,355 +0,0 @@
1
- import { NotificationGateway } from './notification.gateway';
2
- function createMockServer() {
3
- const room = {
4
- emit: jest.fn()
5
- };
6
- return {
7
- to: jest.fn().mockReturnValue(room),
8
- emit: jest.fn()
9
- };
10
- }
11
- function createMockSocket(overrides = {}) {
12
- return {
13
- id: 'socket-id-1',
14
- handshake: {
15
- auth: {},
16
- query: {},
17
- headers: {}
18
- },
19
- data: {},
20
- join: jest.fn(),
21
- disconnect: jest.fn(),
22
- ...overrides
23
- };
24
- }
25
- describe('NotificationGateway', ()=>{
26
- let gateway;
27
- let mockConfigService;
28
- let mockJwtService;
29
- let mockServer;
30
- beforeEach(()=>{
31
- mockConfigService = {
32
- getJwtSecret: jest.fn().mockReturnValue('jwt-secret')
33
- };
34
- mockJwtService = {
35
- verify: jest.fn()
36
- };
37
- gateway = new NotificationGateway(mockConfigService, mockJwtService);
38
- mockServer = createMockServer();
39
- gateway.server = mockServer;
40
- });
41
- describe('afterInit', ()=>{
42
- it('does not throw', ()=>{
43
- expect(()=>gateway.afterInit()).not.toThrow();
44
- });
45
- });
46
- describe('handleConnection', ()=>{
47
- it('disconnects the client when no token is present anywhere', async ()=>{
48
- const client = createMockSocket();
49
- await gateway.handleConnection(client);
50
- expect(client.disconnect).toHaveBeenCalled();
51
- expect(mockJwtService.verify).not.toHaveBeenCalled();
52
- });
53
- it('accepts a token from handshake.auth and joins the user + company rooms', async ()=>{
54
- const client = createMockSocket({
55
- handshake: {
56
- auth: {
57
- token: 'auth-token'
58
- },
59
- query: {},
60
- headers: {}
61
- }
62
- });
63
- mockJwtService.verify.mockReturnValue({
64
- id: 'user-1',
65
- companyId: 'company-1'
66
- });
67
- await gateway.handleConnection(client);
68
- expect(mockJwtService.verify).toHaveBeenCalledWith('auth-token', {
69
- secret: 'jwt-secret',
70
- algorithms: [
71
- 'HS256'
72
- ]
73
- });
74
- expect(client.data.userId).toBe('user-1');
75
- expect(client.data.companyId).toBe('company-1');
76
- expect(client.join).toHaveBeenCalledWith('user:user-1');
77
- expect(client.join).toHaveBeenCalledWith('company:company-1');
78
- expect(client.join).toHaveBeenCalledWith('user:user-1:company:company-1');
79
- expect(client.disconnect).not.toHaveBeenCalled();
80
- expect(gateway.isUserOnline('user-1')).toBe(true);
81
- });
82
- it('accepts a token from the query string', async ()=>{
83
- const client = createMockSocket({
84
- handshake: {
85
- auth: {},
86
- query: {
87
- token: 'query-token'
88
- },
89
- headers: {}
90
- }
91
- });
92
- mockJwtService.verify.mockReturnValue({
93
- id: 'user-2'
94
- });
95
- await gateway.handleConnection(client);
96
- expect(mockJwtService.verify).toHaveBeenCalledWith('query-token', expect.any(Object));
97
- expect(client.join).toHaveBeenCalledWith('user:user-2');
98
- });
99
- it('accepts a token from the Authorization header', async ()=>{
100
- const client = createMockSocket({
101
- handshake: {
102
- auth: {},
103
- query: {},
104
- headers: {
105
- authorization: 'Bearer header-token'
106
- }
107
- }
108
- });
109
- mockJwtService.verify.mockReturnValue({
110
- id: 'user-3'
111
- });
112
- await gateway.handleConnection(client);
113
- expect(mockJwtService.verify).toHaveBeenCalledWith('header-token', expect.any(Object));
114
- expect(client.join).toHaveBeenCalledWith('user:user-3');
115
- });
116
- it('ignores a malformed Authorization header without the Bearer prefix', async ()=>{
117
- const client = createMockSocket({
118
- handshake: {
119
- auth: {},
120
- query: {},
121
- headers: {
122
- authorization: 'Basic abc123'
123
- }
124
- }
125
- });
126
- await gateway.handleConnection(client);
127
- expect(client.disconnect).toHaveBeenCalled();
128
- expect(mockJwtService.verify).not.toHaveBeenCalled();
129
- });
130
- it('joins only the personal room when the token payload has no companyId', async ()=>{
131
- const client = createMockSocket({
132
- handshake: {
133
- auth: {
134
- token: 't'
135
- },
136
- query: {},
137
- headers: {}
138
- }
139
- });
140
- mockJwtService.verify.mockReturnValue({
141
- id: 'user-4'
142
- });
143
- await gateway.handleConnection(client);
144
- expect(client.join).toHaveBeenCalledWith('user:user-4');
145
- expect(client.join).toHaveBeenCalledTimes(1);
146
- });
147
- it('disconnects the client when the JWT secret is not configured', async ()=>{
148
- mockConfigService.getJwtSecret.mockReturnValue(undefined);
149
- const client = createMockSocket({
150
- handshake: {
151
- auth: {
152
- token: 't'
153
- },
154
- query: {},
155
- headers: {}
156
- }
157
- });
158
- await gateway.handleConnection(client);
159
- expect(client.disconnect).toHaveBeenCalled();
160
- expect(mockJwtService.verify).not.toHaveBeenCalled();
161
- });
162
- it('disconnects the client when token verification throws (invalid/expired token)', async ()=>{
163
- const client = createMockSocket({
164
- handshake: {
165
- auth: {
166
- token: 'bad-token'
167
- },
168
- query: {},
169
- headers: {}
170
- }
171
- });
172
- mockJwtService.verify.mockImplementation(()=>{
173
- throw new Error('jwt expired');
174
- });
175
- await gateway.handleConnection(client);
176
- expect(client.disconnect).toHaveBeenCalled();
177
- expect(gateway.isUserOnline('user-1')).toBe(false);
178
- });
179
- it('tracks multiple sockets for the same user', async ()=>{
180
- mockJwtService.verify.mockReturnValue({
181
- id: 'user-5'
182
- });
183
- const clientA = createMockSocket({
184
- id: 'socket-a',
185
- handshake: {
186
- auth: {
187
- token: 't'
188
- },
189
- query: {},
190
- headers: {}
191
- }
192
- });
193
- const clientB = createMockSocket({
194
- id: 'socket-b',
195
- handshake: {
196
- auth: {
197
- token: 't'
198
- },
199
- query: {},
200
- headers: {}
201
- }
202
- });
203
- await gateway.handleConnection(clientA);
204
- await gateway.handleConnection(clientB);
205
- expect(gateway.isUserOnline('user-5')).toBe(true);
206
- expect(gateway.getOnlineUserCount()).toBe(1);
207
- });
208
- it('disconnects the client when an unexpected error occurs during connection handling', async ()=>{
209
- const client = createMockSocket({
210
- handshake: {
211
- auth: {
212
- token: 't'
213
- },
214
- query: {},
215
- headers: {}
216
- }
217
- });
218
- mockJwtService.verify.mockReturnValue({
219
- id: 'user-6'
220
- });
221
- client.join = jest.fn().mockImplementation(()=>{
222
- throw new Error('join failed');
223
- });
224
- await gateway.handleConnection(client);
225
- expect(client.disconnect).toHaveBeenCalled();
226
- });
227
- });
228
- describe('handleDisconnect', ()=>{
229
- it('removes the socket and marks the user offline when it was their only connection', async ()=>{
230
- mockJwtService.verify.mockReturnValue({
231
- id: 'user-1'
232
- });
233
- const client = createMockSocket({
234
- handshake: {
235
- auth: {
236
- token: 't'
237
- },
238
- query: {},
239
- headers: {}
240
- }
241
- });
242
- await gateway.handleConnection(client);
243
- expect(gateway.isUserOnline('user-1')).toBe(true);
244
- gateway.handleDisconnect(client);
245
- expect(gateway.isUserOnline('user-1')).toBe(false);
246
- expect(gateway.getOnlineUserCount()).toBe(0);
247
- });
248
- it('keeps the user online when they still have another connected socket', async ()=>{
249
- mockJwtService.verify.mockReturnValue({
250
- id: 'user-1'
251
- });
252
- const clientA = createMockSocket({
253
- id: 'socket-a',
254
- handshake: {
255
- auth: {
256
- token: 't'
257
- },
258
- query: {},
259
- headers: {}
260
- }
261
- });
262
- const clientB = createMockSocket({
263
- id: 'socket-b',
264
- handshake: {
265
- auth: {
266
- token: 't'
267
- },
268
- query: {},
269
- headers: {}
270
- }
271
- });
272
- await gateway.handleConnection(clientA);
273
- await gateway.handleConnection(clientB);
274
- gateway.handleDisconnect(clientA);
275
- expect(gateway.isUserOnline('user-1')).toBe(true);
276
- });
277
- it('does nothing when the client never authenticated (no userId on socket data)', ()=>{
278
- const client = createMockSocket();
279
- expect(()=>gateway.handleDisconnect(client)).not.toThrow();
280
- expect(gateway.getOnlineUserCount()).toBe(0);
281
- });
282
- it('is a no-op when disconnecting an unknown user id', ()=>{
283
- const client = createMockSocket({
284
- data: {
285
- userId: 'ghost-user'
286
- }
287
- });
288
- expect(()=>gateway.handleDisconnect(client)).not.toThrow();
289
- expect(gateway.isUserOnline('ghost-user')).toBe(false);
290
- });
291
- });
292
- describe('emitToUser', ()=>{
293
- it('emits the event to the user-scoped room', ()=>{
294
- gateway.emitToUser('user-1', 'notification:new', {
295
- title: 'hi'
296
- });
297
- expect(mockServer.to).toHaveBeenCalledWith('user:user-1');
298
- expect(mockServer.to('user:user-1').emit).toHaveBeenCalledWith('notification:new', {
299
- title: 'hi'
300
- });
301
- });
302
- it('does not throw when the server has not been initialized yet', ()=>{
303
- const freshGateway = new NotificationGateway(mockConfigService, mockJwtService);
304
- expect(()=>freshGateway.emitToUser('user-1', 'notification:new', {})).not.toThrow();
305
- });
306
- });
307
- describe('emitToUserInCompany', ()=>{
308
- it('emits to the combined user+company room when companyId is provided', ()=>{
309
- gateway.emitToUserInCompany('user-1', 'company-1', 'notification:new', {
310
- a: 1
311
- });
312
- expect(mockServer.to).toHaveBeenCalledWith('user:user-1:company:company-1');
313
- });
314
- it('falls back to emitToUser when companyId is null', ()=>{
315
- gateway.emitToUserInCompany('user-1', null, 'notification:new', {
316
- a: 1
317
- });
318
- expect(mockServer.to).toHaveBeenCalledWith('user:user-1');
319
- });
320
- it('falls back to emitToUser when companyId is undefined', ()=>{
321
- gateway.emitToUserInCompany('user-1', undefined, 'notification:new', {
322
- a: 1
323
- });
324
- expect(mockServer.to).toHaveBeenCalledWith('user:user-1');
325
- });
326
- it('does not throw when the server has not been initialized yet', ()=>{
327
- const freshGateway = new NotificationGateway(mockConfigService, mockJwtService);
328
- expect(()=>freshGateway.emitToUserInCompany('user-1', 'company-1', 'notification:new', {})).not.toThrow();
329
- });
330
- });
331
- describe('emitToCompany', ()=>{
332
- it('emits the event to the company-scoped room', ()=>{
333
- gateway.emitToCompany('company-1', 'notification:new', {
334
- b: 2
335
- });
336
- expect(mockServer.to).toHaveBeenCalledWith('company:company-1');
337
- });
338
- });
339
- describe('broadcast', ()=>{
340
- it('emits the event to all connected sockets', ()=>{
341
- gateway.broadcast('server:announcement', {
342
- text: 'hi all'
343
- });
344
- expect(mockServer.emit).toHaveBeenCalledWith('server:announcement', {
345
- text: 'hi all'
346
- });
347
- });
348
- });
349
- describe('isUserOnline / getOnlineUserCount', ()=>{
350
- it('reports zero online users when nobody has connected', ()=>{
351
- expect(gateway.isUserOnline('nobody')).toBe(false);
352
- expect(gateway.getOnlineUserCount()).toBe(0);
353
- });
354
- });
355
- });
@@ -1 +0,0 @@
1
- export { };
@@ -1 +0,0 @@
1
- export { };
@@ -1,129 +0,0 @@
1
- function _ts_decorate(decorators, target, key, desc) {
2
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
- else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
- return c > 3 && r && Object.defineProperty(target, key, r), r;
6
- }
7
- import { CacheModule, UtilsModule, createModuleEventsProvider } from '@flusys/nestjs-shared/modules';
8
- import { NOTIFICATION_ADAPTER } from '@flusys/nestjs-shared/interfaces';
9
- import { Module } from '@nestjs/common';
10
- import { JwtService } from '@nestjs/jwt';
11
- import { NOTIFICATION_MODULE_OPTIONS } from '../config/notification.constants';
12
- import { NotificationController } from '../controllers';
13
- import { NotificationAdapter } from '../adapters';
14
- import { NotificationConfigService, NotificationDataSourceProvider, NotificationService, NotificationHelperService } from '../services';
15
- import { NotificationGateway } from '../gateways';
16
- const CONTROLLERS = [
17
- NotificationController
18
- ];
19
- const EXPORTED_SERVICES = [
20
- NotificationConfigService,
21
- NotificationDataSourceProvider,
22
- NotificationService,
23
- NotificationHelperService
24
- ];
25
- const ADAPTER_PROVIDER = {
26
- provide: NOTIFICATION_ADAPTER,
27
- useClass: NotificationAdapter
28
- };
29
- export class NotificationModule {
30
- static forRoot(options) {
31
- return {
32
- module: NotificationModule,
33
- global: options.global ?? false,
34
- imports: [
35
- CacheModule,
36
- UtilsModule
37
- ],
38
- controllers: options.includeController !== false ? CONTROLLERS : [],
39
- providers: [
40
- ...this.buildProviders(options),
41
- JwtService,
42
- NotificationGateway,
43
- NotificationAdapter,
44
- ADAPTER_PROVIDER
45
- ],
46
- exports: [
47
- ...EXPORTED_SERVICES,
48
- NotificationGateway,
49
- NOTIFICATION_ADAPTER
50
- ]
51
- };
52
- }
53
- static forRootAsync(options) {
54
- return {
55
- module: NotificationModule,
56
- global: options.global ?? false,
57
- imports: [
58
- ...options.imports || [],
59
- CacheModule,
60
- UtilsModule
61
- ],
62
- controllers: options.includeController !== false ? CONTROLLERS : [],
63
- providers: [
64
- ...this.createAsyncProviders(options),
65
- ...this.buildProviders(),
66
- JwtService,
67
- NotificationGateway,
68
- NotificationAdapter,
69
- ADAPTER_PROVIDER
70
- ],
71
- exports: [
72
- ...EXPORTED_SERVICES,
73
- NotificationGateway,
74
- NOTIFICATION_ADAPTER
75
- ]
76
- };
77
- }
78
- static buildProviders(options) {
79
- const providers = [
80
- ...EXPORTED_SERVICES
81
- ];
82
- if (options) {
83
- providers.unshift({
84
- provide: NOTIFICATION_MODULE_OPTIONS,
85
- useValue: options
86
- });
87
- }
88
- providers.push(createModuleEventsProvider('notification', NOTIFICATION_MODULE_OPTIONS));
89
- return providers;
90
- }
91
- static createAsyncProviders(options) {
92
- if (options.useFactory) {
93
- return [
94
- {
95
- provide: NOTIFICATION_MODULE_OPTIONS,
96
- useFactory: async (...args)=>({
97
- ...options,
98
- config: await options.useFactory(...args)
99
- }),
100
- inject: options.inject || []
101
- }
102
- ];
103
- }
104
- const factoryClass = options.useClass || options.useExisting;
105
- if (!factoryClass) return [];
106
- const providers = [
107
- {
108
- provide: NOTIFICATION_MODULE_OPTIONS,
109
- useFactory: async (factory)=>({
110
- ...options,
111
- config: await factory.createNotificationOptions()
112
- }),
113
- inject: [
114
- factoryClass
115
- ]
116
- }
117
- ];
118
- if (options.useClass) {
119
- providers.push({
120
- provide: options.useClass,
121
- useClass: options.useClass
122
- });
123
- }
124
- return providers;
125
- }
126
- }
127
- NotificationModule = _ts_decorate([
128
- Module({})
129
- ], NotificationModule);
@@ -1,148 +0,0 @@
1
- function _define_property(obj, key, value) {
2
- if (key in obj) {
3
- Object.defineProperty(obj, key, {
4
- value: value,
5
- enumerable: true,
6
- configurable: true,
7
- writable: true
8
- });
9
- } else {
10
- obj[key] = value;
11
- }
12
- return obj;
13
- }
14
- import { NOTIFICATION_ADAPTER } from '@flusys/nestjs-shared/interfaces';
15
- import { NotificationModule } from './notification.module';
16
- import { NOTIFICATION_MODULE_OPTIONS } from '../config/notification.constants';
17
- import { NotificationController } from '../controllers';
18
- import { NotificationGateway } from '../gateways';
19
- import { NotificationAdapter } from '../adapters';
20
- function providerTokens(providers) {
21
- return providers.map((p)=>typeof p === 'function' ? p : p.provide);
22
- }
23
- describe('NotificationModule', ()=>{
24
- describe('forRoot', ()=>{
25
- it('should default to a non-global module with the notification controller registered', ()=>{
26
- const dynamicModule = NotificationModule.forRoot({});
27
- expect(dynamicModule.module).toBe(NotificationModule);
28
- expect(dynamicModule.global).toBe(false);
29
- expect(dynamicModule.controllers).toEqual([
30
- NotificationController
31
- ]);
32
- });
33
- it('should respect global: true', ()=>{
34
- expect(NotificationModule.forRoot({
35
- global: true
36
- }).global).toBe(true);
37
- });
38
- it('should register no controllers when includeController is false', ()=>{
39
- expect(NotificationModule.forRoot({
40
- includeController: false
41
- }).controllers).toEqual([]);
42
- });
43
- it('should register the NOTIFICATION_ADAPTER provider backed by NotificationAdapter', ()=>{
44
- const dynamicModule = NotificationModule.forRoot({});
45
- const adapterProvider = dynamicModule.providers.find((p)=>p.provide === NOTIFICATION_ADAPTER);
46
- expect(adapterProvider.useClass).toBe(NotificationAdapter);
47
- expect(providerTokens(dynamicModule.providers)).toContain(NotificationGateway);
48
- });
49
- it('should export NotificationGateway and NOTIFICATION_ADAPTER alongside the base services', ()=>{
50
- const dynamicModule = NotificationModule.forRoot({});
51
- expect(dynamicModule.exports).toEqual(expect.arrayContaining([
52
- NotificationGateway,
53
- NOTIFICATION_ADAPTER
54
- ]));
55
- });
56
- it('should register a NOTIFICATION_MODULE_OPTIONS provider carrying the given options', ()=>{
57
- const options = {
58
- bootstrapAppConfig: {
59
- enableCompanyFeature: true
60
- }
61
- };
62
- const dynamicModule = NotificationModule.forRoot(options);
63
- const provider = dynamicModule.providers.find((p)=>p.provide === NOTIFICATION_MODULE_OPTIONS);
64
- expect(provider.useValue).toBe(options);
65
- });
66
- });
67
- describe('forRootAsync', ()=>{
68
- it('should forward external imports alongside CacheModule/UtilsModule', ()=>{
69
- let FakeImportedModule = class FakeImportedModule {
70
- };
71
- const dynamicModule = NotificationModule.forRootAsync({
72
- imports: [
73
- FakeImportedModule
74
- ]
75
- });
76
- expect(dynamicModule.imports).toEqual(expect.arrayContaining([
77
- FakeImportedModule
78
- ]));
79
- });
80
- it('should still wire the adapter/gateway providers when using async registration', ()=>{
81
- const dynamicModule = NotificationModule.forRootAsync({
82
- useFactory: jest.fn()
83
- });
84
- const adapterProvider = dynamicModule.providers.find((p)=>p.provide === NOTIFICATION_ADAPTER);
85
- expect(adapterProvider.useClass).toBe(NotificationAdapter);
86
- });
87
- it('useFactory: builds a NOTIFICATION_MODULE_OPTIONS provider merging resolved config', async ()=>{
88
- const useFactory = jest.fn().mockResolvedValue({
89
- foo: 'bar'
90
- });
91
- const dynamicModule = NotificationModule.forRootAsync({
92
- useFactory,
93
- inject: [
94
- 'SOME_TOKEN'
95
- ]
96
- });
97
- const provider = dynamicModule.providers.find((p)=>p.provide === NOTIFICATION_MODULE_OPTIONS);
98
- expect(provider.inject).toEqual([
99
- 'SOME_TOKEN'
100
- ]);
101
- const resolved = await provider.useFactory('injected');
102
- expect(useFactory).toHaveBeenCalledWith('injected');
103
- expect(resolved.config).toEqual({
104
- foo: 'bar'
105
- });
106
- });
107
- it('useClass: registers both the class provider and an options provider calling createNotificationOptions()', async ()=>{
108
- let MyOptionsFactory = class MyOptionsFactory {
109
- constructor(){
110
- _define_property(this, "createNotificationOptions", jest.fn().mockResolvedValue({
111
- foo: 'from-class'
112
- }));
113
- }
114
- };
115
- const dynamicModule = NotificationModule.forRootAsync({
116
- useClass: MyOptionsFactory
117
- });
118
- const classProvider = dynamicModule.providers.find((p)=>p.provide === MyOptionsFactory);
119
- expect(classProvider.useClass).toBe(MyOptionsFactory);
120
- const optionsProvider = dynamicModule.providers.find((p)=>p.provide === NOTIFICATION_MODULE_OPTIONS);
121
- const instance = new MyOptionsFactory();
122
- const resolved = await optionsProvider.useFactory(instance);
123
- expect(instance.createNotificationOptions).toHaveBeenCalled();
124
- expect(resolved.config).toEqual({
125
- foo: 'from-class'
126
- });
127
- });
128
- it('useExisting: registers a single options provider without a duplicate class registration', ()=>{
129
- let MyOptionsFactory = class MyOptionsFactory {
130
- constructor(){
131
- _define_property(this, "createNotificationOptions", jest.fn());
132
- }
133
- };
134
- const dynamicModule = NotificationModule.forRootAsync({
135
- useExisting: MyOptionsFactory
136
- });
137
- expect(dynamicModule.providers.filter((p)=>p.provide === MyOptionsFactory)).toHaveLength(0);
138
- const optionsProvider = dynamicModule.providers.find((p)=>p.provide === NOTIFICATION_MODULE_OPTIONS);
139
- expect(optionsProvider.inject).toEqual([
140
- MyOptionsFactory
141
- ]);
142
- });
143
- it('should register no NOTIFICATION_MODULE_OPTIONS provider when neither useFactory, useClass, nor useExisting is given', ()=>{
144
- const dynamicModule = NotificationModule.forRootAsync({});
145
- expect(providerTokens(dynamicModule.providers)).not.toContain(NOTIFICATION_MODULE_OPTIONS);
146
- });
147
- });
148
- });