Skip to content

Commit

Permalink
tests(rdvi): add more tests
Browse files Browse the repository at this point in the history
  • Loading branch information
leo-naeka committed Sep 11, 2024
1 parent 923a839 commit 0c6985f
Show file tree
Hide file tree
Showing 8 changed files with 536 additions and 61 deletions.
8 changes: 4 additions & 4 deletions itou/templates/apply/includes/appointments.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,15 @@ <h3>Rendez-vous</h3>
</td>
<td>{{ participation.appointment.starts_at }}</td>
<td>{{ participation.appointment.reason }}</td>
<td>
<button type="button" class="btn btn-link px-0" data-bs-toggle="modal" data-bs-target="#participation-details-{{ participation.pk }}">
<td id="participation-{{ participation.pk }}-row">
<button type="button" class="btn btn-link px-0" data-bs-toggle="modal" data-bs-target="#participation-{{ participation.pk }}-modal">
Détails
</button>
<div class="modal modal--mini fade" id="participation-details-{{ participation.pk }}" tabindex="-1" aria-labelledby="participation-details-{{ participation.pk }}-title" aria-hidden="true">
<div class="modal modal--mini fade" id="participation-{{ participation.pk }}-modal" tabindex="-1" aria-labelledby="participation-{{ participation.pk }}-modal-title" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h3 class="modal-title" id="participation-details-{{ participation.pk }}-title">Détails du rendez-vous</h3>
<h3 class="modal-title" id="participation-{{ participation.pk }}-modal-title">Détails du rendez-vous</h3>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Fermer"></button>
</div>
<div class="modal-body">
Expand Down
13 changes: 13 additions & 0 deletions tests/rdv_insertion/factories.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,12 @@ class Meta:
skip_postgeneration_save = True

