# Testing Patterns

## Test Coverage Goal

Tests should cover all paths in the corresponding `docs/command/*.md`:

- **Process Flow**: Each branch in the mermaid flowchart = one test case
- **Error Scenarios**: Each error code listed = one test case
- **Idempotent paths**: If flowchart shows "Already exists? → Return existing"

## Mock Database

Use `createKyselyMock` from `@tailor-platform/sdk/vitest`, typed with the namespace schema:

```typescript
import { createKyselyMock } from "@tailor-platform/sdk/vitest";
import type { Namespace } from "../generated/kysely-tailordb";

const mock = createKyselyMock<Namespace[keyof Namespace]>();

// Stage the rows upcoming queries return, in execution order
mock.enqueueResults([first], [second]);

// Commands run inside a transaction; queries take mock.db directly
const result = await mock.withTx((trx) => run(trx, input, ctx));
const queryResult = await run(mock.db, input);
```

Inspect recorded queries via `mock.selects` / `mock.inserts` / `mock.updates` / `mock.deletes` (each `{ kind, sql, parameters, node }`):

- Written values: `mock.inserts[0].insertValues()` (single row), `mock.inserts[0].insertRows()` (multi-row), `mock.updates[0].updateValues()`
- Query shape: assert on `mock.selects[0].sql` and `mock.selects[0].parameters`

## Custom Fields Passthrough

For commands with generic `CF`, add one test verifying custom fields reach the insert:

- Import from `./createX.generated` (the generated shell that wires permissions)
- Pass extra fields in the input: `await mock.withTx((trx) => createX(trx, { name: "Test", myField: "value" }, ctx))`
- Assert with `insertValues()`: `expect(mock.inserts[0].insertValues()).toEqual(expect.objectContaining({ myField: "value" }))`
- Index into `mock.inserts[n]` when multiple inserts occur (e.g., audit events)

## Test Case Documentation Sync

Command and query docs include a `## Test Cases` section listing each `it()` description. This list must stay in sync with the actual test file:

- Each `it("...")` in the test file must appear as `- ...` in the doc's `## Test Cases`
- Each item in `## Test Cases` must have a corresponding `it()` in the test file
- Run `erp-kit module sync-check` to verify alignment
- When adding a new test, add the `it()` description to the doc first, then write the test
- Test case descriptions should match the doc's Process Flow branches and Error Scenarios

## Fixtures (`testing/fixtures.ts`)

- Import `Schema` from `lib/types` (not `Namespace` from generated code)
- Pattern: `export const baseEntity = { ... } as const satisfies Entity<Schema>`
- Fixed IDs for traceability: `"entity-1"`
- Consistent timestamp: `new Date("2024-01-01T00:00:00.000Z")`
- `updatedAt: null` for base fixtures
