mirror of
https://github.com/CloakHQ/CloakBrowser.git
synced 2026-06-23 11:41:46 +02:00
feat(js): export buildContextOptions helper (#262)
Co-authored-by: 이민재 <19909783+honor2030@users.noreply.github.com>
This commit is contained in:
+1
-1
@@ -16,7 +16,7 @@
|
||||
*/
|
||||
|
||||
// Launch functions (Playwright API)
|
||||
export { launch, launchContext, launchPersistentContext, buildLaunchOptions, humanizeBrowser } from "./playwright.js";
|
||||
export { launch, launchContext, launchPersistentContext, buildLaunchOptions, buildContextOptions, humanizeBrowser } from "./playwright.js";
|
||||
|
||||
// Binary management
|
||||
export { ensureBinary, clearCache, binaryInfo, checkForUpdate } from "./download.js";
|
||||
|
||||
+22
-14
@@ -44,6 +44,26 @@ function filterStealthCtxOptions(ctx?: BrowserContextOptions): Partial<BrowserCo
|
||||
return rest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build Playwright BrowserContext options for CloakBrowser without launching a browser
|
||||
* or creating a context.
|
||||
*
|
||||
* Useful when integrating CloakBrowser with an existing Playwright Browser while
|
||||
* keeping the wrapper's stealth-safe defaults for `newContext()`.
|
||||
*/
|
||||
export function buildContextOptions(
|
||||
options: LaunchContextOptions = {}
|
||||
): BrowserContextOptions {
|
||||
return {
|
||||
// contextOptions first — explicit wrapper fields below override it.
|
||||
// filterStealthCtxOptions strips locale/timezoneId to prevent CDP detection.
|
||||
...filterStealthCtxOptions(options.contextOptions),
|
||||
...(options.userAgent ? { userAgent: options.userAgent } : {}),
|
||||
viewport: options.viewport === undefined ? DEFAULT_VIEWPORT : options.viewport,
|
||||
...(options.colorScheme ? { colorScheme: options.colorScheme } : {}),
|
||||
} as BrowserContextOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build Playwright launch options for CloakBrowser without starting Chromium.
|
||||
*
|
||||
@@ -144,14 +164,7 @@ export async function launchContext(
|
||||
|
||||
let context: BrowserContext;
|
||||
try {
|
||||
context = await browser.newContext({
|
||||
// contextOptions first — explicit wrapper fields below override it.
|
||||
// filterStealthCtxOptions strips locale/timezoneId to prevent CDP detection.
|
||||
...filterStealthCtxOptions(options.contextOptions),
|
||||
...(options.userAgent ? { userAgent: options.userAgent } : {}),
|
||||
viewport: options.viewport === undefined ? DEFAULT_VIEWPORT : options.viewport,
|
||||
...(options.colorScheme ? { colorScheme: options.colorScheme } : {}),
|
||||
});
|
||||
context = await browser.newContext(buildContextOptions(options));
|
||||
} catch (err) {
|
||||
await browser.close();
|
||||
throw err;
|
||||
@@ -222,12 +235,7 @@ export async function launchPersistentContext(
|
||||
args,
|
||||
ignoreDefaultArgs: IGNORE_DEFAULT_ARGS,
|
||||
...(proxyOption ? { proxy: proxyOption } : {}),
|
||||
// contextOptions before explicit wrapper fields so explicit wins.
|
||||
// filterStealthCtxOptions strips locale/timezoneId to prevent CDP detection.
|
||||
...filterStealthCtxOptions(options.contextOptions),
|
||||
...(options.userAgent ? { userAgent: options.userAgent } : {}),
|
||||
viewport: options.viewport === undefined ? DEFAULT_VIEWPORT : options.viewport,
|
||||
...(options.colorScheme ? { colorScheme: options.colorScheme } : {}),
|
||||
...buildContextOptions(options),
|
||||
...options.launchOptions,
|
||||
});
|
||||
|
||||
|
||||
+38
-1
@@ -40,13 +40,50 @@ describe("composable Playwright launch helpers", () => {
|
||||
}
|
||||
});
|
||||
|
||||
it("exports buildLaunchOptions and humanizeBrowser from the package entrypoint", async () => {
|
||||
it("exports composable helpers from the package entrypoint", async () => {
|
||||
const entry = await import("../src/index.js");
|
||||
|
||||
expect(entry.buildLaunchOptions).toBeTypeOf("function");
|
||||
expect(entry.buildContextOptions).toBeTypeOf("function");
|
||||
expect(entry.humanizeBrowser).toBeTypeOf("function");
|
||||
});
|
||||
|
||||
it("buildContextOptions returns Playwright context options without launching a browser", async () => {
|
||||
const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => {});
|
||||
const { buildContextOptions } = await import("../src/index.js");
|
||||
|
||||
const options = buildContextOptions({
|
||||
userAgent: "Explicit/1.0",
|
||||
viewport: { width: 1280, height: 720 },
|
||||
colorScheme: "dark",
|
||||
contextOptions: {
|
||||
userAgent: "Context/9.9",
|
||||
viewport: { width: 9999, height: 9999 },
|
||||
colorScheme: "light",
|
||||
storageState: "state.json",
|
||||
locale: "de-DE",
|
||||
timezoneId: "Europe/Berlin",
|
||||
},
|
||||
});
|
||||
|
||||
expect(options).toMatchObject({
|
||||
userAgent: "Explicit/1.0",
|
||||
viewport: { width: 1280, height: 720 },
|
||||
colorScheme: "dark",
|
||||
storageState: "state.json",
|
||||
});
|
||||
expect(options.locale).toBeUndefined();
|
||||
expect(options.timezoneId).toBeUndefined();
|
||||
expect(warnSpy).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
||||
it("buildContextOptions applies DEFAULT_VIEWPORT by default and allows null viewport", async () => {
|
||||
const { buildContextOptions } = await import("../src/index.js");
|
||||
|
||||
expect(buildContextOptions().viewport).toEqual(DEFAULT_VIEWPORT);
|
||||
expect(buildContextOptions({ viewport: null }).viewport).toBeNull();
|
||||
});
|
||||
|
||||
it("buildLaunchOptions returns Playwright options without launching a browser", async () => {
|
||||
const freshConfig = await import("../src/config.js");
|
||||
vi.spyOn(freshConfig, "getPlatformTag").mockReturnValue("darwin-arm64");
|
||||
|
||||
Reference in New Issue
Block a user