123 lines
4.0 KiB
Python
123 lines
4.0 KiB
Python
from pathlib import Path
|
|
|
|
import playwright.sync_api as playwright_sync
|
|
|
|
import auth_login
|
|
from auth_login import BrowserRuntime, resolve_selection_chrome_profile
|
|
|
|
REPO_ROOT = Path(__file__).resolve().parents[2]
|
|
|
|
|
|
def _is_relative_to(path: Path, root: Path) -> bool:
|
|
try:
|
|
path.resolve().relative_to(root.resolve())
|
|
except ValueError:
|
|
return False
|
|
return True
|
|
|
|
|
|
def test_default_chrome_profile_is_outside_repo_selection_subdir(monkeypatch):
|
|
monkeypatch.delenv("RPA_SELECTION_CHROME_PROFILE", raising=False)
|
|
monkeypatch.delenv("RPA_CHROME_PROFILE", raising=False)
|
|
profile = resolve_selection_chrome_profile(repo_root=REPO_ROOT)
|
|
assert profile == (REPO_ROOT.parent / "rpa-chrome-profile" / "selection").resolve()
|
|
assert not _is_relative_to(profile, REPO_ROOT)
|
|
|
|
|
|
def test_env_path_inside_repo_is_rejected(monkeypatch):
|
|
inside = REPO_ROOT / "rpa_selection" / "data" / "chrome-profile"
|
|
monkeypatch.delenv("RPA_CHROME_PROFILE", raising=False)
|
|
profile = resolve_selection_chrome_profile(requested=str(inside), repo_root=REPO_ROOT)
|
|
assert profile == (REPO_ROOT.parent / "rpa-chrome-profile" / "selection").resolve()
|
|
assert not _is_relative_to(profile, REPO_ROOT)
|
|
|
|
|
|
def test_env_path_outside_repo_is_kept(tmp_path):
|
|
outside = tmp_path / "custom-chrome"
|
|
outside.mkdir()
|
|
profile = resolve_selection_chrome_profile(requested=str(outside), repo_root=REPO_ROOT)
|
|
assert profile == outside.resolve()
|
|
|
|
|
|
def test_rpa_chrome_profile_uses_selection_subdir(monkeypatch, tmp_path):
|
|
base = tmp_path / "work-profile"
|
|
monkeypatch.delenv("RPA_SELECTION_CHROME_PROFILE", raising=False)
|
|
monkeypatch.setenv("RPA_CHROME_PROFILE", str(base))
|
|
profile = resolve_selection_chrome_profile(repo_root=REPO_ROOT)
|
|
assert profile == (base / "selection").resolve()
|
|
|
|
|
|
class _FakePage:
|
|
url = "about:blank"
|
|
|
|
def bring_to_front(self) -> None:
|
|
return None
|
|
|
|
|
|
class _FakeContext:
|
|
def __init__(self) -> None:
|
|
self.pages = [_FakePage()]
|
|
self.closed = False
|
|
self.new_page_calls = 0
|
|
|
|
def new_page(self) -> _FakePage:
|
|
self.new_page_calls += 1
|
|
page = _FakePage()
|
|
self.pages.append(page)
|
|
return page
|
|
|
|
def close(self) -> None:
|
|
self.closed = True
|
|
|
|
|
|
class _FakeChromium:
|
|
def __init__(self) -> None:
|
|
self.persistent_calls: list[tuple[str, dict]] = []
|
|
self.launch_calls: list[dict] = []
|
|
self.context = _FakeContext()
|
|
|
|
def launch_persistent_context(self, user_data_dir: str, **kwargs):
|
|
self.persistent_calls.append((user_data_dir, kwargs))
|
|
return self.context
|
|
|
|
def launch(self, **kwargs):
|
|
self.launch_calls.append(kwargs)
|
|
raise AssertionError("选品登录必须复用用户目录,禁止 launch 空 Chrome")
|
|
|
|
|
|
class _FakePlaywright:
|
|
def __init__(self, chromium: _FakeChromium) -> None:
|
|
self.chromium = chromium
|
|
|
|
def start(self) -> "_FakePlaywright":
|
|
return self
|
|
|
|
def stop(self) -> None:
|
|
return None
|
|
|
|
|
|
def test_browser_runtime_reuses_persistent_profile(monkeypatch, tmp_path):
|
|
profile = tmp_path / "selection-profile"
|
|
monkeypatch.setenv("RPA_SELECTION_CHROME_PROFILE", str(profile))
|
|
chromium = _FakeChromium()
|
|
fake = _FakePlaywright(chromium)
|
|
monkeypatch.setattr(playwright_sync, "sync_playwright", lambda: fake)
|
|
|
|
runtime = BrowserRuntime(keep=False)
|
|
ctx1, page1 = runtime.new_page()
|
|
ctx2, page2 = runtime.new_page()
|
|
|
|
assert chromium.launch_calls == []
|
|
assert len(chromium.persistent_calls) == 1
|
|
user_data_dir, kwargs = chromium.persistent_calls[0]
|
|
assert user_data_dir == str(profile.resolve())
|
|
assert kwargs.get("channel") == "chrome"
|
|
assert "--disable-blink-features=AutomationControlled" in kwargs.get("args", [])
|
|
assert ctx1 is ctx2 is chromium.context
|
|
assert page1 is not page2
|
|
assert chromium.context.new_page_calls == 1
|
|
|
|
runtime.close()
|
|
assert chromium.context.closed
|
|
assert auth_login.resolve_selection_chrome_profile() == profile.resolve()
|