@ranimontagna/agent-toolkit 0.1.6 → 0.1.7
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.
- package/README.md +28 -8
- package/package.json +1 -1
- package/skills/backend/go/golang-patterns/LICENSE +21 -0
- package/skills/backend/go/golang-patterns/NOTICE.md +10 -0
- package/skills/backend/go/golang-patterns/SKILL.md +674 -0
- package/skills/backend/go/golang-testing/LICENSE +21 -0
- package/skills/backend/go/golang-testing/NOTICE.md +10 -0
- package/skills/backend/go/golang-testing/SKILL.md +329 -0
- package/skills/backend/java/java-coding-standards/LICENSE +21 -0
- package/skills/backend/java/java-coding-standards/NOTICE.md +10 -0
- package/skills/backend/java/java-coding-standards/SKILL.md +383 -0
- package/skills/backend/java/java-junit/LICENSE +21 -0
- package/skills/backend/java/java-junit/NOTICE.md +10 -0
- package/skills/backend/java/java-junit/SKILL.md +64 -0
- package/skills/frontend/react/react-patterns/SKILL.md +4 -4
- package/skills/frontend/react/react-patterns/rules/react/LICENSE +21 -0
- package/skills/frontend/react/react-patterns/rules/react/NOTICE.md +11 -0
- package/skills/frontend/react/react-patterns/rules/react/coding-style.md +109 -0
- package/skills/frontend/react/react-patterns/rules/react/hooks.md +187 -0
- package/skills/frontend/react/react-patterns/rules/react/patterns.md +194 -0
- package/skills/frontend/react/react-patterns/rules/react/security.md +180 -0
- package/skills/frontend/react/react-patterns/rules/react/testing.md +208 -0
- package/skills/frontend/react/react-performance/SKILL.md +2 -2
- package/skills/frontend/react/react-performance/rules/react/LICENSE +21 -0
- package/skills/frontend/react/react-performance/rules/react/NOTICE.md +11 -0
- package/skills/frontend/react/react-performance/rules/react/coding-style.md +109 -0
- package/skills/frontend/react/react-performance/rules/react/hooks.md +187 -0
- package/skills/frontend/react/react-performance/rules/react/patterns.md +194 -0
- package/skills/frontend/react/react-performance/rules/react/security.md +180 -0
- package/skills/frontend/react/react-performance/rules/react/testing.md +208 -0
- package/skills/frontend/react/react-testing/SKILL.md +4 -4
- package/skills/frontend/react/react-testing/rules/react/LICENSE +21 -0
- package/skills/frontend/react/react-testing/rules/react/NOTICE.md +11 -0
- package/skills/frontend/react/react-testing/rules/react/coding-style.md +109 -0
- package/skills/frontend/react/react-testing/rules/react/hooks.md +187 -0
- package/skills/frontend/react/react-testing/rules/react/patterns.md +194 -0
- package/skills/frontend/react/react-testing/rules/react/security.md +180 -0
- package/skills/frontend/react/react-testing/rules/react/testing.md +208 -0
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
---
|
|
2
|
+
paths:
|
|
3
|
+
- "**/*.test.tsx"
|
|
4
|
+
- "**/*.test.jsx"
|
|
5
|
+
- "**/*.spec.tsx"
|
|
6
|
+
- "**/*.spec.jsx"
|
|
7
|
+
- "**/__tests__/**/*.ts"
|
|
8
|
+
- "**/__tests__/**/*.tsx"
|
|
9
|
+
---
|
|
10
|
+
# React Testing
|
|
11
|
+
|
|
12
|
+
> This file extends the upstream `typescript/testing.md` and `common/testing.md` rules with React specific content.
|
|
13
|
+
|
|
14
|
+
## Library Choice
|
|
15
|
+
|
|
16
|
+
- **React Testing Library (RTL)** — the standard for component testing. Tests behavior through the rendered DOM.
|
|
17
|
+
- **Vitest** — preferred runner for new Vite-based projects. Faster than Jest, native ESM, same API.
|
|
18
|
+
- **Jest** — still the default for Next.js / CRA projects. RTL works identically.
|
|
19
|
+
- **Playwright Component Testing** — when component tests need a real browser engine (animation, layout, complex events)
|
|
20
|
+
- **Cypress Component Testing** — alternative real-browser component runner
|
|
21
|
+
|
|
22
|
+
Pick one component test runner per project — do not mix RTL + Playwright CT in the same repo.
|
|
23
|
+
|
|
24
|
+
## Core Principle
|
|
25
|
+
|
|
26
|
+
Test what the user sees and does, not implementation details.
|
|
27
|
+
|
|
28
|
+
- Query by accessible role first, then label, then text — fall back to `data-testid` only when nothing else fits
|
|
29
|
+
- Never assert on internal state, props passed to children, or which hooks were called
|
|
30
|
+
- Refactor without breaking tests = the test was testing behavior; that is the goal
|
|
31
|
+
|
|
32
|
+
## Query Priority
|
|
33
|
+
|
|
34
|
+
RTL exposes queries in three families. Use this priority order top-down:
|
|
35
|
+
|
|
36
|
+
1. **Accessible to everyone**
|
|
37
|
+
- `getByRole(role, { name })` — primary choice
|
|
38
|
+
- `getByLabelText` — for form inputs
|
|
39
|
+
- `getByPlaceholderText` — when no label is available (and add a label)
|
|
40
|
+
- `getByText` — for non-interactive text
|
|
41
|
+
- `getByDisplayValue` — for form fields with a current value
|
|
42
|
+
|
|
43
|
+
2. **Semantic queries**
|
|
44
|
+
- `getByAltText` — for images
|
|
45
|
+
- `getByTitle` — last resort, low accessibility value
|
|
46
|
+
|
|
47
|
+
3. **Test IDs**
|
|
48
|
+
- `getByTestId("some-id")` — escape hatch only, when none of the above work
|
|
49
|
+
|
|
50
|
+
`getBy*` throws when no match. `queryBy*` returns null (use for asserting absence). `findBy*` returns a promise (use for async).
|
|
51
|
+
|
|
52
|
+
## User Interaction
|
|
53
|
+
|
|
54
|
+
Prefer `userEvent` over `fireEvent`. `userEvent` simulates real browser sequences (focus, keydown, beforeinput, input, keyup) — `fireEvent` dispatches a single synthetic event.
|
|
55
|
+
|
|
56
|
+
```tsx
|
|
57
|
+
import userEvent from "@testing-library/user-event";
|
|
58
|
+
|
|
59
|
+
test("submits the form", async () => {
|
|
60
|
+
const user = userEvent.setup();
|
|
61
|
+
render(<UserForm onSubmit={handleSubmit} />);
|
|
62
|
+
|
|
63
|
+
await user.type(screen.getByLabelText("Email"), "user@example.com");
|
|
64
|
+
await user.click(screen.getByRole("button", { name: /save/i }));
|
|
65
|
+
|
|
66
|
+
expect(handleSubmit).toHaveBeenCalledWith({ email: "user@example.com" });
|
|
67
|
+
});
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
- Always `await` `userEvent` calls — they are async
|
|
71
|
+
- Call `userEvent.setup()` once at the top of each test, then reuse the returned `user`
|
|
72
|
+
|
|
73
|
+
## Async Assertions
|
|
74
|
+
|
|
75
|
+
```tsx
|
|
76
|
+
// WRONG: synchronous query for async-rendered content
|
|
77
|
+
expect(screen.getByText("Loaded")).toBeInTheDocument(); // throws — not in DOM yet
|
|
78
|
+
|
|
79
|
+
// CORRECT: findBy* (returns a promise, retries)
|
|
80
|
+
expect(await screen.findByText("Loaded")).toBeInTheDocument();
|
|
81
|
+
|
|
82
|
+
// CORRECT: waitFor for non-element assertions
|
|
83
|
+
await waitFor(() => expect(saveSpy).toHaveBeenCalled());
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
- `findBy*` for async element appearance
|
|
87
|
+
- `waitFor` for async expectations on side effects or other matchers
|
|
88
|
+
- Never `setTimeout` + assertion — flaky
|
|
89
|
+
|
|
90
|
+
## Network Mocking with MSW
|
|
91
|
+
|
|
92
|
+
Use Mock Service Worker for any test that hits a network boundary. MSW runs at the network layer, so the component, hooks, and fetch library all behave as in production.
|
|
93
|
+
|
|
94
|
+
```tsx
|
|
95
|
+
// test setup
|
|
96
|
+
import { setupServer } from "msw/node";
|
|
97
|
+
import { http, HttpResponse } from "msw";
|
|
98
|
+
|
|
99
|
+
const server = setupServer(
|
|
100
|
+
http.get("/api/users/:id", ({ params }) =>
|
|
101
|
+
HttpResponse.json({ id: params.id, name: "Alice" }),
|
|
102
|
+
),
|
|
103
|
+
);
|
|
104
|
+
|
|
105
|
+
beforeAll(() => server.listen());
|
|
106
|
+
afterEach(() => server.resetHandlers());
|
|
107
|
+
afterAll(() => server.close());
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Per-test override:
|
|
111
|
+
|
|
112
|
+
```tsx
|
|
113
|
+
test("renders error on 500", async () => {
|
|
114
|
+
server.use(http.get("/api/users/:id", () => new HttpResponse(null, { status: 500 })));
|
|
115
|
+
render(<UserPage id="1" />);
|
|
116
|
+
expect(await screen.findByText(/something went wrong/i)).toBeInTheDocument();
|
|
117
|
+
});
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Avoid Snapshot Tests for Components
|
|
121
|
+
|
|
122
|
+
Snapshots of rendered output are brittle, hard to review, and rubber-stamped by reviewers. Use them only for:
|
|
123
|
+
|
|
124
|
+
- Pure data serialization (e.g., a transformer that produces a stable string)
|
|
125
|
+
- Catching unintended regressions in non-visual output
|
|
126
|
+
|
|
127
|
+
For component visual regression, use Playwright / Cypress / Percy screenshots — actual visual diffs, not DOM diffs.
|
|
128
|
+
|
|
129
|
+
## Test Setup Helpers
|
|
130
|
+
|
|
131
|
+
Wrap providers once:
|
|
132
|
+
|
|
133
|
+
```tsx
|
|
134
|
+
function renderWithProviders(ui: React.ReactElement) {
|
|
135
|
+
return render(
|
|
136
|
+
<QueryClientProvider client={new QueryClient()}>
|
|
137
|
+
<ThemeProvider theme={lightTheme}>
|
|
138
|
+
<Router>{ui}</Router>
|
|
139
|
+
</ThemeProvider>
|
|
140
|
+
</QueryClientProvider>,
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Export from `test-utils.tsx` and use everywhere.
|
|
146
|
+
|
|
147
|
+
## Custom Hook Testing
|
|
148
|
+
|
|
149
|
+
Use `renderHook` from RTL:
|
|
150
|
+
|
|
151
|
+
```tsx
|
|
152
|
+
import { renderHook, act } from "@testing-library/react";
|
|
153
|
+
|
|
154
|
+
test("useCounter increments", () => {
|
|
155
|
+
const { result } = renderHook(() => useCounter());
|
|
156
|
+
act(() => result.current.increment());
|
|
157
|
+
expect(result.current.count).toBe(1);
|
|
158
|
+
});
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
- Always wrap state-changing calls in `act`
|
|
162
|
+
- Always test through the public hook API, not internal implementation
|
|
163
|
+
|
|
164
|
+
## Accessibility Assertions
|
|
165
|
+
|
|
166
|
+
```tsx
|
|
167
|
+
import { axe } from "vitest-axe"; // or jest-axe
|
|
168
|
+
|
|
169
|
+
test("UserCard has no a11y violations", async () => {
|
|
170
|
+
const { container } = render(<UserCard user={mockUser} />);
|
|
171
|
+
expect(await axe(container)).toHaveNoViolations();
|
|
172
|
+
});
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
Run axe assertions in component tests — catches missing labels, ARIA misuse, color contrast (limited).
|
|
176
|
+
|
|
177
|
+
## When to Reach for Playwright / Cypress
|
|
178
|
+
|
|
179
|
+
Component test with RTL + JSDOM cannot:
|
|
180
|
+
|
|
181
|
+
- Test real layout (flexbox, grid, viewport-dependent rendering)
|
|
182
|
+
- Test scrolling, drag-and-drop, paste from clipboard
|
|
183
|
+
- Test browser-native animation, CSS transitions
|
|
184
|
+
- Test cross-frame interactions (iframes, popups)
|
|
185
|
+
|
|
186
|
+
For those, use Playwright Component Testing or end-to-end Playwright/Cypress runs. See the e2e-testing skill when it is installed.
|
|
187
|
+
|
|
188
|
+
## Coverage Targets
|
|
189
|
+
|
|
190
|
+
| Layer | Target |
|
|
191
|
+
|---|---|
|
|
192
|
+
| Pure utility functions | ≥90% |
|
|
193
|
+
| Custom hooks | ≥85% |
|
|
194
|
+
| Components (presentational) | ≥80% — behavior, not lines |
|
|
195
|
+
| Container components | ≥70% — golden paths + error states |
|
|
196
|
+
| Pages (E2E covered separately) | Smoke test per route minimum |
|
|
197
|
+
|
|
198
|
+
## Anti-Patterns
|
|
199
|
+
|
|
200
|
+
- Asserting on `container.querySelector` — bypasses accessibility queries
|
|
201
|
+
- Asserting on number of renders — implementation detail
|
|
202
|
+
- Mocking React hooks (`jest.mock("react", ...)`) — refactor the component instead
|
|
203
|
+
- Mocking child components by default — tests the integration, not the parent in isolation
|
|
204
|
+
- Manual `act()` warnings ignored — they indicate real bugs
|
|
205
|
+
|
|
206
|
+
## Skill Reference
|
|
207
|
+
|
|
208
|
+
See `skills/react-testing/SKILL.md` for end-to-end test examples, MSW patterns, and accessibility test scaffolding.
|