Skip to content
Merged
Show file tree
Hide file tree
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
46 changes: 46 additions & 0 deletions tests/test_write_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,49 @@ async def test_gh_failure_returns_check_gh_error():
with patch("ghplugin.write_tools.run_gh", fake):
out = await tool.ainvoke({"repo": "o/n", "title": "t"})
assert out == "Error (gh exit 1): could not create issue: forbidden"


def _comment():
return {t.name: t for t in get_write_tools()}["github_comment"]


async def test_comment_returns_comment_url():
"""On success the tool returns the new comment URL (gh's stdout, stripped)."""
tool = _comment()
fake = AsyncMock(return_value=(0, "https://github.com/o/n/issues/42#issuecomment-1\n", ""))
with patch("ghplugin.write_tools.run_gh", fake):
out = await tool.ainvoke({"repo": "o/n", "number": 42, "body": "Thanks!"})
assert out == "https://github.com/o/n/issues/42#issuecomment-1"
args = fake.call_args.args[0]
assert args[:5] == ["issue", "comment", "42", "--repo", "o/n"]
assert "--body" in args and args[args.index("--body") + 1] == "Thanks!"


async def test_comment_number_is_stringified():
"""The integer number is passed to gh as a string argument."""
tool = _comment()
fake = AsyncMock(return_value=(0, "https://github.com/o/n/issues/7#issuecomment-9", ""))
with patch("ghplugin.write_tools.run_gh", fake):
await tool.ainvoke({"repo": "o/n", "number": 7, "body": "hi"})
args = fake.call_args.args[0]
assert args[2] == "7"


async def test_comment_bad_repo_short_circuits():
"""An invalid repo returns the bad_repo error and never shells out."""
tool = _comment()
fake = AsyncMock()
with patch("ghplugin.write_tools.run_gh", fake):
out = await tool.ainvoke({"repo": "not-a-repo", "number": 1, "body": "hi"})
assert out.startswith("Error:")
assert "owner/name" in out
fake.assert_not_called()


async def test_comment_gh_failure_returns_check_gh_error():
"""A nonzero gh exit becomes a readable Error string (via check_gh_error)."""
tool = _comment()
fake = AsyncMock(return_value=(1, "", "could not comment: forbidden"))
with patch("ghplugin.write_tools.run_gh", fake):
out = await tool.ainvoke({"repo": "o/n", "number": 1, "body": "hi"})
assert out == "Error (gh exit 1): could not comment: forbidden"
8 changes: 6 additions & 2 deletions write_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,15 @@ async def github_comment(repo: str, number: int, body: str) -> str:
number: Issue or PR number (a PR is an issue for commenting).
body: The comment body (Markdown).

TODO(team): implement via `gh issue comment {number} --repo {repo} --body ...`.
Returns the new comment URL.
"""
if err := bad_repo(repo):
return err
return "Error: github_comment is not implemented yet (stub — to be built by the team)."
args = ["issue", "comment", str(number), "--repo", repo, "--body", body]
rc, out, serr = await run_gh(args)
if gh_err := check_gh_error(rc, serr):
return gh_err
return out.strip()

@tool
async def github_create_pr(repo: str, head: str, title: str, body: str = "", base: str = "main") -> str:
Expand Down
Loading