sanic/tests/test_routes.py

896 lines
23 KiB
Python
Raw Normal View History

2017-02-20 23:09:54 +00:00
import asyncio
2018-12-13 17:50:50 +00:00
import pytest
2021-01-19 13:54:20 +00:00
from sanic_testing.testing import SanicTestClient
from sanic import Sanic
2017-07-13 04:18:56 +01:00
from sanic.constants import HTTP_METHODS
2018-12-13 17:50:50 +00:00
from sanic.response import json, text
from sanic.router import ParameterNameConflicts, RouteDoesNotExist, RouteExists
# ------------------------------------------------------------ #
# UTF-8
# ------------------------------------------------------------ #
2018-12-30 11:18:06 +00:00
@pytest.mark.parametrize("method", HTTP_METHODS)
2018-08-26 15:43:14 +01:00
def test_versioned_routes_get(app, method):
2017-07-13 04:18:56 +01:00
method = method.lower()
func = getattr(app, method)
if callable(func):
2018-12-30 11:18:06 +00:00
@func(f"/{method}", version=1)
2017-07-13 04:18:56 +01:00
def handler(request):
2018-12-30 11:18:06 +00:00
return text("OK")
2017-07-13 04:18:56 +01:00
else:
print(func)
raise Exception(f"Method: {method} is not callable")
2017-07-13 04:18:56 +01:00
client_method = getattr(app.test_client, method)
request, response = client_method(f"/v1/{method}")
2018-01-08 00:38:54 +00:00
assert response.status == 200
2017-07-13 04:18:56 +01:00
2018-08-26 15:43:14 +01:00
def test_shorthand_routes_get(app):
2018-12-30 11:18:06 +00:00
@app.get("/get")
2017-01-20 07:47:07 +00:00
def handler(request):
2018-12-30 11:18:06 +00:00
return text("OK")
2017-01-20 07:47:07 +00:00
2018-12-30 11:18:06 +00:00
request, response = app.test_client.get("/get")
assert response.text == "OK"
2017-01-20 07:47:07 +00:00
2018-12-30 11:18:06 +00:00
request, response = app.test_client.post("/get")
2017-01-20 18:00:51 +00:00
assert response.status == 405
2017-01-20 07:47:07 +00:00
2018-01-08 00:38:54 +00:00
2018-08-26 15:43:14 +01:00
def test_shorthand_routes_multiple(app):
2018-12-30 11:18:06 +00:00
@app.get("/get")
def get_handler(request):
2018-12-30 11:18:06 +00:00
return text("OK")
2018-12-30 11:18:06 +00:00
@app.options("/get")
def options_handler(request):
2018-12-30 11:18:06 +00:00
return text("")
2018-12-30 11:18:06 +00:00
request, response = app.test_client.get("/get/")
assert response.status == 200
2018-12-30 11:18:06 +00:00
assert response.text == "OK"
2018-12-30 11:18:06 +00:00
request, response = app.test_client.options("/get/")
assert response.status == 200
2018-01-08 00:38:54 +00:00
2018-08-26 15:43:14 +01:00
def test_route_strict_slash(app):
2018-12-30 11:18:06 +00:00
@app.get("/get", strict_slashes=True)
2018-10-22 21:25:38 +01:00
def handler1(request):
2018-12-30 11:18:06 +00:00
return text("OK")
2017-03-16 04:11:45 +00:00
2018-12-30 11:18:06 +00:00
@app.post("/post/", strict_slashes=True)
2018-10-22 21:25:38 +01:00
def handler2(request):
2018-12-30 11:18:06 +00:00
return text("OK")
2017-03-16 04:11:45 +00:00
2018-12-30 11:18:06 +00:00
request, response = app.test_client.get("/get")
assert response.text == "OK"
2017-03-16 04:11:45 +00:00
2018-12-30 11:18:06 +00:00
request, response = app.test_client.get("/get/")
2017-03-16 04:11:45 +00:00
assert response.status == 404
2018-12-30 11:18:06 +00:00
request, response = app.test_client.post("/post/")
assert response.text == "OK"
2017-03-16 04:11:45 +00:00
2018-12-30 11:18:06 +00:00
request, response = app.test_client.post("/post")
2017-03-16 04:11:45 +00:00
assert response.status == 404
2018-01-08 00:38:54 +00:00
2018-08-26 15:43:14 +01:00
def test_route_invalid_parameter_syntax(app):
with pytest.raises(ValueError):
2018-12-30 11:18:06 +00:00
@app.get("/get/<:string>", strict_slashes=True)
def handler(request):
2018-12-30 11:18:06 +00:00
return text("OK")
2018-12-30 11:18:06 +00:00
request, response = app.test_client.get("/get")
2018-01-08 00:38:54 +00:00
2017-08-21 07:37:22 +01:00
def test_route_strict_slash_default_value():
2018-12-30 11:18:06 +00:00
app = Sanic("test_route_strict_slash", strict_slashes=True)
2017-08-21 07:37:22 +01:00
2018-12-30 11:18:06 +00:00
@app.get("/get")
2017-08-21 07:37:22 +01:00
def handler(request):
2018-12-30 11:18:06 +00:00
return text("OK")
2017-08-21 07:37:22 +01:00
2018-12-30 11:18:06 +00:00
request, response = app.test_client.get("/get/")
2017-08-21 07:37:22 +01:00
assert response.status == 404
2018-01-08 00:38:54 +00:00
2018-08-26 15:43:14 +01:00
def test_route_strict_slash_without_passing_default_value(app):
2018-12-30 11:18:06 +00:00
@app.get("/get")
2017-08-21 07:37:22 +01:00
def handler(request):
2018-12-30 11:18:06 +00:00
return text("OK")
2017-08-21 07:37:22 +01:00
2018-12-30 11:18:06 +00:00
request, response = app.test_client.get("/get/")
assert response.text == "OK"
2017-08-21 07:37:22 +01:00
2018-01-08 00:38:54 +00:00
2017-08-21 07:37:22 +01:00
def test_route_strict_slash_default_value_can_be_overwritten():
2018-12-30 11:18:06 +00:00
app = Sanic("test_route_strict_slash", strict_slashes=True)
2017-08-21 07:37:22 +01:00
2018-12-30 11:18:06 +00:00
@app.get("/get", strict_slashes=False)
2017-08-21 07:37:22 +01:00
def handler(request):
2018-12-30 11:18:06 +00:00
return text("OK")
2017-08-21 07:37:22 +01:00
2018-12-30 11:18:06 +00:00
request, response = app.test_client.get("/get/")
assert response.text == "OK"
2017-08-21 07:37:22 +01:00
2018-01-08 00:38:54 +00:00
2018-08-26 15:43:14 +01:00
def test_route_slashes_overload(app):
2018-12-30 11:18:06 +00:00
@app.get("/hello/")
2018-10-22 21:25:38 +01:00
def handler_get(request):
2018-12-30 11:18:06 +00:00
return text("OK")
2018-01-01 10:14:55 +00:00
2018-12-30 11:18:06 +00:00
@app.post("/hello/")
2018-10-22 21:25:38 +01:00
def handler_post(request):
2018-12-30 11:18:06 +00:00
return text("OK")
2018-01-01 10:14:55 +00:00
2018-12-30 11:18:06 +00:00
request, response = app.test_client.get("/hello")
assert response.text == "OK"
2018-01-01 10:14:55 +00:00
2018-12-30 11:18:06 +00:00
request, response = app.test_client.get("/hello/")
assert response.text == "OK"
2018-01-01 10:14:55 +00:00
2018-12-30 11:18:06 +00:00
request, response = app.test_client.post("/hello")
assert response.text == "OK"
2018-01-01 10:14:55 +00:00
2018-12-30 11:18:06 +00:00
request, response = app.test_client.post("/hello/")
assert response.text == "OK"
2018-01-01 10:14:55 +00:00
2018-01-08 00:38:54 +00:00
2018-08-26 15:43:14 +01:00
def test_route_optional_slash(app):
2018-12-30 11:18:06 +00:00
@app.get("/get")
2017-02-20 23:58:27 +00:00
def handler(request):
2018-12-30 11:18:06 +00:00
return text("OK")
2017-02-20 23:58:27 +00:00
2018-12-30 11:18:06 +00:00
request, response = app.test_client.get("/get")
assert response.text == "OK"
2017-02-20 23:58:27 +00:00
2018-12-30 11:18:06 +00:00
request, response = app.test_client.get("/get/")
assert response.text == "OK"
2017-02-20 23:58:27 +00:00
2018-09-29 18:54:47 +01:00
2018-08-26 15:43:14 +01:00
def test_route_strict_slashes_set_to_false_and_host_is_a_list(app):
2018-09-29 18:54:47 +01:00
# Part of regression test for issue #1120
2018-02-09 21:33:34 +00:00
Fix Ctrl+C and tests on Windows. (#1808) * Fix Ctrl+C on Windows. * Disable testing of a function N/A on Windows. * Add test for coverage, avoid crash on missing _stopping. * Initialise StreamingHTTPResponse.protocol = None * Improved comments. * Reduce amount of data in test_request_stream to avoid failures on Windows. * The Windows test doesn't work on Windows :( * Use port numbers more likely to be free than 8000. * Disable the other signal tests on Windows as well. * Windows doesn't properly support SO_REUSEADDR, so that's disabled in Python, and thus rebinding fails. For successful testing, reuse port instead. * app.run argument handling: added server kwargs (alike create_server), added warning on extra kwargs, made auto_reload explicit argument. Another go at Windows tests * Revert "app.run argument handling: added server kwargs (alike create_server), added warning on extra kwargs, made auto_reload explicit argument. Another go at Windows tests" This reverts commit dc5d682448e3f6595bdca5cb764e5f26ca29e295. * Use random test server port on most tests. Should avoid port/addr reuse issues. * Another test to random port instead of 8000. * Fix deprecation warnings about missing name on Sanic() in tests. * Linter and typing * Increase test coverage * Rewrite test for ctrlc_windows_workaround * py36 compat * py36 compat * py36 compat * Don't rely on loop internals but add a stopping flag to app. * App may be restarted. * py36 compat * Linter * Add a constant for OS checking. Co-authored-by: L. Kärkkäinen <tronic@users.noreply.github.com>
2020-03-26 04:42:46 +00:00
test_client = SanicTestClient(app, port=42101)
site1 = f"127.0.0.1:{test_client.port}"
2018-02-09 21:33:34 +00:00
2018-09-29 18:54:47 +01:00
# before fix, this raises a RouteExists error
2018-12-30 11:18:06 +00:00
@app.get("/get", host=[site1, "site2.com"], strict_slashes=False)
2018-10-01 14:46:18 +01:00
def get_handler(request):
2018-12-30 11:18:06 +00:00
return text("OK")
2018-02-09 21:33:34 +00:00
Fix Ctrl+C and tests on Windows. (#1808) * Fix Ctrl+C on Windows. * Disable testing of a function N/A on Windows. * Add test for coverage, avoid crash on missing _stopping. * Initialise StreamingHTTPResponse.protocol = None * Improved comments. * Reduce amount of data in test_request_stream to avoid failures on Windows. * The Windows test doesn't work on Windows :( * Use port numbers more likely to be free than 8000. * Disable the other signal tests on Windows as well. * Windows doesn't properly support SO_REUSEADDR, so that's disabled in Python, and thus rebinding fails. For successful testing, reuse port instead. * app.run argument handling: added server kwargs (alike create_server), added warning on extra kwargs, made auto_reload explicit argument. Another go at Windows tests * Revert "app.run argument handling: added server kwargs (alike create_server), added warning on extra kwargs, made auto_reload explicit argument. Another go at Windows tests" This reverts commit dc5d682448e3f6595bdca5cb764e5f26ca29e295. * Use random test server port on most tests. Should avoid port/addr reuse issues. * Another test to random port instead of 8000. * Fix deprecation warnings about missing name on Sanic() in tests. * Linter and typing * Increase test coverage * Rewrite test for ctrlc_windows_workaround * py36 compat * py36 compat * py36 compat * Don't rely on loop internals but add a stopping flag to app. * App may be restarted. * py36 compat * Linter * Add a constant for OS checking. Co-authored-by: L. Kärkkäinen <tronic@users.noreply.github.com>
2020-03-26 04:42:46 +00:00
request, response = test_client.get("http://" + site1 + "/get")
2018-12-30 11:18:06 +00:00
assert response.text == "OK"
2018-02-09 21:33:34 +00:00
2018-12-30 11:18:06 +00:00
@app.post("/post", host=[site1, "site2.com"], strict_slashes=False)
2018-10-01 14:46:18 +01:00
def post_handler(request):
2018-12-30 11:18:06 +00:00
return text("OK")
2018-02-09 21:33:34 +00:00
Fix Ctrl+C and tests on Windows. (#1808) * Fix Ctrl+C on Windows. * Disable testing of a function N/A on Windows. * Add test for coverage, avoid crash on missing _stopping. * Initialise StreamingHTTPResponse.protocol = None * Improved comments. * Reduce amount of data in test_request_stream to avoid failures on Windows. * The Windows test doesn't work on Windows :( * Use port numbers more likely to be free than 8000. * Disable the other signal tests on Windows as well. * Windows doesn't properly support SO_REUSEADDR, so that's disabled in Python, and thus rebinding fails. For successful testing, reuse port instead. * app.run argument handling: added server kwargs (alike create_server), added warning on extra kwargs, made auto_reload explicit argument. Another go at Windows tests * Revert "app.run argument handling: added server kwargs (alike create_server), added warning on extra kwargs, made auto_reload explicit argument. Another go at Windows tests" This reverts commit dc5d682448e3f6595bdca5cb764e5f26ca29e295. * Use random test server port on most tests. Should avoid port/addr reuse issues. * Another test to random port instead of 8000. * Fix deprecation warnings about missing name on Sanic() in tests. * Linter and typing * Increase test coverage * Rewrite test for ctrlc_windows_workaround * py36 compat * py36 compat * py36 compat * Don't rely on loop internals but add a stopping flag to app. * App may be restarted. * py36 compat * Linter * Add a constant for OS checking. Co-authored-by: L. Kärkkäinen <tronic@users.noreply.github.com>
2020-03-26 04:42:46 +00:00
request, response = test_client.post("http://" + site1 + "/post")
2018-12-30 11:18:06 +00:00
assert response.text == "OK"
2018-02-09 21:33:34 +00:00
2018-12-30 11:18:06 +00:00
@app.put("/put", host=[site1, "site2.com"], strict_slashes=False)
2018-10-01 14:46:18 +01:00
def put_handler(request):
2018-12-30 11:18:06 +00:00
return text("OK")
2018-02-09 21:33:34 +00:00
Fix Ctrl+C and tests on Windows. (#1808) * Fix Ctrl+C on Windows. * Disable testing of a function N/A on Windows. * Add test for coverage, avoid crash on missing _stopping. * Initialise StreamingHTTPResponse.protocol = None * Improved comments. * Reduce amount of data in test_request_stream to avoid failures on Windows. * The Windows test doesn't work on Windows :( * Use port numbers more likely to be free than 8000. * Disable the other signal tests on Windows as well. * Windows doesn't properly support SO_REUSEADDR, so that's disabled in Python, and thus rebinding fails. For successful testing, reuse port instead. * app.run argument handling: added server kwargs (alike create_server), added warning on extra kwargs, made auto_reload explicit argument. Another go at Windows tests * Revert "app.run argument handling: added server kwargs (alike create_server), added warning on extra kwargs, made auto_reload explicit argument. Another go at Windows tests" This reverts commit dc5d682448e3f6595bdca5cb764e5f26ca29e295. * Use random test server port on most tests. Should avoid port/addr reuse issues. * Another test to random port instead of 8000. * Fix deprecation warnings about missing name on Sanic() in tests. * Linter and typing * Increase test coverage * Rewrite test for ctrlc_windows_workaround * py36 compat * py36 compat * py36 compat * Don't rely on loop internals but add a stopping flag to app. * App may be restarted. * py36 compat * Linter * Add a constant for OS checking. Co-authored-by: L. Kärkkäinen <tronic@users.noreply.github.com>
2020-03-26 04:42:46 +00:00
request, response = test_client.put("http://" + site1 + "/put")
2018-12-30 11:18:06 +00:00
assert response.text == "OK"
2018-02-09 21:33:34 +00:00
2018-12-30 11:18:06 +00:00
@app.delete("/delete", host=[site1, "site2.com"], strict_slashes=False)
2018-10-01 14:46:18 +01:00
def delete_handler(request):
2018-12-30 11:18:06 +00:00
return text("OK")
2018-02-09 21:33:34 +00:00
Fix Ctrl+C and tests on Windows. (#1808) * Fix Ctrl+C on Windows. * Disable testing of a function N/A on Windows. * Add test for coverage, avoid crash on missing _stopping. * Initialise StreamingHTTPResponse.protocol = None * Improved comments. * Reduce amount of data in test_request_stream to avoid failures on Windows. * The Windows test doesn't work on Windows :( * Use port numbers more likely to be free than 8000. * Disable the other signal tests on Windows as well. * Windows doesn't properly support SO_REUSEADDR, so that's disabled in Python, and thus rebinding fails. For successful testing, reuse port instead. * app.run argument handling: added server kwargs (alike create_server), added warning on extra kwargs, made auto_reload explicit argument. Another go at Windows tests * Revert "app.run argument handling: added server kwargs (alike create_server), added warning on extra kwargs, made auto_reload explicit argument. Another go at Windows tests" This reverts commit dc5d682448e3f6595bdca5cb764e5f26ca29e295. * Use random test server port on most tests. Should avoid port/addr reuse issues. * Another test to random port instead of 8000. * Fix deprecation warnings about missing name on Sanic() in tests. * Linter and typing * Increase test coverage * Rewrite test for ctrlc_windows_workaround * py36 compat * py36 compat * py36 compat * Don't rely on loop internals but add a stopping flag to app. * App may be restarted. * py36 compat * Linter * Add a constant for OS checking. Co-authored-by: L. Kärkkäinen <tronic@users.noreply.github.com>
2020-03-26 04:42:46 +00:00
request, response = test_client.delete("http://" + site1 + "/delete")
2018-12-30 11:18:06 +00:00
assert response.text == "OK"
2018-01-08 00:38:54 +00:00
2018-10-01 14:46:18 +01:00
2018-08-26 15:43:14 +01:00
def test_shorthand_routes_post(app):
2018-12-30 11:18:06 +00:00
@app.post("/post")
2017-01-20 07:47:07 +00:00
def handler(request):
2018-12-30 11:18:06 +00:00
return text("OK")
2017-01-20 07:47:07 +00:00
2018-12-30 11:18:06 +00:00
request, response = app.test_client.post("/post")
assert response.text == "OK"
2017-01-20 07:47:07 +00:00
2018-12-30 11:18:06 +00:00
request, response = app.test_client.get("/post")
2017-01-20 07:47:07 +00:00
assert response.status == 405
2018-01-08 00:38:54 +00:00
2018-08-26 15:43:14 +01:00
def test_shorthand_routes_put(app):
2018-12-30 11:18:06 +00:00
@app.put("/put")
2017-01-20 18:00:51 +00:00
def handler(request):
2018-12-30 11:18:06 +00:00
return text("OK")
2017-01-20 18:00:51 +00:00
2018-12-30 11:18:06 +00:00
request, response = app.test_client.put("/put")
assert response.text == "OK"
2017-01-20 07:47:07 +00:00
2018-12-30 11:18:06 +00:00
request, response = app.test_client.get("/put")
2017-01-20 07:47:07 +00:00
assert response.status == 405
2018-01-08 00:38:54 +00:00
2018-08-26 15:43:14 +01:00
def test_shorthand_routes_delete(app):
2018-12-30 11:18:06 +00:00
@app.delete("/delete")
def handler(request):
2018-12-30 11:18:06 +00:00
return text("OK")
2018-12-30 11:18:06 +00:00
request, response = app.test_client.delete("/delete")
assert response.text == "OK"
2018-12-30 11:18:06 +00:00
request, response = app.test_client.get("/delete")
assert response.status == 405
2018-01-08 00:38:54 +00:00
2018-08-26 15:43:14 +01:00
def test_shorthand_routes_patch(app):
2018-12-30 11:18:06 +00:00
@app.patch("/patch")
2017-01-20 18:00:51 +00:00
def handler(request):
2018-12-30 11:18:06 +00:00
return text("OK")
2017-01-20 18:00:51 +00:00
2018-12-30 11:18:06 +00:00
request, response = app.test_client.patch("/patch")
assert response.text == "OK"
2017-01-20 07:47:07 +00:00
2018-12-30 11:18:06 +00:00
request, response = app.test_client.get("/patch")
2017-01-20 07:47:07 +00:00
assert response.status == 405
2018-01-08 00:38:54 +00:00
2018-08-26 15:43:14 +01:00
def test_shorthand_routes_head(app):
2018-12-30 11:18:06 +00:00
@app.head("/head")
2017-01-20 18:00:51 +00:00
def handler(request):
2018-12-30 11:18:06 +00:00
return text("OK")
2017-01-20 18:00:51 +00:00
2018-12-30 11:18:06 +00:00
request, response = app.test_client.head("/head")
2017-01-20 18:00:51 +00:00
assert response.status == 200
2017-01-20 07:47:07 +00:00
2018-12-30 11:18:06 +00:00
request, response = app.test_client.get("/head")
2017-01-20 07:47:07 +00:00
assert response.status == 405
2018-01-08 00:38:54 +00:00
2018-08-26 15:43:14 +01:00
def test_shorthand_routes_options(app):
2018-12-30 11:18:06 +00:00
@app.options("/options")
2017-01-20 18:00:51 +00:00
def handler(request):
2018-12-30 11:18:06 +00:00
return text("OK")
2017-01-20 07:47:07 +00:00
2018-12-30 11:18:06 +00:00
request, response = app.test_client.options("/options")
2017-01-20 18:00:51 +00:00
assert response.status == 200
2018-12-30 11:18:06 +00:00
request, response = app.test_client.get("/options")
2017-01-20 18:00:51 +00:00
assert response.status == 405
2017-01-20 07:47:07 +00:00
2018-01-08 00:38:54 +00:00
2018-08-26 15:43:14 +01:00
def test_static_routes(app):
2018-12-30 11:18:06 +00:00
@app.route("/test")
async def handler1(request):
2018-12-30 11:18:06 +00:00
return text("OK1")
2018-12-30 11:18:06 +00:00
@app.route("/pizazz")
async def handler2(request):
2018-12-30 11:18:06 +00:00
return text("OK2")
2018-12-30 11:18:06 +00:00
request, response = app.test_client.get("/test")
assert response.text == "OK1"
2018-12-30 11:18:06 +00:00
request, response = app.test_client.get("/pizazz")
assert response.text == "OK2"
2018-08-26 15:43:14 +01:00
def test_dynamic_route(app):
results = []
2018-12-30 11:18:06 +00:00
@app.route("/folder/<name>")
async def handler(request, name):
results.append(name)
2018-12-30 11:18:06 +00:00
return text("OK")
2018-12-30 11:18:06 +00:00
request, response = app.test_client.get("/folder/test123")
2018-12-30 11:18:06 +00:00
assert response.text == "OK"
assert results[0] == "test123"
2018-08-26 15:43:14 +01:00
def test_dynamic_route_string(app):
results = []
2018-12-30 11:18:06 +00:00
@app.route("/folder/<name:string>")
async def handler(request, name):
results.append(name)
2018-12-30 11:18:06 +00:00
return text("OK")
2018-12-30 11:18:06 +00:00
request, response = app.test_client.get("/folder/test123")
2018-12-30 11:18:06 +00:00
assert response.text == "OK"
assert results[0] == "test123"
2018-12-30 11:18:06 +00:00
request, response = app.test_client.get("/folder/favicon.ico")
2016-10-16 21:41:56 +01:00
2018-12-30 11:18:06 +00:00
assert response.text == "OK"
assert results[1] == "favicon.ico"
2016-10-16 21:41:56 +01:00
2018-08-26 15:43:14 +01:00
def test_dynamic_route_int(app):
results = []
2018-12-30 11:18:06 +00:00
@app.route("/folder/<folder_id:int>")
async def handler(request, folder_id):
results.append(folder_id)
2018-12-30 11:18:06 +00:00
return text("OK")
2018-12-30 11:18:06 +00:00
request, response = app.test_client.get("/folder/12345")
assert response.text == "OK"
assert type(results[0]) is int
2018-12-30 11:18:06 +00:00
request, response = app.test_client.get("/folder/asdf")
assert response.status == 404
2018-08-26 15:43:14 +01:00
def test_dynamic_route_number(app):
results = []
2018-12-30 11:18:06 +00:00
@app.route("/weight/<weight:number>")
async def handler(request, weight):
results.append(weight)
2018-12-30 11:18:06 +00:00
return text("OK")
2018-12-30 11:18:06 +00:00
request, response = app.test_client.get("/weight/12345")
assert response.text == "OK"
assert type(results[0]) is float
2018-12-30 11:18:06 +00:00
request, response = app.test_client.get("/weight/1234.56")
assert response.status == 200
request, response = app.test_client.get("/weight/.12")
assert response.status == 200
request, response = app.test_client.get("/weight/12.")
assert response.status == 200
2018-12-30 11:18:06 +00:00
request, response = app.test_client.get("/weight/1234-56")
assert response.status == 404
request, response = app.test_client.get("/weight/12.34.56")
assert response.status == 404
2018-08-26 15:43:14 +01:00
def test_dynamic_route_regex(app):
2018-12-30 11:18:06 +00:00
@app.route("/folder/<folder_id:[A-Za-z0-9]{0,4}>")
async def handler(request, folder_id):
2018-12-30 11:18:06 +00:00
return text("OK")
2018-12-30 11:18:06 +00:00
request, response = app.test_client.get("/folder/test")
assert response.status == 200
2018-12-30 11:18:06 +00:00
request, response = app.test_client.get("/folder/test1")
assert response.status == 404
2018-12-30 11:18:06 +00:00
request, response = app.test_client.get("/folder/test-123")
assert response.status == 404
2018-12-30 11:18:06 +00:00
request, response = app.test_client.get("/folder/")
assert response.status == 200
2018-08-26 15:43:14 +01:00
def test_dynamic_route_uuid(app):
2018-06-09 09:16:17 +01:00
import uuid
results = []
2018-12-30 11:18:06 +00:00
@app.route("/quirky/<unique_id:uuid>")
2018-06-09 09:16:17 +01:00
async def handler(request, unique_id):
results.append(unique_id)
2018-12-30 11:18:06 +00:00
return text("OK")
2018-06-09 09:16:17 +01:00
2018-12-30 11:18:06 +00:00
url = "/quirky/123e4567-e89b-12d3-a456-426655440000"
2018-10-22 21:25:38 +01:00
request, response = app.test_client.get(url)
2018-12-30 11:18:06 +00:00
assert response.text == "OK"
2018-06-09 09:16:17 +01:00
assert type(results[0]) is uuid.UUID
generated_uuid = uuid.uuid4()
request, response = app.test_client.get(f"/quirky/{generated_uuid}")
2018-06-09 09:16:17 +01:00
assert response.status == 200
2018-12-30 11:18:06 +00:00
request, response = app.test_client.get("/quirky/non-existing")
2018-06-09 09:16:17 +01:00
assert response.status == 404
2018-08-26 15:43:14 +01:00
def test_dynamic_route_path(app):
2018-12-30 11:18:06 +00:00
@app.route("/<path:path>/info")
2017-04-13 04:34:35 +01:00
async def handler(request, path):
2018-12-30 11:18:06 +00:00
return text("OK")
2017-04-13 04:34:35 +01:00
2018-12-30 11:18:06 +00:00
request, response = app.test_client.get("/path/1/info")
2017-04-13 04:34:35 +01:00
assert response.status == 200
2018-12-30 11:18:06 +00:00
request, response = app.test_client.get("/info")
2017-04-13 04:34:35 +01:00
assert response.status == 404
2018-12-30 11:18:06 +00:00
@app.route("/<path:path>")
2017-04-13 04:34:35 +01:00
async def handler1(request, path):
2018-12-30 11:18:06 +00:00
return text("OK")
2017-04-13 04:34:35 +01:00
2018-12-30 11:18:06 +00:00
request, response = app.test_client.get("/info")
2017-04-13 04:34:35 +01:00
assert response.status == 200
2018-12-30 11:18:06 +00:00
request, response = app.test_client.get("/whatever/you/set")
2017-04-13 04:34:35 +01:00
assert response.status == 200
2018-08-26 15:43:14 +01:00
def test_dynamic_route_unhashable(app):
2018-12-30 11:18:06 +00:00
@app.route("/folder/<unhashable:[A-Za-z0-9/]+>/end/")
async def handler(request, unhashable):
2018-12-30 11:18:06 +00:00
return text("OK")
2018-12-30 11:18:06 +00:00
request, response = app.test_client.get("/folder/test/asdf/end/")
assert response.status == 200
2018-12-30 11:18:06 +00:00
request, response = app.test_client.get("/folder/test///////end/")
assert response.status == 200
2018-12-30 11:18:06 +00:00
request, response = app.test_client.get("/folder/test/end/")
assert response.status == 200
2018-12-30 11:18:06 +00:00
request, response = app.test_client.get("/folder/test/nope/")
assert response.status == 404
2018-12-30 11:18:06 +00:00
@pytest.mark.parametrize("url", ["/ws", "ws"])
2018-12-13 17:50:50 +00:00
def test_websocket_route(app, url):
2017-02-20 23:09:54 +00:00
ev = asyncio.Event()
2018-12-13 17:50:50 +00:00
@app.websocket(url)
2017-02-20 23:09:54 +00:00
async def handler(request, ws):
2018-12-30 11:18:06 +00:00
assert request.scheme == "ws"
assert ws.subprotocol is None
2017-02-20 23:09:54 +00:00
ev.set()
request, response = app.test_client.websocket(url)
assert response.opened is True
2017-02-20 23:09:54 +00:00
assert ev.is_set()
@pytest.mark.asyncio
@pytest.mark.parametrize("url", ["/ws", "ws"])
async def test_websocket_route_asgi(app, url):
ev = asyncio.Event()
@app.websocket(url)
async def handler(request, ws):
ev.set()
request, response = await app.asgi_client.websocket(url)
assert ev.is_set()
2018-08-26 15:43:14 +01:00
def test_websocket_route_with_subprotocols(app):
results = []
2018-12-30 11:18:06 +00:00
@app.websocket("/ws", subprotocols=["foo", "bar"])
async def handler(request, ws):
results.append(ws.subprotocol)
assert ws.subprotocol is not None
request, response = app.test_client.websocket("/ws", subprotocols=["bar"])
assert response.opened is True
assert results == ["bar"]
request, response = app.test_client.websocket(
"/ws", subprotocols=["bar", "foo"]
2018-12-30 11:18:06 +00:00
)
assert response.opened is True
assert results == ["bar", "bar"]
request, response = app.test_client.websocket("/ws", subprotocols=["baz"])
assert response.opened is True
assert results == ["bar", "bar", None]
request, response = app.test_client.websocket("/ws")
assert response.opened is True
2018-12-30 11:18:06 +00:00
assert results == ["bar", "bar", None, None]
2018-12-30 11:18:06 +00:00
@pytest.mark.parametrize("strict_slashes", [True, False, None])
2018-12-13 17:50:50 +00:00
def test_add_webscoket_route(app, strict_slashes):
ev = asyncio.Event()
async def handler(request, ws):
assert ws.subprotocol is None
ev.set()
2018-12-30 11:18:06 +00:00
app.add_websocket_route(handler, "/ws", strict_slashes=strict_slashes)
request, response = app.test_client.websocket("/ws")
assert response.opened is True
2018-12-13 17:50:50 +00:00
assert ev.is_set()
def test_add_webscoket_route_with_version(app):
ev = asyncio.Event()
async def handler(request, ws):
assert ws.subprotocol is None
ev.set()
app.add_websocket_route(handler, "/ws", version=1)
request, response = app.test_client.websocket("/v1/ws")
assert response.opened is True
assert ev.is_set()
2018-08-26 15:43:14 +01:00
def test_route_duplicate(app):
with pytest.raises(RouteExists):
2018-12-30 11:18:06 +00:00
@app.route("/test")
async def handler1(request):
pass
2018-12-30 11:18:06 +00:00
@app.route("/test")
async def handler2(request):
pass
with pytest.raises(RouteExists):
2018-12-30 11:18:06 +00:00
@app.route("/test/<dynamic>/")
2018-10-22 21:25:38 +01:00
async def handler3(request, dynamic):
pass
2018-12-30 11:18:06 +00:00
@app.route("/test/<dynamic>/")
2018-10-22 21:25:38 +01:00
async def handler4(request, dynamic):
pass
def test_double_stack_route(app):
@app.route("/test/1")
@app.route("/test/2")
async def handler1(request):
return text("OK")
request, response = app.test_client.get("/test/1")
assert response.status == 200
request, response = app.test_client.get("/test/2")
assert response.status == 200
@pytest.mark.asyncio
async def test_websocket_route_asgi(app):
ev = asyncio.Event()
@app.websocket("/test/1")
@app.websocket("/test/2")
async def handler(request, ws):
ev.set()
request, response = await app.asgi_client.websocket("/test/1")
first_set = ev.is_set()
ev.clear()
request, response = await app.asgi_client.websocket("/test/1")
second_set = ev.is_set()
assert first_set and second_set
2018-08-26 15:43:14 +01:00
def test_method_not_allowed(app):
2018-12-30 11:18:06 +00:00
@app.route("/test", methods=["GET"])
async def handler(request):
2018-12-30 11:18:06 +00:00
return text("OK")
2018-12-30 11:18:06 +00:00
request, response = app.test_client.get("/test")
assert response.status == 200
2018-12-30 11:18:06 +00:00
request, response = app.test_client.post("/test")
assert response.status == 405
2018-12-30 11:18:06 +00:00
@pytest.mark.parametrize("strict_slashes", [True, False, None])
2018-12-13 17:50:50 +00:00
def test_static_add_route(app, strict_slashes):
async def handler1(request):
2018-12-30 11:18:06 +00:00
return text("OK1")
async def handler2(request):
2018-12-30 11:18:06 +00:00
return text("OK2")
2018-12-30 11:18:06 +00:00
app.add_route(handler1, "/test", strict_slashes=strict_slashes)
app.add_route(handler2, "/test2", strict_slashes=strict_slashes)
2018-12-30 11:18:06 +00:00
request, response = app.test_client.get("/test")
assert response.text == "OK1"
2018-12-30 11:18:06 +00:00
request, response = app.test_client.get("/test2")
assert response.text == "OK2"
2018-08-26 15:43:14 +01:00
def test_dynamic_add_route(app):
results = []
async def handler(request, name):
results.append(name)
2018-12-30 11:18:06 +00:00
return text("OK")
2018-12-30 11:18:06 +00:00
app.add_route(handler, "/folder/<name>")
request, response = app.test_client.get("/folder/test123")
2018-12-30 11:18:06 +00:00
assert response.text == "OK"
assert results[0] == "test123"
2018-08-26 15:43:14 +01:00
def test_dynamic_add_route_string(app):
results = []
async def handler(request, name):
results.append(name)
2018-12-30 11:18:06 +00:00
return text("OK")
2018-12-30 11:18:06 +00:00
app.add_route(handler, "/folder/<name:string>")
request, response = app.test_client.get("/folder/test123")
2018-12-30 11:18:06 +00:00
assert response.text == "OK"
assert results[0] == "test123"
2018-12-30 11:18:06 +00:00
request, response = app.test_client.get("/folder/favicon.ico")
2018-12-30 11:18:06 +00:00
assert response.text == "OK"
assert results[1] == "favicon.ico"
2018-08-26 15:43:14 +01:00
def test_dynamic_add_route_int(app):
results = []
async def handler(request, folder_id):
results.append(folder_id)
2018-12-30 11:18:06 +00:00
return text("OK")
2018-12-30 11:18:06 +00:00
app.add_route(handler, "/folder/<folder_id:int>")
2018-12-30 11:18:06 +00:00
request, response = app.test_client.get("/folder/12345")
assert response.text == "OK"
assert type(results[0]) is int
2018-12-30 11:18:06 +00:00
request, response = app.test_client.get("/folder/asdf")
assert response.status == 404
2018-08-26 15:43:14 +01:00
def test_dynamic_add_route_number(app):
results = []
async def handler(request, weight):
results.append(weight)
2018-12-30 11:18:06 +00:00
return text("OK")
2018-12-30 11:18:06 +00:00
app.add_route(handler, "/weight/<weight:number>")
2018-12-30 11:18:06 +00:00
request, response = app.test_client.get("/weight/12345")
assert response.text == "OK"
assert type(results[0]) is float
2018-12-30 11:18:06 +00:00
request, response = app.test_client.get("/weight/1234.56")
assert response.status == 200
request, response = app.test_client.get("/weight/.12")
assert response.status == 200
request, response = app.test_client.get("/weight/12.")
assert response.status == 200
2018-12-30 11:18:06 +00:00
request, response = app.test_client.get("/weight/1234-56")
assert response.status == 404
request, response = app.test_client.get("/weight/12.34.56")
assert response.status == 404
2018-08-26 15:43:14 +01:00
def test_dynamic_add_route_regex(app):
async def handler(request, folder_id):
2018-12-30 11:18:06 +00:00
return text("OK")
2018-12-30 11:18:06 +00:00
app.add_route(handler, "/folder/<folder_id:[A-Za-z0-9]{0,4}>")
2018-12-30 11:18:06 +00:00
request, response = app.test_client.get("/folder/test")
assert response.status == 200
2018-12-30 11:18:06 +00:00
request, response = app.test_client.get("/folder/test1")
assert response.status == 404
2018-12-30 11:18:06 +00:00
request, response = app.test_client.get("/folder/test-123")
assert response.status == 404
2018-12-30 11:18:06 +00:00
request, response = app.test_client.get("/folder/")
assert response.status == 200
2018-08-26 15:43:14 +01:00
def test_dynamic_add_route_unhashable(app):
async def handler(request, unhashable):
2018-12-30 11:18:06 +00:00
return text("OK")
2018-12-30 11:18:06 +00:00
app.add_route(handler, "/folder/<unhashable:[A-Za-z0-9/]+>/end/")
2018-12-30 11:18:06 +00:00
request, response = app.test_client.get("/folder/test/asdf/end/")
assert response.status == 200
2018-12-30 11:18:06 +00:00
request, response = app.test_client.get("/folder/test///////end/")
assert response.status == 200
2018-12-30 11:18:06 +00:00
request, response = app.test_client.get("/folder/test/end/")
assert response.status == 200
2018-12-30 11:18:06 +00:00
request, response = app.test_client.get("/folder/test/nope/")
assert response.status == 404
2018-08-26 15:43:14 +01:00
def test_add_route_duplicate(app):
with pytest.raises(RouteExists):
2018-12-30 11:18:06 +00:00
async def handler1(request):
pass
async def handler2(request):
pass
2018-12-30 11:18:06 +00:00
app.add_route(handler1, "/test")
app.add_route(handler2, "/test")
with pytest.raises(RouteExists):
2018-12-30 11:18:06 +00:00
async def handler1(request, dynamic):
pass
async def handler2(request, dynamic):
pass
2018-12-30 11:18:06 +00:00
app.add_route(handler1, "/test/<dynamic>/")
app.add_route(handler2, "/test/<dynamic>/")
2018-08-26 15:43:14 +01:00
def test_add_route_method_not_allowed(app):
async def handler(request):
2018-12-30 11:18:06 +00:00
return text("OK")
2018-12-30 11:18:06 +00:00
app.add_route(handler, "/test", methods=["GET"])
2018-12-30 11:18:06 +00:00
request, response = app.test_client.get("/test")
assert response.status == 200
2018-12-30 11:18:06 +00:00
request, response = app.test_client.post("/test")
assert response.status == 405
2018-08-26 15:43:14 +01:00
def test_removing_slash(app):
2018-12-30 11:18:06 +00:00
@app.get("/rest/<resource>")
2017-02-28 03:54:58 +00:00
def get(_):
pass
2018-12-30 11:18:06 +00:00
@app.post("/rest/<resource>")
2017-02-28 03:54:58 +00:00
def post(_):
pass
assert len(app.router.routes_all.keys()) == 2
2018-08-26 15:43:14 +01:00
def test_overload_routes(app):
2018-12-30 11:18:06 +00:00
@app.route("/overload", methods=["GET"])
async def handler1(request):
2018-12-30 11:18:06 +00:00
return text("OK1")
2018-12-30 11:18:06 +00:00
@app.route("/overload", methods=["POST", "PUT"])
async def handler2(request):
2018-12-30 11:18:06 +00:00
return text("OK2")
2018-12-30 11:18:06 +00:00
request, response = app.test_client.get("/overload")
assert response.text == "OK1"
2018-12-30 11:18:06 +00:00
request, response = app.test_client.post("/overload")
assert response.text == "OK2"
2018-12-30 11:18:06 +00:00
request, response = app.test_client.put("/overload")
assert response.text == "OK2"
2018-12-30 11:18:06 +00:00
request, response = app.test_client.delete("/overload")
assert response.status == 405
with pytest.raises(RouteExists):
2018-12-30 11:18:06 +00:00
@app.route("/overload", methods=["PUT", "DELETE"])
async def handler3(request):
2018-12-30 11:18:06 +00:00
return text("Duplicated")
2018-08-26 15:43:14 +01:00
def test_unmergeable_overload_routes(app):
2018-12-30 11:18:06 +00:00
@app.route("/overload_whole", methods=None)
async def handler1(request):
2018-12-30 11:18:06 +00:00
return text("OK1")
with pytest.raises(RouteExists):
2018-12-30 11:18:06 +00:00
@app.route("/overload_whole", methods=["POST", "PUT"])
async def handler2(request):
2018-12-30 11:18:06 +00:00
return text("Duplicated")
2018-12-30 11:18:06 +00:00
request, response = app.test_client.get("/overload_whole")
assert response.text == "OK1"
2018-12-30 11:18:06 +00:00
request, response = app.test_client.post("/overload_whole")
assert response.text == "OK1"
2018-12-30 11:18:06 +00:00
@app.route("/overload_part", methods=["GET"])
2018-10-22 21:25:38 +01:00
async def handler3(request):
2018-12-30 11:18:06 +00:00
return text("OK1")
with pytest.raises(RouteExists):
2018-12-30 11:18:06 +00:00
@app.route("/overload_part")
2018-10-22 21:25:38 +01:00
async def handler4(request):
2018-12-30 11:18:06 +00:00
return text("Duplicated")
2018-12-30 11:18:06 +00:00
request, response = app.test_client.get("/overload_part")
assert response.text == "OK1"
2018-12-30 11:18:06 +00:00
request, response = app.test_client.post("/overload_part")
assert response.status == 405
2018-01-08 00:38:54 +00:00
2018-08-26 15:43:14 +01:00
def test_unicode_routes(app):
2018-12-30 11:18:06 +00:00
@app.get("/你好")
2018-01-08 00:38:54 +00:00
def handler1(request):
2018-12-30 11:18:06 +00:00
return text("OK1")
2018-01-08 00:38:54 +00:00
2018-12-30 11:18:06 +00:00
request, response = app.test_client.get("/你好")
assert response.text == "OK1"
2018-01-08 00:38:54 +00:00
2018-12-30 11:18:06 +00:00
@app.route("/overload/<param>", methods=["GET"])
2018-01-08 00:38:54 +00:00
async def handler2(request, param):
2018-12-30 11:18:06 +00:00
return text("OK2 " + param)
2018-01-08 00:38:54 +00:00
2018-12-30 11:18:06 +00:00
request, response = app.test_client.get("/overload/你好")
assert response.text == "OK2 你好"
2018-08-26 15:43:14 +01:00
def test_uri_with_different_method_and_different_params(app):
2018-12-30 11:18:06 +00:00
@app.route("/ads/<ad_id>", methods=["GET"])
async def ad_get(request, ad_id):
2018-12-30 11:18:06 +00:00
return json({"ad_id": ad_id})
2018-12-30 11:18:06 +00:00
@app.route("/ads/<action>", methods=["POST"])
async def ad_post(request, action):
2018-12-30 11:18:06 +00:00
return json({"action": action})
2018-12-30 11:18:06 +00:00
request, response = app.test_client.get("/ads/1234")
assert response.status == 200
2018-12-30 11:18:06 +00:00
assert response.json == {"ad_id": "1234"}
2018-12-30 11:18:06 +00:00
request, response = app.test_client.post("/ads/post")
assert response.status == 200
2018-12-30 11:18:06 +00:00
assert response.json == {"action": "post"}
def test_route_raise_ParameterNameConflicts(app):
with pytest.raises(ParameterNameConflicts):
2018-12-30 11:18:06 +00:00
@app.get("/api/v1/<user>/<user>/")
def handler(request, user):
2018-12-30 11:18:06 +00:00
return text("OK")
def test_route_invalid_host(app):
host = 321
with pytest.raises(ValueError) as excinfo:
2018-12-30 11:18:06 +00:00
@app.get("/test", host=host)
def handler(request):
2018-12-30 11:18:06 +00:00
return text("pass")
assert str(excinfo.value) == (
2018-12-30 11:18:06 +00:00
"Expected either string or Iterable of " "host strings, not {!r}"
).format(host)