Kairo-Jinkendo/backend/tests/test_epic_rollup_unit.py
Lars ef5ee0d19b
Some checks failed
Test Suite / pytest-backend (push) Waiting to run
Test Suite / lint-backend (push) Waiting to run
Test Suite / compose-smoke (push) Waiting to run
Test Suite / k6 /api/health Baseline (push) Blocked by required conditions
Test Suite / playwright-smoke (push) Blocked by required conditions
Deploy Development / deploy (push) Has been cancelled
feat(steering): Epic Roll-up Read Model und Attention (ADP P4)
Schliesst den Backlog/Epic-Track mit kernel-basiertem Fortschritt pro Epic, Steuerungs-Attention und UI-Fortschrittsanzeige im Plan-Eingang ab.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-27 11:13:47 +02:00

126 lines
3.7 KiB
Python

"""Unit tests — Epic roll-up read model (P4)."""
from __future__ import annotations
from steering.read_models.epic_rollup import (
compute_epic_rollup,
epic_rollup_attention_items,
)
def _item(
*,
id: str,
title: str,
item_kind: str = "story",
status: str = "accepted",
parent_backlog_id: str | None = None,
converted_action_id: str | None = None,
) -> dict:
return {
"id": id,
"title": title,
"item_kind": item_kind,
"status": status,
"parent_backlog_id": parent_backlog_id,
"converted_action_id": converted_action_id,
}
def test_epic_rollup_empty_epic():
rollups = compute_epic_rollup(
backlog_items=[_item(id="e1", title="Epic", item_kind="epic")],
actions=[],
)
assert len(rollups) == 1
assert rollups[0]["status"] == "empty"
assert rollups[0]["child_total"] == 0
def test_epic_rollup_intake_only():
rollups = compute_epic_rollup(
backlog_items=[
_item(id="e1", title="Checkout", item_kind="epic"),
_item(id="s1", title="Login", parent_backlog_id="e1"),
_item(id="s2", title="Pay", parent_backlog_id="e1"),
],
actions=[],
)
assert rollups[0]["status"] == "intake_only"
assert rollups[0]["child_total"] == 2
assert rollups[0]["child_uncommitted"] == 2
assert rollups[0]["completion_ratio"] == 0.0
def test_epic_rollup_partial_and_done():
rollups = compute_epic_rollup(
backlog_items=[
_item(id="e1", title="Epic", item_kind="epic"),
_item(
id="s1",
title="Done story",
parent_backlog_id="e1",
status="converted",
converted_action_id="a1",
),
_item(id="s2", title="Open story", parent_backlog_id="e1"),
],
actions=[
{"id": "a1", "status": "done"},
{"id": "a2", "status": "in_progress"},
],
)
assert rollups[0]["status"] == "in_progress"
assert rollups[0]["actions_done"] == 1
assert rollups[0]["child_uncommitted"] == 1
assert rollups[0]["completion_ratio"] == 0.5
def test_epic_rollup_all_done():
rollups = compute_epic_rollup(
backlog_items=[
_item(id="e1", title="Epic", item_kind="epic"),
_item(
id="s1",
title="A",
parent_backlog_id="e1",
status="converted",
converted_action_id="a1",
),
],
actions=[{"id": "a1", "status": "done"}],
)
assert rollups[0]["status"] == "done"
assert rollups[0]["completion_ratio"] == 1.0
def test_epic_rollup_attention_awaiting_commit():
rollups = compute_epic_rollup(
backlog_items=[
_item(id="e1", title="Epic", item_kind="epic"),
_item(id="s1", title="Story", parent_backlog_id="e1"),
],
actions=[],
)
items = epic_rollup_attention_items(initiative_id="init-1", rollups=rollups)
assert any(i["reason_code"] == "epic_awaiting_commit" for i in items)
def test_epic_rollup_attention_split_focus():
rollups = compute_epic_rollup(
backlog_items=[
_item(id="e1", title="Epic", item_kind="epic"),
_item(
id="s1",
title="Running",
parent_backlog_id="e1",
status="converted",
converted_action_id="a1",
),
_item(id="s2", title="Waiting", parent_backlog_id="e1"),
],
actions=[{"id": "a1", "status": "in_progress"}],
)
items = epic_rollup_attention_items(initiative_id="init-1", rollups=rollups)
assert any(i["reason_code"] == "epic_uncommitted_during_execution" for i in items)