Files
WRNexusJS/packages/cli/test/mobile.test.ts
2026-07-12 15:55:18 +05:30

101 lines
4.6 KiB
TypeScript

import { expect, test } from "bun:test";
import { existsSync, mkdirSync, mkdtempSync, readFileSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { generateMobile, mobileOptions } from "../src/mobile.ts";
import { runMobileCommand } from "../src/mobile-command.ts";
import { nativeCatalog, runNativeCommand } from "../src/native-command.ts";
test("generateMobile scaffolds a configurable Capacitor project", async () => {
const dir = mkdtempSync(join(tmpdir(), "wire-mobile-"));
writeFileSync(join(dir, "package.json"), JSON.stringify({ name: "@acme/store-front" }));
await generateMobile(dir, {
appId: "com.acme.store",
appName: "Acme Store",
serverUrl: "https://store.example.com",
});
const config = readFileSync(join(dir, "mobile", "capacitor.config.ts"), "utf8");
expect(config).toContain('appId: mobile.appId ?? "com.acme.store"');
expect(config).toContain('appName: mobile.appName ?? "Acme Store"');
expect(config).toContain("...(mobile.capacitor ?? {})");
expect(config).not.toContain("errorPath:");
expect(config).toContain('"https://store.example.com"');
expect(existsSync(join(dir, "mobile", "web", "index.html"))).toBe(true);
const pkg = JSON.parse(readFileSync(join(dir, "mobile", "package.json"), "utf8"));
expect(pkg.dependencies["@capacitor/android"]).toBe("^8.0.0");
expect(pkg.scripts["open:ios"]).toBe("cap open ios");
});
test("generateMobile derives defaults and does not overwrite files", async () => {
const dir = mkdtempSync(join(tmpdir(), "wire-mobile-"));
writeFileSync(join(dir, "package.json"), JSON.stringify({ name: "demo-app" }));
await generateMobile(dir);
const path = join(dir, "mobile", "capacitor.config.ts");
const before = readFileSync(path, "utf8");
expect(before).toContain('appId: mobile.appId ?? "com.example.demoapp"');
expect(before).toContain('"http://localhost:3000"');
await generateMobile(dir, { appName: "Changed" });
expect(readFileSync(path, "utf8")).toBe(before);
});
test("mobileOptions parses generator flags", () => {
expect(
mobileOptions(["--app-id=com.acme.app", "--app-name=Acme", "--url=https://app.test"]),
).toEqual({
appId: "com.acme.app",
appName: "Acme",
serverUrl: "https://app.test",
mode: undefined,
});
});
test("generateMobile scaffolds a WebView-free native project from config", async () => {
const dir = mkdtempSync(join(tmpdir(), "wire-native-"));
writeFileSync(join(dir, "package.json"), JSON.stringify({ name: "native-demo" }));
writeFileSync(
join(dir, "wrnexus.config.mjs"),
`export default { mobile: { mode: "native", appId: "com.acme.native", apiUrl: "https://api.example.com" } }`,
);
await generateMobile(dir);
const pkg = JSON.parse(readFileSync(join(dir, "mobile", "package.json"), "utf8"));
expect(pkg.wrnexus.mode).toBe("native");
expect(pkg.dependencies.expo).toBeDefined();
expect(existsSync(join(dir, "mobile", "app", "index.tsx"))).toBe(true);
expect(readFileSync(join(dir, "mobile", "src", "wrnexus.ts"), "utf8")).toContain(
"https://api.example.com",
);
expect(existsSync(join(dir, "mobile", "capacitor.config.ts"))).toBe(false);
});
test("mobile compile turns wrn pages into Expo routes", async () => {
const dir = mkdtempSync(join(tmpdir(), "wire-native-compile-"));
writeFileSync(join(dir, "package.json"), JSON.stringify({ name: "native-compile" }));
writeFileSync(join(dir, "wrnexus.config.mjs"), `export default { mobile: { mode: "native" } }`);
await generateMobile(dir);
const pages = join(dir, "app", "pages");
const nested = join(pages, "account");
mkdirSync(nested, { recursive: true });
writeFileSync(
join(nested, "profile.wrn"),
"page Profile { view { <main><h1>Profile</h1></main> } }",
);
await runMobileCommand(dir, "compile");
const output = readFileSync(join(dir, "mobile", "app", "account", "profile.tsx"), "utf8");
expect(output).toContain("function Profile()");
expect(output).toContain("<View><Text>Profile</Text></View>");
});
test("native catalog uses built-in React Native sharing without installing expo-sharing", async () => {
expect(nativeCatalog.share?.expo).toBeUndefined();
const dir = mkdtempSync(join(tmpdir(), "wire-native-share-"));
writeFileSync(join(dir, "package.json"), JSON.stringify({ name: "native-share" }));
writeFileSync(join(dir, "wrnexus.config.mjs"), `export default { mobile: { mode: "native" } }`);
await generateMobile(dir);
await runNativeCommand(dir, "add", ["share"]);
const pkg = JSON.parse(readFileSync(join(dir, "mobile", "package.json"), "utf8"));
expect(pkg.dependencies["expo-sharing"]).toBeUndefined();
});