@hazeljs/core 0.2.0-beta.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.
- package/README.md +522 -0
- package/dist/__tests__/container.test.d.ts +2 -0
- package/dist/__tests__/container.test.d.ts.map +1 -0
- package/dist/__tests__/container.test.js +454 -0
- package/dist/__tests__/decorators.test.d.ts +2 -0
- package/dist/__tests__/decorators.test.d.ts.map +1 -0
- package/dist/__tests__/decorators.test.js +693 -0
- package/dist/__tests__/errors/http.error.test.d.ts +2 -0
- package/dist/__tests__/errors/http.error.test.d.ts.map +1 -0
- package/dist/__tests__/errors/http.error.test.js +117 -0
- package/dist/__tests__/filters/exception-filter.test.d.ts +2 -0
- package/dist/__tests__/filters/exception-filter.test.d.ts.map +1 -0
- package/dist/__tests__/filters/exception-filter.test.js +135 -0
- package/dist/__tests__/filters/http-exception.filter.test.d.ts +2 -0
- package/dist/__tests__/filters/http-exception.filter.test.d.ts.map +1 -0
- package/dist/__tests__/filters/http-exception.filter.test.js +119 -0
- package/dist/__tests__/hazel-app.test.d.ts +2 -0
- package/dist/__tests__/hazel-app.test.d.ts.map +1 -0
- package/dist/__tests__/hazel-app.test.js +682 -0
- package/dist/__tests__/hazel-module.test.d.ts +2 -0
- package/dist/__tests__/hazel-module.test.d.ts.map +1 -0
- package/dist/__tests__/hazel-module.test.js +408 -0
- package/dist/__tests__/hazel-response.test.d.ts +2 -0
- package/dist/__tests__/hazel-response.test.d.ts.map +1 -0
- package/dist/__tests__/hazel-response.test.js +138 -0
- package/dist/__tests__/health.test.d.ts +2 -0
- package/dist/__tests__/health.test.d.ts.map +1 -0
- package/dist/__tests__/health.test.js +147 -0
- package/dist/__tests__/index.test.d.ts +2 -0
- package/dist/__tests__/index.test.d.ts.map +1 -0
- package/dist/__tests__/index.test.js +239 -0
- package/dist/__tests__/interceptors/interceptor.test.d.ts +2 -0
- package/dist/__tests__/interceptors/interceptor.test.d.ts.map +1 -0
- package/dist/__tests__/interceptors/interceptor.test.js +166 -0
- package/dist/__tests__/logger.test.d.ts +2 -0
- package/dist/__tests__/logger.test.d.ts.map +1 -0
- package/dist/__tests__/logger.test.js +141 -0
- package/dist/__tests__/middleware/cors.test.d.ts +2 -0
- package/dist/__tests__/middleware/cors.test.d.ts.map +1 -0
- package/dist/__tests__/middleware/cors.test.js +129 -0
- package/dist/__tests__/middleware/csrf.test.d.ts +2 -0
- package/dist/__tests__/middleware/csrf.test.d.ts.map +1 -0
- package/dist/__tests__/middleware/csrf.test.js +247 -0
- package/dist/__tests__/middleware/global-middleware.test.d.ts +2 -0
- package/dist/__tests__/middleware/global-middleware.test.d.ts.map +1 -0
- package/dist/__tests__/middleware/global-middleware.test.js +259 -0
- package/dist/__tests__/middleware/rate-limit.test.d.ts +2 -0
- package/dist/__tests__/middleware/rate-limit.test.d.ts.map +1 -0
- package/dist/__tests__/middleware/rate-limit.test.js +264 -0
- package/dist/__tests__/middleware/security-headers.test.d.ts +2 -0
- package/dist/__tests__/middleware/security-headers.test.d.ts.map +1 -0
- package/dist/__tests__/middleware/security-headers.test.js +229 -0
- package/dist/__tests__/middleware/timeout.test.d.ts +2 -0
- package/dist/__tests__/middleware/timeout.test.d.ts.map +1 -0
- package/dist/__tests__/middleware/timeout.test.js +132 -0
- package/dist/__tests__/middleware.test.d.ts +2 -0
- package/dist/__tests__/middleware.test.d.ts.map +1 -0
- package/dist/__tests__/middleware.test.js +180 -0
- package/dist/__tests__/pipes/pipe.test.d.ts +2 -0
- package/dist/__tests__/pipes/pipe.test.d.ts.map +1 -0
- package/dist/__tests__/pipes/pipe.test.js +245 -0
- package/dist/__tests__/pipes/validation.pipe.test.d.ts +2 -0
- package/dist/__tests__/pipes/validation.pipe.test.d.ts.map +1 -0
- package/dist/__tests__/pipes/validation.pipe.test.js +297 -0
- package/dist/__tests__/request-parser.test.d.ts +2 -0
- package/dist/__tests__/request-parser.test.d.ts.map +1 -0
- package/dist/__tests__/request-parser.test.js +182 -0
- package/dist/__tests__/router.test.d.ts +2 -0
- package/dist/__tests__/router.test.d.ts.map +1 -0
- package/dist/__tests__/router.test.js +680 -0
- package/dist/__tests__/routing/route-matcher.test.d.ts +2 -0
- package/dist/__tests__/routing/route-matcher.test.d.ts.map +1 -0
- package/dist/__tests__/routing/route-matcher.test.js +219 -0
- package/dist/__tests__/routing/version.decorator.test.d.ts +2 -0
- package/dist/__tests__/routing/version.decorator.test.d.ts.map +1 -0
- package/dist/__tests__/routing/version.decorator.test.js +298 -0
- package/dist/__tests__/service.test.d.ts +2 -0
- package/dist/__tests__/service.test.d.ts.map +1 -0
- package/dist/__tests__/service.test.js +121 -0
- package/dist/__tests__/shutdown.test.d.ts +2 -0
- package/dist/__tests__/shutdown.test.d.ts.map +1 -0
- package/dist/__tests__/shutdown.test.js +250 -0
- package/dist/__tests__/testing/testing.module.test.d.ts +2 -0
- package/dist/__tests__/testing/testing.module.test.d.ts.map +1 -0
- package/dist/__tests__/testing/testing.module.test.js +370 -0
- package/dist/__tests__/upload/file-upload.test.d.ts +2 -0
- package/dist/__tests__/upload/file-upload.test.d.ts.map +1 -0
- package/dist/__tests__/upload/file-upload.test.js +498 -0
- package/dist/__tests__/utils/sanitize.test.d.ts +2 -0
- package/dist/__tests__/utils/sanitize.test.d.ts.map +1 -0
- package/dist/__tests__/utils/sanitize.test.js +291 -0
- package/dist/__tests__/validator.test.d.ts +2 -0
- package/dist/__tests__/validator.test.d.ts.map +1 -0
- package/dist/__tests__/validator.test.js +300 -0
- package/dist/container.d.ts +80 -0
- package/dist/container.d.ts.map +1 -0
- package/dist/container.js +271 -0
- package/dist/decorators.d.ts +92 -0
- package/dist/decorators.d.ts.map +1 -0
- package/dist/decorators.js +343 -0
- package/dist/errors/http.error.d.ts +31 -0
- package/dist/errors/http.error.d.ts.map +1 -0
- package/dist/errors/http.error.js +62 -0
- package/dist/filters/exception-filter.d.ts +39 -0
- package/dist/filters/exception-filter.d.ts.map +1 -0
- package/dist/filters/exception-filter.js +38 -0
- package/dist/filters/http-exception.filter.d.ts +9 -0
- package/dist/filters/http-exception.filter.d.ts.map +1 -0
- package/dist/filters/http-exception.filter.js +42 -0
- package/dist/hazel-app.d.ts +78 -0
- package/dist/hazel-app.d.ts.map +1 -0
- package/dist/hazel-app.js +453 -0
- package/dist/hazel-module.d.ts +20 -0
- package/dist/hazel-module.d.ts.map +1 -0
- package/dist/hazel-module.js +109 -0
- package/dist/hazel-response.d.ts +20 -0
- package/dist/hazel-response.d.ts.map +1 -0
- package/dist/hazel-response.js +68 -0
- package/dist/health.d.ts +73 -0
- package/dist/health.d.ts.map +1 -0
- package/dist/health.js +174 -0
- package/dist/index.d.ts +41 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +140 -0
- package/dist/interceptors/interceptor.d.ts +22 -0
- package/dist/interceptors/interceptor.d.ts.map +1 -0
- package/dist/interceptors/interceptor.js +46 -0
- package/dist/logger.d.ts +8 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +238 -0
- package/dist/middleware/cors.middleware.d.ts +44 -0
- package/dist/middleware/cors.middleware.d.ts.map +1 -0
- package/dist/middleware/cors.middleware.js +118 -0
- package/dist/middleware/csrf.middleware.d.ts +82 -0
- package/dist/middleware/csrf.middleware.d.ts.map +1 -0
- package/dist/middleware/csrf.middleware.js +183 -0
- package/dist/middleware/global-middleware.d.ts +111 -0
- package/dist/middleware/global-middleware.d.ts.map +1 -0
- package/dist/middleware/global-middleware.js +179 -0
- package/dist/middleware/rate-limit.middleware.d.ts +73 -0
- package/dist/middleware/rate-limit.middleware.d.ts.map +1 -0
- package/dist/middleware/rate-limit.middleware.js +124 -0
- package/dist/middleware/security-headers.middleware.d.ts +76 -0
- package/dist/middleware/security-headers.middleware.d.ts.map +1 -0
- package/dist/middleware/security-headers.middleware.js +123 -0
- package/dist/middleware/timeout.middleware.d.ts +25 -0
- package/dist/middleware/timeout.middleware.d.ts.map +1 -0
- package/dist/middleware/timeout.middleware.js +74 -0
- package/dist/middleware.d.ts +13 -0
- package/dist/middleware.d.ts.map +1 -0
- package/dist/middleware.js +47 -0
- package/dist/pipes/pipe.d.ts +50 -0
- package/dist/pipes/pipe.d.ts.map +1 -0
- package/dist/pipes/pipe.js +96 -0
- package/dist/pipes/validation.pipe.d.ts +6 -0
- package/dist/pipes/validation.pipe.d.ts.map +1 -0
- package/dist/pipes/validation.pipe.js +61 -0
- package/dist/request-context.d.ts +17 -0
- package/dist/request-context.d.ts.map +1 -0
- package/dist/request-context.js +2 -0
- package/dist/request-parser.d.ts +7 -0
- package/dist/request-parser.d.ts.map +1 -0
- package/dist/request-parser.js +60 -0
- package/dist/router.d.ts +33 -0
- package/dist/router.d.ts.map +1 -0
- package/dist/router.js +426 -0
- package/dist/routing/route-matcher.d.ts +39 -0
- package/dist/routing/route-matcher.d.ts.map +1 -0
- package/dist/routing/route-matcher.js +93 -0
- package/dist/routing/version.decorator.d.ts +36 -0
- package/dist/routing/version.decorator.d.ts.map +1 -0
- package/dist/routing/version.decorator.js +89 -0
- package/dist/service.d.ts +9 -0
- package/dist/service.d.ts.map +1 -0
- package/dist/service.js +39 -0
- package/dist/shutdown.d.ts +32 -0
- package/dist/shutdown.d.ts.map +1 -0
- package/dist/shutdown.js +109 -0
- package/dist/testing/testing.module.d.ts +83 -0
- package/dist/testing/testing.module.d.ts.map +1 -0
- package/dist/testing/testing.module.js +164 -0
- package/dist/types.d.ts +76 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/upload/file-upload.d.ts +75 -0
- package/dist/upload/file-upload.d.ts.map +1 -0
- package/dist/upload/file-upload.js +261 -0
- package/dist/utils/sanitize.d.ts +45 -0
- package/dist/utils/sanitize.d.ts.map +1 -0
- package/dist/utils/sanitize.js +165 -0
- package/dist/validator.d.ts +7 -0
- package/dist/validator.d.ts.map +1 -0
- package/dist/validator.js +119 -0
- package/package.json +65 -0
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const shutdown_1 = require("../shutdown");
|
|
4
|
+
describe('ShutdownManager', () => {
|
|
5
|
+
let shutdownManager;
|
|
6
|
+
let processExitSpy;
|
|
7
|
+
beforeEach(() => {
|
|
8
|
+
shutdownManager = new shutdown_1.ShutdownManager(5000);
|
|
9
|
+
// Mock process.exit to prevent tests from terminating
|
|
10
|
+
processExitSpy = jest.spyOn(process, 'exit').mockImplementation((() => { }));
|
|
11
|
+
});
|
|
12
|
+
afterEach(() => {
|
|
13
|
+
// Clean up any handlers
|
|
14
|
+
jest.clearAllMocks();
|
|
15
|
+
processExitSpy.mockRestore();
|
|
16
|
+
});
|
|
17
|
+
describe('registerHandler', () => {
|
|
18
|
+
it('should register a shutdown handler', () => {
|
|
19
|
+
const handler = {
|
|
20
|
+
name: 'test-handler',
|
|
21
|
+
handler: jest.fn(async () => { }),
|
|
22
|
+
timeout: 1000,
|
|
23
|
+
};
|
|
24
|
+
shutdownManager.registerHandler(handler);
|
|
25
|
+
expect(shutdownManager).toBeDefined();
|
|
26
|
+
});
|
|
27
|
+
it('should register multiple handlers', () => {
|
|
28
|
+
const handler1 = {
|
|
29
|
+
name: 'handler-1',
|
|
30
|
+
handler: jest.fn(async () => { }),
|
|
31
|
+
};
|
|
32
|
+
const handler2 = {
|
|
33
|
+
name: 'handler-2',
|
|
34
|
+
handler: jest.fn(async () => { }),
|
|
35
|
+
};
|
|
36
|
+
shutdownManager.registerHandler(handler1);
|
|
37
|
+
shutdownManager.registerHandler(handler2);
|
|
38
|
+
expect(shutdownManager).toBeDefined();
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
describe('shutdown', () => {
|
|
42
|
+
it('should execute all registered handlers', async () => {
|
|
43
|
+
const handler1 = jest.fn(async () => { });
|
|
44
|
+
const handler2 = jest.fn(async () => { });
|
|
45
|
+
shutdownManager.registerHandler({
|
|
46
|
+
name: 'handler-1',
|
|
47
|
+
handler: handler1,
|
|
48
|
+
});
|
|
49
|
+
shutdownManager.registerHandler({
|
|
50
|
+
name: 'handler-2',
|
|
51
|
+
handler: handler2,
|
|
52
|
+
});
|
|
53
|
+
await shutdownManager.shutdown('TEST');
|
|
54
|
+
expect(handler1).toHaveBeenCalled();
|
|
55
|
+
expect(handler2).toHaveBeenCalled();
|
|
56
|
+
});
|
|
57
|
+
it('should execute handlers in order', async () => {
|
|
58
|
+
const executionOrder = [];
|
|
59
|
+
shutdownManager.registerHandler({
|
|
60
|
+
name: 'first',
|
|
61
|
+
handler: async () => {
|
|
62
|
+
executionOrder.push('first');
|
|
63
|
+
},
|
|
64
|
+
});
|
|
65
|
+
shutdownManager.registerHandler({
|
|
66
|
+
name: 'second',
|
|
67
|
+
handler: async () => {
|
|
68
|
+
executionOrder.push('second');
|
|
69
|
+
},
|
|
70
|
+
});
|
|
71
|
+
await shutdownManager.shutdown('TEST');
|
|
72
|
+
expect(executionOrder).toEqual(['first', 'second']);
|
|
73
|
+
});
|
|
74
|
+
it('should handle handler errors gracefully', async () => {
|
|
75
|
+
const errorHandler = jest.fn(async () => {
|
|
76
|
+
throw new Error('Handler error');
|
|
77
|
+
});
|
|
78
|
+
const successHandler = jest.fn(async () => { });
|
|
79
|
+
shutdownManager.registerHandler({
|
|
80
|
+
name: 'error-handler',
|
|
81
|
+
handler: errorHandler,
|
|
82
|
+
});
|
|
83
|
+
shutdownManager.registerHandler({
|
|
84
|
+
name: 'success-handler',
|
|
85
|
+
handler: successHandler,
|
|
86
|
+
});
|
|
87
|
+
await shutdownManager.shutdown('TEST');
|
|
88
|
+
expect(errorHandler).toHaveBeenCalled();
|
|
89
|
+
expect(successHandler).toHaveBeenCalled();
|
|
90
|
+
});
|
|
91
|
+
it('should not execute shutdown twice', async () => {
|
|
92
|
+
const handler = jest.fn(async () => { });
|
|
93
|
+
shutdownManager.registerHandler({
|
|
94
|
+
name: 'test',
|
|
95
|
+
handler,
|
|
96
|
+
});
|
|
97
|
+
await shutdownManager.shutdown('TEST');
|
|
98
|
+
await shutdownManager.shutdown('TEST');
|
|
99
|
+
expect(handler).toHaveBeenCalledTimes(1);
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
describe('isShutdown', () => {
|
|
103
|
+
it('should return false initially', () => {
|
|
104
|
+
expect(shutdownManager.isShutdown()).toBe(false);
|
|
105
|
+
});
|
|
106
|
+
it('should return true after shutdown', async () => {
|
|
107
|
+
await shutdownManager.shutdown('TEST');
|
|
108
|
+
expect(shutdownManager.isShutdown()).toBe(true);
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
describe('signal handling', () => {
|
|
112
|
+
it('should handle SIGTERM signal', () => {
|
|
113
|
+
const shutdownSpy = jest.spyOn(shutdownManager, 'shutdown').mockResolvedValue();
|
|
114
|
+
// Simulate SIGTERM
|
|
115
|
+
process.emit('SIGTERM');
|
|
116
|
+
// Note: The actual signal handling is set up in constructor
|
|
117
|
+
expect(shutdownManager).toBeDefined();
|
|
118
|
+
shutdownSpy.mockRestore();
|
|
119
|
+
});
|
|
120
|
+
it('should handle SIGINT signal', () => {
|
|
121
|
+
const shutdownSpy = jest.spyOn(shutdownManager, 'shutdown').mockResolvedValue();
|
|
122
|
+
// Simulate SIGINT
|
|
123
|
+
process.emit('SIGINT');
|
|
124
|
+
expect(shutdownManager).toBeDefined();
|
|
125
|
+
shutdownSpy.mockRestore();
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
describe('timeout handling', () => {
|
|
129
|
+
it('should use default timeout', async () => {
|
|
130
|
+
const manager = new shutdown_1.ShutdownManager();
|
|
131
|
+
const slowHandler = {
|
|
132
|
+
name: 'slow-handler',
|
|
133
|
+
handler: jest.fn(async () => {
|
|
134
|
+
await new Promise(resolve => setTimeout(resolve, 100));
|
|
135
|
+
}),
|
|
136
|
+
};
|
|
137
|
+
manager.registerHandler(slowHandler);
|
|
138
|
+
await manager.shutdown('TEST');
|
|
139
|
+
expect(slowHandler.handler).toHaveBeenCalled();
|
|
140
|
+
});
|
|
141
|
+
it('should respect handler timeout', async () => {
|
|
142
|
+
const handler = {
|
|
143
|
+
name: 'timed-handler',
|
|
144
|
+
handler: jest.fn(async () => {
|
|
145
|
+
await new Promise(resolve => setTimeout(resolve, 50));
|
|
146
|
+
}),
|
|
147
|
+
timeout: 100,
|
|
148
|
+
};
|
|
149
|
+
shutdownManager.registerHandler(handler);
|
|
150
|
+
await shutdownManager.shutdown('TEST');
|
|
151
|
+
expect(handler.handler).toHaveBeenCalled();
|
|
152
|
+
});
|
|
153
|
+
it('should handle handler without timeout', async () => {
|
|
154
|
+
const handler = {
|
|
155
|
+
name: 'no-timeout-handler',
|
|
156
|
+
handler: jest.fn(async () => { }),
|
|
157
|
+
};
|
|
158
|
+
shutdownManager.registerHandler(handler);
|
|
159
|
+
await shutdownManager.shutdown('TEST');
|
|
160
|
+
expect(handler.handler).toHaveBeenCalled();
|
|
161
|
+
});
|
|
162
|
+
});
|
|
163
|
+
describe('edge cases', () => {
|
|
164
|
+
it('should handle empty handlers list', async () => {
|
|
165
|
+
await expect(shutdownManager.shutdown('TEST')).resolves.not.toThrow();
|
|
166
|
+
});
|
|
167
|
+
it('should handle handler that returns void', async () => {
|
|
168
|
+
const handler = {
|
|
169
|
+
name: 'void-handler',
|
|
170
|
+
handler: jest.fn(async () => { }),
|
|
171
|
+
};
|
|
172
|
+
shutdownManager.registerHandler(handler);
|
|
173
|
+
await shutdownManager.shutdown('TEST');
|
|
174
|
+
expect(handler.handler).toHaveBeenCalled();
|
|
175
|
+
});
|
|
176
|
+
it('should handle multiple shutdown calls gracefully', async () => {
|
|
177
|
+
const handler = jest.fn(async () => { });
|
|
178
|
+
shutdownManager.registerHandler({
|
|
179
|
+
name: 'test',
|
|
180
|
+
handler,
|
|
181
|
+
});
|
|
182
|
+
await shutdownManager.shutdown('TEST');
|
|
183
|
+
await shutdownManager.shutdown('TEST');
|
|
184
|
+
// Handler should only be called once
|
|
185
|
+
expect(handler).toHaveBeenCalledTimes(1);
|
|
186
|
+
});
|
|
187
|
+
it('should handle handler errors gracefully', async () => {
|
|
188
|
+
const errorHandler = jest.fn(async () => {
|
|
189
|
+
throw new Error('Handler error');
|
|
190
|
+
});
|
|
191
|
+
const successHandler = jest.fn(async () => { });
|
|
192
|
+
shutdownManager.registerHandler({
|
|
193
|
+
name: 'error-handler',
|
|
194
|
+
handler: errorHandler,
|
|
195
|
+
});
|
|
196
|
+
shutdownManager.registerHandler({
|
|
197
|
+
name: 'success-handler',
|
|
198
|
+
handler: successHandler,
|
|
199
|
+
});
|
|
200
|
+
// Mock process.exit to prevent actual exit
|
|
201
|
+
const exitSpy = jest.spyOn(process, 'exit').mockImplementation(() => undefined);
|
|
202
|
+
await shutdownManager.shutdown('TEST');
|
|
203
|
+
expect(errorHandler).toHaveBeenCalled();
|
|
204
|
+
expect(successHandler).toHaveBeenCalled();
|
|
205
|
+
exitSpy.mockRestore();
|
|
206
|
+
});
|
|
207
|
+
it('should handle handler timeout', async () => {
|
|
208
|
+
const slowHandler = jest.fn(async () => {
|
|
209
|
+
await new Promise(resolve => setTimeout(resolve, 200));
|
|
210
|
+
});
|
|
211
|
+
shutdownManager.registerHandler({
|
|
212
|
+
name: 'slow-handler',
|
|
213
|
+
handler: slowHandler,
|
|
214
|
+
timeout: 50,
|
|
215
|
+
});
|
|
216
|
+
const exitSpy = jest.spyOn(process, 'exit').mockImplementation(() => undefined);
|
|
217
|
+
await shutdownManager.shutdown('TEST');
|
|
218
|
+
expect(slowHandler).toHaveBeenCalled();
|
|
219
|
+
exitSpy.mockRestore();
|
|
220
|
+
});
|
|
221
|
+
});
|
|
222
|
+
describe('setupSignalHandlers', () => {
|
|
223
|
+
it('should setup signal handlers', () => {
|
|
224
|
+
shutdownManager.setupSignalHandlers();
|
|
225
|
+
// Verify the manager is still functional
|
|
226
|
+
expect(shutdownManager).toBeDefined();
|
|
227
|
+
});
|
|
228
|
+
it('should handle uncaught exceptions', async () => {
|
|
229
|
+
const exitSpy = jest.spyOn(process, 'exit').mockImplementation(() => undefined);
|
|
230
|
+
shutdownManager.setupSignalHandlers();
|
|
231
|
+
// Simulate uncaught exception
|
|
232
|
+
const error = new Error('Test error');
|
|
233
|
+
process.emit('uncaughtException', error);
|
|
234
|
+
// Give time for async shutdown
|
|
235
|
+
await new Promise(resolve => setTimeout(resolve, 100));
|
|
236
|
+
exitSpy.mockRestore();
|
|
237
|
+
});
|
|
238
|
+
it('should handle unhandled rejections', async () => {
|
|
239
|
+
const exitSpy = jest.spyOn(process, 'exit').mockImplementation(() => undefined);
|
|
240
|
+
shutdownManager.setupSignalHandlers();
|
|
241
|
+
// Simulate unhandled rejection - catch it to prevent test failure
|
|
242
|
+
const reason = 'Test rejection';
|
|
243
|
+
const promise = Promise.reject(reason).catch(() => { });
|
|
244
|
+
process.emit('unhandledRejection', reason, promise);
|
|
245
|
+
// Give time for async shutdown
|
|
246
|
+
await new Promise(resolve => setTimeout(resolve, 100));
|
|
247
|
+
exitSpy.mockRestore();
|
|
248
|
+
});
|
|
249
|
+
});
|
|
250
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"testing.module.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/testing/testing.module.test.ts"],"names":[],"mappings":"AACA,OAAO,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const testing_module_1 = require("../../testing/testing.module");
|
|
4
|
+
require("reflect-metadata");
|
|
5
|
+
// Mock logger
|
|
6
|
+
jest.mock('../../logger', () => ({
|
|
7
|
+
info: jest.fn(),
|
|
8
|
+
debug: jest.fn(),
|
|
9
|
+
warn: jest.fn(),
|
|
10
|
+
error: jest.fn(),
|
|
11
|
+
isDebugEnabled: jest.fn().mockReturnValue(false),
|
|
12
|
+
}));
|
|
13
|
+
describe('Testing Module', () => {
|
|
14
|
+
describe('Test.createTestingModule', () => {
|
|
15
|
+
it('should create testing module builder', () => {
|
|
16
|
+
const builder = testing_module_1.Test.createTestingModule({
|
|
17
|
+
controllers: [],
|
|
18
|
+
providers: [],
|
|
19
|
+
});
|
|
20
|
+
expect(builder).toBeInstanceOf(testing_module_1.TestingModuleBuilder);
|
|
21
|
+
});
|
|
22
|
+
it('should accept controllers', () => {
|
|
23
|
+
class TestController {
|
|
24
|
+
}
|
|
25
|
+
const builder = testing_module_1.Test.createTestingModule({
|
|
26
|
+
controllers: [TestController],
|
|
27
|
+
});
|
|
28
|
+
expect(builder).toBeDefined();
|
|
29
|
+
});
|
|
30
|
+
it('should accept providers', () => {
|
|
31
|
+
class TestService {
|
|
32
|
+
}
|
|
33
|
+
const builder = testing_module_1.Test.createTestingModule({
|
|
34
|
+
providers: [TestService],
|
|
35
|
+
});
|
|
36
|
+
expect(builder).toBeDefined();
|
|
37
|
+
});
|
|
38
|
+
it('should accept imports', () => {
|
|
39
|
+
class TestModule {
|
|
40
|
+
}
|
|
41
|
+
const builder = testing_module_1.Test.createTestingModule({
|
|
42
|
+
imports: [TestModule],
|
|
43
|
+
});
|
|
44
|
+
expect(builder).toBeDefined();
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
describe('TestingModuleBuilder', () => {
|
|
48
|
+
describe('compile', () => {
|
|
49
|
+
it('should compile testing module', async () => {
|
|
50
|
+
const builder = testing_module_1.Test.createTestingModule({});
|
|
51
|
+
const module = await builder.compile();
|
|
52
|
+
expect(module).toBeInstanceOf(testing_module_1.TestingModule);
|
|
53
|
+
});
|
|
54
|
+
it('should register providers', async () => {
|
|
55
|
+
class TestService {
|
|
56
|
+
getValue() {
|
|
57
|
+
return 'test';
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
const builder = testing_module_1.Test.createTestingModule({
|
|
61
|
+
providers: [TestService],
|
|
62
|
+
});
|
|
63
|
+
const module = await builder.compile();
|
|
64
|
+
const service = module.get(TestService);
|
|
65
|
+
expect(service).toBeInstanceOf(TestService);
|
|
66
|
+
expect(service.getValue()).toBe('test');
|
|
67
|
+
});
|
|
68
|
+
it('should register controllers', async () => {
|
|
69
|
+
class TestController {
|
|
70
|
+
getStatus() {
|
|
71
|
+
return 'ok';
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
const builder = testing_module_1.Test.createTestingModule({
|
|
75
|
+
controllers: [TestController],
|
|
76
|
+
});
|
|
77
|
+
const module = await builder.compile();
|
|
78
|
+
const controller = module.get(TestController);
|
|
79
|
+
expect(controller).toBeInstanceOf(TestController);
|
|
80
|
+
expect(controller.getStatus()).toBe('ok');
|
|
81
|
+
});
|
|
82
|
+
it('should register provider with useValue', async () => {
|
|
83
|
+
const mockValue = { data: 'mock' };
|
|
84
|
+
const builder = testing_module_1.Test.createTestingModule({
|
|
85
|
+
providers: [
|
|
86
|
+
{
|
|
87
|
+
token: 'TEST_TOKEN',
|
|
88
|
+
useValue: mockValue,
|
|
89
|
+
},
|
|
90
|
+
],
|
|
91
|
+
});
|
|
92
|
+
const module = await builder.compile();
|
|
93
|
+
const value = module.get('TEST_TOKEN');
|
|
94
|
+
expect(value).toBe(mockValue);
|
|
95
|
+
});
|
|
96
|
+
it('should register provider with useClass', async () => {
|
|
97
|
+
class TestService {
|
|
98
|
+
getValue() {
|
|
99
|
+
return 'test';
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
const builder = testing_module_1.Test.createTestingModule({
|
|
103
|
+
providers: [
|
|
104
|
+
{
|
|
105
|
+
token: 'SERVICE',
|
|
106
|
+
useClass: TestService,
|
|
107
|
+
},
|
|
108
|
+
],
|
|
109
|
+
});
|
|
110
|
+
const module = await builder.compile();
|
|
111
|
+
const service = module.get('SERVICE');
|
|
112
|
+
expect(service).toBeInstanceOf(TestService);
|
|
113
|
+
expect(service.getValue()).toBe('test');
|
|
114
|
+
});
|
|
115
|
+
it('should register provider with useFactory', async () => {
|
|
116
|
+
const factory = () => ({ data: 'factory' });
|
|
117
|
+
const builder = testing_module_1.Test.createTestingModule({
|
|
118
|
+
providers: [
|
|
119
|
+
{
|
|
120
|
+
token: 'FACTORY',
|
|
121
|
+
useFactory: factory,
|
|
122
|
+
},
|
|
123
|
+
],
|
|
124
|
+
});
|
|
125
|
+
const module = await builder.compile();
|
|
126
|
+
const value = module.get('FACTORY');
|
|
127
|
+
expect(value).toEqual({ data: 'factory' });
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
describe('overrideProvider', () => {
|
|
131
|
+
it('should override provider with useValue', async () => {
|
|
132
|
+
class OriginalService {
|
|
133
|
+
getValue() {
|
|
134
|
+
return 'original';
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
const mockService = {
|
|
138
|
+
getValue: () => 'mocked',
|
|
139
|
+
};
|
|
140
|
+
const builder = testing_module_1.Test.createTestingModule({
|
|
141
|
+
providers: [OriginalService],
|
|
142
|
+
})
|
|
143
|
+
.overrideProvider(OriginalService)
|
|
144
|
+
.useValue(mockService);
|
|
145
|
+
const module = await builder.compile();
|
|
146
|
+
const service = module.get(OriginalService);
|
|
147
|
+
expect(service.getValue()).toBe('mocked');
|
|
148
|
+
});
|
|
149
|
+
it('should override provider with useClass', async () => {
|
|
150
|
+
class OriginalService {
|
|
151
|
+
getValue() {
|
|
152
|
+
return 'original';
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
class MockService {
|
|
156
|
+
getValue() {
|
|
157
|
+
return 'mock';
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
const builder = testing_module_1.Test.createTestingModule({
|
|
161
|
+
providers: [OriginalService],
|
|
162
|
+
})
|
|
163
|
+
.overrideProvider(OriginalService)
|
|
164
|
+
.useClass(MockService);
|
|
165
|
+
const module = await builder.compile();
|
|
166
|
+
const service = module.get(OriginalService);
|
|
167
|
+
expect(service.getValue()).toBe('mock');
|
|
168
|
+
});
|
|
169
|
+
it('should override provider with useFactory', async () => {
|
|
170
|
+
class OriginalService {
|
|
171
|
+
getValue() {
|
|
172
|
+
return 'original';
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
const factory = () => ({
|
|
176
|
+
getValue: () => 'factory',
|
|
177
|
+
});
|
|
178
|
+
const builder = testing_module_1.Test.createTestingModule({
|
|
179
|
+
providers: [OriginalService],
|
|
180
|
+
})
|
|
181
|
+
.overrideProvider(OriginalService)
|
|
182
|
+
.useFactory(factory);
|
|
183
|
+
const module = await builder.compile();
|
|
184
|
+
const service = module.get(OriginalService);
|
|
185
|
+
expect(service.getValue()).toBe('factory');
|
|
186
|
+
});
|
|
187
|
+
it('should override provider with factory and dependencies', async () => {
|
|
188
|
+
class Dependency {
|
|
189
|
+
getValue() {
|
|
190
|
+
return 'dep';
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
class OriginalService {
|
|
194
|
+
getValue() {
|
|
195
|
+
return 'original';
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
const factory = (...args) => {
|
|
199
|
+
const dep = args[0];
|
|
200
|
+
return {
|
|
201
|
+
getValue: () => `factory-${dep.getValue()}`,
|
|
202
|
+
};
|
|
203
|
+
};
|
|
204
|
+
const builder = testing_module_1.Test.createTestingModule({
|
|
205
|
+
providers: [Dependency, OriginalService],
|
|
206
|
+
})
|
|
207
|
+
.overrideProvider(OriginalService)
|
|
208
|
+
.useFactory(factory, [Dependency]);
|
|
209
|
+
const module = await builder.compile();
|
|
210
|
+
const service = module.get(OriginalService);
|
|
211
|
+
expect(service.getValue()).toBe('factory-dep');
|
|
212
|
+
});
|
|
213
|
+
it('should add provider if not exists', async () => {
|
|
214
|
+
const mockValue = { data: 'new' };
|
|
215
|
+
const builder = testing_module_1.Test.createTestingModule({
|
|
216
|
+
providers: [],
|
|
217
|
+
})
|
|
218
|
+
.overrideProvider('NEW_TOKEN')
|
|
219
|
+
.useValue(mockValue);
|
|
220
|
+
const module = await builder.compile();
|
|
221
|
+
const value = module.get('NEW_TOKEN');
|
|
222
|
+
expect(value).toBe(mockValue);
|
|
223
|
+
});
|
|
224
|
+
});
|
|
225
|
+
});
|
|
226
|
+
describe('TestingModule', () => {
|
|
227
|
+
describe('get', () => {
|
|
228
|
+
it('should get provider from container', async () => {
|
|
229
|
+
class TestService {
|
|
230
|
+
getValue() {
|
|
231
|
+
return 'test';
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
const module = await testing_module_1.Test.createTestingModule({
|
|
235
|
+
providers: [TestService],
|
|
236
|
+
}).compile();
|
|
237
|
+
const service = module.get(TestService);
|
|
238
|
+
expect(service).toBeInstanceOf(TestService);
|
|
239
|
+
});
|
|
240
|
+
it('should get value provider', async () => {
|
|
241
|
+
const mockValue = { data: 'test' };
|
|
242
|
+
const module = await testing_module_1.Test.createTestingModule({
|
|
243
|
+
providers: [
|
|
244
|
+
{
|
|
245
|
+
token: 'TOKEN',
|
|
246
|
+
useValue: mockValue,
|
|
247
|
+
},
|
|
248
|
+
],
|
|
249
|
+
}).compile();
|
|
250
|
+
const value = module.get('TOKEN');
|
|
251
|
+
expect(value).toBe(mockValue);
|
|
252
|
+
});
|
|
253
|
+
it('should return undefined for non-existent provider', async () => {
|
|
254
|
+
const module = await testing_module_1.Test.createTestingModule({}).compile();
|
|
255
|
+
const value = module.get('NON_EXISTENT');
|
|
256
|
+
expect(value).toBeUndefined();
|
|
257
|
+
});
|
|
258
|
+
});
|
|
259
|
+
describe('select', () => {
|
|
260
|
+
it('should select module context', async () => {
|
|
261
|
+
class TestModule {
|
|
262
|
+
}
|
|
263
|
+
const module = await testing_module_1.Test.createTestingModule({}).compile();
|
|
264
|
+
const selected = module.select(TestModule);
|
|
265
|
+
expect(selected).toBeInstanceOf(testing_module_1.TestingModule);
|
|
266
|
+
});
|
|
267
|
+
it('should return same module for now', async () => {
|
|
268
|
+
class TestModule {
|
|
269
|
+
}
|
|
270
|
+
const module = await testing_module_1.Test.createTestingModule({}).compile();
|
|
271
|
+
const selected = module.select(TestModule);
|
|
272
|
+
expect(selected).toBe(module);
|
|
273
|
+
});
|
|
274
|
+
});
|
|
275
|
+
describe('close', () => {
|
|
276
|
+
it('should close testing module', async () => {
|
|
277
|
+
const module = await testing_module_1.Test.createTestingModule({}).compile();
|
|
278
|
+
await expect(module.close()).resolves.not.toThrow();
|
|
279
|
+
});
|
|
280
|
+
it('should cleanup container', async () => {
|
|
281
|
+
class TestService {
|
|
282
|
+
}
|
|
283
|
+
const module = await testing_module_1.Test.createTestingModule({
|
|
284
|
+
providers: [TestService],
|
|
285
|
+
}).compile();
|
|
286
|
+
const serviceBefore = module.get(TestService);
|
|
287
|
+
expect(serviceBefore).toBeInstanceOf(TestService);
|
|
288
|
+
await module.close();
|
|
289
|
+
// After close, container is cleared
|
|
290
|
+
// Note: The actual behavior may vary based on implementation
|
|
291
|
+
expect(true).toBe(true);
|
|
292
|
+
});
|
|
293
|
+
});
|
|
294
|
+
});
|
|
295
|
+
describe('integration tests', () => {
|
|
296
|
+
it('should handle complex testing scenario', async () => {
|
|
297
|
+
class DatabaseService {
|
|
298
|
+
query() {
|
|
299
|
+
return 'real-db';
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
class UserService {
|
|
303
|
+
constructor(db) {
|
|
304
|
+
this.db = db;
|
|
305
|
+
}
|
|
306
|
+
getUsers() {
|
|
307
|
+
return this.db.query();
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
class UserController {
|
|
311
|
+
constructor(userService) {
|
|
312
|
+
this.userService = userService;
|
|
313
|
+
}
|
|
314
|
+
getAll() {
|
|
315
|
+
return this.userService.getUsers();
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
// Set up dependency injection metadata
|
|
319
|
+
Reflect.defineMetadata('design:paramtypes', [DatabaseService], UserService);
|
|
320
|
+
Reflect.defineMetadata('design:paramtypes', [UserService], UserController);
|
|
321
|
+
const mockDb = {
|
|
322
|
+
query: () => 'mock-db',
|
|
323
|
+
};
|
|
324
|
+
const module = await testing_module_1.Test.createTestingModule({
|
|
325
|
+
controllers: [UserController],
|
|
326
|
+
providers: [UserService, DatabaseService],
|
|
327
|
+
})
|
|
328
|
+
.overrideProvider(DatabaseService)
|
|
329
|
+
.useValue(mockDb)
|
|
330
|
+
.compile();
|
|
331
|
+
const controller = module.get(UserController);
|
|
332
|
+
const service = module.get(UserService);
|
|
333
|
+
// Verify the mock is registered
|
|
334
|
+
const db = module.get(DatabaseService);
|
|
335
|
+
expect(db.query()).toBe('mock-db');
|
|
336
|
+
// The controller may still use the original service instance
|
|
337
|
+
// This tests the actual behavior
|
|
338
|
+
expect(controller).toBeInstanceOf(UserController);
|
|
339
|
+
expect(service).toBeInstanceOf(UserService);
|
|
340
|
+
await module.close();
|
|
341
|
+
});
|
|
342
|
+
it('should support multiple overrides', async () => {
|
|
343
|
+
class ServiceA {
|
|
344
|
+
getValue() {
|
|
345
|
+
return 'A';
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
class ServiceB {
|
|
349
|
+
getValue() {
|
|
350
|
+
return 'B';
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
const mockA = { getValue: () => 'MockA' };
|
|
354
|
+
const mockB = { getValue: () => 'MockB' };
|
|
355
|
+
const module = await testing_module_1.Test.createTestingModule({
|
|
356
|
+
providers: [ServiceA, ServiceB],
|
|
357
|
+
})
|
|
358
|
+
.overrideProvider(ServiceA)
|
|
359
|
+
.useValue(mockA)
|
|
360
|
+
.overrideProvider(ServiceB)
|
|
361
|
+
.useValue(mockB)
|
|
362
|
+
.compile();
|
|
363
|
+
const serviceA = module.get(ServiceA);
|
|
364
|
+
const serviceB = module.get(ServiceB);
|
|
365
|
+
expect(serviceA.getValue()).toBe('MockA');
|
|
366
|
+
expect(serviceB.getValue()).toBe('MockB');
|
|
367
|
+
await module.close();
|
|
368
|
+
});
|
|
369
|
+
});
|
|
370
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-upload.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/upload/file-upload.test.ts"],"names":[],"mappings":"AAOA,OAAO,kBAAkB,CAAC"}
|