Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/nightly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,6 @@ jobs:
- uses: ./tooling/github/setup

- name: node-datachannel integration
run: bun -F @cyrus/connections test:unit
run: bunx vitest run --project @cyrus/connections
env:
CYRUS_NIGHTLY_WEBRTC: "1"
27 changes: 12 additions & 15 deletions apps/cli/src/git/git.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,24 @@ import { describe, expect, test } from "bun:test";
import { mkdtemp, rm, writeFile } from "node:fs/promises";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { initRepository } from "es-git";
import { getGitPatch } from "@/git/patch";
import { defaultWorktreePath, sanitizeBranchDirName } from "@/git/paths";
import { getGitStatus } from "@/git/status";

async function initRepo(dir: string) {
const proc = Bun.spawn(["git", "init", "-b", "main"], { cwd: dir });
await proc.exited;
await Bun.spawn(["git", "config", "user.email", "test@example.com"], {
cwd: dir,
}).exited;
await Bun.spawn(["git", "config", "user.name", "Test"], { cwd: dir }).exited;
const repo = await initRepository(dir, { initialHead: "main" });
await writeFile(join(dir, "README.md"), "hello\n");
await Bun.spawn(["git", "add", "README.md"], { cwd: dir }).exited;
const commit = Bun.spawn(
["git", "-c", "commit.gpgsign=false", "commit", "-m", "init"],
{ cwd: dir }
);
await commit.exited;
if (commit.exitCode !== 0) {
throw new Error("Failed to create initial commit in test repo");
}
const index = repo.index();
index.addPath("README.md");
index.write();
const tree = repo.getTree(index.writeTree());
const signature = { name: "Test", email: "test@example.com" };
repo.commit(tree, "init", {
author: signature,
committer: signature,
updateRef: "HEAD",
});
}

