Testing
HeadlessCore includes unit tests and a GitHub Actions CI pipeline.
Running tests locally
cd nextjs-starter-kit
npm test # Run once
npm run test:watch # Watch mode
Or from repo root:
npm test
Test framework
- Vitest v3 with Node environment
- Config:
nextjs-starter-kit/vitest.config.ts - Test files:
src/**/*.test.ts
Test coverage
| File | What it tests |
|---|---|
src/lib/blogSearch.test.ts |
Mock blog search, category filter, pagination |
src/lib/siteMode.test.ts |
Mode resolution, sitemap routes, minimal nav |
src/lib/rateLimit.test.ts |
Rate limiter allow/block behaviour |
src/lib/tenant.test.ts |
Multi-tenant host → tenant ID resolution |
src/lib/locale.test.ts |
Locale path parsing and URL prefixing |
src/lib/seo.test.ts |
Metadata and JSON-LD builders |
src/components/BlockRenderer.test.ts |
Gutenberg HTML enhancement (core + pro blocks) |
Example: blog search
filterMockPosts(posts, { search: "headless" });
// → { posts: [...], total, page, totalPages, hasNextPage, hasPreviousPage }
Example: site mode
resolveSiteMode("shop"); // → "shop"
getSitemapRoutes("multi"); // includes "/shop"
isMinimalNavigation("landing"); // → true
CI pipeline
File: .github/workflows/ci.yml
Triggers on push/PR to main or master:
npm ciinnextjs-starter-kit/npm run lintnpm testnpm run build
Adding new tests
- Create
src/lib/myModule.test.tsnext to the module - Import from
vitest:
import { describe, expect, it } from "vitest";
import { myFunction } from "./myModule";
describe("myFunction", () => {
it("does the thing", () => {
expect(myFunction()).toBe(expected);
});
});
- Run
npm test
What is not tested (yet)
- Integration tests against live WordPress
- E2E browser tests (Playwright)
- GraphQL fetch functions (require mock server)
These are planned for future phases. For now, npm run build validates TypeScript across the full app.
Mock data in tests
Tests use inline fixtures or mockData.ts types. They do not require WordPress to be running.