@valentia-ai-skills/framework 1.0.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 (29) hide show
  1. package/README.md +103 -0
  2. package/bin/cli.js +482 -0
  3. package/package.json +42 -0
  4. package/scripts/postinstall.js +18 -0
  5. package/skills/global/api-design/SKILL.md +248 -0
  6. package/skills/global/api-design/tests/test-prompts.md +25 -0
  7. package/skills/global/code-standards/SKILL.md +245 -0
  8. package/skills/global/code-standards/tests/test-prompts.md +26 -0
  9. package/skills/global/deployment/SKILL.md +240 -0
  10. package/skills/global/deployment/tests/test-prompts.md +27 -0
  11. package/skills/global/documentation/SKILL.md +298 -0
  12. package/skills/global/documentation/tests/test-prompts.md +26 -0
  13. package/skills/global/git-workflow/SKILL.md +177 -0
  14. package/skills/global/git-workflow/tests/test-prompts.md +11 -0
  15. package/skills/global/security-baseline/SKILL.md +239 -0
  16. package/skills/global/security-baseline/tests/test-prompts.md +23 -0
  17. package/skills/global/testing-standards/SKILL.md +257 -0
  18. package/skills/global/testing-standards/tests/test-prompts.md +25 -0
  19. package/skills/onboarding/SKILL.md +110 -0
  20. package/skills/stack/devops/SKILL.md +220 -0
  21. package/skills/stack/devops/tests/test-prompts.md +29 -0
  22. package/skills/stack/node-backend/SKILL.md +304 -0
  23. package/skills/stack/node-backend/tests/test-prompts.md +27 -0
  24. package/skills/stack/python-backend/SKILL.md +304 -0
  25. package/skills/stack/python-backend/tests/test-prompts.md +27 -0
  26. package/skills/stack/react/SKILL.md +251 -0
  27. package/skills/stack/react/tests/test-prompts.md +26 -0
  28. package/skills/stack/react-native/SKILL.md +255 -0
  29. package/skills/stack/react-native/tests/test-prompts.md +26 -0
