@lenne.tech/cli 1.0.0 → 1.0.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.
Files changed (25) hide show
  1. package/build/commands/claude/install-commands.js +332 -0
  2. package/build/commands/claude/install-skills.js +5 -1
  3. package/build/commands/server/add-property.js +22 -41
  4. package/build/extensions/server.js +142 -46
  5. package/build/templates/claude-commands/code-cleanup.md +82 -0
  6. package/build/templates/claude-commands/mr-description-clipboard.md +48 -0
  7. package/build/templates/claude-commands/mr-description.md +33 -0
  8. package/build/templates/claude-commands/sec-review.md +62 -0
  9. package/build/templates/claude-commands/skill-optimize.md +140 -0
  10. package/build/templates/claude-commands/test-generate.md +45 -0
  11. package/build/templates/claude-skills/nest-server-generator/SKILL.md +372 -1314
  12. package/build/templates/claude-skills/nest-server-generator/configuration.md +279 -0
  13. package/build/templates/claude-skills/nest-server-generator/declare-keyword-warning.md +124 -0
  14. package/build/templates/claude-skills/nest-server-generator/description-management.md +217 -0
  15. package/build/templates/claude-skills/nest-server-generator/examples.md +131 -5
  16. package/build/templates/claude-skills/nest-server-generator/quality-review.md +855 -0
  17. package/build/templates/claude-skills/nest-server-generator/reference.md +67 -13
  18. package/build/templates/claude-skills/nest-server-generator/security-rules.md +358 -0
  19. package/build/templates/claude-skills/story-tdd/SKILL.md +1173 -0
  20. package/build/templates/claude-skills/story-tdd/code-quality.md +266 -0
  21. package/build/templates/claude-skills/story-tdd/database-indexes.md +173 -0
  22. package/build/templates/claude-skills/story-tdd/examples.md +1332 -0
  23. package/build/templates/claude-skills/story-tdd/reference.md +1180 -0
  24. package/build/templates/claude-skills/story-tdd/security-review.md +299 -0
  25. package/package.json +1 -1
