FlaskTester 5.0__tar.gz → 5.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,16 +1,15 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: FlaskTester
3
- Version: 5.0
3
+ Version: 5.1
4
4
  Summary: Pytest fixtures for Flask internal and external authenticated tests
5
5
  Author-email: Fabien Coelho <flask.tester@coelho.net>
6
- License: CC0
6
+ License-Expression: CC0-1.0
7
7
  Project-URL: repository, https://github.com/zx80/flask-tester
8
8
  Project-URL: documentation, https://zx80.github.io/flask-tester/
9
9
  Project-URL: issues, https://github.com/zx80/flask-tester/issues
10
10
  Project-URL: package, https://pypi.org/project/FlaskTester/
11
11
  Classifier: Development Status :: 5 - Production/Stable
12
12
  Classifier: Intended Audience :: Developers
13
- Classifier: License :: CC0 1.0 Universal (CC0 1.0) Public Domain Dedication
14
13
  Classifier: Programming Language :: Python
15
14
  Classifier: Environment :: Web Environment
16
15
  Classifier: Framework :: Flask
@@ -41,6 +40,7 @@ Provides-Extra: pub
41
40
  Requires-Dist: build; extra == "pub"
42
41
  Requires-Dist: twine; extra == "pub"
43
42
  Requires-Dist: wheel; extra == "pub"
43
+ Dynamic: license-file
44
44
 
45
45
  # FlaskTester - Pytest fixtures for Flask internal and external authenticated tests
46
46
 
@@ -7,6 +7,4 @@ FlaskTester.egg-info/PKG-INFO
7
7
  FlaskTester.egg-info/SOURCES.txt
8
8
  FlaskTester.egg-info/dependency_links.txt
9
9
  FlaskTester.egg-info/requires.txt
10
- FlaskTester.egg-info/top_level.txt
11
- tests/test_app.py
12
- tests/test_app2.py
10
+ FlaskTester.egg-info/top_level.txt
@@ -0,0 +1 @@
1
+ exclude docs/* tests/* */Makefile
@@ -1,16 +1,15 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: FlaskTester
3
- Version: 5.0
3
+ Version: 5.1
4
4
  Summary: Pytest fixtures for Flask internal and external authenticated tests
5
5
  Author-email: Fabien Coelho <flask.tester@coelho.net>
6
- License: CC0
6
+ License-Expression: CC0-1.0
7
7
  Project-URL: repository, https://github.com/zx80/flask-tester
8
8
  Project-URL: documentation, https://zx80.github.io/flask-tester/
9
9
  Project-URL: issues, https://github.com/zx80/flask-tester/issues
10
10
  Project-URL: package, https://pypi.org/project/FlaskTester/
11
11
  Classifier: Development Status :: 5 - Production/Stable
12
12
  Classifier: Intended Audience :: Developers
13
- Classifier: License :: CC0 1.0 Universal (CC0 1.0) Public Domain Dedication
14
13
  Classifier: Programming Language :: Python
15
14
  Classifier: Environment :: Web Environment
16
15
  Classifier: Framework :: Flask
@@ -41,6 +40,7 @@ Provides-Extra: pub
41
40
  Requires-Dist: build; extra == "pub"
42
41
  Requires-Dist: twine; extra == "pub"
43
42
  Requires-Dist: wheel; extra == "pub"
43
+ Dynamic: license-file
44
44
 
45
45
  # FlaskTester - Pytest fixtures for Flask internal and external authenticated tests
46
46
 
@@ -4,11 +4,11 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "FlaskTester"
7
- version = "5.0"
7
+ version = "5.1"
8
8
  authors = [ { name = "Fabien Coelho", email = "flask.tester@coelho.net" } ]
9
9
  description = "Pytest fixtures for Flask internal and external authenticated tests"
10
10
  readme = "README.md"
11
- license = { text = "CC0" }
11
+ license = "CC0-1.0"
12
12
  requires-python = ">=3.10"
