Files
WRNexusJS/packages/cli/test/create.test.ts
T
2026-07-30 13:36:29 +05:30

130 lines
4.5 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 } 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",
"*.log",
"*.db",
"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");
} finally {
rmSync(parent, { recursive: true, force: true });
}
});
test("scaffoldApp pins the current framework and exposes llms.txt publicly", () => {
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(version);
for (const dependency of Object.values(pkg.dependencies) as string[]) {
expect(dependency).toBe(version);
}
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("--wire-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 });
}
});