Files
xread/tests/container-runtime-regressions.test.cjs

146 lines
5.4 KiB
JavaScript

const test = require("node:test");
const assert = require("node:assert/strict");
const fs = require("node:fs");
const path = require("node:path");
const projectRoot = path.resolve(__dirname, "..");
function readProjectFile(relativePath) {
return fs.readFileSync(path.join(projectRoot, relativePath), "utf8");
}
test("browser launchers include container-safe Chrome sandbox flags", () => {
const mainPuppeteer = readProjectFile("src/services/puppeteer.ts");
const serpPuppeteer = readProjectFile("src/services/serp/puppeteer.ts");
for (const source of [mainPuppeteer, serpPuppeteer]) {
assert.match(source, /pipe:\s*true/);
assert.match(source, /--no-sandbox/);
assert.match(source, /--disable-setuid-sandbox/);
}
});
test("SERP puppeteer control uses an absolute control timeout instead of a fixed post-navigation race", () => {
const serpPuppeteer = readProjectFile("src/services/serp/puppeteer.ts");
assert.match(
serpPuppeteer,
/waitUntil:\s*\[\s*["']domcontentloaded["'],\s*["']load["'],?\s*\]/,
);
assert.match(
serpPuppeteer,
/setTimeout\(\(\) => \{\s*resultDeferred\.reject\(\s*new TimeoutError/,
);
assert.doesNotMatch(serpPuppeteer, /networkidle0/);
assert.doesNotMatch(serpPuppeteer, /await delay\(5000\)/);
});
test("canvas service falls back when bundled font asset is missing", () => {
const canvasService = readProjectFile("src/services/canvas.ts");
assert.match(canvasService, /ENOENT/);
assert.match(canvasService, /Bundled font asset unavailable/);
});
test("search host includes Google scraping fallback for standalone builds", () => {
const searcherHost = readProjectFile("src/api/searcher.ts");
assert.match(searcherHost, /protected googleSerp: GoogleSERP/);
assert.match(
searcherHost,
/protected standaloneFallback: StandaloneSearchFallbackService/,
);
assert.match(searcherHost, /yield this\.googleSerp/);
assert.match(searcherHost, /yield this\.standaloneFallback/);
assert.match(
searcherHost,
/const includeSerper = Boolean\(this\.secretExposer\.SERPER_SEARCH_API_KEY\)/,
);
});
test("SERP host skips Serper providers when no API key is configured", () => {
const serpHost = readProjectFile("src/api/serp.ts");
assert.match(
serpHost,
/const includeSerper = Boolean\(this\.secretExposer\.SERPER_SEARCH_API_KEY\)/,
);
assert.match(serpHost, /yield this\.standaloneFallback/);
});
test("standalone fallback search provider is available for local web search without private APIs", () => {
const fallbackProvider = readProjectFile(
"src/services/serp/standalone-fallback.ts",
);
assert.match(fallbackProvider, /DuckDuckGo HTML fallback/i);
assert.match(
fallbackProvider,
/querySelectorAll\(\s*["']\.result:not\(\.result--ad\)["']/,
);
assert.match(fallbackProvider, /ad_domain/);
});
test("google search provider can fall back to direct requests when no proxy is configured", () => {
const googleSerp = readProjectFile("src/services/serp/google.ts");
assert.match(googleSerp, /falling back to direct Google request/i);
});
test("standalone URL validation can allow Docker DNS rewrite ranges behind an explicit env gate", () => {
const miscService = readProjectFile("src/services/misc.ts");
assert.match(miscService, /STANDALONE_ALLOW_INTERNAL_DNS_REWRITE/);
assert.match(miscService, /198\.18/);
assert.match(miscService, /fd00::/i);
});
test("standalone services use extended boot timeouts for cold starts", () => {
const bootTimeouts = readProjectFile("src/services/boot-timeouts.ts");
const crawlHost = readProjectFile("src/api/crawler.ts");
const searcherHost = readProjectFile("src/api/searcher.ts");
const serpHost = readProjectFile("src/api/serp.ts");
const crawlServer = readProjectFile("src/stand-alone/crawl.ts");
const searchServer = readProjectFile("src/stand-alone/search.ts");
const serpServer = readProjectFile("src/stand-alone/serp.ts");
const googleSerp = readProjectFile("src/services/serp/google.ts");
assert.match(bootTimeouts, /STANDALONE_BOOT_TIMEOUT_MS = 90_000/);
assert.match(bootTimeouts, /SERP_BOOT_TIMEOUT_MS = 90_000/);
assert.match(crawlHost, /dependencyReady\(STANDALONE_BOOT_TIMEOUT_MS\)/);
assert.match(
crawlHost,
/override dependencyReady\(timeoutMilliseconds = STANDALONE_BOOT_TIMEOUT_MS\)/,
);
assert.match(searcherHost, /dependencyReady\(STANDALONE_BOOT_TIMEOUT_MS\)/);
assert.match(
searcherHost,
/override dependencyReady\(timeoutMilliseconds = STANDALONE_BOOT_TIMEOUT_MS\)/,
);
assert.match(serpHost, /dependencyReady\(STANDALONE_BOOT_TIMEOUT_MS\)/);
assert.match(
serpHost,
/override dependencyReady\(timeoutMilliseconds = STANDALONE_BOOT_TIMEOUT_MS\)/,
);
assert.match(crawlServer, /dependencyReady\(STANDALONE_BOOT_TIMEOUT_MS\)/);
assert.match(
crawlServer,
/override dependencyReady\(timeoutMilliseconds = STANDALONE_BOOT_TIMEOUT_MS\)/,
);
assert.match(searchServer, /dependencyReady\(STANDALONE_BOOT_TIMEOUT_MS\)/);
assert.match(
searchServer,
/override dependencyReady\(timeoutMilliseconds = STANDALONE_BOOT_TIMEOUT_MS\)/,
);
assert.match(serpServer, /dependencyReady\(STANDALONE_BOOT_TIMEOUT_MS\)/);
assert.match(
serpServer,
/override dependencyReady\(timeoutMilliseconds = STANDALONE_BOOT_TIMEOUT_MS\)/,
);
assert.match(googleSerp, /dependencyReady\(SERP_BOOT_TIMEOUT_MS\)/);
assert.match(
googleSerp,
/override dependencyReady\(timeoutMilliseconds = SERP_BOOT_TIMEOUT_MS\)/,
);
});