release: WRNexusJS 0.5.0
This commit is contained in:
@@ -8,3 +8,11 @@ test("HMR client syncs fresh HTML over the websocket", () => {
|
||||
expect(HMR_CLIENT_JS).not.toContain("fetch(location.href");
|
||||
expect(HMR_CLIENT_JS).not.toContain("location.reload()");
|
||||
});
|
||||
|
||||
test("HMR replaces hydrated components when their server signature changes", () => {
|
||||
expect(HMR_CLIENT_JS).toContain('from.getAttribute("data-wrn-hydration")');
|
||||
expect(HMR_CLIENT_JS).toContain('from.getAttribute("data-wrn-behavior")');
|
||||
expect(HMR_CLIENT_JS).toContain('from.getAttribute("data-scope")');
|
||||
expect(HMR_CLIENT_JS).toContain("window.__wrnexusDisposeBehaviors(from)");
|
||||
expect(HMR_CLIENT_JS).toContain("from.replaceWith(to.cloneNode(true))");
|
||||
});
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
import { afterAll, expect, test } from "bun:test";
|
||||
import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
|
||||
import { get } from "node:http";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
import { definePlugin } from "@wrnexus/plugin";
|
||||
import { startServer } from "../src/index.ts";
|
||||
|
||||
const root = mkdtempSync(join(tmpdir(), "wrnexus-plugin-config-"));
|
||||
const appDir = join(root, "app");
|
||||
const routeFile = join(root, "config-probe.ts");
|
||||
const runtimeKey = `@wrnexus/dev-server:test:plugin-config:${crypto.randomUUID()}`;
|
||||
|
||||
mkdirSync(appDir, { recursive: true });
|
||||
writeFileSync(join(root, "package.json"), JSON.stringify({ name: "plugin-config-lifecycle-test" }));
|
||||
writeFileSync(
|
||||
routeFile,
|
||||
`
|
||||
export function GET() {
|
||||
return Response.json({
|
||||
value: globalThis[Symbol.for(${JSON.stringify(runtimeKey)})],
|
||||
});
|
||||
}
|
||||
`,
|
||||
);
|
||||
|
||||
afterAll(() => {
|
||||
delete (globalThis as Record<PropertyKey, unknown>)[Symbol.for(runtimeKey)];
|
||||
rmSync(root, { recursive: true, force: true });
|
||||
});
|
||||
|
||||
function getJson(url: string): Promise<{ status: number | undefined; body: unknown }> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const request = get(url, (response) => {
|
||||
const chunks: Buffer[] = [];
|
||||
response.on("data", (chunk) => chunks.push(Buffer.from(chunk)));
|
||||
response.on("end", () => {
|
||||
try {
|
||||
resolve({
|
||||
status: response.statusCode,
|
||||
body: JSON.parse(Buffer.concat(chunks).toString("utf8")),
|
||||
});
|
||||
} catch (error) {
|
||||
reject(error);
|
||||
}
|
||||
});
|
||||
});
|
||||
request.on("error", reject);
|
||||
});
|
||||
}
|
||||
|
||||
test("startServer configures plugins once with the complete application config", async () => {
|
||||
let configureCalls = 0;
|
||||
const plugin = definePlugin({
|
||||
name: "plugin-config-lifecycle-test",
|
||||
configure(config) {
|
||||
configureCalls += 1;
|
||||
(globalThis as Record<PropertyKey, unknown>)[Symbol.for(runtimeKey)] =
|
||||
config.lifecycleSentinel;
|
||||
},
|
||||
routeEntries: [{ kind: "api", path: "/api/config-probe", entry: routeFile }],
|
||||
});
|
||||
|
||||
const server = await startServer({
|
||||
appDir,
|
||||
appConfig: { lifecycleSentinel: "configured" },
|
||||
plugins: plugin,
|
||||
hostname: "127.0.0.1",
|
||||
port: 0,
|
||||
mode: "development",
|
||||
hmr: false,
|
||||
});
|
||||
|
||||
try {
|
||||
const response = await getJson(`${server.url}/api/config-probe`);
|
||||
expect(response.status).toBe(200);
|
||||
expect(response.body).toEqual({ value: "configured" });
|
||||
expect(configureCalls).toBe(1);
|
||||
} finally {
|
||||
server.stop();
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,23 @@
|
||||
import { expect, test } from "bun:test";
|
||||
import { createDevAssetServer } from "../src/assets.ts";
|
||||
|
||||
test("UI CSS is read from its live source after an HMR change", async () => {
|
||||
let css = ".wire-card { color: red; }";
|
||||
const assets = createDevAssetServer(
|
||||
process.cwd(),
|
||||
"development",
|
||||
undefined,
|
||||
undefined,
|
||||
() => css,
|
||||
);
|
||||
|
||||
const first = await assets.serve("/__wrnexus/ui.css");
|
||||
expect(await first?.text()).toContain("color: red");
|
||||
|
||||
css = ".wire-card { color: blue; }";
|
||||
assets.invalidateCss();
|
||||
|
||||
const second = await assets.serve("/__wrnexus/ui.css");
|
||||
expect(await second?.text()).toContain("color: blue");
|
||||
expect(second?.headers.get("cache-control")).toBe("no-cache");
|
||||
});
|
||||
Reference in New Issue
Block a user