diff --git a/flask/testing.py b/flask/testing.py index 54ce20efb3..650b196dba 100644 --- a/flask/testing.py +++ b/flask/testing.py @@ -13,6 +13,7 @@ from contextlib import contextmanager from werkzeug.test import Client, EnvironBuilder from flask import _request_ctx_stack +from flask.json import dumps as json_dumps try: from werkzeug.urls import url_parse @@ -20,7 +21,7 @@ from urlparse import urlsplit as url_parse -def make_test_environ_builder(app, path='/', base_url=None, *args, **kwargs): +def make_test_environ_builder(app, path='/', base_url=None, json=None, *args, **kwargs): """Creates a new test builder with some application defaults thrown in.""" http_host = app.config.get('SERVER_NAME') app_root = app.config.get('APPLICATION_ROOT') @@ -33,6 +34,18 @@ def make_test_environ_builder(app, path='/', base_url=None, *args, **kwargs): path = url.path if url.query: path += '?' + url.query + + if json: + if 'data' in kwargs: + raise RuntimeError('Client cannot provide both `json` and `data`') + kwargs['data'] = json_dumps(json) + + # Only set Content-Type when not explicitly provided + if 'Content-Type' not in kwargs.get('headers', {}): + new_headers = kwargs.get('headers', {}).copy() + new_headers['Content-Type'] = 'application/json' + kwargs['headers'] = new_headers + return EnvironBuilder(path, base_url, *args, **kwargs) diff --git a/tests/test_testing.py b/tests/test_testing.py index a9e06fab27..72e5e5ef80 100644 --- a/tests/test_testing.py +++ b/tests/test_testing.py @@ -209,6 +209,20 @@ def action(): assert 'gin' in flask.request.form assert 'vodka' in flask.request.args +def test_json_request(): + app = flask.Flask(__name__) + app.testing = True + + @app.route('/api', methods=['POST']) + def api(): + return '' + + with app.test_client() as c: + json_data = {'drink': {'gin': 1, 'tonic': True}, 'price': 10} + rv = c.post('/api', json=json_data) + assert rv.status_code == 200 + assert flask.request.json == json_data + def test_subdomain(): app = flask.Flask(__name__) app.config['SERVER_NAME'] = 'example.com'