aboutsummaryrefslogtreecommitdiff
path: root/test/cdp/endpoint-test.ts
diff options
context:
space:
mode:
Diffstat (limited to 'test/cdp/endpoint-test.ts')
-rw-r--r--test/cdp/endpoint-test.ts99
1 files changed, 99 insertions, 0 deletions
diff --git a/test/cdp/endpoint-test.ts b/test/cdp/endpoint-test.ts
new file mode 100644
index 0000000..d4b696f
--- /dev/null
+++ b/test/cdp/endpoint-test.ts
@@ -0,0 +1,99 @@
+/**
+ * Unit tests for CDP target resolution — no browser and no network required.
+ *
+ * This is fork-specific logic (see FORK.md): upstream only ever drives a
+ * browser on localhost. The precedence here is deliberately asymmetric — an
+ * explicitly configured endpoint must never silently fall back to a different
+ * browser, while the built-in default must, so a machine off the wire network
+ * still gets the local browser the extension was originally written for.
+ *
+ * Run: npx tsx test/cdp/endpoint-test.ts
+ */
+import { DEFAULT_REMOTE_CDP, describeCdpTarget, resolveCdpTarget } from "../../src/cdp/endpoint";
+
+let passed = 0;
+let failed = 0;
+const check = (cond: boolean, label: string): void => {
+ if (cond) {
+ passed++;
+ console.log(` ✓ ${label}`);
+ } else {
+ failed++;
+ console.error(` ✗ ${label}`);
+ }
+};
+
+const env = (value?: string): NodeJS.ProcessEnv => (value === undefined ? {} : { BU_CDP_HTTP: value });
+
+function main(): void {
+ // E1: the built-in default, used when nothing is configured.
+ {
+ const t = resolveCdpTarget(env());
+ check(t.kind === "remote", "E1: unset BU_CDP_HTTP resolves to a remote target");
+ if (t.kind === "remote") {
+ check(t.source === "default", "E1: it is marked as the built-in default, not an instruction");
+ check(`${t.host}:${t.port}` === DEFAULT_REMOTE_CDP, "E1: it matches DEFAULT_REMOTE_CDP");
+ }
+ }
+
+ // E2: DEFAULT_REMOTE_CDP must itself be parseable, or the default silently
+ // degrades to local for everyone.
+ {
+ const t = resolveCdpTarget(env());
+ check(t.kind !== "local", "E2: the built-in default constant is well-formed");
+ }
+
+ // E3: an explicit endpoint is an instruction — source must reflect that, so
+ // discovery fails loudly rather than falling back.
+ {
+ const t = resolveCdpTarget(env("10.0.0.9:9333"));
+ check(t.kind === "remote", "E3: an explicit host:port resolves to a remote target");
+ if (t.kind === "remote") {
+ check(t.host === "10.0.0.9" && t.port === 9333, "E3: host and port are parsed");
+ check(t.source === "env", "E3: it is marked as explicitly configured");
+ }
+ }
+
+ // E4: opting back into upstream behaviour.
+ for (const alias of ["local", "LOCAL", "off", "none", "0", "no"]) {
+ const t = resolveCdpTarget(env(alias));
+ check(t.kind === "local", `E4: "${alias}" selects this machine's own browser`);
+ }
+
+ // E5: empty or whitespace is treated as unset rather than as an error — a
+ // shell exporting an empty var should not break the browser.
+ for (const blank of ["", " "]) {
+ const t = resolveCdpTarget(env(blank));
+ check(t.kind === "remote" && t.source === "default", `E5: ${JSON.stringify(blank)} falls back to the default`);
+ }
+
+ // E6: malformed values are rejected, not coerced. Silently reinterpreting
+ // these would drive an unexpected browser.
+ for (const bad of ["nonsense", "host:", ":9222", "host:0", "host:70000", "host:abc"]) {
+ const t = resolveCdpTarget(env(bad));
+ check(t.kind === "invalid", `E6: "${bad}" is rejected as malformed`);
+ }
+
+ // E7: IPv6 and hostnames still work — the port is taken from the LAST colon.
+ {
+ const t = resolveCdpTarget(env("castle.local:9223"));
+ check(t.kind === "remote" && t.host === "castle.local", "E7: hostnames are accepted");
+ const v6 = resolveCdpTarget(env("[::1]:9223"));
+ check(v6.kind === "remote" && v6.host === "[::1]" && v6.port === 9223, "E7: bracketed IPv6 keeps its host");
+ }
+
+ // E8: descriptions are for humans in /browser-status; they must distinguish
+ // a default from an instruction, since only one of them falls back.
+ {
+ const d = describeCdpTarget(resolveCdpTarget(env()));
+ const e = describeCdpTarget(resolveCdpTarget(env("10.0.0.9:9333")));
+ check(d.includes("default"), "E8: the default is labelled as such");
+ check(e.includes("BU_CDP_HTTP"), "E8: an explicit endpoint names the variable that set it");
+ check(describeCdpTarget(resolveCdpTarget(env("local"))).includes("own browser"), "E8: local is described plainly");
+ }
+
+ console.log(`\n${passed} passed, ${failed} failed`);
+ if (failed > 0) process.exit(1);
+}
+
+main();