agentic-team-templates 0.3.0

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 (103) hide show
  1. package/README.md +280 -0
  2. package/bin/cli.js +5 -0
  3. package/package.json +47 -0
  4. package/src/index.js +521 -0
  5. package/templates/_shared/code-quality.md +162 -0
  6. package/templates/_shared/communication.md +114 -0
  7. package/templates/_shared/core-principles.md +62 -0
  8. package/templates/_shared/git-workflow.md +165 -0
  9. package/templates/_shared/security-fundamentals.md +173 -0
  10. package/templates/blockchain/.cursorrules/defi-patterns.md +520 -0
  11. package/templates/blockchain/.cursorrules/gas-optimization.md +339 -0
  12. package/templates/blockchain/.cursorrules/overview.md +130 -0
  13. package/templates/blockchain/.cursorrules/security.md +318 -0
  14. package/templates/blockchain/.cursorrules/smart-contracts.md +364 -0
  15. package/templates/blockchain/.cursorrules/testing.md +415 -0
  16. package/templates/blockchain/.cursorrules/web3-integration.md +538 -0
  17. package/templates/blockchain/CLAUDE.md +389 -0
  18. package/templates/cli-tools/.cursorrules/architecture.md +412 -0
  19. package/templates/cli-tools/.cursorrules/arguments.md +406 -0
  20. package/templates/cli-tools/.cursorrules/distribution.md +546 -0
  21. package/templates/cli-tools/.cursorrules/error-handling.md +455 -0
  22. package/templates/cli-tools/.cursorrules/overview.md +136 -0
  23. package/templates/cli-tools/.cursorrules/testing.md +537 -0
  24. package/templates/cli-tools/.cursorrules/user-experience.md +545 -0
  25. package/templates/cli-tools/CLAUDE.md +356 -0
  26. package/templates/data-engineering/.cursorrules/data-modeling.md +367 -0
  27. package/templates/data-engineering/.cursorrules/data-quality.md +455 -0
  28. package/templates/data-engineering/.cursorrules/overview.md +85 -0
  29. package/templates/data-engineering/.cursorrules/performance.md +339 -0
  30. package/templates/data-engineering/.cursorrules/pipeline-design.md +280 -0
  31. package/templates/data-engineering/.cursorrules/security.md +460 -0
  32. package/templates/data-engineering/.cursorrules/testing.md +452 -0
  33. package/templates/data-engineering/CLAUDE.md +974 -0
  34. package/templates/devops-sre/.cursorrules/capacity-planning.md +653 -0
  35. package/templates/devops-sre/.cursorrules/change-management.md +584 -0
  36. package/templates/devops-sre/.cursorrules/chaos-engineering.md +651 -0
  37. package/templates/devops-sre/.cursorrules/disaster-recovery.md +641 -0
  38. package/templates/devops-sre/.cursorrules/incident-management.md +565 -0
  39. package/templates/devops-sre/.cursorrules/observability.md +714 -0
  40. package/templates/devops-sre/.cursorrules/overview.md +230 -0
  41. package/templates/devops-sre/.cursorrules/postmortems.md +588 -0
  42. package/templates/devops-sre/.cursorrules/runbooks.md +760 -0
  43. package/templates/devops-sre/.cursorrules/slo-sli.md +617 -0
  44. package/templates/devops-sre/.cursorrules/toil-reduction.md +567 -0
  45. package/templates/devops-sre/CLAUDE.md +1007 -0
  46. package/templates/documentation/.cursorrules/adr.md +277 -0
  47. package/templates/documentation/.cursorrules/api-documentation.md +411 -0
  48. package/templates/documentation/.cursorrules/code-comments.md +253 -0
  49. package/templates/documentation/.cursorrules/maintenance.md +260 -0
  50. package/templates/documentation/.cursorrules/overview.md +82 -0
  51. package/templates/documentation/.cursorrules/readme-standards.md +306 -0
  52. package/templates/documentation/CLAUDE.md +120 -0
  53. package/templates/fullstack/.cursorrules/api-contracts.md +331 -0
  54. package/templates/fullstack/.cursorrules/architecture.md +298 -0
  55. package/templates/fullstack/.cursorrules/overview.md +109 -0
  56. package/templates/fullstack/.cursorrules/shared-types.md +348 -0
  57. package/templates/fullstack/.cursorrules/testing.md +386 -0
  58. package/templates/fullstack/CLAUDE.md +349 -0
  59. package/templates/ml-ai/.cursorrules/data-engineering.md +483 -0
  60. package/templates/ml-ai/.cursorrules/deployment.md +601 -0
  61. package/templates/ml-ai/.cursorrules/model-development.md +538 -0
  62. package/templates/ml-ai/.cursorrules/monitoring.md +658 -0
  63. package/templates/ml-ai/.cursorrules/overview.md +131 -0
  64. package/templates/ml-ai/.cursorrules/security.md +637 -0
  65. package/templates/ml-ai/.cursorrules/testing.md +678 -0
  66. package/templates/ml-ai/CLAUDE.md +1136 -0
  67. package/templates/mobile/.cursorrules/navigation.md +246 -0
  68. package/templates/mobile/.cursorrules/offline-first.md +302 -0
  69. package/templates/mobile/.cursorrules/overview.md +71 -0
  70. package/templates/mobile/.cursorrules/performance.md +345 -0
  71. package/templates/mobile/.cursorrules/testing.md +339 -0
  72. package/templates/mobile/CLAUDE.md +233 -0
  73. package/templates/platform-engineering/.cursorrules/ci-cd.md +778 -0
  74. package/templates/platform-engineering/.cursorrules/developer-experience.md +632 -0
  75. package/templates/platform-engineering/.cursorrules/infrastructure-as-code.md +600 -0
  76. package/templates/platform-engineering/.cursorrules/kubernetes.md +710 -0
  77. package/templates/platform-engineering/.cursorrules/observability.md +747 -0
  78. package/templates/platform-engineering/.cursorrules/overview.md +215 -0
  79. package/templates/platform-engineering/.cursorrules/security.md +855 -0
  80. package/templates/platform-engineering/.cursorrules/testing.md +878 -0
  81. package/templates/platform-engineering/CLAUDE.md +850 -0
  82. package/templates/utility-agent/.cursorrules/action-control.md +284 -0
  83. package/templates/utility-agent/.cursorrules/context-management.md +186 -0
  84. package/templates/utility-agent/.cursorrules/hallucination-prevention.md +253 -0
  85. package/templates/utility-agent/.cursorrules/overview.md +78 -0
  86. package/templates/utility-agent/.cursorrules/token-optimization.md +369 -0
  87. package/templates/utility-agent/CLAUDE.md +513 -0
  88. package/templates/web-backend/.cursorrules/api-design.md +255 -0
  89. package/templates/web-backend/.cursorrules/authentication.md +309 -0
  90. package/templates/web-backend/.cursorrules/database-patterns.md +298 -0
  91. package/templates/web-backend/.cursorrules/error-handling.md +366 -0
  92. package/templates/web-backend/.cursorrules/overview.md +69 -0
  93. package/templates/web-backend/.cursorrules/security.md +358 -0
  94. package/templates/web-backend/.cursorrules/testing.md +395 -0
  95. package/templates/web-backend/CLAUDE.md +366 -0
  96. package/templates/web-frontend/.cursorrules/accessibility.md +296 -0
  97. package/templates/web-frontend/.cursorrules/component-patterns.md +204 -0
  98. package/templates/web-frontend/.cursorrules/overview.md +72 -0
  99. package/templates/web-frontend/.cursorrules/performance.md +325 -0
  100. package/templates/web-frontend/.cursorrules/state-management.md +227 -0
  101. package/templates/web-frontend/.cursorrules/styling.md +271 -0
  102. package/templates/web-frontend/.cursorrules/testing.md +311 -0
  103. package/templates/web-frontend/CLAUDE.md +399 -0
