Skip to content
Snippets Groups Projects
test_role.py 6.52 KiB
import datetime
import re

import pytest
from django.utils import timezone
from rest_framework.exceptions import ValidationError

from gregui.api.serializers.role import RoleSerializerUi


@pytest.mark.django_db
def test_minimum_ok(role, sponsor_foo):
    """The minimum amount of fields works"""
    ser = RoleSerializerUi(
        data={
            "person": role.person.id,
            "orgunit": role.orgunit.id,
            "type": role.type.id,
            "start_date": None,
            "end_date": (timezone.now() + datetime.timedelta(days=10)).date(),
        },
        context={"sponsor": sponsor_foo},
    )
    assert ser.is_valid(raise_exception=True)


@pytest.mark.django_db
def test_start_date_past_fail(role, sponsor_foo):
    """Should fail because of start_date in the past"""
    ser = RoleSerializerUi(
        data={
            "person": role.person.id,
            "orgunit": role.orgunit.id,
            "type": role.type.id,
            "start_date": (timezone.now() - datetime.timedelta(days=10)).date(),
            "end_date": (timezone.now() + datetime.timedelta(days=10)).date(),
        },
        context={"sponsor": sponsor_foo},
    )
    with pytest.raises(
        ValidationError,
        match=re.escape(
            "{'start_date': [ErrorDetail(string='Start date cannot be in the past', code='invalid')]}"
        ),
    ):
        ser.is_valid(raise_exception=True)


@pytest.mark.django_db
def test_end_date_past_fail(role, sponsor_foo):
    """Should fail because of end_date in the past"""
    ser = RoleSerializerUi(
        data={
            "person": role.person.id,
            "orgunit": role.orgunit.id,
            "type": role.type.id,
            "start_date": datetime.date.today(),
            "end_date": (timezone.now() - datetime.timedelta(days=10)).date(),
        },
        context={"sponsor": sponsor_foo},
    )
    with pytest.raises(
        ValidationError,
        match=re.escape(
            "{'end_date': [ErrorDetail(string='End date cannot be in the past', code='invalid')]}"
        ),
    ):
        ser.is_valid(raise_exception=True)


@pytest.mark.django_db
def test_end_date_expired_role_fail(role, sponsor_foo):
    """New end date fail because role has ended"""
    # Expire the role to ensure failure
    role.end_date = datetime.date.today() - datetime.timedelta(days=10)
    role.save()
    # Try to change it
    ser = RoleSerializerUi(
        instance=role,
        data={
            "person": role.person.id,
            "orgunit": role.orgunit.id,
            "type": role.type.id,
            "start_date": datetime.date.today(),
            "end_date": (timezone.now() + datetime.timedelta(days=10)).date(),
        },
        context={"sponsor": sponsor_foo},
    )
    # Verify that a validation error is raised
    with pytest.raises(
        ValidationError,
        match=re.escape(
            "{'end_date': [ErrorDetail(string='Role has ended, cannot change end date', code='invalid')]}"
        ),
    ):
        ser.is_valid(raise_exception=True)


@pytest.mark.django_db
def test_wrong_sponsor(role, sponsor_foo, sponsor_bar):
    """Touching another sponsor's roles does not work"""
    # Try to touch sponsor_foo's guest role as sponsor_bar
    ser = RoleSerializerUi(
        instance=role,
        data={
            "person": role.person.id,
            "orgunit": role.orgunit.id,
            "type": role.type.id,
            "start_date": datetime.date.today(),
            "end_date": (timezone.now() + datetime.timedelta(days=10)).date(),
        },
        context={"sponsor": sponsor_bar},
    )
    # Verify that a validation error is raised
    with pytest.raises(
        ValidationError,
        match=re.escape(
            "{'non_field_errors': [ErrorDetail(string='You can only edit your own roles.', code='invalid')]}"
        ),
    ):
        ser.is_valid(raise_exception=True)


@pytest.mark.django_db
def test_too_future_end_date(role, sponsor_foo):
    """Setting the end date further than max_days of role_type fails"""
    max_future = timezone.now().date() + datetime.timedelta(days=role.type.max_days)
    ser = RoleSerializerUi(
        instance=role,
        data={
            "person": role.person.id,
            "orgunit": role.orgunit.id,
            "type": role.type.id,
            "start_date": datetime.date.today(),
            "end_date": max_future + datetime.timedelta(days=1),
        },
        context={"sponsor": sponsor_foo},
    )
    # Verify that a validation error is raised
    with pytest.raises(
        ValidationError,
        match=re.escape(
            "".join(
                [
                    "{'non_field_errors': [ErrorDetail(string=",
                    f"'New end date too far into the future for this type. Must be before {max_future}.'",
                    ", code='invalid')]}",
                ]
            )
        ),
    ):
        ser.is_valid(raise_exception=True)


@pytest.mark.django_db
def test_end_before_start(role, sponsor_foo):
    """Setting the end date before start date not allowed"""
    # Existing instance
    ser = RoleSerializerUi(
        instance=role,
        data={
            "person": role.person.id,
            "orgunit": role.orgunit.id,
            "type": role.type.id,
            "start_date": datetime.date.today() + datetime.timedelta(days=1),
            "end_date": datetime.date.today(),
        },
        context={"sponsor": sponsor_foo},
    )
    # Verify that a validation error is raised
    with pytest.raises(
        ValidationError,
        match=re.escape(
            "".join(
                [
                    "{'non_field_errors': [ErrorDetail(string=",
                    "'End date cannot be before start date.'",
                    ", code='invalid')]}",
                ]
            )
        ),
    ):
        ser.is_valid(raise_exception=True)

    # New instance
    ser = RoleSerializerUi(
        data={
            "person": role.person.id,
            "orgunit": role.orgunit.id,
            "type": role.type.id,
            "start_date": datetime.date.today() + datetime.timedelta(days=1),
            "end_date": datetime.date.today(),
        },
        context={"sponsor": sponsor_foo},
    )
    # Verify that a validation error is raised
    with pytest.raises(
        ValidationError,
        match=re.escape(
            "".join(
                [
                    "{'non_field_errors': [ErrorDetail(string=",
                    "'End date cannot be before start date.'",
                    ", code='invalid')]}",
                ]
            )
        ),
    ):
        ser.is_valid(raise_exception=True)