Testing
Planner uses a multi-layered testing strategy: unit tests with Vitest and end-to-end tests with Playwright.
Unit Tests (Vitest)
Backend
204 unit tests covering:
- Auth flows (register, login, refresh, password reset, email verification)
- Organization, team, and project CRUD
- Quota enforcement and plan management
- Notification delivery
- Email templates
- Storage operations
bash
# Run backend unit tests
cd apps/backend && pnpm test
# Watch mode
cd apps/backend && pnpm test:watchFrontend
7 unit tests covering:
- Composables (useStatuses, usePriorities)
- Store logic
bash
# Run frontend unit tests
cd apps/frontend && pnpm testEnd-to-End Tests (Playwright)
63 E2E tests across 19 spec files covering the full user journey.
Prerequisites
- Backend running on port 4000
- Frontend running on port 3000
- Database seeded (via
global-setup.ts)
Test Structure
apps/frontend/e2e/
├── config/ # Playwright config
├── fixtures.ts # Page Object injection
├── global-setup.ts # API seed: user, org, team, project, task
├── helpers/
│ ├── api.ts # Raw fetch helpers
│ └── storage.ts # formatBytes, randomId
├── pages/ # 25 Page Objects
│ ├── login.page.ts
│ ├── dashboard.page.ts
│ ├── task-detail.page.ts
│ └── ... (22 more)
└── specs/ # 19 spec files
├── auth.spec.ts
├── dashboard.spec.ts
├── organizations.spec.ts
├── teams.spec.ts
├── projects.spec.ts
├── tasks.spec.ts
├── chat.spec.ts
├── notifications.spec.ts
├── settings.spec.ts
├── calendar.spec.ts
├── invitations.spec.ts
├── video-rooms.spec.ts
├── admin-dashboard.spec.ts
├── admin-users.spec.ts
├── admin-roles.spec.ts
├── admin-groups.spec.ts
├── admin-orgs.spec.ts
├── admin-teams.spec.ts
└── admin-plans.spec.tsRunning E2E Tests
bash
# Headless
pnpm --filter @planner/frontend test:e2e
# UI mode (interactive debugging)
pnpm --filter @planner/frontend test:e2e:uiPage Object Model
Each page is encapsulated in a Page Object using Playwright native locators (getByRole, getByLabel, locator). Page Objects are injected into tests via fixtures.ts:
typescript
test('should create task', async ({ taskDetailPage }) => {
await taskDetailPage.fillTitle('New task')
await taskDetailPage.submit()
await expect(taskDetailPage.taskTitle).toHaveText('New task')
})Global Setup
global-setup.ts runs before all tests and creates test data via raw API calls:
- Register E2E user
- Create organization
- Create team
- Create project
- Create sample task
Each spec logs in via the UI form in beforeEach, ensuring realistic auth flow testing.
CI
GitHub Actions pipeline:
typecheck → test → build- Type checking runs on all packages
- Unit tests execute in parallel
- Build verifies all apps compile successfully