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.
- {flasktester-5.0 → flasktester-5.1}/FlaskTester.egg-info/PKG-INFO +4 -4
- {flasktester-5.0 → flasktester-5.1}/FlaskTester.egg-info/SOURCES.txt +1 -3
- flasktester-5.1/MANIFEST.in +1 -0
- {flasktester-5.0 → flasktester-5.1}/PKG-INFO +4 -4
- {flasktester-5.0 → flasktester-5.1}/pyproject.toml +2 -3
- flasktester-5.0/MANIFEST.in +0 -1
- flasktester-5.0/tests/test_app.py +0 -392
- flasktester-5.0/tests/test_app2.py +0 -37
- {flasktester-5.0 → flasktester-5.1}/FlaskTester.egg-info/dependency_links.txt +0 -0
- {flasktester-5.0 → flasktester-5.1}/FlaskTester.egg-info/requires.txt +0 -0
- {flasktester-5.0 → flasktester-5.1}/FlaskTester.egg-info/top_level.txt +0 -0
- {flasktester-5.0 → flasktester-5.1}/FlaskTester.py +0 -0
- {flasktester-5.0 → flasktester-5.1}/LICENSE +0 -0
- {flasktester-5.0 → flasktester-5.1}/README.md +0 -0
- {flasktester-5.0 → flasktester-5.1}/setup.cfg +0 -0
|
@@ -1,16 +1,15 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: FlaskTester
|
|
3
|
-
Version: 5.
|
|
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
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
exclude docs/* tests/* */Makefile
|
|
@@ -1,16 +1,15 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: FlaskTester
|
|
3
|
-
Version: 5.
|
|
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.
|
|
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 =
|
|
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",
|
flasktester-5.0/MANIFEST.in
DELETED
|
@@ -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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|