| 1 | import sys |
| 2 | |
| 3 | from plugins._context_doctor import hooks |
| 4 | from plugins._context_doctor.extensions.python.startup_migration import ( |
| 5 | _20_context_doctor_runtime as startup_runtime, |
| 6 | ) |
| 7 | |
| 8 | |
| 9 | def test_dependency_check_requires_root_pinned_version(monkeypatch): |
| 10 | requirement = hooks._json_repair_requirement() |
| 11 | expected_version = requirement.partition("==")[2] |
| 12 | |
| 13 | monkeypatch.setattr(hooks.importlib.util, "find_spec", lambda _name: object()) |
| 14 | monkeypatch.setattr( |
| 15 | hooks.importlib.metadata, "version", lambda _name: expected_version |
| 16 | ) |
| 17 | assert hooks._json_repair_is_current(requirement) |
| 18 | |
| 19 | monkeypatch.setattr( |
| 20 | hooks.importlib.metadata, "version", lambda _name: f"{expected_version}.stale" |
| 21 | ) |
| 22 | assert not hooks._json_repair_is_current(requirement) |
| 23 | |
| 24 | |
| 25 | def test_dependency_hook_installs_root_pinned_requirement(monkeypatch): |
| 26 | requirement = hooks._json_repair_requirement() |
| 27 | checks = iter((False, True)) |
| 28 | calls = [] |
| 29 | |
| 30 | monkeypatch.setattr( |
| 31 | hooks, "_json_repair_is_current", lambda _candidate: next(checks) |
| 32 | ) |
| 33 | monkeypatch.setattr(hooks.shutil, "which", lambda _command: "/usr/local/bin/uv") |
| 34 | monkeypatch.setattr( |
| 35 | hooks.subprocess, |
| 36 | "check_call", |
| 37 | lambda command, cwd: calls.append((command, cwd)), |
| 38 | ) |
| 39 | |
| 40 | assert requirement.startswith("json_repair==") |
| 41 | assert hooks.ensure_dependencies() |
| 42 | assert calls == [ |
| 43 | ( |
| 44 | [ |
| 45 | "/usr/local/bin/uv", |
| 46 | "pip", |
| 47 | "install", |
| 48 | "--python", |
| 49 | sys.executable, |
| 50 | requirement, |
| 51 | ], |
| 52 | str(hooks._PLUGIN_DIR), |
| 53 | ) |
| 54 | ] |
| 55 | |
| 56 | |
| 57 | def test_startup_migration_calls_dependency_hook(monkeypatch): |
| 58 | calls = [] |
| 59 | monkeypatch.setattr( |
| 60 | startup_runtime, |
| 61 | "call_plugin_hook", |
| 62 | lambda *args, **kwargs: calls.append((args, kwargs)), |
| 63 | ) |
| 64 | |
| 65 | startup_runtime.ContextDoctorRuntime(None).execute() |
| 66 | |
| 67 | assert calls == [ |
| 68 | (("_context_doctor", "ensure_dependencies"), {"raise_on_error": False}) |
| 69 | ] |