Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(testing): add msgpack support #2394

Open
wants to merge 18 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion docs/changes/4.1.0.rst
arthurprioli marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,21 @@ on GitHub.

.. NOTE(vytas): No changes to the supported platforms (yet).


arthurprioli marked this conversation as resolved.
Show resolved Hide resolved
.. towncrier release notes start


Misc
arthurprioli marked this conversation as resolved.
Show resolved Hide resolved
----

- Running mypy on code that uses parts of ``falcon.testing`` naively
would lead to errors like::

Name "falcon.testing.TestClient" is not defined

This has been fixed by explicitly exporting the names that are
imported in the ``falcon.testing`` namespace. (`#2387 <https://github.com/falconry/falcon/issues/2387>`__)


Contributors to this Release
----------------------------

Expand Down
40 changes: 40 additions & 0 deletions falcon/testing/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,9 @@
from falcon.asgi_spec import ScopeType
from falcon.constants import COMBINED_METHODS
from falcon.constants import MEDIA_JSON
from falcon.constants import MEDIA_MSGPACK
from falcon.errors import CompatibilityError
from falcon.media import MessagePackHandler
from falcon.testing import helpers
from falcon.testing.srmock import StartResponseMock
from falcon.typing import Headers
Expand Down Expand Up @@ -455,6 +457,7 @@ def simulate_request(
content_type: Optional[str] = None,
body: Optional[Union[str, bytes]] = None,
json: Optional[Any] = None,
msgpack: Optional[Any] = None,
file_wrapper: Optional[Callable[..., Any]] = None,
wsgierrors: Optional[TextIO] = None,
params: Optional[Mapping[str, Any]] = None,
Expand Down Expand Up @@ -592,6 +595,7 @@ def simulate_request(
content_type=content_type,
body=body,
json=json,
msgpack=msgpack,
params=params,
params_csv=params_csv,
protocol=protocol,
Expand All @@ -615,6 +619,7 @@ def simulate_request(
headers,
body,
json,
msgpack,
extras,
)

Expand Down Expand Up @@ -724,6 +729,7 @@ async def _simulate_request_asgi(
content_type: Optional[str] = None,
body: Optional[Union[str, bytes]] = None,
json: Optional[Any] = None,
msgpack: Optional[Any] = None,
params: Optional[Mapping[str, Any]] = None,
params_csv: bool = False,
protocol: str = 'http',
Expand Down Expand Up @@ -808,6 +814,11 @@ async def _simulate_request_asgi(
overrides `body` and sets the Content-Type header to
``'application/json'``, overriding any value specified by either
the `content_type` or `headers` arguments.
msgpack(Msgpack serializable): A Msgpack document to serialize as the
vytas7 marked this conversation as resolved.
Show resolved Hide resolved
body of the request (default: ``None``). If specified,
overrides `body` and sets the Content-Type header to
``'application/msgpack'``, overriding any value specified by
either the `content_type` or `headers` arguments.
host(str): A string to use for the hostname part of the fully
qualified request URL (default: 'falconframework.org')
remote_addr (str): A string to use as the remote IP address for the
Expand Down Expand Up @@ -846,6 +857,7 @@ async def _simulate_request_asgi(
headers,
body,
json,
msgpack,
extras,
)

Expand Down Expand Up @@ -1551,6 +1563,11 @@ def simulate_post(app: Callable[..., Any], path: str, **kwargs: Any) -> Result:
overrides `body` and sets the Content-Type header to
``'application/json'``, overriding any value specified by either
the `content_type` or `headers` arguments.
msgpack(Msgpack serializable): A Msgpack document to serialize as the
body of the request (default: ``None``). If specified,
overrides `body` and sets the Content-Type header to
``'application/msgpack'``, overriding any value specified by
either the `content_type` or `headers` arguments.
file_wrapper (callable): Callable that returns an iterable,
to be used as the value for *wsgi.file_wrapper* in the
WSGI environ (default: ``None``). This can be used to test
Expand Down Expand Up @@ -1662,6 +1679,11 @@ def simulate_put(app: Callable[..., Any], path: str, **kwargs: Any) -> Result:
overrides `body` and sets the Content-Type header to
``'application/json'``, overriding any value specified by either
the `content_type` or `headers` arguments.
msgpack(Msgpack serializable): A Msgpack document to serialize as the
body of the request (default: ``None``). If specified,
overrides `body` and sets the Content-Type header to
``'application/msgpack'``, overriding any value specified by
either the `content_type` or `headers` arguments.
file_wrapper (callable): Callable that returns an iterable,
to be used as the value for *wsgi.file_wrapper* in the
WSGI environ (default: ``None``). This can be used to test
Expand Down Expand Up @@ -1862,6 +1884,11 @@ def simulate_patch(app: Callable[..., Any], path: str, **kwargs: Any) -> Result:
overrides `body` and sets the Content-Type header to
``'application/json'``, overriding any value specified by either
the `content_type` or `headers` arguments.
msgpack(Msgpack serializable): A Msgpack document to serialize as the
body of the request (default: ``None``). If specified,
overrides `body` and sets the Content-Type header to
`'application/msgpack'``, overriding any value specified by
either the `content_type` or `headers` arguments.
host(str): A string to use for the hostname part of the fully
qualified request URL (default: 'falconframework.org')
remote_addr (str): A string to use as the remote IP address for the
Expand Down Expand Up @@ -1968,6 +1995,11 @@ def simulate_delete(app: Callable[..., Any], path: str, **kwargs: Any) -> Result
overrides `body` and sets the Content-Type header to
``'application/json'``, overriding any value specified by either
the `content_type` or `headers` arguments.
msgpack(Msgpack serializable): A Msgpack document to serialize as the
body of the request (default: ``None``). If specified,
overrides `body` and sets the Content-Type header to
``'application/msgpack'``, overriding any value specified by
either the `content_type` or `headers` arguments.
host(str): A string to use for the hostname part of the fully
qualified request URL (default: 'falconframework.org')
remote_addr (str): A string to use as the remote IP address for the
Expand Down Expand Up @@ -2248,6 +2280,7 @@ def _prepare_sim_args(
headers: Optional[HeaderArg],
body: Optional[Union[str, bytes]],
json: Optional[Any],
msgpack: Optional[Any],
extras: Optional[Mapping[str, Any]],
) -> Tuple[
str, str, Optional[HeaderArg], Optional[Union[str, bytes]], Mapping[str, Any]
Expand Down Expand Up @@ -2284,6 +2317,13 @@ def _prepare_sim_args(
headers = dict(headers or {})
headers['Content-Type'] = MEDIA_JSON

if msgpack is not None:
body = MessagePackHandler.serialize(
MessagePackHandler(), content_type=None, media=msgpack
arthurprioli marked this conversation as resolved.
Show resolved Hide resolved
)
headers = headers or {}
headers['Content-Type'] = MEDIA_MSGPACK

return path, query_string, headers, body, extras


Expand Down
14 changes: 14 additions & 0 deletions tests/test_testing.py
arthurprioli marked this conversation as resolved.
Show resolved Hide resolved
arthurprioli marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,20 @@ def on_post(self, req, resp):
)
assert result.text == falcon.MEDIA_JSON

result = testing.simulate_post(app, '/', msgpack={})
assert result.text == falcon.MEDIA_MSGPACK

result = testing.simulate_post(app, '/', msgpack={}, content_type=falcon.MEDIA_HTML)
assert result.text == falcon.MEDIA_MSGPACK

result = testing.simulate_post(app, '/', msgpack={}, headers=headers)
assert result.text == falcon.MEDIA_MSGPACK

result = testing.simulate_post(
app, '/', msgpack={}, headers=headers, content_type=falcon.MEDIA_HTML
)
assert result.text == falcon.MEDIA_MSGPACK
arthurprioli marked this conversation as resolved.
Show resolved Hide resolved


@pytest.mark.parametrize('mode', ['wsgi', 'asgi', 'asgi-stream'])
def test_content_type(util, mode):
Expand Down
Loading