FaceTheory Testing Guide
This guide covers the verification commands that back the public contract and the evidence expected before a push or release.
Test Strategy
FaceTheory verification is centered on deterministic runtime behavior in the TypeScript workspace.
Primary goals:
- Validate request normalization, routing, buffered SSR, streaming SSR, SSG, ISR, and framework adapter behavior.
- Keep example commands runnable so docs and implementation do not drift apart.
- Capture enough evidence to distinguish toolchain issues from runtime regressions.
Baseline Verification
Run the standard checks:
cd ts
npm run typecheck
npm test
Equivalent root wrappers after dependencies are installed:
make ts-typecheck
make ts-test
Expected result:
- Type checking completes with no errors.
- The unit suite passes.
Focused Verification Paths
Run these targeted flows when a change touches one delivery mode or adapter more than the rest of the runtime.
SSG
cd ts
npm run example:ssg:build
npm run example:ssg:serve
Use this when changing:
- route planning
- hydration data output
- static file layout
Resource Routes
cd ts
node --import tsx test/unit/resource.test.ts
node --import tsx test/unit/app.test.ts
Use this when changing:
createFaceApp({ resources })FaceResourceRouterouting, route-precedence, or conflict detectionjsonResourceResponse(),textResourceResponse(),emptyResourceResponse(), ormethodNotAllowedResourceResponse()- docs that show raw JSON/text/empty/method-not-allowed responses
Local expected result:
- resource responses return raw
FaceResponsebodies rather than HTML documents - helper-owned headers are lower-case, sorted, deterministic, and default to
cache-control: no-store - JSON helpers apply the same HTML-significant escaping used by FaceTheory document serialization
methodNotAllowedResourceResponse()emits a stable405with a sortedallowheader- exact duplicate and same-precedence ambiguous Face/resource routes fail closed during app construction
OAC Mutating Form Transport
cd ts
npx tsx test/unit/oac-form.test.ts
Use this when changing:
startAwsOacFormTransport()- URL-encoded form field collection or payload hashing
- AppTheorySsrSite OAC mutating-form documentation
- response navigation, CSP, redirect, or unsupported-encoding behavior for marked forms
Local expected result:
- marked same-origin POSTs send
content-type: application/x-www-form-urlencoded;charset=UTF-8 - marked same-origin POSTs send
x-amz-content-sha256for the exact body bytes passed tofetch - unmarked,
GET, anddialogforms keep native behavior - cross-origin actions and marked unsupported encodings fail before sending
- mutating fetches use
redirect: "error" - default HTML document replacement refuses CSP-protected responses unless the host handles the response
Release-candidate validation for an AppTheorySsrSite consumer should use the published GitHub Release tarball, not a workspace link:
- install the FaceTheory RC tarball exactly in the consuming app;
- mark a same-origin URL-encoded form with
data-facetheory-oac-form; - install
startAwsOacFormTransport()from the client bootstrap module; - route the action path through AppTheory/CloudFront to Lambda, usually with
ssrPathPatterns; - submit through the deployed CloudFront URL and confirm the request reaches Lambda without changing the Function URL
auth type away from
AWS_IAM; - confirm marked multipart/text/plain forms fail closed and do not send a request;
- if the response uses CSP headers, confirm the host handles it through
onResponseoronNavigate.
For the original lab driver, theory-mcp-server should validate POST /agents/new through CloudFront OAC before stable
promotion. A successful RC validation means the app-local workaround can be removed while keeping OAC enabled.
Strict CSP Hydration And Navigation
cd ts
npm run example:vite:svelte:strict-csp:build
node --import tsx test/unit/strict-csp-harness.test.ts
node --import tsx test/unit/vite-strict-csp-svelte-example.test.ts
Use this when changing:
FaceCspPolicy,buildStrictCspHeader(), orvalidateStrictCspDocument()viteHydrationForEntry(),externalHydrationForEntry(), or sidecar URL/data handlingcreateFaceApp({ ssrHydrationSidecars })orcreateSsrHydrationSidecarStore(...)@theory-cloud/facetheory/clienthydration loading- adapter strict-CSP enforcement for React, Vue, or Svelte
startFaceNavigation()external hydration loading or same-origin validation- docs that describe strict no-inline CSP, external hydration, or Svelte/Vite strict examples
Local expected result:
- rendered documents contain no
__FACETHEORY_DATA__inline JSON script - every
<script>hassrcand no inline body text - no
<style>tags,styleattributes, oron*event-handler attributes appear in validated scopes - strict Svelte/Vite output uses external CSS/assets and a same-origin module bootstrap
- the browser harness loads external hydration JSON before initial hydration and before
hydrateFaceNavigation(context) - same-origin navigation to the strict example’s
/nextroute preserves deterministic server/client hydration data - framework-owned SSR sidecars emit
/_facetheory/ssr-data/..., return raw no-store JSON from the same FaceApp handler, and do not increment Faceload()/render()counts when fetched - caller-managed
externalHydrationForEntry(...)URLs are preserved and do not trigger framework sidecar writes - SSG strict hydration sidecars use
/_facetheory/data/*build artifacts, while ISR strict hydration sidecars stay paired with the cached HTML through the ISR runtime instead of using the SSR sidecar prefix loadFaceHydrationData()from@theory-cloud/facetheory/clientreads inline hydration first, fetches same-origin external hydration when linked, and rejects unsafe schemes, cross-origin URLs, cross-origin redirects, and non-JSON sidecar responses
For documentation reviews, explicitly check the unsafe-claim boundary: these tests prove local runtime behavior and example wiring, not that a release has been published, a Simulacrum RC has been validated, or an AWS/customer deployment has succeeded.
React SSR And Streaming
cd ts
npm run example:buffered:serve
npm run example:streaming:serve
Use this when changing:
- head rendering
- streaming behavior
- style extraction timing
Operator Visibility SSR Example
cd ts
npm run example:operator-visibility:build
npx tsx test/unit/operator-visibility-example.test.ts
Use this when changing:
- Stitch admin operator visibility primitives
- deterministic guard/authority/confidence/staleness/correlation rendering
- health panels or visibility matrices used by operator dashboards
The example intentionally passes stable age labels, normalized correlation IDs, guard status, health observations, and matrix cells through Face load() data. Do not compute freshness or correlation from Date.now(), browser globals, auth/session state, or network calls during render.
For operator dashboard documentation or integration reviews, also confirm:
- AppTheory/Autheory-derived auth state is passed into FaceTheory as
OperatorGuardStatus; FaceTheory docs and examples do not embed Autheory validation or product-specific authorization logic. - Live auth-varying dashboards use SSR or a deterministic SPA shell. SSG is limited to static snapshots, and ISR examples call out explicit cache/tenant partitioning for every request-varying dimension.
- Empty, loading, unauthorized, and filtered states do not use production-like mock partner, tenant, release, account, or version values.
Vite SSR Adapters
cd ts
npm run example:vite:ssr:build && npm run example:vite:ssr:serve
npm run example:vite:vue:build && npm run example:vite:vue:serve
npm run example:vite:svelte:build && npm run example:vite:svelte:serve
Use this when changing:
- manifest asset injection
- framework adapter parity
- hydration bootstrap behavior
High-Signal Test Areas
These areas provide the fastest signal that a change has altered public behavior rather than only internal implementation details.
Representative unit coverage includes:
- HTTP and app runtime behavior
- Lambda Function URL conversion
- React streaming and style handling
- SSG planning and output layout
- ISR regeneration and cache state handling
- Vue, Svelte, and Vite example coverage
- AWS S3 and TableTheory adapter behavior
Evidence To Capture
Capture enough context that another engineer can reproduce a failure without reverse-engineering your environment from scratch.
For every regression or risky change, capture:
- command run
- pass or fail result
- failing test names or stack traces
- Node.js version in use
- the adapter or mode involved, such as
react,vue,svelte,ssg, orisr
For example-driven verification, also capture:
- URL checked
- expected versus actual headers
- generated output path if the flow writes files
Operator Verification
Production and staging checks belong with the AWS operator docs so they stay aligned with the deployed topology.
Deployed checks for CloudFront, S3, Lambda URL, or ISR state belong in CDK And AWS Notes.