| Type | Framework | Config |
|---|---|---|
| Unit tests | Vitest 3.1 | vitest.config.ts (workspace mode) |
| E2E tests | Playwright 1.54 | apps/ui/playwright.config.ts |
# All unit tests
pnpm test
# Single workspace
pnpm --filter @hypershell/ui test
pnpm --filter @hypershell/desktop test
pnpm --filter @hypershell/session-core test
pnpm --filter @hypershell/db test
# Watch mode
pnpm --filter @hypershell/ui test -- --watch
# Single test file
pnpm --filter @hypershell/ui test -- src/features/layout/layoutStore.test.ts
# E2E (headless)
pnpm --filter @hypershell/ui test:e2e
# E2E (headed — shows browser)
pnpm --filter @hypershell/ui test:e2e:headed
# CI commands
pnpm ci:test # Unit tests
pnpm ci:test:e2e # E2E with server auto-startTest files live next to their source as *.test.ts or *.test.tsx:
features/layout/
├── layoutStore.ts
├── layoutStore.test.ts ← unit test
├── Workspace.tsx
└── TabBar.tsx
layoutStore.test.ts— Tab/pane layout operationsbroadcastStore.test.ts— Broadcast mode statesessionRecoveryStore.test.ts— Session recovery logicsearchIndex.test.ts— Quick Connect fuzzy searchuseFileKeyboard.test.ts— SFTP keyboard navigationfileUtils.test.ts— File sorting, size formatting, path utilities
main.lifecycle.test.ts— App bootstrap/cleanup lifecycleregisterIpc.test.ts— IPC handler registrationtransferManager.test.ts— SFTP transfer queue
syncEngine.test.ts— SFTP bidirectional syncparseSshConfig.test.ts— SSH config parserportForwarding.test.ts— Port forward profile management
hostsRepository.test.ts— Host CRUD operationsserialProfilesRepository.test.ts— Serial profile CRUDsftpBookmarksRepository.test.ts— Bookmark operationsworkspaceRepository.test.ts— Workspace save/load
Playwright tests are in apps/ui/tests/. They run against headless Chromium with:
- 30-second timeout per test
- Auto-starts Vite dev server on
127.0.0.1:5173 - Configured in
playwright.config.ts
// src/features/myFeature/myStore.test.ts
import { describe, it, expect } from "vitest";
import { createStore } from "./myStore";
describe("myStore", () => {
it("does the thing", () => {
const store = createStore();
store.getState().doThing();
expect(store.getState().result).toBe("expected");
});
});The PR gates workflow (.github/workflows/pr-gates.yml) runs on every pull request:
- Checkout + pnpm install
- Build all workspaces
- Run all unit tests
- Run Playwright E2E tests
- Both Ubuntu and Windows runners
All checks must pass before merge.