Skip to content

Commit 276f5a3

Browse files
authored
Migrate all tests to vitest for reliability (#206)
1 parent 4582a64 commit 276f5a3

116 files changed

Lines changed: 805 additions & 529 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.githooks/pre-commit

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,4 +55,4 @@ fi
5555

5656
echo "[pre-commit] Running backend tests..."
5757
cd packages/backend
58-
bun test
58+
bun run test

.github/workflows/claude-code-review.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,6 @@ jobs:
9393
"Bash(git log:*)",
9494
"Bash(bun install:*)",
9595
"Bash(bun run:*)",
96-
"Bash(bun test:*)",
9796
"Bash(npm run:*)",
9897
"Bash(ls:*)",
9998
"Bash(cat:*)",

.github/workflows/pr-tests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,4 @@ jobs:
3030
continue-on-error: true
3131

3232
- name: Run backend tests
33-
run: cd packages/backend && bun test
33+
run: cd packages/backend && bun run test

AGENTS.md

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,14 +64,17 @@ Drizzle ORM with SQLite (default) or Postgres. Tables: `request_usage`, `provide
6464
## Development & Testing
6565

6666
- **Dev server:** `bun run dev` (backend port 4000 + frontend watcher)
67-
- **Tests:** `bun test` from `packages/backend/`
67+
- **Tests:** `bun run test` from the repo root or from `packages/backend/` (`bun test` is intentionally blocked both at repo root and in `packages/backend` with a guidance message)
6868
- **Format:** `bun run format` / `bun run format:check`
6969

7070
### Test Isolation
7171

72-
- **Global setup:** `bunfig.toml` preloads `packages/backend/test/setup.ts` which mocks Logger and initializes in-memory DB.
73-
- **Do NOT** use `mock.module` to globally mock `config.ts` — it pollutes other tests.
74-
- **Use `registerSpy`** from `test/test-utils.ts` instead of raw `spyOn` — automatic cleanup after each test.
72+
- Backend tests run on **Vitest** via `packages/backend/vitest.config.ts`.
73+
- **Global setup:** `packages/backend/test/vitest.global-setup.ts` creates a temporary file-backed SQLite DB, runs migrations once, and cleans it up automatically after the run.
74+
- **Per-worker setup:** `packages/backend/test/vitest.setup.ts` installs logger/debug test doubles.
75+
- `packages/backend/bunfig.toml` intentionally blocks raw `bun test` in `packages/backend` and directs contributors to `bun run test` / `bun run test:watch`.
76+
- Root `bunfig.toml` intentionally blocks raw `bun test` at the repo root and directs contributors to `cd packages/backend && bun run test`.
77+
- **Use `registerSpy`** from `test/test-utils.ts` instead of raw `spyOn` when you want automatic cleanup after each test.
7578
- If you must mock a module, implement its **full public interface**.
7679

7780
---

CONTRIBUTING.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,11 +59,21 @@ bun run format
5959

6060
## Running Tests
6161

62+
From the repo root:
63+
64+
```bash
65+
bun run test
66+
```
67+
68+
Or from the backend package:
69+
6270
```bash
6371
cd packages/backend
64-
bun test
72+
bun run test
6573
```
6674

75+
> Note: `bun test` is intentionally blocked both at repo root and in `packages/backend`. Use `bun run test` instead.
76+
6777
The pre-commit hook runs backend tests automatically.
6878

6979
## Development

README.md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,12 +140,20 @@ bun run setup:hooks
140140
That configures `core.hooksPath` to `.githooks` and installs a `pre-commit` hook that runs:
141141

142142
```bash
143-
cd packages/backend && bun test
143+
cd packages/backend && bun run test
144144
```
145145

146+
> Note: `bun test` is intentionally blocked both at repo root and in `packages/backend`; use `cd packages/backend && bun run test` instead.
147+
146148
If the tests fail, the commit is blocked.
147149

148-
---
150+
You can also run backend tests from the repo root with:
151+
152+
```bash
153+
bun run test
154+
```
155+
156+
> Note: `bun test` is intentionally blocked both at repo root and in `packages/backend`; use `bun run test` instead.
149157
150158
## Configuration Migration Details
151159

bun.lock

Lines changed: 185 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

bunfig.toml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
1+
# Root tests are intentionally blocked.
2+
# Use `cd packages/backend && bun run test` for backend tests.
3+
14
[test]
2-
preload = ["./packages/backend/test/setup.ts"]
5+
root = "./test/bun-test-guard"

docs/TESTING.md

Lines changed: 40 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -18,41 +18,67 @@ The E2E tests are split by API type:
1818

1919
## Global Test Setup
2020

21-
To ensure test isolation and prevent "mock pollution" in Bun's shared-worker environment, this project uses a global setup script.
21+
Backend tests run on **Vitest**.
2222

23-
### `bunfig.toml` and `test/setup.ts`
23+
### `vitest.config.ts`, `test/vitest.global-setup.ts`, and `test/vitest.setup.ts`
2424

25-
The root `bunfig.toml` is configured to preload `packages/backend/test/setup.ts` before any tests run. This script establishes "Gold Standard" mocks for global dependencies like the **Logger**.
25+
- `packages/backend/vitest.config.ts` is the single backend test-runner config.
26+
- `packages/backend/test/vitest.global-setup.ts` creates a temporary file-backed SQLite database, generates Drizzle metadata if needed, runs migrations once, and removes the temp directory after the run.
27+
- `packages/backend/test/vitest.setup.ts` installs stable logger/debug test doubles for each worker.
28+
- Root `bunfig.toml` intentionally blocks raw `bun test` at the repo root and points contributors to `cd packages/backend && bun run test`.
29+
- `packages/backend/bunfig.toml` intentionally blocks raw `bun test` in `packages/backend` and points contributors to `bun run test`.
2630

2731
### Mocking Pattern: Shared Dependencies
2832

29-
Bun's `mock.module` is a process-global operation. Once a module is mocked, it remains mocked for the duration of that worker thread, and `mock.restore()` does **not** reset it.
33+
Vitest restores mocks reliably, but shared dependencies should still follow these rules:
3034

31-
To prevent crashes in other tests (e.g., `TypeError: logger.info is not a function`), follow these rules:
32-
33-
1. **Use the Global Setup:** Common modules like `src/utils/logger` should be mocked once in `setup.ts`.
34-
2. **Robust Mocking:** If you must mock a module in a specific test file, your mock **MUST** implement the entire public interface of that module (including all log levels like `silly`, `debug`, etc.).
35-
3. **Prefer Spying:** If you need to assert that a global dependency was called, use `spyOn` on the already-mocked global instance rather than re-mocking the module.
35+
1. **Use the shared setup:** Common modules like `src/utils/logger` are mocked once in `vitest.setup.ts`.
36+
2. **Robust Mocking:** If you mock a module in a specific test file, your mock **MUST** implement the relevant public interface of that module.
37+
3. **Prefer Spying:** If you need to assert that a shared dependency was called, use `vi.spyOn` or `registerSpy` rather than replacing the whole module repeatedly.
3638

3739
```typescript
3840
import { logger } from "src/utils/logger";
39-
import { spyOn, expect, test } from "bun:test";
41+
import { expect, test, vi } from "vitest";
4042

4143
test("my test", () => {
42-
const infoSpy = spyOn(logger, "info");
44+
const infoSpy = vi.spyOn(logger, "info");
4345
// ... run code ...
4446
expect(infoSpy).toHaveBeenCalled();
4547
});
4648
```
4749

4850
## Running Tests
4951

50-
### 1. Standard Run (Replay Mode)
51-
Uses existing cassettes. No API keys or network access are required.
52+
### 1. Standard Run
53+
54+
From the repo root:
55+
56+
```bash
57+
bun run test
58+
```
59+
60+
Or from the backend package:
5261

5362
```bash
5463
cd packages/backend
55-
bun test
64+
bun run test
65+
```
66+
67+
> Note: `bun test` is intentionally blocked both at repo root and in `packages/backend`. Use `bun run test` instead.
68+
69+
### 2. Watch Mode
70+
71+
From the repo root:
72+
73+
```bash
74+
bun run test:watch
75+
```
76+
77+
Or from the backend package:
78+
79+
```bash
80+
cd packages/backend
81+
bun run test:watch
5682
```
5783
*Tip: You can also run this via the VS Code task `Bun: Backend Tests`.*
5884

@@ -89,9 +115,3 @@ The following environment variables are used during **Record Mode**:
89115
| `PLEXUS_TEST_BASE_URL` | Base URL for Chat provider. | `https://api.upstream.mock/openai/v1` |
90116
| `PLEXUS_TEST_ANTHROPIC_BASE_URL` | Base URL for Messages provider. | `https://api.anthropic.com/v1` |
91117

92-
## Adding New Test Cases
93-
94-
1. Add a new JSON request body to `cases/chat/` (for Chat-like) or `cases/messages/` (for Messages-like).
95-
2. Run the **Record Mode** command above to capture the network interaction.
96-
3. Commit the new case and its corresponding cassette in `__cassettes__/`.
97-

package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
"module": "index.ts",
44
"devDependencies": {
55
"@biomejs/biome": "latest",
6-
"bun-types": "latest"
6+
"bun-types": "latest",
7+
"vitest": "^3.2.4"
78
},
89
"private": true,
910
"scripts": {
@@ -17,6 +18,8 @@
1718
"build:bin": "bun run build:frontend && bun build packages/backend/src/index.ts packages/backend/drizzle/migrations/*.sql packages/backend/drizzle/migrations_pg/*.sql packages/frontend/dist/*.png packages/frontend/dist/*.ico packages/frontend/dist/*.svg packages/frontend/dist/*.webmanifest --compile --asset-naming=\"[name].[ext]\" --outfile plexus",
1819
"install:all": "bun install && (cd packages/backend && bun install) && (cd packages/frontend && bun install)",
1920
"typecheck": "bun run --workspaces typecheck",
21+
"test": "cd packages/backend && bun run test",
22+
"test:watch": "cd packages/backend && bun run test:watch",
2023
"release": "bun run scripts/release.ts",
2124
"prepare": "git rev-parse --git-dir >/dev/null 2>&1 && git config core.hooksPath .githooks || true",
2225
"setup:hooks": "bash scripts/setup-git-hooks.sh",

0 commit comments

Comments
 (0)