describe("git paths", () => {
Expand Down
8 changes: 2 additions & 6 deletions apps/cli/src/utils/fs.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,11 @@ import { describe, expect, test } from "bun:test";
import { mkdir, mkdtemp, writeFile } from "node:fs/promises";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { initRepository } from "es-git";
import { listFiles, searchFiles } from "./fs";

async function initGitRepo(cwd: string): Promise<void> {
const exitCode = await Bun.spawn(["git", "init"], {
cwd,
stdout: "ignore",
stderr: "ignore",
}).exited;
if (exitCode !== 0) throw new Error("git init failed");
await initRepository(cwd);
}

describe("listFiles", () => {
Expand Down
2 changes: 0 additions & 2 deletions apps/server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
"scripts": {
"dev": "wrangler dev",
"check:types": "tsc --noEmit",
"test:unit": "vitest run --max-workers=1 --no-isolate",
"db:push": "dotenvx run -- drizzle-kit push",
"db:generate": "dotenvx run -- drizzle-kit generate",
"wrangler:types": "wrangler types --cwd src",
Expand Down Expand Up @@ -33,7 +32,6 @@
"zod": "catalog:"
},
"devDependencies": {
"@cloudflare/vitest-pool-workers": "^0.18.6",
"@cyrus/typescript": "workspace:*",
"@types/bun": "catalog:",
"@types/pg": "^8.16.0",
Expand Down
28 changes: 0 additions & 28 deletions apps/server/vitest.config.ts

This file was deleted.

4 changes: 1 addition & 3 deletions apps/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@
"dev": "vite",
"build": "vite build",
"preview": "vite preview",
"check:types": "tsc --noEmit",
"test:unit": "vitest run"
"check:types": "tsc --noEmit"
},
"dependencies": {
"@base-ui/react": "^1.6.0",
Expand Down Expand Up @@ -64,7 +63,6 @@
"zustand": "^5.0.14"
},
"devDependencies": {
"@cyrus/test": "workspace:*",
"@cyrus/typescript": "workspace:*",
"@tailwindcss/vite": "^4.3.2",
"@tanstack/devtools-vite": "^0.8.1",
Expand Down
12 changes: 0 additions & 12 deletions apps/web/vitest.config.ts

This file was deleted.

321 changes: 136 additions & 185 deletions bun.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/adr/0017-vitest-default-bun-only-cli-desktop.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@ The repo's test-runner rule flips: Vitest is now the default everywhere, and `bu

`tests/e2e/web` stays on native `@playwright/test`. Vitest Browser Mode with the Playwright provider was considered and rejected: it uses Playwright only as a rendering engine for browser-based component tests, with no equivalent to Playwright Test's `webServer` lifecycle or the worker-scoped `test.extend` fixtures (`auth`, `cliWorker`) just introduced for this suite. Adopting it would mean rebuilding Playwright Test's own orchestration on top of Playwright, for no fidelity gain, and would undo that work. Consequence: Playwright keeps its own separate report; these specs never appear in Vitest UI.

A single root `vitest.workspace.ts` replaces every package-local `vitest.config.ts`. Root `vitest run` becomes the CI-facing `test:unit` command directly, and turbo's per-package `test:unit` fan-out is dropped — no package's suite is run in isolation today, so the lost per-package cache isn't missed, and Vitest's own `--project` flag (repeatable, glob- and negation-capable) still allows scoping a run when one is needed. Coverage runs on the Istanbul provider globally, not V8: the Cloudflare pool-workers project can't produce V8 coverage at all, and Vitest's coverage config is root-level rather than per-project, so one provider has to work everywhere. No thresholds are set — coverage is visibility only for now. `apps/cli` and `apps/desktop` are out of scope for coverage this round; Bun has its own separate `--coverage` mechanism, left unwired and unmerged with the Istanbul report. Vitest UI is added as its own local-only `test:unit:ui` script, with no CI role.
A single root `vitest.config.ts` (`test.projects`) replaces every package-local `vitest.config.ts`. Root `vitest run` becomes the CI-facing `test:unit` command directly, and turbo's per-package `test:unit` fan-out is dropped — no package's suite is run in isolation today, so the lost per-package cache isn't missed, and Vitest's own `--project` flag (repeatable, glob- and negation-capable) still allows scoping a run when one is needed. Coverage runs on the Istanbul provider globally, not V8: the Cloudflare pool-workers project can't produce V8 coverage at all, and Vitest's coverage config is root-level rather than per-project, so one provider has to work everywhere. No thresholds are set — coverage is visibility only for now. `apps/cli` and `apps/desktop` are out of scope for coverage this round; Bun has its own separate `--coverage` mechanism, left unwired and unmerged with the Istanbul report. Vitest UI is added as its own local-only `test:unit:ui` script, with no CI role.
13 changes: 6 additions & 7 deletions docs/guides/TESTING_FRAMEWORK.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,14 @@ Cyrus uses a layered test setup so each part of the system is tested with the ru

| Scope | Runner | Location |
| --- | --- | --- |
| Pure TypeScript, schemas, CLI, database, process tests | Bun test | Colocated `*.test.ts` or package `__tests__/integration/` |
| `apps/web`, `shared/hooks`, `shared/providers` | Vitest + jsdom | Package-local `vitest.config.ts`; shared setup in `tooling/test/setup/vitest.shared.ts` |
| `apps/server` | Vitest with `@cloudflare/vitest-pool-workers` | Colocated `src/**/*.test.ts` |
| Harness-driven E2E scenarios | Vitest + node | Root `tests/e2e/scenarios/` |
| `apps/cli`, `apps/desktop` | Bun test | Colocated `*.test.ts` or package `__tests__/integration/` |
| Vitest workspace packages (`apps/web`, `apps/server`, `shared/*`) | Root Vitest Projects | `vitest.config.ts` at the repo root; shared DOM setup in `tooling/test/setup/vitest.shared.ts` |
| Harness-driven E2E scenarios | Vitest + node | Root `tests/e2e/scenarios/` (workspace project `e2e`) |
| Browser user flows | Playwright | Root `tests/e2e/web/` |

Vitest is the default runner (ADR 0017). Bun stays permanently for `apps/cli` and `apps/desktop`; remaining Bun suites elsewhere migrate under #88.
Vitest is the default runner (ADR 0017). Bun stays permanently for `apps/cli` and `apps/desktop`.

In `apps/web`, `shared/hooks`, and `shared/providers`, every colocated `*.test.ts` and `*.test.tsx` suite runs on that package's Vitest + jsdom project. Each package's `test:unit` is `vitest run`. The shared Vitest setup registers Testing Library jest-dom matchers and cleans up the DOM after each test.
Root `bun test:unit` runs `vitest run --project='@cyrus/*'` (every unit project; `e2e` and `database-integration` sit outside that glob) plus `apps/cli`'s Bun unit suite. Use `vitest run --project <name>` to scope a single project. DOM packages (`apps/web`, `shared/hooks`, `shared/providers`) share Testing Library jest-dom matchers and DOM cleanup via `@cyrus/test/setup/vitest.shared`.

## Layout

Expand All @@ -27,7 +26,7 @@ tests/e2e/web/
tooling/test/
```

Unit tests stay close to the code they cover. In `apps/server`, every colocated `*.test.ts` runs on the Cloudflare Workers pool via `vitest`. Integration tests live under the package boundary they exercise. Cross-app tests live at the repo root.
Unit tests stay close to the code they cover. In `apps/server`, every colocated `*.test.ts` runs on the Cloudflare Workers pool via the root Vitest workspace. Integration tests live under the package boundary they exercise. Cross-app tests live at the repo root.

## CI Levels

Expand Down
2 changes: 1 addition & 1 deletion docs/guides/VERIFY_LOOP.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ For a faster tracer bullet, run only the nearest scenario from the repository ro

```sh
DATABASE_URL="$DATABASE_URL" NODE_ENV=testing \
vitest run --root tests/e2e scenarios/<scenario>.test.ts
vitest run --project e2e scenarios/<scenario>.test.ts
```

The canonical programmatic authentication flow is implemented in `tests/e2e/harness/auth.ts`. Reuse it instead of inventing test-only auth bypasses.
Expand Down
11 changes: 8 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@
"dev": "turbo dev",
"build": "turbo build",
"check:types": "turbo check:types",
"test": "turbo test:unit test:integration",
"test:unit": "turbo test:unit",
"test:unit:ui": "vitest --ui --watch",
"test": "bun run test:unit && bun run test:integration",
"test:unit": "vitest run --project='@cyrus/*' && bun --filter @cyrus/cli test:unit",
"test:unit:ui": "vitest --ui --watch --project='@cyrus/*'",
"test:integration": "turbo test:integration",
"test:e2e": "turbo test:e2e",
"dev:mobile": "turbo -F @cyrus/mobile dev",
Expand All @@ -68,15 +68,20 @@
},
"devDependencies": {
"@biomejs/biome": "^2.4.15",
"@cloudflare/vitest-pool-workers": "^0.18.6",
"@cyrus/test": "workspace:*",
"@cyrus/typescript": "workspace:*",
"@vitejs/plugin-react": "^4.6.0",
"@vitest/coverage-istanbul": "catalog:",
"@vitest/ui": "catalog:",
"jsdom": "catalog:",
"knip": "^6.27.0",
"lefthook": "^2.1.9",
"syncpack": "^15.3.2",
"turbo": "^2.10.4",
"typescript": "catalog:",
"ultracite": "^7.8.1",
"vite-tsconfig-paths": "^5.1.4",
"vitest": "catalog:"
},
"packageManager": "bun@1.3.14",
Expand Down
3 changes: 0 additions & 3 deletions shared/connections/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,6 @@
"./*": "./src/*.ts",
"./rtc/worker": "./src/rtc/worker/index.ts"
},
"scripts": {
"test:unit": "vitest run"
},
"dependencies": {
"@cyrus/errors": "workspace:*",
"@cyrus/schemas": "workspace:*",
Expand Down
2 changes: 1 addition & 1 deletion shared/connections/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@
"types": [],
"strictNullChecks": true
},
"include": ["src/**/*.ts", "src/**/*.tsx", "vitest.config.ts"],
"include": ["src/**/*.ts", "src/**/*.tsx"],
"exclude": ["node_modules"]
}
8 changes: 0 additions & 8 deletions shared/connections/vitest.config.ts

This file was deleted.

3 changes: 1 addition & 2 deletions shared/constants/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@
"./*": "./src/*.ts"
},
"scripts": {
"check:types": "tsc --noEmit",
"test:unit": "vitest run"
"check:types": "tsc --noEmit"
},
"devDependencies": {
"@cyrus/typescript": "workspace:*",
Expand Down
2 changes: 1 addition & 1 deletion shared/constants/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@
"types": ["bun"],
"strictNullChecks": true
},
"include": ["src/**/*.ts", "vitest.config.ts"],
"include": ["src/**/*.ts"],
"exclude": ["node_modules"]
}
8 changes: 0 additions & 8 deletions shared/constants/vitest.config.ts

This file was deleted.

3 changes: 1 addition & 2 deletions shared/database/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@
"check:types": "tsc --noEmit",
"db:push": "dotenvx run -- drizzle-kit push",
"db:studio": "dotenvx run -- drizzle-kit studio",
"test:unit": "vitest run src",
"test:integration": "vitest run __tests__/integration"
"test:integration": "vitest run --config ../../vitest.config.ts --project database-integration"
},
"dependencies": {
"@cyrus/errors": "workspace:*",
Expand Down
7 changes: 1 addition & 6 deletions shared/database/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,6 @@
"types": ["bun"],
"strictNullChecks": true
},
"include": [
"src/**/*.ts",
"src/**/*.tsx",
"__tests__/**/*.ts",
"vitest.config.ts"
],
"include": ["src/**/*.ts", "src/**/*.tsx", "__tests__/**/*.ts"],
"exclude": ["node_modules"]
}
8 changes: 0 additions & 8 deletions shared/database/vitest.config.ts

This file was deleted.

4 changes: 1 addition & 3 deletions shared/hooks/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@
"./*": "./src/*"
},
"scripts": {
"check:types": "tsc --noEmit",
"test:unit": "vitest run"
"check:types": "tsc --noEmit"
},
"dependencies": {
"@cyrus/constants": "workspace:*",
Expand All @@ -22,7 +21,6 @@
"zustand": "^5.0.14"
},
"devDependencies": {
"@cyrus/test": "workspace:*",
"@cyrus/typescript": "workspace:*",
"@testing-library/jest-dom": "^6.9.1",
"@testing-library/react": "^16.3.2",
Expand Down
2 changes: 1 addition & 1 deletion shared/hooks/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@
"@cyrus/providers/*": ["../providers/src/*"]
}
},
"include": ["src/**/*.ts", "src/**/*.tsx", "vitest.config.ts"],
"include": ["src/**/*.ts", "src/**/*.tsx"],
"exclude": ["node_modules"]
}
9 changes: 0 additions & 9 deletions shared/hooks/vitest.config.ts

This file was deleted.

4 changes: 1 addition & 3 deletions shared/providers/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@
"./*": "./src/*"
},
"scripts": {
"check:types": "tsc --noEmit",
"test:unit": "vitest run"
"check:types": "tsc --noEmit"
},
"dependencies": {
"@cyrus/connections": "workspace:*",
Expand All @@ -18,7 +17,6 @@
"@tanstack/react-query": "catalog:"
},
"devDependencies": {
"@cyrus/test": "workspace:*",
"@cyrus/typescript": "workspace:*",
"@testing-library/jest-dom": "^6.9.1",
"@testing-library/react": "^16.3.2",
Expand Down
2 changes: 1 addition & 1 deletion shared/providers/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@
"types": ["@testing-library/jest-dom"],
"strictNullChecks": true
},
"include": ["src/**/*.ts", "src/**/*.tsx", "vitest.config.ts"],
"include": ["src/**/*.ts", "src/**/*.tsx"],
"exclude": ["node_modules"]
}
9 changes: 0 additions & 9 deletions shared/providers/vitest.config.ts

This file was deleted.

3 changes: 0 additions & 3 deletions shared/schemas/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,6 @@
"./rtc/*": "./src/rtc/*.ts",
"./signaling": "./src/signaling.ts"
},
"scripts": {
"test:unit": "vitest run"
},
"dependencies": {
"zod": "catalog:"
},
Expand Down
2 changes: 1 addition & 1 deletion shared/schemas/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@
"types": ["bun"],
"strictNullChecks": true
},
"include": ["src/**/*.ts", "src/**/*.tsx", "vitest.config.ts"],
"include": ["src/**/*.ts", "src/**/*.tsx"],
"exclude": ["node_modules"]
}
Loading