class Params:
for_snapshot = factory.Trait(
reason_category=InvitationRequest.ReasonCategory.SIAE_INTERVIEW,
job_seeker__for_snapshot=True,
company__for_snapshot=True,
email_invitation__for_snapshot=True,
)
with_sms_invitation = factory.Trait(
job_seeker__phone="0600000000",
sms_invitation=factory.RelatedFactory(
Expand Down Expand Up @@ -104,6 +110,13 @@ class InvitationFactory(factory.django.DjangoModelFactory):
class Meta:
model = Invitation

class Params:
for_snapshot = factory.Trait(
type=Invitation.Type.EMAIL,
status=Invitation.Status.DELIVERED,
rdv_insertion_id=1234,
)

type = factory.Faker("random_element", elements=Invitation.Type.values)
status = factory.Faker("random_element", elements=Invitation.Status.values)
rdv_insertion_id = factory.Sequence(lambda n: n)
Expand Down
179 changes: 178 additions & 1 deletion tests/rdv_insertion/tests.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import datetime
import os
from urllib.parse import urljoin

Expand All @@ -7,13 +8,24 @@
from django.core.cache import cache
from django.core.exceptions import ImproperlyConfigured
from django.test import override_settings
from freezegun import freeze_time

from itou.rdv_insertion.api import RDV_S_CREDENTIALS_CACHE_KEY, get_api_credentials
from itou.rdv_insertion.api import (
RDV_I_INVITATION_DELIVERED_STATUSES,
RDV_I_INVITATION_NOT_DELIVERED_STATUSES,
RDV_S_CREDENTIALS_CACHE_KEY,
get_api_credentials,
get_invitation_status,
)
from itou.rdv_insertion.models import Invitation, Participation
from itou.utils.mocks.rdv_insertion import (
RDV_INSERTION_AUTH_FAILURE_BODY,
RDV_INSERTION_AUTH_SUCCESS_BODY,
RDV_INSERTION_AUTH_SUCCESS_HEADERS,
)
from tests.job_applications.factories import JobApplicationFactory
from tests.prescribers.factories import PrescriberOrganizationWithMembershipFactory
from tests.rdv_insertion.factories import InvitationFactory, InvitationRequestFactory, ParticipationFactory
from tests.utils.test import TestCase


Expand Down Expand Up @@ -94,3 +106,168 @@ def test_renewal_failure_rdvi_misconfiguration(self):
get_api_credentials()
assert not respx.routes["rdv_solidarites_sign_in"].called
assert cache.ttl(RDV_S_CREDENTIALS_CACHE_KEY) == 0


class TestRdvInsertionApiUtils:
def test_get_invitation_status_opened(self):
invitation_dict = {"clicked": True}
assert get_invitation_status(invitation_dict) == Invitation.Status.OPENED

def test_get_invitation_status_delivered(self, subtests):
for status in RDV_I_INVITATION_DELIVERED_STATUSES:
invitation_dict = {"clicked": False, "delivery_status": status}
with subtests.test(status=status):
assert get_invitation_status(invitation_dict) == Invitation.Status.DELIVERED

def test_get_invitation_status_not_delivered(self, subtests):
for status in RDV_I_INVITATION_NOT_DELIVERED_STATUSES:
invitation_dict = {"clicked": False, "delivery_status": status}
with subtests.test(status=status):
assert get_invitation_status(invitation_dict) == Invitation.Status.NOT_DELIVERED

def test_get_invitation_status_logs_error_for_unknown_status(self, caplog):
invitation_dict = {"clicked": False, "delivery_status": "unknown_status"}
get_invitation_status(invitation_dict)
assert "Invalid RDV-I invitation status: 'unknown_status' not in supported list" in caplog.messages


class TestInvitationRequestModel:
def setup_method(self, **kwargs):
organization = PrescriberOrganizationWithMembershipFactory(
membership__user__first_name="Max", membership__user__last_name="Throughput"
)
self.job_application = JobApplicationFactory(
to_company__name="Hit Pit",
to_company__with_membership=True,
to_company__rdv_insertion_id=1234,
job_seeker__first_name="Jacques",
job_seeker__last_name="Henry",
sender=organization.active_members.get(),
for_snapshot=True,
)
self.invitation_request = InvitationRequestFactory(
job_seeker=self.job_application.job_seeker,
company=self.job_application.to_company,
email_invitation=None,
)
self.invitation_email = InvitationFactory(
invitation_request=self.invitation_request,
type=Invitation.Type.EMAIL,
status=Invitation.Status.DELIVERED,
rdv_insertion_id=1234,
)
self.invitation_sms = InvitationFactory(
invitation_request=self.invitation_request,
type=Invitation.Type.SMS,
status=Invitation.Status.DELIVERED,
rdv_insertion_id=1235,
)

def test_email_invitation_property(self):
assert self.invitation_request.email_invitation == self.invitation_email

self.invitation_email.delete()
assert self.invitation_request.email_invitation is None

def test_sms_invitation_property(self):
assert self.invitation_request.sms_invitation == self.invitation_sms

self.invitation_sms.delete()
assert self.invitation_request.sms_invitation is None


class TestInvitationModel:
def setup_method(self, **kwargs):
self.invitation_request = InvitationRequestFactory(email_invitation=None)
self.invitation_email = InvitationFactory(
invitation_request=self.invitation_request,
type=Invitation.Type.EMAIL,
status=Invitation.Status.DELIVERED,
rdv_insertion_id=1234,
)
self.invitation_sms = InvitationFactory(
invitation_request=self.invitation_request,
type=Invitation.Type.SMS,
status=Invitation.Status.DELIVERED,
rdv_insertion_id=1235,
)
self.invitation_postal = InvitationFactory(
invitation_request=self.invitation_request,
type=Invitation.Type.POSTAL,
status=Invitation.Status.DELIVERED,
rdv_insertion_id=1236,
)

def test_is_email_property(self):
assert self.invitation_email.is_email
assert not self.invitation_sms.is_email
assert not self.invitation_postal.is_email

def test_is_sms_property(self):
assert not self.invitation_email.is_sms
assert self.invitation_sms.is_sms
assert not self.invitation_postal.is_sms

def test_is_postal_property(self):
assert not self.invitation_email.is_postal
assert not self.invitation_sms.is_postal
assert self.invitation_postal.is_postal


@freeze_time("2024-08-01")
class TestParticipationModel:
def setup_method(self, freeze, **kwargs):
organization = PrescriberOrganizationWithMembershipFactory(
membership__user__first_name="Max", membership__user__last_name="Throughput"
)
self.job_application = JobApplicationFactory(
to_company__name="Hit Pit",
to_company__with_membership=True,
to_company__rdv_insertion_id=1234,
job_seeker__first_name="Jacques",
job_seeker__last_name="Henry",
sender=organization.active_members.get(),
for_snapshot=True,
)
self.participation = ParticipationFactory(
job_seeker=self.job_application.job_seeker,
appointment__company=self.job_application.to_company,
appointment__starts_at=datetime.datetime(2024, 8, 1, 8, 0, tzinfo=datetime.UTC),
)

def test_get_status_display(self):
# Status unknow and starts_at in the future
self.participation.status = Participation.Status.UNKNOWN
assert self.participation.get_status_display() == "RDV à venir"

# Status unknown and starts_at in the past
self.participation.appointment.starts_at = datetime.datetime(2024, 7, 31, tzinfo=datetime.UTC)
assert self.participation.get_status_display() == "Statut du RDV à préciser"

self.participation.status = Participation.Status.SEEN
assert self.participation.get_status_display() == Participation.Status.SEEN.label

self.participation.status = Participation.Status.REVOKED
assert self.participation.get_status_display() == Participation.Status.REVOKED.label

self.participation.status = Participation.Status.EXCUSED
assert self.participation.get_status_display() == Participation.Status.EXCUSED.label

self.participation.status = Participation.Status.NOSHOW
assert self.participation.get_status_display() == Participation.Status.NOSHOW.label

def test_get_status_class_name(self):
self.participation.status = Participation.Status.UNKNOWN
assert self.participation.get_status_class_name() == "bg-important-lightest text-important"

self.participation.status = Participation.Status.SEEN
assert self.participation.get_status_class_name() == "bg-success-lighter text-success"

self.participation.status = Participation.Status.REVOKED
assert self.participation.get_status_class_name() == "bg-warning-lighter text-warning"

self.participation.status = Participation.Status.EXCUSED
assert self.participation.get_status_class_name() == "bg-warning-lighter text-warning"

self.participation.status = Participation.Status.NOSHOW
assert self.participation.get_status_class_name() == "bg-danger-lighter text-danger"
20 changes: 20 additions & 0 deletions tests/utils/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
from itou.utils.perms.middleware import ItouCurrentOrganizationMiddleware
from itou.utils.sync import DiffItem, DiffItemKind, yield_sync_diff
from itou.utils.templatetags import dict_filters, format_filters, job_applications, job_seekers
from itou.utils.templatetags.datetime_filters import duration
from itou.utils.tokens import COMPANY_SIGNUP_MAGIC_LINK_TIMEOUT, CompanySignupTokenGenerator
from itou.utils.urls import (
add_url_params,
Expand Down Expand Up @@ -1586,3 +1587,22 @@ def test_create_fake_postcode():
with mock.patch.dict(DEPARTMENTS, {"80": "80 - Somme"}):
postcode = create_fake_postcode()
assert department_from_postcode(postcode)


@pytest.mark.parametrize(
"timedelta, expected",
[
(datetime.timedelta(seconds=0), "N/A"),
(datetime.timedelta(seconds=30), "N/A"),
(datetime.timedelta(minutes=1), "1 min"),
(datetime.timedelta(minutes=30), "30 min"),
(datetime.timedelta(hours=1), "1h"),
(datetime.timedelta(hours=1, minutes=30), "1h30"),
(datetime.timedelta(hours=12), "12h"),
(datetime.timedelta(hours=12, minutes=30), "12h30"),
(datetime.timedelta(days=1), "24h"),
(datetime.timedelta(days=1, hours=1, minutes=30), "25h30"),
],
)
def test_duration(timedelta, expected):
assert duration(timedelta) == expected
Loading

0 comments on commit 0c6985f

Please sign in to comment.