fix: stabilize macOS audio test and default browser detection
This commit is contained in:
@@ -8,7 +8,7 @@ import Testing
|
||||
let wav = makeWav16Mono(sampleRate: 8000, samples: 80)
|
||||
defer { _ = TalkAudioPlayer.shared.stop() }
|
||||
|
||||
_ = try await withTimeout(seconds: 2.0) {
|
||||
_ = try await withTimeout(seconds: 4.0) {
|
||||
await TalkAudioPlayer.shared.play(data: wav)
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ import Testing
|
||||
await Task.yield()
|
||||
_ = await TalkAudioPlayer.shared.play(data: wav)
|
||||
|
||||
_ = try await withTimeout(seconds: 2.0) {
|
||||
_ = try await withTimeout(seconds: 4.0) {
|
||||
await first.value
|
||||
}
|
||||
#expect(true)
|
||||
|
||||
@@ -24,10 +24,10 @@ describe("browser default executable detection", () => {
|
||||
it("prefers default Chromium browser on macOS", async () => {
|
||||
vi.mocked(execFileSync).mockImplementation((cmd, args) => {
|
||||
const argsStr = Array.isArray(args) ? args.join(" ") : "";
|
||||
if (cmd === "/usr/bin/osascript" && argsStr.includes("id of application")) {
|
||||
return "com.google.Chrome";
|
||||
if (cmd === "/usr/bin/plutil" && argsStr.includes("LSHandlers")) {
|
||||
return JSON.stringify([{ LSHandlerURLScheme: "http", LSHandlerRoleAll: "com.google.Chrome" }]);
|
||||
}
|
||||
if (cmd === "/usr/bin/osascript" && argsStr.includes("POSIX path")) {
|
||||
if (cmd === "/usr/bin/osascript" && argsStr.includes("path to application id")) {
|
||||
return "/Applications/Google Chrome.app";
|
||||
}
|
||||
if (cmd === "/usr/bin/defaults") {
|
||||
@@ -35,9 +35,11 @@ describe("browser default executable detection", () => {
|
||||
}
|
||||
return "";
|
||||
});
|
||||
vi.mocked(fs.existsSync).mockImplementation((p) =>
|
||||
String(p).includes("/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"),
|
||||
);
|
||||
vi.mocked(fs.existsSync).mockImplementation((p) => {
|
||||
const value = String(p);
|
||||
if (value.includes("com.apple.launchservices.secure.plist")) return true;
|
||||
return value.includes("/Applications/Google Chrome.app/Contents/MacOS/Google Chrome");
|
||||
});
|
||||
|
||||
const { resolveBrowserExecutableForPlatform } = await import("./chrome.executables.js");
|
||||
const exe = resolveBrowserExecutableForPlatform(
|
||||
@@ -52,14 +54,16 @@ describe("browser default executable detection", () => {
|
||||
it("falls back when default browser is non-Chromium on macOS", async () => {
|
||||
vi.mocked(execFileSync).mockImplementation((cmd, args) => {
|
||||
const argsStr = Array.isArray(args) ? args.join(" ") : "";
|
||||
if (cmd === "/usr/bin/osascript" && argsStr.includes("id of application")) {
|
||||
return "com.apple.Safari";
|
||||
if (cmd === "/usr/bin/plutil" && argsStr.includes("LSHandlers")) {
|
||||
return JSON.stringify([{ LSHandlerURLScheme: "http", LSHandlerRoleAll: "com.apple.Safari" }]);
|
||||
}
|
||||
return "";
|
||||
});
|
||||
vi.mocked(fs.existsSync).mockImplementation((p) =>
|
||||
String(p).includes("Google Chrome.app/Contents/MacOS/Google Chrome"),
|
||||
);
|
||||
vi.mocked(fs.existsSync).mockImplementation((p) => {
|
||||
const value = String(p);
|
||||
if (value.includes("com.apple.launchservices.secure.plist")) return true;
|
||||
return value.includes("Google Chrome.app/Contents/MacOS/Google Chrome");
|
||||
});
|
||||
|
||||
const { resolveBrowserExecutableForPlatform } = await import("./chrome.executables.js");
|
||||
const exe = resolveBrowserExecutableForPlatform(
|
||||
|
||||
@@ -95,12 +95,17 @@ function exists(filePath: string) {
|
||||
}
|
||||
}
|
||||
|
||||
function execText(command: string, args: string[], timeoutMs = 1200): string | null {
|
||||
function execText(
|
||||
command: string,
|
||||
args: string[],
|
||||
timeoutMs = 1200,
|
||||
maxBuffer = 1024 * 1024,
|
||||
): string | null {
|
||||
try {
|
||||
const output = execFileSync(command, args, {
|
||||
timeout: timeoutMs,
|
||||
encoding: "utf8",
|
||||
maxBuffer: 1024 * 1024,
|
||||
maxBuffer,
|
||||
});
|
||||
return String(output ?? "").trim() || null;
|
||||
} catch {
|
||||
@@ -140,14 +145,12 @@ function detectDefaultChromiumExecutable(
|
||||
}
|
||||
|
||||
function detectDefaultChromiumExecutableMac(): BrowserExecutable | null {
|
||||
const bundleId = execText("/usr/bin/osascript", [
|
||||
"-e",
|
||||
'id of application (path to default application for URL "http://example.com")',
|
||||
]);
|
||||
if (!bundleId || !CHROMIUM_BUNDLE_IDS.has(bundleId.trim())) return null;
|
||||
const bundleId = detectDefaultBrowserBundleIdMac();
|
||||
if (!bundleId || !CHROMIUM_BUNDLE_IDS.has(bundleId)) return null;
|
||||
|
||||
const appPathRaw = execText("/usr/bin/osascript", [
|
||||
"-e",
|
||||
'POSIX path of (path to default application for URL "http://example.com")',
|
||||
`POSIX path of (path to application id "${bundleId}")`,
|
||||
]);
|
||||
if (!appPathRaw) return null;
|
||||
const appPath = appPathRaw.trim().replace(/\/$/, "");
|
||||
@@ -162,6 +165,45 @@ function detectDefaultChromiumExecutableMac(): BrowserExecutable | null {
|
||||
return { kind: inferKindFromIdentifier(bundleId), path: exePath };
|
||||
}
|
||||
|
||||
function detectDefaultBrowserBundleIdMac(): string | null {
|
||||
const plistPath = path.join(
|
||||
os.homedir(),
|
||||
"Library/Preferences/com.apple.LaunchServices/com.apple.launchservices.secure.plist",
|
||||
);
|
||||
if (!exists(plistPath)) return null;
|
||||
const handlersRaw = execText(
|
||||
"/usr/bin/plutil",
|
||||
["-extract", "LSHandlers", "json", "-o", "-", "--", plistPath],
|
||||
2000,
|
||||
5 * 1024 * 1024,
|
||||
);
|
||||
if (!handlersRaw) return null;
|
||||
let handlers: unknown;
|
||||
try {
|
||||
handlers = JSON.parse(handlersRaw);
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
if (!Array.isArray(handlers)) return null;
|
||||
|
||||
const resolveScheme = (scheme: string) => {
|
||||
let candidate: string | null = null;
|
||||
for (const entry of handlers) {
|
||||
if (!entry || typeof entry !== "object") continue;
|
||||
const record = entry as Record<string, unknown>;
|
||||
if (record.LSHandlerURLScheme !== scheme) continue;
|
||||
const role =
|
||||
(typeof record.LSHandlerRoleAll === "string" && record.LSHandlerRoleAll) ||
|
||||
(typeof record.LSHandlerRoleViewer === "string" && record.LSHandlerRoleViewer) ||
|
||||
null;
|
||||
if (role) candidate = role;
|
||||
}
|
||||
return candidate;
|
||||
};
|
||||
|
||||
return resolveScheme("http") ?? resolveScheme("https");
|
||||
}
|
||||
|
||||
function detectDefaultChromiumExecutableLinux(): BrowserExecutable | null {
|
||||
const desktopId =
|
||||
execText("xdg-settings", ["get", "default-web-browser"]) ||
|
||||
|
||||
Reference in New Issue
Block a user