feat: open the browser window maximized on 148.0.7778.215.4+ builds
Default headed and headless launches to a maximized window (fills the screen) on binaries at or above the same threshold as the headless no-viewport default. Suppressed when the caller sets --window-size / --window-position / --start-maximized or an explicit viewport; older builds are unchanged. Version-gated via a dedicated helper sharing the no-viewport threshold. Mirrored across Python, JS and .NET with parity tests. The Docker image runs openbox so headed --start-maximized is honored (bare Xvfb has no window manager; headless is unaffected).
This commit is contained in:
+1
-1
@@ -11,7 +11,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
libgdk-pixbuf-2.0-0 libxss1 libxtst6 fonts-liberation \
|
||||
fonts-noto-color-emoji fonts-unifont fonts-freefont-ttf \
|
||||
fonts-ipafont-gothic fonts-wqy-zenhei fonts-tlwg-loma-otf \
|
||||
xvfb xdotool \
|
||||
xvfb xdotool openbox \
|
||||
curl ca-certificates \
|
||||
&& curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \
|
||||
&& apt-get install -y --no-install-recommends nodejs \
|
||||
|
||||
@@ -11,6 +11,11 @@ rm -f /tmp/.X99-lock /tmp/.X11-unix/X99
|
||||
Xvfb :99 -screen 0 1920x1080x24 -nolisten tcp &
|
||||
sleep 1
|
||||
|
||||
# Window manager so headed --start-maximized is honored (bare Xvfb has no WM;
|
||||
# without one the flag is a silent no-op and the window stays un-maximized).
|
||||
DISPLAY=:99 openbox &
|
||||
sleep 1
|
||||
|
||||
# Opt-in: fetch the Widevine CDM so persistent contexts present as a real
|
||||
# Chrome (a DRM/EME probe is used by some bot detectors). Off by default — only
|
||||
# runs when CLOAKBROWSER_FETCH_WIDEVINE is set, and never if the user already
|
||||
|
||||
+17
-5
@@ -24,6 +24,7 @@ from .config import (
|
||||
DEFAULT_VIEWPORT,
|
||||
IGNORE_DEFAULT_ARGS,
|
||||
binary_supports_headless_no_viewport,
|
||||
binary_supports_maximized_window,
|
||||
get_default_stealth_args,
|
||||
normalize_requested_version,
|
||||
)
|
||||
@@ -210,7 +211,7 @@ def launch(
|
||||
args = list(args or [])
|
||||
args.append(f"--fingerprint-webrtc-ip={exit_ip}")
|
||||
|
||||
chrome_args = build_args(stealth_args, (args or []) + proxy_extra_args, timezone=timezone, locale=locale, headless=headless, extension_paths=extension_paths)
|
||||
chrome_args = build_args(stealth_args, (args or []) + proxy_extra_args, timezone=timezone, locale=locale, headless=headless, extension_paths=extension_paths, start_maximized=binary_supports_maximized_window(license_key, browser_version))
|
||||
_maybe_warn_windows_fonts(chrome_args)
|
||||
|
||||
logger.debug("Launching stealth Chromium (headless=%s, args=%d)", headless, len(chrome_args))
|
||||
@@ -316,7 +317,7 @@ async def launch_async( # noqa: C901
|
||||
if exit_ip and not (args and any(a.startswith("--fingerprint-webrtc-ip") for a in args)):
|
||||
args = list(args or [])
|
||||
args.append(f"--fingerprint-webrtc-ip={exit_ip}")
|
||||
chrome_args = build_args(stealth_args, (args or []) + proxy_extra_args, timezone=timezone, locale=locale, headless=headless, extension_paths=extension_paths)
|
||||
chrome_args = build_args(stealth_args, (args or []) + proxy_extra_args, timezone=timezone, locale=locale, headless=headless, extension_paths=extension_paths, start_maximized=binary_supports_maximized_window(license_key, browser_version))
|
||||
_maybe_warn_windows_fonts(chrome_args)
|
||||
|
||||
logger.debug("Launching stealth Chromium async (headless=%s, args=%d)", headless, len(chrome_args))
|
||||
@@ -434,7 +435,7 @@ def launch_persistent_context(
|
||||
if exit_ip and not (args and any(a.startswith("--fingerprint-webrtc-ip") for a in args)):
|
||||
args = list(args or [])
|
||||
args.append(f"--fingerprint-webrtc-ip={exit_ip}")
|
||||
chrome_args = build_args(stealth_args, (args or []) + proxy_extra_args, timezone=timezone, locale=locale, headless=headless, extension_paths=extension_paths)
|
||||
chrome_args = build_args(stealth_args, (args or []) + proxy_extra_args, timezone=timezone, locale=locale, headless=headless, extension_paths=extension_paths, start_maximized=binary_supports_maximized_window(license_key, browser_version) and viewport is _VIEWPORT_UNSET and "viewport" not in kwargs and "no_viewport" not in kwargs)
|
||||
_maybe_warn_windows_fonts(chrome_args)
|
||||
|
||||
logger.debug(
|
||||
@@ -573,7 +574,7 @@ async def launch_persistent_context_async(
|
||||
if exit_ip and not (args and any(a.startswith("--fingerprint-webrtc-ip") for a in args)):
|
||||
args = list(args or [])
|
||||
args.append(f"--fingerprint-webrtc-ip={exit_ip}")
|
||||
chrome_args = build_args(stealth_args, (args or []) + proxy_extra_args, timezone=timezone, locale=locale, headless=headless, extension_paths=extension_paths)
|
||||
chrome_args = build_args(stealth_args, (args or []) + proxy_extra_args, timezone=timezone, locale=locale, headless=headless, extension_paths=extension_paths, start_maximized=binary_supports_maximized_window(license_key, browser_version) and viewport is _VIEWPORT_UNSET and "viewport" not in kwargs and "no_viewport" not in kwargs)
|
||||
_maybe_warn_windows_fonts(chrome_args)
|
||||
|
||||
logger.debug(
|
||||
@@ -1079,6 +1080,7 @@ def build_args(
|
||||
locale: str | None = None,
|
||||
headless: bool = True,
|
||||
extension_paths: list[str] | None = None,
|
||||
start_maximized: bool = False,
|
||||
) -> list[str]:
|
||||
"""Combine stealth args with user-provided args and locale flags.
|
||||
|
||||
@@ -1125,12 +1127,22 @@ def build_args(
|
||||
if extension_paths:
|
||||
abs_paths = [os.path.abspath(p) for p in extension_paths]
|
||||
ext_val = ",".join(abs_paths)
|
||||
|
||||
|
||||
seen["--load-extension"] = f"--load-extension={ext_val}"
|
||||
seen["--disable-extensions-except"] = (
|
||||
f"--disable-extensions-except={ext_val}"
|
||||
)
|
||||
|
||||
# Open maximized (real Windows Chrome overwhelmingly runs maximized) so the
|
||||
# window fills the spoofed screen. Skipped if the caller already chose a
|
||||
# window geometry. Gated to binaries where this stays coherent (see
|
||||
# binary_supports_maximized_window) — below the gate it would create
|
||||
# outerWidth < innerWidth.
|
||||
if start_maximized and not any(
|
||||
k in seen for k in ("--start-maximized", "--window-size", "--window-position")
|
||||
):
|
||||
seen["--start-maximized"] = "--start-maximized"
|
||||
|
||||
return list(seen.values())
|
||||
|
||||
|
||||
|
||||
@@ -336,3 +336,19 @@ def binary_supports_headless_no_viewport(
|
||||
return not _version_newer(HEADLESS_NO_VIEWPORT_MIN_VERSION, version)
|
||||
except (ValueError, AttributeError):
|
||||
return False
|
||||
|
||||
|
||||
def binary_supports_maximized_window(
|
||||
license_key: str | None = None, browser_version: str | None = None
|
||||
) -> bool:
|
||||
"""Whether the wrapper may auto-add ``--start-maximized``.
|
||||
|
||||
Gated on the same threshold as the no_viewport shim: only binaries whose
|
||||
headless surface-fix + headed screen-clamp make a maximized window coherent
|
||||
(``outer == screen``). Below it, maximizing headless while the CDP viewport
|
||||
stays at 1280x720 yields ``outerWidth < innerWidth`` — an impossible-window
|
||||
bot tell — so the flag must NOT be added. Shares
|
||||
``HEADLESS_NO_VIEWPORT_MIN_VERSION``; kept as its own name so the two can
|
||||
diverge later. Python, JS and .NET mirror this gate.
|
||||
"""
|
||||
return binary_supports_headless_no_viewport(license_key, browser_version)
|
||||
|
||||
@@ -32,7 +32,8 @@ public static class CloakLauncher
|
||||
|
||||
var combined = new List<string>(args ?? new List<string>());
|
||||
combined.AddRange(proxyResolution.ExtraArgs);
|
||||
var chromeArgs = BuildArgs(options.StealthArgs, combined, timezone, locale, options.Headless, options.ExtensionPaths);
|
||||
var chromeArgs = BuildArgs(options.StealthArgs, combined, timezone, locale, options.Headless, options.ExtensionPaths,
|
||||
startMaximized: Config.BinarySupportsMaximizedWindow(options.LicenseKey, options.BrowserVersion));
|
||||
MaybeWarnWindowsFonts(chromeArgs);
|
||||
|
||||
CloakLog.Debug($"Launching stealth Chromium (headless={options.Headless}, args={chromeArgs.Count})");
|
||||
@@ -137,7 +138,9 @@ public static class CloakLauncher
|
||||
|
||||
var combined = new List<string>(args ?? new List<string>());
|
||||
combined.AddRange(proxyResolution.ExtraArgs);
|
||||
var chromeArgs = BuildArgs(options.StealthArgs, combined, timezone, locale, options.Headless, options.ExtensionPaths);
|
||||
var chromeArgs = BuildArgs(options.StealthArgs, combined, timezone, locale, options.Headless, options.ExtensionPaths,
|
||||
startMaximized: Config.BinarySupportsMaximizedWindow(options.LicenseKey, options.BrowserVersion)
|
||||
&& !options.NoViewport && options.Viewport == null);
|
||||
MaybeWarnWindowsFonts(chromeArgs);
|
||||
|
||||
CloakLog.Debug($"Launching persistent stealth Chromium (headless={options.Headless}, user_data_dir={userDataDir})");
|
||||
@@ -274,7 +277,8 @@ public static class CloakLauncher
|
||||
string? timezone = null,
|
||||
string? locale = null,
|
||||
bool headless = true,
|
||||
List<string>? extensionPaths = null)
|
||||
List<string>? extensionPaths = null,
|
||||
bool startMaximized = false)
|
||||
{
|
||||
// Preserve insertion order while deduping by key.
|
||||
var seen = new Dictionary<string, string>();
|
||||
@@ -322,6 +326,18 @@ public static class CloakLauncher
|
||||
Set("--disable-extensions-except", $"--disable-extensions-except={extVal}");
|
||||
}
|
||||
|
||||
// Open maximized (real Chrome overwhelmingly runs maximized) so the window
|
||||
// fills the spoofed screen. Skipped if the caller chose a window geometry.
|
||||
// Gated to binaries where this stays coherent (see BinarySupportsMaximizedWindow)
|
||||
// — below the gate it would make outerWidth < innerWidth.
|
||||
if (startMaximized
|
||||
&& !seen.ContainsKey("--start-maximized")
|
||||
&& !seen.ContainsKey("--window-size")
|
||||
&& !seen.ContainsKey("--window-position"))
|
||||
{
|
||||
Set("--start-maximized", "--start-maximized");
|
||||
}
|
||||
|
||||
return order.Select(k => seen[k]).ToList();
|
||||
}
|
||||
|
||||
|
||||
@@ -426,4 +426,16 @@ public static class Config
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Whether the wrapper may auto-add <c>--start-maximized</c>. Gated on the same
|
||||
/// threshold as the no_viewport shim: only binaries whose headless surface-fix +
|
||||
/// headed screen-clamp make a maximized window coherent (<c>outer == screen</c>).
|
||||
/// Below it, maximizing headless while the CDP viewport stays at 1280x720 yields
|
||||
/// <c>outerWidth < innerWidth</c> — a bot tell — so the flag must NOT be added.
|
||||
/// Shares <see cref="HeadlessNoViewportMinVersion"/>; own name so the two can
|
||||
/// diverge later. Python, JS and .NET mirror this gate.
|
||||
/// </summary>
|
||||
public static bool BinarySupportsMaximizedWindow(string? licenseKey = null, string? browserVersion = null)
|
||||
=> BinarySupportsHeadlessNoViewport(licenseKey, browserVersion);
|
||||
}
|
||||
|
||||
@@ -73,4 +73,39 @@ public class BuildArgsTests
|
||||
Assert.DoesNotContain(args, a => a.StartsWith("--lang="));
|
||||
Assert.DoesNotContain(args, a => a.StartsWith("--fingerprint-timezone="));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void StartMaximized_True_AddsFlag()
|
||||
{
|
||||
var args = CloakLauncher.BuildArgs(stealthArgs: true, extraArgs: null, startMaximized: true);
|
||||
Assert.Contains("--start-maximized", args);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void StartMaximized_DefaultOff_NoFlag()
|
||||
{
|
||||
var args = CloakLauncher.BuildArgs(stealthArgs: true, extraArgs: null);
|
||||
Assert.DoesNotContain("--start-maximized", args);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void StartMaximized_SuppressedByUserWindowSize()
|
||||
{
|
||||
var args = CloakLauncher.BuildArgs(
|
||||
stealthArgs: true,
|
||||
extraArgs: new List<string> { "--window-size=1000,800" },
|
||||
startMaximized: true);
|
||||
Assert.DoesNotContain("--start-maximized", args);
|
||||
Assert.Contains("--window-size=1000,800", args);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void StartMaximized_NotDoubled()
|
||||
{
|
||||
var args = CloakLauncher.BuildArgs(
|
||||
stealthArgs: true,
|
||||
extraArgs: new List<string> { "--start-maximized" },
|
||||
startMaximized: true);
|
||||
Assert.Single(args, a => a == "--start-maximized");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -238,3 +238,28 @@ public class HeadlessNoViewportGateTests
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// BinarySupportsMaximizedWindow() — parity-critical: Python and JS mirror this gate.
|
||||
/// Shares the no_viewport threshold today.
|
||||
/// </summary>
|
||||
public class MaximizedWindowGateTests
|
||||
{
|
||||
[Fact]
|
||||
public void DeclaredBelowThreshold_Off()
|
||||
{
|
||||
Assert.False(Config.BinarySupportsMaximizedWindow(browserVersion: "148.0.7778.215.3"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DeclaredAtThreshold_On()
|
||||
{
|
||||
Assert.True(Config.BinarySupportsMaximizedWindow(browserVersion: "148.0.7778.215.4"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DeclaredAboveThreshold_On()
|
||||
{
|
||||
Assert.True(Config.BinarySupportsMaximizedWindow(browserVersion: "149.0.0.0"));
|
||||
}
|
||||
}
|
||||
|
||||
+22
-1
@@ -3,7 +3,7 @@
|
||||
*/
|
||||
import path from "path";
|
||||
import type { LaunchOptions } from "./types.js";
|
||||
import { getDefaultStealthArgs } from "./config.js";
|
||||
import { getDefaultStealthArgs, binarySupportsMaximizedWindow } from "./config.js";
|
||||
|
||||
const DEBUG = /\bcloakbrowser\b/.test(process.env.DEBUG ?? "");
|
||||
|
||||
@@ -66,5 +66,26 @@ export function buildArgs(options: LaunchOptions): string[] {
|
||||
`--disable-extensions-except=${joined}`
|
||||
);
|
||||
}
|
||||
|
||||
// Open maximized (real Chrome overwhelmingly runs maximized) so the window
|
||||
// fills the spoofed screen. Skipped if the caller chose a window geometry or an
|
||||
// explicit viewport (Playwright `viewport` / Puppeteer `defaultViewport`).
|
||||
// Gated to binaries where this stays coherent (see binarySupportsMaximizedWindow)
|
||||
// — below the gate it would make outerWidth < innerWidth.
|
||||
// viewport lives on LaunchContextOptions; present at runtime for the
|
||||
// persistent-context path, absent for plain launch. Read defensively.
|
||||
const explicitViewport =
|
||||
(options as { viewport?: unknown }).viewport !== undefined ||
|
||||
options.launchOptions?.defaultViewport !== undefined;
|
||||
const hasWindowFlag = ["--start-maximized", "--window-size", "--window-position"].some(
|
||||
k => seen.has(k)
|
||||
);
|
||||
if (
|
||||
!explicitViewport &&
|
||||
!hasWindowFlag &&
|
||||
binarySupportsMaximizedWindow(options.licenseKey, options.browserVersion)
|
||||
) {
|
||||
seen.set("--start-maximized", "--start-maximized");
|
||||
}
|
||||
return [...seen.values()];
|
||||
}
|
||||
|
||||
@@ -290,6 +290,22 @@ export function binarySupportsHeadlessNoViewport(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the wrapper may auto-add `--start-maximized`. Gated on the same
|
||||
* threshold as the no_viewport shim: only binaries whose headless surface-fix +
|
||||
* headed screen-clamp make a maximized window coherent (`outer == screen`).
|
||||
* Below it, maximizing headless while the CDP viewport stays at 1280x720 yields
|
||||
* `outerWidth < innerWidth` — a bot tell — so the flag must NOT be added. Shares
|
||||
* HEADLESS_NO_VIEWPORT_MIN_VERSION; own name so the two can diverge later.
|
||||
* Python, JS and .NET mirror this gate.
|
||||
*/
|
||||
export function binarySupportsMaximizedWindow(
|
||||
licenseKey?: string,
|
||||
browserVersion?: string,
|
||||
): boolean {
|
||||
return binarySupportsHeadlessNoViewport(licenseKey, browserVersion);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Playwright default args to suppress — these leak automation signals.
|
||||
// --enable-automation: exposes navigator.webdriver = true
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
getFallbackDownloadUrl,
|
||||
normalizeRequestedVersion,
|
||||
binarySupportsHeadlessNoViewport,
|
||||
binarySupportsMaximizedWindow,
|
||||
} from "../src/config.js";
|
||||
import { _buildArgsForTest, resolveTimezone } from "../src/playwright.js";
|
||||
|
||||
@@ -299,3 +300,50 @@ describe("binarySupportsHeadlessNoViewport", () => {
|
||||
expect(binarySupportsHeadlessNoViewport(undefined, "not.a.version")).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("binarySupportsMaximizedWindow", () => {
|
||||
// Parity-critical: Python and .NET mirror this gate. Shares the no_viewport
|
||||
// threshold today.
|
||||
it("is OFF one build below the threshold", () => {
|
||||
expect(binarySupportsMaximizedWindow(undefined, "148.0.7778.215.3")).toBe(false);
|
||||
});
|
||||
it("is ON at the threshold", () => {
|
||||
expect(binarySupportsMaximizedWindow(undefined, "148.0.7778.215.4")).toBe(true);
|
||||
});
|
||||
it("is ON above the threshold", () => {
|
||||
expect(binarySupportsMaximizedWindow(undefined, "149.0.0.0")).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe("buildArgs --start-maximized", () => {
|
||||
it("adds --start-maximized when the binary is gated ON", () => {
|
||||
const args = _buildArgsForTest({ browserVersion: "148.0.7778.215.4" });
|
||||
expect(args).toContain("--start-maximized");
|
||||
});
|
||||
it("does not add it below the gate", () => {
|
||||
const args = _buildArgsForTest({ browserVersion: "148.0.7778.215.3" });
|
||||
expect(args).not.toContain("--start-maximized");
|
||||
});
|
||||
it("is suppressed by a user --window-size", () => {
|
||||
const args = _buildArgsForTest({
|
||||
browserVersion: "148.0.7778.215.4",
|
||||
args: ["--window-size=1000,800"],
|
||||
});
|
||||
expect(args).not.toContain("--start-maximized");
|
||||
expect(args).toContain("--window-size=1000,800");
|
||||
});
|
||||
it("is suppressed by an explicit viewport", () => {
|
||||
const args = _buildArgsForTest({
|
||||
browserVersion: "148.0.7778.215.4",
|
||||
viewport: { width: 800, height: 600 },
|
||||
} as Parameters<typeof _buildArgsForTest>[0]);
|
||||
expect(args).not.toContain("--start-maximized");
|
||||
});
|
||||
it("does not double a user-supplied --start-maximized", () => {
|
||||
const args = _buildArgsForTest({
|
||||
browserVersion: "148.0.7778.215.4",
|
||||
args: ["--start-maximized"],
|
||||
});
|
||||
expect(args.filter(a => a === "--start-maximized")).toHaveLength(1);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -199,3 +199,34 @@ def test_resolve_webrtc_args_no_flag():
|
||||
|
||||
result = _resolve_webrtc_args(["--no-sandbox"], "http://proxy:8080")
|
||||
assert result == ["--no-sandbox"]
|
||||
|
||||
|
||||
def test_start_maximized_injected_when_gated():
|
||||
"""start_maximized=True adds the flag."""
|
||||
args = build_args(stealth_args=True, extra_args=None, start_maximized=True)
|
||||
assert "--start-maximized" in args
|
||||
|
||||
|
||||
def test_start_maximized_absent_by_default():
|
||||
"""Default (gate off) does not add the flag."""
|
||||
args = build_args(stealth_args=True, extra_args=None)
|
||||
assert "--start-maximized" not in args
|
||||
args = build_args(stealth_args=True, extra_args=None, start_maximized=False)
|
||||
assert "--start-maximized" not in args
|
||||
|
||||
|
||||
def test_start_maximized_suppressed_by_user_window_size():
|
||||
"""A user --window-size means the user chose a geometry; don't also maximize."""
|
||||
args = build_args(
|
||||
stealth_args=True, extra_args=["--window-size=1000,800"], start_maximized=True
|
||||
)
|
||||
assert "--start-maximized" not in args
|
||||
assert "--window-size=1000,800" in args
|
||||
|
||||
|
||||
def test_start_maximized_not_doubled():
|
||||
"""A user-supplied --start-maximized is not duplicated."""
|
||||
args = build_args(
|
||||
stealth_args=True, extra_args=["--start-maximized"], start_maximized=True
|
||||
)
|
||||
assert args.count("--start-maximized") == 1
|
||||
|
||||
@@ -7,6 +7,7 @@ import pytest
|
||||
|
||||
from cloakbrowser.config import (
|
||||
binary_supports_headless_no_viewport,
|
||||
binary_supports_maximized_window,
|
||||
get_archive_ext,
|
||||
get_archive_name,
|
||||
get_binary_path,
|
||||
@@ -215,3 +216,25 @@ class TestHeadlessNoViewportGate:
|
||||
os.environ.pop("CLOAKBROWSER_LICENSE_KEY", None)
|
||||
os.environ.pop("CLOAKBROWSER_VERSION", None)
|
||||
assert binary_supports_headless_no_viewport() is False
|
||||
|
||||
|
||||
class TestMaximizedWindowGate:
|
||||
"""binary_supports_maximized_window() — parity-critical: JS and .NET mirror this.
|
||||
|
||||
Shares HEADLESS_NO_VIEWPORT_MIN_VERSION today, so it tracks the same threshold
|
||||
as the no_viewport gate: below it, auto --start-maximized would make headless
|
||||
report outerWidth < innerWidth (a bot tell), so the flag must stay off.
|
||||
"""
|
||||
|
||||
def test_declared_below_threshold_off(self):
|
||||
assert binary_supports_maximized_window(browser_version="148.0.7778.215.3") is False
|
||||
|
||||
def test_declared_at_threshold_on(self):
|
||||
assert binary_supports_maximized_window(browser_version="148.0.7778.215.4") is True
|
||||
|
||||
def test_declared_above_threshold_on(self):
|
||||
assert binary_supports_maximized_window(browser_version="149.0.0.0") is True
|
||||
|
||||
def test_local_override_without_declared_off(self):
|
||||
with patch.dict(os.environ, {"CLOAKBROWSER_BINARY_PATH": "/fake/chrome"}):
|
||||
assert binary_supports_maximized_window() is False
|
||||
|
||||
Reference in New Issue
Block a user