import pytest from nisse_dev.gates import Approved, Gate, Ignored, PlanRevision, Rejected REVISION = PlanRevision(gate="arch", rev=2, content="the plan") OPERATORS = {"don"} def gate() -> Gate: return Gate(REVISION, OPERATORS) def test_bare_approve_binds_to_current_revision() -> None: result = gate().evaluate("don", "approve", channel="transport") assert isinstance(result, Approved) assert result.revision.tag == "rev-2" assert result.approver == "don" def test_tagged_approve_matching_current_revision() -> None: result = gate().evaluate("don", "approve rev-2", channel="gitea") assert isinstance(result, Approved) assert result.channel == "gitea" def test_stale_revision_tag_is_ignored_with_notice() -> None: result = gate().evaluate("don", "approve rev-1", channel="transport") assert isinstance(result, Ignored) assert result.notice is not None assert "rev-1" in result.notice assert "rev-2" in result.notice def test_any_other_reply_is_rejection_with_feedback() -> None: result = gate().evaluate("don", "too vague, split milestone 1", "transport") assert isinstance(result, Rejected) assert result.feedback == "too vague, split milestone 1" def test_unknown_sender_is_silently_ignored() -> None: result = gate().evaluate("mallory", "approve", channel="transport") assert isinstance(result, Ignored) assert result.notice is None def test_approve_with_trailing_words_is_rejection() -> None: # "approve, but rename the module" is feedback, not approval (A4: the # typed word approve, nothing else). result = gate().evaluate("don", "approve, but rename the module", "transport") assert isinstance(result, Rejected) @pytest.mark.parametrize( "text", ["Approve", "APPROVE", "Approve.", "approve!", " Approve rev-2 "] ) def test_approval_ignores_case_and_trailing_punctuation(text: str) -> None: # A phone keyboard's "Approve" used to count as rejection feedback (#64). assert isinstance(gate().evaluate("don", text, channel="transport"), Approved) def test_a_capitalised_stale_approval_is_still_refused() -> None: result = gate().evaluate("don", "Approve REV-1", channel="transport") assert isinstance(result, Ignored) def test_a_sentence_containing_approve_is_still_feedback() -> None: result = gate().evaluate("don", "I approve of most of it", channel="transport") assert isinstance(result, Rejected) assert result.feedback == "I approve of most of it"