Files
WRNexusJS/.publish/test
2026-07-18 13:12:16 +05:30
..
2026-07-18 13:12:16 +05:30
2026-07-12 15:55:18 +05:30

@wrnexus/test

Testing utilities for WrNexus apps — component rendering, reactive-DOM mounting, route handler calls, and a full in-process app harness, plus a one-import re-export of bun:test.

Part of the WrNexus framework — an SSR-first, Bun-native full-stack web framework.

Overview

@wrnexus/test is the server-side test toolkit you reach for when writing tests for a WrNexus app. It runs under bun test (invoked via wrnexus test) and gives you a single import surface: the bun:test primitives (test, expect, mock, …) re-exported alongside WrNexus-aware helpers that compile .wrn components, hydrate server HTML in a DOM, invoke API route handlers, and boot the real app on an ephemeral port for integration tests.

Installation

bun add @wrnexus/test

Private package — the machine must be authenticated to the wrnexus npm org (a read token in ~/.npmrc). Requires Bun (Node is not supported).

API

Re-exported test primitives

For one-import DX, the following are re-exported straight from bun:test:

test, expect, describe, it, beforeEach, afterEach, beforeAll, afterAll, mock, spyOn.

createContext is also re-exported from @wrnexus/core.

renderComponent(source, props?)

function renderComponent(source: string, props?: Record<string, unknown>): Promise<string>;

Compiles a .wrn component source string (via @wrnexus/compiler) and renders it to an HTML string with the given props. Throws if the compiled module has no render export.

mountHtml(html)

function mountHtml(html: string): {
  document: Document;
  window: unknown;
  querySelector: (sel: string) => Element | null;
  querySelectorAll: (sel: string) => Element[];
};

Mounts server-rendered html in a happy-dom window with the reactive runtime hydrated, so you can test data-scope / data-text / data-for / data-show behaviour. Returns the window plus document and query helpers; assert on those.

happy-dom is loaded lazily (via require), so importing this package never requires it unless you actually call mountHtml.

callRoute(handler, request)

function callRoute(
  handler: (ctx: Context) => Response | Promise<Response>,
  request: Request,
): Promise<Response>;

Calls an API route handler with a Context built from a Request (using createContext). Returns the handler's Response.

createHarness(projectRoot, options?)

function createHarness(projectRoot: string, options?: HarnessOptions): Promise<Harness>;

interface HarnessOptions {
  /** Config/env profile. Default "test". */
  profile?: string;
}

interface Harness {
  /** Base URL of the ephemeral test server. */
  url: string;
  /** Fetch a path on the app (relative to `url`). */
  fetch(path: string, init?: RequestInit): Promise<Response>;
  /** The scanned router (pages/api/realtime/components). */
  router: unknown;
  /** Stop the server. */
  close(): void;
}

Boots the app at projectRoot on an ephemeral port (port: 0) for integration tests covering pages, API routes, middleware, and the full request pipeline. Loads env and app config for the given profile (default "test") so it picks up your test database/env. The server runs in development mode with HMR disabled. Remember to await app.close() when done.

Usage

import { test, expect, renderComponent, mountHtml, createHarness } from "@wrnexus/test";

test("counter renders its label", async () => {
  const html = await renderComponent(SRC, { start: 3, label: "Hits" });
  expect(html).toContain("Hits");
});

test("reactive scope hydrates", () => {
  const { querySelector } = mountHtml(serverHtml);
  expect(querySelector("[data-text]")?.textContent).toBe("3");
});

test("home page responds", async () => {
  const app = await createHarness("examples/basic-app");
  const res = await app.fetch("/");
  expect(res.status).toBe(200);
  await app.close();
});

Calling an API route handler directly:

import { test, expect, callRoute } from "@wrnexus/test";
import { GET } from "../app/api/health.ts";

test("health endpoint", async () => {
  const res = await callRoute(GET, new Request("http://test/api/health"));
  expect(res.status).toBe(200);
});

Requirements / Notes

  • Bun-only. Runs under bun test (via wrnexus test); uses Bun's module loading and the bun:test runtime.
  • mountHtml requires happy-dom to be available in the workspace (loaded lazily; it's a dev dependency, not a runtime dependency of this package).
  • Works with the rest of the WrNexus toolchain: @wrnexus/compiler (compiles .wrn sources), @wrnexus/core (Context / createContext), @wrnexus/csr (reactive runtime for mountHtml), @wrnexus/dev-server (startServer behind createHarness), and @wrnexus/styles (config/env/profile loading for the harness).