Skip to content

Commit be5143e

Browse files
Add clean SSE client-server test
1 parent ce10f77 commit be5143e

File tree

5 files changed

+103
-6
lines changed

5 files changed

+103
-6
lines changed

tests/requirements-dev.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
fastapi
2+
uvicorn
3+
httpx
4+
httpx-sse
5+
sse-starlette
6+
anyio

tests/test.yml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
name: Run Tests
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
9+
jobs:
10+
test:
11+
runs-on: ubuntu-latest
12+
13+
steps:
14+
- name: Checkout code
15+
uses: actions/checkout@v3
16+
17+
- name: Set up Python
18+
uses: actions/setup-python@v4
19+
with:
20+
python-version: '3.10'
21+
22+
- name: Install main project dependencies
23+
run: |
24+
pip install -r requirements.txt || true
25+
26+
- name: Install dev dependencies
27+
run: |
28+
pip install -r requirements-dev.txt
29+
30+
- name: Run standalone SSE client-server test
31+
run: |
32+
python tests/test_sse_client_server_plain.py

tests/test_sse_client_server.py

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,31 @@
1+
import asyncio
2+
from typing import AsyncGenerator, List
3+
from fastapi import FastAPI
4+
from starlette.responses import StreamingResponse
5+
import uvicorn
6+
from threading import Thread
7+
import httpx
8+
from mcp.client.sse import aconnect_sse
9+
110
app = FastAPI()
211

312
@app.get("/sse")
413
async def sse_endpoint() -> StreamingResponse:
514
async def event_stream() -> AsyncGenerator[str, None]:
615
for i in range(3):
7-
yield f"data: Hello {i+1}\n\n"
16+
yield f"data: Hello {i+1}\\n\\n"
817
await asyncio.sleep(0.1)
918
return StreamingResponse(event_stream(), media_type="text/event-stream")
1019

1120
def run_mock_server() -> None:
1221
uvicorn.run(app, host="127.0.0.1", port=8012, log_level="warning")
1322

14-
async def test_aconnect_sse_server_response() -> None:
23+
async def run_sse_test() -> None:
1524
server_thread = Thread(target=run_mock_server, daemon=True)
1625
server_thread.start()
1726
await asyncio.sleep(1)
1827

1928
messages: List[str] = []
20-
2129
async with httpx.AsyncClient() as client:
2230
async with aconnect_sse(client, "GET", "http://127.0.0.1:8012/sse") as event_source:
2331
async for event in event_source.aiter_sse():
@@ -27,5 +35,11 @@ async def test_aconnect_sse_server_response() -> None:
2735
if len(messages) == 3:
2836
break
2937

30-
assert messages == ["Hello 1", "Hello 2", "Hello 3"]
31-
print("\n Test passed! SSE connection via aconnect_sse worked correctly.")
38+
if messages == ["Hello 1", "Hello 2", "Hello 3"]:
39+
print("\\n Test passed!")
40+
else:
41+
print("\\n Test failed:", messages)
42+
43+
if __name__ == "__main__":
44+
asyncio.run(run_sse_test())
45+

tests/test_sse_client_server_cleaned.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,4 @@ async def test_aconnect_sse_server_response() -> None:
4040
break
4141

4242
assert messages == ["Hello 1", "Hello 2", "Hello 3"]
43-
print("\n Test passed! SSE connection via aconnect_sse worked correctly.")
43+
print("\n Test passed! SSE connection via aconnect_sse worked correctly.")

tests/test_sse_client_server_plain.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import asyncio
2+
from typing import AsyncGenerator, List
3+
4+
from fastapi import FastAPI
5+
from starlette.responses import StreamingResponse
6+
import uvicorn
7+
from threading import Thread
8+
import httpx
9+
from mcp.client.sse import aconnect_sse
10+
11+
app = FastAPI()
12+
13+
@app.get("/sse")
14+
async def sse_endpoint() -> StreamingResponse:
15+
async def event_stream() -> AsyncGenerator[str, None]:
16+
for i in range(3):
17+
yield f"data: Hello {i+1}\n\n"
18+
await asyncio.sleep(0.1)
19+
return StreamingResponse(event_stream(), media_type="text/event-stream")
20+
21+
def run_mock_server() -> None:
22+
uvicorn.run(app, host="127.0.0.1", port=8012, log_level="warning")
23+
24+
async def run_sse_test() -> None:
25+
server_thread = Thread(target=run_mock_server, daemon=True)
26+
server_thread.start()
27+
await asyncio.sleep(1)
28+
29+
messages: List[str] = []
30+
async with httpx.AsyncClient() as client:
31+
async with aconnect_sse(client, "GET", "http://127.0.0.1:8012/sse") as event_source:
32+
async for event in event_source.aiter_sse():
33+
if event.data:
34+
print("Event received:", event.data)
35+
messages.append(event.data)
36+
if len(messages) == 3:
37+
break
38+
39+
if messages == ["Hello 1", "Hello 2", "Hello 3"]:
40+
print("Test passed!")
41+
else:
42+
print("Test failed:", messages)
43+
44+
if __name__ == "__main__":
45+
asyncio.run(run_sse_test())

0 commit comments

Comments
 (0)