flask/tests/test_views.py

240 lines
5.8 KiB
Python
Raw Normal View History

# -*- coding: utf-8 -*-
"""
2014-09-01 03:54:45 +08:00
tests.views
2014-09-21 22:47:38 +08:00
~~~~~~~~~~~
Pluggable views.
2019-06-23 04:09:09 +08:00
:copyright: 2010 Pallets
:license: BSD-3-Clause
"""
2014-09-02 11:26:52 +08:00
import pytest
import flask
import flask.views
2014-09-04 03:02:03 +08:00
from werkzeug.http import parse_set_header
2014-09-04 02:41:51 +08:00
def common_test(app):
c = app.test_client()
assert c.get('/').data == b'GET'
assert c.post('/').data == b'POST'
assert c.put('/').status_code == 405
meths = parse_set_header(c.open('/', method='OPTIONS').headers['Allow'])
assert sorted(meths) == ['GET', 'HEAD', 'OPTIONS', 'POST']
def test_basic_view(app):
2014-09-04 02:41:51 +08:00
class Index(flask.views.View):
methods = ['GET', 'POST']
2014-09-04 02:41:51 +08:00
def dispatch_request(self):
return flask.request.method
app.add_url_rule('/', view_func=Index.as_view('index'))
common_test(app)
def test_method_based_view(app):
2014-09-04 02:41:51 +08:00
class Index(flask.views.MethodView):
def get(self):
return 'GET'
2014-09-04 02:41:51 +08:00
def post(self):
return 'POST'
app.add_url_rule('/', view_func=Index.as_view('index'))
common_test(app)
def test_view_patching(app):
2014-09-04 02:41:51 +08:00
class Index(flask.views.MethodView):
def get(self):
1 // 0
2014-09-04 02:41:51 +08:00
def post(self):
1 // 0
class Other(Index):
def get(self):
return 'GET'
2014-09-04 02:41:51 +08:00
def post(self):
return 'POST'
view = Index.as_view('index')
view.view_class = Other
app.add_url_rule('/', view_func=view)
common_test(app)
2017-05-25 08:27:36 +08:00
def test_view_inheritance(app, client):
2014-09-04 02:41:51 +08:00
class Index(flask.views.MethodView):
def get(self):
return 'GET'
2014-09-04 02:41:51 +08:00
def post(self):
return 'POST'
class BetterIndex(Index):
def delete(self):
return 'DELETE'
app.add_url_rule('/', view_func=BetterIndex.as_view('index'))
2017-05-25 08:27:36 +08:00
meths = parse_set_header(client.open('/', method='OPTIONS').headers['Allow'])
2014-09-04 02:41:51 +08:00
assert sorted(meths) == ['DELETE', 'GET', 'HEAD', 'OPTIONS', 'POST']
2017-05-25 08:27:36 +08:00
def test_view_decorators(app, client):
2014-09-04 02:41:51 +08:00
def add_x_parachute(f):
def new_function(*args, **kwargs):
resp = flask.make_response(f(*args, **kwargs))
resp.headers['X-Parachute'] = 'awesome'
return resp
2014-09-04 02:41:51 +08:00
return new_function
class Index(flask.views.View):
decorators = [add_x_parachute]
2014-09-04 02:41:51 +08:00
def dispatch_request(self):
return 'Awesome'
app.add_url_rule('/', view_func=Index.as_view('index'))
2017-05-25 08:27:36 +08:00
rv = client.get('/')
2014-09-04 02:41:51 +08:00
assert rv.headers['X-Parachute'] == 'awesome'
assert rv.data == b'Awesome'
def test_view_provide_automatic_options_attr():
app = flask.Flask(__name__)
class Index1(flask.views.View):
provide_automatic_options = False
def dispatch_request(self):
return 'Hello World!'
app.add_url_rule('/', view_func=Index1.as_view('index'))
c = app.test_client()
rv = c.open('/', method='OPTIONS')
assert rv.status_code == 405
app = flask.Flask(__name__)
class Index2(flask.views.View):
methods = ['OPTIONS']
provide_automatic_options = True
def dispatch_request(self):
return 'Hello World!'
app.add_url_rule('/', view_func=Index2.as_view('index'))
c = app.test_client()
rv = c.open('/', method='OPTIONS')
assert sorted(rv.allow) == ['OPTIONS']
app = flask.Flask(__name__)
class Index3(flask.views.View):
def dispatch_request(self):
return 'Hello World!'
app.add_url_rule('/', view_func=Index3.as_view('index'))
c = app.test_client()
rv = c.open('/', method='OPTIONS')
assert 'OPTIONS' in rv.allow
2014-09-04 02:41:51 +08:00
2017-05-25 08:27:36 +08:00
def test_implicit_head(app, client):
2014-09-04 02:41:51 +08:00
class Index(flask.views.MethodView):
def get(self):
return flask.Response('Blub', headers={
'X-Method': flask.request.method
})
app.add_url_rule('/', view_func=Index.as_view('index'))
2017-05-25 08:27:36 +08:00
rv = client.get('/')
2014-09-04 02:41:51 +08:00
assert rv.data == b'Blub'
assert rv.headers['X-Method'] == 'GET'
2017-05-25 08:27:36 +08:00
rv = client.head('/')
2014-09-04 02:41:51 +08:00
assert rv.data == b''
assert rv.headers['X-Method'] == 'HEAD'
2017-05-25 08:27:36 +08:00
def test_explicit_head(app, client):
2014-09-04 02:41:51 +08:00
class Index(flask.views.MethodView):
def get(self):
return 'GET'
2014-09-04 02:41:51 +08:00
def head(self):
return flask.Response('', headers={'X-Method': 'HEAD'})
app.add_url_rule('/', view_func=Index.as_view('index'))
2017-05-25 08:27:36 +08:00
rv = client.get('/')
2014-09-04 02:41:51 +08:00
assert rv.data == b'GET'
2017-05-25 08:27:36 +08:00
rv = client.head('/')
2014-09-04 02:41:51 +08:00
assert rv.data == b''
assert rv.headers['X-Method'] == 'HEAD'
def test_endpoint_override(app):
2014-09-04 02:41:51 +08:00
app.debug = True
class Index(flask.views.View):
methods = ['GET', 'POST']
2014-09-04 02:41:51 +08:00
def dispatch_request(self):
return flask.request.method
app.add_url_rule('/', view_func=Index.as_view('index'))
with pytest.raises(AssertionError):
app.add_url_rule('/', view_func=Index.as_view('index'))
2014-09-04 02:41:51 +08:00
# But these tests should still pass. We just log a warning.
common_test(app)
2016-06-28 23:20:25 +08:00
2017-05-25 08:27:36 +08:00
def test_multiple_inheritance(app, client):
2016-06-28 23:20:25 +08:00
class GetView(flask.views.MethodView):
def get(self):
return 'GET'
class DeleteView(flask.views.MethodView):
def delete(self):
return 'DELETE'
class GetDeleteView(GetView, DeleteView):
pass
app.add_url_rule('/', view_func=GetDeleteView.as_view('index'))
2017-05-25 08:27:36 +08:00
assert client.get('/').data == b'GET'
assert client.delete('/').data == b'DELETE'
2016-06-28 23:20:25 +08:00
assert sorted(GetDeleteView.methods) == ['DELETE', 'GET']
2017-05-25 08:27:36 +08:00
def test_remove_method_from_parent(app, client):
2016-06-28 23:20:25 +08:00
class GetView(flask.views.MethodView):
def get(self):
return 'GET'
class OtherView(flask.views.MethodView):
def post(self):
return 'POST'
class View(GetView, OtherView):
methods = ['GET']
app.add_url_rule('/', view_func=View.as_view('index'))
2017-05-25 08:27:36 +08:00
assert client.get('/').data == b'GET'
assert client.post('/').status_code == 405
2016-06-28 23:20:25 +08:00
assert sorted(View.methods) == ['GET']