"""G11 -- the frontend and its supporting endpoints are served. No browser automation: serving and shape only.""" import re import pytest pytestmark = pytest.mark.contract def _extract_asset_path(html, filename): match = re.search(rf'(?:src|href)=["\']([^"\']*{re.escape(filename)})["\']', html) assert match, f"could not find a reference to {filename} in the index page" path = match.group(1) return path if path.startswith("/") else f"/{path}" async def test_index_serves_html_referencing_assets(api): """G11: GET / returns 200, text/html, and references app.js and style.css.""" resp = await api.get("/") assert resp.status_code == 200 assert "text/html" in resp.headers.get("content-type", "") body = resp.text assert "app.js" in body assert "style.css" in body async def test_app_js_served(api): """G11: app.js returns 200 with a JS content type.""" index_html = (await api.get("/")).text resp = await api.get(_extract_asset_path(index_html, "app.js")) assert resp.status_code == 200 ctype = resp.headers.get("content-type", "") assert "javascript" in ctype or "ecmascript" in ctype async def test_style_css_served(api): """G11: style.css returns 200 with a CSS content type.""" index_html = (await api.get("/")).text resp = await api.get(_extract_asset_path(index_html, "style.css")) assert resp.status_code == 200 assert "css" in resp.headers.get("content-type", "") async def test_accounts_list_endpoint(api): """G11: GET /api/accounts returns >= 100 accounts with the expected shape.""" resp = await api.get("/api/accounts") assert resp.status_code == 200 accounts = resp.json() assert len(accounts) >= 100 sample = accounts[0] for field in ("id", "holder_name", "currency", "balance_minor"): assert field in sample, sample