---
title: "Testing"
description: "vitest for units, Playwright for the admin SPA, and the template smoke script in CI."
canonical_url: "https://vinicunca.dev/taman/guides/testing"
---
# Testing

> vitest for units, Playwright for the admin SPA, and the template smoke script in CI.

## Unit tests (vitest)

Root scripts: `pnpm test` (watch), `pnpm test:unit` (`vitest run --dom`), `pnpm test:core` (`vitest packages`).

Config: `vitest.config.ts` at the repo root. happy-dom is a workspace dependency.

Patterns to copy from todo:

| Layer | Example |
| --- | --- |
| Repo | `apps/api/server/domains/todo/todo.repo.test.ts` + `todo.repo.fake.ts` |
| Service | `todo.service.test.ts` |
| RPC | `server/rpc/procedures/todo.test.ts`, `router.auth.test.ts`, `round-trip.test.ts` |
| Email | `server/email/email.test.ts` |
| Web | `src/api/errors.test.ts`, `src/router/auth-middleware.test.ts` |

Published packages have colocated tests (`packages/request/src/*.test.ts`, `packages/taman-ui/src/popup/**/__tests__`, `packages/taman-core/src/**/__tests__`).

## Playwright (`apps/web`)

```bash
cd apps/web
pnpm test:e2e
pnpm test:e2e-ui
```

`playwright.config.ts` starts Vite on port **5560** (not 5556). If 5560 is taken, the run fails unless `E2E_REUSE_SERVER=1`. Chromium only (Firefox/WebKit commented out).

Credentials (specs skip login if missing):

```bash
export E2E_EMAIL='admin@taman.local'
export E2E_PASSWORD='Admin123!'
# or TAMAN_E2E_EMAIL / TAMAN_E2E_PASSWORD
```

The API must already be running (`pnpm dev:api`), and its `NITRO_TRUSTED_ORIGINS` must include `http://localhost:5560` (the example `.env` does). Seed the admin first. Some comments still say `VITE_DIRECTOR_URL`; the app itself uses `VITE_API_URL`.

Helpers: `common/auth.ts` (login via `PAuthForm`), `common/preferences.ts` (patch the preferences localStorage key), `common/menu.ts`.

The e2e README describes **menu characterization** tests. Demo/System routes mentioned there may not exist in a generated project (examples are stripped).

## Template smoke (source repo / CI)

`.github/scripts/template-smoke.mjs` packs every publishable package, runs `create-taman` against this checkout (`--from`), then install / build / typecheck / test / lint of the generated app.

It currently allows known type errors in `packages/shell/layouts/src/core/tabbar/layout-core-tabbar.vue` (`styleType` on `TabbarPreferences`). The script **fails** if a listed error no longer occurs, so the skip list cannot rot silently.

Release workflow (`.github/workflows/release.yml`) runs `verify-packages.mjs` and `template-smoke.mjs` on every push and PR.

## Seed and e2e

`nx run api:seed` prints `E2E_EMAIL` / `E2E_PASSWORD` export lines. Treat `Admin123!` as **dev-only**.


## Sitemap

See the full [sitemap](https://vinicunca.dev/sitemap.md) for all pages.
