import { beforeEach, describe, expect, it, vi } from "vitest"; vi.mock("node:child_process", () => ({ execFileSync: vi.fn(), })); vi.mock("node:fs", () => { const existsSync = vi.fn(); const readFileSync = vi.fn(); const module = { existsSync, readFileSync }; return { ...module, default: module, }; }); vi.mock("node:os", () => { const homedir = vi.fn(); const module = { homedir }; return { ...module, default: module, }; }); import { execFileSync } from "node:child_process"; import * as fs from "node:fs"; import os from "node:os"; async function loadResolveBrowserExecutableForPlatform() { const mod = await import("./chrome.executables.js"); return mod.resolveBrowserExecutableForPlatform; } describe("browser default executable detection", () => { const launchServicesPlist = "com.apple.launchservices.secure.plist"; const chromeExecutablePath = "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"; let resolveBrowserExecutableForPlatform: Awaited< ReturnType >; function mockMacDefaultBrowser(bundleId: string, appPath = ""): void { vi.mocked(execFileSync).mockImplementation((cmd, args) => { const argsStr = Array.isArray(args) ? args.join(" ") : ""; if (cmd === "/usr/bin/plutil" && argsStr.includes("LSHandlers")) { return JSON.stringify([{ LSHandlerURLScheme: "http", LSHandlerRoleAll: bundleId }]); } if (cmd === "/usr/bin/osascript" && argsStr.includes("path to application id")) { return appPath; } if (cmd === "/usr/bin/defaults") { return "Google Chrome"; } return ""; }); } function mockChromeExecutableExists(): void { vi.mocked(fs.existsSync).mockImplementation((p) => { const value = String(p); if (value.includes(launchServicesPlist)) { return true; } return value.includes(chromeExecutablePath); }); } beforeEach(async () => { vi.resetModules(); vi.clearAllMocks(); vi.mocked(os.homedir).mockReturnValue("/Users/test"); resolveBrowserExecutableForPlatform = await loadResolveBrowserExecutableForPlatform(); }); it("prefers default Chromium browser on macOS", async () => { mockMacDefaultBrowser("com.google.Chrome", "/Applications/Google Chrome.app"); mockChromeExecutableExists(); const exe = resolveBrowserExecutableForPlatform( {} as Parameters[0], "darwin", ); expect(exe?.path).toContain("Google Chrome.app/Contents/MacOS/Google Chrome"); expect(exe?.kind).toBe("chrome"); }); it("detects Edge via LaunchServices bundle ID (com.microsoft.edgemac)", async () => { const edgeExecutablePath = "/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge"; // macOS LaunchServices registers Edge as "com.microsoft.edgemac", which // differs from the CFBundleIdentifier "com.microsoft.Edge" in the app's // own Info.plist. Both must be recognised. // // The existsSync mock deliberately only returns true for the Edge path // when checked via the resolved osascript/defaults path — Chrome's // fallback candidate path is the only other "existing" binary. This // ensures the test fails if the default-browser detection branch is // broken, because the fallback candidate list would return Chrome, not // Edge. vi.mocked(execFileSync).mockImplementation((cmd, args) => { const argsStr = Array.isArray(args) ? args.join(" ") : ""; if (cmd === "/usr/bin/plutil" && argsStr.includes("LSHandlers")) { return JSON.stringify([ { LSHandlerURLScheme: "http", LSHandlerRoleAll: "com.microsoft.edgemac" }, ]); } if (cmd === "/usr/bin/osascript" && argsStr.includes("path to application id")) { return "/Applications/Microsoft Edge.app/"; } if (cmd === "/usr/bin/defaults") { return "Microsoft Edge"; } return ""; }); vi.mocked(fs.existsSync).mockImplementation((p) => { const value = String(p); if (value.includes(launchServicesPlist)) { return true; } // Only Edge (via osascript resolution) and Chrome (fallback candidate) // "exist". If default-browser detection breaks, the resolver would // return Chrome from the fallback list — not Edge — failing the assert. return value === edgeExecutablePath || value.includes(chromeExecutablePath); }); const resolveBrowserExecutableForPlatform = await loadResolveBrowserExecutableForPlatform(); const exe = resolveBrowserExecutableForPlatform( {} as Parameters[0], "darwin", ); expect(exe?.path).toBe(edgeExecutablePath); expect(exe?.kind).toBe("edge"); }); it("falls back when default browser is non-Chromium on macOS", async () => { mockMacDefaultBrowser("com.apple.Safari"); mockChromeExecutableExists(); const exe = resolveBrowserExecutableForPlatform( {} as Parameters[0], "darwin", ); expect(exe?.path).toContain("Google Chrome.app/Contents/MacOS/Google Chrome"); }); });