"""Tests for the whoami endpoint and the static SPA host.""" from __future__ import annotations import dataclasses import tempfile import unittest from pathlib import Path from unittest import mock from httpx import ASGITransport, AsyncClient from pwo import async_test from tavolo.app import app from tavolo.config import settings from tests.helpers import oidc_user class MeRouteTest(unittest.TestCase): @async_test async def test_me_authenticated(self) -> None: transport = ASGITransport(app=app) async with AsyncClient(transport=transport, base_url="http://127.0.0.1") as client: with oidc_user("alice"): response = await client.get("/api/me") self.assertEqual(200, response.status_code) self.assertEqual({"sub": "alice", "name": "alice"}, response.json()) @async_test async def test_me_unauthenticated(self) -> None: transport = ASGITransport(app=app) async with AsyncClient(transport=transport, base_url="http://127.0.0.1") as client: response = await client.get("/api/me") self.assertEqual(401, response.status_code) class StaticRouteTest(unittest.TestCase): """The app only serves the SPA shell; asset files under /static are served by Granian and are not reachable through the ASGI transport.""" @async_test async def test_serves_shell_and_spa_fallback(self) -> None: with tempfile.TemporaryDirectory() as dist: (Path(dist) / "index.html").write_text("spa") patched = dataclasses.replace(settings, static_dir=dist) with mock.patch("tavolo.routes.static.settings", patched): transport = ASGITransport(app=app) async with AsyncClient(transport=transport, base_url="http://127.0.0.1") as client: index = await client.get("/") self.assertEqual(200, index.status_code) self.assertEqual("text/html; charset=utf-8", index.headers["content-type"]) self.assertIn(b"spa", index.content) # Unknown client-side route falls back to the app shell. fallback = await client.get("/game/some-id") self.assertEqual(200, fallback.status_code) self.assertIn(b"spa", fallback.content) @async_test async def test_missing_dist_returns_404(self) -> None: patched = dataclasses.replace(settings, static_dir="/nonexistent-dist") with mock.patch("tavolo.routes.static.settings", patched): transport = ASGITransport(app=app) async with AsyncClient(transport=transport, base_url="http://127.0.0.1") as client: response = await client.get("/") self.assertEqual(404, response.status_code) if __name__ == "__main__": unittest.main()