|
17 | 17 | import sys |
18 | 18 | import tempfile |
19 | 19 |
|
20 | | -from unittest.mock import Mock, call |
21 | | - |
22 | | -if sys.version_info >= (3, 8): |
23 | | - from unittest.mock import AsyncMock |
| 20 | +from unittest.mock import AsyncMock, Mock, call |
24 | 21 |
|
25 | 22 | import pytest |
26 | 23 |
|
| 24 | +from starlette.testclient import TestClient |
| 25 | + |
27 | 26 | from functions_framework import exceptions |
28 | 27 | from functions_framework.aio import ( |
29 | 28 | LazyASGIApp, |
30 | 29 | _cloudevent_func_wrapper, |
31 | 30 | _http_func_wrapper, |
| 31 | + _is_asgi_app, |
32 | 32 | create_asgi_app, |
33 | 33 | ) |
34 | 34 |
|
@@ -192,3 +192,83 @@ def sync_cloud_event(event): |
192 | 192 | assert called_with_event is not None |
193 | 193 | assert called_with_event["type"] == "test.event" |
194 | 194 | assert called_with_event["source"] == "test-source" |
| 195 | + |
| 196 | + |
| 197 | +def test_detects_starlette_app(): |
| 198 | + from starlette.applications import Starlette |
| 199 | + |
| 200 | + app = Starlette() |
| 201 | + assert _is_asgi_app(app) is True |
| 202 | + |
| 203 | + |
| 204 | +def test_detects_fastapi_app(): |
| 205 | + from fastapi import FastAPI |
| 206 | + |
| 207 | + app = FastAPI() |
| 208 | + assert _is_asgi_app(app) is True |
| 209 | + |
| 210 | + |
| 211 | +def test_detects_bare_asgi_callable(): |
| 212 | + async def asgi_app(scope, receive, send): |
| 213 | + pass |
| 214 | + |
| 215 | + assert _is_asgi_app(asgi_app) is True |
| 216 | + |
| 217 | + |
| 218 | +def test_rejects_non_asgi_functions(): |
| 219 | + def regular_function(request): |
| 220 | + return "response" |
| 221 | + |
| 222 | + async def async_function(request): |
| 223 | + return "response" |
| 224 | + |
| 225 | + async def wrong_params(a, b): |
| 226 | + pass |
| 227 | + |
| 228 | + assert _is_asgi_app(regular_function) is False |
| 229 | + assert _is_asgi_app(async_function) is False |
| 230 | + assert _is_asgi_app(wrong_params) is False |
| 231 | + assert _is_asgi_app("not a function") is False |
| 232 | + |
| 233 | + |
| 234 | +def test_fastapi_app(): |
| 235 | + source = str(TEST_FUNCTIONS_DIR / "asgi_apps" / "fastapi_app.py") |
| 236 | + app = create_asgi_app(target="app", source=source) |
| 237 | + client = TestClient(app) |
| 238 | + |
| 239 | + response = client.get("/") |
| 240 | + assert response.status_code == 200 |
| 241 | + assert response.json() == {"message": "Hello World"} |
| 242 | + |
| 243 | + response = client.get("/items/42") |
| 244 | + assert response.status_code == 200 |
| 245 | + assert response.json() == {"item_id": 42} |
| 246 | + |
| 247 | + |
| 248 | +def test_bare_asgi_app(): |
| 249 | + source = str(TEST_FUNCTIONS_DIR / "asgi_apps" / "bare_asgi.py") |
| 250 | + app = create_asgi_app(target="app", source=source) |
| 251 | + client = TestClient(app) |
| 252 | + |
| 253 | + response = client.get("/") |
| 254 | + assert response.status_code == 200 |
| 255 | + assert response.text == "Hello from ASGI" |
| 256 | + |
| 257 | + |
| 258 | +def test_starlette_app(): |
| 259 | + source = str(TEST_FUNCTIONS_DIR / "asgi_apps" / "starlette_app.py") |
| 260 | + app = create_asgi_app(target="app", source=source) |
| 261 | + client = TestClient(app) |
| 262 | + |
| 263 | + response = client.get("/") |
| 264 | + assert response.status_code == 200 |
| 265 | + assert response.json() == {"message": "Hello from Starlette"} |
| 266 | + |
| 267 | + |
| 268 | +def test_error_handling_in_asgi_app(): |
| 269 | + source = str(TEST_FUNCTIONS_DIR / "asgi_apps" / "fastapi_app.py") |
| 270 | + app = create_asgi_app(target="app", source=source) |
| 271 | + client = TestClient(app) |
| 272 | + |
| 273 | + response = client.get("/nonexistent") |
| 274 | + assert response.status_code == 404 |
0 commit comments