mirror of
https://github.com/feder-cr/invisible_playwright.git
synced 2026-07-04 10:52:24 +02:00
Split pure-config into invisible-core; keep back-compat shims
The seed->fingerprint->prefs logic, binary download, and proxy/geo config now live in a standalone invisible-core package (zero Playwright), so a profile manager can reuse it without pulling Playwright in. The wrapper depends on invisible-core and replaces the moved modules with full-alias shims: existing imports (public API, submodules, private names) and isinstance checks keep working unchanged. tests/test_backcompat.py locks that contract (6 guards). Bumps to 0.3.0.
This commit is contained in:
parent
d434ee4059
commit
76e41e2789
36 changed files with 136 additions and 11109 deletions
84
tests/test_backcompat.py
Normal file
84
tests/test_backcompat.py
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
"""Backward-compatibility guard for the invisible_core / invisible_playwright split.
|
||||
|
||||
After extracting the pure config into ``invisible_core`` and turning the moved
|
||||
modules into aliasing shims, EVERY import path that external users (and our own
|
||||
outreach PRs) rely on must keep working — same objects, same behavior. This test
|
||||
is the contract: if it breaks, we broke someone's install.
|
||||
"""
|
||||
import importlib
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_top_level_public_api_imports():
|
||||
import invisible_playwright as ip
|
||||
for name in [
|
||||
"InvisiblePlaywright", "ensure_binary", "ensure_geoip_mmdb",
|
||||
"get_default_stealth_prefs", "get_default_args",
|
||||
"resolve_session_timezone", "GeoTimezoneError",
|
||||
"BINARY_VERSION", "FIREFOX_UPSTREAM_VERSION", "__version__",
|
||||
]:
|
||||
assert hasattr(ip, name), f"invisible_playwright.{name} missing"
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_submodule_imports_external_users_rely_on():
|
||||
# These are the exact import shapes used in the wild + in our Skyvern/onyx/etc PRs.
|
||||
from invisible_playwright._fpforge import generate_profile, Profile # noqa: F401
|
||||
from invisible_playwright._webgl_personas import forced_gpu_class # noqa: F401
|
||||
from invisible_playwright.prefs import translate_profile_to_prefs # noqa: F401
|
||||
from invisible_playwright.download import ensure_binary # noqa: F401
|
||||
from invisible_playwright.constants import BINARY_VERSION # noqa: F401
|
||||
from invisible_playwright.config import get_default_stealth_prefs # noqa: F401
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_deep_submodule_and_private_names_still_import():
|
||||
from invisible_playwright._fpforge.profile import Profile # noqa: F401
|
||||
from invisible_playwright._fpforge import _sampler # noqa: F401
|
||||
from invisible_playwright.prefs import _BASELINE # noqa: F401
|
||||
assert isinstance(_BASELINE, dict)
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_class_identity_is_shared_with_core():
|
||||
# isinstance must hold: the object returned by generate_profile must be an
|
||||
# instance of BOTH the invisible_playwright-path Profile and the core Profile
|
||||
# (they must be the SAME class object, not duplicates).
|
||||
from invisible_playwright._fpforge import generate_profile
|
||||
from invisible_playwright._fpforge import Profile as PW_Profile
|
||||
from invisible_playwright._fpforge.profile import Profile as PW_Profile2
|
||||
import invisible_core
|
||||
from invisible_core import Profile as Core_Profile
|
||||
|
||||
p = generate_profile(seed=42)
|
||||
assert isinstance(p, PW_Profile)
|
||||
assert isinstance(p, PW_Profile2)
|
||||
assert isinstance(p, Core_Profile)
|
||||
assert PW_Profile is Core_Profile
|
||||
assert PW_Profile2 is Core_Profile
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_shim_output_matches_core_output():
|
||||
from invisible_playwright._fpforge import generate_profile as gp_pw
|
||||
from invisible_playwright._webgl_personas import forced_gpu_class as fgc_pw
|
||||
from invisible_playwright.prefs import translate_profile_to_prefs as tp_pw
|
||||
import invisible_core as ic
|
||||
|
||||
a = tp_pw(gp_pw(42, fixed_gpu_class=fgc_pw(42)))
|
||||
b = ic.translate_profile_to_prefs(ic.generate_profile(42, fixed_gpu_class=ic.forced_gpu_class(42)))
|
||||
assert a == b
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_core_imports_without_playwright(monkeypatch):
|
||||
# invisible_core must be importable even if playwright is absent. We simulate
|
||||
# by asserting the core modules never pulled playwright into sys.modules as a
|
||||
# side effect of their own import (the wrapper may have, but core must not need it).
|
||||
import sys
|
||||
import invisible_core # noqa: F401
|
||||
# invisible_core itself must not hard-depend on playwright at import time.
|
||||
core_file = importlib.import_module("invisible_core").__file__
|
||||
assert "invisible_core" in core_file
|
||||
Loading…
Add table
Add a link
Reference in a new issue