|
| 1 | +"""A caller's own binary is never replaced -- but it should still be checked. |
| 2 | +
|
| 3 | +A managed install below the floor gets upgraded by pkgman. `executable_path` |
| 4 | +deliberately bypasses that, which leaves one pairing nothing checks: an old |
| 5 | +build driven by Playwright >= 1.61, whose viewport fields the older Juggler |
| 6 | +schema rejects. Without this the user sees a bare "Protocol error |
| 7 | +(Browser.setDefaultViewport)" and nothing naming the cause. |
| 8 | +
|
| 9 | +It warns rather than raises on purpose: camoufox defaults to no_viewport when |
| 10 | +it spoofs window dimensions, so the default path works on an old build. Only an |
| 11 | +explicit viewport breaks, so refusing to launch would break working setups. |
| 12 | +""" |
| 13 | + |
| 14 | +import json |
| 15 | + |
| 16 | +import pytest |
| 17 | + |
| 18 | +from camoufox import pkgman, utils |
| 19 | + |
| 20 | + |
| 21 | +def _bundle(tmp_path, build): |
| 22 | + """A browser directory with version.json beside the binary, as a release has.""" |
| 23 | + d = tmp_path / f"152.0.4-{build}" |
| 24 | + d.mkdir() |
| 25 | + (d / "version.json").write_text(json.dumps({"version": "152.0.4", "build": build})) |
| 26 | + return d / "camoufox-bin" |
| 27 | + |
| 28 | + |
| 29 | +@pytest.fixture |
| 30 | +def floor_at_beta30(monkeypatch): |
| 31 | + monkeypatch.setattr(utils, "effective_version_min", lambda: pkgman.Version(build="beta.30")) |
| 32 | + |
| 33 | + |
| 34 | +def test_warns_when_the_supplied_build_is_too_old(tmp_path, floor_at_beta30): |
| 35 | + exe = _bundle(tmp_path, "beta.29") |
| 36 | + |
| 37 | + with pytest.warns(RuntimeWarning, match=r"beta\.29.*beta\.30"): |
| 38 | + utils.warn_if_executable_predates_playwright(exe) |
| 39 | + |
| 40 | + |
| 41 | +def test_names_the_symptom_the_user_will_actually_see(tmp_path, floor_at_beta30): |
| 42 | + exe = _bundle(tmp_path, "beta.29") |
| 43 | + |
| 44 | + with pytest.warns(RuntimeWarning) as caught: |
| 45 | + utils.warn_if_executable_predates_playwright(exe) |
| 46 | + |
| 47 | + assert "Browser.setDefaultViewport" in str(caught[0].message) |
| 48 | + |
| 49 | + |
| 50 | +@pytest.mark.parametrize("build", ["beta.30", "beta.31"]) |
| 51 | +def test_silent_when_the_build_is_new_enough(tmp_path, floor_at_beta30, build, recwarn): |
| 52 | + utils.warn_if_executable_predates_playwright(_bundle(tmp_path, build)) |
| 53 | + |
| 54 | + assert not [w for w in recwarn if issubclass(w.category, RuntimeWarning)] |
| 55 | + |
| 56 | + |
| 57 | +def test_silent_for_a_custom_build_with_no_version_json(tmp_path, floor_at_beta30, recwarn): |
| 58 | + """An unpackaged objdir build tells us nothing; do not nag about it.""" |
| 59 | + (tmp_path / "dist").mkdir() |
| 60 | + |
| 61 | + utils.warn_if_executable_predates_playwright(tmp_path / "dist" / "camoufox-bin") |
| 62 | + |
| 63 | + assert not [w for w in recwarn if issubclass(w.category, RuntimeWarning)] |
| 64 | + |
| 65 | + |
| 66 | +def test_silent_when_no_executable_path_was_given(floor_at_beta30, recwarn): |
| 67 | + utils.warn_if_executable_predates_playwright(None) |
| 68 | + |
| 69 | + assert not [w for w in recwarn if issubclass(w.category, RuntimeWarning)] |
0 commit comments