1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236
|
from __future__ import annotations
from collections.abc import AsyncGenerator
from typing import cast
import pytest
from werkzeug.wrappers import Response as WerkzeugResponse
from quart import abort
from quart import jsonify
from quart import Quart
from quart import request
from quart import Response
from quart import ResponseReturnValue
from quart import url_for
from quart import websocket
from quart.testing import WebsocketResponseError
@pytest.fixture
def app() -> Quart:
app = Quart(__name__)
@app.route("/")
async def index() -> ResponseReturnValue:
return "index"
@app.route("/❤️")
async def iri() -> ResponseReturnValue:
return "💔"
@app.route("/sync/")
def sync() -> ResponseReturnValue:
return "index"
@app.route("/json/", methods=["POST"])
async def json() -> ResponseReturnValue:
data = await request.get_json()
return jsonify(data)
@app.route("/implicit_json/", methods=["POST"])
async def implicit_json() -> ResponseReturnValue:
data = await request.get_json()
return data
@app.route("/werkzeug/")
async def werkzeug() -> ResponseReturnValue:
return WerkzeugResponse(b"Hello")
@app.route("/error/")
async def error() -> ResponseReturnValue:
abort(409)
return "OK"
@app.route("/param/<value>")
async def param(value: str) -> ResponseReturnValue:
return value
@app.route("/stream")
async def stream() -> ResponseReturnValue:
async def _gen() -> AsyncGenerator[str, None]:
yield "Hello "
yield "World"
return _gen() # type: ignore
@app.errorhandler(409)
async def generic_http_handler(_: Exception) -> ResponseReturnValue:
return "Something Unique", 409
@app.errorhandler(404)
async def not_found_handler(_: Exception) -> ResponseReturnValue:
return "Not Found", 404
@app.websocket("/ws/")
async def ws() -> None:
# async for message in websocket:
while True:
message = await websocket.receive()
await websocket.send(message)
@app.websocket("/ws/abort/")
async def ws_abort() -> None:
abort(401)
return app
@pytest.mark.parametrize("path", ["/", "/sync/"])
async def test_index(path: str, app: Quart) -> None:
test_client = app.test_client()
response = await test_client.get(path)
assert response.status_code == 200
assert b"index" in (await response.get_data())
async def test_iri(app: Quart) -> None:
test_client = app.test_client()
response = await test_client.get("/❤️")
assert "💔".encode() in (await response.get_data())
async def test_options(app: Quart) -> None:
test_client = app.test_client()
response = await test_client.options("/")
assert response.status_code == 200
assert {method.strip() for method in response.headers["Allow"].split(",")} == {
"HEAD",
"OPTIONS",
"GET",
}
async def test_json(app: Quart) -> None:
test_client = app.test_client()
response = await test_client.post("/json/", json={"value": "json"})
assert response.status_code == 200
assert b'{"value":"json"}\n' == (await response.get_data())
async def test_implicit_json(app: Quart) -> None:
test_client = app.test_client()
response = await test_client.post("/implicit_json/", json={"value": "json"})
assert response.status_code == 200
assert b'{"value":"json"}\n' == (await response.get_data())
async def test_implicit_json_list(app: Quart) -> None:
test_client = app.test_client()
response = await test_client.post("/implicit_json/", json=["a", 2])
assert response.status_code == 200
assert b'["a",2]\n' == (await response.get_data())
async def test_werkzeug(app: Quart) -> None:
test_client = app.test_client()
response = await test_client.get("/werkzeug/")
assert response.status_code == 200
assert b"Hello" == (await response.get_data())
async def test_generic_error(app: Quart) -> None:
test_client = app.test_client()
response = await test_client.get("/error/")
assert response.status_code == 409
assert b"Something Unique" in (await response.get_data())
async def test_url_defaults(app: Quart) -> None:
@app.url_defaults
def defaults(_: str, values: dict) -> None:
values["value"] = "hello"
async with app.test_request_context("/"):
assert url_for("param") == "/param/hello"
async def test_not_found_error(app: Quart) -> None:
test_client = app.test_client()
response = await test_client.get("/not_found/")
assert response.status_code == 404
assert b"Not Found" in (await response.get_data())
async def test_make_response_str(app: Quart) -> None:
response = await app.make_response("Result")
assert response.status_code == 200
assert (await response.get_data()) == b"Result" # type: ignore
response = await app.make_response(("Result", 200))
response = await app.make_response(("Result", {"name": "value"}))
assert response.status_code == 200
assert (await response.get_data()) == b"Result" # type: ignore
assert response.headers["name"] == "value"
response = await app.make_response(("Result", 404, {"name": "value"}))
assert response.status_code == 404
assert (await response.get_data()) == b"Result" # type: ignore
assert response.headers["name"] == "value"
async def test_make_response_response(app: Quart) -> None:
response = await app.make_response(Response("Result"))
assert response.status_code == 200
assert (await response.get_data()) == b"Result" # type: ignore
response = await app.make_response((Response("Result"), {"name": "value"}))
assert response.status_code == 200
assert (await response.get_data()) == b"Result" # type: ignore
assert response.headers["name"] == "value"
response = await app.make_response((Response("Result"), 404, {"name": "value"}))
assert response.status_code == 404
assert (await response.get_data()) == b"Result" # type: ignore
assert response.headers["name"] == "value"
async def test_make_response_errors(app: Quart) -> None:
with pytest.raises(TypeError):
await app.make_response(("Result", {"name": "value"}, 200)) # type: ignore
with pytest.raises(TypeError):
await app.make_response(("Result", {"name": "value"}, 200, "a")) # type: ignore
with pytest.raises(TypeError):
await app.make_response(("Result",)) # type: ignore
async def test_websocket(app: Quart) -> None:
test_client = app.test_client()
data = b"bob"
async with test_client.websocket("/ws/") as test_websocket:
await test_websocket.send(data)
result = await test_websocket.receive()
assert cast(bytes, result) == data
async def test_websocket_abort(app: Quart) -> None:
test_client = app.test_client()
try:
async with test_client.websocket("/ws/abort/") as test_websocket:
await test_websocket.receive()
except WebsocketResponseError as error:
assert error.response.status_code == 401
async def test_root_path(app: Quart) -> None:
test_client = app.test_client()
response = await test_client.get("/", root_path="/bob")
assert response.status_code == 404
response = await test_client.get("/bob/", root_path="/bob")
assert response.status_code == 200
async def test_stream(app: Quart) -> None:
test_client = app.test_client()
response = await test_client.get("/stream")
assert (await response.get_data()) == b"Hello World"
|