tests/test_error_pages.py
Rama main · réplica de lectura del repositorio original.
"""A refusal or a fault, as a person in a browser meets it.
There was no HTML handler at all: 107 `HTTPException`s answered a browser
with `{"detail": ...}`, a form missing a field with FastAPI's list of
errors, and a fault with a bare "Internal Server Error". A page's own
fetch() calls and the API keep their JSON.
"""
from __future__ import annotations
from fastapi.testclient import TestClient
from test_routes import make_login, session_csrf
HTML = {"accept": "text/html"}
NOT_A_TICKER = {"report": "holdings", "fmt": "csv", "ticker": "İ" * 10}
def test_a_page_that_is_not_there_is_a_page(client, session_factory):
make_login(client, session_factory)
resp = client.get("/no-such-page", headers=HTML)
assert resp.status_code == 404
assert resp.headers["content-type"].startswith("text/html")
assert "<h1>Not found</h1>" in resp.text
assert "There's nothing at this address." in resp.text
# Somewhere to go that says where it is (decisions.md #40).
assert '<a class="backlink button secondary" href="/">' in resp.text
def test_a_refusal_is_a_page_giving_the_reason(client, session_factory):
make_login(client, session_factory)
resp = client.get("/export/download", params=NOT_A_TICKER, headers=HTML)
assert resp.status_code == 400
assert "<h1>That didn't work</h1>" in resp.text
assert "That is not a ticker" in resp.text
def test_a_refusal_keeps_its_own_headers(client, session_factory):
make_login(client, session_factory)
resp = client.post("/charts", headers=HTML)
assert resp.status_code == 405
assert "GET" in resp.headers["allow"]
assert "This address doesn't take that kind of request." in resp.text
def test_a_fetch_and_the_api_still_get_json(client, session_factory):
make_login(client, session_factory)
fetched = client.get("/export/download", params=NOT_A_TICKER)
api = client.get("/api/v1/portfolio", headers={**HTML, "Authorization": "Bearer nope"})
assert fetched.json() == {"detail": "that is not a ticker"}
assert api.status_code == 401
assert api.headers["content-type"].startswith("application/json")
def test_a_form_missing_a_field_is_a_page_naming_it(client, session_factory):
make_login(client, session_factory)
resp = client.post("/imports-exports/statement/commit", headers=HTML,
data={"_csrf": session_csrf(session_factory), "ticker": "ACME",
"net_amount": "10.00"})
assert resp.status_code == 422
assert resp.headers["content-type"].startswith("text/html")
assert "Missing or unreadable: payment date." in resp.text
def test_a_fault_is_a_page_that_tells_nothing_of_the_code(client, monkeypatch, app_module):
def broken(db):
raise RuntimeError("the inner workings")
monkeypatch.setattr(app_module, "_users_exist", broken)
quiet = TestClient(app_module.app, raise_server_exceptions=False)
page = quiet.get("/login", headers=HTML)
plain = quiet.get("/login")
assert page.status_code == 500
assert "<h1>Something went wrong</h1>" in page.text
assert "inner workings" not in page.text
assert (plain.status_code, plain.text) == (500, "Internal Server Error")