1import { execFile } from "node:child_process";2import { promisify } from "node:util";3import { describe, expect, it } from "vitest";45const execFileAsync = promisify(execFile);6const scriptPath = "scripts/install-native-sync-host.mjs";78async function showDir(args: string[]): Promise<{ dir: string; registryHint: string | null }> {9 const { stdout } = await execFileAsync(process.execPath, [10 scriptPath,11 "--show-dir",12 "--browser",13 args[0]!,14 "--platform-override",15 args[1]!,16 "--home-override",17 args[2]!,18 ]);19 return JSON.parse(stdout) as { dir: string; registryHint: string | null };20}2122describe("native sync installer path resolution", () => {23 const home = "/home/test";2425 it("resolves macOS Chrome under Application Support/Google/Chrome", async () => {26 const { dir } = await showDir(["chrome", "darwin", home]);27 expect(dir).toBe("/home/test/Library/Application Support/Google/Chrome/NativeMessagingHosts");28 });2930 it("resolves macOS Firefox under Application Support/Mozilla", async () => {31 const { dir } = await showDir(["firefox", "darwin", home]);32 expect(dir).toBe("/home/test/Library/Application Support/Mozilla/NativeMessagingHosts");33 });3435 it("resolves Linux Chrome under .config/google-chrome", async () => {36 const { dir } = await showDir(["chrome", "linux", home]);37 expect(dir).toBe("/home/test/.config/google-chrome/NativeMessagingHosts");38 });3940 it("resolves Linux Firefox under .mozilla/native-messaging-hosts", async () => {41 const { dir } = await showDir(["firefox", "linux", home]);42 expect(dir).toBe("/home/test/.mozilla/native-messaging-hosts");43 });4445 it("resolves Windows with a registry hint", async () => {46 const { dir, registryHint } = await showDir(["chrome", "win32", "C:\\Users\\test"]);47 expect(dir).toContain("Peach");48 expect(registryHint).toContain("HKEY_CURRENT_USER");49 expect(registryHint).toContain("com.peachpasswords.sync");50 });5152 it("rejects unsupported platforms", async () => {53 await expect(showDir(["chrome", "freebsd", home])).rejects.toThrow("unsupported platform");54 });55});5657describe("native sync installer script", () => {58 it("--dry-run prints destination + manifest without writing", async () => {59 const { stdout } = await execFileAsync(process.execPath, [60 scriptPath,61 "--browser",62 "chrome",63 "--extension-id",64 "abcdefghijklmnopabcdefghijklmnop",65 "--host-path",66 "/opt/peach/peach-sync-host",67 "--dry-run",68 ]);69 expect(stdout).toMatch(/Would write .*com\.peachpasswords\.sync\.json/);70 expect(stdout).toContain('"name": "com.peachpasswords.sync"');71 expect(stdout).toContain("/opt/peach/peach-sync-host");72 });7374 it("rejects missing --browser", async () => {75 await expect(76 execFileAsync(process.execPath, [scriptPath, "--dry-run"])77 ).rejects.toThrow("--browser is required");78 });79});