javi-forge 1.2.0 → 1.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 (228) hide show
  1. package/ci-local/ci-local.sh +20 -8
  2. package/package.json +1 -1
  3. package/ai-config/.skillignore +0 -15
  4. package/ai-config/AUTO_INVOKE.md +0 -300
  5. package/ai-config/agents/_TEMPLATE.md +0 -93
  6. package/ai-config/agents/business/api-designer.md +0 -1657
  7. package/ai-config/agents/business/business-analyst.md +0 -1331
  8. package/ai-config/agents/business/product-strategist.md +0 -206
  9. package/ai-config/agents/business/project-manager.md +0 -178
  10. package/ai-config/agents/business/requirements-analyst.md +0 -1277
  11. package/ai-config/agents/business/technical-writer.md +0 -1679
  12. package/ai-config/agents/creative/ux-designer.md +0 -205
  13. package/ai-config/agents/data-ai/ai-engineer.md +0 -487
  14. package/ai-config/agents/data-ai/analytics-engineer.md +0 -953
  15. package/ai-config/agents/data-ai/data-engineer.md +0 -173
  16. package/ai-config/agents/data-ai/data-scientist.md +0 -672
  17. package/ai-config/agents/data-ai/mlops-engineer.md +0 -814
  18. package/ai-config/agents/data-ai/prompt-engineer.md +0 -772
  19. package/ai-config/agents/development/angular-expert.md +0 -620
  20. package/ai-config/agents/development/backend-architect.md +0 -795
  21. package/ai-config/agents/development/database-specialist.md +0 -212
  22. package/ai-config/agents/development/frontend-specialist.md +0 -686
  23. package/ai-config/agents/development/fullstack-engineer.md +0 -668
  24. package/ai-config/agents/development/golang-pro.md +0 -338
  25. package/ai-config/agents/development/java-enterprise.md +0 -400
  26. package/ai-config/agents/development/javascript-pro.md +0 -422
  27. package/ai-config/agents/development/nextjs-pro.md +0 -474
  28. package/ai-config/agents/development/python-pro.md +0 -570
  29. package/ai-config/agents/development/react-pro.md +0 -487
  30. package/ai-config/agents/development/rust-pro.md +0 -246
  31. package/ai-config/agents/development/spring-boot-4-expert.md +0 -326
  32. package/ai-config/agents/development/typescript-pro.md +0 -336
  33. package/ai-config/agents/development/vue-specialist.md +0 -605
  34. package/ai-config/agents/infrastructure/cloud-architect.md +0 -472
  35. package/ai-config/agents/infrastructure/deployment-manager.md +0 -358
  36. package/ai-config/agents/infrastructure/devops-engineer.md +0 -455
  37. package/ai-config/agents/infrastructure/incident-responder.md +0 -519
  38. package/ai-config/agents/infrastructure/kubernetes-expert.md +0 -705
  39. package/ai-config/agents/infrastructure/monitoring-specialist.md +0 -674
  40. package/ai-config/agents/infrastructure/performance-engineer.md +0 -658
  41. package/ai-config/agents/orchestrator.md +0 -241
  42. package/ai-config/agents/quality/accessibility-auditor.md +0 -1204
  43. package/ai-config/agents/quality/code-reviewer-compact.md +0 -123
  44. package/ai-config/agents/quality/code-reviewer.md +0 -363
  45. package/ai-config/agents/quality/dependency-manager.md +0 -743
  46. package/ai-config/agents/quality/e2e-test-specialist.md +0 -1005
  47. package/ai-config/agents/quality/performance-tester.md +0 -1086
  48. package/ai-config/agents/quality/security-auditor.md +0 -133
  49. package/ai-config/agents/quality/test-engineer.md +0 -453
  50. package/ai-config/agents/specialists/api-designer.md +0 -87
  51. package/ai-config/agents/specialists/backend-architect.md +0 -73
  52. package/ai-config/agents/specialists/code-reviewer.md +0 -77
  53. package/ai-config/agents/specialists/db-optimizer.md +0 -75
  54. package/ai-config/agents/specialists/devops-engineer.md +0 -83
  55. package/ai-config/agents/specialists/documentation-writer.md +0 -78
  56. package/ai-config/agents/specialists/frontend-developer.md +0 -75
  57. package/ai-config/agents/specialists/performance-analyst.md +0 -82
  58. package/ai-config/agents/specialists/refactor-specialist.md +0 -74
  59. package/ai-config/agents/specialists/security-auditor.md +0 -74
  60. package/ai-config/agents/specialists/test-engineer.md +0 -81
  61. package/ai-config/agents/specialists/ux-consultant.md +0 -76
  62. package/ai-config/agents/specialized/agent-generator.md +0 -1190
  63. package/ai-config/agents/specialized/blockchain-developer.md +0 -149
  64. package/ai-config/agents/specialized/code-migrator.md +0 -892
  65. package/ai-config/agents/specialized/context-manager.md +0 -978
  66. package/ai-config/agents/specialized/documentation-writer.md +0 -1078
  67. package/ai-config/agents/specialized/ecommerce-expert.md +0 -1756
  68. package/ai-config/agents/specialized/embedded-engineer.md +0 -1714
  69. package/ai-config/agents/specialized/error-detective.md +0 -1034
  70. package/ai-config/agents/specialized/fintech-specialist.md +0 -1659
  71. package/ai-config/agents/specialized/freelance-project-planner-v2.md +0 -1988
  72. package/ai-config/agents/specialized/freelance-project-planner-v3.md +0 -2136
  73. package/ai-config/agents/specialized/freelance-project-planner-v4.md +0 -4503
  74. package/ai-config/agents/specialized/freelance-project-planner.md +0 -722
  75. package/ai-config/agents/specialized/game-developer.md +0 -1963
  76. package/ai-config/agents/specialized/healthcare-dev.md +0 -1620
  77. package/ai-config/agents/specialized/mobile-developer.md +0 -188
  78. package/ai-config/agents/specialized/parallel-plan-executor.md +0 -506
  79. package/ai-config/agents/specialized/plan-executor.md +0 -485
  80. package/ai-config/agents/specialized/solo-dev-planner-modular/00-INDEX.md +0 -485
  81. package/ai-config/agents/specialized/solo-dev-planner-modular/01-CORE.md +0 -3493
  82. package/ai-config/agents/specialized/solo-dev-planner-modular/02-SELF-CORRECTION.md +0 -778
  83. package/ai-config/agents/specialized/solo-dev-planner-modular/03-PROGRESSIVE-SETUP.md +0 -918
  84. package/ai-config/agents/specialized/solo-dev-planner-modular/04-DEPLOYMENT.md +0 -1537
  85. package/ai-config/agents/specialized/solo-dev-planner-modular/05-TESTING.md +0 -2633
  86. package/ai-config/agents/specialized/solo-dev-planner-modular/06-OPERATIONS.md +0 -5610
  87. package/ai-config/agents/specialized/solo-dev-planner-modular/INSTALL.md +0 -335
  88. package/ai-config/agents/specialized/solo-dev-planner-modular/QUICK-REFERENCE.txt +0 -215
  89. package/ai-config/agents/specialized/solo-dev-planner-modular/README.md +0 -260
  90. package/ai-config/agents/specialized/solo-dev-planner-modular/START-HERE.md +0 -379
  91. package/ai-config/agents/specialized/solo-dev-planner-modular/WORKFLOW-DIAGRAM.md +0 -355
  92. package/ai-config/agents/specialized/solo-dev-planner-modular/solo-dev-planner.md +0 -279
  93. package/ai-config/agents/specialized/template-writer.md +0 -347
  94. package/ai-config/agents/specialized/test-runner.md +0 -99
  95. package/ai-config/agents/specialized/vibekanban-smart-worker.md +0 -244
  96. package/ai-config/agents/specialized/wave-executor.md +0 -138
  97. package/ai-config/agents/specialized/workflow-optimizer.md +0 -1114
  98. package/ai-config/commands/git/changelog.md +0 -32
  99. package/ai-config/commands/git/ci-local.md +0 -70
  100. package/ai-config/commands/git/commit.md +0 -35
  101. package/ai-config/commands/git/fix-issue.md +0 -23
  102. package/ai-config/commands/git/pr-create.md +0 -42
  103. package/ai-config/commands/git/pr-review.md +0 -50
  104. package/ai-config/commands/git/worktree.md +0 -39
  105. package/ai-config/commands/refactoring/cleanup.md +0 -24
  106. package/ai-config/commands/refactoring/dead-code.md +0 -40
  107. package/ai-config/commands/refactoring/extract.md +0 -31
  108. package/ai-config/commands/testing/e2e.md +0 -30
  109. package/ai-config/commands/testing/tdd.md +0 -36
  110. package/ai-config/commands/testing/test-coverage.md +0 -30
  111. package/ai-config/commands/testing/test-fix.md +0 -24
  112. package/ai-config/commands/workflow/generate-agents-md.md +0 -85
  113. package/ai-config/commands/workflow/planning.md +0 -47
  114. package/ai-config/commands/workflows/compound.md +0 -89
  115. package/ai-config/commands/workflows/diagnose.md +0 -70
  116. package/ai-config/commands/workflows/discover.md +0 -86
  117. package/ai-config/commands/workflows/plan.md +0 -77
  118. package/ai-config/commands/workflows/review.md +0 -78
  119. package/ai-config/commands/workflows/work.md +0 -75
  120. package/ai-config/config.yaml +0 -18
  121. package/ai-config/hooks/_TEMPLATE.md +0 -96
  122. package/ai-config/hooks/block-dangerous-commands.md +0 -75
  123. package/ai-config/hooks/commit-guard.md +0 -90
  124. package/ai-config/hooks/context-loader.md +0 -73
  125. package/ai-config/hooks/improve-prompt.md +0 -91
  126. package/ai-config/hooks/learning-log.md +0 -72
  127. package/ai-config/hooks/model-router.md +0 -86
  128. package/ai-config/hooks/secret-scanner.md +0 -64
  129. package/ai-config/hooks/skill-validator.md +0 -102
  130. package/ai-config/hooks/task-artifact.md +0 -114
  131. package/ai-config/hooks/validate-workflow.md +0 -100
  132. package/ai-config/prompts/base.md +0 -71
  133. package/ai-config/prompts/modes/debug.md +0 -34
  134. package/ai-config/prompts/modes/deploy.md +0 -40
  135. package/ai-config/prompts/modes/research.md +0 -32
  136. package/ai-config/prompts/modes/review.md +0 -33
  137. package/ai-config/prompts/review-policy.md +0 -79
  138. package/ai-config/skills/_TEMPLATE.md +0 -157
  139. package/ai-config/skills/backend/api-gateway/SKILL.md +0 -254
  140. package/ai-config/skills/backend/bff-concepts/SKILL.md +0 -239
  141. package/ai-config/skills/backend/bff-spring/SKILL.md +0 -364
  142. package/ai-config/skills/backend/chi-router/SKILL.md +0 -396
  143. package/ai-config/skills/backend/error-handling/SKILL.md +0 -255
  144. package/ai-config/skills/backend/exceptions-spring/SKILL.md +0 -323
  145. package/ai-config/skills/backend/fastapi/SKILL.md +0 -302
  146. package/ai-config/skills/backend/gateway-spring/SKILL.md +0 -390
  147. package/ai-config/skills/backend/go-backend/SKILL.md +0 -457
  148. package/ai-config/skills/backend/gradle-multimodule/SKILL.md +0 -274
  149. package/ai-config/skills/backend/graphql-concepts/SKILL.md +0 -352
  150. package/ai-config/skills/backend/graphql-spring/SKILL.md +0 -398
  151. package/ai-config/skills/backend/grpc-concepts/SKILL.md +0 -283
  152. package/ai-config/skills/backend/grpc-spring/SKILL.md +0 -445
  153. package/ai-config/skills/backend/jwt-auth/SKILL.md +0 -412
  154. package/ai-config/skills/backend/notifications-concepts/SKILL.md +0 -259
  155. package/ai-config/skills/backend/recommendations-concepts/SKILL.md +0 -261
  156. package/ai-config/skills/backend/search-concepts/SKILL.md +0 -263
  157. package/ai-config/skills/backend/search-spring/SKILL.md +0 -375
  158. package/ai-config/skills/backend/spring-boot-4/SKILL.md +0 -172
  159. package/ai-config/skills/backend/websockets/SKILL.md +0 -532
  160. package/ai-config/skills/data-ai/ai-ml/SKILL.md +0 -423
  161. package/ai-config/skills/data-ai/analytics-concepts/SKILL.md +0 -195
  162. package/ai-config/skills/data-ai/analytics-spring/SKILL.md +0 -340
  163. package/ai-config/skills/data-ai/duckdb-analytics/SKILL.md +0 -440
  164. package/ai-config/skills/data-ai/langchain/SKILL.md +0 -238
  165. package/ai-config/skills/data-ai/mlflow/SKILL.md +0 -302
  166. package/ai-config/skills/data-ai/onnx-inference/SKILL.md +0 -290
  167. package/ai-config/skills/data-ai/powerbi/SKILL.md +0 -352
  168. package/ai-config/skills/data-ai/pytorch/SKILL.md +0 -274
  169. package/ai-config/skills/data-ai/scikit-learn/SKILL.md +0 -321
  170. package/ai-config/skills/data-ai/vector-db/SKILL.md +0 -301
  171. package/ai-config/skills/database/graph-databases/SKILL.md +0 -218
  172. package/ai-config/skills/database/graph-spring/SKILL.md +0 -361
  173. package/ai-config/skills/database/pgx-postgres/SKILL.md +0 -512
  174. package/ai-config/skills/database/redis-cache/SKILL.md +0 -343
  175. package/ai-config/skills/database/sqlite-embedded/SKILL.md +0 -388
  176. package/ai-config/skills/database/timescaledb/SKILL.md +0 -320
  177. package/ai-config/skills/docs/api-documentation/SKILL.md +0 -293
  178. package/ai-config/skills/docs/docs-spring/SKILL.md +0 -377
  179. package/ai-config/skills/docs/mustache-templates/SKILL.md +0 -190
  180. package/ai-config/skills/docs/technical-docs/SKILL.md +0 -447
  181. package/ai-config/skills/frontend/astro-ssr/SKILL.md +0 -441
  182. package/ai-config/skills/frontend/frontend-design/SKILL.md +0 -54
  183. package/ai-config/skills/frontend/frontend-web/SKILL.md +0 -368
  184. package/ai-config/skills/frontend/mantine-ui/SKILL.md +0 -396
  185. package/ai-config/skills/frontend/tanstack-query/SKILL.md +0 -439
  186. package/ai-config/skills/frontend/zod-validation/SKILL.md +0 -417
  187. package/ai-config/skills/frontend/zustand-state/SKILL.md +0 -350
  188. package/ai-config/skills/infrastructure/chaos-engineering/SKILL.md +0 -244
  189. package/ai-config/skills/infrastructure/chaos-spring/SKILL.md +0 -378
  190. package/ai-config/skills/infrastructure/devops-infra/SKILL.md +0 -435
  191. package/ai-config/skills/infrastructure/docker-containers/SKILL.md +0 -420
  192. package/ai-config/skills/infrastructure/kubernetes/SKILL.md +0 -456
  193. package/ai-config/skills/infrastructure/opentelemetry/SKILL.md +0 -546
  194. package/ai-config/skills/infrastructure/traefik-proxy/SKILL.md +0 -474
  195. package/ai-config/skills/infrastructure/woodpecker-ci/SKILL.md +0 -315
  196. package/ai-config/skills/mobile/ionic-capacitor/SKILL.md +0 -504
  197. package/ai-config/skills/mobile/mobile-ionic/SKILL.md +0 -448
  198. package/ai-config/skills/prompt-improver/SKILL.md +0 -125
  199. package/ai-config/skills/quality/ghagga-review/SKILL.md +0 -216
  200. package/ai-config/skills/references/hooks-patterns/SKILL.md +0 -238
  201. package/ai-config/skills/references/mcp-servers/SKILL.md +0 -275
  202. package/ai-config/skills/references/plugins-reference/SKILL.md +0 -110
  203. package/ai-config/skills/references/skills-reference/SKILL.md +0 -420
  204. package/ai-config/skills/references/subagent-templates/SKILL.md +0 -193
  205. package/ai-config/skills/systems-iot/modbus-protocol/SKILL.md +0 -410
  206. package/ai-config/skills/systems-iot/mqtt-rumqttc/SKILL.md +0 -408
  207. package/ai-config/skills/systems-iot/rust-systems/SKILL.md +0 -386
  208. package/ai-config/skills/systems-iot/tokio-async/SKILL.md +0 -324
  209. package/ai-config/skills/testing/playwright-e2e/SKILL.md +0 -289
  210. package/ai-config/skills/testing/testcontainers/SKILL.md +0 -299
  211. package/ai-config/skills/testing/vitest-testing/SKILL.md +0 -381
  212. package/ai-config/skills/workflow/ci-local-guide/SKILL.md +0 -118
  213. package/ai-config/skills/workflow/claude-automation-recommender/SKILL.md +0 -299
  214. package/ai-config/skills/workflow/claude-md-improver/SKILL.md +0 -158
  215. package/ai-config/skills/workflow/finishing-a-development-branch/SKILL.md +0 -117
  216. package/ai-config/skills/workflow/git-github/SKILL.md +0 -334
  217. package/ai-config/skills/workflow/git-github/references/examples.md +0 -160
  218. package/ai-config/skills/workflow/git-workflow/SKILL.md +0 -214
  219. package/ai-config/skills/workflow/ide-plugins/SKILL.md +0 -277
  220. package/ai-config/skills/workflow/ide-plugins-intellij/SKILL.md +0 -401
  221. package/ai-config/skills/workflow/obsidian-brain-workflow/SKILL.md +0 -199
  222. package/ai-config/skills/workflow/using-git-worktrees/SKILL.md +0 -100
  223. package/ai-config/skills/workflow/verification-before-completion/SKILL.md +0 -73
  224. package/ai-config/skills/workflow/wave-workflow/SKILL.md +0 -178
  225. package/schemas/agent.schema.json +0 -34
  226. package/schemas/ai-config.schema.json +0 -28
  227. package/schemas/plugin.schema.json +0 -62
  228. package/schemas/skill.schema.json +0 -44
