sanic/tests/test_named_routes.py
2017-08-21 18:05:34 +08:00

392 lines
12 KiB
Python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import asyncio
import pytest
from sanic import Sanic
from sanic.blueprints import Blueprint
from sanic.response import text
from sanic.router import RouteExists, RouteDoesNotExist
from sanic.exceptions import URLBuildError
from sanic.constants import HTTP_METHODS
# ------------------------------------------------------------ #
# UTF-8
# ------------------------------------------------------------ #
@pytest.mark.parametrize('method', HTTP_METHODS)
def test_versioned_named_routes_get(method):
app = Sanic('test_shorhand_routes_get')
bp = Blueprint('test_bp', url_prefix='/bp')
method = method.lower()
route_name = 'route_{}'.format(method)
route_name2 = 'route2_{}'.format(method)
func = getattr(app, method)
if callable(func):
@func('/{}'.format(method), version=1, name=route_name)
def handler(request):
return text('OK')
else:
print(func)
raise
func = getattr(bp, method)
if callable(func):
@func('/{}'.format(method), version=1, name=route_name2)
def handler2(request):
return text('OK')
else:
print(func)
raise
app.blueprint(bp)
assert app.router.routes_all['/v1/{}'.format(method)].name == route_name
route = app.router.routes_all['/v1/bp/{}'.format(method)]
assert route.name == 'test_bp.{}'.format(route_name2)
assert app.url_for(route_name) == '/v1/{}'.format(method)
url = app.url_for('test_bp.{}'.format(route_name2))
assert url == '/v1/bp/{}'.format(method)
with pytest.raises(URLBuildError):
app.url_for('handler')
def test_shorthand_default_routes_get():
app = Sanic('test_shorhand_routes_get')
@app.get('/get')
def handler(request):
return text('OK')
assert app.router.routes_all['/get'].name == 'handler'
assert app.url_for('handler') == '/get'
def test_shorthand_named_routes_get():
app = Sanic('test_shorhand_routes_get')
bp = Blueprint('test_bp', url_prefix='/bp')
@app.get('/get', name='route_get')
def handler(request):
return text('OK')
@bp.get('/get', name='route_bp')
def handler2(request):
return text('Blueprint')
app.blueprint(bp)
assert app.router.routes_all['/get'].name == 'route_get'
assert app.url_for('route_get') == '/get'
with pytest.raises(URLBuildError):
app.url_for('handler')
assert app.router.routes_all['/bp/get'].name == 'test_bp.route_bp'
assert app.url_for('test_bp.route_bp') == '/bp/get'
with pytest.raises(URLBuildError):
app.url_for('test_bp.handler2')
def test_shorthand_named_routes_post():
app = Sanic('test_shorhand_routes_post')
@app.post('/post', name='route_name')
def handler(request):
return text('OK')
assert app.router.routes_all['/post'].name == 'route_name'
assert app.url_for('route_name') == '/post'
with pytest.raises(URLBuildError):
app.url_for('handler')
def test_shorthand_named_routes_put():
app = Sanic('test_shorhand_routes_put')
@app.put('/put', name='route_put')
def handler(request):
assert request.stream is None
return text('OK')
assert app.is_request_stream is False
assert app.router.routes_all['/put'].name == 'route_put'
assert app.url_for('route_put') == '/put'
with pytest.raises(URLBuildError):
app.url_for('handler')
def test_shorthand_named_routes_delete():
app = Sanic('test_shorhand_routes_delete')
@app.delete('/delete', name='route_delete')
def handler(request):
assert request.stream is None
return text('OK')
assert app.is_request_stream is False
assert app.router.routes_all['/delete'].name == 'route_delete'
assert app.url_for('route_delete') == '/delete'
with pytest.raises(URLBuildError):
app.url_for('handler')
def test_shorthand_named_routes_patch():
app = Sanic('test_shorhand_routes_patch')
@app.patch('/patch', name='route_patch')
def handler(request):
assert request.stream is None
return text('OK')
assert app.is_request_stream is False
assert app.router.routes_all['/patch'].name == 'route_patch'
assert app.url_for('route_patch') == '/patch'
with pytest.raises(URLBuildError):
app.url_for('handler')
def test_shorthand_named_routes_head():
app = Sanic('test_shorhand_routes_head')
@app.head('/head', name='route_head')
def handler(request):
assert request.stream is None
return text('OK')
assert app.is_request_stream is False
assert app.router.routes_all['/head'].name == 'route_head'
assert app.url_for('route_head') == '/head'
with pytest.raises(URLBuildError):
app.url_for('handler')
def test_shorthand_named_routes_options():
app = Sanic('test_shorhand_routes_options')
@app.options('/options', name='route_options')
def handler(request):
assert request.stream is None
return text('OK')
assert app.is_request_stream is False
assert app.router.routes_all['/options'].name == 'route_options'
assert app.url_for('route_options') == '/options'
with pytest.raises(URLBuildError):
app.url_for('handler')
def test_named_static_routes():
app = Sanic('test_dynamic_route')
@app.route('/test', name='route_test')
async def handler1(request):
return text('OK1')
@app.route('/pizazz', name='route_pizazz')
async def handler2(request):
return text('OK2')
assert app.router.routes_all['/test'].name == 'route_test'
assert app.router.routes_static['/test'].name == 'route_test'
assert app.url_for('route_test') == '/test'
with pytest.raises(URLBuildError):
app.url_for('handler1')
assert app.router.routes_all['/pizazz'].name == 'route_pizazz'
assert app.router.routes_static['/pizazz'].name == 'route_pizazz'
assert app.url_for('route_pizazz') == '/pizazz'
with pytest.raises(URLBuildError):
app.url_for('handler2')
def test_named_dynamic_route():
app = Sanic('test_dynamic_route')
results = []
@app.route('/folder/<name>', name='route_dynamic')
async def handler(request, name):
results.append(name)
return text('OK')
assert app.router.routes_all['/folder/<name>'].name == 'route_dynamic'
assert app.url_for('route_dynamic', name='test') == '/folder/test'
with pytest.raises(URLBuildError):
app.url_for('handler')
def test_dynamic_named_route_regex():
app = Sanic('test_dynamic_route_regex')
@app.route('/folder/<folder_id:[A-Za-z0-9]{0,4}>', name='route_re')
async def handler(request, folder_id):
return text('OK')
route = app.router.routes_all['/folder/<folder_id:[A-Za-z0-9]{0,4}>']
assert route.name == 'route_re'
assert app.url_for('route_re', folder_id='test') == '/folder/test'
with pytest.raises(URLBuildError):
app.url_for('handler')
def test_dynamic_named_route_path():
app = Sanic('test_dynamic_route_path')
@app.route('/<path:path>/info', name='route_dynamic_path')
async def handler(request, path):
return text('OK')
route = app.router.routes_all['/<path:path>/info']
assert route.name == 'route_dynamic_path'
assert app.url_for('route_dynamic_path', path='path/1') == '/path/1/info'
with pytest.raises(URLBuildError):
app.url_for('handler')
def test_dynamic_named_route_unhashable():
app = Sanic('test_dynamic_route_unhashable')
@app.route('/folder/<unhashable:[A-Za-z0-9/]+>/end/',
name='route_unhashable')
async def handler(request, unhashable):
return text('OK')
route = app.router.routes_all['/folder/<unhashable:[A-Za-z0-9/]+>/end/']
assert route.name == 'route_unhashable'
url = app.url_for('route_unhashable', unhashable='test/asdf')
assert url == '/folder/test/asdf/end'
with pytest.raises(URLBuildError):
app.url_for('handler')
def test_websocket_named_route():
app = Sanic('test_websocket_route')
ev = asyncio.Event()
@app.websocket('/ws', name='route_ws')
async def handler(request, ws):
assert ws.subprotocol is None
ev.set()
assert app.router.routes_all['/ws'].name == 'route_ws'
assert app.url_for('route_ws') == '/ws'
with pytest.raises(URLBuildError):
app.url_for('handler')
def test_websocket_named_route_with_subprotocols():
app = Sanic('test_websocket_route')
results = []
@app.websocket('/ws', subprotocols=['foo', 'bar'], name='route_ws')
async def handler(request, ws):
results.append(ws.subprotocol)
assert app.router.routes_all['/ws'].name == 'route_ws'
assert app.url_for('route_ws') == '/ws'
with pytest.raises(URLBuildError):
app.url_for('handler')
def test_static_add_named_route():
app = Sanic('test_static_add_route')
async def handler1(request):
return text('OK1')
async def handler2(request):
return text('OK2')
app.add_route(handler1, '/test', name='route_test')
app.add_route(handler2, '/test2', name='route_test2')
assert app.router.routes_all['/test'].name == 'route_test'
assert app.router.routes_static['/test'].name == 'route_test'
assert app.url_for('route_test') == '/test'
with pytest.raises(URLBuildError):
app.url_for('handler1')
assert app.router.routes_all['/test2'].name == 'route_test2'
assert app.router.routes_static['/test2'].name == 'route_test2'
assert app.url_for('route_test2') == '/test2'
with pytest.raises(URLBuildError):
app.url_for('handler2')
def test_dynamic_add_named_route():
app = Sanic('test_dynamic_add_route')
results = []
async def handler(request, name):
results.append(name)
return text('OK')
app.add_route(handler, '/folder/<name>', name='route_dynamic')
assert app.router.routes_all['/folder/<name>'].name == 'route_dynamic'
assert app.url_for('route_dynamic', name='test') == '/folder/test'
with pytest.raises(URLBuildError):
app.url_for('handler')
def test_dynamic_add_named_route_unhashable():
app = Sanic('test_dynamic_add_route_unhashable')
async def handler(request, unhashable):
return text('OK')
app.add_route(handler, '/folder/<unhashable:[A-Za-z0-9/]+>/end/',
name='route_unhashable')
route = app.router.routes_all['/folder/<unhashable:[A-Za-z0-9/]+>/end/']
assert route.name == 'route_unhashable'
url = app.url_for('route_unhashable', unhashable='folder1')
assert url == '/folder/folder1/end'
with pytest.raises(URLBuildError):
app.url_for('handler')
def test_overload_routes():
app = Sanic('test_dynamic_route')
@app.route('/overload', methods=['GET'], name='route_first')
async def handler1(request):
return text('OK1')
@app.route('/overload', methods=['POST', 'PUT'], name='route_second')
async def handler2(request):
return text('OK2')
@app.route('/overload2', methods=['POST', 'PUT'], name='route_third')
async def handler3(request):
return text('OK2')
request, response = app.test_client.get(app.url_for('route_first'))
assert response.text == 'OK1'
request, response = app.test_client.post(app.url_for('route_first'))
assert response.text == 'OK2'
request, response = app.test_client.put(app.url_for('route_first'))
assert response.text == 'OK2'
assert app.router.routes_all['/overload'].name == 'route_first'
with pytest.raises(URLBuildError):
app.url_for('handler1')
with pytest.raises(URLBuildError):
app.url_for('handler2')
with pytest.raises(URLBuildError):
app.url_for('route_second')
assert app.url_for('route_third') == '/overload2'
with pytest.raises(URLBuildError):
app.url_for('handler3')