gabriel / musehub public
test_phase5_blast_risk_nav.py python
116 lines 3.4 KB
Raw
sha256:a34090cc4a394a78bd72cbbe34b08cc59525141e19135b6c0ab154f10611b9ef debug(push/stream): instrument O-frame decode path with INF… Sonnet 4.6 patch 121 days ago
1 """TDD spec for Phase 5 — navigation + Intel Hub integration (issue #11).
2
3 Verifies:
4 - Back link to /intel on list page and empty-state
5 - Page title contains "Blast Risk"
6 - Detail page back link to /intel/blast-risk
7 - Detail page title contains "Blast Risk"
8
9 Layers:
10 P5_01 list page — back link to /intel present
11 P5_02 list empty-state — back link to /intel present
12 P5_03 list page — title contains "Blast Risk"
13 P5_04 detail page — back link to /intel/blast-risk present
14 P5_05 detail page — title contains "Blast Risk"
15 """
16 from __future__ import annotations
17
18 import secrets
19
20 import pytest
21 import pytest_asyncio
22 from httpx import AsyncClient
23 from sqlalchemy.dialects.postgresql import insert as pg_insert
24 from sqlalchemy.ext.asyncio import AsyncSession
25
26 from muse.core.types import fake_id, long_id
27 from musehub.db import musehub_models as db
28 from tests.factories import create_repo
29
30
31 def _uid() -> str:
32 return fake_id(secrets.token_hex(16))
33
34
35 _OWNER = "testuser"
36 _SLUG = "brnav"
37 _REF = long_id("e" * 64)
38
39
40 async def _seed_risk(session: AsyncSession, repo_id: str, *, address: str) -> None:
41 stmt = (
42 pg_insert(db.MusehubIntelBlastRisk)
43 .values(
44 repo_id=repo_id,
45 address=address,
46 kind="function",
47 risk="high",
48 risk_score=60,
49 impact_score=0.5,
50 churn_score=0.5,
51 test_gap_score=1.0,
52 coupling_score=0.3,
53 ref=_REF,
54 )
55 .on_conflict_do_nothing()
56 )
57 await session.execute(stmt)
58 await session.flush()
59
60
61 @pytest_asyncio.fixture
62 async def nav_repo(db_session: AsyncSession):
63 return await create_repo(db_session, owner=_OWNER, slug=_SLUG)
64
65
66 @pytest_asyncio.fixture
67 async def nav_repo_with_row(db_session: AsyncSession, nav_repo):
68 repo_id = nav_repo.repo_id
69 await db_session.commit()
70 await _seed_risk(db_session, repo_id, address="pkg/nav.py::nav_fn")
71 await db_session.commit()
72 return nav_repo
73
74
75 class TestBlastRiskNav:
76
77 @pytest.mark.asyncio
78 async def test_P5_01_list_page_has_back_link_to_intel(
79 self, client: AsyncClient, nav_repo_with_row
80 ) -> None:
81 resp = await client.get(f"/{_OWNER}/{_SLUG}/intel/blast-risk")
82 assert "/intel" in resp.text
83
84 @pytest.mark.asyncio
85 async def test_P5_02_empty_list_has_back_link_to_intel(
86 self, client: AsyncClient, nav_repo
87 ) -> None:
88 resp = await client.get(f"/{_OWNER}/{_SLUG}/intel/blast-risk")
89 assert "/intel" in resp.text
90
91 @pytest.mark.asyncio
92 async def test_P5_03_list_page_title_contains_blast_risk(
93 self, client: AsyncClient, nav_repo
94 ) -> None:
95 resp = await client.get(f"/{_OWNER}/{_SLUG}/intel/blast-risk")
96 assert "Blast Risk" in resp.text
97
98 @pytest.mark.asyncio
99 async def test_P5_04_detail_page_has_back_link_to_blast_risk(
100 self, client: AsyncClient, nav_repo_with_row
101 ) -> None:
102 resp = await client.get(
103 f"/{_OWNER}/{_SLUG}/intel/blast-risk/detail",
104 params={"address": "pkg/nav.py::nav_fn"},
105 )
106 assert "blast-risk" in resp.text
107
108 @pytest.mark.asyncio
109 async def test_P5_05_detail_page_title_contains_blast_risk(
110 self, client: AsyncClient, nav_repo_with_row
111 ) -> None:
112 resp = await client.get(
113 f"/{_OWNER}/{_SLUG}/intel/blast-risk/detail",
114 params={"address": "pkg/nav.py::nav_fn"},
115 )
116 assert "Blast Risk" in resp.text
File History 1 commit
sha256:a34090cc4a394a78bd72cbbe34b08cc59525141e19135b6c0ab154f10611b9ef debug(push/stream): instrument O-frame decode path with INF… Sonnet 4.6 patch 121 days ago