import { expect, test } from "bun:test";
import { mkdtempSync, rmSync, utimesSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import {
compileWireArtifacts,
compileWireArtifactsAsync,
getWrnCompileMetrics,
invalidateModule,
loadModule,
resetWrnCompileMetrics,
setCompileCacheDir,
setDevCompilerPipeline,
} from "../src/pipeline.ts";
test("development compilation awaits plugin AST and code transforms", async () => {
const root = mkdtempSync(join(tmpdir(), "wrnexus-plugin-pipeline-"));
const file = join(root, "page.wrn");
let astTransformed = false;
setCompileCacheDir(join(root, ".wrnexus"));
setDevCompilerPipeline({
async transformAst(ast) {
await Promise.resolve();
astTransformed = true;
return ast;
},
async transformCode(code) {
await Promise.resolve();
return `${code}\nexport const pluginTransformed = true;\n`;
},
virtualModules: new Map(),
});
try {
writeFileSync(file, "page Home { view {
Plugin
} }\n");
const artifact = await compileWireArtifactsAsync(file);
expect(astTransformed).toBeTrue();
expect((await import(artifact.main)).pluginTransformed).toBeTrue();
} finally {
setDevCompilerPipeline(null);
rmSync(root, { recursive: true, force: true });
}
});
test("WRN compilation exposes cache hit, miss, timing, and error metrics", () => {
const root = mkdtempSync(join(tmpdir(), "wrnexus-cache-metrics-"));
const file = join(root, "page.wrn");
setCompileCacheDir(join(root, ".wrnexus"));
resetWrnCompileMetrics();
try {
writeFileSync(file, "page Home { view { Metrics
} }\n");
compileWireArtifacts(file);
compileWireArtifacts(file);
writeFileSync(file, "page Broken { view { } }\n");
expect(() => compileWireArtifacts(file)).toThrow();
expect(getWrnCompileMetrics()).toMatchObject({
hits: 1,
misses: 2,
compilations: 1,
errors: 1,
});
expect(getWrnCompileMetrics().totalDurationMs).toBeGreaterThanOrEqual(0);
} finally {
rmSync(root, { recursive: true, force: true });
}
});
test("invalidateModule loads changed server modules without restarting the process", async () => {
const root = mkdtempSync(join(tmpdir(), "wrnexus-hmr-"));
const file = join(root, "page.ts");
setCompileCacheDir(join(root, ".wrnexus"));
try {
writeFileSync(file, "export const value = 1;\n");
expect((await loadModule(file)).value).toBe(1);
writeFileSync(file, "export const value = 2;\n");
expect((await loadModule(file)).value).toBe(1);
invalidateModule(file);
expect((await loadModule(file)).value).toBe(2);
} finally {
rmSync(root, { recursive: true, force: true });
}
});
test("invalidateModule recompiles changed WRN files in-process", async () => {
const root = mkdtempSync(join(tmpdir(), "wrnexus-hmr-"));
const file = join(root, "page.wrn");
setCompileCacheDir(join(root, ".wrnexus"));
try {
writeFileSync(file, "page Home { view { First
} }\n");
const first = (await loadModule(file)).default as (ctx: unknown) => unknown;
expect(String(first({}))).toContain("First");
writeFileSync(file, "page Home { view { Second
} }\n");
invalidateModule(file);
const second = (await loadModule(file)).default as (ctx: unknown) => unknown;
expect(String(second({}))).toContain("Second");
} finally {
rmSync(root, { recursive: true, force: true });
}
});
test("WRN cache follows content when a replacement has an older mtime", async () => {
const root = mkdtempSync(join(tmpdir(), "wrnexus-cache-"));
const file = join(root, "component.wrn");
setCompileCacheDir(join(root, ".wrnexus"));
try {
writeFileSync(file, "component Example { view {
Old
} }\n");
const first = (await loadModule(file)).render as () => unknown;
expect(String(first())).toContain("Old");
writeFileSync(file, "component Example { view { Current
} }\n");
utimesSync(file, new Date(0), new Date(0));
invalidateModule(file);
const current = (await loadModule(file)).render as () => unknown;
expect(String(current())).toContain("Current");
} finally {
rmSync(root, { recursive: true, force: true });
}
});