feat: Enhance project and scenario creation with monitoring metrics
Some checks failed
CI / lint (push) Failing after 1m14s
CI / test (push) Has been skipped
CI / build (push) Has been skipped

- Added monitoring metrics for project creation success and error handling in `ProjectRepository`.
- Implemented similar monitoring for scenario creation in `ScenarioRepository`.
- Refactored `run_monte_carlo` function in `simulation.py` to include timing and success/error metrics.
- Introduced new CSS styles for headers, alerts, and navigation buttons in `main.css` and `projects.css`.
- Created a new JavaScript file for navigation logic to handle chevron buttons.
- Updated HTML templates to include new navigation buttons and improved styling for buttons.
- Added tests for reporting service and routes to ensure proper functionality and access control.
- Removed unused imports and optimized existing test files for better clarity and performance.
This commit is contained in:
2025-11-12 10:36:24 +01:00
parent f68321cd04
commit ce9c174b53
61 changed files with 2124 additions and 308 deletions

View File

@@ -284,3 +284,110 @@ class TestLogoutFlow:
set_cookie_header = response.headers.get("set-cookie") or ""
assert "calminer_access_token=" in set_cookie_header
assert "Max-Age=0" in set_cookie_header or "expires=" in set_cookie_header.lower()
class TestLoginFlowEndToEnd:
def test_get_login_form_renders(self, client: TestClient) -> None:
response = client.get("/login")
assert response.status_code == 200
assert "login-form" in response.text
assert "username" in response.text
def test_unauthenticated_root_redirects_to_login(self, client: TestClient) -> None:
# Temporarily override to anonymous session
app = cast(FastAPI, client.app)
original_override = app.dependency_overrides.get(get_auth_session)
app.dependency_overrides[get_auth_session] = lambda: AuthSession.anonymous(
)
try:
response = client.get("/", follow_redirects=False)
assert response.status_code == 303
assert response.headers.get(
"location") == "http://testserver/login"
finally:
if original_override is not None:
app.dependency_overrides[get_auth_session] = original_override
else:
app.dependency_overrides.pop(get_auth_session, None)
def test_login_success_redirects_to_dashboard_and_sets_session(
self, client: TestClient, db_session: Session
) -> None:
password = "TestP@ss123"
user = User(
email="e2e@example.com",
username="e2euser",
password_hash=hash_password(password),
is_active=True,
)
db_session.add(user)
db_session.commit()
# Override to anonymous for login
app = cast(FastAPI, client.app)
app.dependency_overrides[get_auth_session] = lambda: AuthSession.anonymous(
)
try:
login_response = client.post(
"/login",
data={"username": "e2euser", "password": password},
follow_redirects=False,
)
assert login_response.status_code == 303
assert login_response.headers.get(
"location") == "http://testserver/"
set_cookie_header = login_response.headers.get("set-cookie", "")
assert "calminer_access_token=" in set_cookie_header
# Now with cookies, GET / should show dashboard
dashboard_response = client.get("/")
assert dashboard_response.status_code == 200
assert "Dashboard" in dashboard_response.text or "metrics" in dashboard_response.text
finally:
app.dependency_overrides.pop(get_auth_session, None)
def test_logout_redirects_to_login_and_clears_session(self, client: TestClient) -> None:
# Assuming authenticated from conftest
logout_response = client.get("/logout", follow_redirects=False)
assert logout_response.status_code == 303
location = logout_response.headers.get("location")
assert location and "login" in location
set_cookie_header = logout_response.headers.get("set-cookie", "")
assert "calminer_access_token=" in set_cookie_header
assert "Max-Age=0" in set_cookie_header or "expires=" in set_cookie_header.lower()
# After logout, GET / should redirect to login
app = cast(FastAPI, client.app)
app.dependency_overrides[get_auth_session] = lambda: AuthSession.anonymous(
)
try:
root_response = client.get("/", follow_redirects=False)
assert root_response.status_code == 303
assert root_response.headers.get(
"location") == "http://testserver/login"
finally:
app.dependency_overrides.pop(get_auth_session, None)
def test_login_inactive_user_shows_error(self, client: TestClient, db_session: Session) -> None:
user = User(
email="inactive@example.com",
username="inactiveuser",
password_hash=hash_password("TestP@ss123"),
is_active=False,
)
db_session.add(user)
db_session.commit()
app = cast(FastAPI, client.app)
app.dependency_overrides[get_auth_session] = lambda: AuthSession.anonymous(
)
try:
response = client.post(
"/login",
data={"username": "inactiveuser", "password": "TestP@ss123"},
follow_redirects=False,
)
assert response.status_code == 400
assert "Account is inactive" in response.text
finally:
app.dependency_overrides.pop(get_auth_session, None)