/
utils.py
89 lines (79 loc) · 3.7 KB
/
utils.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
from __future__ import annotations
from typing import TYPE_CHECKING
from django.conf import settings
from django.test.client import Client
from django.urls import reverse
from ...conftest import ANONYMOUS
from ...utils import assert_no_error_messages
if TYPE_CHECKING:
from typing import Any
from _pytest.logging import LogCaptureFixture
from .view_config import PostData, Roles, ViewKwargs, ViewName
def check_view_status_code(
login_role_user: tuple[Client, str],
caplog: LogCaptureFixture,
view_name: ViewName,
kwargs: ViewKwargs,
post_data: PostData,
roles: Roles,
) -> None:
"""
This test checks whether the given view return the correct status code for the current role
:param login_role_user: The fixture providing the http client and the current role (see :meth:`~tests.conftest.login_role_user`)
:param caplog: The :fixture:`caplog` fixture
:param view_name: The identifier of the view
:param kwargs: The keyword argument passed to the view
:param post_data: The post data for this view
:param roles: The list of roles which should be able to access this view
"""
client, role = login_role_user
if isinstance(view_name, tuple):
next_url = reverse(view_name[0], kwargs=kwargs)
url = f"{next_url}?{view_name[1]}"
else:
next_url = url = reverse(view_name, kwargs=kwargs)
if post_data:
post_kwargs = {"data": post_data}
# If the post data is a string, assume json as content type
if isinstance(post_data, str):
post_kwargs["content_type"] = "application/json"
response = client.post(url, **post_kwargs)
else:
response = client.get(url)
print(response.headers)
assert_no_error_messages(caplog)
if role in roles:
# If the role should be allowed to access the view, we expect a successful result
if post_data:
if (
response.headers.get("Content-Type") == "application/json"
or post_kwargs.get("content_type") == "application/json"
):
# Json-views should return 200 or 201 CREATED (for feedback)
assert response.status_code in [
200,
201,
], f"JSON view {view_name} returned status code {response.status_code} instead of 200 or 201 for role {role}"
else:
# Normal post-views should redirect after a successful operation (200 usually mean form errors)
assert (
response.status_code == 302
), f"POST view {view_name} returned status code {response.status_code} instead of 302 for role {role}"
else:
# Get-views should return 200
assert (
response.status_code == 200
), f"GET view {view_name} returned status code {response.status_code} instead of 200 for role {role}"
elif role == ANONYMOUS:
# For anonymous users, we want to redirect to the login form instead of showing an error
assert (
response.status_code == 302
), f"View {view_name} did not enforce access control for anonymous users (status code {response.status_code} instead of 302)"
assert (
response.headers.get("location") == f"{settings.LOGIN_URL}?next={next_url}"
), f"View {view_name} did not redirect to login for anonymous users (location header {response.headers.get('location')})"
else:
# For logged in users, we want to show an error if they get a permission denied
assert (
response.status_code == 403
), f"View {view_name} did not enforce access control for role {role} (status code {response.status_code} instead of 403)"