import json import pytest from agentci.workflows.model import ( AgentResult, ReviewFinding, ReviewReport, ReviewSeverity, ) from agentci.workflows.render import ( agent_comment, commit_title, final_comment, pull_request_body, report_for_prompt, required_session, result_comment, review_markdown, ) def report() -> ReviewReport: return ReviewReport( summary="One issue remains.", findings=[ ReviewFinding( severity=ReviewSeverity.MAJOR, title="Missing validation", detail="The empty input is not checked.", location="src/widget.py:12", recommendation="Reject empty input.", ) ], ) def test_review_markdown_renders_user_visible_finding() -> None: assert review_markdown(report()) == ( "## Remaining review findings\n\n" "One issue remains.\n\n" "### MAJOR: Missing validation \u2014 `src/widget.py:12`\n" "The empty input is not checked.\n\n" "Recommendation: Reject empty input." ) assert review_markdown(ReviewReport(summary="Ready", findings=[])) == "" def test_agent_and_final_comments_preserve_protocol_marker() -> None: assert agent_comment("plan", "flow-1", "Plan body") == ( "\nPlan body" ) assert final_comment("plan", "flow-1", "Plan body", report()) == ( f"\nPlan body\n\n{review_markdown(report())}" ) assert ( final_comment("plan", "flow-1", "Plan body", ReviewReport(summary="Ready", findings=[])) == "\nPlan body" ) def test_pull_request_body_and_result_comment_render_validation() -> None: result = AgentResult( summary_markdown="Implemented the widget fix.", tests=["pytest: passed", "ruff: passed"], ) assert pull_request_body(17, result) == ( "Closes #17\n\n" "## Implementation\n\nImplemented the widget fix.\n\n" "## Validation\n\n- pytest: passed\n- ruff: passed\n\n" "_Created by Agent CI._" ) assert result_comment(result, sha="abc123") == ( "## Agent result\n\nImplemented the widget fix.\n\n" "## Validation\n\n- pytest: passed\n- ruff: passed\n\n" "Commit: `abc123`" ) def test_renderers_report_missing_validation() -> None: result = AgentResult(summary_markdown="Applied the change.", tests=[]) assert "## Validation\n\n- Not reported" in pull_request_body(2, result) assert result_comment(result) == ( "## Agent result\n\nApplied the change.\n\n## Validation\n\n- Not reported" ) @pytest.mark.parametrize( ("markdown", "expected"), [ ("# Fix widget\n\nDetails", "Fix widget"), ("\n## Trim heading \n", "Trim heading"), ("\n\t\n", "apply requested changes"), ("x" * 80, "x" * 72), ], ) def test_commit_title_uses_first_content_line(markdown: str, expected: str) -> None: assert commit_title(markdown) == expected def test_report_for_prompt_formats_json_and_preserves_unstructured_text() -> None: stored = '{"summary":"Ready","findings":[]}' formatted = report_for_prompt(stored) assert json.loads(formatted) == {"summary": "Ready", "findings": []} assert formatted == '{\n "summary": "Ready",\n "findings": []\n}' assert report_for_prompt("plain text review") == "plain text review" assert report_for_prompt(None) == "(none)" def test_required_session_returns_value_or_fails_fast() -> None: assert required_session("session-1") == "session-1" with pytest.raises(RuntimeError, match="Expected a persisted OpenCode session ID"): required_session(None)