feat(navigation): Enhance navigation links and add legacy route redirects
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

- 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:
2025-11-13 20:23:53 +01:00
parent ed8e05147c
commit 4d0e1a9989
12 changed files with 1050 additions and 73 deletions

View File

@@ -1,10 +1,16 @@
from __future__ import annotations
from collections.abc import Callable
from fastapi.testclient import TestClient
class TestScenarioLifecycle:
def test_scenario_lifecycle_flow(self, client: TestClient) -> None:
def test_scenario_lifecycle_flow(
self,
client: TestClient,
scenario_calculation_url: Callable[[str, int, int], str],
) -> None:
# Create a project to attach scenarios to
project_response = client.post(
"/projects",
@@ -65,6 +71,18 @@ class TestScenarioLifecycle:
assert "CAD" in scenario_detail.text
assert "Electricity" in scenario_detail.text
assert "Revised scenario assumptions" in scenario_detail.text
scenario_opex_url = scenario_calculation_url(
"calculations.scenario_opex_form",
project_id,
scenario_id,
)
scenario_capex_url = scenario_calculation_url(
"calculations.scenario_capex_form",
project_id,
scenario_id,
)
assert f'href="{scenario_opex_url}"' in scenario_detail.text
assert f'href="{scenario_capex_url}"' in scenario_detail.text
# Project detail page should show the scenario as active with updated currency/resource
project_detail = client.get(f"/projects/{project_id}/view")
@@ -84,6 +102,8 @@ class TestScenarioLifecycle:
# Scenario detail should still show the previous (valid) currency
scenario_detail = client.get(f"/scenarios/{scenario_id}/view")
assert "CAD" in scenario_detail.text
assert f'href="{scenario_opex_url}"' in scenario_detail.text
assert f'href="{scenario_capex_url}"' in scenario_detail.text
# Archive the scenario through the API
archive_response = client.put(
@@ -96,9 +116,17 @@ class TestScenarioLifecycle:
# Scenario detail reflects archived status
scenario_detail = client.get(f"/scenarios/{scenario_id}/view")
assert '<p class="metric-value status-pill status-pill--archived">Archived</p>' in scenario_detail.text
assert f'href="{scenario_opex_url}"' in scenario_detail.text
assert f'href="{scenario_capex_url}"' in scenario_detail.text
# Project detail metrics and table entries reflect the archived state
project_detail = client.get(f"/projects/{project_id}/view")
assert "<h2>Archived</h2>" in project_detail.text
assert '<p class="metric-value">1</p>' in project_detail.text
assert "Archived" in project_detail.text
# Scenario portfolio view includes calculator links for each scenario entry
scenario_portfolio = client.get(f"/projects/{project_id}/scenarios/ui")
assert scenario_portfolio.status_code == 200
assert f'href="{scenario_opex_url}"' in scenario_portfolio.text
assert f'href="{scenario_capex_url}"' in scenario_portfolio.text