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)
 |