import unittest from datetime import datetime from _common import SETTINGS, agent, jira_cfg, no_sleep from fake_jira import FakeJira B = {"board_id": 4216} class ExecutorSprintsTest(unittest.TestCase): def setUp(self): self.fake = FakeJira() self.jira = agent.JiraClient(jira_cfg(self.fake)) self.jira.sleep = no_sleep self.ex = agent.Executor(self.jira, dict(SETTINGS)) self.gaps = [] self.ex.sleep = self.gaps.append self.fake.add("AURORA-1") def tearDown(self): self.fake.stop() def run_cmd(self, ctype, **params): return self.ex.run({"id": 1, "type": ctype, "params": params}) # --- ensure_sprint_meta --- def test_meta_create_then_repeat(self): # сценарий «Создание спринта повтором не дублируется» self.fake.board_sprints[4216] = [{"id": 3, "name": "AWPCA_Sprint_3_Corrections", "state": "active"}] params = dict(B, sprint="AWPCA_Sprint_4", start_date="2026-10-28", end_date="2026-11-11", goal="свод ВГО") out = self.run_cmd("ensure_sprint_meta", **params) self.assertEqual(out["status"], "done", out) sid = out["result"]["sprint_id"] self.assertEqual(out["result"], {"sprint_id": sid, "created": True}) sp = self.fake.board_sprints[4216][-1] off = datetime.now().astimezone().strftime("%z") self.assertEqual((sp["id"], sp["name"], sp["state"], sp["originBoardId"], sp["goal"]), (sid, "AWPCA_Sprint_4", "future", 4216, "свод ВГО")) self.assertEqual((sp["startDate"], sp["endDate"]), ("2026-10-28T09:00:00.000" + off, "2026-11-11T18:00:00.000" + off)) again = self.run_cmd("ensure_sprint_meta", **params) self.assertEqual(again["result"], {"sprint_id": sid, "created": False}) self.assertEqual(len(self.fake.writes()), 1) def test_meta_updates_only_diff(self): # даты совпадают по дню, отличается цель self.fake.board_sprints[4216] = [{"id": 9, "name": "S", "state": "future", "goal": "старая", "startDate": "2026-10-28T10:00:00.000+03:00", "endDate": "2026-11-11T19:00:00.000+03:00"}] out = self.run_cmd("ensure_sprint_meta", sprint="S", start_date="2026-10-28", end_date="2026-11-11", goal="новая", **B) self.assertEqual(out["result"], {"sprint_id": 9, "created": False}) self.assertEqual(self.fake.sprint_posts, [("/rest/agile/1.0/sprint/9", {"goal": "новая"})]) def test_meta_rename_and_name_taken(self): # S → T: POST {"name": "T"}; есть S и T — «имя занято», без записи self.fake.board_sprints[4216] = [{"id": 9, "name": "S", "state": "future"}] out = self.run_cmd("ensure_sprint_meta", sprint="S", rename_to="T", **B) self.assertEqual(out["result"], {"sprint_id": 9, "created": False}) self.assertEqual(self.fake.sprint_posts, [("/rest/agile/1.0/sprint/9", {"name": "T"})]) self.fake.sprint_posts, self.fake.requests = [], [] self.fake.board_sprints[4216] = [{"id": 9, "name": "S", "state": "future"}, {"id": 10, "name": "T", "state": "future"}] out = self.run_cmd("ensure_sprint_meta", sprint="S", rename_to="T", **B) self.assertEqual(out["status"], "failed") self.assertIn("занято", out["error"]) self.assertEqual(self.fake.writes(), []) def test_meta_repeat_after_rename(self): # Review Focus 3, R-69 self.fake.board_sprints[4216] = [{"id": 9, "name": "T", "state": "future"}] out = self.run_cmd("ensure_sprint_meta", sprint="S", rename_to="T", **B) self.assertEqual(out["result"], {"sprint_id": 9, "created": False}) self.assertEqual(self.fake.writes(), []) def test_meta_closed_and_duplicates(self): self.fake.board_sprints[4216] = [{"id": 1, "name": "C", "state": "closed"}, {"id": 5, "name": "D", "state": "future"}, {"id": 6, "name": "D", "state": "active"}] self.assertEqual(self.run_cmd("ensure_sprint_meta", sprint="C", goal="x", **B)["error"], "спринт закрыт") self.assertEqual(self.run_cmd("ensure_sprint_meta", sprint="D", **B)["error"], "несколько спринтов с именем «D»: 5, 6") self.assertEqual(self.fake.writes(), []) def test_meta_bad_date(self): # Review Focus 5 for bad in ("28.10.2026", "2026-13-01"): out = self.run_cmd("ensure_sprint_meta", sprint="N", start_date=bad, **B) self.assertEqual(out["status"], "failed") self.assertIn("ГГГГ-ММ-ДД", out["error"]) self.assertEqual(self.fake.writes(), []) def test_meta_without_board(self): # R-70 out = self.run_cmd("ensure_sprint_meta", sprint="N") self.assertEqual((out["status"], out["error"]), ("failed", "board_id нет в команде — спринты недоступны")) self.assertEqual(self.fake.requests, [])