The canonical renderer (src/domain/render.ts) is the executable DOM specification. Parity tests server-render every generated component and assert normalized HTML equals the canonical output for:
- Every brick
- Every part (or every PHP-supported part)
- Default props + every showcase fixture from
*.data.json
No per-runtime test authoring is needed when adding bricks — fixtures drive cases automatically.
| File | What it tests |
|---|---|
tests/domain.test.ts |
Recipe composition, tag resolution, expression evaluation, naming, validation |
tests/emitters.test.ts |
Structural conventions in generated code (syntax idioms, embeds, escape hatches) |
tests/parity.test.ts |
React 19 + Svelte 5 + Vue 3 DOM parity (always runs) |
tests/parity.templ.test.ts |
Go Templ DOM parity via cmd/parity harness |
tests/parity.latte.test.ts |
Latte DOM parity via cmd/parity-latte |
tests/parity.twig.test.ts |
Twig DOM parity via cmd/parity-twig |
bun test # all suites
bun run test:watch # watch mode
bun run verify # check + typecheck + tests (CI)| Module | Role |
|---|---|
tests/global-setup.ts |
Vitest: regenerate generated/ before run |
tests/preload-bun.ts |
Bun: Svelte SSR + Vue SFC compile plugins |
tests/support/ensure-generated.ts |
Write generated/ once per process |
tests/support/fixtures.ts |
Load *.data.json showcase cases |
tests/support/normalize.ts |
HTML normalization for fair comparison |
tests/support/props.ts |
Map canonical props → runtime-specific props |
tests/support/generated-ui.ts |
Dynamic import of generated React/Svelte/Vue modules |
tests/support/php.ts |
PHP toolchain detection, Composer install, parity runner |
For each brick × part × fixture:
- Build canonical HTML via
renderPart(). - Server-render generated component:
- React:
react-dom/serverrenderToStaticMarkup - Svelte:
svelte/serverrender - Vue:
@vue/server-rendererrenderToString
- React:
- Compare
normalizeHtml(actual)vsnormalizeHtml(expected).
Children fixture text: "Content" when the part has a children prop.
templ generate+go mod tidyingenerated/.- Pipe JSON cases to
go run ./cmd/parity. - Compare results to canonical renderer.
Skipped when: go version fails.
Timeout: 300 seconds (Templ compile + Go build).
- Build cases for PHP-supported parts only (
phpSupported(part).ok). composer installingenerated/if vendor missing.- Pipe JSON to
php cmd/parity-latte/main.phporcmd/parity-twig/main.php. - Compare results to canonical renderer.
Skipped when: PHP unavailable, or Composer unavailable and php/vendor not installed.
Timeout: 120 seconds per suite.
Input (stdin): array of cases
[
{
"template": "button/Button.latte",
"props": { "variant": "default", "size": "sm" },
"attrs": {},
"children": "Content"
}
]Output (stdout): array of HTML strings in the same order.
Go Templ harness uses name instead of template: "button/button/Button".
tests/emitters.test.ts checks properties DOM parity cannot see:
- Templ: boolean attr syntax,
Attrsspread,//go:embed,ButtonClassesexport - React:
forwardRef,Slot,cnimport - Svelte: runes, snippet children
- Vue:
inheritAttrs: false - Latte/Twig:
n:attr/ui8kit_attr_str, parameter blocks
Runs generateFiles(bricks) in-memory — no disk write required.
Cover:
composeRecipe/validateRecipe- Expression evaluators (
cond,mapOr,oneOfOr, …) resolveTag,titleTagvalidateBrickerror casesrenderPartsmoke cases
Workflow: .github/workflows/ci.yml
name: CI
on:
push:
branches: [main]
pull_request:
jobs:
verify:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v2
- uses: actions/setup-go@v5
with:
go-version: "1.25"
- uses: shivammathur/setup-php@v2
with:
php-version: "8.3"
tools: composer
- run: bun install --frozen-lockfile
- run: bun run verify- Definition validation — all 33 bricks, 63 parts
- Engine TypeScript — strict mode, no emit
- Generated TypeScript — full regenerate + typecheck React outputs
- All test suites including:
- Domain units
- Emitter conventions
- React/Svelte/Vue parity (all 63 parts)
- Go Templ parity (all 63 parts)
- Latte parity (60 PHP-supported parts)
- Twig parity (60 PHP-supported parts)
CI installs Go 1.25, PHP 8.3, and Composer so optional local skips do not apply.
| Missing tool | Effect |
|---|---|
| Go | parity.templ.test.ts skipped |
| PHP | Latte/Twig parity skipped |
| Composer (no vendor) | Latte/Twig parity skipped |
React/Svelte/Vue parity always runs — core guarantee.
- Add
bricks/<name>/<name>.data.jsonwith showcase fixtures (optional but recommended). bun run check+bun test— parity cases appear automatically.
No changes to test files required unless the new brick introduces a novel runtime concern.
-
Identify failing label:
{brick.id} {part.name} · {fixture.id}. -
Reproduce canonical output:
import { renderPart } from "./src/domain/render"; // renderPart(brick, "Button", { Variant: "ghost" }, { children: "Content" })
-
Inspect generated file in
generated/ui/<brick>/. -
For PHP: run harness manually:
cd generated echo '[{"template":"button/Button.latte","props":{},"attrs":{},"children":""}]' \ | php cmd/parity-latte/main.php
-
Compare raw HTML before normalization if class order differs cosmetically.