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.
This commit is contained in:
@@ -16,6 +16,7 @@ class StubNavigationLink:
|
||||
id: int
|
||||
slug: str
|
||||
label: str
|
||||
parent_link_id: int | None = None
|
||||
route_name: str | None = None
|
||||
href_override: str | None = None
|
||||
match_prefix: str | None = None
|
||||
@@ -131,6 +132,7 @@ def test_build_sidebar_resolves_profitability_link_with_context():
|
||||
slug="profitability",
|
||||
label="Profitability",
|
||||
route_name="calculations.profitability_form",
|
||||
href_override="/calculations/profitability",
|
||||
)
|
||||
group = StubNavigationGroup(
|
||||
id=99, slug="insights", label="Insights", links=[link])
|
||||
@@ -150,6 +152,66 @@ def test_build_sidebar_resolves_profitability_link_with_context():
|
||||
assert dto.groups[0].links[0].match_prefix == dto.groups[0].links[0].href
|
||||
|
||||
|
||||
def test_build_sidebar_resolves_opex_link_with_context():
|
||||
link = StubNavigationLink(
|
||||
id=2,
|
||||
slug="opex",
|
||||
label="Opex",
|
||||
route_name="calculations.opex_form",
|
||||
href_override="/calculations/opex",
|
||||
)
|
||||
group = StubNavigationGroup(
|
||||
id=5, slug="workspace", label="Workspace", links=[link])
|
||||
|
||||
request = StubRequest(path_params={"project_id": "3", "scenario_id": "9"})
|
||||
service = NavigationService(StubNavigationRepository([group]))
|
||||
|
||||
dto = service.build_sidebar(
|
||||
session=_session(roles=["analyst"]),
|
||||
request=cast(Request, request),
|
||||
)
|
||||
|
||||
href = dto.groups[0].links[0].href
|
||||
assert href == "/calculations.opex_form/project_id-3_scenario_id-9"
|
||||
assert request.url_for_calls[0][0] == "calculations.opex_form"
|
||||
assert request.url_for_calls[0][1] == {
|
||||
"project_id": "3", "scenario_id": "9"}
|
||||
|
||||
|
||||
def test_build_sidebar_uses_href_override_when_calculator_context_missing():
|
||||
class ParamAwareStubRequest(StubRequest):
|
||||
# type: ignore[override]
|
||||
def url_for(self, name: str, **params: str) -> str:
|
||||
if name in {
|
||||
"calculations.opex_form",
|
||||
"calculations.capex_form",
|
||||
} and not params:
|
||||
self._url_for_calls.append((name, params))
|
||||
raise RuntimeError("missing params")
|
||||
return super().url_for(name, **params)
|
||||
|
||||
link = StubNavigationLink(
|
||||
id=3,
|
||||
slug="capex",
|
||||
label="Capex",
|
||||
route_name="calculations.capex_form",
|
||||
href_override="/calculations/capex",
|
||||
)
|
||||
group = StubNavigationGroup(
|
||||
id=6, slug="workspace", label="Workspace", links=[link])
|
||||
|
||||
request = ParamAwareStubRequest()
|
||||
service = NavigationService(StubNavigationRepository([group]))
|
||||
|
||||
dto = service.build_sidebar(
|
||||
session=_session(roles=["analyst"]),
|
||||
request=cast(Request, request),
|
||||
)
|
||||
|
||||
assert dto.groups[0].links[0].href == "/calculations/capex"
|
||||
assert request.url_for_calls[-1][0] == "calculations.capex_form"
|
||||
|
||||
|
||||
def test_build_sidebar_skips_disabled_links_unless_included():
|
||||
enabled_link = StubNavigationLink(
|
||||
id=1,
|
||||
|
||||
Reference in New Issue
Block a user