@@ -1,381 +0,0 @@
1
- ---
2
- name: vitest-testing
3
- description: >
4
- Frontend testing patterns with Vitest, Testing Library, and MSW for React applications.
5
- Trigger: Vitest, testing library, MSW, frontend testing, React testing, unit test, component test
6
- tools:
7
- - Read
8
- - Write
9
- - Bash
10
- - Grep
11
- metadata:
12
- author: plataforma-industrial
13
- version: "2.0"
14
- tags: [vitest, testing, react, msw, testing-library, frontend]
15
- updated: "2026-02"
16
- ---
17
-
18
- # Frontend Testing with Vitest
19
-
20
- Comprehensive testing patterns for React applications with Vitest, Testing Library, and MSW.
21
-
22
- ## Stack
23
-
24
- ```yaml
25
- Vitest: 1.3+
26
- @testing-library/react: 14.2+
27
- @testing-library/user-event: 14.5+
28
- MSW: 2.2+
29
- happy-dom: 13.3+
30
- ```
31
-
32
- ## Configuration
33
-
34
- ### vitest.config.ts
35
-
36
- ```typescript
37
- import { defineConfig } from 'vitest/config';
38
- import react from '@vitejs/plugin-react';
39
- import { resolve } from 'path';
40
-
41
- export default defineConfig({
42
- plugins: [react()],
43
- test: {
44
- globals: true,
45
- environment: 'happy-dom',
46
- setupFiles: ['./src/test/setup.ts'],
47
- include: ['src/**/*.{test,spec}.{ts,tsx}'],
48
- coverage: {
49
- provider: 'v8',
50
- reporter: ['text', 'json', 'html'],
51
- thresholds: {
52
- global: { branches: 80, functions: 80, lines: 80, statements: 80 },
53
- },
54
- },
55
- },
56
- resolve: {
57
- alias: {
58
- '@': resolve(__dirname, './src'),
59
- },
60
- },
61
- });
62
- ```
63
-
64
- ### Setup File
65
-
66
- ```typescript
67
- // src/test/setup.ts
68
- import '@testing-library/jest-dom/vitest';
69
- import { cleanup } from '@testing-library/react';
70
- import { afterEach, beforeAll, afterAll, vi } from 'vitest';
71
- import { server } from '@/mocks/server';
72
-
73
- // Mock matchMedia
74
- Object.defineProperty(window, 'matchMedia', {
75
- writable: true,
76
- value: vi.fn().mockImplementation((query) => ({
77
- matches: false,
78
- media: query,
79
- addEventListener: vi.fn(),
80
- removeEventListener: vi.fn(),
81
- })),
82
- });
83
-
84
- // MSW Server
85
- beforeAll(() => server.listen({ onUnhandledRequest: 'error' }));
86
- afterEach(() => {
87
- cleanup();
88
- server.resetHandlers();
89
- });
90
- afterAll(() => server.close());
91
- ```
92
-
93
- ## Component Testing
94
-
95
- ```typescript
96
- // src/components/Card/Card.test.tsx
97
- import { describe, it, expect, vi } from 'vitest';
98
- import { render, screen } from '@testing-library/react';
99
- import userEvent from '@testing-library/user-event';
100
- import { Card } from './Card';
101
-
102
- const mockItem = {
103
- id: 'item-1',
104
- name: 'Test Item',
105
- status: 'active',
106
- };
107
-
108
- describe('Card', () => {
109
- it('renders item information', () => {
110
- render(<Card item={mockItem} />);
111
-
112
- expect(screen.getByText('Test Item')).toBeInTheDocument();
113
- expect(screen.getByText('active')).toBeInTheDocument();
114
- });
115
-
116
- it('calls onClick when clicked', async () => {
117
- const user = userEvent.setup();
118
- const onClick = vi.fn();
119
-
120
- render(<Card item={mockItem} onClick={onClick} />);
121
- await user.click(screen.getByRole('article'));
122
-
123
- expect(onClick).toHaveBeenCalledWith(mockItem.id);
124
- });
125
-
126
- it('shows alert status when flagged', () => {
127
- const alertItem = { ...mockItem, status: 'alert' };
128
- render(<Card item={alertItem} />);
129
-
130
- expect(screen.getByRole('alert')).toBeInTheDocument();
131
- });
132
- });
133
- ```
134
-
135
- ## Hook Testing
136
-
137
- ```typescript
138
- // src/hooks/useData.test.ts
139
- import { describe, it, expect } from 'vitest';
140
- import { renderHook, waitFor } from '@testing-library/react';
141
- import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
142
- import { useData } from './useData';
143
-
144
- const createWrapper = () => {
145
- const queryClient = new QueryClient({
146
- defaultOptions: { queries: { retry: false, gcTime: 0 } },
147
- });
148
- return ({ children }: { children: React.ReactNode }) => (
149
- <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
150
- );
151
- };
152
-
153
- describe('useData', () => {
154
- it('fetches data successfully', async () => {
155
- const { result } = renderHook(() => useData('item-1'), {
156
- wrapper: createWrapper(),
157
- });
158
-
159
- expect(result.current.isLoading).toBe(true);
160
-
161
- await waitFor(() => {
162
- expect(result.current.isSuccess).toBe(true);
163
- });
164
-
165
- expect(result.current.data).toEqual(
166
- expect.objectContaining({ id: 'item-1' })
167
- );
168
- });
169
-
170
- it('handles error state', async () => {
171
- const { result } = renderHook(() => useData('non-existent'), {
172
- wrapper: createWrapper(),
173
- });
174
-
175
- await waitFor(() => {
176
- expect(result.current.isError).toBe(true);
177
- });
178
- });
179
- });
180
- ```
181
-
182
- ## Store Testing (Zustand)
183
-
184
- ```typescript
185
- // src/stores/store.test.ts
186
- import { describe, it, expect, beforeEach } from 'vitest';
187
- import { useStore } from './store';
188
-
189
- describe('Store', () => {
190
- beforeEach(() => {
191
- useStore.setState({ items: [], selectedId: null });
192
- });
193
-
194
- it('adds item to store', () => {
195
- const { addItem } = useStore.getState();
196
-
197
- addItem({ id: 'item-1', name: 'Test' });
198
-
199
- expect(useStore.getState().items).toHaveLength(1);
200
- });
201
-
202
- it('selects item', () => {
203
- const { selectItem } = useStore.getState();
204
-
205
- selectItem('item-1');
206
-
207
- expect(useStore.getState().selectedId).toBe('item-1');
208
- });
209
- });
210
- ```
211
-
212
- ## MSW Setup
213
-
214
- ### Server
215
-
216
- ```typescript
217
- // src/mocks/server.ts
218
- import { setupServer } from 'msw/node';
219
- import { handlers } from './handlers';
220
-
221
- export const server = setupServer(...handlers);
222
- ```
223
-
224
- ### Handlers
225
-
226
- ```typescript
227
- // src/mocks/handlers.ts
228
- import { http, HttpResponse, delay } from 'msw';
229
-
230
- const API_URL = 'http://localhost:8080/api/v1';
231
-
232
- const items = [
233
- { id: 'item-1', name: 'Item A', status: 'active' },
234
- { id: 'item-2', name: 'Item B', status: 'inactive' },
235
- ];
236
-
237
- export const handlers = [
238
- http.get(`${API_URL}/items`, async () => {
239
- await delay(100);
240
- return HttpResponse.json({ data: items });
241
- }),
242
-
243
- http.get(`${API_URL}/items/:id`, async ({ params }) => {
244
- const item = items.find((i) => i.id === params.id);
245
- if (!item) return new HttpResponse(null, { status: 404 });
246
- return HttpResponse.json(item);
247
- }),
248
-
249
- http.post(`${API_URL}/items`, async ({ request }) => {
250
- const body = await request.json();
251
- return HttpResponse.json({ id: crypto.randomUUID(), ...body });
252
- }),
253
- ];
254
- ```
255
-
256
- ### Override in Tests
257
-
258
- ```typescript
259
- import { server } from '@/mocks/server';
260
- import { http, HttpResponse } from 'msw';
261
-
262
- it('handles server error gracefully', async () => {
263
- server.use(
264
- http.get('http://localhost:8080/api/v1/items', () => {
265
- return new HttpResponse(null, { status: 500 });
266
- })
267
- );
268
-
269
- render(<ItemList />);
270
-
271
- await waitFor(() => {
272
- expect(screen.getByText(/error loading/i)).toBeInTheDocument();
273
- });
274
- });
275
- ```
276
-
277
- ## Testing with Providers
278
-
279
- ```typescript
280
- // src/test/utils.tsx
281
- import { MantineProvider } from '@mantine/core';
282
- import { render, RenderOptions } from '@testing-library/react';
283
- import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
284
-
285
- export function AllProviders({ children }: { children: React.ReactNode }) {
286
- const queryClient = new QueryClient({
287
- defaultOptions: { queries: { retry: false } },
288
- });
289
-
290
- return (
291
- <QueryClientProvider client={queryClient}>
292
- <MantineProvider>{children}</MantineProvider>
293
- </QueryClientProvider>
294
- );
295
- }
296
-
297
- export function renderWithProviders(
298
- ui: React.ReactElement,
299
- options?: Omit<RenderOptions, 'wrapper'>
300
- ) {
301
- return render(ui, { wrapper: AllProviders, ...options });
302
- }
303
-
304
- export * from '@testing-library/react';
305
- export { renderWithProviders as render };
306
- ```
307
-
308
- ## Form Testing
309
-
310
- ```typescript
311
- // src/components/Form/Form.test.tsx
312
- import { describe, it, expect, vi } from 'vitest';
313
- import { render, screen, waitFor } from '@/test/utils';
314
- import userEvent from '@testing-library/user-event';
315
- import { Form } from './Form';
316
-
317
- describe('Form', () => {
318
- it('submits form with valid data', async () => {
319
- const user = userEvent.setup();
320
- const onSubmit = vi.fn();
321
-
322
- render(<Form onSubmit={onSubmit} />);
323
-
324
- await user.type(screen.getByLabelText(/name/i), 'Test Name');
325
- await user.selectOptions(screen.getByLabelText(/type/i), 'option1');
326
- await user.click(screen.getByRole('button', { name: /save/i }));
327
-
328
- await waitFor(() => {
329
- expect(onSubmit).toHaveBeenCalledWith({ name: 'Test Name', type: 'option1' });
330
- });
331
- });
332
-
333
- it('shows validation errors', async () => {
334
- const user = userEvent.setup();
335
-
336
- render(<Form onSubmit={vi.fn()} />);
337
- await user.click(screen.getByRole('button', { name: /save/i }));
338
-
339
- await waitFor(() => {
340
- expect(screen.getByText(/name is required/i)).toBeInTheDocument();
341
- });
342
- });
343
- });
344
- ```
345
-
346
- ## Scripts
347
-
348
- ```json
349
- {
350
- "scripts": {
351
- "test": "vitest",
352
- "test:run": "vitest run",
353
- "test:ui": "vitest --ui",
354
- "test:coverage": "vitest run --coverage"
355
- }
356
- }
357
- ```
358
-
359
- ## Best Practices
360
-
361
- 1. **Test behavior, not implementation** - Test what user sees
362
- 2. **Use user-event over fireEvent** - More realistic
363
- 3. **Query by role/label first** - Accessible queries
364
- 4. **Use findBy for async** - `await screen.findByRole('alert')`
365
- 5. **Avoid testing library internals** - Test hook outputs
366
-
367
- ```typescript
368
- // Good - Accessible queries
369
- screen.getByRole('button', { name: /submit/i });
370
- screen.getByLabelText(/email/i);
371
-
372
- // Avoid - Implementation detail
373
- screen.getByTestId('submit-btn');
374
- ```
375
-
376
- ## Related Skills
377
-
378
- - `playwright-e2e`: E2E test complement
379
- - `tanstack-query`: Query testing patterns
380
- - `mantine-ui`: Component testing
381
- - `zod-validation`: Schema testing
@@ -1,118 +0,0 @@
1
- ---
2
- name: ci-local-guide
3
- description: >
4
- Guide for using CI-Local to run CI/CD locally before pushing.
5
- Trigger: run tests locally, CI simulation, pre-push validation, debugging CI failures, Docker CI
6
- tools:
7
- - Read
8
- - Bash
9
- - Grep
10
- metadata:
11
- author: project-starter-framework
12
- version: "2.0"
13
- tags: [ci-cd, testing, docker, pre-push, validation]
14
- updated: "2026-02"
15
- ---
16
-
17
- # CI-Local Guide
18
-
19
- Run your CI/CD pipeline locally before pushing to avoid broken builds in GitHub Actions.
20
-
21
- ## Quick Commands
22
-
23
- ### Check Stack Detection
24
- ```bash
25
- ./.ci-local/ci-local.sh detect # Linux/Mac
26
- .\.ci-local\ci-local.ps1 detect # Windows
27
- ```
28
-
29
- ### Quick Validation (pre-commit level)
30
- ```bash
31
- ./.ci-local/ci-local.sh quick # Lint + compile
32
- ```
33
-
34
- ### Full CI Simulation (pre-push level)
35
- ```bash
36
- ./.ci-local/ci-local.sh full # Complete CI in Docker
37
- ```
38
-
39
- ### Debug Mode (interactive shell)
40
- ```bash
41
- ./.ci-local/ci-local.sh shell # Opens bash in CI container
42
- ```
43
-
44
- ## Supported Stacks
45
-
46
- | Stack | Detection | Lint Command | Test Command |
47
- |-------|-----------|--------------|--------------|
48
- | Java/Gradle | `build.gradle(.kts)` | `./gradlew spotlessCheck` | `./gradlew test` |
49
- | Java/Maven | `pom.xml` | `./mvnw spotless:check` | `./mvnw test` |
50
- | Go | `go.mod` | `golangci-lint run` | `go test ./...` |
51
- | Rust | `Cargo.toml` | `cargo clippy` | `cargo test` |
52
- | Node.js | `package.json` | `npm run lint` | `npm test` |
53
- | Python | `pyproject.toml` | `ruff check .` | `pytest` |
54
-
55
- ## Git Hooks
56
-
57
- CI-Local installs these hooks automatically:
58
-
59
- | Hook | Trigger | Checks |
60
- |------|---------|--------|
61
- | `pre-commit` | `git commit` | AI attribution, lint, security (Semgrep) |
62
- | `commit-msg` | After message | No AI attribution in message |
63
- | `pre-push` | `git push` | Full CI in Docker container |
64
-
65
- ## Bypass Hooks (Emergency Only)
66
-
67
- ```bash
68
- git commit --no-verify # Skip pre-commit
69
- git push --no-verify # Skip pre-push
70
- ```
71
-
72
- **Warning**: Only use when absolutely necessary. You risk breaking CI.
73
-
74
- ## Troubleshooting
75
-
76
- ### "Docker not running"
77
- Start Docker Desktop or run `docker info` to verify.
78
-
79
- ### "Tests pass locally but fail in pre-push"
80
- That's the point! The pre-push uses Docker to replicate the exact CI environment.
81
- Debug with:
82
- ```bash
83
- ./.ci-local/ci-local.sh shell
84
- # You're now in the same environment as CI
85
- ```
86
-
87
- ### "Hook blocked my commit"
88
- Check the error message. Common causes:
89
- - AI attribution detected (remove `Co-authored-by: Claude` etc.)
90
- - Lint errors (run `./gradlew spotlessApply`)
91
- - Security issues (check Semgrep output)
92
-
93
- ## Configuration
94
-
95
- ### Add Custom Semgrep Rules
96
- Edit `.ci-local/semgrep.yml`:
97
- ```yaml
98
- rules:
99
- - id: my-custom-rule
100
- pattern: $DANGER_PATTERN
101
- message: "Dangerous pattern detected"
102
- severity: ERROR
103
- ```
104
-
105
- ### Modify CI Commands
106
- Edit the `detect_stack()` function in:
107
- - `.ci-local/ci-local.sh` (Linux/Mac)
108
- - `.ci-local/ci-local.ps1` (Windows)
109
-
110
- ## Philosophy
111
-
112
- > "If it passes locally, it MUST pass in CI."
113
-
114
- CI-Local ensures:
115
- 1. Same JDK/runtime version as CI
116
- 2. Same Docker image as GitHub Actions
117
- 3. No "works on my machine" syndrome
118
- 4. Fast feedback loop before push