Files

96 lines
3.8 KiB
Python
Raw Permalink Normal View History

"""Conflicted PRs become card state: the poller folds GitHub's
mergeable field into the PR snapshot, a conflict drops any
approved-green verdict as changes-needed-by-you (not a CI failure),
and GitHub's lazily-computed UNKNOWN keeps the previous reading so the
chip never flaps. The snapshot's `conflicts` key must reach the UI."""
import sys
import unittest
from pathlib import Path
REPO = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(REPO / "manager" / "core"))
import github # noqa: E402
def payload(**overrides):
"""A gh pr-view JSON payload with the fields _fold reads."""
data = {"reviews": [], "reviewRequests": [], "statusCheckRollup": []}
data.update(overrides)
return data
APPROVED = [{"state": "APPROVED"}]
class ConflictFolding(unittest.TestCase):
def test_conflict_drops_green_even_when_approved(self):
entry = github._fold(payload(reviews=APPROVED,
mergeable="CONFLICTING"), {})
self.assertTrue(entry["conflicts"])
self.assertEqual(entry["verdict"], "red")
self.assertIn("conflicts with main", entry["detail"])
def test_conflict_is_not_a_ci_failure(self):
entry = github._fold(payload(mergeable="CONFLICTING"), {})
self.assertIsNone(entry["ci"])
self.assertEqual(entry["verdict"], "red")
def test_mergeable_approved_pr_stays_green(self):
entry = github._fold(payload(reviews=APPROVED,
mergeable="MERGEABLE"), {})
self.assertFalse(entry["conflicts"])
self.assertEqual(entry["verdict"], "green")
def test_unknown_keeps_the_previous_reading_both_ways(self):
# GitHub computes mergeability lazily after a push: UNKNOWN means
# "not yet", never "fine" — the chip must not flap.
still = github._fold(payload(mergeable="UNKNOWN"),
{"conflicts": True})
self.assertTrue(still["conflicts"])
self.assertEqual(still["verdict"], "red")
clean = github._fold(payload(reviews=APPROVED, mergeable="UNKNOWN"),
{"conflicts": False})
self.assertFalse(clean["conflicts"])
self.assertEqual(clean["verdict"], "green")
def test_unknown_on_first_sight_alarms_nobody(self):
entry = github._fold(payload(mergeable="UNKNOWN"), {})
self.assertIsNone(entry["conflicts"])
self.assertEqual(entry["verdict"], "pending")
self.assertNotIn("conflicts", entry["detail"])
def test_resolution_lets_green_return(self):
entry = github._fold(payload(reviews=APPROVED, mergeable="MERGEABLE"),
{"conflicts": True, "verdict": "red"})
self.assertFalse(entry["conflicts"])
self.assertEqual(entry["verdict"], "green")
class SnapshotReachesTheUI(unittest.TestCase):
def test_public_state_carries_conflicts(self):
github.PR_STATE["x.md"] = {"verdict": "red", "ci": None,
"copilot": None, "conflicts": True,
"detail": "conflicts with main",
"url": "u", "ts": 1}
try:
self.assertTrue(github.public_state()["x.md"]["conflicts"])
finally:
github.PR_STATE.pop("x.md", None)
def test_the_card_wears_an_alarm_coloured_chip(self):
html = (REPO / "manager" / "core" / "board.html").read_text(
encoding="utf-8")
self.assertIn("prState.conflicts", html)
self.assertIn("label: 'conflicts', glyph: '✕', cls: 'bad'", html)
def test_poller_asks_github_for_mergeable(self):
source = (REPO / "manager" / "core" / "github.py").read_text(
encoding="utf-8")
self.assertIn("statusCheckRollup,state,mergeable", source)
if __name__ == "__main__":
unittest.main()