Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014Typ5sXWNMFirr2va2uL8o
155 lines
8.5 KiB
Python
155 lines
8.5 KiB
Python
import unittest
|
||
|
||
from _common import SETTINGS, agent, jira_cfg, no_sleep
|
||
from fake_hub import FakeHub
|
||
from fake_jira import FakeJira
|
||
|
||
|
||
class RefreshTest(unittest.TestCase):
|
||
def setUp(self):
|
||
self.fake = FakeJira()
|
||
self.hub = FakeHub(SETTINGS)
|
||
cfg = jira_cfg(self.fake, hub_url=self.hub.base_url, hub_token=self.hub.token)
|
||
self.jira = agent.JiraClient(cfg)
|
||
self.jira.sleep = no_sleep
|
||
self.ex = agent.Executor(self.jira, dict(SETTINGS), agent.HubClient(cfg))
|
||
self.ex.sleep = no_sleep
|
||
|
||
def tearDown(self):
|
||
self.fake.stop()
|
||
self.hub.stop()
|
||
|
||
def test_to_state_and_links(self):
|
||
self.fake.add("AURORA-1", assignee="ivanov", customfield_10801="2026-10-20T00:00:00.000+0300",
|
||
customfield_15302="AURORA-1350", labels=["AWPCA", "kind-dev"], sprint="Спринт 2")
|
||
self.fake.add("AURORA-2")
|
||
self.fake.links.append({"id": 1, "type": "ASUPR_Блокер_Начала", "source": "AURORA-1", "target": "AURORA-2"})
|
||
raw = self.fake.issue_json("AURORA-1")
|
||
st = self.ex.to_state(raw)
|
||
self.assertEqual(st["key"], "AURORA-1")
|
||
self.assertEqual(st["assignee"], "ivanov")
|
||
self.assertEqual(st["planned_start"], "2026-10-20")
|
||
self.assertEqual(st["epic_key"], "AURORA-1350")
|
||
self.assertEqual(st["labels"], ["AWPCA", "kind-dev"])
|
||
self.assertEqual(st["issue_type"], "Задача")
|
||
self.assertEqual(st["jira_updated"], "2026-10-01T10:00:00.000+0300")
|
||
self.assertIsNone(st["sprint"]) # спринт заполняет do_refresh
|
||
self.assertEqual(self.ex.links_from(raw), [{"source_key": "AURORA-1", "target_key": "AURORA-2", "link_type": "ASUPR_Блокер_Начала"}])
|
||
self.assertEqual(self.ex.links_from(self.fake.issue_json("AURORA-2")),
|
||
[{"source_key": "AURORA-1", "target_key": "AURORA-2", "link_type": "ASUPR_Блокер_Начала"}])
|
||
self.assertIn("customfield_15302", self.ex.state_fields())
|
||
|
||
def test_full_refresh_with_neighbors_and_sprints(self):
|
||
for i in range(1, 4):
|
||
self.fake.add("AURORA-%d" % i, sprint="Спринт 2" if i < 3 else None)
|
||
self.fake.add("OTHER-9", in_base=False)
|
||
self.fake.add("AURORA-7", in_base=False)
|
||
self.fake.links.append({"id": 1, "type": "ASUPR_Связанные", "source": "AURORA-1", "target": "OTHER-9"})
|
||
self.fake.links.append({"id": 2, "type": "ASUPR_Связанные", "source": "AURORA-7", "target": "AURORA-2"})
|
||
self.hub.known = ["AURORA-7"]
|
||
out = self.ex.run({"id": 5, "type": "refresh", "params": {"jql": "project = AURORA AND labels = AWPCA"}})
|
||
self.assertEqual(out["status"], "done")
|
||
self.assertEqual(out["result"], {"issues": 3, "neighbors": 1, "pages": 1})
|
||
state = self.hub.states[0]
|
||
self.assertEqual(state["command_id"], 5)
|
||
self.assertEqual(sorted(i["key"] for i in state["issues"]), ["AURORA-1", "AURORA-2", "AURORA-3", "OTHER-9"])
|
||
self.assertEqual(state["neighbor_keys"], ["OTHER-9"])
|
||
self.assertTrue(state["last_page"])
|
||
sprints = {i["key"]: i["sprint"] for i in state["issues"]}
|
||
self.assertEqual(sprints["AURORA-1"], "Спринт 2")
|
||
self.assertIsNone(sprints["AURORA-3"])
|
||
links = {(l["source_key"], l["target_key"]) for l in state["links"]}
|
||
self.assertEqual(links, {("AURORA-1", "OTHER-9"), ("AURORA-7", "AURORA-2")})
|
||
searches = [r for r in self.fake.requests if r[1] == "/rest/api/2/search"]
|
||
self.assertEqual(len(searches), 2) # базовая выборка + дочитывание соседей
|
||
|
||
def test_refresh_by_keys_pages(self):
|
||
for i in range(1, 121):
|
||
self.fake.add("AURORA-%d" % i)
|
||
keys = ["AURORA-%d" % i for i in range(1, 121)]
|
||
out = self.ex.run({"id": 6, "type": "refresh", "params": {"keys": keys}})
|
||
self.assertEqual(out["result"], {"issues": 120, "neighbors": 0, "pages": 2})
|
||
self.assertEqual(len(self.hub.states), 2)
|
||
self.assertEqual(self.hub.states[0]["page"], 1)
|
||
self.assertFalse(self.hub.states[0]["last_page"])
|
||
self.assertTrue(self.hub.states[1]["last_page"])
|
||
self.assertEqual(len(self.hub.states[0]["issues"]) + len(self.hub.states[1]["issues"]), 120)
|
||
|
||
def test_refresh_empty_keys(self):
|
||
out = self.ex.run({"id": 7, "type": "refresh", "params": {"keys": []}})
|
||
self.assertEqual(out["result"], {"issues": 0, "neighbors": 0, "pages": 0})
|
||
self.assertEqual(self.fake.requests, [])
|
||
self.assertEqual(self.hub.states, [])
|
||
|
||
def test_refresh_empty_jql_result(self):
|
||
out = self.ex.run({"id": 8, "type": "refresh", "params": {"jql": "project = AURORA AND labels = AWPCA"}})
|
||
self.assertEqual(out["status"], "done")
|
||
self.assertEqual(out["result"], {"issues": 0, "neighbors": 0, "pages": 0})
|
||
self.assertEqual(self.hub.states, [])
|
||
|
||
def test_keys_with_deleted_key(self):
|
||
for i in (1, 2, 3, 4):
|
||
self.fake.add("AURORA-%d" % i)
|
||
out = self.ex.run({"id": 9, "type": "refresh",
|
||
"params": {"keys": ["AURORA-1", "AURORA-2", "AURORA-99", "AURORA-3", "AURORA-98"]}})
|
||
self.assertEqual(out["status"], "done")
|
||
self.assertEqual(out["result"], {"issues": 3, "neighbors": 0, "pages": 1, "missing": ["AURORA-98", "AURORA-99"]})
|
||
self.assertEqual(sorted(i["key"] for i in self.hub.states[0]["issues"]), ["AURORA-1", "AURORA-2", "AURORA-3"])
|
||
|
||
def test_deleted_neighbor(self):
|
||
self.fake.add("AURORA-1")
|
||
self.fake.add("AURORA-2", in_base=False)
|
||
self.fake.links.append({"id": 1, "type": "ASUPR_Связанные", "source": "AURORA-1", "target": "GONE-1"})
|
||
self.fake.links.append({"id": 2, "type": "ASUPR_Связанные", "source": "AURORA-1", "target": "AURORA-2"})
|
||
out = self.ex.run({"id": 10, "type": "refresh", "params": {"jql": "project = AURORA AND labels = AWPCA"}})
|
||
self.assertEqual(out["status"], "done")
|
||
self.assertEqual(out["result"], {"issues": 1, "neighbors": 1, "pages": 1, "missing": ["GONE-1"]})
|
||
self.assertEqual(self.hub.states[0]["neighbor_keys"], ["AURORA-2"])
|
||
|
||
def test_non_400_error_fails(self):
|
||
self.fake.add("AURORA-1")
|
||
|
||
def boom(jql):
|
||
raise agent.HttpError(500, "oops")
|
||
self.ex.search_all = boom
|
||
out = self.ex.run({"id": 11, "type": "refresh", "params": {"keys": ["AURORA-1"]}})
|
||
self.assertEqual(out["status"], "failed")
|
||
self.assertIn("500", out["error"])
|
||
|
||
def test_link_visible_from_both_ends_deduped(self):
|
||
self.fake.add("AURORA-1")
|
||
self.fake.add("AURORA-2")
|
||
self.fake.links.append({"id": 1, "type": "ASUPR_Связанные", "source": "AURORA-1", "target": "AURORA-2"})
|
||
self.ex.run({"id": 12, "type": "refresh", "params": {"keys": ["AURORA-1", "AURORA-2"]}})
|
||
self.assertEqual(len(self.hub.states[0]["links"]), 1)
|
||
|
||
def test_many_neighbors_several_requests(self):
|
||
self.fake.add("AURORA-1")
|
||
for i in range(1, 151):
|
||
self.fake.add("NB-%d" % i, in_base=False)
|
||
self.fake.links.append({"id": i, "type": "ASUPR_Связанные", "source": "AURORA-1", "target": "NB-%d" % i})
|
||
out = self.ex.run({"id": 13, "type": "refresh", "params": {"jql": "project = AURORA AND labels = AWPCA"}})
|
||
self.assertEqual(out["result"], {"issues": 1, "neighbors": 150, "pages": 2})
|
||
searches = [r for r in self.fake.requests if r[1] == "/rest/api/2/search"]
|
||
self.assertEqual(len(searches), 1 + 2) # база + два чанка соседей
|
||
|
||
def test_sprint_names_paginated(self):
|
||
for i in range(1, 121):
|
||
self.fake.add("AURORA-%d" % i, sprint="Спринт 2")
|
||
names = self.ex.sprint_names(["AURORA-%d" % i for i in range(1, 101)])
|
||
self.assertEqual(len(names), 100)
|
||
pages = [r for r in self.fake.requests if r[1] == "/rest/agile/1.0/sprint/2/issue"]
|
||
self.assertEqual(len(pages), 2)
|
||
|
||
def test_fake_hub_terminal_result_not_overwritten(self):
|
||
cid = self.hub.enqueue("refresh", {"keys": []})
|
||
hub = agent.HubClient(jira_cfg(self.fake, hub_url=self.hub.base_url, hub_token=self.hub.token))
|
||
hub.result(cid, {"status": "done", "result": {"a": 1}})
|
||
hub.result(cid, {"status": "failed", "error": "x"})
|
||
self.assertEqual(self.hub.commands[cid]["status"], "done")
|
||
self.assertEqual(self.hub.results[cid]["status"], "done")
|
||
|
||
|
||
if __name__ == "__main__":
|
||
unittest.main()
|