mirror of
https://github.com/CloakHQ/CloakBrowser.git
synced 2026-06-23 11:41:46 +02:00
The `proxy` parameter now accepts a Playwright proxy dict
({server, bypass, username, password}) in addition to URL strings.
Dict proxies are passed directly to Playwright, enabling bypass
lists and other advanced proxy options.
- Add ProxySettings TypedDict for Python type safety
- Extract server URL from dict proxies for geoip resolution
- Handle dict proxy args/auth in Puppeteer wrapper
- Strip inline credentials from dict proxy server URL in Puppeteer
- Fix JS launchContext() double-setting timezone (binary flag + context)
- Remove unnecessary non-null assertions in TS geoip helpers
- Use nullish coalescing for password fallbacks
- Add unit tests for geoip with dict proxy input
85 lines
2.7 KiB
TypeScript
85 lines
2.7 KiB
TypeScript
import { describe, it, expect } from "vitest";
|
|
import { parseProxyUrl } from "../src/proxy.js";
|
|
import type { LaunchOptions } from "../src/types.js";
|
|
|
|
describe("parseProxyUrl", () => {
|
|
it("passes through URL without credentials", () => {
|
|
expect(parseProxyUrl("http://proxy:8080")).toEqual({
|
|
server: "http://proxy:8080",
|
|
});
|
|
});
|
|
|
|
it("extracts credentials from URL", () => {
|
|
expect(parseProxyUrl("http://user:pass@proxy:8080")).toEqual({
|
|
server: "http://proxy:8080",
|
|
username: "user",
|
|
password: "pass",
|
|
});
|
|
});
|
|
|
|
it("decodes URL-encoded special chars", () => {
|
|
const result = parseProxyUrl("http://user:p%40ss%3Aword@proxy:8080");
|
|
expect(result.password).toBe("p@ss:word");
|
|
expect(result.username).toBe("user");
|
|
expect(result.server).toBe("http://proxy:8080");
|
|
});
|
|
|
|
it("handles socks5 protocol", () => {
|
|
const result = parseProxyUrl("socks5://user:pass@proxy:1080");
|
|
expect(result.server).toBe("socks5://proxy:1080");
|
|
expect(result.username).toBe("user");
|
|
expect(result.password).toBe("pass");
|
|
});
|
|
|
|
it("handles URL without port", () => {
|
|
const result = parseProxyUrl("http://user:pass@proxy");
|
|
expect(result.server).toBe("http://proxy");
|
|
expect(result.username).toBe("user");
|
|
});
|
|
|
|
it("handles username only (no password)", () => {
|
|
const result = parseProxyUrl("http://user@proxy:8080");
|
|
expect(result.server).toBe("http://proxy:8080");
|
|
expect(result.username).toBe("user");
|
|
expect(result.password).toBeUndefined();
|
|
});
|
|
|
|
it("passes through unparseable string", () => {
|
|
expect(parseProxyUrl("not-a-url")).toEqual({ server: "not-a-url" });
|
|
});
|
|
});
|
|
|
|
describe("proxy dict type", () => {
|
|
it("accepts string proxy in LaunchOptions", () => {
|
|
const opts: LaunchOptions = { proxy: "http://proxy:8080" };
|
|
expect(typeof opts.proxy).toBe("string");
|
|
});
|
|
|
|
it("accepts dict proxy with bypass in LaunchOptions", () => {
|
|
const opts: LaunchOptions = {
|
|
proxy: { server: "http://proxy:8080", bypass: ".google.com,localhost" },
|
|
};
|
|
expect(typeof opts.proxy).toBe("object");
|
|
if (typeof opts.proxy === "object") {
|
|
expect(opts.proxy.server).toBe("http://proxy:8080");
|
|
expect(opts.proxy.bypass).toBe(".google.com,localhost");
|
|
}
|
|
});
|
|
|
|
it("accepts dict proxy with auth and bypass in LaunchOptions", () => {
|
|
const opts: LaunchOptions = {
|
|
proxy: {
|
|
server: "http://proxy:8080",
|
|
username: "user",
|
|
password: "pass",
|
|
bypass: ".example.com",
|
|
},
|
|
};
|
|
if (typeof opts.proxy === "object") {
|
|
expect(opts.proxy.username).toBe("user");
|
|
expect(opts.proxy.password).toBe("pass");
|
|
expect(opts.proxy.bypass).toBe(".example.com");
|
|
}
|
|
});
|
|
});
|