fix(tests): fix veto bug preventing disputed state, add manager notification and dispute-resolution routing

This commit is contained in:
kitos
2026-07-06 12:40:05 +02:00
parent 388c9773ab
commit f53e124c50
7 changed files with 448 additions and 8 deletions
+81 -2
View File
@@ -414,7 +414,7 @@ def test_dual_validation_blue_rejects_first(mock_log):
@patch("app.services.test_workflow_service.log_action")
def test_dual_validation_red_approves_blue_rejects(mock_log):
"""Red approves, then blue rejects -> rejected."""
"""Red approves, then blue rejects -> genuine conflict -> disputed."""
test = _make_test(TestState.in_review)
red_lead = _make_user("red_lead")
blue_lead = _make_user("blue_lead")
@@ -424,7 +424,7 @@ def test_dual_validation_red_approves_blue_rejects(mock_log):
assert test.state == TestState.in_review # waiting for blue
validate_as_blue_lead(db, test, blue_lead, "rejected", "Bad detection")
assert test.state == TestState.rejected
assert test.state == TestState.disputed
# ===========================================================================
@@ -687,6 +687,85 @@ class TestReviewDecisions:
assert result.system_gaps == "Missing EDR agent on host X"
# ===========================================================================
# 12c. resolve_dispute — flip approver's vote to reject, route to a team
# ===========================================================================
class TestResolveDispute:
@patch("app.services.test_workflow_service.log_action")
def test_red_lead_approver_flips_to_red_queue(self, mock_log):
test = _make_test(
TestState.disputed,
red_validation_status="approved",
blue_validation_status="rejected",
)
red_lead = _make_user("red_lead")
db = _make_db()
from app.services.test_workflow_service import resolve_dispute
result = resolve_dispute(db, test, red_lead, "red", notes="redo the attack")
assert result.state == TestState.red_executing
assert result.red_validation_status is None
assert result.blue_validation_status is None
@patch("app.services.test_workflow_service.log_action")
def test_blue_lead_approver_flips_to_blue_queue(self, mock_log):
test = _make_test(
TestState.disputed,
blue_validation_status="approved",
red_validation_status="rejected",
)
blue_lead = _make_user("blue_lead")
db = _make_db()
from app.services.test_workflow_service import resolve_dispute
result = resolve_dispute(db, test, blue_lead, "blue")
assert result.state == TestState.blue_evaluating
def test_non_approver_cannot_resolve_dispute(self):
test = _make_test(
TestState.disputed,
red_validation_status="rejected",
blue_validation_status="approved",
)
red_lead = _make_user("red_lead") # red_lead REJECTED, didn't approve
db = _make_db()
from app.services.test_workflow_service import resolve_dispute
with pytest.raises(InvalidOperationError):
resolve_dispute(db, test, red_lead, "red")
def test_invalid_target_team_rejected(self):
test = _make_test(
TestState.disputed,
red_validation_status="approved",
blue_validation_status="rejected",
)
red_lead = _make_user("red_lead")
db = _make_db()
from app.services.test_workflow_service import resolve_dispute
with pytest.raises(InvalidOperationError):
resolve_dispute(db, test, red_lead, "purple")
@patch("app.services.test_workflow_service.log_action")
def test_admin_can_resolve_dispute_regardless_of_vote(self, mock_log):
test = _make_test(
TestState.disputed,
red_validation_status="approved",
blue_validation_status="rejected",
)
admin = _make_user("admin")
db = _make_db()
from app.services.test_workflow_service import resolve_dispute
result = resolve_dispute(db, test, admin, "red")
assert result.state == TestState.red_executing
# ===========================================================================
# 13. select_reviewer — load-balanced reviewer assignment
# ===========================================================================