@aicgen/aicgen 1.0.0-beta.2 → 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 (39) hide show
  1. package/.agent/rules/api-design.md +649 -0
  2. package/.agent/rules/architecture.md +2507 -0
  3. package/.agent/rules/best-practices.md +622 -0
  4. package/.agent/rules/code-style.md +308 -0
  5. package/.agent/rules/design-patterns.md +577 -0
  6. package/.agent/rules/devops.md +230 -0
  7. package/.agent/rules/error-handling.md +417 -0
  8. package/.agent/rules/instructions.md +28 -0
  9. package/.agent/rules/language.md +786 -0
  10. package/.agent/rules/performance.md +710 -0
  11. package/.agent/rules/security.md +587 -0
  12. package/.agent/rules/testing.md +572 -0
  13. package/.agent/workflows/add-documentation.md +10 -0
  14. package/.agent/workflows/generate-integration-tests.md +10 -0
  15. package/.agent/workflows/generate-unit-tests.md +11 -0
  16. package/.agent/workflows/performance-audit.md +11 -0
  17. package/.agent/workflows/refactor-extract-module.md +12 -0
  18. package/.agent/workflows/security-audit.md +12 -0
  19. package/.gemini/instructions.md +4843 -0
  20. package/AGENTS.md +9 -11
  21. package/bun.lock +755 -4
  22. package/claude.md +2 -2
  23. package/config.example.yml +129 -0
  24. package/config.yml +38 -0
  25. package/data/guideline-mappings.yml +128 -0
  26. package/data/language/dart/async.md +289 -0
  27. package/data/language/dart/basics.md +280 -0
  28. package/data/language/dart/error-handling.md +355 -0
  29. package/data/language/dart/index.md +10 -0
  30. package/data/language/dart/testing.md +352 -0
  31. package/data/language/swift/basics.md +477 -0
  32. package/data/language/swift/concurrency.md +654 -0
  33. package/data/language/swift/error-handling.md +679 -0
  34. package/data/language/swift/swiftui-mvvm.md +795 -0
  35. package/data/language/swift/testing.md +708 -0
  36. package/data/version.json +10 -8
  37. package/dist/index.js +50295 -29101
  38. package/jest.config.js +46 -0
  39. package/package.json +13 -2
