Files
OmniRoute/tests/unit/browserBackedChat-optional-package-absent.test.ts
oyi77 0f96a97e33 fix: browser-pool stub type errors, silent-fallback regression, grokClearance signature
Pre-merge fixes for the CloakBrowser/Playwright extraction into the
optional @omniroute/browser-pool workspace package:

- Add the @omniroute/browser-pool path mapping to the root tsconfig.json
  (tsconfig.typecheck-core.json extends the root, not open-sse/tsconfig.json,
  so typecheck:core was failing with 3x TS2307 in browserPool.ts).
- tryBackedChat() in browserBackedChat.ts silently returned the stale
  httpResult (the unsolved challenge/403 body) when the optional
  browser-pool package was absent, instead of surfacing an error. Now
  throws a descriptive error so callers (claude-web, duckduckgo-web) and
  upstream fallback handling can react correctly instead of treating an
  unsolved challenge as a definitive response. Restored
  resolveBrowserContextProxy (dropped during the browserPool.ts merge
  conflict resolution against origin/release/v3.8.49) which
  tests/unit/browserPool-proxy.test.ts already depends on.
- Fix acquireFreshGrokClearance stub signature in grokClearance.ts to
  match the real package impl and the grok-web.ts caller:
  (signal?: AbortSignal | null) => Promise<string | null>, not
  (prompt: string) => Promise<PooledContext | null>.
- Add tests/unit/browserBackedChat-optional-package-absent.test.ts
  covering the previously-silent "package absent + challenge response"
  regression, plus a __setBrowserPoolModOverrideForTesting() hook to
  simulate that path deterministically.

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
2026-07-23 20:35:58 -03:00

93 lines
3.2 KiB
TypeScript

import assert from "node:assert/strict";
import { describe, it } from "node:test";
import {
__resetBrowserPoolModOverrideForTesting,
__resetHttpBackedChatOverrideForTesting,
__setBrowserPoolModOverrideForTesting,
__setHttpBackedChatOverrideForTesting,
tryBackedChat,
} from "../../open-sse/services/browserBackedChat.ts";
// Regression test for the "optional @omniroute/browser-pool package absent"
// path in tryBackedChat(). Before the fix, when the upstream returned a
// challenge response (e.g. 403) and the optional browser-pool package was
// not installed (getMod() resolves to null — the same shape a real failed
// `import("@omniroute/browser-pool")` produces), tryBackedChat() silently
// returned the stale challenge result instead of surfacing a clear error —
// callers (claude-web, duckduckgo-web) would then treat the unsolved
// challenge as a definitive upstream response.
//
// __setBrowserPoolModOverrideForTesting(null) simulates the module-absent
// case deterministically (same as getMod() catching a failed dynamic
// import), without depending on a real failing dynamic import of a
// nonexistent package.
describe("tryBackedChat — optional @omniroute/browser-pool package absent", () => {
it("throws a descriptive error instead of silently returning the stale challenge response", async () => {
__setBrowserPoolModOverrideForTesting(null);
__setHttpBackedChatOverrideForTesting(async () => ({
status: 403,
contentType: "text/html",
body: Buffer.from("<html>Just a moment...</html>"),
isStealth: true,
timing: {
acquireContextMs: 0,
navigateMs: 0,
submitMs: 0,
captureResponseMs: 0,
totalMs: 0,
},
}));
try {
await assert.rejects(
() =>
tryBackedChat({
poolKey: "duckduckgo-web",
chatUrl: "https://duck.ai/duckchat/v1/chat",
userMessage: "hello",
}),
(err: unknown) => {
assert.ok(err instanceof Error);
// Must NOT resolve with the stale challenge body — must throw with
// enough context to diagnose (challenge status + missing package).
assert.match(err.message, /challenge/i);
assert.match(err.message, /@omniroute\/browser-pool/);
assert.match(err.message, /403/);
return true;
}
);
} finally {
__resetHttpBackedChatOverrideForTesting();
__resetBrowserPoolModOverrideForTesting();
}
});
it("returns the httpResult directly when it is not a challenge response (2xx path unaffected)", async () => {
__setHttpBackedChatOverrideForTesting(async () => ({
status: 200,
contentType: "application/json",
body: Buffer.from(JSON.stringify({ ok: true })),
isStealth: true,
timing: {
acquireContextMs: 0,
navigateMs: 0,
submitMs: 0,
captureResponseMs: 0,
totalMs: 0,
},
}));
try {
const result = await tryBackedChat({
poolKey: "duckduckgo-web",
chatUrl: "https://duck.ai/duckchat/v1/chat",
userMessage: "hello",
});
assert.equal(result.status, 200);
} finally {
__resetHttpBackedChatOverrideForTesting();
}
});
});