From 73e1c10236350b4788f79a547d669f960c68bf78 Mon Sep 17 00:00:00 2001 From: Perumalla Giridhar Date: Wed, 29 Oct 2025 18:04:11 +0530 Subject: [PATCH] Implementing test cases for request state --- .github/workflows/main.yml | 2 +- tests/test_applications.py | 24 +++++++++++++++++++++++- tests/test_requests.py | 16 +++++++++++++++- 3 files changed, 39 insertions(+), 3 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 68699b92f..76e2c621f 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -14,7 +14,7 @@ jobs: strategy: matrix: - python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"] + python-version: ["3.9", "3.10", "3.11", "3.12", "3.13", "3.14"] steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 diff --git a/tests/test_applications.py b/tests/test_applications.py index 310eef6b4..e682ec70e 100644 --- a/tests/test_applications.py +++ b/tests/test_applications.py @@ -4,7 +4,7 @@ from collections.abc import AsyncGenerator, AsyncIterator, Generator from contextlib import asynccontextmanager from pathlib import Path -from typing import Callable +from typing import Callable, TypedDict import anyio.from_thread import pytest @@ -96,6 +96,19 @@ def custom_ws_exception_handler(websocket: WebSocket, exc: CustomWSException) -> anyio.from_thread.run(websocket.close, status.WS_1013_TRY_AGAIN_LATER) +class ExampleState(TypedDict): + count: int + + +@asynccontextmanager +async def lifespan(app: Starlette) -> AsyncGenerator[ExampleState]: + yield {"count": 1} + + +async def request_state(request: Request[ExampleState]) -> JSONResponse: + return JSONResponse({"state.count": request.state["count"]}, status_code=200) + + users = Router( routes=[ Route("/", endpoint=all_users_page), @@ -124,6 +137,7 @@ def custom_ws_exception_handler(websocket: WebSocket, exc: CustomWSException) -> Route("/async", endpoint=async_homepage), Route("/class", endpoint=Homepage), Route("/500", endpoint=runtime_error), + Route("/state", endpoint=request_state), WebSocketRoute("/ws", endpoint=websocket_endpoint), WebSocketRoute("/ws-raise-websocket", endpoint=websocket_raise_websocket_exception), WebSocketRoute("/ws-raise-http", endpoint=websocket_raise_http_exception), @@ -133,6 +147,7 @@ def custom_ws_exception_handler(websocket: WebSocket, exc: CustomWSException) -> ], exception_handlers=exception_handlers, # type: ignore middleware=middleware, + lifespan=lifespan, ) @@ -217,6 +232,12 @@ def test_500(test_client_factory: TestClientFactory) -> None: assert response.json() == {"detail": "Server Error"} +def test_request_state(client: TestClient) -> None: + response = client.get("/state") + assert response.status_code == 200 + assert response.json() == {"state.count": 1} + + def test_websocket_raise_websocket_exception(client: TestClient) -> None: with client.websocket_connect("/ws-raise-websocket") as session: response = session.receive() @@ -258,6 +279,7 @@ def test_routes() -> None: Route("/async", endpoint=async_homepage, methods=["GET"]), Route("/class", endpoint=Homepage), Route("/500", endpoint=runtime_error, methods=["GET"]), + Route("/state", endpoint=request_state, methods=["GET"]), WebSocketRoute("/ws", endpoint=websocket_endpoint), WebSocketRoute("/ws-raise-websocket", endpoint=websocket_raise_websocket_exception), WebSocketRoute("/ws-raise-http", endpoint=websocket_raise_http_exception), diff --git a/tests/test_requests.py b/tests/test_requests.py index 1799e89e0..f6f1a7086 100644 --- a/tests/test_requests.py +++ b/tests/test_requests.py @@ -297,11 +297,25 @@ def test_request_state_object() -> None: s.new = "value" assert s.new == "value" - del s.new + s["item"] = "baar" + assert s["item"] == "baar" + + assert len(s) == 3 + + assert "item" in s + + assert "old" in s + assert "new" in s + + del s.new with pytest.raises(AttributeError): s.new + del s["item"] + with pytest.raises(KeyError): + s["item"] + def test_request_state(test_client_factory: TestClientFactory) -> None: async def app(scope: Scope, receive: Receive, send: Send) -> None: