# Write node:test Tests for a Fastify API

Yes. An agent adds fastify.inject error-path tests with node:test against MySQL, runs npm test, and opens a pull request.

[Run this on Rush](https://cloud.getrush.ai/run/write-node-test-tests/fastify/), in a Project that has your repository.

## What the agent does

The agent maps routes and plugins to the existing test tree. In fastify/demo, `package.json` names scripts `test` → `db:seed` then `c8 npm run test:run`, and `test:run` → `glob -c "tsx --test" "./test/**/*.ts"` using Node's built-in test runner. Dependencies include Fastify 5, `@fastify/autoload`, TypeBox, Knex and `mysql2`. `docker-compose.yml` runs `mysql:8.4` with a healthcheck on `mysqladmin ping`.

Source lives under `src/routes/api/` (`auth/index.ts`, `users/index.ts`, `tasks/index.ts`) and `src/plugins/app/` (authorization, password-manager, repositories, file-manager). Tests already cover happy paths and some errors: `test/routes/api/auth/auth.test.ts` (invalid credentials, rollback), `test/app/error-handler.test.ts`, `not-found-handler.test.ts`, `rate-limit.test.ts`, and task/user suites that call `app.inject` / `injectWithLogin` from `test/helper.js`. The agent diffs route handlers for branches that still lack inject cases (authorization failures, validation 400s, missing task ids, multipart errors, knex failures).

New files stay idiomatic: `import { describe, it, before, after } from 'node:test'`, `assert` from `node:assert`, `build()` from the helper, and `app.inject({ method, url, payload })` against the real seeded MySQL. It does not switch the suite to Jest or Vitest, and it does not mock Knex for these error paths when the demo's style is an integration inject.

It brings up MySQL the way the README expects (`docker compose up -d` or the project's scripts), runs `npm test`, fixes failures, and opens a pull request adding only test sources plus seed data if a new fixture user is required. Concrete gaps it looks for include unauthorized access to `GET /api/tasks` without a session, TypeBox validation failures on task create payloads from `src/schemas/tasks.ts`, missing task ids on update/delete, and multipart upload failures through `tasks-file-manager.ts` when the file is empty or the wrong type. Each new case follows the seeding helpers already in `tasks.test.ts` (`createUser`, `createTask`) so foreign keys stay valid in MySQL.

## Start it with one API call

`POST https://api.prix.dev/o/{org}/sessions`

```json
{
  "agent": "claude",
  "input": "Find the routes and plugins in this Fastify API whose error paths have no tests and write node:test tests for them using fastify.inject against a real MySQL in the sandbox. Run npm test and open a pull request.",
  "resources": [
    {
      "url": "https://github.com/your-org/your-fastify-api"
    }
  ]
}
```

1. **Get an API key.** In the console, open Settings, then API keys, and create a key for your org. Send it in the Authorization header as a Bearer token.
2. **Send the request.** POST the body in request.json to https://api.prix.dev/o/{org}/sessions, with your repository as the resources URL. The run starts in its own cloud sandbox.
3. **Read what came back.** Follow the run on its live stream or wait for the run.completed webhook, then read the result and its trajectory.

## What comes back

What comes back is a pull request under `test/` that adds `node:test` cases for the missing error paths, still using `fastify.inject` and the shared `build` helper. Application plugins remain untouched unless a test-only export is required.

The pull request description lists which routes gained coverage and the `npm test` command that passed (including c8). The trajectory keeps Docker MySQL logs and failing inject payloads from earlier attempts.

Before merging, a reviewer checks that assertions expect the demo's error shape (for example the internal error handler's `{ message: 'Internal Server Error' }`), that login helpers match `injectWithLogin`, and that CI's MySQL service definition still matches `docker-compose.yml`.

## Run it on every API route or plugin changed

On pulls that touch `src/routes/**` or `src/plugins/**`, POST this session body so new error branches get inject coverage against MySQL in a fresh sandbox instead of sharing a developer's local database.

Forward Rush `run.completed` webhooks to your API team channel with the session URL. Stay within `max_concurrent` when several Fastify services share one API key.

## Why run it on Rush?

These tests need MySQL 8.4, migrations, seeds and a full Fastify boot. Rush runs Docker Compose and `npm test` in an isolated sandbox so your laptop's MySQL port and data stay alone, and the agent can reset the database between attempts. Coverage from `c8` stays enabled through the existing `npm test` script, so the pull request can mention which error branches moved off zero without inventing a second coverage tool.

The proof is green `tsx --test` output in the trajectory plus a pull request reviewers can re-run with the same compose file. Multiple services can get error-path suites in parallel without colliding on one MySQL instance.

## Frequently asked questions

### Why node:test instead of Jest?

Because that is what the Fastify demo already uses: `tsx --test` over `./test/**/*.ts` with `c8`. The agent extends that runner rather than introducing another.

### Does it mock MySQL?

No. Error-path inject tests run against the real database from `docker-compose.yml` (`mysql:8.4`), after `npm run db:seed`, matching the existing task and auth suites.

### Will it add tests for every happy path again?

It focuses on error paths that lack coverage (validation, authz, missing resources, handler failures). Existing happy-path tests stay as they are.

### How does it call authenticated routes?

Through the demo's `injectWithLogin` helper used in `auth.test.ts` and the tasks suite, so session cookies match `@fastify/session` configuration.
