Files
boss/tests/codex-desktop-integration-probe.test.mjs

124 lines
4.3 KiB
JavaScript

import test from "node:test";
import assert from "node:assert/strict";
import fs from "node:fs/promises";
import os from "node:os";
import path from "node:path";
import { spawn } from "node:child_process";
import { detectCodexDesktopIntegration } from "../scripts/codex-desktop-integration-probe.mjs";
const repoRoot = path.resolve(import.meta.dirname, "..");
async function makeFakeCodexApp() {
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "boss-codex-app-"));
const appPath = path.join(tempDir, "Codex.app");
const contentsDir = path.join(appPath, "Contents");
const resourcesDir = path.join(contentsDir, "Resources");
await fs.mkdir(resourcesDir, { recursive: true });
await fs.writeFile(
path.join(contentsDir, "Info.plist"),
`<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleIdentifier</key>
<string>com.openai.codex</string>
<key>CFBundleShortVersionString</key>
<string>26.429.30905</string>
<key>CFBundleVersion</key>
<string>2345</string>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLName</key>
<string>Codex</string>
<key>CFBundleURLSchemes</key>
<array>
<string>codex</string>
</array>
</dict>
</array>
</dict>
</plist>
`,
"utf8",
);
await fs.writeFile(
path.join(resourcesDir, "app.asar"),
"function copyThreadLink(id){return `codex://threads/${id}`} // no plugin host export",
"utf8",
);
return { tempDir, appPath };
}
test("detectCodexDesktopIntegration reports stable deeplink and bridge capabilities without patching app", async () => {
const { tempDir, appPath } = await makeFakeCodexApp();
try {
const result = await detectCodexDesktopIntegration({
appPath,
bridgeEventsUrl: "http://127.0.0.1:4318/api/v1/codex-desktop/events",
});
assert.equal(result.ok, true);
assert.equal(result.app.bundleIdentifier, "com.openai.codex");
assert.equal(result.app.shortVersion, "26.429.30905");
assert.deepEqual(result.app.urlSchemes, ["codex"]);
assert.deepEqual(result.capabilities.threadDeepLink, {
supported: true,
template: "codex://threads/{threadId}",
evidence: "CFBundleURLSchemes contains codex and app resources contain codex://threads/",
});
assert.equal(result.capabilities.desktopBridgeSse.supported, true);
assert.equal(result.capabilities.desktopBridgeSse.url, "http://127.0.0.1:4318/api/v1/codex-desktop/events");
assert.equal(result.capabilities.inAppSubscription.supported, false);
assert.equal(result.capabilities.packagePatch.supported, false);
} finally {
await fs.rm(tempDir, { recursive: true, force: true });
}
});
test("codex desktop refresh bridge daemon exposes capabilities from the integration probe", async () => {
const { tempDir, appPath } = await makeFakeCodexApp();
const child = spawn(process.execPath, [path.join(repoRoot, "scripts/codex-desktop-refresh-bridge-daemon.mjs")], {
cwd: repoRoot,
env: {
...process.env,
BOSS_CODEX_DESKTOP_BRIDGE_HOST: "127.0.0.1",
BOSS_CODEX_DESKTOP_BRIDGE_PORT: "0",
BOSS_CODEX_DESKTOP_APP_PATH: appPath,
BOSS_CODEX_DESKTOP_REFRESH_DRY_RUN: "true",
},
stdio: ["ignore", "pipe", "pipe"],
});
try {
const ready = await new Promise((resolve, reject) => {
let buffer = "";
const timer = setTimeout(() => reject(new Error("daemon not ready")), 4000);
child.stdout.setEncoding("utf8");
child.stdout.on("data", (chunk) => {
buffer += chunk;
const line = buffer.trim().split(/\r?\n/).at(-1);
if (line) {
try {
clearTimeout(timer);
resolve(JSON.parse(line));
} catch {
// wait
}
}
});
child.on("error", reject);
});
const response = await fetch(`http://${ready.host}:${ready.port}/api/v1/codex-desktop/capabilities`);
const result = await response.json();
assert.equal(response.status, 200);
assert.equal(result.ok, true);
assert.equal(result.capabilities.threadDeepLink.supported, true);
assert.equal(result.capabilities.packagePatch.supported, false);
} finally {
child.kill("SIGTERM");
await fs.rm(tempDir, { recursive: true, force: true });
}
});