nextjs-cms

Testing

The four test layers, how to run each, and where new tests belong.

Tests run on Vitest, configured as three projects in the root vitest.config.ts, plus Playwright for end-to-end tests of the admin.

LayerCommandFilesNeeds
Unitpnpm test:unitpackages/**/*.test.ts, apps/**/*.test.tsnothing
Componentpnpm test:component**/*.test.tsx (rooted in apps/cms)Playwright's Chromium
Integrationpnpm test:integration**/*.integration.test.tsDocker test database
End-to-endpnpm --filter nextjs-cms-app test:e2eapps/cms/sections/__TESTS__/**/*.spec.tsRunning admin + database

Unit tests

Fast, no I/O. Most of the core is covered here: field helpers and classes, validators, conditional rules, config merging, CLI helpers, schema generation (with the database mocked).

Terminal
pnpm test:unit
pnpm test:unit:watch
pnpm vitest run packages/nextjs-cms/src/core/fields/__tests__/slug.test.ts

Put tests next to the code: foo.ts → foo.test.ts, or a __tests__/ folder for larger suites.

Component tests

React components run in a real headless Chromium through Vitest browser mode (vitest-browser-react). The project is rooted in apps/cms, and @ resolves to the app. Name files *.test.tsx so the Node unit project never picks them up.

Terminal
pnpm exec playwright install chromium   # once
pnpm test:component

Integration tests

Run against a real MariaDB started by Docker Compose (testing/docker-compose-test.yml, port 3307, data in tmpfs):

Terminal
pnpm test:db:up
pnpm test:integration
pnpm test:db:down
  • Files are named *.integration.test.ts.
  • They run serially (--no-file-parallelism) against one shared database initialized once by testing/global-test-setup.ts (with a file lock).
  • Connection defaults: localhost:3307, root / password, database nextjs_cms_test; override with TEST_DB_HOST, TEST_DB_PORT, TEST_DB_USER, TEST_DB_PASSWORD, TEST_DB_NAME.
  • Auth tests also need ACCESS_TOKEN_SECRET and REFRESH_TOKEN_SECRET.
  • Test sections live in packages/nextjs-cms/src/api/__tests__/test_sections (and test_sections_localized), with a matching test.cms.config.ts.

Write an integration test whenever the behavior depends on SQL: submit classes, uniqueness, destination tables, locale rows, delete cascades.

End-to-end tests

Playwright drives the real admin (apps/cms/playwright.config.ts):

  • Tests live next to their sections in apps/cms/sections/__TESTS__/ (*.spec.ts), with sections like e2e-all-fields.section.ts that register every field type.
  • A setup project signs in once and stores the session in playwright/.auth/admin.json.
  • Environment comes from apps/cms/.env.test (E2E_* variables), and PLAYWRIGHT_BASE_URL (default http://localhost:3000).
  • Runs serially with one worker; reports go to apps/cms/playwright/reports.
Terminal
cd apps/cms
pnpm test:e2e         # headless, tears down test data
pnpm test:e2e:ui      # interactive
pnpm test:e2e:report  # open the last report

Coverage

Terminal
pnpm test:unit:coverage

Thresholds are set in vitest.config.ts (80% lines, functions, statements; 75% branches).

What to test for common changes

ChangeTests
New field optionField unit test (helper rejects bad input, class behavior), validator test, docs example compiles
Column type changeupdate-sections.test.ts
Submit behaviorIntegration test in core/submit/__tests__ or api/__tests__/integration
Router / procedurerouters/*.test.ts (unit, with mocks) or integration
Admin UI inputComponent test, and the e2e all-fields section