Files
calminer/tests/integration/test_navigation_sidebar.py
zwitschi 4d0e1a9989
Some checks failed
CI / test (push) Has been skipped
CI / build (push) Has been skipped
CI / lint (push) Failing after 14s
CI / deploy (push) Has been skipped
feat(navigation): Enhance navigation links and add legacy route redirects
- Updated navigation links in `init_db.py` to include href overrides and parent slugs for profitability, opex, and capex planners.
- Modified `NavigationService` to handle child links and href overrides, ensuring proper routing when context is missing.
- Adjusted scenario detail and list templates to use new route names for opex and capex forms, with legacy fallbacks.
- Introduced integration tests for legacy calculation routes to ensure proper redirection and error handling.
- Added tests for navigation sidebar to validate role-based access and link visibility.
- Enhanced navigation sidebar tests to include calculation links and contextual URLs based on project and scenario IDs.
2025-11-13 20:23:53 +01:00

147 lines
4.2 KiB
Python

"""Integration coverage for the /navigation/sidebar endpoint.
These tests validate role-based filtering, ordering, and disabled-link handling
through the full FastAPI stack so future changes keep navigation behaviour under
explicit test coverage.
"""
from __future__ import annotations
from collections.abc import Callable
from typing import Any, Mapping
import pytest
from fastapi.testclient import TestClient
from models.navigation import NavigationGroup, NavigationLink
from services.unit_of_work import UnitOfWork
@pytest.fixture()
def seed_navigation(unit_of_work_factory: Callable[[], UnitOfWork]) -> Callable[[], None]:
def _seed() -> None:
with unit_of_work_factory() as uow:
repo = uow.navigation
assert repo is not None
workspace = repo.add_group(
NavigationGroup(
slug="workspace",
label="Workspace",
sort_order=10,
)
)
insights = repo.add_group(
NavigationGroup(
slug="insights",
label="Insights",
sort_order=20,
)
)
repo.add_link(
NavigationLink(
group_id=workspace.id,
slug="projects",
label="Projects",
href_override="/projects",
sort_order=5,
required_roles=[],
)
)
repo.add_link(
NavigationLink(
group_id=workspace.id,
slug="admin-tools",
label="Admin Tools",
href_override="/admin/tools",
sort_order=10,
required_roles=["admin"],
)
)
repo.add_link(
NavigationLink(
group_id=workspace.id,
slug="disabled-link",
label="Hidden",
href_override="/hidden",
sort_order=15,
required_roles=[],
is_enabled=False,
)
)
repo.add_link(
NavigationLink(
group_id=insights.id,
slug="reports",
label="Reports",
href_override="/reports",
sort_order=1,
required_roles=[],
)
)
return _seed
def _link_labels(group_json: Mapping[str, Any]) -> list[str]:
return [link["label"] for link in group_json["links"]]
def test_admin_session_receives_all_enabled_links(
client: TestClient,
seed_navigation: Callable[[], None],
) -> None:
seed_navigation()
response = client.get("/navigation/sidebar")
assert response.status_code == 200
payload = response.json()
assert [group["label"] for group in payload["groups"]] == [
"Workspace",
"Insights",
]
workspace, insights = payload["groups"]
assert _link_labels(workspace) == ["Projects", "Admin Tools"]
assert _link_labels(insights) == ["Reports"]
assert payload["roles"] == ["admin"]
def test_viewer_session_filters_admin_only_links(
client: TestClient,
seed_navigation: Callable[[], None],
test_user_headers: Callable[[str | None], dict[str, str]],
) -> None:
seed_navigation()
response = client.get(
"/navigation/sidebar",
headers=test_user_headers("viewer"),
)
assert response.status_code == 200
payload = response.json()
assert [group["label"] for group in payload["groups"]] == [
"Workspace",
"Insights",
]
workspace, insights = payload["groups"]
assert _link_labels(workspace) == ["Projects"]
assert _link_labels(insights) == ["Reports"]
assert payload["roles"] == ["viewer"]
def test_anonymous_access_is_rejected(
client: TestClient,
seed_navigation: Callable[[], None],
test_user_headers: Callable[[str | None], dict[str, str]],
) -> None:
seed_navigation()
response = client.get(
"/navigation/sidebar",
headers=test_user_headers("anonymous"),
)
assert response.status_code == 401