forked from beba/foerderbarometer
153 lines
4.0 KiB
Python
153 lines
4.0 KiB
Python
from typing import Any, Iterable, Mapping, Union, Tuple, Protocol
|
|
|
|
from django.apps import apps
|
|
from django.conf import settings
|
|
from django.http import HttpRequest, HttpResponse
|
|
from django.http.response import HttpResponseRedirectBase, StreamingHttpResponse
|
|
from django.shortcuts import resolve_url
|
|
from django.template import Context
|
|
from django.template.response import TemplateResponse
|
|
from django.test import Client, SimpleTestCase
|
|
from django.urls import reverse, ResolverMatch
|
|
from django.utils.http import urlencode
|
|
|
|
FormData = dict
|
|
JSONDict = dict
|
|
JSONList = list
|
|
RequestData = Union[FormData, JSONDict, JSONList]
|
|
QueryParams = Union[Mapping[str, Any], Iterable[Tuple[str, Any]]]
|
|
|
|
|
|
class TestClientResponse(Protocol):
|
|
client: Client
|
|
request: HttpRequest
|
|
templates: list
|
|
context: Context
|
|
resolver_match: ResolverMatch
|
|
|
|
def json(self) -> Union[JSONList, JSONDict]: ...
|
|
|
|
|
|
Response = Union[
|
|
HttpResponse,
|
|
HttpResponseRedirectBase,
|
|
StreamingHttpResponse,
|
|
TemplateResponse,
|
|
TestClientResponse,
|
|
]
|
|
|
|
|
|
class ObjectWithGetAbsoluteURLMethod(Protocol):
|
|
|
|
def get_absolute_url(self) -> str: ...
|
|
|
|
|
|
URL = Union[str, ObjectWithGetAbsoluteURLMethod]
|
|
URLArgs = Union[tuple, list]
|
|
URLKwargs = dict
|
|
|
|
|
|
def get_url(url: URL, args: URLArgs = None, kwargs: URLKwargs = None) -> str:
|
|
"""
|
|
Helper to reverse the given url name.
|
|
"""
|
|
|
|
if args or kwargs:
|
|
return reverse(url, args=args, kwargs=kwargs)
|
|
|
|
return resolve_url(url)
|
|
|
|
|
|
def get_handler(test_case: SimpleTestCase, method: str = None, data=None):
|
|
if data:
|
|
method = str.lower(method or 'POST')
|
|
else:
|
|
method = str.lower(method or 'GET')
|
|
|
|
return getattr(test_case.client, method)
|
|
|
|
|
|
def request(
|
|
test_case: SimpleTestCase,
|
|
url: URL,
|
|
status_code: int = None,
|
|
expected_url: URL = None,
|
|
args: URLArgs = None,
|
|
kwargs: URLKwargs = None,
|
|
headers: dict = None,
|
|
msg: str = None,
|
|
query_params: QueryParams = None,
|
|
method: str = None,
|
|
data: RequestData = None,
|
|
**options,
|
|
) -> Response:
|
|
"""
|
|
A helper to make a request with the test case's http client.
|
|
|
|
The given args and kwargs are used to reverse the url
|
|
but not the expected url. When expected url needs
|
|
args/kwargs pass an absolute url instead.
|
|
|
|
All additional kwargs are passed as post parameters.
|
|
When posting without parameters just pass post=True.
|
|
"""
|
|
|
|
data = data or options or None
|
|
handler = get_handler(test_case, method, data)
|
|
url = get_url(url, args, kwargs)
|
|
|
|
if query_params:
|
|
url = f'{url}?%s' % urlencode(query_params, doseq=True)
|
|
|
|
headers = headers or {}
|
|
status_code = status_code or 200
|
|
response = handler(url, data=data, **headers)
|
|
msg = msg or getattr(response, 'content', None)
|
|
|
|
if expected_url:
|
|
test_case.assertRedirects(
|
|
response=response,
|
|
expected_url=get_url(expected_url),
|
|
target_status_code=status_code,
|
|
)
|
|
else:
|
|
test_case.assertEqual(response.status_code, status_code, msg=msg)
|
|
|
|
return response
|
|
|
|
|
|
def login(test_case: SimpleTestCase, user=None, password: str = None) -> bool:
|
|
"""
|
|
Logs in the user trying to use the raw password or the given password.
|
|
Force logs in the user when no password is found.
|
|
"""
|
|
|
|
user = user or getattr(test_case, 'user')
|
|
password = password or getattr(user, 'raw_password', password)
|
|
|
|
if password is None:
|
|
return test_case.client.force_login(user=user) or True
|
|
|
|
return test_case.client.login(username=user.username, password=password)
|
|
|
|
|
|
def create_user(username: str, *, model=None, **kwargs):
|
|
model = model or apps.get_model(settings.AUTH_USER_MODEL)
|
|
password = kwargs.setdefault('password', 'P4sSW0rD')
|
|
|
|
kwargs.setdefault('email', f'{username}@test.case')
|
|
kwargs.setdefault(model.USERNAME_FIELD, username)
|
|
|
|
user = model.objects.create_user(**kwargs)
|
|
|
|
user.raw_password = password
|
|
|
|
return user
|
|
|
|
|
|
def create_superuser(username: str, **kwargs):
|
|
kwargs['is_superuser'] = True
|
|
kwargs['is_staff'] = True
|
|
|
|
return create_user(username, **kwargs)
|