perf(csr): load component controllers on demand
This commit is contained in:
@@ -1,11 +1,11 @@
|
||||
import { test, expect, beforeEach } from "bun:test";
|
||||
import { Window } from "happy-dom";
|
||||
import { REACTIVE_RUNTIME } from "../src/reactive-runtime.ts";
|
||||
import { getReactiveRuntime } from "../src/index.ts";
|
||||
import { getComponentControllerRuntime, getReactiveRuntime } from "../src/index.ts";
|
||||
import { mountHtml } from "@wrnexus/test";
|
||||
|
||||
// Fresh DOM per test, with the runtime's globals bound.
|
||||
function mount(html: string): Window {
|
||||
function mount(html: string, runtime = REACTIVE_RUNTIME, controllers = ""): Window {
|
||||
const win = new Window() as unknown as Window & Record<string, unknown>;
|
||||
win.document.body.innerHTML = `<div id="app">${html}</div>`;
|
||||
(globalThis as Record<string, unknown>).window = win;
|
||||
@@ -25,7 +25,8 @@ function mount(html: string): Window {
|
||||
(globalThis as Record<string, unknown>).CustomEvent = (
|
||||
win as unknown as { CustomEvent: unknown }
|
||||
).CustomEvent;
|
||||
(0, eval)(REACTIVE_RUNTIME);
|
||||
(0, eval)(runtime);
|
||||
if (controllers) (0, eval)(controllers);
|
||||
// Hydrate deterministically (auto-init waits on DOMContentLoaded, which the
|
||||
// test window may not fire). setupScope is idempotent, so this is safe.
|
||||
const w = win as unknown as { __wrnexusHydrateScopes?: (root: unknown) => void };
|
||||
@@ -41,6 +42,28 @@ beforeEach(() => {
|
||||
delete (globalThis as Record<string, unknown>).MutationObserver;
|
||||
});
|
||||
|
||||
test("split runtime hydrates a controller only from the controller asset", () => {
|
||||
const core = getReactiveRuntime(true);
|
||||
const controllers = getComponentControllerRuntime(true);
|
||||
expect(core).not.toContain("function setupRovingFocus");
|
||||
expect(controllers).toContain("function setupRovingFocus");
|
||||
|
||||
const win = mount(
|
||||
`<div data-wrn-roving="horizontal"><button data-wrn-roving-item>One</button><button data-wrn-roving-item>Two</button></div>`,
|
||||
core,
|
||||
controllers,
|
||||
);
|
||||
const buttons = win.document.querySelectorAll("button");
|
||||
(buttons[0] as unknown as HTMLButtonElement).focus();
|
||||
buttons[0]!.dispatchEvent(new win.KeyboardEvent("keydown", { key: "ArrowRight", bubbles: true }));
|
||||
expect(win.document.activeElement).toBe(buttons[1]);
|
||||
});
|
||||
|
||||
test("a page without controller markers does not request the controller asset", () => {
|
||||
const win = mount(`<main data-scope="count: 1"><span>{count}</span></main>`, getReactiveRuntime(true));
|
||||
expect(win.document.querySelector('script[src$="controllers.js"]')).toBeNull();
|
||||
});
|
||||
|
||||
test("hydrates {expr} mustaches from data-scope", () => {
|
||||
const win = mount(`<div data-scope="count: 0"><span>{count}, {count * 2}</span></div>`);
|
||||
expect(win.document.querySelector("span")!.textContent).toBe("0, 0");
|
||||
|
||||
Reference in New Issue
Block a user