@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,352 @@
1
+ # Testing in Dart
2
+
3
+ ## Unit Testing
4
+
5
+ ```dart
6
+ import 'package:test/test.dart';
7
+
8
+ // ✅ Arrange-Act-Assert pattern
9
+ void main() {
10
+ group('UserService', () {
11
+ test('should create user with hashed password', () async {
12
+ // Arrange
13
+ final repository = MockUserRepository();
14
+ final service = UserService(repository);
15
+ final userData = UserData(email: 'test@example.com', password: 'secret');
16
+
17
+ // Act
18
+ final user = await service.createUser(userData);
19
+
20
+ // Assert
21
+ expect(user.email, equals('test@example.com'));
22
+ expect(user.passwordHash, isNot(equals('secret')));
23
+ verify(repository.save(any)).called(1);
24
+ });
25
+
26
+ test('should throw ValidationException for invalid email', () {
27
+ final service = UserService(MockUserRepository());
28
+
29
+ expect(
30
+ () => service.createUser(UserData(email: 'invalid', password: 'pass')),
31
+ throwsA(isA<ValidationException>()),
32
+ );
33
+ });
34
+ });
35
+ }
36
+ ```
37
+
38
+ ## Test Organization
39
+
40
+ ```dart
41
+ void main() {
42
+ // ✅ Use group for related tests
43
+ group('Calculator', () {
44
+ late Calculator calculator;
45
+
46
+ // setUp runs before each test
47
+ setUp(() {
48
+ calculator = Calculator();
49
+ });
50
+
51
+ // tearDown runs after each test
52
+ tearDown(() {
53
+ calculator.dispose();
54
+ });
55
+
56
+ test('adds two numbers', () {
57
+ expect(calculator.add(2, 3), equals(5));
58
+ });
59
+
60
+ test('subtracts two numbers', () {
61
+ expect(calculator.subtract(5, 3), equals(2));
62
+ });
63
+
64
+ group('division', () {
65
+ test('divides two numbers', () {
66
+ expect(calculator.divide(10, 2), equals(5));
67
+ });
68
+
69
+ test('throws on division by zero', () {
70
+ expect(
71
+ () => calculator.divide(10, 0),
72
+ throwsA(isA<DivisionByZeroException>()),
73
+ );
74
+ });
75
+ });
76
+ });
77
+ }
78
+ ```
79
+
80
+ ## Matchers
81
+
82
+ ```dart
83
+ // Equality
84
+ expect(value, equals(expected));
85
+ expect(value, isNot(equals(unexpected)));
86
+
87
+ // Types
88
+ expect(value, isA<String>());
89
+ expect(value, isNotNull);
90
+ expect(value, isNull);
91
+
92
+ // Numbers
93
+ expect(value, greaterThan(5));
94
+ expect(value, lessThan(10));
95
+ expect(value, closeTo(3.14, 0.01));
96
+
97
+ // Strings
98
+ expect(text, contains('hello'));
99
+ expect(text, startsWith('Hello'));
100
+ expect(text, endsWith('world'));
101
+ expect(text, matches(r'^\d+$'));
102
+
103
+ // Collections
104
+ expect(list, isEmpty);
105
+ expect(list, isNotEmpty);
106
+ expect(list, hasLength(3));
107
+ expect(list, contains(item));
108
+ expect(map, containsValue(value));
109
+
110
+ // Futures
111
+ expect(future, completes);
112
+ expect(future, throwsException);
113
+ expect(future, completion(equals(value)));
114
+
115
+ // Custom matchers
116
+ expect(user, isA<User>().having((u) => u.email, 'email', 'test@example.com'));
117
+ ```
118
+
119
+ ## Mocking with Mockito
120
+
121
+ ```dart
122
+ import 'package:mockito/mockito.dart';
123
+ import 'package:mockito/annotations.dart';
124
+
125
+ // Generate mocks
126
+ @GenerateMocks([UserRepository, ApiClient])
127
+ void main() {
128
+ group('UserService', () {
129
+ late MockUserRepository repository;
130
+ late UserService service;
131
+
132
+ setUp(() {
133
+ repository = MockUserRepository();
134
+ service = UserService(repository);
135
+ });
136
+
137
+ test('should fetch user by id', () async {
138
+ // Arrange - stub method
139
+ final expectedUser = User(id: '1', name: 'Alice');
140
+ when(repository.findById('1')).thenAnswer((_) async => expectedUser);
141
+
142
+ // Act
143
+ final user = await service.getUser('1');
144
+
145
+ // Assert
146
+ expect(user, equals(expectedUser));
147
+ verify(repository.findById('1')).called(1);
148
+ });
149
+
150
+ test('should handle not found', () async {
151
+ // Stub to return null
152
+ when(repository.findById(any)).thenAnswer((_) async => null);
153
+
154
+ expect(
155
+ () => service.getUser('999'),
156
+ throwsA(isA<NotFoundException>()),
157
+ );
158
+ });
159
+ });
160
+ }
161
+ ```
162
+
163
+ ## Testing Async Code
164
+
165
+ ```dart
166
+ test('should fetch data asynchronously', () async {
167
+ final data = await fetchData();
168
+ expect(data, isNotNull);
169
+ });
170
+
171
+ test('should complete within timeout', () async {
172
+ await expectLater(
173
+ slowOperation().timeout(const Duration(seconds: 2)),
174
+ completes,
175
+ );
176
+ });
177
+
178
+ test('should handle errors', () {
179
+ expect(
180
+ failingOperation(),
181
+ throwsA(isA<NetworkException>()),
182
+ );
183
+ });
184
+ ```
185
+
186
+ ## Testing Streams
187
+
188
+ ```dart
189
+ test('should emit values from stream', () async {
190
+ final stream = Stream.fromIterable([1, 2, 3]);
191
+
192
+ expect(stream, emitsInOrder([1, 2, 3]));
193
+ });
194
+
195
+ test('should emit and complete', () {
196
+ expect(
197
+ countStream(3),
198
+ emitsInOrder([
199
+ 1,
200
+ 2,
201
+ 3,
202
+ emitsDone,
203
+ ]),
204
+ );
205
+ });
206
+
207
+ test('should handle stream errors', () {
208
+ expect(
209
+ errorStream(),
210
+ emitsInOrder([
211
+ 1,
212
+ emitsError(isA<Exception>()),
213
+ ]),
214
+ );
215
+ });
216
+ ```
217
+
218
+ ## Widget Testing (Flutter)
219
+
220
+ ```dart
221
+ import 'package:flutter_test/flutter_test.dart';
222
+
223
+ void main() {
224
+ testWidgets('should display user name', (WidgetTester tester) async {
225
+ // Arrange
226
+ final user = User(id: '1', name: 'Alice');
227
+
228
+ // Act
229
+ await tester.pumpWidget(
230
+ MaterialApp(home: UserProfile(user: user)),
231
+ );
232
+
233
+ // Assert
234
+ expect(find.text('Alice'), findsOneWidget);
235
+ });
236
+
237
+ testWidgets('should handle button tap', (WidgetTester tester) async {
238
+ bool tapped = false;
239
+
240
+ await tester.pumpWidget(
241
+ MaterialApp(
242
+ home: Scaffold(
243
+ body: ElevatedButton(
244
+ onPressed: () => tapped = true,
245
+ child: const Text('Tap me'),
246
+ ),
247
+ ),
248
+ ),
249
+ );
250
+
251
+ // Find and tap button
252
+ await tester.tap(find.text('Tap me'));
253
+ await tester.pump();
254
+
255
+ expect(tapped, isTrue);
256
+ });
257
+ }
258
+ ```
259
+
260
+ ## Integration Testing
261
+
262
+ ```dart
263
+ import 'package:integration_test/integration_test.dart';
264
+ import 'package:flutter_test/flutter_test.dart';
265
+
266
+ void main() {
267
+ IntegrationTestWidgetsFlutterBinding.ensureInitialized();
268
+
269
+ group('Login flow', () {
270
+ testWidgets('should login successfully', (tester) async {
271
+ await tester.pumpWidget(MyApp());
272
+
273
+ // Enter credentials
274
+ await tester.enterText(
275
+ find.byKey(const Key('email_field')),
276
+ 'test@example.com',
277
+ );
278
+ await tester.enterText(
279
+ find.byKey(const Key('password_field')),
280
+ 'password123',
281
+ );
282
+
283
+ // Tap login
284
+ await tester.tap(find.byKey(const Key('login_button')));
285
+ await tester.pumpAndSettle();
286
+
287
+ // Verify navigation to home
288
+ expect(find.byType(HomePage), findsOneWidget);
289
+ });
290
+ });
291
+ }
292
+ ```
293
+
294
+ ## Test Doubles
295
+
296
+ ```dart
297
+ // Fake - working implementation (not for production)
298
+ class FakeUserRepository implements UserRepository {
299
+ final _users = <String, User>{};
300
+
301
+ @override
302
+ Future<User?> findById(String id) async {
303
+ return _users[id];
304
+ }
305
+
306
+ @override
307
+ Future<void> save(User user) async {
308
+ _users[user.id] = user;
309
+ }
310
+ }
311
+
312
+ // Stub - returns canned responses
313
+ class StubApiClient implements ApiClient {
314
+ @override
315
+ Future<Response> get(String url) async {
316
+ return Response(statusCode: 200, data: {'id': '1', 'name': 'Alice'});
317
+ }
318
+ }
319
+
320
+ // Mock - pre-programmed with expectations (use Mockito)
321
+ final mock = MockUserRepository();
322
+ when(mock.findById('1')).thenAnswer((_) async => testUser);
323
+ ```
324
+
325
+ ## Coverage
326
+
327
+ ```bash
328
+ # Run tests with coverage
329
+ dart test --coverage=coverage
330
+
331
+ # Generate HTML report
332
+ genhtml coverage/lcov.info -o coverage/html
333
+
334
+ # View coverage
335
+ open coverage/html/index.html
336
+ ```
337
+
338
+ ## Best Practices
339
+
340
+ - Use `group()` to organize related tests
341
+ - One test per behavior
342
+ - Use descriptive test names: "should [expected behavior] when [scenario]"
343
+ - Follow Arrange-Act-Assert pattern
344
+ - Test observable behavior, not implementation
345
+ - Use setUp/tearDown for common initialization
346
+ - Mock external dependencies
347
+ - Test edge cases and error conditions
348
+ - Keep tests fast and independent
349
+ - Use `pump()` and `pumpAndSettle()` in widget tests
350
+ - Verify interactions with mocks
351
+ - Aim for high code coverage (80%+)
352
+ - Run tests in CI/CD pipeline