afterhours-shift-manager/tests/portal_api/test_handler.py

102 lines
3.2 KiB
Python
Raw Permalink Normal View History

"""Tests for the portal shift API handler."""
import json
import pytest
def _event(method="GET", path="/api/shifts", body=None, token="id-token", origin=None):
headers = {"authorization": f"Bearer {token}"}
if origin:
headers["origin"] = origin
payload = None
if body is not None:
payload = json.dumps(body)
return {
"version": "2.0",
"routeKey": f"{method} {path}",
"rawPath": path,
"headers": headers,
"queryStringParameters": {},
"requestContext": {"http": {"method": method, "path": path}},
"body": payload,
"isBase64Encoded": False,
}
@pytest.fixture
def identity(portalapi_app, monkeypatch):
monkeypatch.setattr(
"shared.portal_http.verify_cognito_id_token",
lambda _token: {"name": "Alice", "email": "alice@seahavenind.com"},
)
def test_unlinked_email_returns_linked_false(portalapi_app, schedule, identity):
result = portalapi_app.handler(_event(), None)
assert result["statusCode"] == 200
body = json.loads(result["body"])
assert body["linked"] is False
assert body["email"] == "alice@seahavenind.com"
def test_401_without_bearer(portalapi_app, schedule):
event = _event()
event["headers"] = {}
result = portalapi_app.handler(event, None)
assert result["statusCode"] == 401
def test_linked_snapshot_and_admin_flag(portalapi_app, schedule, seed, identity):
seed.roster(
"114",
"Alice",
slack_user_id="U_ADMIN",
email="alice@seahavenind.com",
)
seed.config(admin_users=["U_ADMIN"])
seed.weekly("Monday", "114", "Alice")
result = portalapi_app.handler(_event(), None)
assert result["statusCode"] == 200
body = json.loads(result["body"])
assert body["linked"] is True
assert body["isAdmin"] is True
assert body["me"]["extension"] == "114"
assert len(body["days"]) == 7
def test_non_admin_cannot_override(portalapi_app, schedule, seed, identity):
seed.roster("114", "Alice", slack_user_id="U_ALICE", email="alice@seahavenind.com")
seed.config(admin_users=["U_OTHER"])
result = portalapi_app.handler(
_event(
method="POST",
path="/api/shifts/admin/override",
body={"date": "2026-06-10", "extension": "114", "shiftType": "night"},
),
None,
)
assert result["statusCode"] == 403
def test_cors_header_for_portal_origin(portalapi_app, schedule, identity):
result = portalapi_app.handler(_event(origin="https://internal.seahaven.com"), None)
assert (
result["headers"]["Access-Control-Allow-Origin"]
== "https://internal.seahaven.com"
)
def test_unexpected_failure_keeps_cors(portalapi_app, identity, monkeypatch):
monkeypatch.setattr(
"shared.portal_http.ShiftSchedule",
lambda: (_ for _ in ()).throw(RuntimeError("ddb down")),
)
result = portalapi_app.handler(_event(origin="https://internal.seahaven.com"), None)
assert result["statusCode"] == 500
assert (
result["headers"]["Access-Control-Allow-Origin"]
== "https://internal.seahaven.com"
)
assert json.loads(result["body"])["error"]["code"] == "INTERNAL"