@@ -0,0 +1,572 @@
1
+ # Testing Rules
2
+
3
+ # Unit Testing Fundamentals
4
+
5
+ ## Arrange-Act-Assert Pattern
6
+
7
+ ```typescript
8
+ describe('UserService', () => {
9
+ it('should create user with hashed password', async () => {
10
+ // Arrange - Set up test data and dependencies
11
+ const userData = { email: 'test@example.com', password: 'secret123' };
12
+ const mockRepo = { save: jest.fn().mockResolvedValue({ id: '1', ...userData }) };
13
+ const service = new UserService(mockRepo);
14
+
15
+ // Act - Execute the behavior being tested
16
+ const result = await service.createUser(userData);
17
+
18
+ // Assert - Verify the outcomes
19
+ expect(result.id).toBe('1');
20
+ expect(mockRepo.save).toHaveBeenCalledWith(
21
+ expect.objectContaining({ email: 'test@example.com' })
22
+ );
23
+ });
24
+ });
25
+ ```
26
+
27
+ ## Test Observable Behavior, Not Implementation
28
+
29
+ ```typescript
30
+ // ❌ Bad: Testing implementation details
31
+ it('should call validateEmail method', () => {
32
+ const spy = jest.spyOn(service, 'validateEmail');
33
+ service.createUser({ email: 'test@example.com' });
34
+ expect(spy).toHaveBeenCalled();
35
+ });
36
+
37
+ // ✅ Good: Testing observable behavior
38
+ it('should reject invalid email', async () => {
39
+ await expect(
40
+ service.createUser({ email: 'invalid-email' })
41
+ ).rejects.toThrow('Invalid email format');
42
+ });
43
+
44
+ it('should accept valid email', async () => {
45
+ const result = await service.createUser({ email: 'valid@example.com' });
46
+ expect(result.email).toBe('valid@example.com');
47
+ });
48
+ ```
49
+
50
+ ## One Assertion Per Test Concept
51
+
52
+ ```typescript
53
+ // ❌ Bad: Multiple unrelated assertions
54
+ it('should validate user input', () => {
55
+ expect(() => validate({ age: -1 })).toThrow();
56
+ expect(() => validate({ age: 200 })).toThrow();
57
+ expect(() => validate({ name: '' })).toThrow();
58
+ });
59
+
60
+ // ✅ Good: One test per scenario
61
+ it('should reject negative age', () => {
62
+ expect(() => validate({ age: -1 })).toThrow('Age must be positive');
63
+ });
64
+
65
+ it('should reject age over 150', () => {
66
+ expect(() => validate({ age: 200 })).toThrow('Age must be under 150');
67
+ });
68
+
69
+ it('should reject empty name', () => {
70
+ expect(() => validate({ name: '' })).toThrow('Name is required');
71
+ });
72
+ ```
73
+
74
+ ## Descriptive Test Names
75
+
76
+ ```typescript
77
+ // ❌ Vague names
78
+ it('should work correctly', () => {});
79
+ it('handles edge case', () => {});
80
+
81
+ // ✅ Descriptive names - describe the scenario and expected outcome
82
+ it('should return empty array when no users match filter', () => {});
83
+ it('should throw ValidationError when email is empty', () => {});
84
+ it('should retry failed payment up to 3 times before giving up', () => {});
85
+ ```
86
+
87
+ ## Tests Should Be Independent
88
+
89
+ ```typescript
90
+ // ❌ Bad: Tests depend on each other
91
+ let userId: string;
92
+
93
+ it('should create user', async () => {
94
+ const user = await service.createUser(data);
95
+ userId = user.id; // Shared state!
96
+ });
97
+
98
+ it('should update user', async () => {
99
+ await service.updateUser(userId, newData); // Depends on previous test
100
+ });
101
+
102
+ // ✅ Good: Each test is self-contained
103
+ it('should update user', async () => {
104
+ const user = await service.createUser(data);
105
+ const updated = await service.updateUser(user.id, newData);
106
+ expect(updated.name).toBe(newData.name);
107
+ });
108
+ ```
109
+
110
+ ## Test Edge Cases
111
+
112
+ ```typescript
113
+ describe('divide', () => {
114
+ it('should divide two positive numbers', () => {
115
+ expect(divide(10, 2)).toBe(5);
116
+ });
117
+
118
+ it('should throw when dividing by zero', () => {
119
+ expect(() => divide(10, 0)).toThrow('Division by zero');
120
+ });
121
+
122
+ it('should handle negative numbers', () => {
123
+ expect(divide(-10, 2)).toBe(-5);
124
+ });
125
+
126
+ it('should return zero when numerator is zero', () => {
127
+ expect(divide(0, 5)).toBe(0);
128
+ });
129
+ });
130
+ ```
131
+
132
+
133
+ ---
134
+
135
+ # Test Doubles and Mocking
136
+
137
+ ## Types of Test Doubles
138
+
139
+ ```typescript
140
+ // STUB: Returns canned responses
141
+ const stubUserRepo = {
142
+ findById: () => ({ id: '1', name: 'Test User' })
143
+ };
144
+
145
+ // MOCK: Pre-programmed with expectations
146
+ const mockPaymentGateway = {
147
+ charge: jest.fn()
148
+ .mockResolvedValueOnce({ success: true, transactionId: 'tx1' })
149
+ .mockResolvedValueOnce({ success: false, error: 'Declined' })
150
+ };
151
+
152
+ // SPY: Records calls for verification
153
+ const spy = jest.spyOn(emailService, 'send');
154
+
155
+ // FAKE: Working implementation (not for production)
156
+ class FakeDatabase implements Database {
157
+ private data = new Map<string, any>();
158
+
159
+ async save(id: string, entity: any) { this.data.set(id, entity); }
160
+ async find(id: string) { return this.data.get(id); }
161
+ }
162
+ ```
163
+
164
+ ## When to Mock
165
+
166
+ ```typescript
167
+ // ✅ Mock external services (APIs, databases)
168
+ const mockHttpClient = {
169
+ get: jest.fn().mockResolvedValue({ data: userData })
170
+ };
171
+
172
+ // ✅ Mock time-dependent operations
173
+ jest.useFakeTimers();
174
+ jest.setSystemTime(new Date('2024-01-15'));
175
+
176
+ // ✅ Mock random/non-deterministic functions
177
+ jest.spyOn(Math, 'random').mockReturnValue(0.5);
178
+
179
+ // ❌ Don't mock the code you're testing
180
+ // ❌ Don't mock simple data structures
181
+ ```
182
+
183
+ ## Mock Verification
184
+
185
+ ```typescript
186
+ it('should send welcome email after registration', async () => {
187
+ const mockEmail = { send: jest.fn().mockResolvedValue(true) };
188
+ const service = new UserService({ emailService: mockEmail });
189
+
190
+ await service.register({ email: 'new@example.com' });
191
+
192
+ expect(mockEmail.send).toHaveBeenCalledWith({
193
+ to: 'new@example.com',
194
+ template: 'welcome',
195
+ subject: 'Welcome!'
196
+ });
197
+ expect(mockEmail.send).toHaveBeenCalledTimes(1);
198
+ });
199
+ ```
200
+
201
+ ## Partial Mocks
202
+
203
+ ```typescript
204
+ // Mock only specific methods
205
+ const service = new OrderService();
206
+
207
+ jest.spyOn(service, 'validateOrder').mockReturnValue(true);
208
+ jest.spyOn(service, 'calculateTotal').mockReturnValue(100);
209
+ // Other methods use real implementation
210
+
211
+ const result = await service.processOrder(orderData);
212
+ expect(result.total).toBe(100);
213
+ ```
214
+
215
+ ## Resetting Mocks
216
+
217
+ ```typescript
218
+ describe('PaymentService', () => {
219
+ const mockGateway = { charge: jest.fn() };
220
+ const service = new PaymentService(mockGateway);
221
+
222
+ beforeEach(() => {
223
+ jest.clearAllMocks(); // Clear call history
224
+ // or jest.resetAllMocks() to also reset return values
225
+ });
226
+
227
+ it('should process payment', async () => {
228
+ mockGateway.charge.mockResolvedValue({ success: true });
229
+ await service.charge(100);
230
+ expect(mockGateway.charge).toHaveBeenCalledTimes(1);
231
+ });
232
+ });
233
+ ```
234
+
235
+ ## Mock Modules
236
+
237
+ ```typescript
238
+ // Mock entire module
239
+ jest.mock('./email-service', () => ({
240
+ EmailService: jest.fn().mockImplementation(() => ({
241
+ send: jest.fn().mockResolvedValue(true)
242
+ }))
243
+ }));
244
+
245
+ // Mock with partial implementation
246
+ jest.mock('./config', () => ({
247
+ ...jest.requireActual('./config'),
248
+ API_KEY: 'test-key'
249
+ }));
250
+ ```
251
+
252
+
253
+ ---
254
+
255
+ # Integration Testing
256
+
257
+ ## Testing Real Dependencies
258
+
259
+ ```typescript
260
+ describe('UserRepository Integration', () => {
261
+ let db: Database;
262
+ let repository: UserRepository;
263
+
264
+ beforeAll(async () => {
265
+ db = await createTestDatabase();
266
+ repository = new UserRepository(db);
267
+ });
268
+
269
+ afterAll(async () => {
270
+ await db.close();
271
+ });
272
+
273
+ beforeEach(async () => {
274
+ await db.clear('users'); // Clean slate for each test
275
+ });
276
+
277
+ it('should persist and retrieve user', async () => {
278
+ const userData = { email: 'test@example.com', name: 'Test User' };
279
+
280
+ const created = await repository.create(userData);
281
+ const found = await repository.findById(created.id);
282
+
283
+ expect(found).toEqual(expect.objectContaining(userData));
284
+ });
285
+ });
286
+ ```
287
+
288
+ ## API Integration Tests
289
+
290
+ ```typescript
291
+ describe('POST /api/users', () => {
292
+ let app: Express;
293
+ let db: Database;
294
+
295
+ beforeAll(async () => {
296
+ db = await createTestDatabase();
297
+ app = createApp(db);
298
+ });
299
+
300
+ afterEach(async () => {
301
+ await db.clear('users');
302
+ });
303
+
304
+ it('should create user and return 201', async () => {
305
+ const response = await request(app)
306
+ .post('/api/users')
307
+ .send({ email: 'new@example.com', name: 'New User' })
308
+ .expect(201);
309
+
310
+ expect(response.body.data).toEqual(
311
+ expect.objectContaining({
312
+ email: 'new@example.com',
313
+ name: 'New User'
314
+ })
315
+ );
316
+
317
+ // Verify in database
318
+ const user = await db.findOne('users', { email: 'new@example.com' });
319
+ expect(user).toBeTruthy();
320
+ });
321
+
322
+ it('should return 400 for invalid email', async () => {
323
+ const response = await request(app)
324
+ .post('/api/users')
325
+ .send({ email: 'invalid', name: 'Test' })
326
+ .expect(400);
327
+
328
+ expect(response.body.error.code).toBe('VALIDATION_ERROR');
329
+ });
330
+ });
331
+ ```
332
+
333
+ ## Database Transaction Testing
334
+
335
+ ```typescript
336
+ describe('OrderService Integration', () => {
337
+ it('should rollback on payment failure', async () => {
338
+ const order = await orderService.createOrder({ items: [...] });
339
+
340
+ // Mock payment to fail
341
+ paymentGateway.charge.mockRejectedValue(new Error('Declined'));
342
+
343
+ await expect(
344
+ orderService.processOrder(order.id)
345
+ ).rejects.toThrow('Payment failed');
346
+
347
+ // Verify order status unchanged
348
+ const updatedOrder = await orderRepository.findById(order.id);
349
+ expect(updatedOrder.status).toBe('pending');
350
+
351
+ // Verify inventory not deducted
352
+ const inventory = await inventoryRepository.findByProductId(productId);
353
+ expect(inventory.quantity).toBe(originalQuantity);
354
+ });
355
+ });
356
+ ```
357
+
358
+ ## Test Data Builders
359
+
360
+ ```typescript
361
+ class UserBuilder {
362
+ private data: Partial<User> = {
363
+ email: 'default@example.com',
364
+ name: 'Default User',
365
+ role: 'user'
366
+ };
367
+
368
+ withEmail(email: string) { this.data.email = email; return this; }
369
+ withRole(role: string) { this.data.role = role; return this; }
370
+ asAdmin() { this.data.role = 'admin'; return this; }
371
+
372
+ build(): User { return this.data as User; }
373
+
374
+ async save(db: Database): Promise<User> {
375
+ return db.insert('users', this.data);
376
+ }
377
+ }
378
+
379
+ // Usage
380
+ const admin = await new UserBuilder()
381
+ .withEmail('admin@example.com')
382
+ .asAdmin()
383
+ .save(db);
384
+ ```
385
+
386
+ ## Test Isolation
387
+
388
+ ```typescript
389
+ // Use transactions that rollback
390
+ describe('IntegrationTests', () => {
391
+ beforeEach(async () => {
392
+ await db.beginTransaction();
393
+ });
394
+
395
+ afterEach(async () => {
396
+ await db.rollbackTransaction();
397
+ });
398
+ });
399
+
400
+ // Or use test containers
401
+ import { PostgreSqlContainer } from '@testcontainers/postgresql';
402
+
403
+ let container: PostgreSqlContainer;
404
+
405
+ beforeAll(async () => {
406
+ container = await new PostgreSqlContainer().start();
407
+ db = await connect(container.getConnectionUri());
408
+ });
409
+
410
+ afterAll(async () => {
411
+ await container.stop();
412
+ });
413
+ ```
414
+
415
+
416
+ ---
417
+
418
+ # Testing Basics
419
+
420
+ ## Your First Unit Test
421
+
422
+ A unit test verifies that a small piece of code works correctly.
423
+
424
+ ```pseudocode
425
+ // Function to test
426
+ function add(a, b):
427
+ return a + b
428
+
429
+ // Test for the function
430
+ test "add should sum two numbers":
431
+ result = add(2, 3)
432
+ expect result equals 5
433
+ ```
434
+
435
+ ## Test Structure
436
+
437
+ Every test has three parts:
438
+
439
+ 1. **Setup** - Prepare what you need
440
+ 2. **Execute** - Run the code
441
+ 3. **Verify** - Check the result
442
+
443
+ ```pseudocode
444
+ test "should create user with name":
445
+ // 1. Setup
446
+ userName = "Alice"
447
+
448
+ // 2. Execute
449
+ user = createUser(userName)
450
+
451
+ // 3. Verify
452
+ expect user.name equals "Alice"
453
+ ```
454
+
455
+ ## Common Assertions
456
+
457
+ ```pseudocode
458
+ // Equality
459
+ expect value equals 5
460
+ expect value equals { id: 1 }
461
+
462
+ // Truthiness
463
+ expect value is truthy
464
+ expect value is falsy
465
+ expect value is null
466
+ expect value is undefined
467
+
468
+ // Numbers
469
+ expect value > 3
470
+ expect value < 10
471
+
472
+ // Strings
473
+ expect text contains "hello"
474
+
475
+ // Arrays/Lists
476
+ expect array contains item
477
+ expect array length equals 3
478
+ ```
479
+
480
+ ## Testing Expected Errors
481
+
482
+ ```pseudocode
483
+ test "should throw error for invalid input":
484
+ expect error when:
485
+ divide(10, 0)
486
+ with message "Cannot divide by zero"
487
+ ```
488
+
489
+ ## Async Tests
490
+
491
+ ```pseudocode
492
+ test "should fetch user data" async:
493
+ user = await fetchUser(123)
494
+ expect user.id equals 123
495
+ ```
496
+
497
+ ## Test Naming
498
+
499
+ Use clear, descriptive names:
500
+
501
+ ```pseudocode
502
+ // ❌ Bad
503
+ test "test1"
504
+ test "it works"
505
+
506
+ // ✅ Good
507
+ test "should return user when ID exists"
508
+ test "should throw error when ID is invalid"
509
+ ```
510
+
511
+ ## Running Tests
512
+
513
+ ```bash
514
+ # Run all tests
515
+ run-tests
516
+
517
+ # Run specific test file
518
+ run-tests user-test
519
+
520
+ # Watch mode (re-run on changes)
521
+ run-tests --watch
522
+ ```
523
+
524
+ ## Best Practices
525
+
526
+ 1. **One test, one thing** - Test one behavior per test
527
+ 2. **Independent tests** - Tests should not depend on each other
528
+ 3. **Clear names** - Name should describe what is being tested
529
+ 4. **Fast tests** - Tests should run quickly
530
+
531
+ ```pseudocode
532
+ // ❌ Bad: Testing multiple things
533
+ test "user operations":
534
+ expect createUser("Bob").name equals "Bob"
535
+ expect deleteUser(1) equals true
536
+ expect listUsers().length equals 0
537
+
538
+ // ✅ Good: One test per operation
539
+ test "should create user with given name":
540
+ user = createUser("Bob")
541
+ expect user.name equals "Bob"
542
+
543
+ test "should delete user by ID":
544
+ result = deleteUser(1)
545
+ expect result equals true
546
+
547
+ test "should return empty list when no users":
548
+ users = listUsers()
549
+ expect users.length equals 0
550
+ ```
551
+
552
+ ## When to Write Tests
553
+
554
+ - **Before fixing bugs** - Write test that fails, then fix
555
+ - **For new features** - Test expected behavior
556
+ - **For edge cases** - Empty input, null values, large numbers
557
+
558
+ ## What to Test
559
+
560
+ ✅ **Do test:**
561
+ - Public functions and methods
562
+ - Edge cases (empty, null, zero, negative)
563
+ - Error conditions
564
+
565
+ ❌ **Don't test:**
566
+ - Private implementation details
567
+ - Third-party libraries (they're already tested)
568
+ - Getters/setters with no logic
569
+
570
+
571
+ ---
572
+ *Generated by aicgen*
@@ -0,0 +1,10 @@
1
+ ---
2
+ description: Add or update comprehensive documentation for code
3
+ ---
4
+
5
+ * Analyze the selected code for documentation needs
6
+ * Add inline documentation with clear descriptions
7
+ * Include parameter types and return value documentation
8
+ * Add usage examples for complex functions
9
+ * Follow language-specific documentation standards
10
+ * Update README.md if adding new features
@@ -0,0 +1,10 @@
1
+ ---
2
+ description: Generate integration tests for API endpoints and system components
3
+ ---
4
+
5
+ * Identify integration points (APIs, databases, services)
6
+ * Create integration test files
7
+ * Test end-to-end workflows
8
+ * Use realistic test data and fixtures
9
+ * Include proper setup and teardown
10
+ * Ensure tests are idempotent
@@ -0,0 +1,11 @@
1
+ ---
2
+ description: Generate comprehensive unit tests for all functions and methods
3
+ ---
4
+
5
+ * Analyze the selected file or directory for testable code
6
+ * Generate test files with appropriate naming conventions
7
+ * Create test cases covering happy path, edge cases, and error handling
8
+ * Mock external dependencies appropriately
9
+ * Follow language-specific testing best practices
10
+ * Aim for >80% code coverage
11
+ * Include setup and teardown methods where needed
@@ -0,0 +1,11 @@
1
+ ---
2
+ description: Analyze code for performance bottlenecks and optimization opportunities
3
+ ---
4
+
5
+ * Profile code to identify hotspots
6
+ * Check for N+1 queries and inefficient algorithms
7
+ * Analyze caching opportunities
8
+ * Review resource management
9
+ * Suggest specific optimizations
10
+ * Estimate performance impact
11
+ * Prioritize recommendations
@@ -0,0 +1,12 @@
1
+ ---
2
+ description: Extract code into a separate, reusable module
3
+ ---
4
+
5
+ * Identify the code section to extract
6
+ * Analyze dependencies and determine module interface
7
+ * Create a new module file following project conventions
8
+ * Maintain original functionality and behavior
9
+ * Update imports and exports appropriately
10
+ * Ensure no circular dependencies
11
+ * Add documentation to the new module
12
+ * Verify all tests still pass
@@ -0,0 +1,12 @@
1
+ ---
2
+ description: Perform comprehensive security audit of the codebase
3
+ ---
4
+
5
+ * Scan for common vulnerabilities (SQL injection, XSS, etc.)
6
+ * Check authentication and authorization logic
7
+ * Review input validation and sanitization
8
+ * Examine error handling for information leakage
9
+ * Verify secure handling of sensitive data
10
+ * Check third-party dependencies
11
+ * Suggest remediation steps
12
+ * Prioritize findings by severity