forked from marshmallow-code/webargs
/
testing.py
232 lines (186 loc) · 8.52 KB
/
testing.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
# -*- coding: utf-8 -*-
"""Utilities for testing. Includes a base test class
for testing parsers.
.. warning::
Methods and functions in this module may change without
warning and without a major version change.
"""
import pytest
import webtest
from webargs.core import json
class CommonTestCase(object):
"""Base test class that defines test methods for common functionality across all
parsers. Subclasses must define `create_app`, which returns a WSGI-like app.
"""
def create_app(self):
"""Return a WSGI app"""
raise NotImplementedError("Must define create_app()")
def create_testapp(self, app):
return webtest.TestApp(app)
def before_create_app(self):
pass
def after_create_app(self):
pass
@pytest.fixture(scope="class")
def testapp(self):
self.before_create_app()
yield self.create_testapp(self.create_app())
self.after_create_app()
def test_parse_querystring_args(self, testapp):
assert testapp.get("/echo?name=Fred").json == {"name": "Fred"}
def test_parse_form(self, testapp):
assert testapp.post("/echo_form", {"name": "Joe"}).json == {"name": "Joe"}
def test_parse_json(self, testapp):
assert testapp.post_json("/echo_json", {"name": "Fred"}).json == {
"name": "Fred"
}
def test_parse_querystring_default(self, testapp):
assert testapp.get("/echo").json == {"name": "World"}
def test_parse_json_default(self, testapp):
assert testapp.post_json("/echo_json", {}).json == {"name": "World"}
def test_parse_json_with_charset(self, testapp):
res = testapp.post(
"/echo_json",
json.dumps({"name": "Steve"}),
content_type="application/json;charset=UTF-8",
)
assert res.json == {"name": "Steve"}
def test_parse_json_with_vendor_media_type(self, testapp):
res = testapp.post(
"/echo_json",
json.dumps({"name": "Steve"}),
content_type="application/vnd.api+json;charset=UTF-8",
)
assert res.json == {"name": "Steve"}
def test_parse_json_ignores_extra_data(self, testapp):
assert testapp.post_json("/echo_json", {"extra": "data"}).json == {
"name": "World"
}
def test_parse_json_empty(self, testapp):
assert testapp.post_json("/echo_json", {}).json == {"name": "World"}
def test_parse_json_error_unexpected_int(self, testapp):
res = testapp.post_json("/echo_json", 1, expect_errors=True)
assert res.status_code == 422
def test_parse_json_error_unexpected_list(self, testapp):
res = testapp.post_json("/echo_json", [{"extra": "data"}], expect_errors=True)
assert res.status_code == 422
def test_parse_json_many_schema_invalid_input(self, testapp):
res = testapp.post_json(
"/echo_many_schema", [{"name": "a"}], expect_errors=True
)
assert res.status_code == 422
def test_parse_json_many_schema(self, testapp):
res = testapp.post_json("/echo_many_schema", [{"name": "Steve"}]).json
assert res == [{"name": "Steve"}]
def test_parse_json_many_schema_error_malformed_data(self, testapp):
res = testapp.post_json(
"/echo_many_schema", {"extra": "data"}, expect_errors=True
)
assert res.status_code == 422
def test_parsing_form_default(self, testapp):
assert testapp.post("/echo_form", {}).json == {"name": "World"}
def test_parse_querystring_multiple(self, testapp):
expected = {"name": ["steve", "Loria"]}
assert testapp.get("/echo_multi?name=steve&name=Loria").json == expected
def test_parse_form_multiple(self, testapp):
expected = {"name": ["steve", "Loria"]}
assert (
testapp.post("/echo_multi_form", {"name": ["steve", "Loria"]}).json
== expected
)
def test_parse_json_list(self, testapp):
expected = {"name": ["Steve"]}
assert (
testapp.post_json("/echo_multi_json", {"name": ["Steve"]}).json == expected
)
def test_parse_json_list_error_malformed_data(self, testapp):
res = testapp.post_json(
"/echo_multi_json", {"name": "Steve"}, expect_errors=True
)
assert res.status_code == 422
def test_parse_json_with_nonascii_chars(self, testapp):
text = u"øˆƒ£ºº∆ƒˆ∆"
assert testapp.post_json("/echo_json", {"name": text}).json == {"name": text}
def test_validation_error_returns_422_response(self, testapp):
res = testapp.post("/echo_json", {"name": "b"}, expect_errors=True)
assert res.status_code == 422
def test_user_validation_error_returns_422_response_by_default(self, testapp):
res = testapp.post_json("/error", {"text": "foo"}, expect_errors=True)
assert res.status_code == 422
def test_use_args_decorator(self, testapp):
assert testapp.get("/echo_use_args?name=Fred").json == {"name": "Fred"}
def test_use_args_with_path_param(self, testapp):
url = "/echo_use_args_with_path_param/foo"
res = testapp.get(url + "?value=42")
assert res.json == {"value": 42}
def test_use_args_with_validation(self, testapp):
result = testapp.post("/echo_use_args_validated", {"value": 43})
assert result.status_code == 200
result = testapp.post(
"/echo_use_args_validated", {"value": 41}, expect_errors=True
)
assert result.status_code == 422
def test_use_kwargs_decorator(self, testapp):
assert testapp.get("/echo_use_kwargs?name=Fred").json == {"name": "Fred"}
def test_use_kwargs_with_path_param(self, testapp):
url = "/echo_use_kwargs_with_path_param/foo"
res = testapp.get(url + "?value=42")
assert res.json == {"value": 42}
def test_parsing_headers(self, testapp):
res = testapp.get("/echo_headers", headers={"name": "Fred"})
assert res.json == {"name": "Fred"}
def test_parsing_cookies(self, testapp):
testapp.set_cookie("name", "Steve")
res = testapp.get("/echo_cookie")
assert res.json == {"name": "Steve"}
def test_parse_nested_json(self, testapp):
res = testapp.post_json(
"/echo_nested", {"name": {"first": "Steve", "last": "Loria"}}
)
assert res.json == {"name": {"first": "Steve", "last": "Loria"}}
def test_parse_nested_many_json(self, testapp):
in_data = {"users": [{"id": 1, "name": "foo"}, {"id": 2, "name": "bar"}]}
res = testapp.post_json("/echo_nested_many", in_data)
assert res.json == in_data
# Regression test for https://github.com/marshmallow-code/webargs/issues/120
def test_parse_nested_many_missing(self, testapp):
in_data = {}
res = testapp.post_json("/echo_nested_many", in_data)
assert res.json == {}
def test_parse_json_if_no_json(self, testapp):
res = testapp.post("/echo_json", expect_errors=True)
assert res.status_code == 422
def test_parse_files(self, testapp):
res = testapp.post(
"/echo_file", {"myfile": webtest.Upload("README.rst", b"data")}
)
assert res.json == {"myfile": "data"}
# https://github.com/sloria/webargs/pull/297
#
# NOTE: although this was originally considered correct behavior for
# webargs under #297 , under the refactor for #419 it is being reconsidered
# as *incorrect*
# the reason is that it makes it impossible to disambiguate "" (not valid
# JSON) from "{}" (valid, empty JSON). This in turn has downstream negative
# impact when you try to build sophisticated nested loaders which traverse
# the various location_load_{locname} methods because you can't tell if the
# user submitted empty data or no data in a location. In particular, this
# would pose serious problems for implementing the "json_or_form" location
def test_empty_json(self, testapp):
res = testapp.post(
"/echo_json",
"",
headers={"Accept": "application/json", "Content-Type": "application/json"},
expect_errors=True,
)
assert res.status_code == 422
# https://github.com/sloria/webargs/issues/329
def test_invalid_json(self, testapp):
res = testapp.post(
"/echo_json",
'{"foo": "bar", }',
headers={"Accept": "application/json", "Content-Type": "application/json"},
expect_errors=True,
)
assert res.status_code == 400
assert res.json == {"json": ["Invalid JSON body."]}