Skip to content

Commit

Permalink
add json argument for test client
Browse files Browse the repository at this point in the history
  • Loading branch information
davidism committed Nov 25, 2018
1 parent d402d77 commit f6ce5a4
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 10 deletions.
11 changes: 7 additions & 4 deletions CHANGES.rst
Expand Up @@ -116,8 +116,7 @@ Unreleased
versions of Lighttpd. ``LighttpdCGIRootFix`` was renamed to
``CGIRootFix`` in 0.9. The old name emits a deprecation warning and
will be removed in the next version. (`#1141`_)
- The test :class:`~test.Client` redirect handling is rewritten.
(`#1402`_)
- :class:`test.Client` redirect handling is rewritten. (`#1402`_)

- The redirect environ is copied from the initial request environ.
- Script root and path are correctly distinguished when
Expand All @@ -127,13 +126,16 @@ Unreleased
ignore the body and related headers.
- Headers are passed to the new request for all codes, following
what browsers do.
- :class:`~test.EnvironBuilder` sets the content type and length
- :class:`test.EnvironBuilder` sets the content type and length
headers in addition to the WSGI keys when detecting them from
the data.
- Intermediate response bodies are iterated over even when
``buffered=False`` to ensure iterator middleware can run cleanup
code safely. Only the last response is not buffered. (`#988`_)

- :class:`test.EnvironBuilder` and :class:`test.Client` take a
``json`` argument instead of manually passing ``data`` and
``content_type``. This is serialized using the
:func:`test.EnvironBuilder.json_dumps` function. (`#1404`_)

.. _`#209`: https://github.com/pallets/werkzeug/pull/209
.. _`#609`: https://github.com/pallets/werkzeug/pull/609
Expand Down Expand Up @@ -184,6 +186,7 @@ Unreleased
.. _`#1395`: https://github.com/pallets/werkzeug/pull/1395
.. _`#1401`: https://github.com/pallets/werkzeug/pull/1401
.. _`#1402`: https://github.com/pallets/werkzeug/pull/1402
.. _#1404: https://github.com/pallets/werkzeug/pull/1404


Version 0.14.1
Expand Down
15 changes: 15 additions & 0 deletions tests/test_test.py
Expand Up @@ -11,6 +11,7 @@

from __future__ import with_statement

import json
import pytest

import sys
Expand Down Expand Up @@ -174,6 +175,20 @@ def check_list_content(b, length):
check_list_content(b, 2)


def test_environ_builder_json():
@Request.application
def app(request):
assert request.content_type == "application/json"
return Response(json.loads(request.get_data(as_text=True))["foo"])

c = Client(app, Response)
response = c.post("/", json={"foo": "bar"})
assert response.data == b"bar"

with pytest.raises(TypeError):
c.post("/", json={"foo": "bar"}, data={"baz": "qux"})


def test_environ_builder_headers():
b = EnvironBuilder(environ_base={'HTTP_USER_AGENT': 'Foo/0.1'},
environ_overrides={'wsgi.version': (1, 1)})
Expand Down
34 changes: 28 additions & 6 deletions werkzeug/test.py
Expand Up @@ -219,7 +219,6 @@ def _iter_data(data):


class EnvironBuilder(object):

"""This class can be used to conveniently create a WSGI environment
for testing purposes. It can be used to quickly create WSGI environments
or request objects from arbitrary data.
Expand Down Expand Up @@ -251,10 +250,6 @@ class EnvironBuilder(object):
- a file-like object: The object content is loaded in memory and then
handled like a regular `str` or a `bytes`.
.. versionadded:: 0.6
`path` and `base_url` can now be unicode strings that are encoded using
the :func:`iri_to_uri` function.
:param path: the path of the request. In the WSGI environment this will
end up as `PATH_INFO`. If the `query_string` is not defined
and there is a question mark in the `path` everything after
Expand Down Expand Up @@ -282,9 +277,19 @@ class EnvironBuilder(object):
:param headers: an optional list or :class:`Headers` object of headers.
:param data: a string or dict of form data or a file-object.
See explanation above.
:param json: An object to be serialized and assigned to ``data``.
Defaults the content type to ``"application/json"``.
Serialized with the function assigned to :attr:`json_dumps`.
:param environ_base: an optional dict of environment defaults.
:param environ_overrides: an optional dict of environment overrides.
:param charset: the charset used to encode unicode data.
.. versionadded:: 0.15
The ``json`` param and :attr:`json_dumps` attr.
.. versionchanged:: 0.6
``path`` and ``base_url`` can now be unicode strings that are
encoded with :func:`iri_to_uri`.
"""

#: the server protocol to use. defaults to HTTP/1.1
Expand All @@ -296,12 +301,17 @@ class EnvironBuilder(object):
#: the default request class for :meth:`get_request`
request_class = BaseRequest

import json
#: The serialization function used when ``json`` is passed.
json_dumps = staticmethod(json.dumps)
del json

def __init__(self, path='/', base_url=None, query_string=None,
method='GET', input_stream=None, content_type=None,
content_length=None, errors_stream=None, multithread=False,
multiprocess=False, run_once=False, headers=None, data=None,
environ_base=None, environ_overrides=None, charset='utf-8',
mimetype=None):
mimetype=None, json=None):
path_s = make_literal_wrapper(path)
if query_string is not None and path_s('?') in path:
raise ValueError('Query string is defined in the path and as an argument')
Expand Down Expand Up @@ -340,6 +350,15 @@ def __init__(self, path='/', base_url=None, query_string=None,
self.content_length = content_length
self.closed = False

if json is not None:
if data is not None:
raise TypeError("can't provide both json and data")

data = self.json_dumps(json)

if content_type is None:
self.content_type = "application/json"

if data:
if input_stream is not None:
raise TypeError('can\'t provide input stream and data')
Expand Down Expand Up @@ -735,6 +754,9 @@ class ClientResponse(BaseResponse):
.. versionadded:: 0.14
The `mimetype` parameter was added.
.. versionadded:: 0.15
The ``json`` parameter.
"""

def __init__(self, application, response_wrapper=None, use_cookies=True,
Expand Down

0 comments on commit f6ce5a4

Please sign in to comment.