@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,245 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const pipe_1 = require("../../pipes/pipe");
|
|
4
|
+
// Mock logger
|
|
5
|
+
jest.mock('../../logger', () => ({
|
|
6
|
+
debug: jest.fn(),
|
|
7
|
+
error: jest.fn(),
|
|
8
|
+
}));
|
|
9
|
+
describe('Pipes', () => {
|
|
10
|
+
let context;
|
|
11
|
+
beforeEach(() => {
|
|
12
|
+
context = {
|
|
13
|
+
method: 'GET',
|
|
14
|
+
url: '/test',
|
|
15
|
+
headers: {},
|
|
16
|
+
params: { id: '123' },
|
|
17
|
+
query: {},
|
|
18
|
+
body: {},
|
|
19
|
+
};
|
|
20
|
+
});
|
|
21
|
+
describe('ValidationError', () => {
|
|
22
|
+
it('should create validation error with message and errors', () => {
|
|
23
|
+
const errors = [
|
|
24
|
+
{
|
|
25
|
+
property: 'email',
|
|
26
|
+
constraints: { isEmail: 'email must be a valid email' },
|
|
27
|
+
value: 'invalid',
|
|
28
|
+
},
|
|
29
|
+
];
|
|
30
|
+
const error = new pipe_1.ValidationError('Validation failed', errors);
|
|
31
|
+
expect(error.message).toBe('Validation failed');
|
|
32
|
+
expect(error.errors).toEqual(errors);
|
|
33
|
+
expect(error.name).toBe('ValidationError');
|
|
34
|
+
});
|
|
35
|
+
it('should convert to JSON format', () => {
|
|
36
|
+
const errors = [
|
|
37
|
+
{
|
|
38
|
+
property: 'email',
|
|
39
|
+
constraints: {
|
|
40
|
+
isEmail: 'email must be a valid email',
|
|
41
|
+
isNotEmpty: 'email should not be empty',
|
|
42
|
+
},
|
|
43
|
+
value: 'invalid',
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
property: 'age',
|
|
47
|
+
constraints: { isInt: 'age must be an integer' },
|
|
48
|
+
value: 'abc',
|
|
49
|
+
},
|
|
50
|
+
];
|
|
51
|
+
const error = new pipe_1.ValidationError('Validation failed', errors);
|
|
52
|
+
const json = error.toJSON();
|
|
53
|
+
expect(json).toEqual({
|
|
54
|
+
message: 'Validation failed',
|
|
55
|
+
errors: [
|
|
56
|
+
{
|
|
57
|
+
field: 'email',
|
|
58
|
+
messages: ['email must be a valid email', 'email should not be empty'],
|
|
59
|
+
value: 'invalid',
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
field: 'age',
|
|
63
|
+
messages: ['age must be an integer'],
|
|
64
|
+
value: 'abc',
|
|
65
|
+
},
|
|
66
|
+
],
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
describe('ParseIntPipe', () => {
|
|
71
|
+
let pipe;
|
|
72
|
+
beforeEach(() => {
|
|
73
|
+
pipe = new pipe_1.ParseIntPipe();
|
|
74
|
+
});
|
|
75
|
+
it('should parse valid integer string', () => {
|
|
76
|
+
const result = pipe.transform('123', context);
|
|
77
|
+
expect(result).toBe(123);
|
|
78
|
+
});
|
|
79
|
+
it('should parse negative integers', () => {
|
|
80
|
+
const result = pipe.transform('-456', context);
|
|
81
|
+
expect(result).toBe(-456);
|
|
82
|
+
});
|
|
83
|
+
it('should parse zero', () => {
|
|
84
|
+
const result = pipe.transform('0', context);
|
|
85
|
+
expect(result).toBe(0);
|
|
86
|
+
});
|
|
87
|
+
it('should throw error for empty string', () => {
|
|
88
|
+
expect(() => pipe.transform('', context)).toThrow(pipe_1.ValidationError);
|
|
89
|
+
});
|
|
90
|
+
it('should throw error for non-numeric string', () => {
|
|
91
|
+
expect(() => pipe.transform('abc', context)).toThrow(pipe_1.ValidationError);
|
|
92
|
+
});
|
|
93
|
+
it('should throw error for float string', () => {
|
|
94
|
+
const result = pipe.transform('123.45', context);
|
|
95
|
+
// parseInt truncates, so this should return 123
|
|
96
|
+
expect(result).toBe(123);
|
|
97
|
+
});
|
|
98
|
+
it('should throw error for null/undefined', () => {
|
|
99
|
+
expect(() => pipe.transform(null, context)).toThrow(pipe_1.ValidationError);
|
|
100
|
+
});
|
|
101
|
+
it('should include proper error details', () => {
|
|
102
|
+
try {
|
|
103
|
+
pipe.transform('invalid', context);
|
|
104
|
+
fail('Should have thrown error');
|
|
105
|
+
}
|
|
106
|
+
catch (error) {
|
|
107
|
+
expect(error).toBeInstanceOf(pipe_1.ValidationError);
|
|
108
|
+
const validationError = error;
|
|
109
|
+
expect(validationError.errors[0].property).toBe('id');
|
|
110
|
+
expect(validationError.errors[0].constraints.isInt).toBeDefined();
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
describe('ParseFloatPipe', () => {
|
|
115
|
+
let pipe;
|
|
116
|
+
beforeEach(() => {
|
|
117
|
+
pipe = new pipe_1.ParseFloatPipe();
|
|
118
|
+
});
|
|
119
|
+
it('should parse valid float string', () => {
|
|
120
|
+
const result = pipe.transform('123.45', context);
|
|
121
|
+
expect(result).toBe(123.45);
|
|
122
|
+
});
|
|
123
|
+
it('should parse integer as float', () => {
|
|
124
|
+
const result = pipe.transform('100', context);
|
|
125
|
+
expect(result).toBe(100);
|
|
126
|
+
});
|
|
127
|
+
it('should parse negative floats', () => {
|
|
128
|
+
const result = pipe.transform('-99.99', context);
|
|
129
|
+
expect(result).toBe(-99.99);
|
|
130
|
+
});
|
|
131
|
+
it('should parse scientific notation', () => {
|
|
132
|
+
const result = pipe.transform('1.5e2', context);
|
|
133
|
+
expect(result).toBe(150);
|
|
134
|
+
});
|
|
135
|
+
it('should throw error for non-numeric string', () => {
|
|
136
|
+
expect(() => pipe.transform('abc', context)).toThrow(pipe_1.ValidationError);
|
|
137
|
+
});
|
|
138
|
+
it('should throw error for empty string', () => {
|
|
139
|
+
expect(() => pipe.transform('', context)).toThrow(pipe_1.ValidationError);
|
|
140
|
+
});
|
|
141
|
+
it('should include proper error details', () => {
|
|
142
|
+
try {
|
|
143
|
+
pipe.transform('invalid', context);
|
|
144
|
+
fail('Should have thrown error');
|
|
145
|
+
}
|
|
146
|
+
catch (error) {
|
|
147
|
+
expect(error).toBeInstanceOf(pipe_1.ValidationError);
|
|
148
|
+
const validationError = error;
|
|
149
|
+
expect(validationError.errors[0].constraints.isFloat).toBeDefined();
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
describe('ParseBoolPipe', () => {
|
|
154
|
+
let pipe;
|
|
155
|
+
beforeEach(() => {
|
|
156
|
+
pipe = new pipe_1.ParseBoolPipe();
|
|
157
|
+
});
|
|
158
|
+
it('should parse "true" string to true', () => {
|
|
159
|
+
const result = pipe.transform('true', context);
|
|
160
|
+
expect(result).toBe(true);
|
|
161
|
+
});
|
|
162
|
+
it('should parse "false" string to false', () => {
|
|
163
|
+
const result = pipe.transform('false', context);
|
|
164
|
+
expect(result).toBe(false);
|
|
165
|
+
});
|
|
166
|
+
it('should throw error for "1"', () => {
|
|
167
|
+
expect(() => pipe.transform('1', context)).toThrow(pipe_1.ValidationError);
|
|
168
|
+
});
|
|
169
|
+
it('should throw error for "0"', () => {
|
|
170
|
+
expect(() => pipe.transform('0', context)).toThrow(pipe_1.ValidationError);
|
|
171
|
+
});
|
|
172
|
+
it('should throw error for "yes"', () => {
|
|
173
|
+
expect(() => pipe.transform('yes', context)).toThrow(pipe_1.ValidationError);
|
|
174
|
+
});
|
|
175
|
+
it('should throw error for empty string', () => {
|
|
176
|
+
expect(() => pipe.transform('', context)).toThrow(pipe_1.ValidationError);
|
|
177
|
+
});
|
|
178
|
+
it('should throw error for invalid boolean string', () => {
|
|
179
|
+
expect(() => pipe.transform('invalid', context)).toThrow(pipe_1.ValidationError);
|
|
180
|
+
});
|
|
181
|
+
it('should include proper error details', () => {
|
|
182
|
+
try {
|
|
183
|
+
pipe.transform('invalid', context);
|
|
184
|
+
fail('Should have thrown error');
|
|
185
|
+
}
|
|
186
|
+
catch (error) {
|
|
187
|
+
expect(error).toBeInstanceOf(pipe_1.ValidationError);
|
|
188
|
+
const validationError = error;
|
|
189
|
+
expect(validationError.errors[0].constraints.isBoolean).toBeDefined();
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
});
|
|
193
|
+
describe('DefaultValuePipe', () => {
|
|
194
|
+
it('should return default value for undefined', () => {
|
|
195
|
+
const pipe = new pipe_1.DefaultValuePipe('default');
|
|
196
|
+
const result = pipe.transform(undefined);
|
|
197
|
+
expect(result).toBe('default');
|
|
198
|
+
});
|
|
199
|
+
it('should return actual value when defined', () => {
|
|
200
|
+
const pipe = new pipe_1.DefaultValuePipe('default');
|
|
201
|
+
const result = pipe.transform('actual');
|
|
202
|
+
expect(result).toBe('actual');
|
|
203
|
+
});
|
|
204
|
+
it('should work with number default', () => {
|
|
205
|
+
const pipe = new pipe_1.DefaultValuePipe(42);
|
|
206
|
+
expect(pipe.transform(undefined)).toBe(42);
|
|
207
|
+
expect(pipe.transform(10)).toBe(10);
|
|
208
|
+
});
|
|
209
|
+
it('should work with boolean default', () => {
|
|
210
|
+
const pipe = new pipe_1.DefaultValuePipe(true);
|
|
211
|
+
expect(pipe.transform(undefined)).toBe(true);
|
|
212
|
+
expect(pipe.transform(false)).toBe(false);
|
|
213
|
+
});
|
|
214
|
+
it('should work with object default', () => {
|
|
215
|
+
const defaultObj = { key: 'value' };
|
|
216
|
+
const pipe = new pipe_1.DefaultValuePipe(defaultObj);
|
|
217
|
+
expect(pipe.transform(undefined)).toBe(defaultObj);
|
|
218
|
+
});
|
|
219
|
+
it('should work with array default', () => {
|
|
220
|
+
const defaultArr = [1, 2, 3];
|
|
221
|
+
const pipe = new pipe_1.DefaultValuePipe(defaultArr);
|
|
222
|
+
expect(pipe.transform(undefined)).toBe(defaultArr);
|
|
223
|
+
});
|
|
224
|
+
it('should not treat null as undefined', () => {
|
|
225
|
+
const pipe = new pipe_1.DefaultValuePipe('default');
|
|
226
|
+
const result = pipe.transform(null);
|
|
227
|
+
expect(result).toBe(null);
|
|
228
|
+
});
|
|
229
|
+
it('should not treat empty string as undefined', () => {
|
|
230
|
+
const pipe = new pipe_1.DefaultValuePipe('default');
|
|
231
|
+
const result = pipe.transform('');
|
|
232
|
+
expect(result).toBe('');
|
|
233
|
+
});
|
|
234
|
+
it('should not treat zero as undefined', () => {
|
|
235
|
+
const pipe = new pipe_1.DefaultValuePipe(42);
|
|
236
|
+
const result = pipe.transform(0);
|
|
237
|
+
expect(result).toBe(0);
|
|
238
|
+
});
|
|
239
|
+
it('should not treat false as undefined', () => {
|
|
240
|
+
const pipe = new pipe_1.DefaultValuePipe(true);
|
|
241
|
+
const result = pipe.transform(false);
|
|
242
|
+
expect(result).toBe(false);
|
|
243
|
+
});
|
|
244
|
+
});
|
|
245
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.pipe.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/pipes/validation.pipe.test.ts"],"names":[],"mappings":"AAIA,OAAO,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
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;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
const validation_pipe_1 = require("../../pipes/validation.pipe");
|
|
13
|
+
const pipe_1 = require("../../pipes/pipe");
|
|
14
|
+
const class_validator_1 = require("class-validator");
|
|
15
|
+
require("reflect-metadata");
|
|
16
|
+
// Mock logger
|
|
17
|
+
jest.mock('../../logger', () => ({
|
|
18
|
+
debug: jest.fn(),
|
|
19
|
+
error: jest.fn(),
|
|
20
|
+
info: jest.fn(),
|
|
21
|
+
warn: jest.fn(),
|
|
22
|
+
}));
|
|
23
|
+
describe('ValidationPipe', () => {
|
|
24
|
+
let pipe;
|
|
25
|
+
beforeEach(() => {
|
|
26
|
+
pipe = new validation_pipe_1.ValidationPipe();
|
|
27
|
+
});
|
|
28
|
+
describe('transform', () => {
|
|
29
|
+
it('should return value as-is when no DTO type provided', async () => {
|
|
30
|
+
const value = { name: 'test' };
|
|
31
|
+
const context = {};
|
|
32
|
+
const result = await pipe.transform(value, context);
|
|
33
|
+
expect(result).toBe(value);
|
|
34
|
+
});
|
|
35
|
+
it('should return value as-is when DTO type is not a constructor', async () => {
|
|
36
|
+
const value = { name: 'test' };
|
|
37
|
+
const context = {
|
|
38
|
+
dtoType: 'not-a-constructor',
|
|
39
|
+
};
|
|
40
|
+
const result = await pipe.transform(value, context);
|
|
41
|
+
expect(result).toBe(value);
|
|
42
|
+
});
|
|
43
|
+
it('should validate and transform valid DTO', async () => {
|
|
44
|
+
class CreateUserDto {
|
|
45
|
+
}
|
|
46
|
+
__decorate([
|
|
47
|
+
(0, class_validator_1.IsString)(),
|
|
48
|
+
__metadata("design:type", String)
|
|
49
|
+
], CreateUserDto.prototype, "name", void 0);
|
|
50
|
+
__decorate([
|
|
51
|
+
(0, class_validator_1.IsInt)(),
|
|
52
|
+
(0, class_validator_1.Min)(0),
|
|
53
|
+
__metadata("design:type", Number)
|
|
54
|
+
], CreateUserDto.prototype, "age", void 0);
|
|
55
|
+
const value = { name: 'John', age: 25 };
|
|
56
|
+
const context = {
|
|
57
|
+
dtoType: CreateUserDto,
|
|
58
|
+
};
|
|
59
|
+
const result = await pipe.transform(value, context);
|
|
60
|
+
expect(result).toBeInstanceOf(CreateUserDto);
|
|
61
|
+
expect(result.name).toBe('John');
|
|
62
|
+
expect(result.age).toBe(25);
|
|
63
|
+
});
|
|
64
|
+
it('should throw ValidationError for invalid DTO', async () => {
|
|
65
|
+
class CreateUserDto {
|
|
66
|
+
}
|
|
67
|
+
__decorate([
|
|
68
|
+
(0, class_validator_1.IsString)(),
|
|
69
|
+
__metadata("design:type", String)
|
|
70
|
+
], CreateUserDto.prototype, "name", void 0);
|
|
71
|
+
__decorate([
|
|
72
|
+
(0, class_validator_1.IsInt)(),
|
|
73
|
+
(0, class_validator_1.Min)(18),
|
|
74
|
+
__metadata("design:type", Number)
|
|
75
|
+
], CreateUserDto.prototype, "age", void 0);
|
|
76
|
+
const value = { name: 'John', age: 15 };
|
|
77
|
+
const context = {
|
|
78
|
+
dtoType: CreateUserDto,
|
|
79
|
+
};
|
|
80
|
+
await expect(pipe.transform(value, context)).rejects.toThrow(pipe_1.ValidationError);
|
|
81
|
+
});
|
|
82
|
+
it('should throw ValidationError when value is not an object', async () => {
|
|
83
|
+
class CreateUserDto {
|
|
84
|
+
}
|
|
85
|
+
__decorate([
|
|
86
|
+
(0, class_validator_1.IsString)(),
|
|
87
|
+
__metadata("design:type", String)
|
|
88
|
+
], CreateUserDto.prototype, "name", void 0);
|
|
89
|
+
const value = 'not an object';
|
|
90
|
+
const context = {
|
|
91
|
+
dtoType: CreateUserDto,
|
|
92
|
+
};
|
|
93
|
+
await expect(pipe.transform(value, context)).rejects.toThrow(pipe_1.ValidationError);
|
|
94
|
+
await expect(pipe.transform(value, context)).rejects.toThrow('Invalid input: expected an object');
|
|
95
|
+
});
|
|
96
|
+
it('should throw ValidationError when value is null', async () => {
|
|
97
|
+
class CreateUserDto {
|
|
98
|
+
}
|
|
99
|
+
__decorate([
|
|
100
|
+
(0, class_validator_1.IsString)(),
|
|
101
|
+
__metadata("design:type", String)
|
|
102
|
+
], CreateUserDto.prototype, "name", void 0);
|
|
103
|
+
const value = null;
|
|
104
|
+
const context = {
|
|
105
|
+
dtoType: CreateUserDto,
|
|
106
|
+
};
|
|
107
|
+
await expect(pipe.transform(value, context)).rejects.toThrow(pipe_1.ValidationError);
|
|
108
|
+
});
|
|
109
|
+
it('should handle multiple validation errors', async () => {
|
|
110
|
+
class CreateUserDto {
|
|
111
|
+
}
|
|
112
|
+
__decorate([
|
|
113
|
+
(0, class_validator_1.IsString)(),
|
|
114
|
+
__metadata("design:type", String)
|
|
115
|
+
], CreateUserDto.prototype, "name", void 0);
|
|
116
|
+
__decorate([
|
|
117
|
+
(0, class_validator_1.IsInt)(),
|
|
118
|
+
__metadata("design:type", Number)
|
|
119
|
+
], CreateUserDto.prototype, "age", void 0);
|
|
120
|
+
__decorate([
|
|
121
|
+
(0, class_validator_1.IsEmail)(),
|
|
122
|
+
__metadata("design:type", String)
|
|
123
|
+
], CreateUserDto.prototype, "email", void 0);
|
|
124
|
+
const value = { name: 123, age: 'not-a-number', email: 'invalid-email' };
|
|
125
|
+
const context = {
|
|
126
|
+
dtoType: CreateUserDto,
|
|
127
|
+
};
|
|
128
|
+
try {
|
|
129
|
+
await pipe.transform(value, context);
|
|
130
|
+
fail('Should have thrown ValidationError');
|
|
131
|
+
}
|
|
132
|
+
catch (error) {
|
|
133
|
+
expect(error).toBeInstanceOf(pipe_1.ValidationError);
|
|
134
|
+
const validationError = error;
|
|
135
|
+
expect(validationError.errors.length).toBeGreaterThan(0);
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
it('should handle empty constraints', async () => {
|
|
139
|
+
class CreateUserDto {
|
|
140
|
+
}
|
|
141
|
+
__decorate([
|
|
142
|
+
(0, class_validator_1.IsString)(),
|
|
143
|
+
__metadata("design:type", String)
|
|
144
|
+
], CreateUserDto.prototype, "name", void 0);
|
|
145
|
+
const value = { name: 123 };
|
|
146
|
+
const context = {
|
|
147
|
+
dtoType: CreateUserDto,
|
|
148
|
+
};
|
|
149
|
+
try {
|
|
150
|
+
await pipe.transform(value, context);
|
|
151
|
+
fail('Should have thrown ValidationError');
|
|
152
|
+
}
|
|
153
|
+
catch (error) {
|
|
154
|
+
expect(error).toBeInstanceOf(pipe_1.ValidationError);
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
it('should transform nested objects', async () => {
|
|
158
|
+
class AddressDto {
|
|
159
|
+
}
|
|
160
|
+
__decorate([
|
|
161
|
+
(0, class_validator_1.IsString)(),
|
|
162
|
+
__metadata("design:type", String)
|
|
163
|
+
], AddressDto.prototype, "street", void 0);
|
|
164
|
+
__decorate([
|
|
165
|
+
(0, class_validator_1.IsString)(),
|
|
166
|
+
__metadata("design:type", String)
|
|
167
|
+
], AddressDto.prototype, "city", void 0);
|
|
168
|
+
class CreateUserDto {
|
|
169
|
+
}
|
|
170
|
+
__decorate([
|
|
171
|
+
(0, class_validator_1.IsString)(),
|
|
172
|
+
__metadata("design:type", String)
|
|
173
|
+
], CreateUserDto.prototype, "name", void 0);
|
|
174
|
+
const value = {
|
|
175
|
+
name: 'John',
|
|
176
|
+
address: {
|
|
177
|
+
street: '123 Main St',
|
|
178
|
+
city: 'New York',
|
|
179
|
+
},
|
|
180
|
+
};
|
|
181
|
+
const context = {
|
|
182
|
+
dtoType: CreateUserDto,
|
|
183
|
+
};
|
|
184
|
+
const result = await pipe.transform(value, context);
|
|
185
|
+
expect(result).toBeInstanceOf(CreateUserDto);
|
|
186
|
+
expect(result.name).toBe('John');
|
|
187
|
+
});
|
|
188
|
+
it('should handle arrays in DTO', async () => {
|
|
189
|
+
class CreateUserDto {
|
|
190
|
+
}
|
|
191
|
+
__decorate([
|
|
192
|
+
(0, class_validator_1.IsString)(),
|
|
193
|
+
__metadata("design:type", String)
|
|
194
|
+
], CreateUserDto.prototype, "name", void 0);
|
|
195
|
+
const value = {
|
|
196
|
+
name: 'John',
|
|
197
|
+
tags: ['developer', 'typescript'],
|
|
198
|
+
};
|
|
199
|
+
const context = {
|
|
200
|
+
dtoType: CreateUserDto,
|
|
201
|
+
};
|
|
202
|
+
const result = await pipe.transform(value, context);
|
|
203
|
+
expect(result).toBeInstanceOf(CreateUserDto);
|
|
204
|
+
expect(result.tags).toEqual(['developer', 'typescript']);
|
|
205
|
+
});
|
|
206
|
+
it('should validate email format', async () => {
|
|
207
|
+
class CreateUserDto {
|
|
208
|
+
}
|
|
209
|
+
__decorate([
|
|
210
|
+
(0, class_validator_1.IsEmail)(),
|
|
211
|
+
__metadata("design:type", String)
|
|
212
|
+
], CreateUserDto.prototype, "email", void 0);
|
|
213
|
+
const validValue = { email: 'user@example.com' };
|
|
214
|
+
const invalidValue = { email: 'not-an-email' };
|
|
215
|
+
const context = {
|
|
216
|
+
dtoType: CreateUserDto,
|
|
217
|
+
};
|
|
218
|
+
const validResult = await pipe.transform(validValue, context);
|
|
219
|
+
expect(validResult).toBeInstanceOf(CreateUserDto);
|
|
220
|
+
await expect(pipe.transform(invalidValue, context)).rejects.toThrow(pipe_1.ValidationError);
|
|
221
|
+
});
|
|
222
|
+
it('should handle minimum value validation', async () => {
|
|
223
|
+
class CreateProductDto {
|
|
224
|
+
}
|
|
225
|
+
__decorate([
|
|
226
|
+
(0, class_validator_1.IsInt)(),
|
|
227
|
+
(0, class_validator_1.Min)(1),
|
|
228
|
+
__metadata("design:type", Number)
|
|
229
|
+
], CreateProductDto.prototype, "quantity", void 0);
|
|
230
|
+
const validValue = { quantity: 5 };
|
|
231
|
+
const invalidValue = { quantity: 0 };
|
|
232
|
+
const context = {
|
|
233
|
+
dtoType: CreateProductDto,
|
|
234
|
+
};
|
|
235
|
+
const validResult = await pipe.transform(validValue, context);
|
|
236
|
+
expect(validResult).toBeInstanceOf(CreateProductDto);
|
|
237
|
+
await expect(pipe.transform(invalidValue, context)).rejects.toThrow(pipe_1.ValidationError);
|
|
238
|
+
});
|
|
239
|
+
it('should preserve extra properties', async () => {
|
|
240
|
+
class CreateUserDto {
|
|
241
|
+
}
|
|
242
|
+
__decorate([
|
|
243
|
+
(0, class_validator_1.IsString)(),
|
|
244
|
+
__metadata("design:type", String)
|
|
245
|
+
], CreateUserDto.prototype, "name", void 0);
|
|
246
|
+
const value = { name: 'John', extra: 'property' };
|
|
247
|
+
const context = {
|
|
248
|
+
dtoType: CreateUserDto,
|
|
249
|
+
};
|
|
250
|
+
const result = await pipe.transform(value, context);
|
|
251
|
+
expect(result).toBeInstanceOf(CreateUserDto);
|
|
252
|
+
expect(result.name).toBe('John');
|
|
253
|
+
});
|
|
254
|
+
it('should handle validation error with constraints', async () => {
|
|
255
|
+
class CreateUserDto {
|
|
256
|
+
}
|
|
257
|
+
__decorate([
|
|
258
|
+
(0, class_validator_1.IsString)(),
|
|
259
|
+
(0, class_validator_1.IsEmail)(),
|
|
260
|
+
__metadata("design:type", String)
|
|
261
|
+
], CreateUserDto.prototype, "email", void 0);
|
|
262
|
+
const value = { email: 'invalid' };
|
|
263
|
+
const context = {
|
|
264
|
+
dtoType: CreateUserDto,
|
|
265
|
+
};
|
|
266
|
+
try {
|
|
267
|
+
await pipe.transform(value, context);
|
|
268
|
+
fail('Should have thrown ValidationError');
|
|
269
|
+
}
|
|
270
|
+
catch (error) {
|
|
271
|
+
expect(error).toBeInstanceOf(pipe_1.ValidationError);
|
|
272
|
+
const validationError = error;
|
|
273
|
+
expect(validationError.message).toBe('Validation failed');
|
|
274
|
+
expect(validationError.errors[0].property).toBe('email');
|
|
275
|
+
}
|
|
276
|
+
});
|
|
277
|
+
it('should rethrow caught errors', async () => {
|
|
278
|
+
class CreateUserDto {
|
|
279
|
+
}
|
|
280
|
+
__decorate([
|
|
281
|
+
(0, class_validator_1.IsString)(),
|
|
282
|
+
__metadata("design:type", String)
|
|
283
|
+
], CreateUserDto.prototype, "name", void 0);
|
|
284
|
+
const value = { name: 123 };
|
|
285
|
+
const context = {
|
|
286
|
+
dtoType: CreateUserDto,
|
|
287
|
+
};
|
|
288
|
+
try {
|
|
289
|
+
await pipe.transform(value, context);
|
|
290
|
+
fail('Should have thrown error');
|
|
291
|
+
}
|
|
292
|
+
catch (error) {
|
|
293
|
+
expect(error).toBeDefined();
|
|
294
|
+
}
|
|
295
|
+
});
|
|
296
|
+
});
|
|
297
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"request-parser.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/request-parser.test.ts"],"names":[],"mappings":""}
|