Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 26 additions & 5 deletions tests/test_url_copy.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from __future__ import annotations

import io
from typing import cast

import pytest
from rich.console import Console
Expand All @@ -15,6 +16,18 @@ def _console() -> Console:
return Console(file=io.StringIO(), force_terminal=True, width=80)


def _output(console: Console) -> str:
"""Everything a ``_console()`` was asked to print.

Rich declares ``Console.file`` as ``IO[str]``, which has no ``getvalue``,
so reading the buffer straight off the console is a type error (`ty`). The
cast narrows it back to the ``StringIO`` ``_console`` put there -- the same
idiom ``tests/test_output.py`` uses at its 23 read sites. Wrapped in a
helper here only because this file reads the buffer from several tests.
"""
return cast(io.StringIO, console.file).getvalue()


class _Recorder:
def __init__(self) -> None:
self.copied: list[str] = []
Expand Down Expand Up @@ -50,7 +63,13 @@ def test_detect_clipboard_linux_prefers_wl_copy(monkeypatch: pytest.MonkeyPatch)
assert detect_clipboard() is not None


def test_disabled_without_backend() -> None:
def test_disabled_without_backend(monkeypatch: pytest.MonkeyPatch) -> None:
# `copier=None` means "detect one", NOT "there is none" (_url_copy.py:123),
# so the no-backend case has to be staged by making detection fail. Without
# this the test passes only on a machine with no clipboard command -- i.e.
# a bare CI container -- and fails for every developer on macOS (`pbcopy`
# is always there), Windows, WSL, or a Linux desktop.
monkeypatch.setattr(_url_copy, "detect_clipboard", lambda: None)
wait = CopyableUrlWait(_console(), copier=None, interactive=True)
assert wait.enabled is False

Expand All @@ -64,14 +83,16 @@ def test_on_prompt_prints_hint_when_enabled() -> None:
console = _console()
wait = CopyableUrlWait(console, copier=_Recorder(), interactive=True)
wait.on_prompt("https://example.com/x")
assert "Press c to copy the link" in console.file.getvalue()
assert "Press c to copy the link" in _output(console)


def test_on_prompt_silent_when_disabled() -> None:
def test_on_prompt_silent_when_disabled(monkeypatch: pytest.MonkeyPatch) -> None:
# Same staging as test_disabled_without_backend: no detectable backend.
monkeypatch.setattr(_url_copy, "detect_clipboard", lambda: None)
console = _console()
wait = CopyableUrlWait(console, copier=None, interactive=True)
wait.on_prompt("https://example.com/x")
assert console.file.getvalue() == ""
assert _output(console) == ""


def test_wait_copies_on_c_keypress(monkeypatch: pytest.MonkeyPatch) -> None:
Expand All @@ -83,7 +104,7 @@ def test_wait_copies_on_c_keypress(monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.setattr(wait, "_read_key", lambda _timeout: next(keys, None))
wait.wait(0.01)
assert rec.copied == ["https://example.com/x"]
assert "Copied to clipboard" in console.file.getvalue()
assert "Copied to clipboard" in _output(console)


def test_wait_copies_only_once(monkeypatch: pytest.MonkeyPatch) -> None:
Expand Down