feat: reorder project route registration to prioritize static UI paths and add pytest coverage for navigation endpoints

This commit is contained in:
2025-11-09 19:21:25 +01:00
parent 400f85c907
commit dad862e48e
3 changed files with 55 additions and 39 deletions

View File

@@ -13,3 +13,4 @@
- Delivered a new dashboard experience with `templates/dashboard.html`, dedicated styling, and a FastAPI route supplying real project/scenario metrics via repository helpers. - Delivered a new dashboard experience with `templates/dashboard.html`, dedicated styling, and a FastAPI route supplying real project/scenario metrics via repository helpers.
- Extended repositories with count/recency utilities and added pytest coverage, including a dashboard rendering smoke test validating empty-state messaging. - Extended repositories with count/recency utilities and added pytest coverage, including a dashboard rendering smoke test validating empty-state messaging.
- Brought project and scenario detail pages plus their forms in line with the dashboard visuals, adding metric cards, layout grids, and refreshed CTA styles. - Brought project and scenario detail pages plus their forms in line with the dashboard visuals, adding metric cards, layout grids, and refreshed CTA styles.
- Reordered project route registration to prioritize static UI paths, eliminating 422 errors on `/projects/ui` and `/projects/create`, and added pytest smoke coverage for the navigation endpoints.

View File

@@ -46,45 +46,6 @@ def create_project(
return _to_read_model(created) return _to_read_model(created)
@router.get("/{project_id}", response_model=ProjectRead)
def get_project(project_id: int, uow: UnitOfWork = Depends(get_unit_of_work)) -> ProjectRead:
try:
project = uow.projects.get(project_id)
except EntityNotFoundError as exc:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, detail=str(exc)) from exc
return _to_read_model(project)
@router.put("/{project_id}", response_model=ProjectRead)
def update_project(
project_id: int,
payload: ProjectUpdate,
uow: UnitOfWork = Depends(get_unit_of_work),
) -> ProjectRead:
try:
project = uow.projects.get(project_id)
except EntityNotFoundError as exc:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, detail=str(exc)) from exc
update_data = payload.model_dump(exclude_unset=True)
for field, value in update_data.items():
setattr(project, field, value)
uow.flush()
return _to_read_model(project)
@router.delete("/{project_id}", status_code=status.HTTP_204_NO_CONTENT)
def delete_project(project_id: int, uow: UnitOfWork = Depends(get_unit_of_work)) -> None:
try:
uow.projects.delete(project_id)
except EntityNotFoundError as exc:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, detail=str(exc)) from exc
@router.get( @router.get(
"/ui", "/ui",
response_class=HTMLResponse, response_class=HTMLResponse,
@@ -188,6 +149,48 @@ def create_project_submit(
) )
@router.get("/{project_id}", response_model=ProjectRead)
def get_project(project_id: int, uow: UnitOfWork = Depends(get_unit_of_work)) -> ProjectRead:
try:
project = uow.projects.get(project_id)
except EntityNotFoundError as exc:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, detail=str(exc)
) from exc
return _to_read_model(project)
@router.put("/{project_id}", response_model=ProjectRead)
def update_project(
project_id: int,
payload: ProjectUpdate,
uow: UnitOfWork = Depends(get_unit_of_work),
) -> ProjectRead:
try:
project = uow.projects.get(project_id)
except EntityNotFoundError as exc:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, detail=str(exc)
) from exc
update_data = payload.model_dump(exclude_unset=True)
for field, value in update_data.items():
setattr(project, field, value)
uow.flush()
return _to_read_model(project)
@router.delete("/{project_id}", status_code=status.HTTP_204_NO_CONTENT)
def delete_project(project_id: int, uow: UnitOfWork = Depends(get_unit_of_work)) -> None:
try:
uow.projects.delete(project_id)
except EntityNotFoundError as exc:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, detail=str(exc)
) from exc
@router.get( @router.get(
"/{project_id}/view", "/{project_id}/view",
response_class=HTMLResponse, response_class=HTMLResponse,

View File

@@ -71,3 +71,15 @@ class TestDashboardRoute:
assert "No simulation runs yet" in html assert "No simulation runs yet" in html
assert "All scenarios look good" in html assert "All scenarios look good" in html
assert "" in html # Last data import placeholder assert "" in html # Last data import placeholder
class TestProjectUIRoutes:
def test_projects_ui_page_resolves(self, client: TestClient) -> None:
response = client.get("/projects/ui")
assert response.status_code == 200
assert "Projects" in response.text
def test_projects_create_form_resolves(self, client: TestClient) -> None:
response = client.get("/projects/create")
assert response.status_code == 200
assert "Create Project" in response.text