"""AP2.2f — Backlog Epic-Hierarchie (parent_backlog_id + item_kind epic).""" from __future__ import annotations from tests.factories import provision_user_in_tenant from tests.test_initiatives_actions import _auth, _create_initiative, _login def _create_product_initiative(client, token, title="Epic Product"): created = _create_initiative( client, token, title=title, archetype_key="initiative.product", ) assert created.status_code == 201 return created.json()["id"] def test_create_epic_and_story_under_epic(client): user = provision_user_in_tenant(tenant_role="admin") token = _login(client, user) initiative_id = _create_product_initiative(client, token) epic = client.post( f"/api/initiatives/{initiative_id}/backlog", json={"title": "Checkout Epic", "item_kind": "epic", "status": "accepted"}, headers=_auth(token), ) assert epic.status_code == 201 epic_id = epic.json()["id"] assert epic.json()["item_kind"] == "epic" assert epic.json().get("parent_backlog_id") is None story = client.post( f"/api/initiatives/{initiative_id}/backlog", json={ "title": "Login Story", "item_kind": "story", "parent_backlog_id": epic_id, "status": "accepted", }, headers=_auth(token), ) assert story.status_code == 201 assert story.json()["parent_backlog_id"] == epic_id listed = client.get( f"/api/initiatives/{initiative_id}/backlog", headers=_auth(token), ) assert listed.status_code == 200 by_id = {item["id"]: item for item in listed.json()} assert by_id[story.json()["id"]]["parent_backlog_id"] == epic_id def test_epic_cannot_convert_to_action(client): user = provision_user_in_tenant(tenant_role="admin") token = _login(client, user) initiative_id = _create_product_initiative(client, token, title="Epic Convert Block") epic = client.post( f"/api/initiatives/{initiative_id}/backlog", json={"title": "Big Epic", "item_kind": "epic", "status": "accepted"}, headers=_auth(token), ) epic_id = epic.json()["id"] converted = client.post( f"/api/backlog/{epic_id}/convert-to-action", json={}, headers=_auth(token), ) assert converted.status_code == 400 assert "Epic" in converted.json()["detail"] def test_story_under_epic_converts_to_action(client): user = provision_user_in_tenant(tenant_role="admin") token = _login(client, user) initiative_id = _create_product_initiative(client, token, title="Story Convert") epic = client.post( f"/api/initiatives/{initiative_id}/backlog", json={"title": "Epic", "item_kind": "epic", "status": "accepted"}, headers=_auth(token), ) epic_id = epic.json()["id"] story = client.post( f"/api/initiatives/{initiative_id}/backlog", json={ "title": "Story", "item_kind": "story", "parent_backlog_id": epic_id, "status": "accepted", }, headers=_auth(token), ) story_id = story.json()["id"] converted = client.post( f"/api/backlog/{story_id}/convert-to-action", json={}, headers=_auth(token), ) assert converted.status_code == 201 assert converted.json()["action"]["title"] == "Story" def test_cannot_delete_epic_with_children(client): user = provision_user_in_tenant(tenant_role="admin") token = _login(client, user) initiative_id = _create_product_initiative(client, token, title="Epic Delete Guard") epic = client.post( f"/api/initiatives/{initiative_id}/backlog", json={"title": "Epic", "item_kind": "epic", "status": "accepted"}, headers=_auth(token), ) epic_id = epic.json()["id"] client.post( f"/api/initiatives/{initiative_id}/backlog", json={ "title": "Child Story", "item_kind": "story", "parent_backlog_id": epic_id, "status": "new", }, headers=_auth(token), ) deleted = client.delete(f"/api/backlog/{epic_id}", headers=_auth(token)) assert deleted.status_code == 400 assert "untergeordneten" in deleted.json()["detail"] def test_epic_cannot_have_parent_backlog(client): user = provision_user_in_tenant(tenant_role="admin") token = _login(client, user) initiative_id = _create_product_initiative(client, token, title="Epic Parent Guard") epic_a = client.post( f"/api/initiatives/{initiative_id}/backlog", json={"title": "Epic A", "item_kind": "epic", "status": "accepted"}, headers=_auth(token), ) epic_a_id = epic_a.json()["id"] epic_b = client.post( f"/api/initiatives/{initiative_id}/backlog", json={ "title": "Epic B", "item_kind": "epic", "parent_backlog_id": epic_a_id, "status": "accepted", }, headers=_auth(token), ) assert epic_b.status_code == 400