From dad862e48e60cd13e090e9f350d254d5e174d5cb Mon Sep 17 00:00:00 2001 From: zwitschi Date: Sun, 9 Nov 2025 19:21:25 +0100 Subject: [PATCH] feat: reorder project route registration to prioritize static UI paths and add pytest coverage for navigation endpoints --- changelog.md | 1 + routes/projects.py | 81 ++++++++++++++++++----------------- tests/test_dashboard_route.py | 12 ++++++ 3 files changed, 55 insertions(+), 39 deletions(-) diff --git a/changelog.md b/changelog.md index 642ee46..6feea6d 100644 --- a/changelog.md +++ b/changelog.md @@ -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. - 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. +- 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. diff --git a/routes/projects.py b/routes/projects.py index 57a1c30..2511620 100644 --- a/routes/projects.py +++ b/routes/projects.py @@ -46,45 +46,6 @@ def create_project( 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( "/ui", 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( "/{project_id}/view", response_class=HTMLResponse, diff --git a/tests/test_dashboard_route.py b/tests/test_dashboard_route.py index 35a7131..02bab98 100644 --- a/tests/test_dashboard_route.py +++ b/tests/test_dashboard_route.py @@ -71,3 +71,15 @@ class TestDashboardRoute: assert "No simulation runs yet" in html assert "All scenarios look good" in html 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