13
13
  dependencies = [
14
14
  "requests",
@@ -17,7 +17,6 @@ dependencies = [
17
17
  classifiers = [
18
18
  "Development Status :: 5 - Production/Stable",
19
19
  "Intended Audience :: Developers",
20
- "License :: CC0 1.0 Universal (CC0 1.0) Public Domain Dedication",
21
20
  "Programming Language :: Python",
22
21
  "Environment :: Web Environment",
23
22
  "Framework :: Flask",
@@ -1 +0,0 @@
1
- exclude docs/* */Makefile
@@ -1,392 +0,0 @@
1
- import os
2
- import pytest
3
- import FlaskSimpleAuth as fsa
4
- import FlaskTester as ft
5
- from FlaskTester import ft_client, ft_authenticator
6
- import secret
7
- import http.server as htsv
8
- import threading
9
- import io
10
- import logging
11
- import model
12
-
13
- logging.basicConfig(level=logging.INFO)
14
- # logging.basicConfig(level=logging.DEBUG)
15
- log = logging.getLogger("test")
16
-
17
- # set authn for ft_authenticator
18
- os.environ.update(
19
- FLASK_TESTER_TESTING="*",
20
- FLASK_TESTER_ALLOW="bearer basic param none",
21
- FLASK_TESTER_AUTH=",".join(f"{l}:{p}" for l, p in secret.PASSES.items()),
22
- )
23
-
24
- def test_sanity():
25
- # must provide url or package of Flask application to test
26
- assert "FLASK_TESTER_APP" in os.environ
27
- # log.debug(f"TEST_SEED={os.environ.get('TEST_SEED')}")
28
-
29
- # example from README.md
30
- def authHook(api, user: str, pwd: str|None):
31
- if pwd is not None: # get token
32
- try:
33
- res = api.get("/login", login=user, auth="basic", status=200)
34
- api.setToken(user, res.json["token"])
35
- except ft.FlaskTesterError as e: # pragma: no cover
36
- log.warning(f"error: {e}")
37
- else: # cleanup
38
- api.setToken(user, None)
39
-
40
- @pytest.fixture
41
- def app(ft_client):
42
- # hook when adding login/passwords
43
- ft_client.setHook(authHook)
44
- # Calvin authentication
45
- ft_client.setPass("calvin", secret.PASSES["calvin"])
46
- ft_client.setCookie("hobbes", "lang", "fr")
47
- # Hobbes authentication
48
- ft_client.setPass("hobbes", secret.PASSES["hobbes"])
49
- ft_client.setCookie("calvin", "lang", "en")
50
- # return working client
51
- yield ft_client
52
- # cleanup
53
- ft_client.setPass("calvin", None)
54
- ft_client.setPass("hobbes", None)
55
-
56
- def test_app_admin(app): # GET /admin
57
- app.get("/admin", login=None, status=401)
58
- for auth in ["bearer", "basic", "param"]:
59
- res = app.get("/admin", login="calvin", auth=auth, status=200)
60
- assert res.json["user"] == "calvin" and res.json["isadmin"]
61
- res = app.get("/admin", login="hobbes", auth=auth, status=403)
62
- assert 'not in group "ADMIN"' in res.text
63
-
64
- def test_app_who_am_i(app): # GET /who-am-i
65
- app.get("/who-am-i", login=None, status=401)
66
- for auth in ["bearer", "basic", "param"]:
67
- res = app.get("/who-am-i", login="calvin", auth=auth, status=200)
68
- assert res.json["lang"] == "en" and res.json["isadmin"]
69
- res = app.get("/who-am-i", login="hobbes", auth=auth, status=200)
70
- assert res.json["lang"] == "fr" and not res.json["isadmin"]
71
-
72
- @pytest.fixture
73
- def api(ft_client):
74
- # set a default
75
- ft_client._default_login = "calvin"
76
- # bad password and token
77
- ft_client.setPass("moe", None)
78
- ft_client.setToken("moe", None)
79
- ft_client.setPass("moe", "bad password")
80
- ft_client.setToken("moe", "bad token")
81
- # set language cookies
82
- ft_client.setCookie("calvin", "lang", "en")
83
- ft_client.setCookie("hobbes", "lang", "fr")
84
- # get valid tokens using password authn on /login
85
- res = ft_client.get("/login", login="calvin", auth="basic", status=200)
86
- assert res.json["user"] == "calvin"
87
- ft_client._auth.setToken("calvin", res.json["token"])
88
- res = ft_client.post("/login", login="hobbes", auth="param", status=201, data={})
89
- assert res.json["user"] == "hobbes"
90
- ft_client._auth.setToken("hobbes", res.json["token"])
91
- res = ft_client.post("/login", login="susie", auth="param", status=201, json={})
92
- assert res.json["user"] == "susie"
93
- ft_client._auth.setToken("susie", res.json["token"])
94
- ft_client.get("/login", login="calvin", auth="none", status=401)
95
- # check that token auth and cookie is ok
96
- res = ft_client.get("/who-am-i", login="calvin", status=200, auth="bearer")
97
- assert res.json["user"] == "calvin" and res.json["lang"] == "en"
98
- res = ft_client.get("/who-am-i", login="hobbes", status=200, auth="bearer")
99
- assert res.json["user"] == "hobbes" and res.json["lang"] == "fr"
100
- res = ft_client.get("/who-am-i", login="susie", status=200, auth="bearer")
101
- assert res.json["user"] == "susie" and res.json["lang"] is None
102
- # with defaults
103
- res = ft_client.get("/who-am-i", auth="basic", status=200)
104
- assert res.json["user"] == "calvin"
105
- res = ft_client.get("/who-am-i", auth="param", status=200)
106
- assert res.json["user"] == "calvin"
107
- res = ft_client.get("/who-am-i", auth="bearer", status=200)
108
- assert res.json["user"] == "calvin"
109
- res = ft_client.get("/who-am-i", status=200)
110
- assert res.json["user"] == "calvin"
111
- # ready for testing routes
112
- yield ft_client
113
-
114
- def test_admin(api):
115
- # check authentication schemes
116
- for auth in (None, "basic", "param", "bearer"):
117
- api.get("/admin", status=200, login="calvin", auth=auth)
118
- api.get("/admin", 200, login="susie", auth=auth)
119
- api.get("/admin", 403, login="hobbes", auth=auth)
120
- api.get("/admin", 401, login="moe", auth=auth)
121
- api.get("/admin", 401, login=None, auth=auth)
122
- # test status error
123
- try:
124
- api.get("/admin", status=599, login="calvin", auth=auth)
125
- pytest.fail("assert on status must fail") # pragma: no cover
126
- except ft._AssertError as e:
127
- assert "200" in str(e)
128
- # test content error
129
- try:
130
- api.get("/admin", status=200, login="calvin", auth=auth, content="NOT THERE")
131
- pytest.fail("assert on content must fail") # pragma: no cover
132
- except ft._AssertError as e:
133
- assert "NOT THERE" in str(e)
134
-
135
- def test_errors(api):
136
- # these schemes are not allowed
137
- for scheme in ("header", "cookie", "fake", "tparam"):
138
- try:
139
- api.get("/login", login="calvin", auth=scheme)
140
- pytest.fail("must raise an exception") # pragma: no cover
141
- except ft.AuthError as e:
142
- assert "auth is not allowed" in str(e)
143
- try:
144
- api.get("/login", login="calvin", auth="foobla")
145
- pytest.fail("must raise an exception") # pragma: no cover
146
- except ft.AuthError as e:
147
- assert "unexpected auth" in str(e)
148
-
149
- def test_methods(api):
150
- res = api.get("/who-am-i", login="susie", status=200, cookies={"lang": "it"})
151
- assert res.json["lang"] == "it"
152
- api.post("/who-am-i", login="hobbes", status=405)
153
- api.put("/who-am-i", login="hobbes", status=405)
154
- api.patch("/who-am-i", login="hobbes", status=405)
155
- api.delete("/who-am-i", login="hobbes", status=405)
156
-
157
- def test_hello(api):
158
- res = api.get("/hello", login="calvin", auth="none", status=200)
159
- assert res.json["lang"] == "en" and res.json["hello"] == "Hi"
160
- assert res.headers["FSA-User"] == "None (None)"
161
- res = api.get("/hello", login="hobbes", auth="none", status=200)
162
- assert res.json["lang"] == "fr" and res.json["hello"] == "Salut"
163
- assert res.headers["FSA-User"] == "None (None)"
164
- res = api.get("/hello", login="susie", auth="none", status=200, cookies={"lang": "it"})
165
- assert res.json["lang"] == "it" and res.json["hello"] == "Ciao"
166
- assert res.headers["FSA-User"] == "None (None)"
167
- res = api.get("/hello", login="moe", auth="none", status=200)
168
- assert res.json["lang"] == "en" and res.json["hello"] == "Hi"
169
- assert res.headers["FSA-User"] == "None (None)"
170
-
171
- def test_authenticator_token():
172
- # all token carriers
173
- auth = ft.Authenticator(allow=["bearer", "header", "tparam", "cookie"])
174
- auth.setToken("calvin", "clv-token")
175
- auth.setToken("susie", "ss-token")
176
- auth.setToken("hobbes", "hbs-token")
177
- auth.setToken("moe", "m-token")
178
- auth.setCookie("calvin", "what", "clv-cookie")
179
- kwargs, cookies = {}, {}
180
- auth.setAuth("calvin", kwargs, cookies, auth="bearer")
181
- assert kwargs["headers"]["Authorization"] == "Bearer clv-token"
182
- assert cookies["what"] == "clv-cookie"
183
- kwargs, cookies = {}, {}
184
- auth.setAuth("susie", kwargs, cookies, auth="header")
185
- assert kwargs["headers"]["Auth"] == "ss-token"
186
- assert not cookies
187
- kwargs, cookies = {"data": {}}, {}
188
- auth.setAuth("hobbes", kwargs, cookies, auth="tparam")
189
- assert kwargs["data"]["AUTH"] == "hbs-token"
190
- assert not cookies
191
- kwargs, cookies = {"json": {}}, {}
192
- auth.setAuth("hobbes", kwargs, cookies, auth="tparam")
193
- assert kwargs["json"]["AUTH"] == "hbs-token"
194
- assert not cookies
195
- kwargs, cookies = {}, {}
196
- auth.setAuth("moe", kwargs, cookies, auth="cookie")
197
- assert not kwargs
198
- assert cookies["auth"] == "m-token"
199
- # dad does not have a token
200
- try:
201
- kwargs, cookies = {}, {}
202
- auth.setAuth("dad", kwargs, cookies)
203
- pytest.fail("must raise an error") # pragma: no cover
204
- except ft.FlaskTesterError:
205
- assert True, "error raised"
206
- # rosalyn as a password, but no password carrier is allowed
207
- try:
208
- auth.setPass("rosalyn", "rsln-pass")
209
- pytest.fail("must raise an error") # pragma: no cover
210
- except ft.AuthError:
211
- assert True, "error raised"
212
- # force to trigger later errors
213
- auth._has_pass = True
214
- auth.setPass("rosalyn", "rsln-pass")
215
- try:
216
- kwargs, cookies = {}, {}
217
- auth.setAuth("rosalyn", kwargs, cookies)
218
- pytest.fail("must raise an error") # pragma: no cover
219
- except ft.FlaskTesterError:
220
- assert True, "error raised"
221
-
222
- def test_authenticator_password():
223
- # all password carriers plus fake
224
- auth = ft.Authenticator(allow=["basic", "param", "fake"])
225
- auth.setPass("calvin", "clv-pass")
226
- auth.setPass("hobbes", "hbs-pass")
227
- auth.setPass("moe", "m-pass")
228
- auth.setPass("rosalyn", "rsln-pass")
229
- auth.setCookie("moe", "hello", "world!")
230
- kwargs, cookies = {}, {}
231
- auth.setAuth("calvin", kwargs, cookies, auth="basic")
232
- assert kwargs["auth"] == ("calvin", "clv-pass")
233
- assert not cookies
234
- kwargs, cookies = {"data": {}}, {}
235
- auth.setAuth("hobbes", kwargs, cookies, auth="param")
236
- assert kwargs["data"]["USER"] == "hobbes" and kwargs["data"]["PASS"] == "hbs-pass"
237
- assert not cookies
238
- kwargs, cookies = {"json": {}}, {}
239
- auth.setAuth("moe", kwargs, cookies, auth="param")
240
- assert kwargs["json"]["USER"] == "moe" and kwargs["json"]["PASS"] == "m-pass"
241
- assert cookies["hello"] == "world!"
242
- kwargs, cookies = {"data": {}}, {}
243
- auth.setAuth("rosalyn", kwargs, cookies, auth="fake")
244
- assert kwargs["data"]["LOGIN"] == "rosalyn"
245
- assert not cookies
246
- kwargs, cookies = {"json": {}}, {}
247
- auth.setAuth("hobbes", kwargs, cookies, auth="fake")
248
- assert kwargs["json"]["LOGIN"] == "hobbes"
249
- assert not cookies
250
- # susie as a token, but no token carrier is allowed
251
- try:
252
- auth.setToken("susie", "ss-token")
253
- pytest.fail("must raise an error") # pragma: no cover
254
- except ft.FlaskTesterError:
255
- assert True, "error raised"
256
- # force to trigger later error
257
- auth._has_token = True
258
- auth.setToken("susie", "ss-token")
259
- try:
260
- kwargs, cookies = {}, {}
261
- auth.setAuth("susie", kwargs, cookies)
262
- pytest.fail("must raise an error") # pragma: no cover
263
- except ft.FlaskTesterError:
264
- assert True, "error raised"
265
-
266
- def test_request_flask_response():
267
-
268
- class RequestResponse:
269
- """Local class for testing RequestFlaskResponse."""
270
-
271
- def __init__(self, is_json: bool):
272
- self._is_json = is_json
273
- self.status_code = 200
274
- self.content = b"hello world!"
275
- self.text = "hello world!"
276
- self.headers = {"Server": "test/0.1"}
277
- self.cookies = {}
278
-
279
- def json(self):
280
- if self._is_json:
281
- return {"hello": "world!"}
282
- else:
283
- raise Exception("not json!")
284
-
285
- jres = ft.RequestFlaskResponse(RequestResponse(True))
286
- assert jres.is_json and jres.json is not None
287
-
288
- xres = ft.RequestFlaskResponse(RequestResponse(False))
289
- assert not xres.is_json and xres.json is None
290
-
291
- def test_client():
292
- # abstract class for coverage
293
- client = ft.Client(ft.Authenticator())
294
- try:
295
- client._request("GET", "/", {})
296
- pytest.fail("must raise an error") # pragma: no cover
297
- except NotImplementedError:
298
- assert True, "expected error raised"
299
-
300
- def test_request_client():
301
- # start a tmp server on port 8888 for URL client coverage
302
- httpd = htsv.HTTPServer(("", 8888), htsv.SimpleHTTPRequestHandler)
303
- thread = threading.Thread(target = lambda: httpd.serve_forever())
304
- thread.start()
305
- try:
306
- client = ft.RequestClient(ft.Authenticator(), "http://localhost:8888")
307
- client.get("/", 200)
308
- client.request("GET", "/", 200)
309
- hello = io.BytesIO(b"hello world")
310
- client.post("/", 501, data={"hello": hello})
311
- hello = io.BytesIO(b"hello world")
312
- client.post("/", 501, data={"hello": (hello, "hello.txt", "text/plain")})
313
- client.post("/", 501, data={"hello": "world!"})
314
- finally:
315
- httpd.shutdown()
316
-
317
- def test_client_fixture():
318
- # ft_client coverage
319
- auth = ft._ft_authenticator()
320
- # check and save env
321
- app = None
322
- if "FLASK_TESTER_APP" in os.environ:
323
- app = os.environ["FLASK_TESTER_APP"]
324
- del os.environ["FLASK_TESTER_APP"]
325
- # no url nor app, defaults to "app"
326
- init = ft._ft_client(auth)
327
- # url
328
- os.environ["FLASK_TESTER_APP"] = "http://localhost:5000"
329
- init = ft._ft_client(auth)
330
- assert isinstance(init, ft.RequestClient)
331
- del os.environ["FLASK_TESTER_APP"]
332
- # bad package
333
- os.environ["FLASK_TESTER_APP"] = "no_such_package"
334
- try:
335
- init = ft._ft_client(auth)
336
- pytest.fail("must fail on missing package") # pragma: no cover
337
- except ModuleNotFoundError:
338
- assert True, "expected error raised"
339
- # bad name
340
- os.environ["FLASK_TESTER_APP"] = "app:no_such_app"
341
- try:
342
- init = ft._ft_client(auth)
343
- pytest.fail("must fail on missing package") # pragma: no cover
344
- except ft.FlaskTesterError:
345
- assert True, "expected error raised"
346
- del os.environ["FLASK_TESTER_APP"]
347
- # reset env
348
- if app:
349
- os.environ["FLASK_TESTER_APP"] = app
350
-
351
- def test_classes(api):
352
-
353
- def thing_eq(ta, tb):
354
- ta = model.Thing1(**ta) if isinstance(ta, dict) else ta
355
- tb = model.Thing1(**tb) if isinstance(tb, dict) else tb
356
- return ta.tid == tb.tid and ta.name == tb.name and ta.owner == tb.owner
357
-
358
- # Things
359
- t0 = {"tid": 0, "name": "zero", "owner": "Rosalyn"}
360
- t1 = model.Thing1(tid=1, name="one", owner="Susie")
361
- t2 = model.Thing2(tid=2, name="two", owner="Calvin")
362
- t3 = model.Thing3(tid=3, name="three", owner="Hobbes")
363
-
364
- n = 0
365
- # check all combinations
366
- for path in ["/t0", "/t1", "/t2", "/t3"]:
367
- for param in [t0, t1, t2, t3]:
368
- for tclass in [dict, model.Thing1, model.Thing2, model.Thing3]:
369
- for method in ["GET", "POST"]:
370
- for mode in ["data", "json"]:
371
- n +=1
372
- parameter = {mode: {"t": param}}
373
- res = api.request(method, path, 200, **parameter)
374
- assert res.is_json and isinstance(res.json, dict)
375
- assert thing_eq(tclass(**res.json), param)
376
- assert n == 256
377
-
378
- # simple types translation
379
- assert api.get("/t0", 200, json={"t": None}).json is None
380
- assert api.get("/t0", 200, data={"t": None}).json is None
381
- assert api.get("/t0", 200, json={"t": True}).json == True
382
- assert api.get("/t0", 200, json={"t": False}).json == False
383
- # non working, bad JsonData conversion
384
- api.get("/t0", 400, data={"t": True})
385
- api.get("/t0", 400, data={"t": False})
386
- assert api.get("/t0", 200, json={"t": 2345}).json == 2345
387
- assert api.get("/t0", 200, data={"t": 5432}).json == 5432
388
- assert api.get("/t0", 200, json={"t": 23.45}).json == 23.45
389
- assert api.get("/t0", 200, data={"t": 54.32}).json == 54.32
390
- assert api.get("/t0", 200, json={"t": "Susie"}).json == "Susie"
391
- api.get("/t0", 400, data={"t": "Susie"}) # raw str is not JSON
392
- assert api.get("/t0", 200, data={"t": "\"Susie\""}).json == "Susie"
@@ -1,37 +0,0 @@
1
- import os
2
- import pytest
3
- from FlaskTester import ft_client, ft_authenticator
4
- import secret
5
-
6
- os.environ.update(FLASK_TESTER_ALLOW="basic param none")
7
-
8
- @pytest.fixture
9
- def app(ft_client):
10
- ft_client.setPass("calvin", secret.PASSES["calvin"])
11
- ft_client.setCookie("calvin", "lang", "en")
12
- ft_client.setPass("hobbes", secret.PASSES["hobbes"])
13
- ft_client.setCookie("hobbes", "lang", "fr")
14
- yield ft_client
15
-
16
- def test_something(app):
17
- # requires an authentication
18
- app.get("/authenticated", 401, login=None)
19
- app.get("/authenticated", 200, "Hello", login="calvin")
20
- app.get("/authenticated", 200, "Bonjour", login="hobbes")
21
- # only allowed to calvin
22
- app.get("/only-admin", 401, login=None)
23
- app.get("/only-admin", 200, "administrateur", login="calvin")
24
- app.get("/only-admin", 403, "not in group", login="hobbes")
25
- # no authentication required, but depends on lang
26
- app.get("/open", 200, "Hello", login="calvin", auth="none")
27
- app.get("/open", 200, "Bonjour", login="hobbes", auth="none")
28
- app.get("/open", 200, "Guten Tag", login=None)
29
-
30
- def test_params(app):
31
- res = app.get("/add", 200, data={"i": 39, "j": 3}, login=None)
32
- assert res.is_json and res.json["sum"] == 42
33
- res = app.get("/add", 200, json={"i": 35, "j": 7}, login=None)
34
- assert res.is_json and res.json["sum"] == 42
35
- # mixing data/json is okay for FlaskTester
36
- res = app.get("/add", 200, data={"i": 30}, json={"j": 12}, login=None)
37
- assert res.is_json and res.json["sum"] == 42
File without changes
File without changes
File without changes
File without changes