@loomfsm/bundle-code 0.1.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.
- package/LICENSE +201 -0
- package/agents/acceptance.md +141 -0
- package/agents/api-contract.md +89 -0
- package/agents/architect.md +52 -0
- package/agents/challenger-reviewer.md +104 -0
- package/agents/classifier.md +74 -0
- package/agents/code-analyzer.md +43 -0
- package/agents/context-doc-verifier.md +94 -0
- package/agents/dependency-auditor.md +42 -0
- package/agents/implementer.md +135 -0
- package/agents/logic-reviewer.md +132 -0
- package/agents/migration.md +55 -0
- package/agents/performance.md +95 -0
- package/agents/plan-conformance.md +127 -0
- package/agents/plan-grounding-check.md +106 -0
- package/agents/planner.md +143 -0
- package/agents/playwright.md +68 -0
- package/agents/research.md +52 -0
- package/agents/security.md +88 -0
- package/agents/style-reviewer.md +85 -0
- package/agents/test.md +206 -0
- package/agents/ui-consistency.md +75 -0
- package/dist/manifest.d.ts +2 -0
- package/dist/manifest.js +34 -0
- package/dist/manifest.js.map +1 -0
- package/dist/src/bundle.d.ts +2 -0
- package/dist/src/bundle.js +424 -0
- package/dist/src/bundle.js.map +1 -0
- package/dist/src/index.d.ts +5 -0
- package/dist/src/index.js +14 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/invariants.d.ts +10 -0
- package/dist/src/invariants.js +208 -0
- package/dist/src/invariants.js.map +1 -0
- package/dist/src/policy-resolver.d.ts +2 -0
- package/dist/src/policy-resolver.js +65 -0
- package/dist/src/policy-resolver.js.map +1 -0
- package/dist/src/sandbox-rules.d.ts +2 -0
- package/dist/src/sandbox-rules.js +40 -0
- package/dist/src/sandbox-rules.js.map +1 -0
- package/dist/test/bundle.test.d.ts +1 -0
- package/dist/test/bundle.test.js +289 -0
- package/dist/test/bundle.test.js.map +1 -0
- package/dist/test/sandbox-rules.test.d.ts +1 -0
- package/dist/test/sandbox-rules.test.js +73 -0
- package/dist/test/sandbox-rules.test.js.map +1 -0
- package/knowledge/references/api-design.md +188 -0
- package/knowledge/references/arch-patterns.md +106 -0
- package/knowledge/references/caching.md +190 -0
- package/knowledge/references/concurrency.md +195 -0
- package/knowledge/references/db-postgres.md +153 -0
- package/knowledge/references/e2e-flutter.md +56 -0
- package/knowledge/references/e2e-playwright.md +53 -0
- package/knowledge/references/error-handling.md +208 -0
- package/knowledge/references/next-app-router.md +231 -0
- package/knowledge/references/observability.md +169 -0
- package/knowledge/references/optimization-strategy.md +197 -0
- package/knowledge/references/perf-flutter.md +62 -0
- package/knowledge/references/perf-nestjs.md +59 -0
- package/knowledge/references/perf-python.md +50 -0
- package/knowledge/references/perf-react.md +52 -0
- package/knowledge/references/react19.md +176 -0
- package/knowledge/references/redis.md +175 -0
- package/knowledge/references/security-backend.md +219 -0
- package/knowledge/references/test-flutter.md +65 -0
- package/knowledge/references/test-nestjs.md +82 -0
- package/knowledge/references/test-python.md +76 -0
- package/knowledge/references/test-react.md +66 -0
- package/knowledge/references/test-strategy.md +175 -0
- package/knowledge/references/ui-flutter.md +56 -0
- package/knowledge/references/ui-web.md +51 -0
- package/package.json +34 -0
- package/schemas/agent-feedback.schema.json +80 -0
- package/schemas/category-vocab.json +170 -0
- package/schemas/classifier-output.schema.json +53 -0
- package/schemas/finding.schema.json +92 -0
- package/schemas/pipeline-state.schema.json +238 -0
- package/schemas/reviewer-output.schema.json +62 -0
- package/schemas/state-extension.schema.json +53 -0
- package/schemas/validator-output.schema.json +48 -0
- package/stack-candidates.yaml +248 -0
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
---
|
|
2
|
+
tags: [security, auth, authentication, authorization, jwt, oauth, secrets, backend]
|
|
3
|
+
stack_signals:
|
|
4
|
+
- project_type: [backend, monorepo]
|
|
5
|
+
summary: |
|
|
6
|
+
Backend security stance — input is hostile until proven otherwise. Covers
|
|
7
|
+
authentication, authorization, sessions, JWTs, cookies, secrets handling,
|
|
8
|
+
input validation, file uploads, SQL/NoSQL with user input, CORS/CSRF.
|
|
9
|
+
when_to_load: |
|
|
10
|
+
Task touches authentication, authorization, sessions, JWTs, cookies,
|
|
11
|
+
secrets/env vars, input validation, file uploads, SQL or NoSQL queries
|
|
12
|
+
with user input, server-side rendering of user content, CORS/CSRF
|
|
13
|
+
middleware, logging of user data, or password handling. Diff in auth/,
|
|
14
|
+
middleware/, routes/, controllers/, or new DB queries built from user input
|
|
15
|
+
also qualifies.
|
|
16
|
+
agent_hints: [security, logic-reviewer, challenger-reviewer]
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
# Backend Security — Senior Stance
|
|
20
|
+
|
|
21
|
+
## When this applies
|
|
22
|
+
Load when task touches: authentication, authorization, sessions, JWTs, cookies, secrets/env vars, input validation, file uploads, SQL or NoSQL queries with user input, server-side rendering of user content, CORS/CSRF middleware, logging of user data, password handling. Reviewer (especially Security Agent) auto-loads when diff includes auth code, route handlers accepting user input, DB queries built from user input, or any change in `auth/`, `middleware/`, `routes/`, `controllers/`. Also referenced by orchestrator's `--no-tests` confirmation prompt — backend-security-sensitive scope.
|
|
23
|
+
|
|
24
|
+
## Default Stance
|
|
25
|
+
Backend security failures are silent until they're not. Most app code is trusted to be correct; security code is trusted to be paranoid. Default to "this input is hostile until proven otherwise". Validate at the boundary, log without leaking, fail closed, sandbox what you can't trust. Time spent on auth design pays off; time spent debugging an exploited deployment after the fact does not.
|
|
26
|
+
|
|
27
|
+
## Patterns (use these)
|
|
28
|
+
|
|
29
|
+
### Authentication: tokens with short expiry + refresh
|
|
30
|
+
- Access token: short-lived (15 min - 1 hour), used per request.
|
|
31
|
+
- Refresh token: longer-lived (days/weeks), only sent to refresh endpoint, rotation on use.
|
|
32
|
+
- Server-side revocation list for refresh tokens (DB or Redis with TTL).
|
|
33
|
+
- JWT signed with strong key (RS256 or ES256 preferred over HS256 for distributed verification). Validate `alg`, `iss`, `aud`, `exp`, `nbf` on every request.
|
|
34
|
+
|
|
35
|
+
### Authorization: explicit per-resource check
|
|
36
|
+
- Authn produces a principal; authz checks the principal vs the resource per request.
|
|
37
|
+
- "Can this principal perform this action on this resource?" — answered by an explicit check, not by URL pattern alone.
|
|
38
|
+
- Default DENY. Whitelist allowed actions. No "if not in this blocklist, allow".
|
|
39
|
+
- Audit log every privileged action with `actor_id`, `target_id`, `action`, `outcome`, `request_id`.
|
|
40
|
+
|
|
41
|
+
### Input validation at the boundary
|
|
42
|
+
- Validate at controller entry, BEFORE the request hits any business logic.
|
|
43
|
+
- Reject unknown fields explicitly (don't silently ignore). Tools: Zod, Pydantic, class-validator, JSON Schema.
|
|
44
|
+
- Validate types AND ranges AND lengths. `string` is not enough; `string between 1 and 200 chars matching /^[a-zA-Z0-9_]+$/` is.
|
|
45
|
+
- File uploads: check size, MIME type, magic bytes. Re-encode images server-side; never trust client-supplied content-type.
|
|
46
|
+
|
|
47
|
+
### SQL: parameterized queries always
|
|
48
|
+
- ORM: usually parameterized by default. Never `prisma.$queryRawUnsafe` with user input.
|
|
49
|
+
- Raw SQL: `pg.query('SELECT * WHERE id = $1', [userId])`, never `\`SELECT * WHERE id = ${userId}\``.
|
|
50
|
+
- Even for "trusted" internal callers — defense in depth.
|
|
51
|
+
- Avoid dynamic table/column names from user input. If you must, allowlist the values.
|
|
52
|
+
|
|
53
|
+
### Secrets handling
|
|
54
|
+
- NEVER commit secrets to git. Even ".env.example" should have placeholder values.
|
|
55
|
+
- Load from env vars or a secrets manager (Vault, AWS Secrets Manager, GCP Secret Manager).
|
|
56
|
+
- Rotate regularly. After any incident, immediately.
|
|
57
|
+
- Don't log secrets. Don't include them in error messages. Don't return them in API responses.
|
|
58
|
+
- Frontend bundles: anything in `process.env.NEXT_PUBLIC_*` / `VITE_*` is PUBLIC. Never put secrets in client-visible env vars.
|
|
59
|
+
|
|
60
|
+
### CSRF protection
|
|
61
|
+
- For cookie-based auth: CSRF token (double-submit or synchronizer) required on state-changing requests.
|
|
62
|
+
- For pure bearer-token auth (Authorization header): CSRF less of a risk because browsers don't auto-send the header.
|
|
63
|
+
- SameSite cookies: `Strict` for sessions where possible; `Lax` is the default fallback.
|
|
64
|
+
|
|
65
|
+
### CORS done right
|
|
66
|
+
- Specific allowed origins. Never `*` with credentials.
|
|
67
|
+
- Allowed methods/headers explicit, not wildcard.
|
|
68
|
+
- Preflight responses cached with `Access-Control-Max-Age` to reduce overhead.
|
|
69
|
+
|
|
70
|
+
### Rate limiting at the boundary
|
|
71
|
+
- Per-user (authenticated) AND per-IP (unauthenticated).
|
|
72
|
+
- Stricter on auth endpoints (login, password reset, signup) — typical: 5 attempts / 15 min.
|
|
73
|
+
- Token bucket via redis-cell or equivalent.
|
|
74
|
+
- 429 with `Retry-After` header.
|
|
75
|
+
|
|
76
|
+
### Password handling
|
|
77
|
+
- Hash with bcrypt / argon2id, NEVER MD5 / SHA1 / SHA256-without-salt.
|
|
78
|
+
- Bcrypt cost ≥ 12 in 2026; argon2id memory ≥ 64MiB.
|
|
79
|
+
- Compare with constant-time comparison.
|
|
80
|
+
- Rate-limit login attempts.
|
|
81
|
+
- Optional: pwned-passwords check at signup/change.
|
|
82
|
+
|
|
83
|
+
### SSRF prevention
|
|
84
|
+
- If you accept a URL from a user (webhooks, image fetch, OAuth callback):
|
|
85
|
+
- Resolve DNS server-side; reject private IP ranges (10.x, 172.16-31.x, 192.168.x, 127.x, 169.254.x, fc00::/7, fe80::/10, ::1).
|
|
86
|
+
- Disallow `file://`, `gopher://`, `ftp://` etc. — only `https://` (or `http://` with explicit scope).
|
|
87
|
+
- Set short timeout; cap response size.
|
|
88
|
+
|
|
89
|
+
### Path traversal prevention
|
|
90
|
+
- Never use user input directly in file paths.
|
|
91
|
+
- Resolve and check: `resolved = path.resolve(base, userPath); if (!resolved.startsWith(base)) reject`.
|
|
92
|
+
- Reject `..` / null bytes / absolute paths.
|
|
93
|
+
|
|
94
|
+
### Server-side rendering of user content
|
|
95
|
+
- Encode for the context: HTML body, HTML attribute, JS, CSS, URL — each has different escape rules.
|
|
96
|
+
- Frameworks (React, Vue, Svelte, etc.) auto-escape by default. Be wary of `dangerouslySetInnerHTML`, `v-html`, `{@html}` — these bypass.
|
|
97
|
+
- For markdown/HTML user input: sanitize with a vetted lib (DOMPurify, bleach) — allowlist, not blocklist.
|
|
98
|
+
|
|
99
|
+
### Sensitive data overreturn
|
|
100
|
+
API endpoint returns full user record including `password_hash`, `email_verified_at`, internal flags.
|
|
101
|
+
**Rule:** explicit response DTOs. List the fields you're sending. Never `return user` directly when `user` is the DB row.
|
|
102
|
+
|
|
103
|
+
## Anti-Patterns (DO NOT)
|
|
104
|
+
|
|
105
|
+
### Auth check in component, not in action
|
|
106
|
+
React Server Action does work; auth check is in the calling component.
|
|
107
|
+
**Why it bites:** action callable directly via fetch from anywhere. Components aren't security boundaries.
|
|
108
|
+
**Rule:** every Server Action begins with explicit auth check. Same for API routes, GraphQL resolvers, RPC methods.
|
|
109
|
+
|
|
110
|
+
### Trusting `req.user` without verifying token freshness
|
|
111
|
+
Token decoded once at session start; for hours, code uses cached `req.user` without re-checking expiry, revocation, or scope changes.
|
|
112
|
+
**Rule:** validate token on every request (cheap with stateless JWT). For revocation, check Redis/DB on every request (or accept short cache window matching revocation SLA).
|
|
113
|
+
|
|
114
|
+
### `eval` / `Function()` / dynamic require with user input
|
|
115
|
+
**Why it bites:** RCE.
|
|
116
|
+
**Rule:** never `eval` user input. If you need dynamic execution, use a sandbox (vm2 etc., though even those have escapes) and severely restrict capability.
|
|
117
|
+
|
|
118
|
+
### MD5 / SHA1 / unsalted SHA256 for passwords
|
|
119
|
+
**Rule:** bcrypt or argon2id. Never anything weaker.
|
|
120
|
+
|
|
121
|
+
### Comparing tokens / hashes with `==`
|
|
122
|
+
Timing-attack vulnerable. Naive equality reveals string length and partial match by timing.
|
|
123
|
+
**Rule:** constant-time compare (`crypto.timingSafeEqual` in Node, `hmac.compare_digest` in Python).
|
|
124
|
+
|
|
125
|
+
### CORS `Access-Control-Allow-Origin: *` with credentials
|
|
126
|
+
**Why it bites:** browsers reject this anyway, but seeing it = misconfigured intent. May be loosened next sprint to "fix" the rejection.
|
|
127
|
+
**Rule:** explicit origin allowlist. Never wildcard with credentials.
|
|
128
|
+
|
|
129
|
+
### Logging entire request bodies
|
|
130
|
+
Login request body logged → password in logs → log files compromised → password breach.
|
|
131
|
+
**Rule:** redact known-sensitive field paths (`password`, `token`, `card_number`, etc.) at log boundary. Whitelist what's logged, not blacklist.
|
|
132
|
+
|
|
133
|
+
### Returning DB error messages to users
|
|
134
|
+
`SQLSTATE: 23505 unique constraint "users_email_key"` returned in HTTP response.
|
|
135
|
+
**Why it bites:** leaks schema info. Helps attackers map the DB.
|
|
136
|
+
**Rule:** map DB errors to user-facing categories at the boundary. "Email already in use" not "violates unique_constraint".
|
|
137
|
+
|
|
138
|
+
### `findOne({...userInput})` without sanitization
|
|
139
|
+
NoSQL injection: `userInput = { $ne: null }` returns first user.
|
|
140
|
+
**Rule:** typed input validation. Reject objects where strings expected. ORMs help; raw drivers don't.
|
|
141
|
+
|
|
142
|
+
### Storing JWT in localStorage
|
|
143
|
+
**Why it bites:** XSS reads it. There's no httpOnly defense in localStorage.
|
|
144
|
+
**Rule:** httpOnly cookie for session tokens (SameSite=Strict / Lax). If you must use bearer in JS, isolate via subdomain + strict CSP.
|
|
145
|
+
|
|
146
|
+
### Client-side validation as the only validation
|
|
147
|
+
Client validates email format → server trusts → attacker bypasses client → server processes invalid.
|
|
148
|
+
**Rule:** server validates everything. Client validation is UX only.
|
|
149
|
+
|
|
150
|
+
### Webhook endpoint without signature verification
|
|
151
|
+
Anyone can POST to `/webhooks/stripe` and claim to be Stripe.
|
|
152
|
+
**Rule:** verify signature with shared secret on every webhook. Reject unsigned/invalid.
|
|
153
|
+
|
|
154
|
+
### Open redirect
|
|
155
|
+
`/login?next=https://evil.com` → after login, redirect to evil.com → phishing.
|
|
156
|
+
**Rule:** allowlist redirect destinations or restrict to relative paths.
|
|
157
|
+
|
|
158
|
+
### Mass assignment
|
|
159
|
+
`User.update(req.body)` where `req.body` includes `is_admin: true`.
|
|
160
|
+
**Rule:** explicit allowlist of editable fields. Or DTO that strips non-allowed fields before update.
|
|
161
|
+
|
|
162
|
+
### Same JWT for short-lived and long-lived contexts
|
|
163
|
+
One token used both for API auth (15 min OK) and for "remember me" (weeks). Compromise of either ruins both.
|
|
164
|
+
**Rule:** access token (short) + refresh token (long) split. Different scopes.
|
|
165
|
+
|
|
166
|
+
## Decision Framework
|
|
167
|
+
|
|
168
|
+
| Need | Choice |
|
|
169
|
+
|---|---|
|
|
170
|
+
| Web session for users | httpOnly cookie + SameSite=Lax + CSRF token on writes |
|
|
171
|
+
| API token for service-to-service | Short-lived JWT, signed with RS256 |
|
|
172
|
+
| Long-lived "remember me" | Refresh token, server-side revocation |
|
|
173
|
+
| User uploads files | Size limit + MIME check + magic-bytes check + re-encode if image; store on object storage with random key |
|
|
174
|
+
| Password storage | argon2id (preferred) or bcrypt cost 12+ |
|
|
175
|
+
| Per-resource permission | Explicit authz check per request; default deny |
|
|
176
|
+
| Rate limit on login/signup | 5 req / 15 min per IP + per username |
|
|
177
|
+
| Webhook receiver | Verify signature; reject unsigned |
|
|
178
|
+
| URL fetched from user | Allowlist domains OR SSRF protection (DNS resolve + private-IP rejection) |
|
|
179
|
+
| Sensitive log content | Redact at log boundary; whitelist what's emitted |
|
|
180
|
+
| Admin actions | Re-auth (step-up) before privileged actions; audit log all |
|
|
181
|
+
| CORS | Specific origins; no wildcard with credentials |
|
|
182
|
+
|
|
183
|
+
## Cost Model
|
|
184
|
+
|
|
185
|
+
| Vulnerability | Cost when exploited |
|
|
186
|
+
|---|---|
|
|
187
|
+
| SQL injection | Full DB compromise; data exfiltration; possible RCE |
|
|
188
|
+
| XSS | Session theft; account takeover at scale |
|
|
189
|
+
| Auth bypass | Full system compromise |
|
|
190
|
+
| SSRF | Internal service compromise; cloud metadata endpoint exposure (AWS IMDS) |
|
|
191
|
+
| Open redirect | Phishing campaigns leveraging your domain |
|
|
192
|
+
| Weak password hash | Password breach → credential stuffing across other sites |
|
|
193
|
+
| CSRF on sensitive action | Drive-by state changes from malicious sites |
|
|
194
|
+
| Token in localStorage + XSS | Account takeover via single XSS |
|
|
195
|
+
| Excessive log content with PII | GDPR fine; user data exposure |
|
|
196
|
+
|
|
197
|
+
## Red Flags in Diff
|
|
198
|
+
|
|
199
|
+
- New raw SQL string built with template literals containing user input → flag immediately (SQL injection).
|
|
200
|
+
- New endpoint without explicit auth check at top of handler → flag.
|
|
201
|
+
- New `eval`, `new Function`, `vm.runInNewContext` with user input → flag immediately (RCE).
|
|
202
|
+
- Password handling using `crypto.createHash('md5'|'sha1'|'sha256')` directly → flag.
|
|
203
|
+
- Token/hash compared with `===` / `==` → flag (use constant-time compare).
|
|
204
|
+
- `dangerouslySetInnerHTML` / `v-html` / `{@html}` with user content → flag (XSS unless sanitized).
|
|
205
|
+
- New `Access-Control-Allow-Origin: *` with `credentials: true` → flag immediately.
|
|
206
|
+
- `findOne(req.body)` / `find(req.query)` patterns → flag (NoSQL injection / mass assignment).
|
|
207
|
+
- New `User.update(req.body)` without explicit field allowlist → flag (mass assignment).
|
|
208
|
+
- `localStorage.setItem('token', ...)` for session token → flag (XSS exposure).
|
|
209
|
+
- `redirect(req.query.next)` without allowlist → flag (open redirect).
|
|
210
|
+
- New webhook endpoint without signature verification → flag.
|
|
211
|
+
- Logging `req.body` directly → flag (PII / secrets in logs).
|
|
212
|
+
- Error response containing stack trace / DB error verbatim → flag (info leak).
|
|
213
|
+
- New URL fetch from user input without SSRF protection → flag.
|
|
214
|
+
- `path.join(baseDir, userInput)` without resolved-path check → flag (path traversal).
|
|
215
|
+
- Secrets / API keys / DB URLs visible in `process.env.NEXT_PUBLIC_*` or `VITE_*` → flag (client bundle exposure).
|
|
216
|
+
- New JWT validation skipping `exp` / `aud` / `iss` checks → flag.
|
|
217
|
+
- Missing rate limit on auth endpoint (login, signup, password-reset) → flag.
|
|
218
|
+
- Bcrypt cost < 12 / argon2id memory < 64MiB → flag.
|
|
219
|
+
- Cache layer caching responses across users without `Vary` / proper key → flag (cross-user data leak).
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
---
|
|
2
|
+
tags: [testing, flutter, dart, widget-test, mobile]
|
|
3
|
+
stack_signals:
|
|
4
|
+
- language: [dart]
|
|
5
|
+
- project_type: [mobile, frontend-app]
|
|
6
|
+
summary: |
|
|
7
|
+
Flutter / Dart testing — widget tests for logic-bearing widgets, naming
|
|
8
|
+
conventions, do-not-test rules for pure layout.
|
|
9
|
+
when_to_load: |
|
|
10
|
+
Task writes or changes tests for a Flutter codebase, OR review of test
|
|
11
|
+
code in a Flutter project. pubspec.yaml with flutter_test in
|
|
12
|
+
dev_dependencies.
|
|
13
|
+
agent_hints: [test, acceptance, logic-reviewer]
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
# Testing: Flutter / Dart
|
|
17
|
+
|
|
18
|
+
## Framework Detection
|
|
19
|
+
- `pubspec.yaml` with `flutter_test` in dev_dependencies → `flutter test`
|
|
20
|
+
- `test/` directory with `*_test.dart` files → match existing patterns
|
|
21
|
+
- `integration_test/` → integration tests (run separately)
|
|
22
|
+
|
|
23
|
+
## What to Test
|
|
24
|
+
**Widgets — only if they contain logic:**
|
|
25
|
+
- Widget renders correctly with given parameters
|
|
26
|
+
- User interaction (tap, swipe) → expected state change
|
|
27
|
+
- Conditional rendering based on state
|
|
28
|
+
- Do NOT test: pure layout widgets, theme styling, static text
|
|
29
|
+
|
|
30
|
+
## File Naming
|
|
31
|
+
`*_test.dart` in `test/` directory (mirroring `lib/` structure)
|
|
32
|
+
|
|
33
|
+
## Finder Priority
|
|
34
|
+
Prefer in this order:
|
|
35
|
+
1. `find.byKey` (most stable, immune to text/type changes)
|
|
36
|
+
2. `find.byType` (good for unique widgets)
|
|
37
|
+
3. `find.text` (for verifying visible content)
|
|
38
|
+
|
|
39
|
+
## pump vs pumpAndSettle
|
|
40
|
+
- `tester.pump()` — advance one frame. Use when you need precise frame control.
|
|
41
|
+
- `tester.pumpAndSettle()` — pump until no more frames scheduled. Use after actions that trigger animations/transitions. Default timeout is 10 seconds — pass custom `Duration` for slow screens.
|
|
42
|
+
- After `tester.tap()` / `tester.enterText()` → always pump or pumpAndSettle.
|
|
43
|
+
|
|
44
|
+
## Mocking
|
|
45
|
+
- `mocktail` or `mockito` for dependencies
|
|
46
|
+
- `ProviderScope.overrides` for Riverpod state
|
|
47
|
+
- `BlocProvider` with mock blocs for BLoC pattern
|
|
48
|
+
- `pumpWidget()` with required providers and `MaterialApp` wrapper
|
|
49
|
+
|
|
50
|
+
## Golden (Screenshot) Testing
|
|
51
|
+
- Use `matchesGoldenFile('goldens/widget_name.png')` for visual regression
|
|
52
|
+
- Run `flutter test --update-goldens` to generate/update baselines
|
|
53
|
+
- Store goldens in version control
|
|
54
|
+
- Goldens are platform-sensitive — generate on CI or use `alchemist` for platform-agnostic goldens
|
|
55
|
+
|
|
56
|
+
## Async Testing
|
|
57
|
+
- `expectLater` with `emitsInOrder` for Stream assertions
|
|
58
|
+
- `tester.runAsync(() async { ... })` for real async operations in widget tests
|
|
59
|
+
- Wrap Future assertions in `expectLater` not `expect`
|
|
60
|
+
|
|
61
|
+
## Do NOT
|
|
62
|
+
- Test implementation details (internal state variables)
|
|
63
|
+
- Test third-party package widgets
|
|
64
|
+
- Use arbitrary `Future.delayed` — use pump/pumpAndSettle
|
|
65
|
+
- Forget to `addTearDown` for controllers/subscriptions created in tests
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
---
|
|
2
|
+
tags: [testing, nestjs, jest, backend]
|
|
3
|
+
stack_signals:
|
|
4
|
+
- language: [typescript, javascript]
|
|
5
|
+
- project_type: [backend, monorepo]
|
|
6
|
+
summary: |
|
|
7
|
+
NestJS testing patterns — Jest defaults, controller validation, service
|
|
8
|
+
input/output mapping, auth guard behavior, error response shapes.
|
|
9
|
+
when_to_load: |
|
|
10
|
+
Task writes or changes tests for a NestJS backend, OR review of test code
|
|
11
|
+
in a NestJS project. jest.config present.
|
|
12
|
+
agent_hints: [test, acceptance, logic-reviewer]
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
# Testing: NestJS
|
|
16
|
+
|
|
17
|
+
## Framework Detection
|
|
18
|
+
- `jest.config.*` or `package.json "jest"` → Jest (built-in with NestJS)
|
|
19
|
+
|
|
20
|
+
## What to Test
|
|
21
|
+
**Controllers / Endpoints:**
|
|
22
|
+
- Request validation (missing fields, wrong types via class-validator)
|
|
23
|
+
- Success response shape
|
|
24
|
+
- Error responses (401, 403, 404, 422)
|
|
25
|
+
- Auth guard behavior
|
|
26
|
+
|
|
27
|
+
**Services:**
|
|
28
|
+
- Input → output mapping
|
|
29
|
+
- Error handling paths
|
|
30
|
+
- Edge cases
|
|
31
|
+
|
|
32
|
+
**Guards / Pipes / Interceptors:**
|
|
33
|
+
- Guard returns true/false correctly based on request context
|
|
34
|
+
- Pipe transforms/validates input correctly
|
|
35
|
+
- Interceptor modifies response as expected
|
|
36
|
+
|
|
37
|
+
## File Naming
|
|
38
|
+
- Unit tests: `*.spec.ts` (colocated with source)
|
|
39
|
+
- E2E tests: `*.e2e-spec.ts` in `test/` directory
|
|
40
|
+
|
|
41
|
+
## Module Setup
|
|
42
|
+
```typescript
|
|
43
|
+
const module = await Test.createTestingModule({
|
|
44
|
+
providers: [
|
|
45
|
+
ServiceUnderTest,
|
|
46
|
+
{ provide: DependencyService, useValue: mockDependency },
|
|
47
|
+
],
|
|
48
|
+
}).compile();
|
|
49
|
+
|
|
50
|
+
const service = module.get(ServiceUnderTest);
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## HTTP Testing
|
|
54
|
+
Use `supertest` for endpoint tests:
|
|
55
|
+
```typescript
|
|
56
|
+
const app = module.createNestApplication();
|
|
57
|
+
await app.init();
|
|
58
|
+
await request(app.getHttpServer())
|
|
59
|
+
.get('/endpoint')
|
|
60
|
+
.expect(200)
|
|
61
|
+
.expect({ data: expected });
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Mocking
|
|
65
|
+
- `overrideProvider(Service).useValue(mock)` in TestingModule
|
|
66
|
+
- `jest.mock()` for external modules
|
|
67
|
+
- Custom providers for DB/HTTP mocks
|
|
68
|
+
- `@nestjs/testing` utilities for full module compilation
|
|
69
|
+
|
|
70
|
+
## DTO Validation Testing
|
|
71
|
+
Test that class-validator decorators reject invalid input:
|
|
72
|
+
```typescript
|
|
73
|
+
const dto = plainToInstance(CreateUserDto, { name: '' });
|
|
74
|
+
const errors = await validate(dto);
|
|
75
|
+
expect(errors.length).toBeGreaterThan(0);
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Do NOT
|
|
79
|
+
- Test NestJS framework internals (DI resolution, module loading)
|
|
80
|
+
- Leave real DB/HTTP calls in unit tests
|
|
81
|
+
- Share state between tests (each test gets fresh module)
|
|
82
|
+
- Test generated code (Prisma client, TypeORM entities with no custom logic)
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
---
|
|
2
|
+
tags: [testing, python, pytest, unittest, backend]
|
|
3
|
+
stack_signals:
|
|
4
|
+
- language: [python]
|
|
5
|
+
- project_type: [backend, monorepo]
|
|
6
|
+
summary: |
|
|
7
|
+
Python testing patterns — pytest vs unittest detection, API/service
|
|
8
|
+
testing, fixtures, mocking external calls.
|
|
9
|
+
when_to_load: |
|
|
10
|
+
Task writes or changes tests for a Python codebase, OR review of test code
|
|
11
|
+
in a Python project. pytest.ini / pyproject.toml [tool.pytest] / conftest.py
|
|
12
|
+
present.
|
|
13
|
+
agent_hints: [test, acceptance, logic-reviewer]
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
# Testing: Python
|
|
17
|
+
|
|
18
|
+
## Framework Detection
|
|
19
|
+
- `pytest.ini`, `pyproject.toml [tool.pytest]`, `conftest.py` → pytest
|
|
20
|
+
- `unittest` imports in existing code → unittest
|
|
21
|
+
- Neither → recommend pytest
|
|
22
|
+
|
|
23
|
+
## What to Test
|
|
24
|
+
**API Endpoints:**
|
|
25
|
+
- Request validation (missing fields, wrong types)
|
|
26
|
+
- Success response shape
|
|
27
|
+
- Error responses (401, 403, 404, 422)
|
|
28
|
+
- Auth guard behavior
|
|
29
|
+
|
|
30
|
+
**Services / Business Logic:**
|
|
31
|
+
- Input → output mapping
|
|
32
|
+
- Edge cases (empty, null, boundary values)
|
|
33
|
+
- Error handling paths
|
|
34
|
+
|
|
35
|
+
## File Naming
|
|
36
|
+
`test_*.py` in `tests/` directory
|
|
37
|
+
|
|
38
|
+
## Fixtures
|
|
39
|
+
- Use `conftest.py` for shared fixtures
|
|
40
|
+
- Scope correctly: `function` (default), `module`, `session`
|
|
41
|
+
- Compose fixtures — small focused fixtures combined in tests
|
|
42
|
+
- Factory fixtures for creating test data with overrides
|
|
43
|
+
|
|
44
|
+
## Parametrize
|
|
45
|
+
Use `@pytest.mark.parametrize` for testing multiple inputs:
|
|
46
|
+
```python
|
|
47
|
+
@pytest.mark.parametrize("input,expected", [
|
|
48
|
+
("valid", True),
|
|
49
|
+
("", False),
|
|
50
|
+
(None, False),
|
|
51
|
+
])
|
|
52
|
+
def test_validate(input, expected):
|
|
53
|
+
assert validate(input) == expected
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Async Testing
|
|
57
|
+
- `@pytest.mark.asyncio` for async test functions
|
|
58
|
+
- `AsyncMock` for mocking async dependencies
|
|
59
|
+
- `pytest-asyncio` plugin with `asyncio_mode = "auto"` in config
|
|
60
|
+
|
|
61
|
+
## FastAPI-Specific
|
|
62
|
+
- `httpx.AsyncClient` with `ASGITransport(app=app)` for async endpoint tests
|
|
63
|
+
- Override dependencies via `app.dependency_overrides[get_db] = mock_db`
|
|
64
|
+
- Test lifespan events separately if they have side effects
|
|
65
|
+
|
|
66
|
+
## Mocking
|
|
67
|
+
- `unittest.mock.AsyncMock` / `MagicMock` for dependencies
|
|
68
|
+
- `pytest` fixtures for DB/connection setup
|
|
69
|
+
- `monkeypatch` for env vars and simple attribute patches
|
|
70
|
+
- `pytest.raises(ExceptionType)` for exception assertions
|
|
71
|
+
|
|
72
|
+
## Do NOT
|
|
73
|
+
- Use `mock.patch` on the thing being tested
|
|
74
|
+
- Hardcode dates — use `freezegun` or fixture
|
|
75
|
+
- Rely on test execution order
|
|
76
|
+
- Leave real network calls in unit tests
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
---
|
|
2
|
+
tags: [testing, react, nextjs, vitest, jest, frontend]
|
|
3
|
+
stack_signals:
|
|
4
|
+
- language: [typescript, javascript]
|
|
5
|
+
- project_type: [frontend-app, monorepo]
|
|
6
|
+
summary: |
|
|
7
|
+
React / Next.js testing — Vitest / Jest detection, what to test
|
|
8
|
+
(components with logic, hooks, mutations), Testing Library patterns.
|
|
9
|
+
when_to_load: |
|
|
10
|
+
Task writes or changes tests for a React/Next.js codebase, OR review of
|
|
11
|
+
test code in a React/Next.js project. Vitest/Jest config present.
|
|
12
|
+
agent_hints: [test, acceptance, logic-reviewer]
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
# Testing: React / Next.js
|
|
16
|
+
|
|
17
|
+
## Framework Detection
|
|
18
|
+
- `vitest.config.*` or `vite.config.* with test` → Vitest
|
|
19
|
+
- `jest.config.*` or `package.json "jest"` → Jest
|
|
20
|
+
- Neither → check CLAUDE.md stack. React/Next.js → recommend Vitest. NestJS → Jest (built-in).
|
|
21
|
+
|
|
22
|
+
## What to Test
|
|
23
|
+
**Components — only if they contain logic:**
|
|
24
|
+
- Conditional rendering
|
|
25
|
+
- User interaction → expected outcome
|
|
26
|
+
- Do NOT test: pure layout, styling, static content
|
|
27
|
+
|
|
28
|
+
**Custom hooks:**
|
|
29
|
+
- Use `renderHook` from Testing Library
|
|
30
|
+
- Test state changes, return values, cleanup
|
|
31
|
+
|
|
32
|
+
## File Naming
|
|
33
|
+
`*.test.ts`, `*.test.tsx`, `*.spec.ts`
|
|
34
|
+
|
|
35
|
+
## Query Priority (Testing Library)
|
|
36
|
+
Prefer in this order:
|
|
37
|
+
1. `getByRole` (most accessible)
|
|
38
|
+
2. `getByLabelText`
|
|
39
|
+
3. `getByText`
|
|
40
|
+
4. `getByTestId` (last resort)
|
|
41
|
+
|
|
42
|
+
## User Interaction
|
|
43
|
+
Prefer `userEvent` over `fireEvent` — it simulates real browser behavior:
|
|
44
|
+
```typescript
|
|
45
|
+
import userEvent from '@testing-library/user-event';
|
|
46
|
+
const user = userEvent.setup();
|
|
47
|
+
await user.click(button);
|
|
48
|
+
await user.type(input, 'text');
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Async Patterns
|
|
52
|
+
- Use `waitFor` / `findBy*` for async state updates
|
|
53
|
+
- Handle act() warnings by using Testing Library's async utilities
|
|
54
|
+
- Always `await` user events
|
|
55
|
+
|
|
56
|
+
## Mocking
|
|
57
|
+
- MSW for API mocking (intercepts at network level)
|
|
58
|
+
- `vi.mock()` / `jest.mock()` for module mocks
|
|
59
|
+
- `renderWithProviders` wrapper for QueryClient + Router + Store
|
|
60
|
+
- Mock router: `MemoryRouter` with initial entries
|
|
61
|
+
|
|
62
|
+
## Do NOT
|
|
63
|
+
- Test implementation details (internal state, method calls)
|
|
64
|
+
- Test third-party library behavior
|
|
65
|
+
- Use snapshot tests unless project already has them
|
|
66
|
+
- Hardcode dates or rely on test execution order
|