@@ -0,0 +1,177 @@
1
+ ---
2
+ name: git-workflow
3
+ description: >
4
+ Organization-wide Git workflow standards. Use this skill whenever the developer
5
+ is working with Git — creating branches, writing commit messages, preparing PRs,
6
+ merging code, resolving conflicts, or discussing branching strategy. Also triggers
7
+ when asked to "commit", "push", "merge", "create a PR", "branch off", "tag a
8
+ release", "cherry-pick", "rebase", or any other Git operation. Applies to all
9
+ teams and all repositories in the organization.
10
+ version: "1.0.0"
11
+ scope: global
12
+ author: Framework Admin
13
+ last_reviewed: 2026-03-19
14
+ ---
15
+
16
+ # Git Workflow
17
+
18
+ ## Overview
19
+
20
+ Standardized Git workflow that all teams follow. Ensures clean history, traceable
21
+ changes, and smooth code review processes across 10+ teams working on different
22
+ projects.
23
+
24
+ ## 1. Branching Strategy
25
+
26
+ We use a **trunk-based development** model with short-lived feature branches.
27
+
28
+ ### Branch Naming Convention
29
+
30
+ ```
31
+ {type}/{ticket-id}/{short-description}
32
+ ```
33
+
34
+ | Type | Use Case | Example |
35
+ |------|----------|---------|
36
+ | `feature/` | New functionality | `feature/PROJ-123/user-registration` |
37
+ | `fix/` | Bug fixes | `fix/PROJ-456/login-timeout` |
38
+ | `hotfix/` | Production emergency | `hotfix/PROJ-789/payment-crash` |
39
+ | `chore/` | Maintenance, deps, config | `chore/PROJ-101/upgrade-node-20` |
40
+ | `refactor/` | Code improvements | `refactor/PROJ-202/extract-auth-service` |
41
+ | `docs/` | Documentation only | `docs/PROJ-303/api-endpoint-guide` |
42
+
43
+ ### Rules
44
+ - Branch from `main` (or `develop` if your team uses GitFlow)
45
+ - Branch lifetime: **maximum 3 days** — if longer, break the work into smaller PRs
46
+ - Delete branches after merge
47
+ - Never commit directly to `main`
48
+
49
+ ## 2. Commit Messages
50
+
51
+ ### Format
52
+
53
+ ```
54
+ {type}({scope}): {short description}
55
+
56
+ {optional body — explain WHY, not WHAT}
57
+
58
+ {optional footer — ticket references, breaking changes}
59
+ ```
60
+
61
+ ### Types
62
+
63
+ | Type | When |
64
+ |------|------|
65
+ | `feat` | New feature |
66
+ | `fix` | Bug fix |
67
+ | `refactor` | Code change that doesn't fix a bug or add a feature |
68
+ | `docs` | Documentation only |
69
+ | `test` | Adding or updating tests |
70
+ | `chore` | Build, deps, CI config |
71
+ | `style` | Formatting, whitespace (no logic change) |
72
+ | `perf` | Performance improvement |
73
+
74
+ ### Examples
75
+
76
+ ✅ Good:
77
+ ```
78
+ feat(auth): add password reset via email
79
+
80
+ Users can now request a password reset link sent to their
81
+ registered email. Link expires after 24 hours.
82
+
83
+ Closes PROJ-123
84
+ ```
85
+
86
+ ```
87
+ fix(cart): prevent duplicate items on rapid click
88
+
89
+ Added debounce to add-to-cart handler. Previously, rapid
90
+ clicking could add the same item multiple times before
91
+ the UI updated.
92
+
93
+ Fixes PROJ-456
94
+ ```
95
+
96
+ ❌ Bad:
97
+ ```
98
+ fixed stuff // no type, no scope, vague
99
+ update // meaningless
100
+ WIP // don't commit WIP to shared branches
101
+ feat: changes // no scope, no description
102
+ ```
103
+
104
+ ### Rules
105
+ - Subject line: max 72 characters
106
+ - Use imperative mood: "add feature" not "added feature"
107
+ - No period at end of subject
108
+ - Body wraps at 80 characters
109
+ - Reference ticket numbers in footer
110
+
111
+ ## 3. Pull Requests
112
+
113
+ ### PR Title Format
114
+ Same as commit message format:
115
+ ```
116
+ feat(auth): add password reset via email
117
+ ```
118
+
119
+ ### PR Description Template
120
+ Every PR must include:
121
+ 1. **What** — One sentence describing the change
122
+ 2. **Why** — Context for why this change is needed
123
+ 3. **How** — Key implementation decisions
124
+ 4. **Testing** — How you verified this works
125
+ 5. **Screenshots** — If UI changes (before/after)
126
+
127
+ ### PR Size Rules
128
+ - **Target**: Under 400 lines changed
129
+ - **Hard limit**: 800 lines — larger PRs must be split
130
+ - Exception: Generated files, migrations, dependency updates
131
+
132
+ ### Review Requirements
133
+ - Minimum 1 approval required
134
+ - 2 approvals for: security-related changes, shared library changes, infrastructure changes
135
+ - All CI checks must pass
136
+ - No unresolved comments
137
+
138
+ ### Merge Strategy
139
+ - **Squash merge** for feature branches (clean history)
140
+ - **Merge commit** for release branches (preserve history)
141
+ - Never force push to `main`
142
+
143
+ ## 4. Release Tagging
144
+
145
+ ### Version Format
146
+ Semantic versioning: `vMAJOR.MINOR.PATCH`
147
+
148
+ ```
149
+ v1.0.0 — initial release
150
+ v1.1.0 — new feature added
151
+ v1.1.1 — bug fix
152
+ v2.0.0 — breaking change
153
+ ```
154
+
155
+ ### Tagging Process
156
+ ```bash
157
+ git tag -a v1.2.0 -m "Release v1.2.0: Add user dashboard"
158
+ git push origin v1.2.0
159
+ ```
160
+
161
+ ## 5. Git Hygiene
162
+
163
+ - Pull and rebase before pushing: `git pull --rebase origin main`
164
+ - Resolve conflicts locally, never in GitHub UI
165
+ - Don't commit: `.env` files, `node_modules/`, build artifacts, IDE configs
166
+ - Keep `.gitignore` up to date
167
+ - Squash fixup commits before review
168
+
169
+ ## Checklist
170
+
171
+ Before any Git operation, verify:
172
+ - [ ] Branch name follows `{type}/{ticket}/{description}` format
173
+ - [ ] Commit message follows conventional format with type and scope
174
+ - [ ] PR is under 400 lines (or justified if larger)
175
+ - [ ] PR description includes What/Why/How/Testing
176
+ - [ ] No secrets, env files, or build artifacts committed
177
+ - [ ] Branch is rebased on latest main
@@ -0,0 +1,11 @@
1
+ ## Test 1: Branch Creation
2
+ **Prompt**: "I need to start working on a new user dashboard feature, ticket DASH-42"
3
+ **Expected**: Suggests `feature/DASH-42/user-dashboard` branch name, shows git checkout command
4
+
5
+ ## Test 2: Commit Message Writing
6
+ **Prompt**: "Write a commit message for: I updated the login page to show an error when the password is wrong"
7
+ **Expected**: `fix(auth): show error message on incorrect password` with body explaining context
8
+
9
+ ## Test 3: PR Preparation
10
+ **Prompt**: "Help me prepare a PR for my authentication refactor that moved from JWT to session-based auth"
11
+ **Expected**: PR title in conventional format, description with What/Why/How/Testing sections, notes about breaking change
@@ -0,0 +1,239 @@
1
+ ---
2
+ name: security-baseline
3
+ description: >
4
+ Organization-wide security standards for all code. Use this skill whenever
5
+ writing code that handles: authentication, authorization, passwords, tokens,
6
+ API keys, secrets, user input, database queries, file uploads, HTTP requests,
7
+ CORS, headers, cookies, sessions, encryption, hashing, or any security-sensitive
8
+ operation. Also triggers on: "login", "signup", "auth", "validate", "sanitize",
9
+ "encrypt", "hash", "permission", "role", "access control", "secret", "API key",
10
+ "environment variable", ".env", "OWASP", "vulnerability", "injection",
11
+ "XSS", "CSRF", or "security review". Applies to ALL stacks.
12
+ version: "1.0.0"
13
+ scope: global
14
+ author: Framework Admin
15
+ last_reviewed: 2026-03-19
16
+ ---
17
+
18
+ # Security Baseline
19
+
20
+ ## Overview
21
+
22
+ Non-negotiable security standards that every developer and every AI-generated
23
+ piece of code must follow. These rules prevent the most common vulnerability
24
+ classes (OWASP Top 10) and protect user data.
25
+
26
+ ## 1. Secret Management
27
+
28
+ ### NEVER Hardcode Secrets
29
+
30
+ Secrets must NEVER appear in code, config files, or version control.
31
+
32
+ ✅ Good:
33
+ ```typescript
34
+ const dbUrl = process.env.DATABASE_URL;
35
+ const apiKey = process.env.STRIPE_API_KEY;
36
+ ```
37
+
38
+ ❌ Bad:
39
+ ```typescript
40
+ const dbUrl = "postgres://admin:password123@db.example.com/prod";
41
+ const apiKey = "sk_live_abc123xyz789";
42
+ ```
43
+
44
+ ### Rules
45
+ - All secrets go in environment variables
46
+ - Use `.env.example` with placeholder values (never real secrets)
47
+ - `.env` must be in `.gitignore` — verify this exists
48
+ - Use a secrets manager (Vault, AWS SSM, etc.) for production
49
+ - Rotate secrets on any suspected exposure
50
+ - Never log secrets — even partially
51
+
52
+ ### Pre-Commit Check
53
+ If generating any config or setup code, always include:
54
+ ```gitignore
55
+ # .gitignore — MUST include:
56
+ .env
57
+ .env.local
58
+ .env.*.local
59
+ *.pem
60
+ *.key
61
+ ```
62
+
63
+ ## 2. Input Validation
64
+
65
+ ### Validate ALL User Input
66
+
67
+ Never trust input from clients, APIs, forms, URLs, or any external source.
68
+
69
+ ### Rules
70
+ - Validate at the boundary (API endpoint / form handler)
71
+ - Use schema validation (Zod, Joi, class-validator, Pydantic)
72
+ - Validate types, lengths, formats, and ranges
73
+ - Reject invalid input — don't try to "fix" it
74
+ - Return clear error messages without exposing internals
75
+
76
+ ✅ Good:
77
+ ```typescript
78
+ import { z } from "zod";
79
+
80
+ const createUserSchema = z.object({
81
+ email: z.string().email().max(255),
82
+ name: z.string().min(1).max(100),
83
+ age: z.number().int().min(13).max(150),
84
+ role: z.enum(["user", "admin"]),
85
+ });
86
+
87
+ function createUser(req, res) {
88
+ const result = createUserSchema.safeParse(req.body);
89
+ if (!result.success) {
90
+ return res.status(400).json({ error: "Invalid input", details: result.error.issues });
91
+ }
92
+ // proceed with validated data: result.data
93
+ }
94
+ ```
95
+
96
+ ❌ Bad:
97
+ ```typescript
98
+ function createUser(req, res) {
99
+ const { email, name, age, role } = req.body;
100
+ // directly using unvalidated input
101
+ db.users.insert({ email, name, age, role });
102
+ }
103
+ ```
104
+
105
+ ## 3. SQL Injection Prevention
106
+
107
+ ### ALWAYS Use Parameterized Queries
108
+
109
+ Never concatenate user input into SQL strings.
110
+
111
+ ✅ Good:
112
+ ```typescript
113
+ // Parameterized query
114
+ const user = await db.query("SELECT * FROM users WHERE email = $1", [email]);
115
+
116
+ // ORM (also safe)
117
+ const user = await User.findOne({ where: { email } });
118
+ ```
119
+
120
+ ❌ Bad:
121
+ ```typescript
122
+ // SQL INJECTION VULNERABILITY
123
+ const user = await db.query(`SELECT * FROM users WHERE email = '${email}'`);
124
+ const user = await db.query("SELECT * FROM users WHERE email = '" + email + "'");
125
+ ```
126
+
127
+ ## 4. Authentication
128
+
129
+ ### Password Rules
130
+ - Hash with bcrypt (cost factor ≥ 12) or Argon2
131
+ - Never store plaintext passwords
132
+ - Never log passwords — even hashed
133
+ - Minimum 8 characters, check against breached password lists
134
+
135
+ ✅ Good:
136
+ ```typescript
137
+ import bcrypt from "bcrypt";
138
+
139
+ const SALT_ROUNDS = 12;
140
+
141
+ async function hashPassword(password: string): Promise<string> {
142
+ return bcrypt.hash(password, SALT_ROUNDS);
143
+ }
144
+
145
+ async function verifyPassword(password: string, hash: string): Promise<boolean> {
146
+ return bcrypt.compare(password, hash);
147
+ }
148
+ ```
149
+
150
+ ### Token Rules
151
+ - Use short-lived access tokens (15-60 minutes)
152
+ - Use refresh tokens for session extension
153
+ - Store tokens in httpOnly, secure, sameSite cookies
154
+ - Never store tokens in localStorage (XSS vulnerable)
155
+
156
+ ✅ Good:
157
+ ```typescript
158
+ res.cookie("token", jwt, {
159
+ httpOnly: true, // not accessible via JavaScript
160
+ secure: true, // HTTPS only
161
+ sameSite: "strict", // CSRF protection
162
+ maxAge: 15 * 60 * 1000, // 15 minutes
163
+ });
164
+ ```
165
+
166
+ ❌ Bad:
167
+ ```typescript
168
+ localStorage.setItem("token", jwt); // XSS vulnerable
169
+ res.cookie("token", jwt); // missing security flags
170
+ ```
171
+
172
+ ## 5. Authorization
173
+
174
+ - Check permissions on EVERY protected endpoint
175
+ - Never rely on client-side checks alone
176
+ - Use role-based (RBAC) or attribute-based (ABAC) access control
177
+ - Verify resource ownership: user can only access THEIR data
178
+
179
+ ```typescript
180
+ // Always verify ownership
181
+ async function getOrder(req, res) {
182
+ const order = await Order.findById(req.params.id);
183
+
184
+ if (!order) return res.status(404).json({ error: "Not found" });
185
+ if (order.userId !== req.user.id) return res.status(403).json({ error: "Forbidden" });
186
+
187
+ return res.json(order);
188
+ }
189
+ ```
190
+
191
+ ## 6. XSS Prevention
192
+
193
+ - Escape all user-generated content before rendering in HTML
194
+ - Use framework-provided escaping (React auto-escapes, etc.)
195
+ - Never use `dangerouslySetInnerHTML` (React) or `v-html` (Vue) with user content
196
+ - Set `Content-Security-Policy` headers
197
+
198
+ ## 7. Dependency Security
199
+
200
+ - Run `npm audit` / `pip audit` in CI pipeline
201
+ - No known critical/high vulnerabilities in production
202
+ - Pin dependency versions (use lockfiles)
203
+ - Review dependencies before adding — prefer well-maintained packages
204
+
205
+ ## 8. Logging & Error Handling
206
+
207
+ - Never log: passwords, tokens, API keys, credit cards, SSNs, PII
208
+ - Log: failed auth attempts, permission denials, validation failures
209
+ - Don't expose stack traces to users in production
210
+ - Return generic error messages to clients
211
+
212
+ ✅ Good:
213
+ ```typescript
214
+ // Log for debugging (server-side only)
215
+ logger.error("Payment failed", { userId: user.id, orderId: order.id, error: err.code });
216
+
217
+ // Return to client (generic)
218
+ res.status(500).json({ error: "Payment processing failed. Please try again." });
219
+ ```
220
+
221
+ ❌ Bad:
222
+ ```typescript
223
+ // Exposes internals to client
224
+ res.status(500).json({ error: err.stack, query: sql, dbPassword: config.db.password });
225
+ ```
226
+
227
+ ## Checklist
228
+
229
+ Before finalizing any code that touches security:
230
+ - [ ] No hardcoded secrets — all from environment variables
231
+ - [ ] .env is in .gitignore
232
+ - [ ] All user input is validated with schema validation
233
+ - [ ] SQL queries are parameterized
234
+ - [ ] Passwords are hashed (bcrypt/Argon2, cost ≥ 12)
235
+ - [ ] Tokens are in httpOnly secure cookies (not localStorage)
236
+ - [ ] Authorization checks on every protected endpoint
237
+ - [ ] No user content rendered via dangerouslySetInnerHTML or equivalent
238
+ - [ ] Error messages don't expose internals
239
+ - [ ] No PII in logs
@@ -0,0 +1,23 @@
1
+ ## Test 1: Login Endpoint
2
+ **Prompt**: "Write a login endpoint that takes email and password, checks the database, and returns a session token"
3
+ **Expected**:
4
+ - Input validation with schema (Zod/Joi)
5
+ - bcrypt password comparison (not plaintext)
6
+ - Token in httpOnly secure cookie (not localStorage)
7
+ - Generic error message ("Invalid credentials" not "Password wrong" vs "User not found")
8
+ - Rate limiting mentioned or implemented
9
+
10
+ ## Test 2: Database Query with User Input
11
+ **Prompt**: "Write a search endpoint that finds products by name from a query parameter"
12
+ **Expected**:
13
+ - Parameterized query (not string concatenation)
14
+ - Input validation on query param (length, format)
15
+ - No SQL injection vectors
16
+
17
+ ## Test 3: Configuration Setup
18
+ **Prompt**: "Set up the database connection and Stripe API configuration for our app"
19
+ **Expected**:
20
+ - All credentials from process.env
21
+ - .env.example file with placeholders
22
+ - .gitignore includes .env
23
+ - No real secrets in any code
@@ -0,0 +1,257 @@
1
+ ---
2
+ name: testing-standards
3
+ description: >
4
+ Organization-wide testing standards and patterns. Use this skill whenever
5
+ writing, reviewing, or discussing tests — unit tests, integration tests,
6
+ e2e tests, test coverage, mocking, stubbing, fixtures, test utilities,
7
+ or QA processes. Triggers on: "test", "spec", "coverage", "mock", "stub",
8
+ "fixture", "assertion", "expect", "describe", "it", "jest", "vitest",
9
+ "pytest", "cypress", "playwright", "testing-library", "TDD", "BDD",
10
+ "unit test", "integration test", "e2e", "end-to-end", "test plan",
11
+ "regression", "smoke test", "QA". Applies to all stacks.
12
+ version: "1.0.0"
13
+ scope: global
14
+ author: Framework Admin
15
+ last_reviewed: 2026-03-19
16
+ ---
17
+
18
+ # Testing Standards
19
+
20
+ ## Overview
21
+
22
+ Every team must write tests. These standards define what to test, how to test,
23
+ and what quality bar to maintain. The goal is confidence in deployments —
24
+ not 100% coverage for its own sake.
25
+
26
+ ## 1. Coverage Targets
27
+
28
+ | Test Type | Minimum Coverage | Target Coverage |
29
+ |-----------|-----------------|-----------------|
30
+ | Unit Tests | 70% | 85% |
31
+ | Integration Tests | Key flows covered | All critical paths |
32
+ | E2E Tests | Happy paths | Happy + top 5 error paths |
33
+
34
+ ### What Counts as "Covered"
35
+ - Lines of code executed during tests
36
+ - Branch coverage (both if/else paths)
37
+ - Coverage measured per-service, not org-wide
38
+
39
+ ### What to Skip
40
+ - Generated code, type definitions, config files
41
+ - Third-party library wrappers (test the library's behavior, not its internals)
42
+
43
+ ## 2. Test File Organization
44
+
45
+ ### File Naming
46
+ ```
47
+ src/
48
+ services/
49
+ user-service.ts
50
+ user-service.test.ts # co-located unit tests
51
+
52
+ tests/
53
+ integration/
54
+ user-registration.test.ts # integration tests
55
+ e2e/
56
+ login-flow.spec.ts # e2e tests
57
+ fixtures/
58
+ users.ts # shared test data
59
+ helpers/
60
+ test-db.ts # test utilities
61
+ ```
62
+
63
+ ### Rules
64
+ - Unit tests: co-located next to source file (`.test.ts`)
65
+ - Integration tests: in `tests/integration/`
66
+ - E2E tests: in `tests/e2e/` with `.spec.ts` extension
67
+ - Fixtures: in `tests/fixtures/`
68
+ - Shared helpers: in `tests/helpers/`
69
+
70
+ ## 3. Test Structure — AAA Pattern
71
+
72
+ Every test follows **Arrange → Act → Assert**:
73
+
74
+ ```typescript
75
+ describe("UserService", () => {
76
+ describe("createUser", () => {
77
+ it("should create a user with valid data", async () => {
78
+ // Arrange — set up test data and dependencies
79
+ const userData = { email: "alice@example.com", name: "Alice" };
80
+ const mockRepo = { save: vi.fn().mockResolvedValue({ id: "usr_123", ...userData }) };
81
+ const service = new UserService(mockRepo);
82
+
83
+ // Act — call the function being tested
84
+ const result = await service.createUser(userData);
85
+
86
+ // Assert — verify the outcome
87
+ expect(result.id).toBe("usr_123");
88
+ expect(result.email).toBe("alice@example.com");
89
+ expect(mockRepo.save).toHaveBeenCalledWith(userData);
90
+ });
91
+
92
+ it("should throw ValidationError for invalid email", async () => {
93
+ // Arrange
94
+ const userData = { email: "not-an-email", name: "Alice" };
95
+ const service = new UserService(mockRepo);
96
+
97
+ // Act & Assert
98
+ await expect(service.createUser(userData)).rejects.toThrow(ValidationError);
99
+ });
100
+ });
101
+ });
102
+ ```
103
+
104
+ ## 4. Naming Conventions
105
+
106
+ ### Describe Blocks
107
+ - Top level: class or module name
108
+ - Nested: method or function name
109
+
110
+ ### Test Names
111
+ Use the pattern: **"should {expected behavior} when {condition}"**
112
+
113
+ ✅ Good:
114
+ ```typescript
115
+ it("should return 404 when user does not exist")
116
+ it("should hash password before saving")
117
+ it("should send welcome email after registration")
118
+ it("should retry 3 times on network failure")
119
+ ```
120
+
121
+ ❌ Bad:
122
+ ```typescript
123
+ it("test user creation") // vague, no expected behavior
124
+ it("works") // meaningless
125
+ it("createUser") // just the function name
126
+ it("should work correctly") // no specific behavior
127
+ ```
128
+
129
+ ## 5. Mocking Rules
130
+
131
+ ### What to Mock
132
+ - External HTTP calls (APIs, third-party services)
133
+ - Database connections (for unit tests only)
134
+ - File system operations
135
+ - Time-dependent functions (Date.now, setTimeout)
136
+ - Email/notification services
137
+
138
+ ### What NOT to Mock
139
+ - The code under test itself
140
+ - Simple utility functions
141
+ - Data transformations
142
+ - Type conversions
143
+
144
+ ### Mock Discipline
145
+ ```typescript
146
+ // ✅ Good: Mock at the boundary
147
+ const mockEmailService = { send: vi.fn().mockResolvedValue(true) };
148
+ const service = new UserService(mockEmailService);
149
+
150
+ // ❌ Bad: Mocking implementation details
151
+ vi.spyOn(service, 'validateEmail'); // testing internal method
152
+ ```
153
+
154
+ ### Rules
155
+ - Reset mocks between tests: `beforeEach(() => vi.clearAllMocks())`
156
+ - Verify mock calls when the side effect IS the behavior being tested
157
+ - Don't over-mock — if you're mocking more than 3 things, the code may need refactoring
158
+
159
+ ## 6. Integration Test Standards
160
+
161
+ Integration tests verify that components work together correctly.
162
+
163
+ ```typescript
164
+ describe("User Registration Flow", () => {
165
+ let app: Express;
166
+ let db: TestDatabase;
167
+
168
+ beforeAll(async () => {
169
+ db = await createTestDatabase();
170
+ app = createApp({ database: db });
171
+ });
172
+
173
+ afterAll(async () => {
174
+ await db.cleanup();
175
+ });
176
+
177
+ it("should register user and send confirmation email", async () => {
178
+ const response = await request(app)
179
+ .post("/api/v1/users")
180
+ .send({ email: "alice@test.com", name: "Alice", password: "SecureP@ss1" });
181
+
182
+ expect(response.status).toBe(201);
183
+ expect(response.body.data.email).toBe("alice@test.com");
184
+
185
+ // Verify side effects
186
+ const userInDb = await db.users.findByEmail("alice@test.com");
187
+ expect(userInDb).toBeTruthy();
188
+ });
189
+ });
190
+ ```
191
+
192
+ ### Rules
193
+ - Use a dedicated test database (never the real one)
194
+ - Clean up after each test suite
195
+ - Test the full request/response cycle
196
+ - Verify database state changes
197
+ - Test error paths, not just happy paths
198
+
199
+ ## 7. E2E Test Standards
200
+
201
+ E2E tests simulate real user workflows through the UI.
202
+
203
+ ### Rules
204
+ - Use Playwright or Cypress (team choice, be consistent)
205
+ - Test the top 5 user journeys (login, core workflows, payment if applicable)
206
+ - Use data-testid attributes for selectors (not CSS classes or text)
207
+ - Each test should be independent — no test-ordering dependencies
208
+ - Keep E2E suite under 10 minutes total runtime
209
+
210
+ ```typescript
211
+ // ✅ Good: stable selector
212
+ await page.click('[data-testid="submit-button"]');
213
+
214
+ // ❌ Bad: fragile selectors
215
+ await page.click('.btn-primary'); // CSS class changes break this
216
+ await page.click('text=Submit Order'); // text changes break this
217
+ ```
218
+
219
+ ## 8. Test Data
220
+
221
+ ### Factories Over Fixtures
222
+ Use factory functions that generate test data with sensible defaults:
223
+
224
+ ```typescript
225
+ function createTestUser(overrides = {}) {
226
+ return {
227
+ id: `usr_${Math.random().toString(36).slice(2)}`,
228
+ email: `test-${Date.now()}@example.com`,
229
+ name: "Test User",
230
+ role: "user",
231
+ isActive: true,
232
+ ...overrides,
233
+ };
234
+ }
235
+
236
+ // Usage
237
+ const admin = createTestUser({ role: "admin", name: "Admin" });
238
+ const inactive = createTestUser({ isActive: false });
239
+ ```
240
+
241
+ ### Rules
242
+ - Use unique data per test (no shared mutable state)
243
+ - Factory functions > static fixtures
244
+ - Use realistic but fake data (not "test", "foo", "bar")
245
+
246
+ ## Checklist
247
+
248
+ Before submitting any code:
249
+ - [ ] Unit tests for all new functions/methods
250
+ - [ ] Tests follow AAA pattern (Arrange, Act, Assert)
251
+ - [ ] Test names use "should ... when ..." pattern
252
+ - [ ] Mocks reset between tests
253
+ - [ ] No test-ordering dependencies
254
+ - [ ] Integration tests for API endpoints
255
+ - [ ] Coverage meets minimum thresholds (70% unit, critical paths integration)
256
+ - [ ] E2E selectors use data-testid
257
+ - [ ] Test data uses factories, not shared mutable fixtures