@@ -0,0 +1,855 @@
1
+ ---
2
+ name: nest-server-generator-quality-review
3
+ version: 1.0.0
4
+ description: Comprehensive quality review guidelines before creating final report
5
+ ---
6
+
7
+ # Phase 8: Pre-Report Quality Review
8
+
9
+ **CRITICAL**: Before creating the final report, you MUST perform a comprehensive quality review:
10
+
11
+ ## Step 1: Identify All Changes
12
+
13
+ Use git to identify all created and modified files:
14
+
15
+ ```bash
16
+ git status --short
17
+ git diff --name-only
18
+ ```
19
+
20
+ For each file, review:
21
+ - All newly created files
22
+ - All modified files
23
+ - File structure and organization
24
+
25
+ ## Step 2: Test Management
26
+
27
+ **CRITICAL**: Ensure tests are created/updated for all changes:
28
+
29
+ ### Step 2.1: Analyze Existing Tests FIRST
30
+
31
+ **BEFORE creating or modifying ANY tests, you MUST thoroughly analyze existing tests**:
32
+
33
+ 1. **Identify all existing test files**:
34
+ ```bash
35
+ # List all test directories and files
36
+ ls -la tests/
37
+ ls -la tests/modules/
38
+ find tests -name "*.e2e-spec.ts" -type f
39
+ ```
40
+
41
+ 2. **Read multiple existing test files completely**:
42
+ ```bash
43
+ # Read at least 2-3 different module tests to understand patterns
44
+ cat tests/modules/user.e2e-spec.ts
45
+ cat tests/modules/<another-module>.e2e-spec.ts
46
+
47
+ # Also check the common and project test files
48
+ cat tests/common.e2e-spec.ts
49
+ cat tests/project.e2e-spec.ts
50
+ ```
51
+
52
+ 3. **CRITICAL: Understand the TestHelper thoroughly**:
53
+
54
+ **Before creating any tests, you MUST understand the TestHelper from @lenne.tech/nest-server**:
55
+
56
+ ```bash
57
+ # Read the TestHelper source code to understand its capabilities
58
+ cat node_modules/@lenne.tech/nest-server/src/test/test.helper.ts
59
+ ```
60
+
61
+ **Analyze the TestHelper to understand**:
62
+ - **Available methods**: What methods does TestHelper provide?
63
+ - **Configuration options**: How can TestHelper be configured?
64
+ - **GraphQL support**: How to use `graphQl()` method? What parameters does it accept?
65
+ - **REST support**: How to use `rest()` method? What parameters does it accept?
66
+ - **Authentication**: How does TestHelper handle tokens and authentication?
67
+ - **Request building**: How are requests constructed? What options are available?
68
+ - **Response handling**: How are responses processed? What format is returned?
69
+ - **Error handling**: How does TestHelper handle errors and failures?
70
+ - **Helper utilities**: What additional utilities are available?
71
+
72
+ **Document your findings**:
73
+ ```typescript
74
+ // Example: Understanding TestHelper.graphQl()
75
+ // Method signature: graphQl(options: GraphQLOptions, config?: RequestConfig)
76
+ // GraphQLOptions: { name, type (QUERY/MUTATION), arguments, fields }
77
+ // RequestConfig: { token, statusCode, headers }
78
+ // Returns: Parsed response data or error
79
+
80
+ // Example: Understanding TestHelper.rest()
81
+ // Method signature: rest(method: HttpMethod, path: string, options?: RestOptions)
82
+ // HttpMethod: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'
83
+ // RestOptions: { body, token, statusCode, headers }
84
+ // Returns: Response data or error
85
+ ```
86
+
87
+ **Common TestHelper patterns to understand**:
88
+ - How to execute GraphQL queries/mutations with `graphQl()`
89
+ - How to execute REST requests with `rest()`
90
+ - How to pass authentication tokens (same for both methods)
91
+ - How to handle expected errors (statusCode parameter)
92
+ - How to work with response data
93
+ - How to structure test data
94
+ - When to use GraphQL vs REST methods
95
+
96
+ **Only after fully understanding TestHelper, proceed to next step.**
97
+
98
+ 4. **Understand the testing approach used**:
99
+ - Which test framework? (Jest, Mocha, etc.)
100
+ - Which testing utilities? (@lenne.tech/nest-server testHelper, custom helpers)
101
+ - How is the test app initialized? (beforeAll setup)
102
+ - How are test users/auth handled?
103
+ - How is test data created and cleaned up?
104
+ - What assertion library? (expect, should, etc.)
105
+ - Are there custom matchers?
106
+
107
+ 5. **Document the patterns you observe**:
108
+ - **Import patterns**: Which modules are imported? In what order?
109
+ - **Setup patterns**: How is beforeAll/beforeEach structured?
110
+ - **Auth patterns**: How do tests authenticate? Token handling?
111
+ - **Test structure**: Describe blocks organization? Test naming conventions?
112
+ - **CRUD patterns**: How are create/read/update/delete tested?
113
+ - **Assertion patterns**: What assertions are used? How detailed?
114
+ - **Cleanup patterns**: How is afterAll/afterEach structured?
115
+ - **Error testing**: How are failures/validations tested?
116
+
117
+ 6. **Verify existing tests run successfully**:
118
+ ```bash
119
+ # Run existing tests to ensure they pass
120
+ npm run test:e2e
121
+
122
+ # If any fail, understand why before proceeding
123
+ # Your new/modified tests MUST NOT break existing tests
124
+ ```
125
+
126
+ 7. **Create a mental checklist**:
127
+ - [ ] I have read and understand the TestHelper source code
128
+ - [ ] I understand TestHelper methods and configuration
129
+ - [ ] I understand how to use graphQl() method (GraphQL queries/mutations)
130
+ - [ ] I understand how to use rest() method (REST endpoints)
131
+ - [ ] I understand when to use graphQl() vs rest()
132
+ - [ ] I understand TestHelper authentication and error handling
133
+ - [ ] I understand which test helpers/utilities are used
134
+ - [ ] I understand the authentication/authorization pattern
135
+ - [ ] I understand the test data lifecycle (create/cleanup)
136
+ - [ ] I understand the assertion patterns
137
+ - [ ] I understand the error testing approach
138
+ - [ ] All existing tests pass before I make changes
139
+
140
+ **Only after completing this analysis, proceed to create or modify tests.**
141
+
142
+ ### Step 2.1.1: Understanding Permissions and User Rights in Tests
143
+
144
+ **CRITICAL**: Before creating tests, you MUST understand the 3-layer permission system:
145
+
146
+ **Important Definitions**:
147
+
148
+ - **Admin User**: A user whose `roles` array contains `'admin'`
149
+ ```typescript
150
+ // Example admin user
151
+ {
152
+ id: '123',
153
+ email: 'admin@test.com',
154
+ roles: ['admin', 'user'] // ← Contains 'admin'
155
+ }
156
+ ```
157
+
158
+ - **Creator**: The user who created an object, identified by matching IDs
159
+ ```typescript
160
+ // User who created the object
161
+ const user = { id: 'user-123', email: 'creator@test.com' };
162
+
163
+ // Object created by this user
164
+ const product = {
165
+ id: 'product-456',
166
+ name: 'Test Product',
167
+ createdBy: 'user-123' // ← Matches user.id → This user is the CREATOR
168
+ };
169
+
170
+ // Different user (NOT the creator)
171
+ const otherUser = { id: 'user-789', email: 'other@test.com' };
172
+ // otherUser.id !== product.createdBy → NOT the creator!
173
+ ```
174
+
175
+ **The Three Permission Layers**:
176
+
177
+ 1. **Controller/Resolver Layer** (`@Roles()` decorator):
178
+ - Controls WHO can call the endpoint
179
+ - Example: `@Roles(RoleEnum.ADMIN)` → Only admins can call this endpoint
180
+ - Example: `@Roles(RoleEnum.S_USER)` → All signed-in users can call
181
+
182
+ 2. **Service Layer** (`serviceOptions.roles` parameter):
183
+ - Controls what permissions are checked during service processing
184
+ - Example: Update/Delete often require `[RoleEnum.ADMIN, RoleEnum.S_CREATOR]`
185
+ - The creator can update/delete their own items
186
+
187
+ 3. **Model Layer** (`securityCheck()` method):
188
+ - Controls WHAT data is returned to the user
189
+ - Standard implementation:
190
+ ```typescript
191
+ securityCheck(user: User, force?: boolean) {
192
+ // Admins see everything (user.roles contains 'admin')
193
+ if (force || user?.hasRole(RoleEnum.ADMIN)) {
194
+ return this;
195
+ }
196
+ // Only creator can see their own data (user.id === this.createdBy)
197
+ if (!equalIds(user, this.createdBy)) {
198
+ return undefined; // Non-creator gets nothing!
199
+ }
200
+ return this;
201
+ }
202
+ ```
203
+ - **Key checks**:
204
+ - `user?.hasRole(RoleEnum.ADMIN)` → Returns `true` if `user.roles.includes('admin')`
205
+ - `equalIds(user, this.createdBy)` → Returns `true` if `user.id === this.createdBy`
206
+
207
+ **Default Permission Behavior**:
208
+ - **Create**: Usually accessible to signed-in users (`RoleEnum.S_USER`)
209
+ - **Read/List**: Usually accessible to signed-in users, but securityCheck filters results
210
+ - **Update**: Only ADMIN or CREATOR (via `serviceOptions.roles` check)
211
+ - **Delete**: Only ADMIN or CREATOR (via `serviceOptions.roles` check)
212
+
213
+ **Analyzing Permissions Before Creating Tests**:
214
+
215
+ Before writing tests, check these 3 locations:
216
+
217
+ 1. **Check Controller/Resolver decorators**:
218
+ ```typescript
219
+ // In product.resolver.ts
220
+ @Roles(RoleEnum.ADMIN) // ← WHO can call this?
221
+ @Query(() => Product)
222
+ async getProduct(@Args('id') id: string) { ... }
223
+
224
+ @Roles(RoleEnum.S_USER) // ← All signed-in users
225
+ @Mutation(() => Product)
226
+ async createProduct(@Args('input') input: ProductCreateInput) { ... }
227
+ ```
228
+
229
+ 2. **Check Model/Object `@Restricted` decorators**:
230
+ ```typescript
231
+ // In product.model.ts
232
+ @Restricted(RoleEnum.ADMIN) // ← Model-level restriction
233
+ export class Product extends CoreModel {
234
+
235
+ @Restricted(RoleEnum.ADMIN) // ← Property-level restriction
236
+ @UnifiedField()
237
+ internalNotes?: string;
238
+ }
239
+ ```
240
+
241
+ 3. **Check Model `securityCheck()` logic**:
242
+ ```typescript
243
+ // In product.model.ts
244
+ securityCheck(user: User, force?: boolean) {
245
+ // Admin check: user.roles contains 'admin'
246
+ if (force || user?.hasRole(RoleEnum.ADMIN)) {
247
+ return this; // Admin sees all
248
+ }
249
+
250
+ // Custom logic: Allow public products for everyone
251
+ if (this.isPublic) {
252
+ return this;
253
+ }
254
+
255
+ // Creator check: user.id === this.createdBy
256
+ if (!equalIds(user, this.createdBy)) {
257
+ return undefined; // Non-creator gets nothing
258
+ }
259
+ return this; // Creator sees their own product
260
+ }
261
+ ```
262
+
263
+ **Creating Appropriate Test Users**:
264
+
265
+ Based on permission analysis, create appropriate test users:
266
+
267
+ ```typescript
268
+ describe('Product Module', () => {
269
+ let testHelper: TestHelper;
270
+ let adminToken: string;
271
+ let userToken: string;
272
+ let otherUserToken: string;
273
+ let createdProductId: string;
274
+
275
+ beforeAll(async () => {
276
+ testHelper = new TestHelper(app);
277
+
278
+ // Admin user (user.roles contains 'admin')
279
+ const adminAuth = await testHelper.graphQl({
280
+ name: 'signIn',
281
+ type: TestGraphQLType.MUTATION,
282
+ arguments: { email: 'admin@test.com', password: 'admin' },
283
+ fields: ['token', 'user { id email roles }']
284
+ });
285
+ adminToken = adminAuth.token;
286
+ // adminAuth.user.roles = ['admin', 'user'] ← Contains 'admin'
287
+
288
+ // Regular user (will be the creator of test objects)
289
+ const userAuth = await testHelper.graphQl({
290
+ name: 'signIn',
291
+ type: TestGraphQLType.MUTATION,
292
+ arguments: { email: 'user@test.com', password: 'user' },
293
+ fields: ['token', 'user { id email roles }']
294
+ });
295
+ userToken = userAuth.token;
296
+ // When this user creates an object → object.createdBy = userAuth.user.id
297
+
298
+ // Another regular user (will NOT be the creator)
299
+ const otherUserAuth = await testHelper.graphQl({
300
+ name: 'signIn',
301
+ type: TestGraphQLType.MUTATION,
302
+ arguments: { email: 'other@test.com', password: 'other' },
303
+ fields: ['token', 'user { id email roles }']
304
+ });
305
+ otherUserToken = otherUserAuth.token;
306
+ // otherUserAuth.user.id !== object.createdBy → NOT the creator
307
+ });
308
+ });
309
+ ```
310
+
311
+ **Test Structure Based on Permissions**:
312
+
313
+ ```typescript
314
+ describe('Product Module', () => {
315
+ // ... setup with adminToken, userToken, otherUserToken
316
+
317
+ describe('Create Product', () => {
318
+ it('should create product as regular user', async () => {
319
+ const result = await testHelper.graphQl({
320
+ name: 'createProduct',
321
+ type: TestGraphQLType.MUTATION,
322
+ arguments: { input: { name: 'Test Product', price: 99.99 } },
323
+ fields: ['id', 'name', 'createdBy { id }']
324
+ }, { token: userToken }); // ← Created by userToken
325
+
326
+ expect(result.name).toBe('Test Product');
327
+ // result.createdBy.id now equals userAuth.user.id
328
+ // → userToken is the CREATOR of this product
329
+ createdProductId = result.id;
330
+ });
331
+ });
332
+
333
+ describe('Update Product', () => {
334
+ it('should update product as creator', async () => {
335
+ const result = await testHelper.graphQl({
336
+ name: 'updateProduct',
337
+ type: TestGraphQLType.MUTATION,
338
+ arguments: {
339
+ id: createdProductId,
340
+ input: { price: 89.99 }
341
+ },
342
+ fields: ['id', 'price']
343
+ }, { token: userToken }); // ← Creator: userAuth.user.id === product.createdBy
344
+
345
+ expect(result.price).toBe(89.99);
346
+ });
347
+
348
+ it('should update product as admin', async () => {
349
+ const result = await testHelper.graphQl({
350
+ name: 'updateProduct',
351
+ type: TestGraphQLType.MUTATION,
352
+ arguments: {
353
+ id: createdProductId,
354
+ input: { price: 79.99 }
355
+ },
356
+ fields: ['id', 'price']
357
+ }, { token: adminToken }); // ← Admin: adminAuth.user.roles contains 'admin'
358
+
359
+ expect(result.price).toBe(79.99);
360
+ });
361
+
362
+ it('should fail to update product as non-creator', async () => {
363
+ const result = await testHelper.graphQl({
364
+ name: 'updateProduct',
365
+ type: TestGraphQLType.MUTATION,
366
+ arguments: {
367
+ id: createdProductId,
368
+ input: { price: 69.99 }
369
+ },
370
+ fields: ['id']
371
+ }, { token: otherUserToken, statusCode: 403 }); // ← Not creator: otherUserAuth.user.id !== product.createdBy
372
+
373
+ expect(result.errors).toBeDefined();
374
+ });
375
+ });
376
+
377
+ describe('Delete Product', () => {
378
+ it('should delete product as creator', async () => {
379
+ // First create a new product to delete
380
+ const created = await testHelper.graphQl({
381
+ name: 'createProduct',
382
+ type: TestGraphQLType.MUTATION,
383
+ arguments: { input: { name: 'To Delete', price: 50 } },
384
+ fields: ['id']
385
+ }, { token: userToken });
386
+
387
+ // Delete as creator
388
+ const result = await testHelper.graphQl({
389
+ name: 'deleteProduct',
390
+ type: TestGraphQLType.MUTATION,
391
+ arguments: { id: created.id },
392
+ fields: ['id']
393
+ }, { token: userToken }); // ← Creator: userAuth.user.id === created.createdBy
394
+
395
+ expect(result.id).toBe(created.id);
396
+ });
397
+
398
+ it('should fail to delete product as non-creator', async () => {
399
+ const result = await testHelper.graphQl({
400
+ name: 'deleteProduct',
401
+ type: TestGraphQLType.MUTATION,
402
+ arguments: { id: createdProductId },
403
+ fields: ['id']
404
+ }, { token: otherUserToken, statusCode: 403 }); // ← Not creator: otherUserAuth.user.id !== product.createdBy
405
+
406
+ expect(result.errors).toBeDefined();
407
+ });
408
+
409
+ it('should delete any product as admin', async () => {
410
+ const result = await testHelper.graphQl({
411
+ name: 'deleteProduct',
412
+ type: TestGraphQLType.MUTATION,
413
+ arguments: { id: createdProductId },
414
+ fields: ['id']
415
+ }, { token: adminToken }); // ← Admin: adminAuth.user.roles contains 'admin'
416
+
417
+ expect(result.id).toBe(createdProductId);
418
+ });
419
+ });
420
+ });
421
+ ```
422
+
423
+ **Permission Testing Checklist**:
424
+
425
+ Before creating tests, verify:
426
+
427
+ - [ ] I have checked the `@Roles()` decorators in controllers/resolvers
428
+ - [ ] I have checked the `@Restricted()` decorators in models/objects
429
+ - [ ] I have reviewed the `securityCheck()` logic in models
430
+ - [ ] I understand who can CREATE items (usually S_USER)
431
+ - [ ] I understand who can READ items (S_USER + securityCheck filtering)
432
+ - [ ] I understand who can UPDATE items (usually ADMIN + S_CREATOR)
433
+ - [ ] I understand who can DELETE items (usually ADMIN + S_CREATOR)
434
+ - [ ] I have created appropriate test users (admin, creator, non-creator)
435
+ - [ ] My tests use the CREATOR token (user.id === object.createdBy) for update/delete operations
436
+ - [ ] My tests verify that non-creators (user.id !== object.createdBy) CANNOT update/delete
437
+ - [ ] My tests verify that admins (user.roles contains 'admin') CAN update/delete everything
438
+
439
+ **Common Permission Test Patterns**:
440
+
441
+ 1. **Test with creator** (user.id === object.createdBy) → Should succeed
442
+ 2. **Test with admin** (user.roles contains 'admin') → Should succeed
443
+ 3. **Test with other user** (user.id !== object.createdBy) → Should fail (403)
444
+
445
+ **Only after understanding permissions, proceed to create tests.**
446
+
447
+ ### Step 2.2: For Newly Created Modules
448
+
449
+ **CRITICAL: Follow the correct test folder structure**:
450
+
451
+ The project uses a specific test organization:
452
+
453
+ 1. **Module tests** (for modules in `src/server/modules/`):
454
+ ```
455
+ tests/modules/<module-name>.e2e-spec.ts
456
+ ```
457
+ - Each module gets its own test file directly in `tests/modules/`
458
+ - Examples: `tests/modules/user.e2e-spec.ts`, `tests/modules/book.e2e-spec.ts`
459
+
460
+ 2. **Common tests** (for common functionality in `src/server/common/`):
461
+ ```
462
+ tests/common.e2e-spec.ts
463
+ ```
464
+ - All common functionality (enums, objects, helpers) tested here
465
+ - Single file for all common-related tests
466
+
467
+ 3. **Project tests** (for everything else - root level, config, etc.):
468
+ ```
469
+ tests/project.e2e-spec.ts
470
+ ```
471
+ - General project-level tests
472
+ - Configuration tests
473
+ - Integration tests
474
+
475
+ **Determine correct test location**:
476
+
477
+ ```bash
478
+ # BEFORE creating a test, ask yourself:
479
+ # - Is this a module in src/server/modules/? → tests/modules/<name>.e2e-spec.ts
480
+ # - Is this common functionality? → Add to tests/common.e2e-spec.ts
481
+ # - Is this project-level? → Add to tests/project.e2e-spec.ts
482
+
483
+ # Check existing test structure to confirm:
484
+ ls -la tests/
485
+ ls tests/modules/
486
+ ```
487
+
488
+ **Create new test files** for modules following the patterns you identified:
489
+
490
+ ```bash
491
+ # For a new module (e.g., Book)
492
+ tests/modules/book.e2e-spec.ts
493
+ ```
494
+
495
+ **IMPORTANT**: Your new test file MUST:
496
+ 1. **Match the exact structure** of existing test files
497
+ 2. **Use the same imports** as existing tests
498
+ 3. **Follow the same setup/cleanup pattern** (beforeAll, afterAll)
499
+ 4. **Use the same test helpers/utilities** you observed
500
+ 5. **Follow the same authentication pattern**
501
+ 6. **Use the same assertion style**
502
+ 7. **Follow the same naming conventions** for describe/it blocks
503
+
504
+ **Each new test file must include**:
505
+ 1. All CRUD operations (create, find all, find by ID, update, delete)
506
+ 2. Authorization tests (unauthorized should fail, authorized should succeed)
507
+ 3. Required field validation (missing required fields should fail)
508
+ 4. Proper test data setup and cleanup (beforeAll, afterAll)
509
+ 5. Tests for any custom methods or relationships
510
+
511
+ **Ensure all prerequisites are met by analyzing existing tests**:
512
+
513
+ Before writing test code, identify ALL prerequisites from existing test files:
514
+
515
+ ```bash
516
+ # Read an existing module test to understand prerequisites
517
+ cat tests/modules/user.e2e-spec.ts
518
+ ```
519
+
520
+ **Common prerequisites to check**:
521
+ 1. **Test data dependencies**:
522
+ - Does the module reference other modules? (e.g., Book → User for borrowedBy)
523
+ - Do you need to create related test data first?
524
+ - Example: To test Book with borrowedBy: User, create test User first
525
+
526
+ 2. **Authentication requirements**:
527
+ - What roles/permissions are needed?
528
+ - Do test users need to be created with specific roles?
529
+ - Example: Admin user for create operations, regular user for read operations
530
+
531
+ 3. **Database setup**:
532
+ - Are there database constraints or required collections?
533
+ - Do embedded objects or enums need to exist?
534
+
535
+ 4. **Configuration**:
536
+ - Are environment variables or config values needed?
537
+ - Example: JWT secrets, database connections
538
+
539
+ **Pattern from existing tests**:
540
+ ```typescript
541
+ // Example structure you should follow:
542
+ beforeAll(async () => {
543
+ // 1. Initialize test app/module
544
+ // 2. Set up database connection
545
+ // 3. Create prerequisite test data (users, roles, etc.)
546
+ // 4. Authenticate and get tokens
547
+ });
548
+
549
+ describe('Module Tests', () => {
550
+ // Tests here
551
+ });
552
+
553
+ afterAll(async () => {
554
+ // 1. Delete created test data (in reverse order)
555
+ // 2. Clean up connections
556
+ // 3. Close app
557
+ });
558
+ ```
559
+
560
+ **CRITICAL**: Look at how existing tests handle prerequisites and replicate the exact same approach.
561
+
562
+ ### Step 2.3: For Modified Existing Modules
563
+
564
+ **Update existing test files** when you modify modules:
565
+
566
+ 1. **FIRST: Read the existing test file completely**:
567
+ ```bash
568
+ # Find and read the test file for the module you modified
569
+ find tests -name "*<module-name>*.e2e-spec.ts"
570
+ cat tests/modules/<module-name>.e2e-spec.ts
571
+ ```
572
+
573
+ 2. **Understand what the existing tests cover**:
574
+ - Which operations are tested?
575
+ - Which properties are validated?
576
+ - What edge cases are covered?
577
+ - How is test data structured?
578
+
579
+ 3. **Run existing tests to ensure they pass BEFORE your changes**:
580
+ ```bash
581
+ npm run test:e2e
582
+ ```
583
+
584
+ 4. **Review and update tests**:
585
+ - **Added properties**: Add tests verifying new properties work correctly
586
+ - **Changed validation**: Update tests to reflect new validation rules
587
+ - **Added relationships**: Add tests for new references/embedded objects
588
+ - **Changed required fields**: Update CreateInput tests accordingly
589
+ - **Removed properties**: Remove related test assertions
590
+
591
+ 5. **Verify test coverage**:
592
+ - All new properties are tested
593
+ - Changed behavior is verified
594
+ - Edge cases are covered
595
+ - Authorization still works correctly
596
+
597
+ 6. **Run tests again to ensure your changes don't break anything**:
598
+ ```bash
599
+ npm run test:e2e
600
+ ```
601
+
602
+ ## Step 3: Compare with Existing Code
603
+
604
+ **Compare generated code with existing project code**:
605
+
606
+ 1. **Read existing similar modules** to understand project patterns:
607
+ ```bash
608
+ # Example: If you created a User module, check existing modules
609
+ ls src/server/modules/
610
+ ```
611
+
612
+ 2. **Check for consistency**:
613
+ - Code style (indentation, spacing, formatting)
614
+ - Import ordering and organization
615
+ - Naming conventions (camelCase, PascalCase, kebab-case)
616
+ - File structure and directory organization
617
+ - Comment style and documentation
618
+ - Decorator usage (@Field, @Prop, etc.)
619
+ - Error handling patterns
620
+ - Validation patterns
621
+
622
+ 3. **Review property ordering**:
623
+ - Verify alphabetical order in models
624
+ - Verify alphabetical order in inputs
625
+ - Verify alphabetical order in outputs
626
+ - Check decorator consistency
627
+
628
+ ## Step 4: Critical Analysis
629
+
630
+ **Analyze each file critically**:
631
+
632
+ 1. **Style consistency**:
633
+ - Does the code match the project's existing style?
634
+ - Are imports grouped and ordered correctly?
635
+ - Is indentation consistent with the project?
636
+ - Are naming conventions followed?
637
+
638
+ 2. **Structural consistency**:
639
+ - Are decorators in the same order as existing code?
640
+ - Is the file structure identical to existing modules?
641
+ - Are descriptions formatted the same way?
642
+ - Are relationships implemented consistently?
643
+
644
+ 3. **Code quality**:
645
+ - Are there any redundant imports?
646
+ - Are there any missing imports?
647
+ - Are descriptions meaningful and complete?
648
+ - Are TypeScript types correctly used?
649
+
650
+ 4. **Best practices**:
651
+ - Are required fields properly marked?
652
+ - Are nullable fields correctly configured?
653
+ - Are references properly typed?
654
+ - Are arrays correctly configured?
655
+
656
+ ## Step 5: Automated Optimizations
657
+
658
+ **Apply automatic improvements**:
659
+
660
+ 1. **Fix import ordering**:
661
+ - External imports first (alphabetically)
662
+ - @lenne.tech/nest-server imports next
663
+ - Local imports last (alphabetically by path depth)
664
+
665
+ 2. **Fix property ordering**:
666
+ - Reorder all properties alphabetically in models
667
+ - Reorder all properties alphabetically in inputs
668
+ - Reorder all properties alphabetically in outputs
669
+
670
+ 3. **Fix formatting**:
671
+ - Ensure consistent indentation
672
+ - Remove extra blank lines
673
+ - Add missing blank lines between sections
674
+
675
+ 4. **Fix descriptions**:
676
+ - Ensure all follow "ENGLISH (DEUTSCH)" format
677
+ - Add missing descriptions
678
+ - Improve unclear descriptions
679
+
680
+ 5. **Fix common patterns**:
681
+ - Standardize decorator usage
682
+ - Standardize validation patterns
683
+ - Standardize error handling
684
+
685
+ ## Step 6: Pre-Report Testing
686
+
687
+ **MANDATORY**: Run all tests before reporting:
688
+
689
+ ```bash
690
+ # Run TypeScript compilation
691
+ npm run build
692
+
693
+ # Run linting
694
+ npm run lint
695
+
696
+ # Run all tests
697
+ npm run test:e2e
698
+
699
+ # If any fail, fix issues and repeat
700
+ ```
701
+
702
+ **If tests fail**:
703
+ 1. Analyze the error
704
+ 2. Fix the issue
705
+ 3. Re-run tests
706
+ 4. Repeat until all tests pass
707
+
708
+ ### Debugging Failed Tests - Important Guidelines
709
+
710
+ **When tests fail, use systematic debugging with console.log statements:**
711
+
712
+ 1. **Add debug messages in Controllers/Resolvers**:
713
+ ```typescript
714
+ // In controller/resolver - BEFORE service call
715
+ console.log('🔵 [Controller] createProduct - Input:', input);
716
+ console.log('🔵 [Controller] createProduct - User:', serviceOptions?.user);
717
+
718
+ const result = await this.productService.create(input, serviceOptions);
719
+
720
+ // AFTER service call
721
+ console.log('🔵 [Controller] createProduct - Result:', result);
722
+ ```
723
+
724
+ 2. **Add debug messages in Services**:
725
+ ```typescript
726
+ // In service method
727
+ console.log('🟢 [Service] create - Input:', input);
728
+ console.log('🟢 [Service] create - ServiceOptions:', serviceOptions);
729
+
730
+ const created = await super.create(input, serviceOptions);
731
+
732
+ console.log('🟢 [Service] create - Created:', created);
733
+ ```
734
+
735
+ 3. **Understand the permissions system**:
736
+ - **Controllers/Resolvers**: `@Roles()` decorator controls WHO can call the endpoint
737
+ - **Services**: `serviceOptions.roles` controls what the service checks during processing
738
+ - **Models**: `securityCheck()` method determines what data is returned to the user
739
+
740
+ 4. **Default permission behavior**:
741
+ - Only **Admin users** (user.roles contains 'admin') OR the **creator** (user.id === object.createdBy) of an element can access it
742
+ - This is enforced in the `securityCheck()` method in models:
743
+ ```typescript
744
+ securityCheck(user: User, force?: boolean) {
745
+ // Admin: user.roles contains 'admin'
746
+ if (force || user?.hasRole(RoleEnum.ADMIN)) {
747
+ return this; // Admin sees everything
748
+ }
749
+ // Creator: user.id === this.createdBy
750
+ if (!equalIds(user, this.createdBy)) {
751
+ return undefined; // Non-creator (user.id !== this.createdBy) gets nothing
752
+ }
753
+ return this; // Creator sees their own data
754
+ }
755
+ ```
756
+
757
+ 5. **Debugging strategy for permission issues**:
758
+
759
+ **Step 1**: Run failing test with Admin user first
760
+ ```typescript
761
+ // In test setup
762
+ const adminToken = await testHelper.signIn('admin@test.com', 'admin-password');
763
+
764
+ // Use admin token in test
765
+ const result = await testHelper.graphQl({...}, { token: adminToken });
766
+ ```
767
+
768
+ **Step 2**: Analyze results
769
+ - ✅ **Works with Admin, fails with normal user** → Permission issue (check Roles, securityCheck)
770
+ - ❌ **Fails with Admin too** → Different issue (check logic, data, validation)
771
+
772
+ 6. **Common permission issues and solutions**:
773
+
774
+ | Problem | Cause | Solution |
775
+ |---------|-------|----------|
776
+ | 401/403 on endpoint | `@Roles()` too restrictive | Adjust decorator in controller/resolver |
777
+ | Empty result despite data existing | `securityCheck()` returns undefined | Modify securityCheck logic or use Admin |
778
+ | Service throws permission error | `serviceOptions.roles` check fails | Pass correct roles in serviceOptions |
779
+
780
+ 7. **Remove debug messages after fixing**:
781
+ ```bash
782
+ # After tests pass, remove all console.log statements
783
+ # Search for debug patterns
784
+ grep -r "console.log" src/server/modules/your-module/
785
+
786
+ # Remove them manually or with sed
787
+ # Then verify tests still pass
788
+ npm run test:e2e
789
+ ```
790
+
791
+ **Debugging workflow example**:
792
+ ```typescript
793
+ // 1. Test fails - add debugging
794
+ @Mutation(() => Product)
795
+ async createProduct(@Args('input') input: ProductCreateInput, @GraphQLServiceOptions() opts) {
796
+ console.log('🔵 START createProduct', { input, user: opts?.user?.email });
797
+
798
+ const result = await this.productService.create(input, opts);
799
+
800
+ console.log('🔵 END createProduct', { result: result?.id });
801
+ return result;
802
+ }
803
+
804
+ // In service
805
+ async create(input: ProductCreateInput, serviceOptions?: ServiceOptions) {
806
+ console.log('🟢 Service create', { input, user: serviceOptions?.user?.email });
807
+
808
+ const created = await super.create(input, serviceOptions);
809
+
810
+ console.log('🟢 Service created', { id: created?.id, createdBy: created?.createdBy });
811
+ return created;
812
+ }
813
+
814
+ // 2. Run test - observe output:
815
+ // 🔵 START createProduct { input: {...}, user: 'test@test.com' }
816
+ // 🟢 Service create { input: {...}, user: 'test@test.com' }
817
+ // 🟢 Service created { id: '123', createdBy: '456' }
818
+ // 🔵 END createProduct { result: undefined } ← AHA! Result is undefined!
819
+
820
+ // 3. Check model securityCheck() - likely returns undefined for non-creator (user.id !== object.createdBy)
821
+ // 4. Fix: Either use Admin user (user.roles contains 'admin') or adjust securityCheck logic
822
+ // 5. Test passes → Remove console.log statements
823
+ // 6. Verify tests still pass
824
+ ```
825
+
826
+ **Do not proceed to final report if**:
827
+ - TypeScript compilation fails
828
+ - Linting fails
829
+ - Any tests fail
830
+ - Console shows errors or warnings
831
+
832
+ ## Step 7: Final Verification
833
+
834
+ Before reporting, verify:
835
+
836
+ - [ ] All files compared with existing code
837
+ - [ ] Code style matches project patterns
838
+ - [ ] All imports properly ordered
839
+ - [ ] All properties in alphabetical order
840
+ - [ ] All descriptions follow format
841
+ - [ ] **TestHelper source code read and understood**
842
+ - [ ] **TestHelper methods and configuration understood**
843
+ - [ ] **Existing tests analyzed BEFORE creating/modifying tests**
844
+ - [ ] **Existing tests passed BEFORE making changes**
845
+ - [ ] **Tests in correct location (tests/modules/<name>.e2e-spec.ts, tests/common.e2e-spec.ts, or tests/project.e2e-spec.ts)**
846
+ - [ ] **New test files created for all new modules**
847
+ - [ ] **Existing test files updated for all modified modules**
848
+ - [ ] **All prerequisites identified and handled (test data dependencies, auth, etc.)**
849
+ - [ ] **All new/modified tests follow exact patterns from existing tests**
850
+ - [ ] TypeScript compiles without errors
851
+ - [ ] Linter passes without warnings
852
+ - [ ] **All tests pass AFTER changes**
853
+ - [ ] No console errors or warnings
854
+
855
+ **Only after ALL checks pass, proceed to Final Report.**