test / verify-nytimes.js
// Integration test for the agent-browser wrapper.
//
// Drives src/agentBrowser.ts (via the compiled dist/) end-to-end against
// nytimes.com under a stripped PATH that mimics LM Studio's plugin runtime.
// Validates PATH discovery, argument ordering, and real-site behavior.
//
// Requires: `npm install` and a build (the npm script handles this).
// Network-dependent — needs reachable nytimes.com.
//
// Run: npm run test:verify
"use strict";
// Strip the inherited shell PATH so we exercise the wrapper's discovery logic
// the same way LM Studio's plugin runtime does.
process.env.PATH = "/usr/bin:/bin";
const path = require("path");
const { runAgentBrowser, summarize } = require(
path.join(__dirname, "..", "dist", "agentBrowser"),
);
const SETTINGS = {
binCommand: "npx agent-browser",
// Unique per-run session so the test doesn't collide with the user's
// working session if they have one open.
session: `lmstudio-verify-${process.pid}`,
headed: false,
timeoutMs: 60000,
screenshotDir: "",
userAgent:
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 " +
"(KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36",
viewport: "1440x900",
acceptLanguage: "en-US,en;q=0.9",
colorScheme: "light",
extraBrowserArgs: "--disable-blink-features=AutomationControlled",
};
const TARGET_URL = "https://www.nytimes.com";
function bar(label) {
console.log("\n" + "=".repeat(8) + " " + label + " " + "=".repeat(8));
}
async function main() {
let failed = false;
const t0 = Date.now();
try {
bar(`open ${TARGET_URL}`);
const open = await runAgentBrowser(SETTINGS, ["open", TARGET_URL]);
console.log("exit:", open.exitCode, "stderr:", open.stderr.trim().slice(0, 200));
console.log("stdout:", summarize(open, "(empty)").slice(0, 400));
if (open.exitCode !== 0) failed = true;
bar("snapshot (compact, depth 3)");
const snap = await runAgentBrowser(SETTINGS, ["snapshot", "-c", "-d", "3"]);
console.log("exit:", snap.exitCode);
console.log("stdout (first 800 chars):");
console.log(snap.stdout.slice(0, 800));
if (snap.exitCode !== 0) failed = true;
if (!snap.stdout.includes("[ref=e")) {
console.log("FAIL: snapshot did not contain any @eN refs");
failed = true;
}
bar("get title");
const title = await runAgentBrowser(SETTINGS, ["get", "title"]);
console.log("exit:", title.exitCode, "title:", title.stdout.trim());
if (title.exitCode !== 0) failed = true;
if (!/new york times/i.test(title.stdout)) {
console.log("FAIL: title did not match New York Times");
failed = true;
}
bar("get url");
const url = await runAgentBrowser(SETTINGS, ["get", "url"]);
console.log("exit:", url.exitCode, "url:", url.stdout.trim());
if (url.exitCode !== 0) failed = true;
if (!url.stdout.includes("nytimes.com")) {
console.log("FAIL: url did not contain nytimes.com");
failed = true;
}
} catch (err) {
console.error("THREW:", err);
failed = true;
} finally {
bar("cleanup: close session");
try {
const close = await runAgentBrowser(SETTINGS, ["close"]);
console.log("exit:", close.exitCode, close.stdout.trim());
} catch (err) {
console.error("close threw:", err);
}
}
const elapsed = ((Date.now() - t0) / 1000).toFixed(1);
bar(failed ? `FAIL (${elapsed}s)` : `PASS (${elapsed}s)`);
process.exit(failed ? 1 : 0);
}
main();