@@ -0,0 +1,537 @@
1
+ # CLI Testing
2
+
3
+ Strategies for testing command-line applications: unit tests, integration tests, and mocking I/O.
4
+
5
+ ## Testing Philosophy
6
+
7
+ 1. **Test behavior, not implementation** - Verify what the CLI does, not how
8
+ 2. **Test at multiple levels** - Unit, integration, and end-to-end
9
+ 3. **Test edge cases** - Invalid inputs, missing files, network errors
10
+ 4. **Test non-interactively** - Support CI/CD environments
11
+
12
+ ## Unit Testing
13
+
14
+ ### Testing Business Logic
15
+
16
+ Separate business logic from CLI framework for easy testing:
17
+
18
+ ```go
19
+ // Go: Testable business logic
20
+ // lib/build.go
21
+ func Build(config *BuildConfig) (*BuildResult, error) {
22
+ // Pure business logic, no CLI dependencies
23
+ // Easy to test in isolation
24
+ }
25
+
26
+ // cmd/build.go
27
+ var buildCmd = &cobra.Command{
28
+ RunE: func(cmd *cobra.Command, args []string) error {
29
+ config := loadBuildConfig(cmd)
30
+ result, err := lib.Build(config)
31
+ if err != nil {
32
+ return err
33
+ }
34
+ printResult(result)
35
+ return nil
36
+ },
37
+ }
38
+ ```
39
+
40
+ ```go
41
+ // Go: Unit test
42
+ func TestBuild(t *testing.T) {
43
+ config := &BuildConfig{
44
+ Source: "testdata/src",
45
+ Output: t.TempDir(),
46
+ }
47
+
48
+ result, err := Build(config)
49
+
50
+ require.NoError(t, err)
51
+ assert.Equal(t, 5, result.FilesProcessed)
52
+ assert.FileExists(t, filepath.Join(config.Output, "main.js"))
53
+ }
54
+ ```
55
+
56
+ ```typescript
57
+ // TypeScript: Unit test
58
+ describe('build', () => {
59
+ it('processes all source files', async () => {
60
+ const config: BuildConfig = {
61
+ source: 'testdata/src',
62
+ output: await mkdtemp('build-test'),
63
+ };
64
+
65
+ const result = await build(config);
66
+
67
+ expect(result.filesProcessed).toBe(5);
68
+ expect(fs.existsSync(path.join(config.output, 'main.js'))).toBe(true);
69
+ });
70
+ });
71
+ ```
72
+
73
+ ### Testing Argument Parsing
74
+
75
+ ```go
76
+ // Go with Cobra: Test argument validation
77
+ func TestBuildArgsValidation(t *testing.T) {
78
+ tests := []struct {
79
+ name string
80
+ args []string
81
+ wantErr bool
82
+ }{
83
+ {
84
+ name: "valid single path",
85
+ args: []string{"./src"},
86
+ wantErr: false,
87
+ },
88
+ {
89
+ name: "no args uses current dir",
90
+ args: []string{},
91
+ wantErr: false,
92
+ },
93
+ {
94
+ name: "too many args",
95
+ args: []string{"./src", "./lib", "./extra"},
96
+ wantErr: true,
97
+ },
98
+ }
99
+
100
+ for _, tt := range tests {
101
+ t.Run(tt.name, func(t *testing.T) {
102
+ cmd := NewBuildCmd()
103
+ cmd.SetArgs(tt.args)
104
+ err := cmd.Execute()
105
+
106
+ if tt.wantErr {
107
+ assert.Error(t, err)
108
+ } else {
109
+ assert.NoError(t, err)
110
+ }
111
+ })
112
+ }
113
+ }
114
+ ```
115
+
116
+ ## Integration Testing
117
+
118
+ ### Testing Full Commands
119
+
120
+ ```go
121
+ // Go: Integration test with captured output
122
+ func TestBuildCommand(t *testing.T) {
123
+ // Setup
124
+ tempDir := t.TempDir()
125
+ setupTestProject(t, tempDir)
126
+
127
+ // Capture stdout/stderr
128
+ stdout := new(bytes.Buffer)
129
+ stderr := new(bytes.Buffer)
130
+
131
+ // Create and run command
132
+ cmd := NewRootCmd()
133
+ cmd.SetOut(stdout)
134
+ cmd.SetErr(stderr)
135
+ cmd.SetArgs([]string{"build", tempDir, "-o", filepath.Join(tempDir, "dist")})
136
+
137
+ // Execute
138
+ err := cmd.Execute()
139
+
140
+ // Assert
141
+ require.NoError(t, err)
142
+ assert.Contains(t, stdout.String(), "Build complete")
143
+ assert.DirExists(t, filepath.Join(tempDir, "dist"))
144
+ }
145
+ ```
146
+
147
+ ```typescript
148
+ // TypeScript: Integration test
149
+ import { execSync } from 'child_process';
150
+
151
+ describe('build command', () => {
152
+ let tempDir: string;
153
+
154
+ beforeEach(async () => {
155
+ tempDir = await mkdtemp('build-test');
156
+ setupTestProject(tempDir);
157
+ });
158
+
159
+ afterEach(() => {
160
+ fs.rmSync(tempDir, { recursive: true });
161
+ });
162
+
163
+ it('builds project successfully', () => {
164
+ const result = execSync(`node ./bin/cli.js build ${tempDir}`, {
165
+ encoding: 'utf-8',
166
+ });
167
+
168
+ expect(result).toContain('Build complete');
169
+ expect(fs.existsSync(path.join(tempDir, 'dist'))).toBe(true);
170
+ });
171
+
172
+ it('returns error for invalid path', () => {
173
+ expect(() => {
174
+ execSync('node ./bin/cli.js build /nonexistent', {
175
+ encoding: 'utf-8',
176
+ });
177
+ }).toThrow();
178
+ });
179
+ });
180
+ ```
181
+
182
+ ### Testing Exit Codes
183
+
184
+ ```go
185
+ // Go: Test exit codes
186
+ func TestExitCodes(t *testing.T) {
187
+ tests := []struct {
188
+ name string
189
+ args []string
190
+ exitCode int
191
+ }{
192
+ {
193
+ name: "success",
194
+ args: []string{"build", "testdata/valid"},
195
+ exitCode: 0,
196
+ },
197
+ {
198
+ name: "invalid args",
199
+ args: []string{"build", "--invalid-flag"},
200
+ exitCode: 2,
201
+ },
202
+ {
203
+ name: "file not found",
204
+ args: []string{"build", "/nonexistent"},
205
+ exitCode: 1,
206
+ },
207
+ }
208
+
209
+ for _, tt := range tests {
210
+ t.Run(tt.name, func(t *testing.T) {
211
+ cmd := exec.Command("./mytool", tt.args...)
212
+ err := cmd.Run()
213
+
214
+ exitErr, ok := err.(*exec.ExitError)
215
+ if tt.exitCode == 0 {
216
+ assert.NoError(t, err)
217
+ } else {
218
+ require.True(t, ok)
219
+ assert.Equal(t, tt.exitCode, exitErr.ExitCode())
220
+ }
221
+ })
222
+ }
223
+ }
224
+ ```
225
+
226
+ ## Mocking I/O
227
+
228
+ ### Mocking stdin
229
+
230
+ ```go
231
+ // Go: Mock stdin for testing
232
+ func TestInteractivePrompt(t *testing.T) {
233
+ // Create a pipe to simulate stdin
234
+ r, w, _ := os.Pipe()
235
+ oldStdin := os.Stdin
236
+ os.Stdin = r
237
+
238
+ // Write test input
239
+ go func() {
240
+ w.WriteString("y\n")
241
+ w.Close()
242
+ }()
243
+
244
+ // Run function that reads from stdin
245
+ result := confirmAction("Delete?")
246
+
247
+ // Restore stdin
248
+ os.Stdin = oldStdin
249
+
250
+ assert.True(t, result)
251
+ }
252
+ ```
253
+
254
+ ```typescript
255
+ // TypeScript: Mock stdin with mock-stdin
256
+ import mockStdin from 'mock-stdin';
257
+
258
+ describe('interactive prompts', () => {
259
+ let stdin: ReturnType<typeof mockStdin.stdin>;
260
+
261
+ beforeEach(() => {
262
+ stdin = mockStdin.stdin();
263
+ });
264
+
265
+ afterEach(() => {
266
+ stdin.restore();
267
+ });
268
+
269
+ it('accepts confirmation', async () => {
270
+ // Schedule input after prompt appears
271
+ setTimeout(() => {
272
+ stdin.send('y\n');
273
+ }, 10);
274
+
275
+ const result = await confirmAction('Delete?');
276
+
277
+ expect(result).toBe(true);
278
+ });
279
+ });
280
+ ```
281
+
282
+ ### Mocking stdout/stderr
283
+
284
+ ```go
285
+ // Go: Capture output
286
+ func TestOutputFormatting(t *testing.T) {
287
+ stdout := new(bytes.Buffer)
288
+ stderr := new(bytes.Buffer)
289
+
290
+ logger := NewLogger(stdout, stderr, LevelNormal)
291
+ logger.Info("Hello, world!")
292
+ logger.Error("Something went wrong")
293
+
294
+ assert.Contains(t, stdout.String(), "Hello, world!")
295
+ assert.Contains(t, stderr.String(), "Something went wrong")
296
+ }
297
+ ```
298
+
299
+ ```typescript
300
+ // TypeScript: Mock console
301
+ describe('output formatting', () => {
302
+ let consoleOutput: string[] = [];
303
+ let consoleError: string[] = [];
304
+
305
+ beforeEach(() => {
306
+ consoleOutput = [];
307
+ consoleError = [];
308
+ jest.spyOn(console, 'log').mockImplementation((...args) => {
309
+ consoleOutput.push(args.join(' '));
310
+ });
311
+ jest.spyOn(console, 'error').mockImplementation((...args) => {
312
+ consoleError.push(args.join(' '));
313
+ });
314
+ });
315
+
316
+ afterEach(() => {
317
+ jest.restoreAllMocks();
318
+ });
319
+
320
+ it('prints info to stdout', () => {
321
+ logger.info('Hello, world!');
322
+ expect(consoleOutput).toContain('Hello, world!');
323
+ });
324
+ });
325
+ ```
326
+
327
+ ### Mocking File System
328
+
329
+ ```go
330
+ // Go: Use interfaces for file system
331
+ type FileSystem interface {
332
+ ReadFile(path string) ([]byte, error)
333
+ WriteFile(path string, data []byte, perm os.FileMode) error
334
+ Exists(path string) bool
335
+ }
336
+
337
+ // Real implementation
338
+ type OSFileSystem struct{}
339
+
340
+ func (fs *OSFileSystem) ReadFile(path string) ([]byte, error) {
341
+ return os.ReadFile(path)
342
+ }
343
+
344
+ // Mock implementation
345
+ type MockFileSystem struct {
346
+ Files map[string][]byte
347
+ Err error
348
+ }
349
+
350
+ func (fs *MockFileSystem) ReadFile(path string) ([]byte, error) {
351
+ if fs.Err != nil {
352
+ return nil, fs.Err
353
+ }
354
+ data, ok := fs.Files[path]
355
+ if !ok {
356
+ return nil, os.ErrNotExist
357
+ }
358
+ return data, nil
359
+ }
360
+
361
+ // Test
362
+ func TestLoadConfig(t *testing.T) {
363
+ mockFS := &MockFileSystem{
364
+ Files: map[string][]byte{
365
+ "/config.yaml": []byte("key: value"),
366
+ },
367
+ }
368
+
369
+ loader := NewConfigLoader(mockFS)
370
+ config, err := loader.Load("/config.yaml")
371
+
372
+ require.NoError(t, err)
373
+ assert.Equal(t, "value", config.Key)
374
+ }
375
+ ```
376
+
377
+ ### Mocking Network
378
+
379
+ ```go
380
+ // Go: Use httptest for API mocking
381
+ func TestAPIClient(t *testing.T) {
382
+ server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
383
+ assert.Equal(t, "/api/projects", r.URL.Path)
384
+ w.Header().Set("Content-Type", "application/json")
385
+ json.NewEncoder(w).Encode([]Project{{Name: "test"}})
386
+ }))
387
+ defer server.Close()
388
+
389
+ client := NewAPIClient(server.URL)
390
+ projects, err := client.ListProjects()
391
+
392
+ require.NoError(t, err)
393
+ assert.Len(t, projects, 1)
394
+ assert.Equal(t, "test", projects[0].Name)
395
+ }
396
+ ```
397
+
398
+ ## Snapshot Testing
399
+
400
+ ### Output Snapshots
401
+
402
+ ```go
403
+ // Go: Snapshot testing with golden files
404
+ func TestHelpOutput(t *testing.T) {
405
+ cmd := NewRootCmd()
406
+ cmd.SetArgs([]string{"--help"})
407
+
408
+ output := new(bytes.Buffer)
409
+ cmd.SetOut(output)
410
+ cmd.Execute()
411
+
412
+ golden := filepath.Join("testdata", "help.golden")
413
+
414
+ if *update {
415
+ // Update golden file
416
+ os.WriteFile(golden, output.Bytes(), 0644)
417
+ }
418
+
419
+ expected, err := os.ReadFile(golden)
420
+ require.NoError(t, err)
421
+ assert.Equal(t, string(expected), output.String())
422
+ }
423
+ ```
424
+
425
+ ```typescript
426
+ // TypeScript with Jest snapshots
427
+ describe('help output', () => {
428
+ it('matches snapshot', () => {
429
+ const output = execSync('node ./bin/cli.js --help', {
430
+ encoding: 'utf-8',
431
+ });
432
+
433
+ expect(output).toMatchSnapshot();
434
+ });
435
+ });
436
+ ```
437
+
438
+ ## Test Organization
439
+
440
+ ### Directory Structure
441
+
442
+ ```
443
+ tests/
444
+ ├── unit/
445
+ │ ├── config_test.go
446
+ │ ├── build_test.go
447
+ │ └── output_test.go
448
+ ├── integration/
449
+ │ ├── build_command_test.go
450
+ │ ├── deploy_command_test.go
451
+ │ └── interactive_test.go
452
+ ├── e2e/
453
+ │ ├── full_workflow_test.go
454
+ │ └── ci_environment_test.go
455
+ ├── fixtures/
456
+ │ ├── valid_project/
457
+ │ ├── invalid_config/
458
+ │ └── large_project/
459
+ └── testdata/
460
+ ├── help.golden
461
+ └── version.golden
462
+ ```
463
+
464
+ ### Test Helpers
465
+
466
+ ```go
467
+ // Go: Common test helpers
468
+ // testutil/setup.go
469
+ func SetupTestProject(t *testing.T) string {
470
+ t.Helper()
471
+
472
+ dir := t.TempDir()
473
+
474
+ // Create test files
475
+ os.WriteFile(filepath.Join(dir, "main.ts"), []byte("console.log('hi')"), 0644)
476
+ os.WriteFile(filepath.Join(dir, "package.json"), []byte("{}"), 0644)
477
+
478
+ return dir
479
+ }
480
+
481
+ func CaptureOutput(t *testing.T, cmd *cobra.Command) (stdout, stderr string) {
482
+ t.Helper()
483
+
484
+ outBuf := new(bytes.Buffer)
485
+ errBuf := new(bytes.Buffer)
486
+
487
+ cmd.SetOut(outBuf)
488
+ cmd.SetErr(errBuf)
489
+
490
+ return outBuf.String(), errBuf.String()
491
+ }
492
+ ```
493
+
494
+ ## CI Considerations
495
+
496
+ ### Environment Detection
497
+
498
+ ```go
499
+ // Tests should handle CI environment
500
+ func TestProgressBar(t *testing.T) {
501
+ if os.Getenv("CI") != "" {
502
+ t.Skip("Skipping interactive test in CI")
503
+ }
504
+
505
+ // Test interactive progress bar
506
+ }
507
+ ```
508
+
509
+ ### Parallelization
510
+
511
+ ```go
512
+ // Go: Run tests in parallel
513
+ func TestBuild(t *testing.T) {
514
+ t.Parallel()
515
+
516
+ // Test uses t.TempDir() which is safe for parallel tests
517
+ dir := t.TempDir()
518
+ // ...
519
+ }
520
+ ```
521
+
522
+ ### Test Timeouts
523
+
524
+ ```go
525
+ // Go: Set reasonable timeouts
526
+ func TestLongRunningCommand(t *testing.T) {
527
+ ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
528
+ defer cancel()
529
+
530
+ cmd := exec.CommandContext(ctx, "./mytool", "slow-command")
531
+ err := cmd.Run()
532
+
533
+ if ctx.Err() == context.DeadlineExceeded {
534
+ t.Fatal("Command timed out")
535
+ }
536
+ }
537
+ ```