Browse Source

test: cover stream_item_type propagation through include_router

pull/15544/head
Nilesh Patil 2 months ago
parent
commit
21ec9d9729
  1. 38
      tests/test_sse.py

38
tests/test_sse.py

@ -6,6 +6,7 @@ import fastapi.routing
import pytest import pytest
from fastapi import APIRouter, FastAPI from fastapi import APIRouter, FastAPI
from fastapi.responses import EventSourceResponse from fastapi.responses import EventSourceResponse
from fastapi.routing import APIRoute
from fastapi.sse import ServerSentEvent from fastapi.sse import ServerSentEvent
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from pydantic import BaseModel from pydantic import BaseModel
@ -99,6 +100,20 @@ async def stream_events():
app.include_router(router, prefix="/api") app.include_router(router, prefix="/api")
# Router with a typed SSE route to test stream_item_type propagation
typed_router = APIRouter()
@typed_router.get("/typed-events", response_class=EventSourceResponse)
async def stream_typed_events() -> AsyncIterable[Item]:
for item in items:
yield item
typed_app = FastAPI()
typed_app.include_router(typed_router, prefix="/api")
@pytest.fixture(name="client") @pytest.fixture(name="client")
def client_fixture(): def client_fixture():
with TestClient(app) as c: with TestClient(app) as c:
@ -237,9 +252,7 @@ def test_raw_data_sent_without_json_encoding(client: TestClient):
assert response.status_code == 200 assert response.status_code == 200
text = response.text text = response.text
# raw_data should appear without JSON quotes
assert "data: plain text without quotes\n" in text assert "data: plain text without quotes\n" in text
# Not JSON-quoted
assert 'data: "plain text without quotes"' not in text assert 'data: "plain text without quotes"' not in text
assert "event: html\n" in text assert "event: html\n" in text
@ -265,6 +278,23 @@ def test_sse_on_router_included_in_app(client: TestClient):
assert len(data_lines) == 2 assert len(data_lines) == 2
def test_stream_item_type_propagated_through_include_router():
included_route = next(
r for r in typed_app.routes if getattr(r, "path", None) == "/api/typed-events"
)
assert isinstance(included_route, APIRoute)
assert included_route.stream_item_type is Item
with TestClient(typed_app) as client:
response = client.get("/api/typed-events")
assert response.status_code == 200
data_lines = [
line for line in response.text.strip().split("\n") if line.startswith("data: ")
]
assert len(data_lines) == 3
assert '"name"' in data_lines[0]
# Keepalive ping tests # Keepalive ping tests
@ -274,8 +304,6 @@ keepalive_app = FastAPI()
@keepalive_app.get("/slow-async", response_class=EventSourceResponse) @keepalive_app.get("/slow-async", response_class=EventSourceResponse)
async def slow_async_stream(): async def slow_async_stream():
yield {"n": 1} yield {"n": 1}
# Sleep longer than the (monkeypatched) ping interval so a keepalive
# comment is emitted before the next item.
await asyncio.sleep(0.3) await asyncio.sleep(0.3)
yield {"n": 2} yield {"n": 2}
@ -293,7 +321,6 @@ def test_keepalive_ping_async(monkeypatch: pytest.MonkeyPatch):
response = c.get("/slow-async") response = c.get("/slow-async")
assert response.status_code == 200 assert response.status_code == 200
text = response.text text = response.text
# The keepalive comment ": ping" should appear between the two data events
assert ": ping\n" in text assert ": ping\n" in text
data_lines = [line for line in text.split("\n") if line.startswith("data: ")] data_lines = [line for line in text.split("\n") if line.startswith("data: ")]
assert len(data_lines) == 2 assert len(data_lines) == 2
@ -314,5 +341,4 @@ def test_no_keepalive_when_fast(client: TestClient):
"""No keepalive comment when items arrive quickly.""" """No keepalive comment when items arrive quickly."""
response = client.get("/items/stream") response = client.get("/items/stream")
assert response.status_code == 200 assert response.status_code == 200
# KEEPALIVE_COMMENT is ": ping\n\n".
assert ": ping\n" not in response.text assert ": ping\n" not in response.text

Loading…
Cancel
Save