FlaskTester 3.0__tar.gz → 3.2__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,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: FlaskTester
3
- Version: 3.0
3
+ Version: 3.2
4
4
  Summary: Pytest fixtures for Flask internal and external authenticated tests
5
5
  Author-email: Fabien Coelho <flask.tester@coelho.net>
6
6
  License: CC0
@@ -46,13 +46,13 @@ Requires-Dist: myst_parser; extra == "doc"
46
46
  This package allows to run authenticated tests against a Flask application,
47
47
  either with internal Flask tests (aka `test_client`) or external tests (with
48
48
  `requests` which performs actual HTTP requests), including password and token
49
- authentication.
49
+ authentication and per-user cookies.
50
50
 
51
51
  Only one set of tests is needed, switching from internal to external is
52
52
  achieved through environment variables.
53
53
 
54
54
  ![Status](https://github.com/zx80/flask-tester/actions/workflows/package.yml/badge.svg?branch=main&style=flat)
55
- ![Tests](https://img.shields.io/badge/tests-11%20✓-success)
55
+ ![Tests](https://img.shields.io/badge/tests-12%20✓-success)
56
56
  ![Coverage](https://img.shields.io/badge/coverage-100%25-success)
57
57
  ![Issues](https://img.shields.io/github/issues/zx80/flask-tester?style=flat)
58
58
  ![Python](https://img.shields.io/badge/python-3-informational)
@@ -87,8 +87,8 @@ def app(ft_client):
87
87
  assert res.is_json
88
88
  ft_client.setToken("hobbes", res.json["token"])
89
89
  # also set a cookie
90
- ft_client.setCookie("hobbes", "lang", "fr_FR")
91
- ft_client.setCookie("calvin", "lang", "en_EN")
90
+ ft_client.setCookie("hobbes", "lang", "fr")
91
+ ft_client.setCookie("calvin", "lang", "en")
92
92
  # return working client
93
93
  yield ft_client
94
94
 
@@ -109,7 +109,7 @@ def test_app_admin(app):
109
109
  This can be run against a (local) server:
110
110
 
111
111
  ```shell
112
- export TEST_SEED="some-random-data" # shared seed
112
+ export TEST_SEED="some-random-data" # shared test seed
113
113
  flask --app app:app run & # start flask app
114
114
  pid=$! # keep pid
115
115
  export FLASK_TESTER_URL="http://localhost:5000" # set app local url
@@ -128,6 +128,11 @@ The above test runs with [`tests/app.py`](tests/app.py)
128
128
  [Flask](https://flask.palletsprojects.com/)
129
129
  REST application back-end with password and token authentication based on
130
130
  [FlaskSimpleAuth](https://pypi.org/project/FlaskSimpleAuth/).
131
+ The code uses _25_ lines of Python for implementing
132
+ password (basic and parameters) and token authentications,
133
+ admin group authorization, and routes for
134
+ token generation (2), identity tests (2) and an incredible open cookie-based
135
+ translation service.
131
136
 
132
137
  ## Fixtures
133
138
 
@@ -155,11 +160,12 @@ The package provides two fixtures:
155
160
  - `FLASK_TESTER_LOG_LEVEL` log level for module,
156
161
  default is `NOTSET`.
157
162
 
158
- The fixture has 3 main methods:
163
+ The fixture has 4 main methods:
159
164
  - `setPass` to associate a password to a user, set to _None_ to remove credential.
160
165
  - `setToken` to associate a token to a user, set to _None_ to remove credential.
161
166
  - `setCookie` to add a cookie to a user, set value to _None_ to remove cookie.
162
- - `setAuth` to add authentication data to a request `kwargs` and `cookies`.
167
+ - `setAuth` to add authentication data to a request `kwargs` and `cookies`.
168
+ This method is called automatically for adding credentials to a request.
163
169
 
164
170
  - `ft_client` for app testing, which depends on the previous fixture, plus
165
171
  environment variables which allow to find the application, at least one must
@@ -178,7 +184,7 @@ The package provides two fixtures:
178
184
 
179
185
  The fixture then provides test methods to issue test requests against a Flask application:
180
186
  - `request` generic request with `login`, `auth`, `status` end `content` extensions.
181
- - `get post put patch delete` methods with `login`, `auth` and `status` extensions.
187
+ - `get post put patch delete` methods with `login`, `auth` and `status` extensions.
182
188
  Moreover, `setPass`, `setToken` and `setCookie` are forwarded to the internal authenticator.
183
189
 
184
190
  Authenticator environment variables can be set from the pytest Python test file by
@@ -242,6 +248,17 @@ Packages are distributed from [PyPI](https://pypi.org/project/FlaskTester/),
242
248
  see also the [documentation](https://zx80.github.io/flask-tester/),
243
249
  please report any [issues](https://github.com/zx80/flask-tester/issues).
244
250
 
251
+ ### 3.2 on 2024-03-24
252
+
253
+ Improved documentation.
254
+ Simpler code and API documentation.
255
+
256
+ ### 3.1 on 2024-03-24
257
+
258
+ More consistent test and demo code.
259
+ Reach actual full coverage, without _any_ pragma.
260
+ Fix default allowed authenticator schemes.
261
+
245
262
  ### 3.0 on 2024-03-23
246
263
 
247
264
  Add support for `none` authentication, with only cookies.
@@ -293,7 +293,8 @@ class Client:
293
293
  """Run a request and return response."""
294
294
  raise NotImplementedError()
295
295
 
296
- def request(self, method: str, path: str, status: int|None = None, auth: str|None = None, **kwargs):
296
+ def request(self, method: str, path: str, status: int|None = None, content: str|None = None,
297
+ auth: str|None = None, **kwargs):
297
298
  """Run a possibly authenticated HTTP request.
298
299
 
299
300
  Mandatory parameters:
@@ -304,6 +305,7 @@ class Client:
304
305
  Optional parameters:
305
306
 
306
307
  - ``status``: expected HTTP status, *None* to skip status check
308
+ - ``content``: regular expression for response body, *None* to skip content check
307
309
  - ``login``: authenticated user, use **explicit** *None* to skip
308
310
  - ``auth``: authentication scheme to use instead of default behavior
309
311
  - ``**kwargs``: more request parameters (headers, data, json…)
@@ -323,11 +325,18 @@ class Client:
323
325
  self._auth.setAuth(login, kwargs, cookies, auth=auth)
324
326
  res = self._request(method, path, cookies, **kwargs) # type: ignore
325
327
 
328
+ # check status
326
329
  if status is not None:
327
330
  if res.status_code != status: # show error before aborting
328
331
  log.error(f"bad {status} result: {res.status_code} {res.text[:512]}")
329
332
  assert res.status_code == status, f"unexpected status {res.status_code}, expecting {status}"
330
333
 
334
+ # check content
335
+ if content is not None:
336
+ if not re.search(content, res.text, re.DOTALL):
337
+ log.error(f"cannot find {content} in {res.text}")
338
+ assert False, f"expected content {content} not found in {res.text}"
339
+
331
340
  return res
332
341
 
333
342
  def get(self, path, **kwargs):
@@ -350,32 +359,13 @@ class Client:
350
359
  """HTTP DELETE request."""
351
360
  return self.request("DELETE", path, **kwargs)
352
361
 
353
- def check(self, method: str, path: str, status: int, content: str|None = None, **kwargs):
354
- """Run a query and check the response.
355
-
356
- Mandatory parameters:
362
+ def check(self, method: str, path: str, status: int, **kwargs):
363
+ """Run a query and check the response status.
357
364
 
358
- - ``method``: HTTP method ("GET", "POST", "PATCH", "DELETE"…)
359
- - ``path``: local path under the base URL
360
- - ``status``: expected HTTP status
361
-
362
- Optional parameters:
363
-
364
- - ``content``: regular expression in response body
365
- - ``login``: authenticated user, use explicit *None* to skip
366
- - ``**kwargs``: more request parameters (headers, data, json…)
365
+ Same as ``request``, but ``status`` is mandatory.
367
366
  """
368
367
 
369
- # get HTTP response
370
- res = self.request(method, path, status=status, **kwargs)
371
-
372
- # check contents
373
- if content is not None:
374
- if not re.search(content, res.text, re.DOTALL):
375
- log.error(f"cannot find {content} in {res.text}")
376
- assert False, f"expected content {content} not found in {res.text}"
377
-
378
- return res
368
+ return self.request(method, path, status=status, **kwargs)
379
369
 
380
370
 
381
371
  class RequestClient(Client):
@@ -455,36 +445,8 @@ class FlaskClient(Client):
455
445
 
456
446
  return self._client.open(method=method, path=path, **kwargs)
457
447
 
458
-
459
- @pytest.fixture
460
- def ft_authenticator():
461
- """Pytest Fixture: ft_authenticator.
462
-
463
- Environment variables:
464
-
465
- - ``FLASK_TESTER_LOG_LEVEL``: package log level in
466
- ``DEBUG INFO WARNING ERROR CRITICAL NOSET``.
467
- Default is ``NOTSET``.
468
- - ``FLASK_TESTER_ALLOW``: allowed space-separated authentication schemes, in
469
- ``basic param bearer header cookie tparam fake none``.
470
- Default is ``bearer basic param``.
471
- - ``FLASK_TESTER_USER``: user login parameter for ``param`` authentication.
472
- Default is ``USER``.
473
- - ``FLASK_TESTER_PASS``: user password parameter for ``param`` authentication.
474
- Default is ``PASS``.
475
- - ``FLASK_TESTER_LOGIN``: user login parameter for ``fake`` authentication.
476
- Default is ``LOGIN``.
477
- - ``FLASK_TESTER_BEARER``: bearer name for *token* authentication.
478
- Default is ``Bearer``.
479
- - ``FLASK_TESTER_HEADER``: header name for *token* authentication.
480
- Default is ``Auth``.
481
- - ``FLASK_TESTER_COOKIE``: cookie name for *token* authentication.
482
- Default is ``auth``.
483
- - ``FLASK_TESTER_TPARAM``: parameter for *token* authentication.
484
- Default is ``AUTH``.
485
- - ``FLASK_TESTER_AUTH``: initial comma-separated list of *login:password*.
486
- Default is not set.
487
- """
448
+ def _ft_authenticator():
449
+ """Fixture implementation separated for testing."""
488
450
 
489
451
  level = os.environ.get("FLASK_TESTER_LOG_LEVEL", "NOTSET")
490
452
  log.setLevel(logging.DEBUG if level == "DEBUG" else
@@ -494,7 +456,7 @@ def ft_authenticator():
494
456
  logging.CRITICAL if level == "CRITICAL" else
495
457
  logging.NOTSET)
496
458
 
497
- allow = os.environ.get("FLASK_TESTER_ALLOW", "bearer basic param").split(" ")
459
+ allow = os.environ.get("FLASK_TESTER_ALLOW", "bearer basic param none").split(" ")
498
460
 
499
461
  # per-scheme parameters, must be consistent with FSA configuration
500
462
  user = os.environ.get("FLASK_TESTER_USER", "USER")
@@ -511,31 +473,50 @@ def ft_authenticator():
511
473
  if "FLASK_TESTER_AUTH" in os.environ:
512
474
  auth.setPasses(os.environ["FLASK_TESTER_AUTH"].split(","))
513
475
 
514
- yield auth
515
-
476
+ return auth
516
477
 
517
478
  @pytest.fixture
518
- def ft_client(ft_authenticator):
519
- """Pytest Fixture: ft_client.
479
+ def ft_authenticator():
480
+ """Pytest Fixture: ft_authenticator.
520
481
 
521
- Target environment variable, one **must** be defined:
482
+ Environment variables:
522
483
 
523
- - ``FLASK_TESTER_URL``: application HTTP base URL.
524
- - ``FLASK_TESTER_APP``: Flask application, eg ``app:create_app``.
484
+ - ``FLASK_TESTER_LOG_LEVEL``: package log level in
485
+ ``DEBUG INFO WARNING ERROR CRITICAL NOSET``.
486
+ Default is ``NOTSET``.
487
+ - ``FLASK_TESTER_ALLOW``: allowed space-separated authentication schemes, in
488
+ ``basic param bearer header cookie tparam fake none``.
489
+ Default is ``bearer basic param none``.
490
+ - ``FLASK_TESTER_USER``: user login parameter for ``param`` authentication.
491
+ Default is ``USER``.
492
+ - ``FLASK_TESTER_PASS``: user password parameter for ``param`` authentication.
493
+ Default is ``PASS``.
494
+ - ``FLASK_TESTER_LOGIN``: user login parameter for ``fake`` authentication.
495
+ Default is ``LOGIN``.
496
+ - ``FLASK_TESTER_BEARER``: bearer name for *token* authentication.
497
+ Default is ``Bearer``.
498
+ - ``FLASK_TESTER_HEADER``: header name for *token* authentication.
499
+ Default is ``Auth``.
500
+ - ``FLASK_TESTER_COOKIE``: cookie name for *token* authentication.
501
+ Default is ``auth``.
502
+ - ``FLASK_TESTER_TPARAM``: parameter for *token* authentication.
503
+ Default is ``AUTH``.
504
+ - ``FLASK_TESTER_AUTH``: initial comma-separated list of *login:password*.
505
+ Default is not set.
506
+ """
525
507
 
526
- Other environment variable:
508
+ yield _ft_authenticator()
527
509
 
528
- - ``FLASK_TESTER_DEFAULT``: Default client login, default is *None* for no
529
- default.
530
- """
510
+ def _ft_client(authenticator):
511
+ """Fixture implementation separated for testing."""
531
512
 
532
513
  default_login = os.environ.get("FLASK_TESTER_DEFAULT", None)
533
514
  client: Client
534
515
 
535
- if "FLASK_TESTER_URL" in os.environ: # pragma: no cover
516
+ if "FLASK_TESTER_URL" in os.environ:
536
517
 
537
518
  app_url = os.environ["FLASK_TESTER_URL"]
538
- client = RequestClient(ft_authenticator, app_url, default_login)
519
+ client = RequestClient(authenticator, app_url, default_login)
539
520
 
540
521
  elif "FLASK_TESTER_APP" in os.environ:
541
522
 
@@ -553,12 +534,29 @@ def ft_client(ft_authenticator):
553
534
  if callable(app) and not hasattr(app, "test_client"):
554
535
  app = app()
555
536
  break
556
- if not app: # pragma: no cover
537
+ if not app:
557
538
  raise FlaskTesterError(f"cannot find Flask app in {pkg_name}")
558
- client = FlaskClient(ft_authenticator, app.test_client(), default_login)
539
+ client = FlaskClient(authenticator, app.test_client(), default_login)
559
540
 
560
- else: # pragma: no cover
541
+ else:
561
542
 
562
543
  raise FlaskTesterError("no Flask application to test")
563
544
 
564
- yield client
545
+ return client
546
+
547
+ @pytest.fixture
548
+ def ft_client(ft_authenticator):
549
+ """Pytest Fixture: ft_client.
550
+
551
+ Target environment variable, one **must** be defined:
552
+
553
+ - ``FLASK_TESTER_URL``: application HTTP base URL.
554
+ - ``FLASK_TESTER_APP``: Flask application, eg ``app:create_app``.
555
+
556
+ Other environment variable:
557
+
558
+ - ``FLASK_TESTER_DEFAULT``: Default client login, default is *None* for no
559
+ default.
560
+ """
561
+
562
+ yield _ft_client(ft_authenticator)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: FlaskTester
3
- Version: 3.0
3
+ Version: 3.2
4
4
  Summary: Pytest fixtures for Flask internal and external authenticated tests
5
5
  Author-email: Fabien Coelho <flask.tester@coelho.net>
6
6
  License: CC0
@@ -46,13 +46,13 @@ Requires-Dist: myst_parser; extra == "doc"
46
46
  This package allows to run authenticated tests against a Flask application,
47
47
  either with internal Flask tests (aka `test_client`) or external tests (with
48
48
  `requests` which performs actual HTTP requests), including password and token
49
- authentication.
49
+ authentication and per-user cookies.
50
50
 
51
51
  Only one set of tests is needed, switching from internal to external is
52
52
  achieved through environment variables.
53
53
 
54
54
  ![Status](https://github.com/zx80/flask-tester/actions/workflows/package.yml/badge.svg?branch=main&style=flat)
55
- ![Tests](https://img.shields.io/badge/tests-11%20✓-success)
55
+ ![Tests](https://img.shields.io/badge/tests-12%20✓-success)
56
56
  ![Coverage](https://img.shields.io/badge/coverage-100%25-success)
57
57
  ![Issues](https://img.shields.io/github/issues/zx80/flask-tester?style=flat)
58
58
  ![Python](https://img.shields.io/badge/python-3-informational)
@@ -87,8 +87,8 @@ def app(ft_client):
87
87
  assert res.is_json
88
88
  ft_client.setToken("hobbes", res.json["token"])
89
89
  # also set a cookie
90
- ft_client.setCookie("hobbes", "lang", "fr_FR")
91
- ft_client.setCookie("calvin", "lang", "en_EN")
90
+ ft_client.setCookie("hobbes", "lang", "fr")
91
+ ft_client.setCookie("calvin", "lang", "en")
92
92
  # return working client
93
93
  yield ft_client
94
94
 
@@ -109,7 +109,7 @@ def test_app_admin(app):
109
109
  This can be run against a (local) server:
110
110
 
111
111
  ```shell
112
- export TEST_SEED="some-random-data" # shared seed
112
+ export TEST_SEED="some-random-data" # shared test seed
113
113
  flask --app app:app run & # start flask app
114
114
  pid=$! # keep pid
115
115
  export FLASK_TESTER_URL="http://localhost:5000" # set app local url
@@ -128,6 +128,11 @@ The above test runs with [`tests/app.py`](tests/app.py)
128
128
  [Flask](https://flask.palletsprojects.com/)
129
129
  REST application back-end with password and token authentication based on
130
130
  [FlaskSimpleAuth](https://pypi.org/project/FlaskSimpleAuth/).
131
+ The code uses _25_ lines of Python for implementing
132
+ password (basic and parameters) and token authentications,
133
+ admin group authorization, and routes for
134
+ token generation (2), identity tests (2) and an incredible open cookie-based
135
+ translation service.
131
136
 
132
137
  ## Fixtures
133
138
 
@@ -155,11 +160,12 @@ The package provides two fixtures:
155
160
  - `FLASK_TESTER_LOG_LEVEL` log level for module,
156
161
  default is `NOTSET`.
157
162
 
158
- The fixture has 3 main methods:
163
+ The fixture has 4 main methods:
159
164
  - `setPass` to associate a password to a user, set to _None_ to remove credential.
160
165
  - `setToken` to associate a token to a user, set to _None_ to remove credential.
161
166
  - `setCookie` to add a cookie to a user, set value to _None_ to remove cookie.
162
- - `setAuth` to add authentication data to a request `kwargs` and `cookies`.
167
+ - `setAuth` to add authentication data to a request `kwargs` and `cookies`.
168
+ This method is called automatically for adding credentials to a request.
163
169
 
164
170
  - `ft_client` for app testing, which depends on the previous fixture, plus
165
171
  environment variables which allow to find the application, at least one must
@@ -178,7 +184,7 @@ The package provides two fixtures:
178
184
 
179
185
  The fixture then provides test methods to issue test requests against a Flask application:
180
186
  - `request` generic request with `login`, `auth`, `status` end `content` extensions.
181
- - `get post put patch delete` methods with `login`, `auth` and `status` extensions.
187
+ - `get post put patch delete` methods with `login`, `auth` and `status` extensions.
182
188
  Moreover, `setPass`, `setToken` and `setCookie` are forwarded to the internal authenticator.
183
189
 
184
190
  Authenticator environment variables can be set from the pytest Python test file by
@@ -242,6 +248,17 @@ Packages are distributed from [PyPI](https://pypi.org/project/FlaskTester/),
242
248
  see also the [documentation](https://zx80.github.io/flask-tester/),
243
249
  please report any [issues](https://github.com/zx80/flask-tester/issues).
244
250
 
251
+ ### 3.2 on 2024-03-24
252
+
253
+ Improved documentation.
254
+ Simpler code and API documentation.
255
+
256
+ ### 3.1 on 2024-03-24
257
+
258
+ More consistent test and demo code.
259
+ Reach actual full coverage, without _any_ pragma.
260
+ Fix default allowed authenticator schemes.
261
+
245
262
  ### 3.0 on 2024-03-23
246
263
 
247
264
  Add support for `none` authentication, with only cookies.
@@ -3,13 +3,13 @@
3
3
  This package allows to run authenticated tests against a Flask application,
4
4
  either with internal Flask tests (aka `test_client`) or external tests (with
5
5
  `requests` which performs actual HTTP requests), including password and token
6
- authentication.
6
+ authentication and per-user cookies.
7
7
 
8
8
  Only one set of tests is needed, switching from internal to external is
9
9
  achieved through environment variables.
10
10
 
11
11
  ![Status](https://github.com/zx80/flask-tester/actions/workflows/package.yml/badge.svg?branch=main&style=flat)
12
- ![Tests](https://img.shields.io/badge/tests-11%20✓-success)
12
+ ![Tests](https://img.shields.io/badge/tests-12%20✓-success)
13
13
  ![Coverage](https://img.shields.io/badge/coverage-100%25-success)
14
14
  ![Issues](https://img.shields.io/github/issues/zx80/flask-tester?style=flat)
15
15
  ![Python](https://img.shields.io/badge/python-3-informational)
@@ -44,8 +44,8 @@ def app(ft_client):
44
44
  assert res.is_json
45
45
  ft_client.setToken("hobbes", res.json["token"])
46
46
  # also set a cookie
47
- ft_client.setCookie("hobbes", "lang", "fr_FR")
48
- ft_client.setCookie("calvin", "lang", "en_EN")
47
+ ft_client.setCookie("hobbes", "lang", "fr")
48
+ ft_client.setCookie("calvin", "lang", "en")
49
49
  # return working client
50
50
  yield ft_client
51
51
 
@@ -66,7 +66,7 @@ def test_app_admin(app):
66
66
  This can be run against a (local) server:
67
67
 
68
68
  ```shell
69
- export TEST_SEED="some-random-data" # shared seed
69
+ export TEST_SEED="some-random-data" # shared test seed
70
70
  flask --app app:app run & # start flask app
71
71
  pid=$! # keep pid
72
72
  export FLASK_TESTER_URL="http://localhost:5000" # set app local url
@@ -85,6 +85,11 @@ The above test runs with [`tests/app.py`](tests/app.py)
85
85
  [Flask](https://flask.palletsprojects.com/)
86
86
  REST application back-end with password and token authentication based on
87
87
  [FlaskSimpleAuth](https://pypi.org/project/FlaskSimpleAuth/).
88
+ The code uses _25_ lines of Python for implementing
89
+ password (basic and parameters) and token authentications,
90
+ admin group authorization, and routes for
91
+ token generation (2), identity tests (2) and an incredible open cookie-based
92
+ translation service.
88
93
 
89
94
  ## Fixtures
90
95
 
@@ -112,11 +117,12 @@ The package provides two fixtures:
112
117
  - `FLASK_TESTER_LOG_LEVEL` log level for module,
113
118
  default is `NOTSET`.
114
119
 
115
- The fixture has 3 main methods:
120
+ The fixture has 4 main methods:
116
121
  - `setPass` to associate a password to a user, set to _None_ to remove credential.
117
122
  - `setToken` to associate a token to a user, set to _None_ to remove credential.
118
123
  - `setCookie` to add a cookie to a user, set value to _None_ to remove cookie.
119
- - `setAuth` to add authentication data to a request `kwargs` and `cookies`.
124
+ - `setAuth` to add authentication data to a request `kwargs` and `cookies`.
125
+ This method is called automatically for adding credentials to a request.
120
126
 
121
127
  - `ft_client` for app testing, which depends on the previous fixture, plus
122
128
  environment variables which allow to find the application, at least one must
@@ -135,7 +141,7 @@ The package provides two fixtures:
135
141
 
136
142
  The fixture then provides test methods to issue test requests against a Flask application:
137
143
  - `request` generic request with `login`, `auth`, `status` end `content` extensions.
138
- - `get post put patch delete` methods with `login`, `auth` and `status` extensions.
144
+ - `get post put patch delete` methods with `login`, `auth` and `status` extensions.
139
145
  Moreover, `setPass`, `setToken` and `setCookie` are forwarded to the internal authenticator.
140
146
 
141
147
  Authenticator environment variables can be set from the pytest Python test file by
@@ -199,6 +205,17 @@ Packages are distributed from [PyPI](https://pypi.org/project/FlaskTester/),
199
205
  see also the [documentation](https://zx80.github.io/flask-tester/),
200
206
  please report any [issues](https://github.com/zx80/flask-tester/issues).
201
207
 
208
+ ### 3.2 on 2024-03-24
209
+
210
+ Improved documentation.
211
+ Simpler code and API documentation.
212
+
213
+ ### 3.1 on 2024-03-24
214
+
215
+ More consistent test and demo code.
216
+ Reach actual full coverage, without _any_ pragma.
217
+ Fix default allowed authenticator schemes.
218
+
202
219
  ### 3.0 on 2024-03-23
203
220
 
204
221
  Add support for `none` authentication, with only cookies.
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "FlaskTester"
7
- version = "3.0"
7
+ version = "3.2"
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"
@@ -38,8 +38,8 @@ def app(ft_client):
38
38
  assert res.is_json
39
39
  ft_client.setToken("hobbes", res.json["token"])
40
40
  # also set a cookie
41
- ft_client.setCookie("hobbes", "lang", "fr_FR")
42
- ft_client.setCookie("calvin", "lang", "en_EN")
41
+ ft_client.setCookie("hobbes", "lang", "fr")
42
+ ft_client.setCookie("calvin", "lang", "en")
43
43
  # return working client
44
44
  yield ft_client
45
45
 
@@ -136,16 +136,16 @@ def test_methods(api):
136
136
 
137
137
  def test_hello(api):
138
138
  res = api.get("/hello", login="calvin", auth="none", status=200)
139
- assert res.json["hello"] == "Hi"
139
+ assert res.json["lang"] == "en" and res.json["hello"] == "Hi"
140
140
  assert res.headers["FSA-User"] == "None (None)"
141
141
  res = api.get("/hello", login="hobbes", auth="none", status=200)
142
- assert res.json["hello"] == "Salut"
142
+ assert res.json["lang"] == "fr" and res.json["hello"] == "Salut"
143
143
  assert res.headers["FSA-User"] == "None (None)"
144
144
  res = api.get("/hello", login="susie", auth="none", status=200, cookies={"lang": "it"})
145
- assert res.json["hello"] == "Ciao"
145
+ assert res.json["lang"] == "it" and res.json["hello"] == "Ciao"
146
146
  assert res.headers["FSA-User"] == "None (None)"
147
147
  res = api.get("/hello", login="moe", auth="none", status=200)
148
- assert res.json["hello"] == "Hi"
148
+ assert res.json["lang"] == "en" and res.json["hello"] == "Hi"
149
149
  assert res.headers["FSA-User"] == "None (None)"
150
150
 
151
151
  def test_authenticator_token():
@@ -269,6 +269,7 @@ def test_request_flask_response():
269
269
  assert not xres.is_json and xres.json is None
270
270
 
271
271
  def test_client():
272
+ # abstract class for coverage
272
273
  client = ft.Client(ft.Authenticator())
273
274
  try:
274
275
  client._request("GET", "/", {})
@@ -277,6 +278,7 @@ def test_client():
277
278
  assert True, "expected error raised"
278
279
 
279
280
  def test_request_client():
281
+ # start a tmp server on port 8888 for URL client coverage
280
282
  httpd = htsv.HTTPServer(("", 8888), htsv.SimpleHTTPRequestHandler)
281
283
  thread = threading.Thread(target = lambda: httpd.serve_forever())
282
284
  thread.start()
@@ -290,3 +292,48 @@ def test_request_client():
290
292
  client.post("/", status=501, data={"hello": "world!"})
291
293
  finally:
292
294
  httpd.shutdown()
295
+
296
+ def test_client_fixture():
297
+ # ft_client coverage
298
+ auth = ft._ft_authenticator()
299
+ # check and save env
300
+ # assert "FLASK_TESTER_URL" not in os.environ
301
+ url = None
302
+ if "FLASK_TESTER_URL" in os.environ: # pragma: no cover
303
+ url = os.environ["FLASK_TESTER_URL"]
304
+ del os.environ["FLASK_TESTER_URL"]
305
+ app = None
306
+ if "FLASK_TESTER_APP" in os.environ:
307
+ app = os.environ["FLASK_TESTER_APP"]
308
+ del os.environ["FLASK_TESTER_APP"]
309
+ # no url nor app
310
+ try:
311
+ init = ft._ft_client(auth)
312
+ pytest.fail("must fail without environment variables") # pragma: no cover
313
+ except ft.FlaskTesterError:
314
+ assert True, "expected error raised"
315
+ # url
316
+ os.environ["FLASK_TESTER_URL"] = "http://localhost:5000"
317
+ init = ft._ft_client(auth)
318
+ assert isinstance(init, ft.RequestClient)
319
+ del os.environ["FLASK_TESTER_URL"]
320
+ # bad package
321
+ os.environ["FLASK_TESTER_APP"] = "no_such_package"
322
+ try:
323
+ init = ft._ft_client(auth)
324
+ pytest.fail("must fail on missing package") # pragma: no cover
325
+ except ModuleNotFoundError:
326
+ assert True, "expected error raised"
327
+ # bad name
328
+ os.environ["FLASK_TESTER_APP"] = "app:no_such_app"
329
+ try:
330
+ init = ft._ft_client(auth)
331
+ pytest.fail("must fail on missing package") # pragma: no cover
332
+ except ft.FlaskTesterError:
333
+ assert True, "expected error raised"
334
+ del os.environ["FLASK_TESTER_APP"]
335
+ # reset env
336
+ if url: # pragma: no cover
337
+ os.environ["FLASK_TESTER_URL"] = url
338
+ if app:
339
+ os.environ["FLASK_TESTER_APP"] = app
File without changes
File without changes
File without changes