Skip to content
Snippets Groups Projects
Verified Commit c7b19419 authored by Andreas Ellewsen's avatar Andreas Ellewsen
Browse files

Add more tests for gregui

Adding tests for a serializer prompted moving of view tests to their own
subdirectory.
parent 369baf3f
No related branches found
No related tags found
1 merge request!160Tests/increase coverage
Pipeline #100626 passed
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)
import datetime
import pytest
from django.utils import timezone
from rest_framework.reverse import reverse
from rest_framework import status
from greg.models import OrganizationalUnit
@pytest.mark.django_db
def test_role_anon_post(client):
"""Should get 403 forbidden since we are not a sponsor"""
resp = client.post(reverse("gregui-v1:role-list"), data={})
assert resp.status_code == status.HTTP_403_FORBIDDEN
@pytest.mark.django_db
def test_role_anon_patch(client):
"""Should get 403 forbidden since we are not a sponsor"""
resp = client.patch(reverse("gregui-v1:role-detail", kwargs={"pk": 1}), data={})
assert resp.status_code == status.HTTP_403_FORBIDDEN
@pytest.mark.django_db
def test_role_sponsor_post_ok(client, log_in, user_sponsor, role):
"""Should work since we are a sponsor at this unit"""
log_in(user_sponsor)
resp = client.post(
reverse("gregui-v1:role-list"),
data={
"person": role.person.id,
"type": role.type.id,
"orgunit": role.orgunit.id,
"start_date": "",
"end_date": (timezone.now() + datetime.timedelta(days=10)).strftime(
"%Y-%m-%d"
),
},
)
assert resp.content == b""
assert resp.status_code == status.HTTP_201_CREATED
@pytest.mark.django_db
def test_role_sponsor_post_no_data_fail(client, log_in, user_sponsor):
"""Should fail since we did not provide any role data"""
log_in(user_sponsor)
resp = client.post(reverse("gregui-v1:role-list"), data={})
assert resp.status_code == status.HTTP_400_BAD_REQUEST
@pytest.mark.django_db
def test_role_sponsor_post_fail(client, log_in, user_sponsor, role):
"""Should fail since we are not a sponsor at this unit."""
# Unit the sponsor is not connected to so that we fail
ou = OrganizationalUnit.objects.create(name_nb="foo", name_en="foo_en")
log_in(user_sponsor)
resp = client.post(
reverse("gregui-v1:role-list"),
data={
"person": role.person.id,
"type": role.type.id,
"orgunit": ou.id,
"start_date": "",
"end_date": (timezone.now() + datetime.timedelta(days=10)).strftime(
"%Y-%m-%d"
),
},
)
assert (
resp.content
== b'{"orgunit":["A sponsor can only make changes to roles at units they are sponsors for."]}'
)
assert resp.status_code == status.HTTP_400_BAD_REQUEST
@pytest.mark.django_db
def test_role_sponsor_patch_ok(
client,
log_in,
user_sponsor,
role,
):
"""Should work since we are the sponsor owning the role."""
log_in(user_sponsor)
new_date = (timezone.now() + datetime.timedelta(days=10)).date()
resp = client.patch(
reverse("gregui-v1:role-detail", kwargs={"pk": role.id}),
data={
"end_date": new_date.strftime("%Y-%m-%d"),
},
)
assert resp.status_code == status.HTTP_200_OK
# Verify the new date was set
role.refresh_from_db()
assert role.end_date == new_date
@pytest.mark.django_db
def test_role_sponsor_patch_fail(client, log_in, user_sponsor, role):
"""Should fail since we are not a sponsor at this unit."""
# Unit the sponsor is not connected to so that we fail
ou = OrganizationalUnit.objects.create(name_nb="foo", name_en="foo_en")
log_in(user_sponsor)
resp = client.patch(
reverse("gregui-v1:role-detail", kwargs={"pk": role.id}),
data={
"orgunit": ou.id,
},
)
assert (
resp.content
== b'{"orgunit":["A sponsor can only make changes to roles at units they are sponsors for."]}'
)
assert resp.status_code == status.HTTP_400_BAD_REQUEST
@pytest.mark.django_db
def test_role_sponsor_patch_fail_unknown_role(
client,
log_in,
user_sponsor,
):
"""Should fail since the role does not exist"""
log_in(user_sponsor)
new_date = (timezone.now() + datetime.timedelta(days=10)).date()
resp = client.patch(
reverse("gregui-v1:role-detail", kwargs={"pk": 1}),
data={
"end_date": new_date.strftime("%Y-%m-%d"),
},
)
assert resp.content == b""
assert resp.status_code == status.HTTP_400_BAD_REQUEST
import pytest
from rest_framework.reverse import reverse
from rest_framework import status
@pytest.mark.django_db
def test_userinfo_anon_get(client):
"""Anonymous people should be forbidden."""
response = client.get(reverse("api-userinfo"))
assert response.status_code == status.HTTP_403_FORBIDDEN
@pytest.mark.django_db
def test_userinfo_invited_get(client, invitation_link):
"""Invited guests should get info about themself and the role."""
session = client.session
session["invite_id"] = str(invitation_link.uuid)
session.save()
response = client.get(reverse("api-userinfo"))
assert response.status_code == status.HTTP_200_OK
assert response.json() == {
"feide_id": None,
"sponsor_id": None,
"person_id": 1,
"first_name": "Foo",
"last_name": "Bar",
"email": "foo@example.org",
"mobile_phone": None,
"fnr": None,
"passport": None,
"roles": [
{
"id": 1,
"ou_nb": "Foo NB",
"ou_en": "Foo EN",
"name_nb": "Role Foo NB",
"name_en": "Role Foo EN",
"start_date": None,
"end_date": "2050-10-15",
"sponsor": {"first_name": "Sponsor", "last_name": "Bar"},
}
],
}
@pytest.mark.django_db
def test_userinfo_sponsor_get(client, log_in, user_sponsor):
"""Sponsors should get info about themselves"""
log_in(user_sponsor)
response = client.get(reverse("api-userinfo"))
assert response.status_code == status.HTTP_200_OK
assert response.json() == {
"feide_id": "",
"person_id": None,
"roles": [],
"sponsor_id": 1,
}
@pytest.mark.django_db
def test_userinfo_guest_get(client, log_in, user_person):
"""Logged in guests should get info about themself"""
log_in(user_person)
response = client.get(reverse("api-userinfo"))
assert response.status_code == status.HTTP_200_OK
assert response.json() == {
"feide_id": "",
"sponsor_id": None,
"person_id": 1,
"roles": [],
"first_name": "Foo",
"last_name": "Bar",
"email": "foo@bar.com",
"mobile_phone": None,
"fnr": "123456*****",
"passport": None,
}
......@@ -109,6 +109,13 @@ def sponsor_foo(
return create_sponsor(**sponsor_foo_data, unit=unit_foo)
@pytest.fixture
def sponsor_bar(unit_foo: OrganizationalUnit, create_sponsor) -> Sponsor:
return create_sponsor(
feide_id="bar@example.com", first_name="Bar", last_name="Baz", unit=unit_foo
)
@pytest.fixture
def create_user() -> Callable[[str, str, str, str], UserModel]:
user_model = get_user_model()
......@@ -144,6 +151,23 @@ def user_sponsor(sponsor_foo: Sponsor, create_user) -> User:
return user_model.objects.get(id=user.id)
@pytest.fixture
def user_person(person_foo: Sponsor, create_user) -> User:
user_model = get_user_model()
# Create a user and link him to a sponsor
user = create_user(
username="test_person",
email="person@example.org",
first_name="Test",
last_name="Person",
)
GregUserProfile.objects.create(user=user, person=person_foo)
# This user is a sponsor for unit_foo
return user_model.objects.get(id=user.id)
@pytest.fixture
def create_greg_user_profile() -> Callable[
[UserModel, Optional[Person], Optional[Sponsor]], GregUserProfile
......
......@@ -19,7 +19,7 @@ urlpatterns: List[URLResolver] = [
path("api/ui/v1/session/", views.SessionView.as_view(), name="api-session"),
path("api/ui/v1/testmail/", views.send_test_email, name="api-testmail"),
path("api/ui/v1/whoami/", views.WhoAmIView.as_view(), name="api-whoami"),
path("api/ui/v1/userinfo/", UserInfoView.as_view()), # type: ignore
path("api/ui/v1/userinfo/", UserInfoView.as_view(), name="api-userinfo"), # type: ignore
path("api/ui/v1/ous/", OusView.as_view()),
path("api/ui/v1/guests/", GuestInfoView.as_view()),
]
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment