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

Merge branch 'tests/increase-coverage' into 'master'

Increase test coverage

See merge request !150
parents 6d5020d1 a6820d47
No related branches found
No related tags found
1 merge request!150Increase test coverage
Pipeline #100432 passed
......@@ -91,7 +91,7 @@ class InvitationView(CreateAPIView, DestroyAPIView):
logger.warning(
f"Attempting to delete invitation for already registered guest with person ID {person_id}"
)
return Response(status.HTTP_400_BAD_REQUEST)
return Response(status=status.HTTP_400_BAD_REQUEST)
# Delete the person. The delete will cascade and all roles, identities and invitations will be removed.
# It is OK to do this here since the person has not gone through the registration, so it is not
......@@ -237,6 +237,7 @@ class InvitedGuestView(GenericAPIView):
person = invite_link.invitation.role.person
data = request.data
fnr = data.get("person") and data["person"].get("fnr")
# If there is a Feide ID registered with the guest, assume that the name is also coming from there
feide_id = self._get_identity_or_none(person, Identity.IdentityType.FEIDE_ID)
......@@ -248,7 +249,7 @@ class InvitedGuestView(GenericAPIView):
):
return Response(status=status.HTTP_400_BAD_REQUEST)
if self._verified_fnr_already_exists(person) and "fnr" in data:
if self._verified_fnr_already_exists(person) and fnr:
# The user should not be allowed to change a verified fnr
return Response(status=status.HTTP_400_BAD_REQUEST)
......
......@@ -56,7 +56,9 @@ class PersonView(APIView):
def patch(self, request, id):
person = Person.objects.get(id=id)
# For now only the e-mail is allowed to be updated
email = request.data["email"]
email = request.data.get("email")
if not email:
return Response(status=status.HTTP_400_BAD_REQUEST)
validate_email(email)
# The following line will raise an exception if the e-mail is not valid
create_identity_or_update(Identity.IdentityType.PRIVATE_EMAIL, email, person)
......
import datetime
from django.utils import timezone
import pytest
from rest_framework import status
......@@ -8,14 +10,14 @@ from greg.models import InvitationLink, Person, Identity
@pytest.mark.django_db
def test_get_invite(client):
def test_post_invite(client):
"""Forbid access with bad invitation link uuid"""
response = client.post(reverse("gregui-v1:invite-verify"), data={"uuid": "baduuid"})
assert response.status_code == status.HTTP_403_FORBIDDEN
@pytest.mark.django_db
def test_get_invite_ok(client, invitation_link):
def test_post_invite_ok(client, invitation_link):
"""Access okay with valid invitation link"""
response = client.post(
reverse("gregui-v1:invite-verify"), data={"uuid": invitation_link.uuid}
......@@ -24,7 +26,7 @@ def test_get_invite_ok(client, invitation_link):
@pytest.mark.django_db
def test_get_invite_expired(client, invitation_link_expired):
def test_post_invite_expired(client, invitation_link_expired):
"""Forbid access with expired invite link"""
response = client.post(
reverse("gregui-v1:invite-verify"), data={"uuid": invitation_link_expired.uuid}
......@@ -32,8 +34,22 @@ def test_get_invite_expired(client, invitation_link_expired):
assert response.status_code == status.HTTP_403_FORBIDDEN
@pytest.mark.django_db
def test_post_missing_invite_id(client):
"""Forbid access if no id provided."""
response = client.post(reverse("gregui-v1:invite-verify"))
assert response.status_code == status.HTTP_403_FORBIDDEN
@pytest.mark.django_db
def test_get_invited_info_no_session(client, invitation_link):
"""Forbid access if invite expired after session was created."""
# get a session
client.post(reverse("gregui-v1:invite-verify"), data={"uuid": invitation_link.uuid})
# expire the invitation link
invitation_link.expire = timezone.now() - datetime.timedelta(days=1)
invitation_link.save()
# fail to get info because session has expired
response = client.get(reverse("gregui-v1:invited-info"))
assert response.status_code == status.HTTP_403_FORBIDDEN
......@@ -336,3 +352,41 @@ def test_name_update_allowed_if_feide_identity_is_not_present(
person.refresh_from_db()
assert person.first_name == "Someone"
assert person.last_name == "Test"
@pytest.mark.django_db
def test_post_info_fail_fnr_already_verified(client, invited_person_verified_nin):
"""Ensure that an automatically verified fnr cannot be changed"""
person, invitation_link = invited_person_verified_nin
fnr = "10093720895"
session = client.session
session["invite_id"] = str(invitation_link.uuid)
session.save()
url = reverse("gregui-v1:invited-info")
data = {"person": {"mobile_phone": "+4797543992", "fnr": fnr}}
response = client.post(url, data, format="json")
# Verify rejection
assert response.status_code == status.HTTP_400_BAD_REQUEST
# Verify fnr was not changed
person.refresh_from_db()
assert person.fnr.value != fnr
@pytest.mark.django_db
def test_post_info_fail_unknown_field(client, invited_person_verified_nin):
"""Ensure that including an unknown field gives bad request"""
_, invitation_link = invited_person_verified_nin
session = client.session
session["invite_id"] = str(invitation_link.uuid)
session.save()
url = reverse("gregui-v1:invited-info")
data = {"person": {"mobile_phone": "+4797543992", "badfield": "foo"}}
response = client.post(url, data, format="json")
# Verify rejection
assert response.status_code == status.HTTP_400_BAD_REQUEST
......@@ -82,6 +82,30 @@ def test_invite_cancel(client, invitation_link, invitation, role, log_in, user_s
assert InvitationLink.objects.filter(invitation__id=invitation.id).count() == 0
@pytest.mark.django_db
def test_fail_delete_confirmed_invitation(
client, role, log_in, user_sponsor, sponsor_foo, invitation, invitation_link
):
log_in(user_sponsor)
role = Role.objects.get(pk=role.id)
pe = Person.objects.get(pk=role.person_id)
pe.registration_completed_date = datetime.date.today()
pe.save()
assert pe.registration_completed_date
assert pe.is_registered
url = reverse("gregui-v1:invitation")
response = client.delete(f"{url}?person_id={str(pe.id)}")
assert response.status_code == status.HTTP_400_BAD_REQUEST
# The role, invitation and connected links should still exist
assert Role.objects.filter(id=role.id).count() == 1
assert Invitation.objects.filter(id=invitation.id).count() == 1
assert InvitationLink.objects.filter(invitation__id=invitation.id).count() == 1
@pytest.mark.django_db
def test_invite_resend_existing_invite_active(
client,
......@@ -162,3 +186,74 @@ def test_invite_resend_existing_invite_not_active(
InvitationLink.objects.get(
invitation__role__person_id=person_invited.id, expire__gt=timezone.now()
)
@pytest.mark.django_db
def test_invite_resend_person_no_invites_fail(
client, log_in, user_sponsor, person_invited
):
"""Resending an invite for a person without invites should return bad request."""
log_in(user_sponsor)
url = reverse("gregui-v1:invite-resend", kwargs={"person_id": person_invited.id})
response = client.patch(url)
assert response.status_code == status.HTTP_400_BAD_REQUEST
@pytest.mark.django_db
def test_invite_resend_person_multiple_links_send_all(
client, log_in, user_sponsor, invited_person, registration_template, mocker
):
"""Resending an invite for a person with multiple working links should resend all of them."""
send_invite_mock_function = mocker.patch(
"gregui.api.views.invitation.send_invite_mail"
)
log_in(user_sponsor)
person, invitation = invited_person
invitation = Invitation.objects.filter(role__person_id=person.id).first()
InvitationLink.objects.create(
invitation=invitation, expire=timezone.now() + datetime.timedelta(days=1)
)
InvitationLink.objects.create(
invitation=invitation, expire=timezone.now() + datetime.timedelta(days=1)
)
invitation_links_for_person = InvitationLink.objects.filter(
invitation__role__person_id=person.id
)
assert invitation_links_for_person.count() == 3
url = reverse("gregui-v1:invite-resend", kwargs={"person_id": person.id})
response = client.patch(url)
assert response.status_code == status.HTTP_200_OK
assert send_invite_mock_function.call_count == 3
@pytest.mark.django_db
def test_invite_resend_person_multiple_expired_links_send_all(
client, log_in, user_sponsor, invited_person, registration_template, mocker
):
"""
Resending invites for a person with multiple invitations where all links are
expired should resend all of them.
"""
send_invite_mock_function = mocker.patch(
"gregui.api.views.invitation.send_invite_mail"
)
log_in(user_sponsor)
# Expire invitation link
person, invitation = invited_person
invitation = Invitation.objects.filter(role__person_id=person.id).first()
link = InvitationLink.objects.get(invitation=invitation)
link.expire = timezone.now() - datetime.timedelta(days=1)
link.save()
# Make another invitation with an expired link
inv2 = Invitation.objects.create(role=invitation.role)
InvitationLink.objects.create(
invitation=inv2, expire=timezone.now() - datetime.timedelta(days=1)
)
# Resend request should trigger creation of new links for both invitations
url = reverse("gregui-v1:invite-resend", kwargs={"person_id": person.id})
response = client.patch(url)
assert response.status_code == status.HTTP_200_OK
assert send_invite_mock_function.call_count == 2
import pytest
from rest_framework import status
from rest_framework.reverse import reverse
@pytest.mark.django_db
def test_get_person_fail(client):
"""Anonymous user cannot get person info"""
url = reverse("gregui-v1:person-get", kwargs={"id": 1})
response = client.get(url)
assert response.status_code == status.HTTP_403_FORBIDDEN
@pytest.mark.django_db
def test_get_person(client, log_in, user_sponsor, invited_person):
"""Logged in sponsor can get person info"""
person, _ = invited_person
url = reverse("gregui-v1:person-get", kwargs={"id": person.id})
log_in(user_sponsor)
response = client.get(url)
assert response.status_code == status.HTTP_200_OK
@pytest.mark.django_db
def test_patch_person_no_data_fail(client, log_in, user_sponsor, invited_person):
"""No data in patch should fail"""
person, _ = invited_person
url = reverse("gregui-v1:person-get", kwargs={"id": person.id})
log_in(user_sponsor)
response = client.patch(url)
assert response.status_code == status.HTTP_400_BAD_REQUEST
@pytest.mark.django_db
def test_patch_person_new_email_ok(client, log_in, user_sponsor, invited_person):
"""Logged in sponsor can update email address of person"""
person, _ = invited_person
url = reverse("gregui-v1:person-get", kwargs={"id": person.id})
log_in(user_sponsor)
assert person.private_email.value == "foo@example.org"
response = client.patch(url, data={"email": "new@example.com"})
assert response.status_code == status.HTTP_200_OK
person.refresh_from_db()
assert person.private_email.value == "new@example.com"
......@@ -385,6 +385,40 @@ def invited_person_no_ids(
)
@pytest.fixture
def invited_person_verified_nin(
create_person,
create_role,
create_invitation,
create_invitation_link,
sponsor_foo,
unit_foo,
role_type_foo,
) -> Tuple[Person, InvitationLink]:
"""
Invited person, with a verified NIN.
"""
person = create_person(
first_name="Victor",
last_name="Verified",
email="foo@bar2.com",
nin="12345678912",
)
fnr = person.identities.get(type=Identity.IdentityType.NORWEGIAN_NATIONAL_ID_NUMBER)
fnr.verified = Identity.Verified.AUTOMATIC
fnr.save()
role = create_role(
person=person, sponsor=sponsor_foo, unit=unit_foo, role_type=role_type_foo
)
invitation = create_invitation(role=role)
invitation_link = create_invitation_link(invitation=invitation)
return Person.objects.get(id=person.id), InvitationLink.objects.get(
id=invitation_link.id
)
@pytest.fixture
def log_in(client) -> Callable[[UserModel], APIClient]:
def _log_in(user):
......
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