Documentation menu

Testing API

Import the public testing surface from goldar/testing. These helpers exercise the same application assembly and request lifecycle used by the server; they do not replace a real browser or deployed integration test.

Request targets

route(application, path) creates an immutable RouteTarget at https://goldar.test for a relative path, or preserves an absolute URL. Its API is:

  • application: the ApplicationSource used to assemble each request;
  • path: pathname plus query string;
  • url: a defensive URL copy;
  • using(...arrangements): returns a new target with resource and store arrangements;
  • request(init?, bindings?): assembles the app, issues a request, and returns its Response.

Every attached arrangement must match exactly one request-owned instance and be used by the request. Duplicate arrangements for the same constructor, unused arrangements, or ambiguous subclass matches fail the test instead of silently falling back.

const response = await route(ApplicationType, "/users/42?mode=full")
	.using(mockResource(UserData).resolve(user))
	.request({ headers: { Accept: "application/json" } });

Resource arrangements

mockResource(DataType) returns a typed ResourceMock factory:

  • .resolve(value) replaces matching loads with a value;
  • .reject(error) replaces matching loads with a rejected promise;
  • .load(loader) receives the real DataContext and may return a value or promise;
  • .deferred() returns a DeferredResource whose .resolve(value) or .reject(error) controls the pending load. A deferred arrangement can settle only once.

Every resource arrangement exposes its matched type, the "resource" discriminator, and a loadCount. ResourceArrangement, DeferredResource, ResourceMock, and TestArrangement are exported for typed test helpers.

Store arrangements

stageUI(StoreType, stage) creates a UIArrangement. The callback receives each matching request-owned store after route construction and before owned data loads. Use it to establish UI state while preserving the real route and data lifecycle.

const target = route(ApplicationType, "/account").using(
	stageUI(SessionStore, (store) => store.signIn("user-42")),
);

Rendering

renderScreen(target) requests a RouteTarget, requires a successful text/html response, and parses the body into a private Happy DOM window. A legacy StaticRouteConstructor may be passed directly when its path contains no dynamic : or * segments.

The returned Screen exposes:

  • document and window for DOM assertions;
  • root, the document body;
  • response, an unread clone of the server response;
  • url, the requested URL;
  • dispose(), an idempotent asynchronous cleanup method.

Always dispose a screen in finally. Happy DOM does not prove layout, accessibility-tree output, browser JavaScript, navigation, animation, or cross-browser behavior.

Accessibility baseline

collectAccessibilityViolations(document) returns frozen AccessibilityViolation objects without throwing. assertAccessibleDocument(document) throws one Node AssertionError containing all violations.

AccessibilityViolationCode currently includes accessible names, ARIA references, document language/title, duplicate IDs, heading order, image alt text, the main landmark, and the page heading. Each violation contains a code, human-readable message, and compact target.

This baseline is deterministic markup validation. It does not evaluate contrast, focus visibility or order, keyboard behavior, live regions, Shadow DOM, layout, or assistive-technology output.