@oalacea/daemon 0.7.2 → 0.7.4

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 (38) hide show
  1. package/dist/cli/commands/init.command.js +1 -1
  2. package/dist/cli/commands/init.command.js.map +1 -1
  3. package/dist/prompts/DEPS_EFFICIENCY.md +558 -0
  4. package/dist/prompts/E2E.md +491 -0
  5. package/dist/prompts/EXECUTE.md +1060 -0
  6. package/dist/prompts/INTEGRATION_API.md +484 -0
  7. package/dist/prompts/INTEGRATION_DB.md +425 -0
  8. package/dist/prompts/PERF_API.md +433 -0
  9. package/dist/prompts/PERF_DB.md +430 -0
  10. package/dist/prompts/PERF_FRONT.md +357 -0
  11. package/dist/prompts/REMEDIATION.md +482 -0
  12. package/dist/prompts/UNIT.md +260 -0
  13. package/dist/templates/README.md +221 -0
  14. package/dist/templates/k6/load-test.js +54 -0
  15. package/dist/templates/nestjs/controller.spec.ts +203 -0
  16. package/dist/templates/nestjs/e2e/api.e2e-spec.ts +451 -0
  17. package/dist/templates/nestjs/e2e/auth.e2e-spec.ts +533 -0
  18. package/dist/templates/nestjs/fixtures/test-module.ts +311 -0
  19. package/dist/templates/nestjs/guard.spec.ts +314 -0
  20. package/dist/templates/nestjs/interceptor.spec.ts +458 -0
  21. package/dist/templates/nestjs/module.spec.ts +173 -0
  22. package/dist/templates/nestjs/pipe.spec.ts +474 -0
  23. package/dist/templates/nestjs/service.spec.ts +296 -0
  24. package/dist/templates/playwright/e2e.spec.ts +61 -0
  25. package/dist/templates/rust/Cargo.toml +72 -0
  26. package/dist/templates/rust/actix-controller.test.rs +114 -0
  27. package/dist/templates/rust/axum-handler.test.rs +117 -0
  28. package/dist/templates/rust/integration.test.rs +63 -0
  29. package/dist/templates/rust/rocket-route.test.rs +106 -0
  30. package/dist/templates/rust/unit.test.rs +38 -0
  31. package/dist/templates/vitest/angular-component.test.ts +38 -0
  32. package/dist/templates/vitest/api.test.ts +51 -0
  33. package/dist/templates/vitest/component.test.ts +27 -0
  34. package/dist/templates/vitest/hook.test.ts +36 -0
  35. package/dist/templates/vitest/solid-component.test.ts +34 -0
  36. package/dist/templates/vitest/svelte-component.test.ts +33 -0
  37. package/dist/templates/vitest/vue-component.test.ts +39 -0
  38. package/package.json +2 -2
