release: WRNexusJS 0.8.0
Quality / quality (ubuntu-latest) (push) Failing after 21s
Quality / quality (windows-latest) (push) Canceled after 0s

This commit is contained in:
2026-08-02 23:18:51 +05:30
parent 87507edf59
commit 586a6db8ff
625 changed files with 243608 additions and 11210 deletions
+67
View File
@@ -0,0 +1,67 @@
import { afterEach, describe, expect, test } from "bun:test";
import { mkdir, readFile, rm, writeFile } from "node:fs/promises";
import { join } from "node:path";
import { tmpdir } from "node:os";
import { createOpenApi, generateApiArtifacts, inspectApi } from "../src/api-command.ts";
const roots: string[] = [];
afterEach(async () =>
Promise.all(roots.splice(0).map((root) => rm(root, { recursive: true, force: true }))),
);
async function fixture() {
const root = join(tmpdir(), `wrnexus-api-${crypto.randomUUID()}`);
roots.push(root);
await mkdir(join(root, "app", "api", "users"), { recursive: true });
await writeFile(
join(root, "app", "api", "users", "[id].ts"),
"export async function GET(){}\nexport const PATCH = () => {};\n",
);
return root;
}
describe("API and SDK generation", () => {
test("derives methods, paths and OpenAPI operations from file routes", async () => {
const operations = inspectApi(await fixture());
expect(operations.map((operation) => `${operation.method} ${operation.path}`)).toEqual([
"GET /api/users/{id}",
"PATCH /api/users/{id}",
]);
expect(createOpenApi(operations).openapi).toBe("3.1.0");
});
test("emits docs, Postman, examples and all requested SDK languages", async () => {
const root = await fixture();
const result = generateApiArtifacts(root, ["typescript", "javascript", "java", "go", "python"]);
expect(result.files).toHaveLength(9);
expect(
JSON.parse(await readFile(join(root, "generated/api/openapi.json"), "utf8")).paths[
"/api/users/{id}"
].get.operationId,
).toBe("getUsersId");
expect(await readFile(join(root, "generated/api/sdk/python/wrnexus-api.py"), "utf8")).toContain(
"class WrnexusApi",
);
});
test("extracts webhook prose and schemas into OpenAPI 3.1 webhooks", async () => {
const root = await fixture();
await mkdir(join(root, "app", "api", "webhooks"), { recursive: true });
await writeFile(
join(root, "app", "api", "webhooks", "payment.ts"),
`
export const webhook = defineWebhook({
event: "payment.completed",
summary: "Payment completed",
description: "Sent after settlement.",
payloadSchema: "#/components/schemas/Payment",
signatureHeader: "x-payment-signature"
});
export const POST = () => new Response("ok");
`,
);
const spec = createOpenApi(inspectApi(root)) as any;
expect(spec.webhooks["payment.completed"].post.description).toBe("Sent after settlement.");
expect(
spec.webhooks["payment.completed"].post.requestBody.content["application/json"].schema.$ref,
).toBe("#/components/schemas/Payment");
expect(spec.webhooks["payment.completed"].post.parameters[0].name).toBe("x-payment-signature");
});
});
+17
View File
@@ -0,0 +1,17 @@
import { expect, test } from "bun:test";
import { mkdtempSync, readFileSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { compatibilityReport, upgradeCompatibility } from "../src/compatibility-command.ts";
test("compatibility upgrade is backed up, current, and idempotent", async () => {
const root = mkdtempSync(join(tmpdir(), "wrnexus-compatibility-"));
const file = join(root, "wrnexus.config.ts");
writeFileSync(file, `export default { port: 3000 };\n`);
const first = upgradeCompatibility(root);
expect(first.changed).toBe(true);
expect(readFileSync(first.backup, "utf8")).toContain("port: 3000");
expect(readFileSync(file, "utf8")).toContain('compatibilityDate: "2026-08-02"');
expect(upgradeCompatibility(root).changed).toBe(false);
expect((await compatibilityReport(root)).needsUpgrade).toBe(false);
});
+59
View File
@@ -0,0 +1,59 @@
import { afterEach, describe, expect, test } from "bun:test";
import { mkdir, rm, writeFile } from "node:fs/promises";
import { join } from "node:path";
import { tmpdir } from "node:os";
import { runContractsCommand } from "../src/contracts-command.ts";
const roots: string[] = [];
afterEach(async () =>
Promise.all(roots.splice(0).map((root) => rm(root, { recursive: true, force: true }))),
);
async function fixture(): Promise<string> {
const root = join(tmpdir(), `wrnexus-contracts-${crypto.randomUUID()}`);
roots.push(root);
await mkdir(root, { recursive: true });
await writeFile(
join(root, "wrnexus.contracts.json"),
JSON.stringify({
format: 1,
contracts: [
{
kind: "queue",
name: "mail",
version: 1,
consumers: ["worker"],
payload: {
type: "object",
fields: { to: { type: "string", rules: [] } },
},
},
],
}),
);
return root;
}
describe("contracts command", () => {
test("snapshots and checks compatible contracts", async () => {
const root = await fixture();
expect((await runContractsCommand(root, "snapshot")).ok).toBe(true);
expect((await runContractsCommand(root, "check")).ok).toBe(true);
});
test("returns a failed result for breaking changes", async () => {
const root = await fixture();
await runContractsCommand(root, "snapshot");
await writeFile(
join(root, "wrnexus.contracts.json"),
JSON.stringify({ format: 1, contracts: [] }),
);
const result = await runContractsCommand(root, "check");
expect(result).toMatchObject({ ok: false, issueCount: 1 });
});
test("requires an explicit baseline", async () => {
const root = await fixture();
await expect(runContractsCommand(root, "check")).rejects.toThrow("WRN-CONTRACT-BASELINE");
});
});
+75
View File
@@ -22,8 +22,10 @@ test("scaffoldApp creates a comprehensive .gitignore", () => {
".wrnexus/",
".env.*",
"!.env.example",
"!.env.*.example",
"*.log",
"*.db",
"uploads/",
"coverage/",
"mobile/android/",
".vscode/",
@@ -47,6 +49,79 @@ test("scaffoldApp includes production build and start scripts", () => {
expect(pkg.scripts.build).toBe("wrnexus build .");
expect(pkg.scripts.start).toBe("bun dist/server.js");
expect(pkg.scripts.production).toBe("bun run build && bun run start");
expect(pkg.scripts.typecheck).toBe("tsc --noEmit");
expect(pkg.scripts.test).toBe("wrnexus test .");
expect(pkg.scripts.check).toBe(
"bun run typecheck && bun run lint && bun run test && bun run format:check",
);
} finally {
rmSync(parent, { recursive: true, force: true });
}
});
test("scaffoldApp includes the complete v0.8 configuration and starter structure", () => {
const parent = mkdtempSync(join(tmpdir(), "wrnexus-create-"));
const root = join(parent, "complete-app");
try {
scaffoldApp(root, "complete-app");
const pkg = JSON.parse(readFileSync(join(root, "package.json"), "utf8"));
const config = readFileSync(join(root, "wrnexus.config.ts"), "utf8");
for (const packageName of [
"@wrnexus/auth",
"@wrnexus/captcha",
"@wrnexus/db",
"@wrnexus/encryption",
"@wrnexus/i18n",
"@wrnexus/image",
"@wrnexus/jwt",
"@wrnexus/observability",
"@wrnexus/realtime",
"@wrnexus/security",
"@wrnexus/store",
"@wrnexus/ui",
"@wrnexus/uploader",
"@wrnexus/validation",
]) {
expect(pkg.dependencies[packageName]).toBe(currentCliVersion());
}
for (const block of [
"plugins:",
"imports:",
"types:",
"stores:",
"compatibility:",
"performance:",
"observability:",
"tenancy:",
"build:",
"navigation:",
"devToolbar:",
"theme:",
"i18n:",
"db:",
"databases:",
"storage:",
"realtime:",
"profiles:",
]) {
expect(config).toContain(block);
}
for (const relative of [
".env.example",
".env.test.example",
"app/locales/en.json",
"app/db/migrations/0001_init.sql",
"app/db/seed.ts",
"app/schemas/contact.ts",
"app/realtime/chat.ts",
"test/smoke.test.ts",
]) {
expect(existsSync(join(root, relative))).toBe(true);
}
} finally {
rmSync(parent, { recursive: true, force: true });
}
+30
View File
@@ -0,0 +1,30 @@
import { describe, expect, test } from "bun:test";
import { mkdtempSync, readFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { DEPLOY_TARGETS, generateDeployment } from "../src/deploy.ts";
describe("deployment presets", () => {
for (const target of DEPLOY_TARGETS) {
test(`generates ${target}`, () => {
const root = mkdtempSync(join(tmpdir(), `wrnexus-${target}-`));
const files = generateDeployment(root, target);
expect(files).toContain(".env.production.example");
expect(readFileSync(join(root, "deploy/README.md"), "utf8")).toContain("/readyz");
expect(generateDeployment(root, target)).toEqual([]);
});
}
test("Kubernetes includes probes, limits and release migration", () => {
const root = mkdtempSync(join(tmpdir(), "wrnexus-k8s-"));
generateDeployment(root, "kubernetes");
const manifest = readFileSync(join(root, "deploy/kubernetes.yaml"), "utf8");
expect(manifest).toContain("readinessProbe");
expect(manifest).toContain("kind: Job");
expect(manifest).toContain("resources:");
});
test("rejects unknown targets", () => {
expect(() => generateDeployment(".", "unknown")).toThrow("WRN-DEPLOY-TARGET");
});
});
+28 -2
View File
@@ -1,8 +1,8 @@
import { expect, test } from "bun:test";
import { mkdirSync, mkdtempSync, writeFileSync } from "node:fs";
import { existsSync, mkdirSync, mkdtempSync, readFileSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { inspectProject } from "../src/doctor.ts";
import { inspectProject, repairProject } from "../src/doctor.ts";
test("doctor reports a healthy minimal project", () => {
const root = mkdtempSync(join(tmpdir(), "wrnexus-doctor-"));
@@ -19,3 +19,29 @@ test("doctor returns actionable missing-project checks", () => {
expect(checks.find((check) => check.name === "package.json")?.ok).toBe(false);
expect(checks.find((check) => check.name === "app/pages")?.detail).toBe("Create app/pages");
});
test("doctor --fix applies safe repairs and is idempotent", () => {
const root = mkdtempSync(join(tmpdir(), "wrnexus-doctor-fix-"));
writeFileSync(
join(root, "package.json"),
JSON.stringify({
name: "app",
dependencies: { "@wrnexus/core": "^0.8.0", "@wrnexus/router": "^0.7.0" },
wrnexus: { version: "0.7.0" },
}),
);
mkdirSync(join(root, "app", "components"), { recursive: true });
writeFileSync(
join(root, "app", "components", "Greeting.wrn"),
'component Greeting { props { name:string="World" } view { <p>{name}</p> } }',
);
const repairs = repairProject(root);
expect(repairs.map(({ name }) => name)).toContain("app/pages");
expect(repairs.map(({ name }) => name)).toContain("configuration");
expect(existsSync(join(root, "wrnexus.config.ts"))).toBe(true);
const manifest = JSON.parse(readFileSync(join(root, "package.json"), "utf8"));
expect(manifest.dependencies["@wrnexus/router"]).toBe("^0.8.0");
expect(manifest.wrnexus.version).toBe("0.8.0");
expect(repairProject(root)).toEqual([]);
});
+74
View File
@@ -0,0 +1,74 @@
import { afterEach, describe, expect, test } from "bun:test";
import { mkdir, rm, writeFile } from "node:fs/promises";
import { join } from "node:path";
import { tmpdir } from "node:os";
import { explainBuildDecision } from "../src/explain.ts";
const roots: string[] = [];
afterEach(async () =>
Promise.all(roots.splice(0).map((root) => rm(root, { recursive: true, force: true }))),
);
async function fixture(): Promise<string> {
const root = join(tmpdir(), `wrnexus-explain-${crypto.randomUUID()}`);
roots.push(root);
await mkdir(join(root, "dist"), { recursive: true });
await writeFile(
join(root, "dist", "build-report.json"),
JSON.stringify({
frameworkVersion: "0.8.0",
adapter: "edge",
measurements: { routeJsBytes: 12 },
budgetViolations: [],
assets: [{ file: "server.js", bytes: 12 }],
routes: [
{
kind: "page",
path: "/users/[id]",
source: "app/pages/users/[id].wrn",
execution: "authenticated-ssr",
canPrerender: false,
needsClientRuntime: true,
needsServerRuntime: true,
hydrationStrategy: "visible",
reasons: ["client interactivity", "authentication required"],
cachePolicy: { strategy: "stale-while-revalidate", ttl: "30s" },
requiredPermission: "users.read",
},
],
}),
);
return root;
}
describe("causal build explanations", () => {
test("explains route execution and hydration from persisted compiler evidence", async () => {
const root = await fixture();
const route = explainBuildDecision(root, "route", "/users/[id]");
expect(route.summary).toContain("authenticated-ssr");
expect(route.reasons).toContain("authentication required");
expect(explainBuildDecision(root, "hydration", "users/[id]").summary).toContain("visible");
});
test("explains build and bundle measurements", async () => {
const root = await fixture();
expect(explainBuildDecision(root, "build").reasons).toContain(
"all configured performance budgets pass",
);
expect(explainBuildDecision(root, "bundle").reasons[0]).toBe("server.js: 12 bytes");
});
test("explains cache and permission decisions", async () => {
const root = await fixture();
expect(explainBuildDecision(root, "cache", "/users/[id]").summary).toContain(
"stale-while-revalidate",
);
expect(explainBuildDecision(root, "permission", "users.read").reasons[0]).toContain(
"security.permission",
);
});
test("uses stable diagnostics for missing evidence", () => {
expect(() => explainBuildDecision("missing", "build")).toThrow("WRN-EXPLAIN-NO-BUILD");
});
});
+35
View File
@@ -0,0 +1,35 @@
import { expect, test } from "bun:test";
import { existsSync, mkdirSync, mkdtempSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { runI18nCommand } from "../src/i18n-command.ts";
test("i18n extract and validate audit native WRN translation keys", () => {
const root = mkdtempSync(join(tmpdir(), "wrnexus-i18n-cli-"));
mkdirSync(join(root, "app/pages"), { recursive: true });
mkdirSync(join(root, "app/locales"), { recursive: true });
writeFileSync(
join(root, "app/pages/index.wrn"),
`page Home { view { <h1>{t:home.title}</h1> } }`,
);
writeFileSync(join(root, "app/locales/en.json"), JSON.stringify({ home: { title: "Home" } }));
writeFileSync(
join(root, "app/locales/mr.json"),
JSON.stringify({ home: { title: "मुख्यपृष्ठ" } }),
);
expect(runI18nCommand(root, "extract")).toBe(true);
expect(existsSync(join(root, ".wrnexus/i18n-keys.json"))).toBe(true);
expect(runI18nCommand(root, "validate")).toBe(true);
});
test("i18n validate fails missing locale keys", () => {
const root = mkdtempSync(join(tmpdir(), "wrnexus-i18n-cli-"));
mkdirSync(join(root, "app/pages"), { recursive: true });
mkdirSync(join(root, "app/locales"), { recursive: true });
writeFileSync(
join(root, "app/pages/index.wrn"),
`page Home { view { <h1>{t:home.title}</h1> } }`,
);
writeFileSync(join(root, "app/locales/en.json"), JSON.stringify({ home: { title: "Home" } }));
writeFileSync(join(root, "app/locales/es.json"), JSON.stringify({}));
expect(runI18nCommand(root, "validate")).toBe(false);
});
+32
View File
@@ -0,0 +1,32 @@
import { afterEach, expect, test } from "bun:test";
import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
import { join } from "node:path";
import { tmpdir } from "node:os";
import { runPluginCliCommand } from "../src/plugin-command.ts";
const roots: string[] = [];
afterEach(() => {
for (const root of roots.splice(0)) rmSync(root, { recursive: true, force: true });
delete (globalThis as Record<string, unknown>).__pluginCommandArgs;
});
test("application plugins can register executable CLI commands", async () => {
const root = mkdtempSync(join(tmpdir(), "wrnexus-plugin-command-"));
roots.push(root);
writeFileSync(
join(root, "wrnexus.config.ts"),
`export default {
plugins: [{
name: "command-test",
cliCommands: [{
name: "greet",
run(args) { globalThis.__pluginCommandArgs = args }
}]
}]
};
`,
);
expect(await runPluginCliCommand(root, "greet", ["Ada"])).toBe(true);
expect((globalThis as Record<string, unknown>).__pluginCommandArgs).toEqual(["Ada"]);
expect(await runPluginCliCommand(root, "missing", [])).toBe(false);
});
+31
View File
@@ -0,0 +1,31 @@
import { afterEach, describe, expect, test } from "bun:test";
import { mkdir, rm, writeFile } from "node:fs/promises";
import { join } from "node:path";
import { tmpdir } from "node:os";
import { productionEntry, runPreview } from "../src/preview.ts";
const roots: string[] = [];
afterEach(async () =>
Promise.all(roots.splice(0).map((root) => rm(root, { recursive: true, force: true }))),
);
describe("production preview", () => {
test("refuses to approximate a missing production build", () => {
expect(() => productionEntry("missing-preview-root")).toThrow("WRN-PREVIEW-NO-BUILD");
});
test("executes the exact dist server with production environment", async () => {
const root = join(tmpdir(), `wrnexus-preview-${crypto.randomUUID()}`);
roots.push(root);
await mkdir(join(root, "dist"), { recursive: true });
await writeFile(
join(root, "dist", "server.js"),
"console.log(process.env.NODE_ENV + ':' + process.env.PORT)",
);
expect(productionEntry(root)).toBe(join(root, "dist", "server.js"));
const child = runPreview(root, { port: 4100, stdio: "pipe" });
const output = await new Response(child.stdout as never).text();
expect(await new Promise<number | null>((resolve) => child.on("exit", resolve))).toBe(0);
expect(output.trim()).toBe("production:4100");
});
});
+42
View File
@@ -0,0 +1,42 @@
import { expect, test } from "bun:test";
import { mkdirSync, mkdtempSync, readFileSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { generateReproductionReport } from "../src/report.ts";
test("report bundles actionable diagnostics while redacting secrets and user/internal data", () => {
const root = mkdtempSync(join(tmpdir(), "wrnexus-report-"));
mkdirSync(join(root, "app/pages"), { recursive: true });
writeFileSync(
join(root, "package.json"),
JSON.stringify({ dependencies: { "@wrnexus/core": "0.8.0" } }),
);
writeFileSync(
join(root, "wrnexus.config.ts"),
`export default { apiKey: "sk_secretsecretsecret", endpoint: "https://internal.police.local/api" }`,
);
writeFileSync(
join(root, "app/pages/index.wrn"),
`page Home { view { <p>officer@example.com</p> } }`,
);
const result = generateReproductionReport(root, {
file: "app/pages/index.wrn",
error: "token=wrn_supersecrettoken at 10.0.0.1",
output: ".wrnexus/report-test",
});
const all = readFileSync(result.reportFile, "utf8") + readFileSync(result.sourceFile!, "utf8");
expect(all).toContain("frameworkVersion");
expect(all).toContain("diagnostics");
expect(all).not.toContain("sk_secretsecretsecret");
expect(all).not.toContain("officer@example.com");
expect(all).not.toContain("internal.police.local");
expect(all).not.toContain("10.0.0.1");
});
test("report rejects traversal inputs and outputs", () => {
const root = mkdtempSync(join(tmpdir(), "wrnexus-report-"));
writeFileSync(join(root, "package.json"), "{}");
expect(() => generateReproductionReport(root, { file: "../secret" })).toThrow("WRN-REPORT-FILE");
expect(() => generateReproductionReport(root, { output: "../outside" })).toThrow(
"WRN-REPORT-OUTPUT",
);
});
@@ -0,0 +1,14 @@
import { expect, test } from "bun:test";
import { mkdirSync, mkdtempSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { validateRuntimeCapabilities } from "../src/build.ts";
test("production targets fail before bundling incompatible application imports", () => {
const root = mkdtempSync(join(tmpdir(), "wrnexus-edge-build-"));
mkdirSync(join(root, "app", "api"), { recursive: true });
writeFileSync(join(root, "app", "api", "files.ts"), `import fs from "node:fs";`);
expect(() => validateRuntimeCapabilities(root, "edge")).toThrow(/WRN-RUNTIME-CAPABILITY/);
expect(() => validateRuntimeCapabilities(root, "worker")).toThrow(/filesystem/);
expect(() => validateRuntimeCapabilities(root, "bun")).not.toThrow();
});
@@ -0,0 +1,50 @@
import { afterEach, describe, expect, test } from "bun:test";
import { mkdir, rm, writeFile } from "node:fs/promises";
import { join } from "node:path";
import { tmpdir } from "node:os";
import { runSecurityCommand, securityAudit, securityHeaders } from "../src/security-command.ts";
const roots: string[] = [];
afterEach(async () =>
Promise.all(roots.splice(0).map((root) => rm(root, { recursive: true, force: true }))),
);
async function fixture(config = "export default {};"): Promise<string> {
const root = join(tmpdir(), `wrnexus-security-${crypto.randomUUID()}`);
roots.push(root);
await mkdir(root, { recursive: true });
await writeFile(join(root, "wrnexus.config.ts"), config);
return root;
}
describe("security command", () => {
test("audits secure framework defaults against mapped ASVS controls", async () => {
const report = await securityAudit(await fixture());
expect(report.passed).toBe(true);
expect(report.version).toBe("ASVS 5.0.0");
expect(report.checks.every((check) => check.asvs.length > 0)).toBe(true);
});
test("reports deliberately disabled headers", async () => {
const report = await securityAudit(
await fixture("export default { security: { headers: false } };"),
);
expect(report.passed).toBe(false);
expect(report.checks.find((check) => check.id === "SEC-HEADERS")?.passed).toBe(false);
});
test("prints the effective production headers", async () => {
const headers = await securityHeaders(await fixture());
expect(headers["content-security-policy"]).toContain("nonce-audit-nonce");
expect(headers["strict-transport-security"]).toContain("max-age=");
expect(headers["x-content-type-options"]).toBe("nosniff");
});
test("rejects credentialed wildcard CORS and unknown commands", async () => {
const root = await fixture(
'export default { security: { cors: { origin: "*", credentials: true } } };',
);
expect((await securityAudit(root)).passed).toBe(false);
await expect(runSecurityCommand(root, "unknown")).rejects.toThrow("WRN-SECURITY-COMMAND");
});
});
+99
View File
@@ -0,0 +1,99 @@
import { describe, expect, test } from "bun:test";
import { mkdtempSync, statSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { X509Certificate } from "node:crypto";
import {
createLocalServicesHandler,
ensureLocalCertificate,
startLocalServices,
} from "../src/services.ts";
describe("local production service simulator", () => {
test("simulates bounded mail, cache, storage, auth and health APIs", async () => {
const handler = createLocalServicesHandler();
expect((await handler(new Request("http://local/healthz"))).status).toBe(200);
expect(
(
await handler(
new Request("http://local/mail", {
method: "POST",
body: JSON.stringify({ to: "u@test", subject: "Welcome" }),
}),
)
).status,
).toBe(202);
expect(await (await handler(new Request("http://local/mail"))).json()).toHaveLength(1);
await handler(
new Request("http://local/cache", {
method: "POST",
body: JSON.stringify({ key: "user", value: 1 }),
}),
);
expect(await (await handler(new Request("http://local/cache"))).json()).toHaveProperty(
"user.value",
1,
);
expect(
(
await handler(
new Request("http://local/storage?key=file.txt", { method: "POST", body: "hello" }),
)
).status,
).toBe(201);
expect(await (await handler(new Request("http://local/storage/file.txt"))).text()).toBe(
"hello",
);
expect(
(
await handler(
new Request("http://local/auth", {
method: "POST",
body: JSON.stringify({ email: "u@test" }),
}),
)
).status,
).toBe(201);
});
test("rejects unsafe storage keys and oversized declared JSON", async () => {
const handler = createLocalServicesHandler();
expect(
(
await handler(
new Request("http://local/storage?key=../secret", { method: "POST", body: "bad" }),
)
).status,
).toBe(400);
const response = await handler(
new Request("http://local/mail", {
method: "POST",
body: JSON.stringify({ value: "x".repeat(300_000) }),
}),
);
expect(response.status).toBe(413);
});
test("generates and safely reuses a localhost HTTPS certificate", async () => {
const root = mkdtempSync(join(tmpdir(), "wrnexus-services-cert-"));
const first = await ensureLocalCertificate(root);
const certificate = new X509Certificate(first.cert);
expect(certificate.subjectAltName).toContain("DNS:localhost");
expect(certificate.subjectAltName).toContain("IP Address:127.0.0.1");
expect(statSync(first.keyFile).size).toBeGreaterThan(100);
const second = await ensureLocalCertificate(root);
expect(second.reused).toBe(true);
expect(second.cert).toBe(first.cert);
});
test("serves the simulator over generated HTTPS", async () => {
const root = mkdtempSync(join(tmpdir(), "wrnexus-services-tls-"));
const server = await startLocalServices({ appRoot: root, port: 0, hostname: "127.0.0.1" });
try {
const response = await fetch(`https://127.0.0.1:${server.port}/healthz`, {
tls: { rejectUnauthorized: false },
});
expect(response.status).toBe(200);
expect(await response.json()).toHaveProperty("service", "wrnexus-local-services");
} finally {
server.stop(true);
}
});
});
+55
View File
@@ -0,0 +1,55 @@
import { afterEach, describe, expect, test } from "bun:test";
import { mkdir, rm, writeFile } from "node:fs/promises";
import { join } from "node:path";
import { tmpdir } from "node:os";
import { createTestPlan } from "../src/test.ts";
const roots: string[] = [];
afterEach(async () =>
Promise.all(roots.splice(0).map((root) => rm(root, { recursive: true, force: true }))),
);
async function fixture(): Promise<string> {
const root = join(tmpdir(), `wrnexus-test-command-${crypto.randomUUID()}`);
roots.push(root);
await mkdir(join(root, "test", "component"), { recursive: true });
await writeFile(join(root, "test", "math.unit.test.ts"), "export {};\n");
await writeFile(join(root, "test", "component", "card.test.ts"), "export {};\n");
await writeFile(join(root, "test", "home.a11y.test.ts"), "export {};\n");
await writeFile(join(root, "package.json"), "{}");
return root;
}
describe("test command planning", () => {
test("discovers the requested Bun test level", async () => {
const root = await fixture();
expect(createTestPlan(root, ["unit"]).files).toHaveLength(1);
expect(createTestPlan(root, ["component"]).files[0]).toContain("card.test.ts");
expect(createTestPlan(root, ["accessibility"]).files[0]).toContain("a11y.test.ts");
});
test("delegates browser and visual suites to Playwright", async () => {
const root = await fixture();
await writeFile(join(root, "playwright.config.ts"), "export default {};\n");
expect(createTestPlan(root, ["browser"]).args).toContain("playwright");
expect(createTestPlan(root, ["visual"]).args).toContain("@visual");
const matrix = createTestPlan(root, [
"browser",
"--browsers=chromium,firefox",
"--shard=2/3",
"--install-browsers",
]);
expect(matrix.args).toContain("firefox");
expect(matrix.args).toContain("--shard=2/3");
expect(matrix.args).toContain("--reporter=line,html");
expect(matrix.setup?.args).toEqual(["x", "playwright", "install", "chromium", "firefox"]);
});
test("deterministically shards convention-based suites", async () => {
const root = await fixture();
await writeFile(join(root, "test", "second.unit.test.ts"), "export {};\n");
expect(createTestPlan(root, ["unit", "--shard=1/2"]).files).toHaveLength(1);
expect(() => createTestPlan(root, ["unit", "--shard=3/2"])).toThrow("WRN-TEST-SHARD");
});
test("keeps the unfiltered legacy command", async () => {
const plan = createTestPlan(await fixture(), ["--watch"]);
expect(plan.level).toBeUndefined();
expect(plan.args).toEqual(["test", "--watch"]);
});
});
+61
View File
@@ -0,0 +1,61 @@
import { afterEach, expect, test } from "bun:test";
import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { checkApplication, generateApplicationTypes } from "../src/types.ts";
import { inspectComponent } from "../src/inspect.ts";
const roots: string[] = [];
afterEach(() => {
for (const root of roots.splice(0)) rmSync(root, { recursive: true, force: true });
});
function fixture(): string {
const root = mkdtempSync(join(tmpdir(), "wrnexus-types-"));
roots.push(root);
for (const dir of ["pages/users", "components", "api", "realtime", "queues", "locales"])
mkdirSync(join(root, "app", dir), { recursive: true });
writeFileSync(join(root, ".env.example"), "PUBLIC_API_URL=https://example.test\n");
writeFileSync(join(root, "app/pages/index.wrn"), "page Home { view { <h1>Home</h1> } }\n");
writeFileSync(
join(root, "app/pages/users/[id].wrn"),
"page User { props { id: string } view { <p>{id}</p> } }\n",
);
writeFileSync(
join(root, "app/components/Button.wrn"),
"component Button { props { label: string } outputs { press(event: MouseEvent) } view { <button>{label}</button> } }\n",
);
writeFileSync(join(root, "app/api/users.ts"), "export default () => new Response('ok');\n");
writeFileSync(join(root, "app/realtime/chat.ts"), "export default {};\n");
writeFileSync(join(root, "app/queues/email.ts"), "export default {};\n");
writeFileSync(join(root, "app/locales/en.json"), JSON.stringify({ common: { save: "Save" } }));
return root;
}
test("generate types emits application-wide deterministic contracts", () => {
const root = fixture();
const result = generateApplicationTypes(root);
const output = readFileSync(join(root, result.file), "utf8");
expect(existsSync(join(root, "app/routes.gen.ts"))).toBe(true);
expect(output).toContain('type RouteName = "index" | "users.id"');
expect(output).toContain('type EnvironmentKey = "PUBLIC_API_URL"');
expect(output).toContain('type TranslationKey = "common.save"');
expect(output).toContain('type QueueName = "email"');
expect(output).toContain('"Button": { props: { "label": string }');
expect(output).toContain("interface ApiContracts");
expect(output).toContain('"/api/users": { default: ApiContract<');
expect(output).toContain("interface RealtimeMessages");
expect(output).toContain('"/realtime/chat": RealtimeMessage<');
expect(output).toContain("interface QueuePayloads");
expect(output).toContain('"email": QueuePayload<');
});
test("application checker validates every wrn source", () => {
expect(checkApplication(fixture()).filter((item) => item.category === "error")).toEqual([]);
}, 15_000);
test("component inspection exposes its typed public contract", () => {
const value = inspectComponent(fixture(), "button") as { name: string; props: unknown[] };
expect(value.name).toBe("Button");
expect(value.props).toEqual([{ name: "label", type: "string", required: true }]);
});
+13 -1
View File
@@ -1,5 +1,5 @@
import { describe, expect, test } from "bun:test";
import { migrateV060WrnSource } from "../src/update.ts";
import { formatCurrentWrnSource, migrateV060WrnSource } from "../src/update.ts";
const report = () => ({
changedAutomatically: [],
@@ -30,4 +30,16 @@ describe("v0.6 source migration", () => {
expect(first).toContain("output.confirm({ ok: true })");
expect(second).toBe(first);
});
test("uses the canonical framework formatter idempotently", () => {
const source = `page Home {
view {
<button type="button" class="one two three four five six seven eight nine ten eleven twelve" @click='save()'>Save</button>
}
}`;
const formatted = formatCurrentWrnSource(source);
expect(formatted).toContain("<button\n");
expect(formatCurrentWrnSource(formatted)).toBe(formatted);
});
});
+53
View File
@@ -286,3 +286,56 @@ test("0.4 migration removes manual CAPTCHA runtime wiring and archives copied as
rmSync(root, { recursive: true, force: true });
}
});
test("0.8 migration modernizes every WRN source with imports and a review report", () => {
const root = mkdtempSync(join(tmpdir(), "wrnexus-update-current-source-"));
mkdirSync(join(root, "app", "components"), { recursive: true });
mkdirSync(join(root, "app", "layouts"), { recursive: true });
mkdirSync(join(root, "app", "pages"), { recursive: true });
writeFileSync(
join(root, "package.json"),
JSON.stringify({
name: "source-app",
dependencies: { "@wrnexus/core": "^0.7.0" },
wrnexus: { version: "0.7.0" },
}),
);
writeFileSync(
join(root, "app", "components", "Notice.wrn"),
'component Notice {\r\n props { label = "Ready" count = 1 } \r\n view { <p>{label}</p> }\r\n}',
);
writeFileSync(
join(root, "app", "layouts", "shell.wrn"),
"layout Shell {\n view { <main><slot /></main> }\n}\n",
);
writeFileSync(
join(root, "app", "pages", "index.wrn"),
'page Home {\n layout = "shell"\n view { <Notice label={"Updated"} /> <Missing /> }\n}\n',
);
try {
updateApp(root, "0.8.0", false);
const first = readFileSync(join(root, "app", "pages", "index.wrn"), "utf8");
expect(first).toContain('import Notice from "@/components/Notice.wrn"');
expect(first).toContain('import Shell from "@/layouts/shell.wrn"');
expect(first).toContain("layout = Shell");
expect(first).toContain("label='{\"Updated\"}'");
expect(first.endsWith("\n")).toBe(true);
const component = readFileSync(join(root, "app", "components", "Notice.wrn"), "utf8");
expect(component).toContain('props {\n label = "Ready"\n count = 1\n }');
expect(component).not.toContain("\r");
const reportPath = join(root, ".wrnexus", "migrations", "0.8.0-source-modernization.json");
const report = JSON.parse(readFileSync(reportPath, "utf8"));
expect(report.changedFiles).toContain("app/pages/index.wrn");
expect(report.unresolvedImports).toContain(
"app/pages/index.wrn: component 'Missing' could not be resolved",
);
updateApp(root, "0.8.0", false);
expect(readFileSync(join(root, "app", "pages", "index.wrn"), "utf8")).toBe(first);
} finally {
rmSync(root, { recursive: true, force: true });
}
});
+6
View File
@@ -47,8 +47,14 @@ test("workspace templates pin the running framework release", () => {
expect(files["README.md"]).toContain("http://127.0.0.1:3000");
expect(files["README.md"]).toContain("internal gateway targets");
expect(JSON.parse(files["package.json"]!).scripts.production).toBe("wrnexus production");
expect(JSON.parse(files["package.json"]!).scripts.check).toContain("typecheck");
expect(JSON.parse(files["package.json"]!).scripts.check).toContain("format:check");
expect(files["wrnexus.workspace.ts"]).toContain('runtime: "development"');
expect(files["wrnexus.workspace.ts"]).toContain("hmr: false");
expect(files[".env.example"]).toContain("REDIS_URL");
expect(files["eslint.config.js"]).toContain("typescript-eslint");
expect(files["tsconfig.json"]).toContain('"strict": true');
expect(files[".vscode/extensions.json"]).toContain("wrnexus.wrnexus");
});
test("production workspace detects default and named SQL migrations", () => {