# TDD Transition Plan — MeshiTrack This document details the blueprint for transitioning the MeshiTrack monorepo to a strict Test-Driven Development (TDD) workflow. It outlines the specific steps, tooling enhancements, repository guidelines, and architectural patterns required to shift from "test-after" to "test-first" development. --- ## 1. Objectives 1. **Maintain Strict Quality Bars**: Ensure all new code seamlessly meets our high coverage gates (100% lines/functions/statements, 90% branches for `packages/api` & `packages/shared`, and 90% lines, 85% functions, 75% branches, 85% statements for `packages/web`). 2. **Prevent Architecture Regression**: Stop implementing business logic before definitions and type interfaces are established in `packages/shared`. 3. **Elevate DX and Iteration Speed**: Speed up the local feedback loop (Vitest/RTL runtimes) to enable a continuous Red-Green-Refactor cycle. 4. **Standardize Mocks and Factories**: Establish reusable test builders and automated dependency mocks to reduce boilerplate. --- ## 2. The MeshiTrack TDD Loop (Red-Green-Refactor) TDD requires writing tests *before* writing the corresponding implementation. In MeshiTrack, this cycle is applied iteratively across each vertical slice. ```mermaid graph TD A[1. Write Failing Test - RED] --> B[2. Run Test & Verify Failure] B --> C[3. Write Minimal Code - GREEN] C --> D[4. Run Test & Verify Pass] D --> E[5. Refactor Code & Clean Boilerplate] E --> F[6. Run All Tests to Prevent Regression] F --> A ``` ### The Rules of TDD in MeshiTrack: 1. **Write no production code** unless it is to make a failing unit or integration test pass. 2. **Write only enough of a test** to demonstrate a failure (compilation failure counts as a failure). 3. **Write only enough production code** to make the single failing test pass. 4. **Refactor immediately** after going Green, while both the unit test and existing regression suite are passing. --- ## 3. Layer-by-Layer TDD Guide ### Layer 1: Shared Package (`packages/shared`) The shared package contains domain types, enums, and Zod schemas. It must remain pure TypeScript. 1. **Red**: Define the interface or enum signature in TypeScript. Write a test in `src/validation/*.test.ts` asserting how the validation schema should handle valid, invalid, and edge-case payloads. 2. **Green**: Implement the Zod v4 validation schema in `src/validation/*.schemas.ts`. Run the test to verify it passes. 3. **Refactor**: Clean up the schema declarations, refine custom error messages, and ensure barrel exports are updated in `index.ts`. --- ### Layer 2: Database Schema & Repository (`packages/api`) This layer handles persistence via Mongoose schemas and Awilix-registered repositories. 1. **Red**: Write an integration test (`*.repository.test.ts`) using `mongodb-memory-server` that tests data storage, constraints, index behavior, and `householdId` filtering. 2. **Green**: Implement the Mongoose schema, compile the model, and write the Repository class methods using `.lean().exec()` on all reads. Verify the integration test passes. 3. **Refactor**: Optimize database indexes, ensure appropriate Mongoose options are set, and check for memory leaks or unclosed connections. --- ### Layer 3: Service Layer (`packages/api`) Services contain the core business logic, including validation, authorization checks, and transactional tasks. 1. **Red**: Write unit tests (`*.service.test.ts`) using Vitest. Mock all dependencies (e.g., repositories, event emitters) using `vi.fn()`. Write tests asserting correct handling of successful cases, expected errors (`NotFoundError`, `ConflictError`, etc.), and household isolation boundaries. 2. **Green**: Create the Service class with constructor injection via Awilix. Implement only the minimum logic required to pass the test cases. 3. **Refactor**: Extract duplicate logic into helper functions, improve type safety, and simplify constructor dependencies. --- ### Layer 4: Route Layer (`packages/api`) Fastify routes define endpoints, validate incoming payloads via Zod, resolve services, and return responses. 1. **Red**: Write a route test (`*.routes.test.ts`) using Fastify's `app.inject()`. Assert status codes, headers, and the response body structure. Mock the service layer resolved from the request DI scope (`request.diScope.resolve`). 2. **Green**: Implement the Fastify route plugin, declare path validation schemas, resolve the service from the DI container, and call it. Register the plugin. 3. **Refactor**: Optimize error mappings, clean up route paths, verify route configuration options (e.g., household scope exclusions). --- ### Layer 5: Web API Client (`packages/web`) The client wrapper calls the backend API and handles client-side caching or state synchronization (e.g., via SWR). 1. **Red**: Write a service unit test (`*.test.ts`) using Vitest. Configure MSW (Mock Service Worker) to mock the API endpoint response. Write assertions checking payload formatting, query serialization, and error transformations. 2. **Green**: Implement the frontend service in `src/services/` using fetch. Run tests and verify MSW handlers return correctly. 3. **Refactor**: Standardize request configuration, dry up common header settings, and enhance client type-safety. --- ### Layer 6: Web UI (`packages/web`) React components and Next.js pages display data, capture input, and handle interactions. 1. **Red**: Write component tests (`*.test.tsx`) using React Testing Library. Query elements by accessible roles (e.g., `screen.getByRole('button', { name: /save/i })`). Assert correct rendering of states (loading, empty, success) and verify user interactions fire expected service callbacks. 2. **Green**: Implement the React component (Server/Client split as appropriate). Write the bare minimum JSX/TSX to satisfy the test roles and events. 3. **Refactor**: Refine CSS structures, optimize components for re-renders, clean up accessibility attributes, and verify responsive design parameters. --- ## 4. DX Tooling Enhancements (Bridges) To enable developers to practice TDD seamlessly, we must upgrade our test execution loop and reduce boilerplate. ### Bridge A: Immediate Watch Mode for Active Files Running `npm run test` or `npm run test:cov` across the entire workspace takes too long for the continuous TDD loop. We need scripts to instantly watch specific directories or single files. We will update package-level `package.json` scripts to introduce: 1. **Root package.json**: - Add `"test:watch": "turbo run test:watch"` 2. **packages/web/package.json**: - Add `"test:watch": "vitest"` (mirroring packages/api) This will allow developers to run: * `npm run test:watch -w packages/api` to start a continuous, interactive Vitest runner for API files. * `npm run test:watch -w packages/api -- src/modules/products/products.service.test.ts` to focus only on a single service during the Red-Green cycle. ### Bridge B: Automated Mock Helpers Creating manual mocks for every repository in every service test adds substantial boilerplate. We will introduce a standard mock utility `packages/api/src/common/test/mock-repository.ts` that dynamically mocks any repository interface. ```typescript import { vi } from 'vitest'; export function createMockRepository(repoClass: new (...args: any[]) => T): Record { const methods = Object.getOwnPropertyNames(repoClass.prototype).filter( (name) => name !== 'constructor' && typeof repoClass.prototype[name] === 'function' ); const mock: Record = {}; for (const method of methods) { mock[method] = vi.fn(); } return mock as Record; } ``` This reduces the boilerplate in service tests from a manual 15-line structure to a single line: ```typescript const mockRepo = createMockRepository(ProductsRepository); ``` --- ## 5. TDD Commit & Git Conventions To document and encourage step-by-step TDD, we will adopt atomic commit structures matching the Red-Green-Refactor steps: 1. **Red Commit**: When a new test suite is created and fails. - `test(pantry): add failing test for spoilage calculation (RED)` 2. **Green Commit**: When the production code is completed and tests pass. - `feat(pantry): implement spoilage calculation logic (GREEN)` 3. **Refactor Commit**: When the code is cleaned up while staying green. - `refactor(pantry): optimize date difference utility in spoilage` These atomic commits make peer reviews and rollbacks extremely clean and make it simple to track development momentum. --- ## 6. Guidelines Alignment & Updates To formalize the transition, we will execute the following file updates: 1. **Update `ANTIGRAVITY.md`**: - Modify the "Implementation Workflow" section to make TDD mandatory. - Replace steps with the Red-Green-Refactor workflow per layer. - Introduce the `test:watch` commands and mock helper directives. 2. **Update `docs/instructions/conventions.md`**: - Re-orient the "Implementation Workflow" from "test-after" to TDD-first. 3. **Introduce `docs/instructions/tdd.md`**: - A dedicated developer tutorial on TDD in the MeshiTrack codebase, explaining mocks, databases, and Next.js testing patterns in detail. --- ## 7. Immediate Action Plan To bridge the TDD gap immediately, we will execute these concrete steps in this task: 1. **Step 1: Codebase Tooling Infrastructure** - Add `"test:watch": "vitest"` to `packages/web/package.json`. - Add `"test:watch": "turbo run test:watch"` to root `package.json`. 2. **Step 2: Reusable Mock Helper** - Create `packages/api/src/common/test/mock-repository.ts` containing the automated mock builder utility. 3. **Step 3: Document TDD & Update Guidelines** - Create `docs/instructions/tdd.md` as the definitive guide. - Update `ANTIGRAVITY.md`'s workflow section. - Update `docs/instructions/conventions.md`'s workflow section. 4. **Step 4: Verification** - Verify the codebase build and tests are completely operational.