@@ -0,0 +1,474 @@
1
+ /**
2
+ * NestJS Pipe Test Template
3
+ *
4
+ * Tests for NestJS pipes following best practices:
5
+ * - Data transformation
6
+ * - Validation logic
7
+ * - Error handling
8
+ * - Custom business rules
9
+ *
10
+ * @package test
11
+ */
12
+
13
+ import { ArgumentMetadata, BadRequestException } from '@nestjs/common';
14
+ import { ValidationPipe } from './validation.pipe';
15
+ import { TransformPipe } from './transform.pipe';
16
+ import { ParseIntPipe } from './parse-int.pipe';
17
+ import { CustomValidationPipe } from './custom-validation.pipe';
18
+
19
+ describe('ValidationPipe', () => {
20
+ let pipe: ValidationPipe;
21
+
22
+ beforeEach(() => {
23
+ pipe = new ValidationPipe();
24
+ });
25
+
26
+ describe('transform', () => {
27
+ it('should return value unchanged when valid', async () => {
28
+ const value = { name: 'Test', age: 25 };
29
+ const metadata: ArgumentMetadata = {
30
+ type: 'body',
31
+ metatype: Object,
32
+ };
33
+
34
+ const result = await pipe.transform(value, metadata);
35
+
36
+ expect(result).toEqual(value);
37
+ });
38
+
39
+ it('should throw BadRequestException for invalid data', async () => {
40
+ const value = { name: '', age: -1 };
41
+ const metadata: ArgumentMetadata = {
42
+ type: 'body',
43
+ metatype: Object,
44
+ };
45
+
46
+ await expect(pipe.transform(value, metadata)).rejects.toThrow(
47
+ BadRequestException
48
+ );
49
+ });
50
+
51
+ it('should validate required fields', async () => {
52
+ const value = { age: 25 }; // missing name
53
+ const metadata: ArgumentMetadata = {
54
+ type: 'body',
55
+ metatype: Object,
56
+ };
57
+
58
+ await expect(pipe.transform(value, metadata)).rejects.toThrow();
59
+ });
60
+
61
+ it('should validate data types', async () => {
62
+ const value = { name: 'Test', age: 'not-a-number' };
63
+ const metadata: ArgumentMetadata = {
64
+ type: 'body',
65
+ metatype: Object,
66
+ };
67
+
68
+ await expect(pipe.transform(value, metadata)).rejects.toThrow();
69
+ });
70
+
71
+ it('should skip validation when whitelist is true', async () => {
72
+ pipe = new ValidationPipe({ whitelist: true });
73
+ const value = { name: 'Test', age: 25, extraField: 'should be removed' };
74
+ const metadata: ArgumentMetadata = {
75
+ type: 'body',
76
+ metatype: class TestDto {
77
+ name: string;
78
+ age: number;
79
+ },
80
+ };
81
+
82
+ const result = await pipe.transform(value, metadata);
83
+
84
+ expect(result).not.toHaveProperty('extraField');
85
+ });
86
+
87
+ it('should handle nested objects', async () => {
88
+ const value = {
89
+ name: 'Test',
90
+ address: {
91
+ street: '123 Main St',
92
+ city: 'Springfield',
93
+ },
94
+ };
95
+ const metadata: ArgumentMetadata = {
96
+ type: 'body',
97
+ metatype: Object,
98
+ };
99
+
100
+ const result = await pipe.transform(value, metadata);
101
+
102
+ expect(result).toHaveProperty('address');
103
+ expect(result.address).toHaveProperty('street');
104
+ });
105
+
106
+ it('should validate arrays', async () => {
107
+ const value = { items: [{ name: 'Item 1' }, { name: 'Item 2' }] };
108
+ const metadata: ArgumentMetadata = {
109
+ type: 'body',
110
+ metatype: Object,
111
+ };
112
+
113
+ const result = await pipe.transform(value, metadata);
114
+
115
+ expect(Array.isArray(result.items)).toBe(true);
116
+ });
117
+
118
+ it('should handle null and undefined values', async () => {
119
+ const metadata: ArgumentMetadata = {
120
+ type: 'body',
121
+ metatype: Object,
122
+ };
123
+
124
+ await expect(pipe.transform(null, metadata)).rejects.toThrow();
125
+ await expect(pipe.transform(undefined, metadata)).rejects.toThrow();
126
+ });
127
+ });
128
+
129
+ describe('error messages', () => {
130
+ it('should provide descriptive error messages', async () => {
131
+ const value = { name: '', age: -1 };
132
+ const metadata: ArgumentMetadata = {
133
+ type: 'body',
134
+ metatype: Object,
135
+ };
136
+
137
+ try {
138
+ await pipe.transform(value, metadata);
139
+ fail('Should have thrown BadRequestException');
140
+ } catch (error) {
141
+ expect(error).toBeInstanceOf(BadRequestException);
142
+ expect(error.message).toBeDefined();
143
+ }
144
+ });
145
+
146
+ it('should include field names in errors', async () => {
147
+ const value = { name: '', age: -1 };
148
+ const metadata: ArgumentMetadata = {
149
+ type: 'body',
150
+ metatype: Object,
151
+ };
152
+
153
+ try {
154
+ await pipe.transform(value, metadata);
155
+ fail('Should have thrown BadRequestException');
156
+ } catch (error) {
157
+ const responseBody = error.getResponse();
158
+ if (typeof responseBody === 'object') {
159
+ expect(responseBody).toHaveProperty('message');
160
+ }
161
+ }
162
+ });
163
+ });
164
+ });
165
+
166
+ describe('TransformPipe', () => {
167
+ let pipe: TransformPipe;
168
+
169
+ beforeEach(() => {
170
+ pipe = new TransformPipe();
171
+ });
172
+
173
+ describe('transform', () => {
174
+ it('should transform string to number', async () => {
175
+ const value = '123';
176
+ const metadata: ArgumentMetadata = {
177
+ type: 'param',
178
+ metatype: Number,
179
+ };
180
+
181
+ const result = await pipe.transform(value, metadata);
182
+
183
+ expect(result).toBe(123);
184
+ expect(typeof result).toBe('number');
185
+ });
186
+
187
+ it('should trim strings', async () => {
188
+ const value = ' test ';
189
+ const metadata: ArgumentMetadata = {
190
+ type: 'body',
191
+ metatype: String,
192
+ };
193
+
194
+ const result = await pipe.transform(value, metadata);
195
+
196
+ expect(result).toBe('test');
197
+ });
198
+
199
+ it('should transform lowercase', async () => {
200
+ pipe = new TransformPipe({ toLowerCase: true });
201
+ const value = 'HELLO WORLD';
202
+ const metadata: ArgumentMetadata = {
203
+ type: 'body',
204
+ metatype: String,
205
+ };
206
+
207
+ const result = await pipe.transform(value, metadata);
208
+
209
+ expect(result).toBe('hello world');
210
+ });
211
+
212
+ it('should transform boolean strings', async () => {
213
+ const value = 'true';
214
+ const metadata: ArgumentMetadata = {
215
+ type: 'query',
216
+ metatype: Boolean,
217
+ };
218
+
219
+ const result = await pipe.transform(value, metadata);
220
+
221
+ expect(result).toBe(true);
222
+ });
223
+
224
+ it('should transform date strings', async () => {
225
+ const value = '2024-01-01';
226
+ const metadata: ArgumentMetadata = {
227
+ type: 'body',
228
+ metatype: Date,
229
+ };
230
+
231
+ const result = await pipe.transform(value, metadata);
232
+
233
+ expect(result).toBeInstanceOf(Date);
234
+ });
235
+
236
+ it('should handle null values', async () => {
237
+ const metadata: ArgumentMetadata = {
238
+ type: 'body',
239
+ metatype: String,
240
+ };
241
+
242
+ const result = await pipe.transform(null, metadata);
243
+
244
+ expect(result).toBeNull();
245
+ });
246
+ });
247
+ });
248
+
249
+ describe('ParseIntPipe', () => {
250
+ let pipe: ParseIntPipe;
251
+
252
+ beforeEach(() => {
253
+ pipe = new ParseIntPipe();
254
+ });
255
+
256
+ describe('transform', () => {
257
+ it('should parse valid integer string', async () => {
258
+ const value = '42';
259
+ const metadata: ArgumentMetadata = {
260
+ type: 'param',
261
+ metatype: Number,
262
+ };
263
+
264
+ const result = await pipe.transform(value, metadata);
265
+
266
+ expect(result).toBe(42);
267
+ });
268
+
269
+ it('should throw BadRequestException for non-numeric string', async () => {
270
+ const value = 'not-a-number';
271
+ const metadata: ArgumentMetadata = {
272
+ type: 'param',
273
+ metatype: Number,
274
+ };
275
+
276
+ await expect(pipe.transform(value, metadata)).rejects.toThrow(
277
+ BadRequestException
278
+ );
279
+ });
280
+
281
+ it('should throw BadRequestException for float string', async () => {
282
+ const value = '42.5';
283
+ const metadata: ArgumentMetadata = {
284
+ type: 'param',
285
+ metatype: Number,
286
+ };
287
+
288
+ await expect(pipe.transform(value, metadata)).rejects.toThrow(
289
+ BadRequestException
290
+ );
291
+ });
292
+
293
+ it('should handle negative numbers', async () => {
294
+ const value = '-42';
295
+ const metadata: ArgumentMetadata = {
296
+ type: 'param',
297
+ metatype: Number,
298
+ };
299
+
300
+ const result = await pipe.transform(value, metadata);
301
+
302
+ expect(result).toBe(-42);
303
+ });
304
+
305
+ it('should handle zero', async () => {
306
+ const value = '0';
307
+ const metadata: ArgumentMetadata = {
308
+ type: 'param',
309
+ metatype: Number,
310
+ };
311
+
312
+ const result = await pipe.transform(value, metadata);
313
+
314
+ expect(result).toBe(0);
315
+ });
316
+
317
+ it('should throw exception for empty string', async () => {
318
+ const value = '';
319
+ const metadata: ArgumentMetadata = {
320
+ type: 'param',
321
+ metatype: Number,
322
+ };
323
+
324
+ await expect(pipe.transform(value, metadata)).rejects.toThrow(
325
+ BadRequestException
326
+ );
327
+ });
328
+ });
329
+
330
+ describe('custom error messages', () => {
331
+ it('should include field name in error', async () => {
332
+ pipe = new ParseIntPipe('fieldName');
333
+ const value = 'invalid';
334
+ const metadata: ArgumentMetadata = {
335
+ type: 'param',
336
+ metatype: Number,
337
+ data: 'fieldName',
338
+ };
339
+
340
+ try {
341
+ await pipe.transform(value, metadata);
342
+ fail('Should have thrown BadRequestException');
343
+ } catch (error) {
344
+ expect(error.message).toContain('fieldName');
345
+ }
346
+ });
347
+ });
348
+ });
349
+
350
+ describe('CustomValidationPipe', () => {
351
+ let pipe: CustomValidationPipe;
352
+
353
+ describe('email validation', () => {
354
+ beforeEach(() => {
355
+ pipe = new CustomValidationPipe();
356
+ });
357
+
358
+ it('should accept valid email', async () => {
359
+ const value = { email: 'test@example.com' };
360
+ const metadata: ArgumentMetadata = {
361
+ type: 'body',
362
+ metatype: Object,
363
+ };
364
+
365
+ const result = await pipe.transform(value, metadata);
366
+
367
+ expect(result.email).toBe('test@example.com');
368
+ });
369
+
370
+ it('should reject invalid email', async () => {
371
+ const value = { email: 'not-an-email' };
372
+ const metadata: ArgumentMetadata = {
373
+ type: 'body',
374
+ metatype: Object,
375
+ };
376
+
377
+ await expect(pipe.transform(value, metadata)).rejects.toThrow();
378
+ });
379
+
380
+ it('should reject empty email', async () => {
381
+ const value = { email: '' };
382
+ const metadata: ArgumentMetadata = {
383
+ type: 'body',
384
+ metatype: Object,
385
+ };
386
+
387
+ await expect(pipe.transform(value, metadata)).rejects.toThrow();
388
+ });
389
+ });
390
+
391
+ describe('password validation', () => {
392
+ it('should enforce password complexity', async () => {
393
+ pipe = new CustomValidationPipe({
394
+ passwordMinLength: 8,
395
+ requireUppercase: true,
396
+ requireLowercase: true,
397
+ requireNumbers: true,
398
+ requireSpecialChars: true,
399
+ });
400
+
401
+ const value = { password: 'Simple123' }; // Missing special char
402
+ const metadata: ArgumentMetadata = {
403
+ type: 'body',
404
+ metatype: Object,
405
+ };
406
+
407
+ await expect(pipe.transform(value, metadata)).rejects.toThrow();
408
+ });
409
+
410
+ it('should accept complex password', async () => {
411
+ pipe = new CustomValidationPipe({
412
+ passwordMinLength: 8,
413
+ requireUppercase: true,
414
+ requireLowercase: true,
415
+ requireNumbers: true,
416
+ requireSpecialChars: true,
417
+ });
418
+
419
+ const value = { password: 'Complex123!' };
420
+ const metadata: ArgumentMetadata = {
421
+ type: 'body',
422
+ metatype: Object,
423
+ };
424
+
425
+ const result = await pipe.transform(value, metadata);
426
+
427
+ expect(result.password).toBe('Complex123!');
428
+ });
429
+ });
430
+
431
+ describe('custom business rules', () => {
432
+ it('should validate custom rules', async () => {
433
+ pipe = new CustomValidationPipe({
434
+ customRules: [
435
+ {
436
+ field: 'age',
437
+ validate: (value) => value >= 18,
438
+ message: 'Age must be at least 18',
439
+ },
440
+ ],
441
+ });
442
+
443
+ const value = { age: 15 };
444
+ const metadata: ArgumentMetadata = {
445
+ type: 'body',
446
+ metatype: Object,
447
+ };
448
+
449
+ await expect(pipe.transform(value, metadata)).rejects.toThrow();
450
+ });
451
+
452
+ it('should pass valid custom rules', async () => {
453
+ pipe = new CustomValidationPipe({
454
+ customRules: [
455
+ {
456
+ field: 'age',
457
+ validate: (value) => value >= 18,
458
+ message: 'Age must be at least 18',
459
+ },
460
+ ],
461
+ });
462
+
463
+ const value = { age: 25 };
464
+ const metadata: ArgumentMetadata = {
465
+ type: 'body',
466
+ metatype: Object,
467
+ };
468
+
469
+ const result = await pipe.transform(value, metadata);
470
+
471
+ expect(result.age).toBe(25);
472
+ });
473
+ });
474
+ });