sanic/tests/test_views.py
2018-08-26 16:43:14 +02:00

254 lines
6.8 KiB
Python

import pytest as pytest
from sanic.exceptions import InvalidUsage
from sanic.response import text, HTTPResponse
from sanic.views import HTTPMethodView, CompositionView
from sanic.blueprints import Blueprint
from sanic.request import Request
from sanic.constants import HTTP_METHODS
@pytest.mark.parametrize('method', HTTP_METHODS)
def test_methods(app, method):
class DummyView(HTTPMethodView):
async def get(self, request):
assert request.stream is None
return text('', headers={'method': 'GET'})
def post(self, request):
return text('', headers={'method': 'POST'})
async def put(self, request):
return text('', headers={'method': 'PUT'})
def head(self, request):
return text('', headers={'method': 'HEAD'})
def options(self, request):
return text('', headers={'method': 'OPTIONS'})
async def patch(self, request):
return text('', headers={'method': 'PATCH'})
def delete(self, request):
return text('', headers={'method': 'DELETE'})
app.add_route(DummyView.as_view(), '/')
assert app.is_request_stream is False
request, response = getattr(app.test_client, method.lower())('/')
assert response.headers['method'] == method
def test_unexisting_methods(app):
class DummyView(HTTPMethodView):
def get(self, request):
return text('I am get method')
app.add_route(DummyView.as_view(), '/')
request, response = app.test_client.get('/')
assert response.text == 'I am get method'
request, response = app.test_client.post('/')
assert response.text == 'Error: Method POST not allowed for URL /'
def test_argument_methods(app):
class DummyView(HTTPMethodView):
def get(self, request, my_param_here):
return text('I am get method with %s' % my_param_here)
app.add_route(DummyView.as_view(), '/<my_param_here>')
request, response = app.test_client.get('/test123')
assert response.text == 'I am get method with test123'
def test_with_bp(app):
bp = Blueprint('test_text')
class DummyView(HTTPMethodView):
def get(self, request):
assert request.stream is None
return text('I am get method')
bp.add_route(DummyView.as_view(), '/')
app.blueprint(bp)
request, response = app.test_client.get('/')
assert app.is_request_stream is False
assert response.text == 'I am get method'
def test_with_bp_with_url_prefix(app):
bp = Blueprint('test_text', url_prefix='/test1')
class DummyView(HTTPMethodView):
def get(self, request):
return text('I am get method')
bp.add_route(DummyView.as_view(), '/')
app.blueprint(bp)
request, response = app.test_client.get('/test1/')
assert response.text == 'I am get method'
def test_with_middleware(app):
class DummyView(HTTPMethodView):
def get(self, request):
return text('I am get method')
app.add_route(DummyView.as_view(), '/')
results = []
@app.middleware
async def handler(request):
results.append(request)
request, response = app.test_client.get('/')
assert response.text == 'I am get method'
assert type(results[0]) is Request
def test_with_middleware_response(app):
results = []
@app.middleware('request')
async def process_response(request):
results.append(request)
@app.middleware('response')
async def process_response(request, response):
results.append(request)
results.append(response)
class DummyView(HTTPMethodView):
def get(self, request):
return text('I am get method')
app.add_route(DummyView.as_view(), '/')
request, response = app.test_client.get('/')
assert response.text == 'I am get method'
assert type(results[0]) is Request
assert type(results[1]) is Request
assert isinstance(results[2], HTTPResponse)
def test_with_custom_class_methods(app):
class DummyView(HTTPMethodView):
global_var = 0
def _iternal_method(self):
self.global_var += 10
def get(self, request):
self._iternal_method()
return text('I am get method and global var is {}'.format(self.global_var))
app.add_route(DummyView.as_view(), '/')
request, response = app.test_client.get('/')
assert response.text == 'I am get method and global var is 10'
def test_with_decorator(app):
results = []
def stupid_decorator(view):
def decorator(*args, **kwargs):
results.append(1)
return view(*args, **kwargs)
return decorator
class DummyView(HTTPMethodView):
decorators = [stupid_decorator]
def get(self, request):
return text('I am get method')
app.add_route(DummyView.as_view(), '/')
request, response = app.test_client.get('/')
assert response.text == 'I am get method'
assert results[0] == 1
def test_composition_view_rejects_incorrect_methods():
def foo(request):
return text('Foo')
view = CompositionView()
with pytest.raises(InvalidUsage) as e:
view.add(['GET', 'FOO'], foo)
assert str(e.value) == 'FOO is not a valid HTTP method.'
def test_composition_view_rejects_duplicate_methods():
def foo(request):
return text('Foo')
view = CompositionView()
with pytest.raises(InvalidUsage) as e:
view.add(['GET', 'POST', 'GET'], foo)
assert str(e.value) == 'Method GET is already registered.'
@pytest.mark.parametrize('method', HTTP_METHODS)
def test_composition_view_runs_methods_as_expected(app, method):
view = CompositionView()
def first(request):
assert request.stream is None
return text('first method')
view.add(['GET', 'POST', 'PUT'], first)
view.add(['DELETE', 'PATCH'], lambda x: text('second method'))
app.add_route(view, '/')
assert app.is_request_stream is False
if method in ['GET', 'POST', 'PUT']:
request, response = getattr(app.test_client, method.lower())('/')
assert response.text == 'first method'
if method in ['DELETE', 'PATCH']:
request, response = getattr(app.test_client, method.lower())('/')
assert response.text == 'second method'
@pytest.mark.parametrize('method', HTTP_METHODS)
def test_composition_view_rejects_invalid_methods(app, method):
view = CompositionView()
view.add(['GET', 'POST', 'PUT'], lambda x: text('first method'))
app.add_route(view, '/')
if method in ['GET', 'POST', 'PUT']:
request, response = getattr(app.test_client, method.lower())('/')
assert response.status == 200
assert response.text == 'first method'
if method in ['DELETE', 'PATCH']:
request, response = getattr(app.test_client, method.lower())('/')
assert response.status == 405