Files
WRNexusJS/packages/cli/test/create.test.ts
Clintchiz 2c960fc1dc
Quality / quality (ubuntu-latest) (push) Failing after 9m49s
Quality / quality (windows-latest) (push) Canceled after 0s
refactor: migrate legacy wire namespace to wrn
2026-08-12 18:51:15 +05:30

209 lines
6.7 KiB
TypeScript

import { expect, test } from "bun:test";
import { existsSync, mkdtempSync, readFileSync, rmSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { format } from "prettier";
import { scaffoldApp, scaffoldFrameworkRange } from "../src/create.ts";
import { currentCliVersion } from "../src/update-notifier.ts";
test("scaffoldApp creates a comprehensive .gitignore", () => {
const parent = mkdtempSync(join(tmpdir(), "wrnexus-create-"));
const root = join(parent, "demo-app");
try {
scaffoldApp(root, "demo-app");
const file = join(root, ".gitignore");
expect(existsSync(file)).toBe(true);
const contents = readFileSync(file, "utf8");
for (const entry of [
"node_modules/",
"dist/",
".wrnexus/",
".env.*",
"!.env.example",
"!.env.*.example",
"*.log",
"*.db",
"uploads/",
"coverage/",
"mobile/android/",
".vscode/",
"*.tsbuildinfo",
]) {
expect(contents).toContain(entry);
}
} finally {
rmSync(parent, { recursive: true, force: true });
}
});
test("scaffoldApp includes production build and start scripts", () => {
const parent = mkdtempSync(join(tmpdir(), "wrnexus-create-"));
const root = join(parent, "production-app");
try {
scaffoldApp(root, "production-app");
const pkg = JSON.parse(readFileSync(join(root, "package.json"), "utf8"));
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");
const documentLayout = readFileSync(join(root, "app/layouts/document.wrn"), "utf8");
expect(documentLayout).toContain('runtime = "server"');
expect(documentLayout).not.toContain("cookies =");
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(scaffoldFrameworkRange);
}
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 });
}
});
test("scaffoldApp uses compatible framework packages and pins the current CLI", () => {
const parent = mkdtempSync(join(tmpdir(), "wrnexus-create-"));
const root = join(parent, "current-app");
try {
scaffoldApp(root, "current-app");
const pkg = JSON.parse(readFileSync(join(root, "package.json"), "utf8"));
const version = currentCliVersion();
expect(pkg.wrnexus.version).toBe(version);
expect(pkg.dependencies["@wrnexus/helpers"]).toBe(scaffoldFrameworkRange);
for (const dependency of Object.values(pkg.dependencies) as string[]) {
expect(dependency).toBe(scaffoldFrameworkRange);
}
expect(pkg.devDependencies["@wrnexus/cli"]).toBe(version);
expect(pkg.devDependencies["@iconify/tailwind4"]).toBe("^1.2.3");
expect(pkg.devDependencies["@iconify-json/lucide"]).toBe("^1.2.118");
const globalCss = readFileSync(join(root, "app", "styles", "global.css"), "utf8");
expect(globalCss).toContain('@plugin "@iconify/tailwind4";');
expect(globalCss).toContain('"Plus Jakarta Sans"');
expect(globalCss).toContain("--wrn-font-sans");
const appConfig = readFileSync(join(root, "wrnexus.config.ts"), "utf8");
expect(appConfig).toContain('family: "Plus Jakarta Sans"');
expect(appConfig).toContain("weights: [400, 500, 600, 700]");
expect(existsSync(join(root, "public", "llms.txt"))).toBe(true);
expect(existsSync(join(root, "llms.txt"))).toBe(false);
expect(readFileSync(join(root, ".prettierignore"), "utf8")).toContain("CLAUDE.md");
expect(readFileSync(join(root, ".vscode", "settings.json"), "utf8")).toContain(
'"editor.formatOnSave": true',
);
expect(readFileSync(join(root, ".vscode", "settings.json"), "utf8")).toContain(
'"editor.defaultFormatter": "wrnexus.wrnexus"',
);
expect(readFileSync(join(root, ".vscode", "extensions.json"), "utf8")).toContain(
"wrnexus.wrnexus",
);
expect(readFileSync(join(root, "app", "pages", "index.wrn"), "utf8")).toContain(
'href="/api/hello"',
);
expect(existsSync(join(root, "app", "pages", "about.wrn"))).toBe(true);
} finally {
rmSync(parent, { recursive: true, force: true });
}
});
test("scaffoldApp emits Prettier-compliant editor and framework files", async () => {
const parent = mkdtempSync(join(tmpdir(), "wrnexus-create-"));
const root = join(parent, "formatted-app");
try {
scaffoldApp(root, "formatted-app");
for (const relative of [
"app/styles/global.css",
"eslint.config.js",
".vscode/settings.json",
".vscode/extensions.json",
]) {
const file = join(root, relative);
const source = readFileSync(file, "utf8");
const formatted = await format(source, {
filepath: file,
printWidth: 100,
tabWidth: 2,
useTabs: false,
semi: true,
singleQuote: false,
trailingComma: "all",
endOfLine: "lf",
});
expect(formatted).toBe(source);
}
} finally {
rmSync(parent, { recursive: true, force: true });
}
});