mirror of
https://github.com/kuhyx/utils.git
synced 2026-11-10 21:07:15 +01:00
Some checks are pending
dependency freshness / dependencies on newest stable (push) Waiting to run
file length / file-length (push) Waiting to run
md-naming / markdown naming convention (push) Waiting to run
palette drift / palette (push) Waiting to run
repo-contract / repo contract (push) Waiting to run
shared gate tests / gate unit tests (push) Waiting to run
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
141 lines
5.0 KiB
Python
141 lines
5.0 KiB
Python
"""Tests for the SessionStart task summary."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
import time
|
|
from typing import TYPE_CHECKING
|
|
|
|
from todo_hooks import __main__ as cli
|
|
from todo_hooks.tests._fakes import TOKEN, FakeMcp, line
|
|
|
|
if TYPE_CHECKING:
|
|
from collections.abc import Callable
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
ORIGIN = "git@github.com:kuhyx/demo.git"
|
|
|
|
|
|
def _rows(count: int) -> str:
|
|
return "\n".join(
|
|
line(f"{i:08x}-x", "kuhyx/demo", f"# Task {i}") for i in range(count)
|
|
)
|
|
|
|
|
|
def _env(mcp: FakeMcp) -> dict[str, str]:
|
|
return {"TODO_MCP_URL": mcp.url, "TODO_MCP_TOKEN": TOKEN}
|
|
|
|
|
|
def _stdin(cwd: Path) -> str:
|
|
return json.dumps({"cwd": str(cwd), "hook_event_name": "SessionStart"})
|
|
|
|
|
|
def test_prints_header_and_tasks(
|
|
mcp: FakeMcp, make_repo: Callable[..., Path], capsys: pytest.CaptureFixture[str]
|
|
) -> None:
|
|
root = make_repo("demo", origin=ORIGIN)
|
|
seen: list[dict[str, object]] = []
|
|
mcp.tools["list_tasks"] = lambda a: seen.append(a) or _rows(2)
|
|
assert cli.main(["session-start"], env=_env(mcp), stdin=_stdin(root)) == 0
|
|
assert capsys.readouterr().out.splitlines() == [
|
|
"Open todo tasks for kuhyx/demo (2):",
|
|
"- 00000000 Task 0",
|
|
"- 00000001 Task 1",
|
|
]
|
|
assert seen == [{"repo": "kuhyx/demo", "status": "open"}]
|
|
|
|
|
|
def test_nine_tasks_fit_ten_lines(
|
|
mcp: FakeMcp, make_repo: Callable[..., Path], capsys: pytest.CaptureFixture[str]
|
|
) -> None:
|
|
root = make_repo("demo", origin=ORIGIN)
|
|
mcp.tools["list_tasks"] = lambda _a: _rows(9)
|
|
cli.main(["session-start"], env=_env(mcp), stdin=_stdin(root))
|
|
assert len(capsys.readouterr().out.splitlines()) == 10
|
|
|
|
|
|
def test_more_than_nine_is_truncated(
|
|
mcp: FakeMcp, make_repo: Callable[..., Path], capsys: pytest.CaptureFixture[str]
|
|
) -> None:
|
|
root = make_repo("demo", origin=ORIGIN)
|
|
mcp.tools["list_tasks"] = lambda _a: _rows(15)
|
|
cli.main(["session-start"], env=_env(mcp), stdin=_stdin(root))
|
|
lines = capsys.readouterr().out.splitlines()
|
|
assert len(lines) == 10
|
|
assert lines[0] == "Open todo tasks for kuhyx/demo (15):"
|
|
assert lines[-1] == '… +7 more: list_tasks(repo="kuhyx/demo")'
|
|
|
|
|
|
def test_no_tasks_prints_nothing(
|
|
mcp: FakeMcp, make_repo: Callable[..., Path], capsys: pytest.CaptureFixture[str]
|
|
) -> None:
|
|
root = make_repo("demo", origin=ORIGIN)
|
|
mcp.tools["list_tasks"] = lambda _a: "no tasks match"
|
|
assert cli.main(["session-start"], env=_env(mcp), stdin=_stdin(root)) == 0
|
|
assert capsys.readouterr().out == ""
|
|
|
|
|
|
def test_cwd_fallback_when_stdin_is_not_json(
|
|
mcp: FakeMcp, make_repo: Callable[..., Path], capsys: pytest.CaptureFixture[str]
|
|
) -> None:
|
|
root = make_repo("demo", origin=ORIGIN)
|
|
mcp.tools["list_tasks"] = lambda _a: _rows(1)
|
|
cli.main(["session-start"], env=_env(mcp), cwd=root, stdin="not json")
|
|
assert "kuhyx/demo" in capsys.readouterr().out
|
|
cli.main(["session-start"], env=_env(mcp), cwd=root, stdin="[1]")
|
|
assert "kuhyx/demo" in capsys.readouterr().out
|
|
cli.main(["session-start"], env=_env(mcp), cwd=root, stdin="{}")
|
|
assert "kuhyx/demo" in capsys.readouterr().out
|
|
|
|
|
|
def test_silent_without_git_or_origin(
|
|
mcp: FakeMcp,
|
|
make_repo: Callable[..., Path],
|
|
tmp_path: Path,
|
|
capsys: pytest.CaptureFixture[str],
|
|
) -> None:
|
|
mcp.tools["list_tasks"] = lambda _a: _rows(1)
|
|
plain = tmp_path / "plain"
|
|
plain.mkdir()
|
|
assert cli.main(["session-start"], env=_env(mcp), stdin=_stdin(plain)) == 0
|
|
local = make_repo("local")
|
|
assert cli.main(["session-start"], env=_env(mcp), stdin=_stdin(local)) == 0
|
|
assert capsys.readouterr().out == ""
|
|
assert mcp.requests == []
|
|
|
|
|
|
def test_silent_when_server_down_or_token_bad(
|
|
mcp: FakeMcp, make_repo: Callable[..., Path], capsys: pytest.CaptureFixture[str]
|
|
) -> None:
|
|
root = make_repo("demo", origin=ORIGIN)
|
|
bad = {**_env(mcp), "TODO_MCP_TOKEN": "wrong"}
|
|
assert cli.main(["session-start"], env=bad, stdin=_stdin(root)) == 0
|
|
dead = {**_env(mcp), "TODO_MCP_URL": "http://127.0.0.1:1/mcp"}
|
|
assert cli.main(["session-start"], env=dead, stdin=_stdin(root)) == 0
|
|
no_token = {"TODO_MCP_URL": mcp.url, "TODO_MCP_TOKEN_FILE": "/nonexistent"}
|
|
assert cli.main(["session-start"], env=no_token, stdin=_stdin(root)) == 0
|
|
assert capsys.readouterr().out == ""
|
|
|
|
|
|
def test_silent_on_unexpected_error(
|
|
mcp: FakeMcp, make_repo: Callable[..., Path], capsys: pytest.CaptureFixture[str]
|
|
) -> None:
|
|
root = make_repo("demo", origin=ORIGIN)
|
|
mcp.mode = "garbage"
|
|
assert cli.main(["session-start"], env=_env(mcp), stdin=_stdin(root)) == 0
|
|
assert capsys.readouterr().out == ""
|
|
|
|
|
|
def test_slow_server_stays_within_budget(
|
|
mcp: FakeMcp, make_repo: Callable[..., Path], capsys: pytest.CaptureFixture[str]
|
|
) -> None:
|
|
root = make_repo("demo", origin=ORIGIN)
|
|
mcp.delay = 3.0
|
|
mcp.tools["list_tasks"] = lambda _a: _rows(1)
|
|
start = time.monotonic()
|
|
assert cli.main(["session-start"], env=_env(mcp), stdin=_stdin(root)) == 0
|
|
assert time.monotonic() - start < 1.6
|
|
assert capsys.readouterr().out == ""
|