Files
unshackle/tests/core/test_service_remote_config.py
T

108 lines
4.5 KiB
Python

"""``services.<TAG>.dl`` ``remote`` and ``server`` route a service without ``--remote``. Explicit CLI values win."""
from __future__ import annotations
from typing import Any, Optional, cast
import click
import pytest
from unshackle.commands.dl import dl
from unshackle.commands.search import search
from unshackle.core.config import config
from unshackle.core.services import Services
def make_ctx(
command: click.Command, args: Optional[list[str]] = None, default_map: Optional[dict[str, Any]] = None
) -> click.Context:
"""Parse the group options of a real ``Services`` command, without running its callback."""
return command.make_context(
command.name or "dl", [*(args or []), "EXAMPLE", "title"], default_map=default_map or {}
)
def group(ctx: click.Context) -> Services:
return cast(Services, ctx.command)
@pytest.fixture
def routed(monkeypatch: pytest.MonkeyPatch) -> list[tuple[str, Optional[str]]]:
"""Record the path get_command takes and the server it passes, without loading a service or calling a server."""
calls: list[tuple[str, Optional[str]]] = []
def remote(name: str, server_name: Optional[str]) -> click.Command:
calls.append(("remote", server_name))
return click.Command(name)
def local(tag: str) -> Any:
calls.append(("local", None))
return type("FakeService", (), {"cli": click.Command(tag)})
monkeypatch.setattr(Services, "make_remote_command", staticmethod(remote))
monkeypatch.setattr(Services, "load", staticmethod(local))
return calls
@pytest.mark.parametrize("command", [dl.cli, search])
def test_service_remote_routes_to_remote_command(
monkeypatch: pytest.MonkeyPatch, routed: list[tuple[str, Optional[str]]], command: click.Command
) -> None:
"""The typed name matches the config key in any case, as a service only the server has keeps the typed case."""
monkeypatch.setattr(config, "services", {"EXAMPLE": {"dl": {"remote": True, "server": "box"}}})
ctx = make_ctx(command)
group(ctx).resolve_command(ctx, ["example", "title"])
assert routed == [("remote", "box")]
assert ctx.params["remote"] is True
assert ctx.params["server"] == "box"
@pytest.mark.parametrize(
("services", "args", "default_map", "expected"),
[
({"OTHER": {"dl": {"remote": True}}}, [], None, ("local", None)),
({"EXAMPLE": {"dl": {"remote": True, "server": "box"}}}, ["--server", "other"], None, ("remote", "other")),
({"EXAMPLE": {"dl": {"remote": False}}}, [], {"remote": True}, ("local", None)),
({"EXAMPLE": {"dl": {"remote": "false"}}}, [], None, ("local", None)),
({"EXAMPLE": {"dl": {"remote": True}}}, ["--local"], {"remote": True}, ("local", None)),
],
ids=["other-service", "cli-server-wins", "service-false-beats-global", "quoted-false-is-cast", "cli-local-wins"],
)
def test_routing_precedence(
monkeypatch: pytest.MonkeyPatch,
routed: list,
services: dict,
args: list[str],
default_map: Optional[dict[str, Any]],
expected: tuple[str, Optional[str]],
) -> None:
monkeypatch.setattr(config, "services", services)
ctx = make_ctx(dl.cli, args, default_map)
group(ctx).get_command(ctx, "EXAMPLE")
assert routed == [expected]
def test_invalid_value_names_the_config_key(monkeypatch: pytest.MonkeyPatch, routed: list) -> None:
monkeypatch.setattr(config, "services", {"EXAMPLE": {"dl": {"remote": "maybe"}}})
ctx = make_ctx(dl.cli)
with pytest.raises(click.ClickException, match=r"services\.EXAMPLE\.dl\.remote"):
group(ctx).get_command(ctx, "EXAMPLE")
def test_resolved_service_does_not_route_the_next(monkeypatch: pytest.MonkeyPatch, routed: list) -> None:
"""Help and shell completion call get_command for every service on the context that resolved one."""
monkeypatch.setattr(config, "services", {"EXAMPLE": {"dl": {"remote": True}}})
ctx = make_ctx(dl.cli)
group(ctx).resolve_command(ctx, ["EXAMPLE", "title"])
assert ctx.params["remote"] is True
group(ctx).get_command(ctx, "OTHER")
assert routed == [("remote", None), ("local", None)]
def test_import_ignores_service_remote(monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.setattr(config, "services", {"EXAMPLE": {"dl": {"remote": True}}})
monkeypatch.setattr(Services, "make_import_command", staticmethod(lambda tag, ctx: click.Command(tag)))
ctx = make_ctx(dl.cli, ["--import", "export.json"])
group(ctx).resolve_command(ctx, ["EXAMPLE", "title"])
assert ctx.params["remote"] is False