From a9900a507a4f17eb520a57096ca1236e89b5ff5a Mon Sep 17 00:00:00 2001 From: Ewen Corre Date: Fri, 10 Jan 2025 13:57:04 +0100 Subject: [PATCH] job_seekers_views: generalize the `Start` view to get/create job seeker The `Start` view is now plugged to both `UpdateJobSeeker*` views and `CheckNIR*` views (which are the first step in the get orrr create job seeker process). All `job_seeker_session`s are now initialized with this `Start` view. --- .../apply/submit/application/base.html | 3 +- .../check_job_seeker_info_for_hire.html | 2 +- itou/www/apply/views/submit_views.py | 37 +- itou/www/job_seekers_views/urls.py | 10 +- itou/www/job_seekers_views/views.py | 94 ++-- tests/gps/test_create_beneficiary.py | 48 +- .../www/apply/__snapshots__/test_submit.ambr | 40 +- tests/www/apply/test_submit.py | 176 +++++-- .../test_create_or_update.py | 455 +++++++++++++----- 9 files changed, 635 insertions(+), 230 deletions(-) diff --git a/itou/templates/apply/submit/application/base.html b/itou/templates/apply/submit/application/base.html index 3812b69394..059cf10d5c 100644 --- a/itou/templates/apply/submit/application/base.html +++ b/itou/templates/apply/submit/application/base.html @@ -37,7 +37,8 @@

{% include 'apply/includes/_submit_title.ht

Dernière actualisation du profil : {{ job_seeker.last_checked_at|date }} à {{ job_seeker.last_checked_at|time }} {% if can_view_personal_information and not request.user.is_job_seeker %} - Vérifier le profil + Vérifier le profil {% endif %} {% if new_check_needed %}{% endif %}

diff --git a/itou/templates/job_seekers_views/check_job_seeker_info_for_hire.html b/itou/templates/job_seekers_views/check_job_seeker_info_for_hire.html index fb6f712a97..5206bc8014 100644 --- a/itou/templates/job_seekers_views/check_job_seeker_info_for_hire.html +++ b/itou/templates/job_seekers_views/check_job_seeker_info_for_hire.html @@ -15,7 +15,7 @@

Informations personnelles de {{ job_seeker.

Informations personnelles Mettre à jour + href="{% url "job_seekers_views:start" %}{% querystring session_kind="job-seeker-update" job_seeker=job_seeker.public_id company=siae.pk from_url=request.get_full_path|urlencode %}">Mettre à jour

{% include "apply/includes/profile_infos.html" %} diff --git a/itou/www/apply/views/submit_views.py b/itou/www/apply/views/submit_views.py index 16b5b2d53a..3ed39dafec 100644 --- a/itou/www/apply/views/submit_views.py +++ b/itou/www/apply/views/submit_views.py @@ -140,18 +140,6 @@ def get_reset_url(self): return reverse("companies_views:card", kwargs={"siae_id": self.company.pk}) return reverse("companies_views:job_description_card", kwargs={"job_description_id": job_description}) - def init_job_seeker_session(self, request): - job_seeker_session = SessionNamespace.create_uuid_namespace( - request.session, - data={ - "config": { - "reset_url": self.get_reset_url(), - }, - "apply": {"company_pk": self.company.pk}, - }, - ) - return job_seeker_session - def get_context_data(self, **kwargs): return super().get_context_data(**kwargs) | { "siae": self.company, @@ -296,13 +284,15 @@ def get(self, request, *args, **kwargs): reverse("apply:pending_authorization_for_sender", kwargs={"company_pk": self.company.pk}) ) - # Init a job_seeker_session needed for job_seekers_views - job_seeker_session = self.init_job_seeker_session(request) + params = { + "session_kind": f"job-seeker-get-or-create-{tunnel}", + "company": self.company.pk, + "from_url": self.get_reset_url(), + "gps": "true" if self.is_gps else None, + } - return HttpResponseRedirect( - reverse(f"job_seekers_views:check_nir_for_{tunnel}", kwargs={"session_uuid": job_seeker_session.name}) - + ("?gps=true" if self.is_gps else "") - ) + next_url = add_url_params(reverse("job_seekers_views:start"), params) + return HttpResponseRedirect(next_url) class PendingAuthorizationForSender(ApplyStepForSenderBaseView): @@ -310,10 +300,13 @@ class PendingAuthorizationForSender(ApplyStepForSenderBaseView): def setup(self, request, *args, **kwargs): super().setup(request, *args, **kwargs) - self.job_seeker_session = self.init_job_seeker_session(request) - self.next_url = reverse( - "job_seekers_views:check_nir_for_sender", kwargs={"session_uuid": self.job_seeker_session.name} - ) + params = { + "session_kind": "job-seeker-get-or-create-sender", + "company": self.company.pk, + "from_url": self.get_reset_url(), + } + + self.next_url = add_url_params(reverse("job_seekers_views:start"), params) def get_context_data(self, **kwargs): return super().get_context_data(**kwargs) | {"next_url": self.next_url} diff --git a/itou/www/job_seekers_views/urls.py b/itou/www/job_seekers_views/urls.py index 30d6f506bb..2ea0c94911 100644 --- a/itou/www/job_seekers_views/urls.py +++ b/itou/www/job_seekers_views/urls.py @@ -8,6 +8,11 @@ urlpatterns = [ path("details/", views.JobSeekerDetailView.as_view(), name="details"), path("list", views.JobSeekerListView.as_view(), name="list"), + path( + "start", + views.JobSeekerStartView.as_view(), + name="start", + ), # For sender path("/sender/check-nir", views.CheckNIRForSenderView.as_view(), name="check_nir_for_sender"), path( @@ -110,11 +115,6 @@ name="check_nir_for_job_seeker", ), # Job seeker check/updates - path( - "update/start", - views.UpdateJobSeekerStartView.as_view(), - name="update_job_seeker_start", - ), path( "update//1", views.UpdateJobSeekerStep1View.as_view(), diff --git a/itou/www/job_seekers_views/views.py b/itou/www/job_seekers_views/views.py index 3a8102132e..f931c902d7 100644 --- a/itou/www/job_seekers_views/views.py +++ b/itou/www/job_seekers_views/views.py @@ -185,7 +185,7 @@ def get_queryset(self): class JobSeekerBaseView(TemplateView): - EXPECTED_SESSION_KIND = None + EXPECTED_SESSION_KINDS = None def __init__(self): super().__init__() @@ -203,7 +203,7 @@ def setup(self, request, *args, session_uuid, hire_process=False, **kwargs): # Ensure we are performing the action (update, create…) the session was created for. if ( session_kind := self.job_seeker_session.get("config").get("session_kind") - ) and session_kind != self.EXPECTED_SESSION_KIND: + ) and session_kind not in self.EXPECTED_SESSION_KINDS: raise Http404 self.is_gps = "gps" in request.GET and request.GET["gps"] == "true" if company_pk := self.job_seeker_session.get("apply", {}).get("company_pk"): @@ -244,7 +244,7 @@ def get_back_url(self): return None def get_reset_url(self): - return self.job_seeker_session.get("config", {}).get("reset_url") or reverse("dashboard:index") + return self.job_seeker_session.get("config", {}).get("from_url") or reverse("dashboard:index") def get_context_data(self, **kwargs): return super().get_context_data(**kwargs) | { @@ -276,7 +276,7 @@ def dispatch(self, request, *args, **kwargs): class CheckNIRForJobSeekerView(JobSeekerBaseView): template_name = "job_seekers_views/step_check_job_seeker_nir.html" - EXPECTED_SESSION_KIND = "job-seeker-get-or-create-job-seeker" + EXPECTED_SESSION_KINDS = ["job-seeker-get-or-create-job_seeker"] def __init__(self): super().__init__() @@ -336,7 +336,7 @@ def get_context_data(self, **kwargs): class CheckNIRForSenderView(JobSeekerForSenderBaseView): template_name = "job_seekers_views/step_check_job_seeker_nir.html" - EXPECTED_SESSION_KIND = "job-seeker-get-or-create-sender" + EXPECTED_SESSION_KINDS = ["job-seeker-get-or-create-sender", "job-seeker-get-or-create-hire"] def __init__(self): super().__init__() @@ -398,6 +398,7 @@ def get_context_data(self, **kwargs): class SearchByEmailForSenderView(JobSeekerForSenderBaseView): template_name = "job_seekers_views/step_search_job_seeker_by_email.html" + EXPECTED_SESSION_KINDS = ["job-seeker-get-or-create-sender", "job-seeker-get-or-create-hire"] def __init__(self): super().__init__() @@ -496,6 +497,7 @@ def get_context_data(self, **kwargs): class CreateJobSeekerForSenderBaseView(JobSeekerForSenderBaseView): required_session_namespaces = ["job_seeker_session"] + EXPECTED_SESSION_KINDS = ["job-seeker-get-or-create-sender", "job-seeker-get-or-create-hire"] def __init__(self): super().__init__() @@ -764,46 +766,80 @@ def get_context_data(self, **kwargs): return super().get_context_data(**kwargs) | {"profile": self.profile, "progress": "80"} -class UpdateJobSeekerStartView(View): +class JobSeekerStartView(View): def setup(self, request, *args, **kwargs): super().setup(request, *args, **kwargs) - try: - job_seeker = get_object_or_404( - User.objects.filter(kind=UserKind.JOB_SEEKER), public_id=request.GET.get("job_seeker") - ) - except ValidationError: - raise Http404("Aucun candidat n'a été trouvé") + self.session_kind = request.GET.get("session_kind") + self.is_gps = "gps" in request.GET and request.GET["gps"] == "true" + from_url = get_safe_url(request, "from_url") - try: - company = get_object_or_404(Company.objects.with_has_active_members(), pk=request.GET.get("company")) - except ValueError: - raise Http404("Aucune entreprise n'a été trouvée") + job_seeker = None + if job_seeker_public_id := request.GET.get("job_seeker"): + try: + job_seeker = get_object_or_404( + User.objects.filter(kind=UserKind.JOB_SEEKER), public_id=job_seeker_public_id + ) + except ValidationError: + raise Http404("Aucun candidat n'a été trouvé") - from_url = get_safe_url(request, "from_url", fallback_url=reverse("dashboard:index")) + company = None + if company_pk := request.GET.get("company"): + try: + company = ( + get_object_or_404(Company.objects.with_has_active_members(), pk=company_pk) + if not self.is_gps + else Company.unfiltered_objects.get(siret=companies_enums.POLE_EMPLOI_SIRET) + ) + except ValueError: + raise Http404("Aucune entreprise n'a été trouvée") - if request.user.is_job_seeker or not request.user.can_view_personal_information(job_seeker): + if (request.user.is_job_seeker and self.session_kind != "job-seeker-get-or-create-job_seeker") or ( + job_seeker and not request.user.can_view_personal_information(job_seeker) + ): raise PermissionDenied("Votre utilisateur n'est pas autorisé à vérifier les informations de ce candidat") - self.job_seeker_session = SessionNamespace.create_uuid_namespace( - request.session, - data={ - "config": {"from_url": from_url, "session_kind": "job-seeker-update"}, - "job_seeker_pk": job_seeker.pk, - "apply": {"company_pk": company.pk}, + # Data validation per session_kind + if ( + not self.session_kind + or not from_url + or (self.session_kind == "job-seeker-update" and not job_seeker) + or (self.session_kind.startswith("job-seeker-get-or-create") and not company) + ): + raise Http404 + + apply_data = {"company_pk": company.pk} if company_pk else {} + + data = { + "config": { + "from_url": from_url, + "session_kind": self.session_kind, }, - ) + "apply": apply_data, + } | ({"job_seeker_pk": job_seeker.pk} if job_seeker else {}) + + self.job_seeker_session = SessionNamespace.create_uuid_namespace(request.session, data) def get(self, request, *args, **kwargs): + if self.session_kind == "job-seeker-get-or-create-job_seeker": + view_name = "job_seekers_views:check_nir_for_job_seeker" + elif self.session_kind == "job-seeker-get-or-create-sender": + view_name = "job_seekers_views:check_nir_for_sender" + elif self.session_kind == "job-seeker-get-or-create-hire": + view_name = "job_seekers_views:check_nir_for_hire" + elif self.session_kind == "job-seeker-update": + view_name = "job_seekers_views:update_job_seeker_step_1" + else: + raise Http404 + return HttpResponseRedirect( - reverse( - "job_seekers_views:update_job_seeker_step_1", kwargs={"session_uuid": self.job_seeker_session.name} - ) + reverse(view_name, kwargs={"session_uuid": self.job_seeker_session.name}) + + ("?gps=true" if self.is_gps else "") ) class UpdateJobSeekerBaseView(JobSeekerBaseView): - EXPECTED_SESSION_KIND = "job-seeker-update" + EXPECTED_SESSION_KINDS = ["job-seeker-update"] def __init__(self): super().__init__() diff --git a/tests/gps/test_create_beneficiary.py b/tests/gps/test_create_beneficiary.py index 4855098eb8..85969bb2c3 100644 --- a/tests/gps/test_create_beneficiary.py +++ b/tests/gps/test_create_beneficiary.py @@ -16,6 +16,7 @@ from itou.users.models import User from itou.utils.mocks.address_format import mock_get_geocoding_data_by_ban_api_resolved from itou.utils.models import InclusiveDateRange +from itou.utils.urls import add_url_params from tests.cities.factories import create_city_geispolsheim, create_test_cities from tests.companies.factories import CompanyWithMembershipAndJobsFactory from tests.prescribers.factories import PrescriberOrganizationWithMembershipFactory @@ -53,6 +54,16 @@ def test_create_job_seeker(_mock, client): apply_start_url = reverse("apply:start", kwargs={"company_pk": singleton.pk}) + "?gps=true" response = client.get(apply_start_url) + params = { + "session_kind": "job-seeker-get-or-create-sender", + "company": singleton.pk, + "from_url": reverse("companies_views:card", kwargs={"siae_id": singleton.pk}), + "gps": "true", + } + next_url = add_url_params(reverse("job_seekers_views:start"), params) + assert response.url == next_url + + response = client.get(next_url) [job_seeker_session_name] = [k for k in client.session.keys() if k not in KNOWN_SESSION_KEYS] next_url = ( reverse("job_seekers_views:check_nir_for_sender", kwargs={"session_uuid": job_seeker_session_name}) @@ -79,7 +90,8 @@ def test_create_job_seeker(_mock, client): expected_job_seeker_session = { "config": { - "reset_url": reverse("companies_views:card", kwargs={"siae_id": singleton.pk}), + "from_url": reverse("companies_views:card", kwargs={"siae_id": singleton.pk}), + "session_kind": "job-seeker-get-or-create-sender", }, "apply": {"company_pk": singleton.pk}, "profile": { @@ -238,6 +250,16 @@ def test_gps_bypass(client): apply_start_url = reverse("apply:start", kwargs={"company_pk": singleton.pk}) + "?gps=true" response = client.get(apply_start_url) + params = { + "session_kind": "job-seeker-get-or-create-sender", + "company": singleton.pk, + "from_url": reverse("companies_views:card", kwargs={"siae_id": singleton.pk}), + "gps": "true", + } + next_url = add_url_params(reverse("job_seekers_views:start"), params) + assert response.url == next_url + + response = client.get(next_url) [job_seeker_session_name] = [k for k in client.session.keys() if k not in KNOWN_SESSION_KEYS] next_url = ( reverse("job_seekers_views:check_nir_for_sender", kwargs={"session_uuid": job_seeker_session_name}) @@ -258,6 +280,17 @@ def test_gps_bypass(client): apply_start_url = reverse("apply:start", kwargs={"company_pk": singleton.pk}) + "?gps=true" response = client.get(apply_start_url) + params = { + "session_kind": "job-seeker-get-or-create-sender", + "company": singleton.pk, + "from_url": reverse("companies_views:card", kwargs={"siae_id": singleton.pk}), + "gps": "true", + } + next_url = add_url_params(reverse("job_seekers_views:start"), params) + assert response.url == next_url + + response = client.get(next_url) + [job_seeker_session_name] = [k for k in client.session.keys() if k not in KNOWN_SESSION_KEYS] next_url = ( reverse("job_seekers_views:check_nir_for_sender", kwargs={"session_uuid": job_seeker_session_name}) @@ -308,7 +341,8 @@ def test_existing_user_with_email(client): ) expected_job_seeker_session = { "config": { - "reset_url": reverse("companies_views:card", kwargs={"siae_id": singleton.pk}), + "from_url": reverse("companies_views:card", kwargs={"siae_id": singleton.pk}), + "session_kind": "job-seeker-get-or-create-sender", }, "apply": {"company_pk": singleton.pk}, "profile": { @@ -411,6 +445,16 @@ def test_creation_by_user_kind(client, UserFactory, factory_args, expected_acces assert response.status_code == 403 response = client.get(create_beneficiary_url) + params = { + "session_kind": "job-seeker-get-or-create-sender", + "company": singleton.pk, + "from_url": reverse("companies_views:card", kwargs={"siae_id": singleton.pk}), + "gps": "true", + } + next_url = add_url_params(reverse("job_seekers_views:start"), params) + assert response.url == next_url + + response = client.get(next_url) [job_seeker_session_name] = [k for k in client.session.keys() if k not in KNOWN_SESSION_KEYS] assert response.status_code == 302 assert ( diff --git a/tests/www/apply/__snapshots__/test_submit.ambr b/tests/www/apply/__snapshots__/test_submit.ambr index a93341f06b..de171ae102 100644 --- a/tests/www/apply/__snapshots__/test_submit.ambr +++ b/tests/www/apply/__snapshots__/test_submit.ambr @@ -1059,7 +1059,7 @@ }), dict({ 'origin': list([ - 'UpdateJobSeekerStartView.setup[www/job_seekers_views/views.py]', + 'JobSeekerStartView.setup[www/job_seekers_views/views.py]', ]), 'sql': ''' SELECT "users_user"."id", @@ -1102,7 +1102,7 @@ }), dict({ 'origin': list([ - 'UpdateJobSeekerStartView.setup[www/job_seekers_views/views.py]', + 'JobSeekerStartView.setup[www/job_seekers_views/views.py]', ]), 'sql': ''' SELECT "companies_company"."id", @@ -1157,7 +1157,7 @@ 'User.is_prescriber_with_authorized_org[users/models.py]', 'User.can_edit_personal_information[users/models.py]', 'User.can_view_personal_information[users/models.py]', - 'UpdateJobSeekerStartView.setup[www/job_seekers_views/views.py]', + 'JobSeekerStartView.setup[www/job_seekers_views/views.py]', ]), 'sql': ''' SELECT %s AS "a" @@ -2804,7 +2804,7 @@ }), dict({ 'origin': list([ - 'UpdateJobSeekerStartView.setup[www/job_seekers_views/views.py]', + 'JobSeekerStartView.setup[www/job_seekers_views/views.py]', ]), 'sql': ''' SELECT "users_user"."id", @@ -2847,7 +2847,7 @@ }), dict({ 'origin': list([ - 'UpdateJobSeekerStartView.setup[www/job_seekers_views/views.py]', + 'JobSeekerStartView.setup[www/job_seekers_views/views.py]', ]), 'sql': ''' SELECT "companies_company"."id", @@ -4778,7 +4778,7 @@ }), dict({ 'origin': list([ - 'UpdateJobSeekerStartView.setup[www/job_seekers_views/views.py]', + 'JobSeekerStartView.setup[www/job_seekers_views/views.py]', ]), 'sql': ''' SELECT "users_user"."id", @@ -4821,7 +4821,7 @@ }), dict({ 'origin': list([ - 'UpdateJobSeekerStartView.setup[www/job_seekers_views/views.py]', + 'JobSeekerStartView.setup[www/job_seekers_views/views.py]', ]), 'sql': ''' SELECT "companies_company"."id", @@ -4876,7 +4876,7 @@ 'User.is_prescriber_with_authorized_org[users/models.py]', 'User.can_edit_personal_information[users/models.py]', 'User.can_view_personal_information[users/models.py]', - 'UpdateJobSeekerStartView.setup[www/job_seekers_views/views.py]', + 'JobSeekerStartView.setup[www/job_seekers_views/views.py]', ]), 'sql': ''' SELECT %s AS "a" @@ -6523,7 +6523,7 @@ }), dict({ 'origin': list([ - 'UpdateJobSeekerStartView.setup[www/job_seekers_views/views.py]', + 'JobSeekerStartView.setup[www/job_seekers_views/views.py]', ]), 'sql': ''' SELECT "users_user"."id", @@ -6566,7 +6566,7 @@ }), dict({ 'origin': list([ - 'UpdateJobSeekerStartView.setup[www/job_seekers_views/views.py]', + 'JobSeekerStartView.setup[www/job_seekers_views/views.py]', ]), 'sql': ''' SELECT "companies_company"."id", @@ -8497,7 +8497,7 @@ }), dict({ 'origin': list([ - 'UpdateJobSeekerStartView.setup[www/job_seekers_views/views.py]', + 'JobSeekerStartView.setup[www/job_seekers_views/views.py]', ]), 'sql': ''' SELECT "users_user"."id", @@ -8540,7 +8540,7 @@ }), dict({ 'origin': list([ - 'UpdateJobSeekerStartView.setup[www/job_seekers_views/views.py]', + 'JobSeekerStartView.setup[www/job_seekers_views/views.py]', ]), 'sql': ''' SELECT "companies_company"."id", @@ -8595,7 +8595,7 @@ 'User.is_prescriber_with_authorized_org[users/models.py]', 'User.can_edit_personal_information[users/models.py]', 'User.can_view_personal_information[users/models.py]', - 'UpdateJobSeekerStartView.setup[www/job_seekers_views/views.py]', + 'JobSeekerStartView.setup[www/job_seekers_views/views.py]', ]), 'sql': ''' SELECT %s AS "a" @@ -9713,7 +9713,7 @@ }), dict({ 'origin': list([ - 'UpdateJobSeekerStartView.setup[www/job_seekers_views/views.py]', + 'JobSeekerStartView.setup[www/job_seekers_views/views.py]', ]), 'sql': ''' SELECT "users_user"."id", @@ -9756,7 +9756,7 @@ }), dict({ 'origin': list([ - 'UpdateJobSeekerStartView.setup[www/job_seekers_views/views.py]', + 'JobSeekerStartView.setup[www/job_seekers_views/views.py]', ]), 'sql': ''' SELECT "companies_company"."id", @@ -11727,7 +11727,7 @@ }), dict({ 'origin': list([ - 'UpdateJobSeekerStartView.setup[www/job_seekers_views/views.py]', + 'JobSeekerStartView.setup[www/job_seekers_views/views.py]', ]), 'sql': ''' SELECT "users_user"."id", @@ -11770,7 +11770,7 @@ }), dict({ 'origin': list([ - 'UpdateJobSeekerStartView.setup[www/job_seekers_views/views.py]', + 'JobSeekerStartView.setup[www/job_seekers_views/views.py]', ]), 'sql': ''' SELECT "companies_company"."id", @@ -11825,7 +11825,7 @@ 'User.is_prescriber_with_authorized_org[users/models.py]', 'User.can_edit_personal_information[users/models.py]', 'User.can_view_personal_information[users/models.py]', - 'UpdateJobSeekerStartView.setup[www/job_seekers_views/views.py]', + 'JobSeekerStartView.setup[www/job_seekers_views/views.py]', ]), 'sql': ''' SELECT %s AS "a" @@ -12943,7 +12943,7 @@ }), dict({ 'origin': list([ - 'UpdateJobSeekerStartView.setup[www/job_seekers_views/views.py]', + 'JobSeekerStartView.setup[www/job_seekers_views/views.py]', ]), 'sql': ''' SELECT "users_user"."id", @@ -12986,7 +12986,7 @@ }), dict({ 'origin': list([ - 'UpdateJobSeekerStartView.setup[www/job_seekers_views/views.py]', + 'JobSeekerStartView.setup[www/job_seekers_views/views.py]', ]), 'sql': ''' SELECT "companies_company"."id", diff --git a/tests/www/apply/test_submit.py b/tests/www/apply/test_submit.py index aa5c5f946a..d047f42af8 100644 --- a/tests/www/apply/test_submit.py +++ b/tests/www/apply/test_submit.py @@ -262,10 +262,11 @@ def test_404_when_trying_to_update_a_prescriber(self, client): prescriber = PrescriberFactory() client.force_login(company.members.first()) params = { + "session_kind": "job-seeker-update", "job_seeker": prescriber.public_id, "company": company.pk, } - url = add_url_params(reverse("job_seekers_views:update_job_seeker_start"), params) + url = add_url_params(reverse("job_seekers_views:start"), params) response = client.get(url) assert response.status_code == 404 @@ -329,6 +330,15 @@ def test_check_nir_job_seeker_with_lack_of_nir_reason(client): response = client.get(reverse("apply:start", kwargs={"company_pk": company.pk})) assert response.status_code == 302 + params = { + "session_kind": "job-seeker-get-or-create-job_seeker", + "company": company.pk, + "from_url": reverse("companies_views:card", kwargs={"siae_id": company.pk}), + } + next_url = add_url_params(reverse("job_seekers_views:start"), params) + assert response.url == next_url + + response = client.get(next_url) [job_seeker_session_name] = [k for k in client.session.keys() if k not in KNOWN_SESSION_KEYS] next_url = reverse("job_seekers_views:check_nir_for_job_seeker", kwargs={"session_uuid": job_seeker_session_name}) assert response.url == next_url @@ -361,7 +371,7 @@ def test_apply_as_job_seeker_with_suspension_sanction(self, client): user = JobSeekerFactory(jobseeker_profile__birthdate=None, jobseeker_profile__nir="") client.force_login(user) - response = client.get(reverse("apply:start", kwargs={"company_pk": company.pk})) + response = client.get(reverse("apply:start", kwargs={"company_pk": company.pk}), follow=True) [job_seeker_session_name] = [k for k in client.session.keys() if k not in KNOWN_SESSION_KEYS] # The suspension does not prevent access to the process assertRedirects( @@ -386,6 +396,15 @@ def test_apply_as_jobseeker(self, client, pdf_file): response = client.get(reverse("apply:start", kwargs={"company_pk": company.pk})) assert response.status_code == 302 + params = { + "session_kind": "job-seeker-get-or-create-job_seeker", + "company": company.pk, + "from_url": reset_url_company, + } + next_url = add_url_params(reverse("job_seekers_views:start"), params) + assert response.url == next_url + + response = client.get(next_url) [job_seeker_session_name] = [k for k in client.session.keys() if k not in KNOWN_SESSION_KEYS] next_url = reverse( "job_seekers_views:check_nir_for_job_seeker", kwargs={"session_uuid": job_seeker_session_name} @@ -611,6 +630,16 @@ def test_apply_as_job_seeker_from_job_description(self, client): reverse("apply:start", kwargs={"company_pk": company.pk}), {"job_description_id": job_description.pk}, ) + + params = { + "session_kind": "job-seeker-get-or-create-job_seeker", + "company": company.pk, + "from_url": reset_url_job_description, + } + next_url = add_url_params(reverse("job_seekers_views:start"), params) + assert response.url == next_url + response = client.get(next_url) + [job_seeker_session_name] = [ k for k in client.session.keys() if k not in KNOWN_SESSION_KEYS and not k.startswith("job_application") ] @@ -856,17 +885,31 @@ def test_apply_as_prescriber_with_pending_authorization(self, client, pdf_file): # ---------------------------------------------------------------------- response = client.get(next_url) - [job_seeker_session_name] = [k for k in client.session.keys() if k not in KNOWN_SESSION_KEYS] - next_url = reverse("job_seekers_views:check_nir_for_sender", kwargs={"session_uuid": job_seeker_session_name}) + params = { + "session_kind": "job-seeker-get-or-create-sender", + "company": company.pk, + "from_url": reverse("companies_views:card", kwargs={"siae_id": company.pk}), + } + next_url = add_url_params(reverse("job_seekers_views:start"), params) assertContains(response, "Statut de prescripteur habilité non vérifié") - assertContains(response, next_url) + assertContains( + response, + f""" + + Suivant + + """, + html=True, + ) # Step determine the job seeker with a NIR. # ---------------------------------------------------------------------- response = client.get(next_url) - assert response.status_code == 200 + [job_seeker_session_name] = [k for k in client.session.keys() if k not in KNOWN_SESSION_KEYS] + next_url = reverse("job_seekers_views:check_nir_for_sender", kwargs={"session_uuid": job_seeker_session_name}) + assertRedirects(response, next_url) response = client.post(next_url, data={"nir": dummy_job_seeker.jobseeker_profile.nir, "confirm": 1}) assert response.status_code == 302 @@ -876,10 +919,10 @@ def test_apply_as_prescriber_with_pending_authorization(self, client, pdf_file): kwargs={"session_uuid": job_seeker_session_name}, ) expected_job_seeker_session = { - "config": { - "reset_url": reverse("companies_views:card", kwargs={"siae_id": company.pk}), + "config": {"from_url": params["from_url"], "session_kind": params["session_kind"]}, + "apply": { + "company_pk": company.pk, }, - "apply": {"company_pk": company.pk}, "profile": { "nir": dummy_job_seeker.jobseeker_profile.nir, }, @@ -1128,6 +1171,15 @@ def test_apply_as_authorized_prescriber(self, client, pdf_file): response = client.get(reverse("apply:start", kwargs={"company_pk": company.pk})) assert response.status_code == 302 + params = { + "session_kind": "job-seeker-get-or-create-sender", + "company": company.pk, + "from_url": reset_url_company, + } + next_url = add_url_params(reverse("job_seekers_views:start"), params) + assert response.url == next_url + + response = client.get(next_url) [job_seeker_session_name] = [k for k in client.session.keys() if k not in KNOWN_SESSION_KEYS] next_url = reverse("job_seekers_views:check_nir_for_sender", kwargs={"session_uuid": job_seeker_session_name}) assert response.url == next_url @@ -1160,9 +1212,12 @@ def test_apply_as_authorized_prescriber(self, client, pdf_file): expected_job_seeker_session = { "config": { - "reset_url": reset_url_company, + "from_url": reset_url_company, + "session_kind": params["session_kind"], + }, + "apply": { + "company_pk": company.pk, }, - "apply": {"company_pk": company.pk}, "user": { "email": dummy_job_seeker.email, }, @@ -1399,7 +1454,7 @@ def test_cannot_create_job_seeker_with_pole_emploi_email(self, client): # Init session start_url = reverse("apply:start", kwargs={"company_pk": company.pk}) - client.get(start_url) + client.get(start_url, follow=True) [job_seeker_session_name] = [k for k in client.session.keys() if k not in KNOWN_SESSION_KEYS] nir_url = reverse("job_seekers_views:check_nir_for_sender", kwargs={"session_uuid": job_seeker_session_name}) response = client.get(nir_url) @@ -1457,8 +1512,15 @@ def test_apply_with_temporary_nir(self, client): client.force_login(user) response = client.get(reverse("apply:start", kwargs={"company_pk": company.pk})) - assert response.status_code == 302 + params = { + "session_kind": "job-seeker-get-or-create-sender", + "company": company.pk, + "from_url": reverse("companies_views:card", kwargs={"siae_id": company.pk}), + } + next_url = add_url_params(reverse("job_seekers_views:start"), params) + assert response.url == next_url + response = client.get(next_url) [job_seeker_session_name] = [k for k in client.session.keys() if k not in KNOWN_SESSION_KEYS] assertRedirects( response, @@ -1509,7 +1571,7 @@ def test_apply_as_prescriber_with_suspension_sanction(self, client): user = PrescriberFactory() client.force_login(user) - response = client.get(reverse("apply:start", kwargs={"company_pk": company.pk})) + response = client.get(reverse("apply:start", kwargs={"company_pk": company.pk}), follow=True) [job_seeker_session_name] = [k for k in client.session.keys() if k not in KNOWN_SESSION_KEYS] # The suspension does not prevent the access to the process @@ -1542,7 +1604,15 @@ def test_apply_as_prescriber(self, client, pdf_file): response = client.get(reverse("apply:start", kwargs={"company_pk": company.pk})) assert response.status_code == 302 + params = { + "session_kind": "job-seeker-get-or-create-sender", + "company": company.pk, + "from_url": reset_url_company, + } + next_url = add_url_params(reverse("job_seekers_views:start"), params) + assert response.url == next_url + response = client.get(next_url) [job_seeker_session_name] = [k for k in client.session.keys() if k not in KNOWN_SESSION_KEYS] next_url = reverse("job_seekers_views:check_nir_for_sender", kwargs={"session_uuid": job_seeker_session_name}) assert response.url == next_url @@ -1565,7 +1635,8 @@ def test_apply_as_prescriber(self, client, pdf_file): expected_job_seeker_session = { "config": { - "reset_url": reset_url_company, + "from_url": reset_url_company, + "session_kind": params["session_kind"], }, "apply": {"company_pk": company.pk}, "profile": {"nir": dummy_job_seeker.jobseeker_profile.nir}, @@ -1960,7 +2031,8 @@ def test_one_account_no_nir(self, client): ) expected_job_seeker_session = { "config": { - "reset_url": reverse("companies_views:card", kwargs={"siae_id": company.pk}), + "from_url": reverse("companies_views:card", kwargs={"siae_id": company.pk}), + "session_kind": "job-seeker-get-or-create-sender", }, "apply": {"company_pk": company.pk}, "profile": { @@ -2045,7 +2117,8 @@ def test_one_account_lack_of_nir_reason(self, client): ) expected_job_seeker_session = { "config": { - "reset_url": reverse("companies_views:card", kwargs={"siae_id": siae.pk}), + "from_url": reverse("companies_views:card", kwargs={"siae_id": siae.pk}), + "session_kind": "job-seeker-get-or-create-sender", }, "apply": {"company_pk": siae.pk}, "profile": { @@ -2098,7 +2171,7 @@ def test_perms_for_company(self, client): user = company_1.members.first() client.force_login(user) - response = client.get(reverse("apply:start", kwargs={"company_pk": company_2.pk})) + response = client.get(reverse("apply:start", kwargs={"company_pk": company_2.pk}), follow=True) [job_seeker_session_name] = [k for k in client.session.keys() if k not in KNOWN_SESSION_KEYS] assertRedirects( response, @@ -2139,6 +2212,15 @@ def _test_apply_as_company(self, client, user, company, dummy_job_seeker, pdf_fi response = client.get(reverse("apply:start", kwargs={"company_pk": company.pk})) assert response.status_code == 302 + params = { + "session_kind": "job-seeker-get-or-create-sender", + "company": company.pk, + "from_url": reset_url, + } + next_url = add_url_params(reverse("job_seekers_views:start"), params) + assert response.url == next_url + + response = client.get(next_url) [job_seeker_session_name] = [k for k in client.session.keys() if k not in KNOWN_SESSION_KEYS] next_url = reverse("job_seekers_views:check_nir_for_sender", kwargs={"session_uuid": job_seeker_session_name}) assert response.url == next_url @@ -2158,7 +2240,7 @@ def _test_apply_as_company(self, client, user, company, dummy_job_seeker, pdf_fi kwargs={"session_uuid": job_seeker_session_name}, ) expected_job_seeker_session = { - "config": {"reset_url": reset_url}, + "config": {"from_url": reset_url, "session_kind": params["session_kind"]}, "apply": {"company_pk": company.pk}, "profile": { "nir": dummy_job_seeker.jobseeker_profile.nir, @@ -2499,7 +2581,7 @@ def test_cannot_create_job_seeker_with_pole_emploi_email(self, client): # Init session start_url = reverse("apply:start", kwargs={"company_pk": company.pk}) - client.get(start_url) + client.get(start_url, follow=True) [job_seeker_session_name] = [k for k in client.session.keys() if k not in KNOWN_SESSION_KEYS] nir_url = reverse("job_seekers_views:check_nir_for_sender", kwargs={"session_uuid": job_seeker_session_name}) response = client.get(nir_url) @@ -2598,7 +2680,7 @@ def test_hire_as_company(self, client): # Step determine the job seeker with a NIR. # ---------------------------------------------------------------------- # Init session - response = client.get(reverse("apply:start_hire", kwargs={"company_pk": company.pk})) + response = client.get(reverse("apply:start_hire", kwargs={"company_pk": company.pk}), follow=True) [job_seeker_session_name] = [k for k in client.session.keys() if k not in KNOWN_SESSION_KEYS] check_nir_url = reverse( @@ -2628,8 +2710,10 @@ def test_hire_as_company(self, client): assert response.status_code == 302 expected_job_seeker_session = { - "config": {"reset_url": reset_url_dashboard}, - "apply": {"company_pk": company.pk}, + "config": {"from_url": reset_url_dashboard, "session_kind": "job-seeker-get-or-create-hire"}, + "apply": { + "company_pk": company.pk, + }, "profile": { "nir": dummy_job_seeker.jobseeker_profile.nir, }, @@ -2908,7 +2992,7 @@ def test_hire_as_geiq(self, client): # Step determine the job seeker with a NIR. # ---------------------------------------------------------------------- # Init session - response = client.get(reverse("apply:start_hire", kwargs={"company_pk": company.pk})) + response = client.get(reverse("apply:start_hire", kwargs={"company_pk": company.pk}), follow=True) [job_seeker_session_name] = [k for k in client.session.keys() if k not in KNOWN_SESSION_KEYS] check_nir_url = reverse( @@ -3137,7 +3221,7 @@ def test_application_start_with_invalid_job_description_id(self, client): company = CompanyFactory(subject_to_eligibility=True, with_membership=True, with_jobs=True) client.force_login(company.members.get()) response = client.get( - reverse("apply:start", kwargs={"company_pk": company.pk}), {"job_description_id": "invalid"} + reverse("apply:start", kwargs={"company_pk": company.pk}), {"job_description_id": "invalid"}, follow=True ) [job_seeker_session_name] = [k for k in client.session.keys() if k not in KNOWN_SESSION_KEYS] assertRedirects( @@ -3425,11 +3509,12 @@ def _check_last_checked_at(self, client, user, sees_warning, sees_verify_link): assert response.status_code == 200 params = { + "session_kind": "job-seeker-update", "job_seeker": self.job_seeker.public_id, "company": self.company.pk, "from_url": url, } - update_url = add_url_params(reverse("job_seekers_views:update_job_seeker_start"), params) + update_url = add_url_params(reverse("job_seekers_views:start"), params) link_check = assertContains if sees_verify_link else assertNotContains link_check(response, f'Vérifier le profil', html=True) # Check last_checked_at is shown @@ -3512,11 +3597,12 @@ def setup_method(self, settings, mocker): ) params = { + "session_kind": "job-seeker-update", "job_seeker": self.job_seeker.public_id, "company": self.company.pk, "from_url": from_url, } - self.start_url = add_url_params(reverse("job_seekers_views:update_job_seeker_start"), params) + self.start_url = add_url_params(reverse("job_seekers_views:start"), params) def get_job_seeker_session_key(self, client): [job_seeker_session_key] = [ @@ -4614,10 +4700,12 @@ def test_job_seeker_with_profile_has_check_boxes_ticked_in_step3(self, client): # START to setup jobseeker session params = { + "session_kind": "job-seeker-update", "job_seeker": job_seeker.public_id, "company": company.pk, + "from_url": reverse("dashboard:index"), } - url = add_url_params(reverse("job_seekers_views:update_job_seeker_start"), params) + url = add_url_params(reverse("job_seekers_views:start"), params) response = client.get(url) assert response.status_code == 302 @@ -4683,13 +4771,23 @@ def test_detect_existing_job_seeker(client): response = client.get(reverse("apply:start", kwargs={"company_pk": company.pk})) assert response.status_code == 302 - [job_seeker_session_name] = [k for k in client.session.keys() if k not in KNOWN_SESSION_KEYS] - next_url = reverse("job_seekers_views:check_nir_for_sender", kwargs={"session_uuid": job_seeker_session_name}) + params = { + "session_kind": "job-seeker-get-or-create-sender", + "company": company.pk, + "from_url": reverse("companies_views:card", kwargs={"siae_id": company.pk}), + } + next_url = add_url_params(reverse("job_seekers_views:start"), params) assert response.url == next_url # Step determine the job seeker with a NIR. # ---------------------------------------------------------------------- + response = client.get(next_url) + assert response.status_code == 302 + + [job_seeker_session_name] = [k for k in client.session.keys() if k not in KNOWN_SESSION_KEYS] + next_url = reverse("job_seekers_views:check_nir_for_sender", kwargs={"session_uuid": job_seeker_session_name}) + response = client.get(next_url) assert response.status_code == 200 @@ -4702,7 +4800,8 @@ def test_detect_existing_job_seeker(client): ) expected_job_seeker_session = { "config": { - "reset_url": reverse("companies_views:card", kwargs={"siae_id": company.pk}), + "session_kind": "job-seeker-get-or-create-sender", + "from_url": reverse("companies_views:card", kwargs={"siae_id": company.pk}), }, "apply": {"company_pk": company.pk}, "profile": { @@ -5273,7 +5372,7 @@ def setup_method(self): def get_check_nir_url(self, client): # Init session start_url = reverse("apply:start_hire", kwargs={"company_pk": self.company.pk}) - client.get(start_url) + client.get(start_url, follow=True) [job_seeker_session_name] = [k for k in client.session.keys() if k not in KNOWN_SESSION_KEYS] return reverse("job_seekers_views:check_nir_for_hire", kwargs={"session_uuid": job_seeker_session_name}) @@ -5392,7 +5491,8 @@ def test_no_job_seeker_redirect_to_create(self, client): expected_job_seeker_session = { "config": { - "reset_url": reverse("dashboard:index"), # Hire: reset_url = dashboard + "from_url": reverse("dashboard:index"), # Hire: reset_url = dashboard + "session_kind": "job-seeker-get-or-create-hire", }, "apply": {"company_pk": self.company.pk}, "user": { @@ -5428,13 +5528,14 @@ def test_company(self, client): assertTemplateNotUsed(response, "approvals/includes/box.html") assertContains(response, "Éligibilité IAE à valider") params = { + "session_kind": "job-seeker-update", "job_seeker": job_seeker.public_id, "company": company.pk, "from_url": url_check_infos, } url_update = f""" Mettre à jour + href="{add_url_params(reverse("job_seekers_views:start"), params)}">Mettre à jour """ assertContains(response, url_update, html=True) assertContains( @@ -5472,13 +5573,14 @@ def test_geiq(self, client): ) assertTemplateNotUsed(response, "approvals/includes/box.html") params = { + "session_kind": "job-seeker-update", "job_seeker": job_seeker.public_id, "company": company.pk, "from_url": url_check_infos, } url_update = f""" Mettre à jour + href="{add_url_params(reverse("job_seekers_views:start"), params)}">Mettre à jour """ assertContains(response, url_update, html=True) assertContains( @@ -5824,7 +5926,7 @@ def test_as_employer(self, client): client.force_login(self.company.members.first()) # Init session - response = client.get(reverse("apply:start_hire", kwargs={"company_pk": self.company.pk})) + response = client.get(reverse("apply:start_hire", kwargs={"company_pk": self.company.pk}), follow=True) [job_seeker_session_name] = [k for k in client.session.keys() if k not in KNOWN_SESSION_KEYS] response = client.get( reverse("job_seekers_views:check_nir_for_sender", kwargs={"session_uuid": job_seeker_session_name}) @@ -5840,7 +5942,7 @@ def test_as_employer(self, client): client.force_login(self.geiq.members.first()) # Init session - response = client.get(reverse("apply:start_hire", kwargs={"company_pk": self.geiq.pk})) + response = client.get(reverse("apply:start_hire", kwargs={"company_pk": self.geiq.pk}), follow=True) [job_seeker_session_name_geiq] = [k for k in client.session.keys() if k not in KNOWN_SESSION_KEYS] response = client.get( reverse("job_seekers_views:check_nir_for_sender", kwargs={"session_uuid": job_seeker_session_name_geiq}) diff --git a/tests/www/job_seekers_views/test_create_or_update.py b/tests/www/job_seekers_views/test_create_or_update.py index 65ba8be4bb..24c46472e1 100644 --- a/tests/www/job_seekers_views/test_create_or_update.py +++ b/tests/www/job_seekers_views/test_create_or_update.py @@ -16,6 +16,108 @@ class TestCreateForJobSeeker: + @pytest.mark.parametrize( + "job_seeker_value, company_value, session_kind_value, from_url_value, expected_status_code", + [ + # Valid parameters + pytest.param(None, "valid", "valid", "valid", 302, id="valid_values"), + pytest.param("valid", "valid", "valid", "valid", 302, id="valid_values_with_jobseeker_id"), + # Invalid parameters + pytest.param("someone_else", "valid", "valid", "valid", 403, id="invalid_other_job_seeker"), + pytest.param("invalid_uuid", "valid", "valid", "valid", 404, id="invalid_job_seeker_not_a_uuid"), + pytest.param("invalid", "valid", "valid", "valid", 404, id="invalid_job_seeker_not_found"), + pytest.param(None, "valid", "invalid", "valid", 403, id="invalid_session_kind"), + pytest.param(None, "valid", "forbidden_sender", "valid", 403, id="forbidden_session_kind_sender"), + pytest.param(None, "valid", "forbidden_hire", "valid", 403, id="forbidden_session_kind_hire"), + pytest.param(None, None, "valid", "valid", 404, id="missing_company"), + pytest.param(None, "valid", None, "valid", 403, id="missing_session_kind"), + pytest.param(None, "valid", "valid", None, 404, id="missing_from_url"), + ], + ) + def test_start_get_or_create_job_seeker( + self, job_seeker_value, company_value, session_kind_value, from_url_value, expected_status_code, client + ): + job_seeker = JobSeekerFactory(jobseeker_profile__birthdate=None, jobseeker_profile__nir="") + other_job_seeker = JobSeekerFactory(jobseeker_profile__birthdate=None, jobseeker_profile__nir="") + company = CompanyFactory(with_membership=True) + client.force_login(job_seeker) + + if job_seeker_value == "valid": + job_seeker_public_id = job_seeker.public_id + elif job_seeker_value == "someone_else": + job_seeker_public_id = other_job_seeker.public_id + elif job_seeker_value == "invalid_uuid": + job_seeker_public_id = "invalid_uuid_value" + elif job_seeker_value == "invalid": + job_seeker_public_id = uuid.uuid4() + else: + job_seeker_public_id = None + + company_pk = company.pk if company_value == "valid" else None + + if session_kind_value == "valid": + session_kind = "job-seeker-get-or-create-job_seeker" + elif session_kind_value == "invalid": + session_kind = "invalid-job-seeker-session" + elif session_kind_value == "forbidden_sender": + session_kind = "job-seeker-get-or-create-sender" + elif session_kind_value == "forbidden_hire": + session_kind = "job-seeker-get-or-create-hire" + else: + session_kind = None + + if from_url_value == "valid": + from_url = reverse( + "apply:application_jobs", + kwargs={"company_pk": company.pk, "job_seeker_public_id": job_seeker.public_id}, + ) + else: + from_url = None + + params = { + "session_kind": session_kind, + "job_seeker": job_seeker_public_id, + "company": company_pk, + "from_url": from_url, + } + start_url = add_url_params(reverse("job_seekers_views:start"), params) + + response = client.get(start_url) + assert response.status_code == expected_status_code + + if expected_status_code == 302: + [job_seeker_session_name] = [k for k in client.session.keys() if k not in KNOWN_SESSION_KEYS] + if session_kind_value == "valid": + tunnel = "job_seeker" + elif session_kind_value == "forbidden_sender": + tunnel = "sender" + elif session_kind_value == "forbidden_hire": + tunnel = "hire" + + next_url = reverse( + f"job_seekers_views:check_nir_for_{tunnel}", + kwargs={"session_uuid": job_seeker_session_name}, + ) + + if not from_url: + from_url = reverse("dashboard:index") + + assertRedirects(response, next_url) + assert client.session[job_seeker_session_name].get("config").get("from_url") == from_url + response = client.get(next_url) + assertContains( + response, + f""" + + + Annuler + + """, + html=True, + ) + def test_check_nir_with_session(self, client): company = CompanyFactory(with_membership=True) user = JobSeekerFactory(jobseeker_profile__birthdate=None, jobseeker_profile__nir="") @@ -24,7 +126,7 @@ def test_check_nir_with_session(self, client): # Init session start_url = reverse("apply:start", kwargs={"company_pk": company.pk}) - client.get(start_url) + client.get(start_url, follow=True) [job_seeker_session_name] = [k for k in client.session.keys() if k not in KNOWN_SESSION_KEYS] response = client.get( @@ -52,7 +154,16 @@ def test_cannot_check_nir_if_already_set(self, client): # Init session start_url = reverse("apply:start", kwargs={"company_pk": company.pk}) - client.get(start_url) + response = client.get(start_url) + params = { + "session_kind": "job-seeker-get-or-create-job_seeker", + "company": company.pk, + "from_url": reverse("companies_views:card", kwargs={"siae_id": company.pk}), + } + next_url = add_url_params(reverse("job_seekers_views:start"), params) + assert response.url == next_url + + response = client.get(next_url) [job_seeker_session_name] = [k for k in client.session.keys() if k not in KNOWN_SESSION_KEYS] response = client.get( @@ -68,13 +179,111 @@ def test_cannot_check_nir_if_already_set(self, client): class TestCreateForSender: + @pytest.mark.parametrize( + "job_seeker_value, company_value, session_kind_value, from_url_value, expected_status_code", + [ + # Valid parameters + pytest.param(None, "valid", "valid", "valid", 302, id="valid_values"), + pytest.param("valid", "valid", "valid", "valid", 302, id="valid_values_existing_job_seeker"), + pytest.param(None, "valid", "valid_hire", "valid", 302, id="valid_values_hire"), + pytest.param("valid", "valid", "valid_hire", "valid", 302, id="valid_values_existing_job_seeker_hire"), + # Invalid parameters + pytest.param("invalid_uuid", "valid", "valid", "valid", 404, id="invalid_job_seeker_not_a_uuid"), + pytest.param("invalid", "valid", "valid", "valid", 404, id="invalid_job_seeker_not_found"), + pytest.param("valid", "valid", "invalid", "valid", 404, id="invalid_session_kind"), + pytest.param("valid", None, "valid", "valid", 404, id="missing_company"), + pytest.param("valid", None, "valid", "valid_hire", 404, id="missing_company_hire"), + pytest.param("valid", "valid", None, "valid", 404, id="missing_session_kind"), + pytest.param("valid", "valid", "valid", None, 404, id="missing_from_url"), + ], + ) + def test_start_get_or_create_sender( + self, + job_seeker_value, + company_value, + session_kind_value, + from_url_value, + expected_status_code, + client, + ): + job_seeker = JobSeekerFactory() + company = CompanyFactory(with_membership=True) + user = company.members.get() + client.force_login(user) + + if job_seeker_value == "valid": + job_seeker_public_id = job_seeker.public_id + elif job_seeker_value == "invalid_uuid": + job_seeker_public_id = "invalid_uuid_value" + elif job_seeker_value == "invalid": + job_seeker_public_id = uuid.uuid4() + else: + job_seeker_public_id = None + + company_pk = company.pk if company_value == "valid" else None + + if session_kind_value == "valid": + session_kind = "job-seeker-get-or-create-sender" + elif session_kind_value == "valid_hire": + session_kind = "job-seeker-get-or-create-hire" + elif session_kind_value == "invalid": + session_kind = "invalid-job-seeker-session" + else: + session_kind = None + + if from_url_value == "valid": + from_url = reverse( + "apply:application_jobs", + kwargs={"company_pk": company.pk, "job_seeker_public_id": job_seeker.public_id}, + ) + else: + from_url = None + + params = { + "session_kind": session_kind, + "job_seeker": job_seeker_public_id, + "company": company_pk, + "from_url": from_url, + } + start_url = add_url_params(reverse("job_seekers_views:start"), params) + + response = client.get(start_url) + assert response.status_code == expected_status_code + + if expected_status_code == 302: + [job_seeker_session_name] = [k for k in client.session.keys() if k not in KNOWN_SESSION_KEYS] + tunnel = "hire" if session_kind_value == "valid_hire" else "sender" + next_url = reverse( + f"job_seekers_views:check_nir_for_{tunnel}", + kwargs={"session_uuid": job_seeker_session_name}, + ) + + if not from_url: + from_url = reverse("dashboard:index") + + assertRedirects(response, next_url) + assert client.session[job_seeker_session_name].get("config").get("from_url") == from_url + response = client.get(next_url) + assertContains( + response, + f""" + + + Annuler + + """, + html=True, + ) + def test_check_nir_with_session(self, client): company = CompanyFactory(with_membership=True) client.force_login(company.members.get()) # Init session start_url = reverse("apply:start", kwargs={"company_pk": company.pk}) - client.get(start_url) + client.get(start_url, follow=True) [job_seeker_session_name] = [k for k in client.session.keys() if k not in KNOWN_SESSION_KEYS] response = client.get( @@ -91,7 +300,7 @@ def test_create_step_1(self, born_in_france, client): client.force_login(company.members.get()) # Init session - client.get(reverse("apply:start", kwargs={"company_pk": company.pk})) + client.get(reverse("apply:start", kwargs={"company_pk": company.pk}), follow=True) [job_seeker_session_name] = [k for k in client.session.keys() if k not in KNOWN_SESSION_KEYS] birthdate = datetime.date(1911, 11, 1) @@ -129,7 +338,7 @@ def test_birth_country_not_france_and_birthplace(self, client): client.force_login(company.members.get()) # Init session - client.get(reverse("apply:start", kwargs={"company_pk": company.pk})) + client.get(reverse("apply:start", kwargs={"company_pk": company.pk}), follow=True) [job_seeker_session_name] = [k for k in client.session.keys() if k not in KNOWN_SESSION_KEYS] birthdate = datetime.date(1911, 11, 1) @@ -163,7 +372,7 @@ def test_birth_country_france_and_no_birthplace(self, client): client.force_login(company.members.get()) # Init session - client.get(reverse("apply:start", kwargs={"company_pk": company.pk})) + client.get(reverse("apply:start", kwargs={"company_pk": company.pk}), follow=True) [job_seeker_session_name] = [k for k in client.session.keys() if k not in KNOWN_SESSION_KEYS] response = client.post( @@ -192,131 +401,139 @@ def test_birth_country_france_and_no_birthplace(self, client): ) -class TestUpdateJobSeeker: - def test_update_with_wrong_tunnel_in_session(self, client): - job_seeker = JobSeekerFactory() +class TestUpdateForJobSeeker: + def test_start_update_job_seeker_forbidden(self, client): + job_seeker = JobSeekerFactory(jobseeker_profile__birthdate=None, jobseeker_profile__nir="") company = CompanyFactory(with_membership=True) - prescriber = PrescriberOrganizationWithMembershipFactory(authorized=True).members.first() - client.force_login(prescriber) - - # Create a session with a wrong tunnel key - job_seeker_session = SessionNamespace.create_uuid_namespace( - client.session, - data={ - "config": {"from_url": reverse("dashboard:index"), "session_kind": "job-seeker-get-or-create-sender"}, - "job_seeker_pk": job_seeker.pk, - "apply": {"company_pk": company.pk}, - }, - ) - job_seeker_session.save() - - url = reverse("job_seekers_views:update_job_seeker_step_1", kwargs={"session_uuid": job_seeker_session.name}) - response = client.get(url) + client.force_login(job_seeker) - assert response.status_code == 404 + company_pk = company.pk - -class TestUpdateJobSeekerStart: - def test_update_start_with_valid_parameters(self, client): - job_seeker = JobSeekerFactory() - company = CompanyFactory(with_membership=True) - user = company.members.get() - client.force_login(user) + session_kind = "job-seeker-update" from_url = reverse( - "apply:application_jobs", kwargs={"company_pk": company.pk, "job_seeker_public_id": job_seeker.public_id} + "apply:application_jobs", + kwargs={"company_pk": company.pk, "job_seeker_public_id": job_seeker.public_id}, ) - params = {"job_seeker": job_seeker.public_id, "company": company.pk, "from_url": from_url} - start_url = add_url_params(reverse("job_seekers_views:update_job_seeker_start"), params) + params = { + "session_kind": session_kind, + "company": company_pk, + "from_url": from_url, + } + start_url = add_url_params(reverse("job_seekers_views:start"), params) response = client.get(start_url) - [job_seeker_session_name] = [k for k in client.session.keys() if k not in KNOWN_SESSION_KEYS] - step_1_url = reverse( - "job_seekers_views:update_job_seeker_step_1", - kwargs={"session_uuid": job_seeker_session_name}, - ) + assert response.status_code == 403 - assertRedirects(response, step_1_url) - assert client.session[job_seeker_session_name].get("config").get("from_url") == from_url - response = client.get(step_1_url) - assertContains( - response, - f""" - - - Annuler - - """, - html=True, - ) - def test_update_start_with_invalid_parameters(self, client): +class TestUpdateForSender: + @pytest.mark.parametrize( + "job_seeker_value, company_value, session_kind_value, from_url_value, expected_status_code", + [ + # Valid parameters + pytest.param("valid", "valid", "valid", "valid", 302, id="valid_values"), + pytest.param("valid", None, "valid", "valid", 302, id="valid_values_no_company"), + # Invalid parameters + pytest.param("invalid_uuid", "valid", "valid", "valid", 404, id="invalid_job_seeker_not_a_uuid"), + pytest.param("invalid", "valid", "valid", "valid", 404, id="invalid_job_seeker_not_found"), + pytest.param(None, "valid", "valid", "valid", 404, id="missing_job_seeker"), + pytest.param("valid", "valid", "invalid", "valid", 404, id="invalid_session_kind"), + pytest.param("valid", "valid", None, "valid", 404, id="missing_session_kind"), + pytest.param("valid", "valid", "valid", None, 404, id="missing_from_url"), + ], + ) + def test_start_update( + self, job_seeker_value, company_value, session_kind_value, from_url_value, expected_status_code, client + ): job_seeker = JobSeekerFactory() company = CompanyFactory(with_membership=True) user = company.members.get() client.force_login(user) - # Invalid uuid - params = {"job_seeker": "invalid_uuid", "company": company.pk} - start_url = add_url_params(reverse("job_seekers_views:update_job_seeker_start"), params) - response = client.get(start_url) - assert response.status_code == 404 + if job_seeker_value == "valid": + job_seeker_public_id = job_seeker.public_id + elif job_seeker_value == "invalid_uuid": + job_seeker_public_id = "invalid_uuid_value" + elif job_seeker_value == "invalid": + job_seeker_public_id = uuid.uuid4() + else: + job_seeker_public_id = None + + company_pk = company.pk if company_value == "valid" else None + + if session_kind_value == "valid": + session_kind = "job-seeker-update" + elif session_kind_value == "invalid": + session_kind = "invalid-job-seeker-session" + else: + session_kind = None + + if from_url_value == "valid": + from_url = reverse( + "apply:application_jobs", + kwargs={"company_pk": company.pk, "job_seeker_public_id": job_seeker.public_id}, + ) + else: + from_url = None - # Valid UUID but no job seeker associated to it params = { - "job_seeker": uuid.uuid4(), - "company": company.pk, + "session_kind": session_kind, + "job_seeker": job_seeker_public_id, + "company": company_pk, + "from_url": from_url, } - start_url = add_url_params(reverse("job_seekers_views:update_job_seeker_start"), params) - response = client.get(start_url) - assert response.status_code == 404 + start_url = add_url_params(reverse("job_seekers_views:start"), params) - # No company parameter - params = { - "job_seeker": job_seeker.public_id, - } - start_url = add_url_params(reverse("job_seekers_views:update_job_seeker_start"), params) response = client.get(start_url) - assert response.status_code == 404 + assert response.status_code == expected_status_code - # Invalid company parameter - params = { - "job_seeker": job_seeker.public_id, - "company": "stringAndNotNumber", - } - start_url = add_url_params(reverse("job_seekers_views:update_job_seeker_start"), params) - response = client.get(start_url) - assert response.status_code == 404 + if expected_status_code == 302: + [job_seeker_session_name] = [k for k in client.session.keys() if k not in KNOWN_SESSION_KEYS] + step_1_url = reverse( + "job_seekers_views:update_job_seeker_step_1", + kwargs={"session_uuid": job_seeker_session_name}, + ) + + if not from_url: + from_url = reverse("dashboard:index") + + assertRedirects(response, step_1_url) + assert client.session[job_seeker_session_name].get("config").get("from_url") == from_url + response = client.get(step_1_url) + assertContains( + response, + f""" + + + Annuler + + """, + html=True, + ) - # No from_url parameter - params = { - "job_seeker": job_seeker.public_id, - "company": company.pk, - } - start_url = add_url_params(reverse("job_seekers_views:update_job_seeker_start"), params) - response = client.get(start_url) + def test_update_with_wrong_tunnel_in_session(self, client): + job_seeker = JobSeekerFactory() + company = CompanyFactory(with_membership=True) + prescriber = PrescriberOrganizationWithMembershipFactory(authorized=True).members.first() + client.force_login(prescriber) - [job_seeker_session_name] = [k for k in client.session.keys() if k not in KNOWN_SESSION_KEYS] - step_1_url = reverse( - "job_seekers_views:update_job_seeker_step_1", - kwargs={"session_uuid": job_seeker_session_name}, - ) - assert client.session[job_seeker_session_name].get("config").get("from_url") == reverse("dashboard:index") - response = client.get(step_1_url) - assertContains( - response, - f""" - - - Annuler - - """, - html=True, + # Create a session with a wrong tunnel key + job_seeker_session = SessionNamespace.create_uuid_namespace( + client.session, + data={ + "config": {"from_url": reverse("dashboard:index"), "session_kind": "job-seeker-get-or-create-sender"}, + "job_seeker_pk": job_seeker.pk, + "apply": {"company_pk": company.pk}, + }, ) + job_seeker_session.save() + + url = reverse("job_seekers_views:update_job_seeker_step_1", kwargs={"session_uuid": job_seeker_session.name}) + response = client.get(url) + + assert response.status_code == 404 class TestUpdateJobSeekerStep1: @@ -331,10 +548,14 @@ def test_create_step_1(self, born_in_france, client): # Init session params = { + "session_kind": "job-seeker-update", "job_seeker": job_seeker.public_id, - "company": company.pk, + "from_url": reverse( + "apply:application_jobs", + kwargs={"company_pk": company.pk, "job_seeker_public_id": job_seeker.public_id}, + ), } - start_url = add_url_params(reverse("job_seekers_views:update_job_seeker_start"), params) + start_url = add_url_params(reverse("job_seekers_views:start"), params) client.get(start_url) [job_seeker_session_name] = [k for k in client.session.keys() if k not in KNOWN_SESSION_KEYS] @@ -375,10 +596,14 @@ def test_birth_country_not_france_and_birthplace(self, client): # Init session params = { + "session_kind": "job-seeker-update", "job_seeker": job_seeker.public_id, - "company": company.pk, + "from_url": reverse( + "apply:application_jobs", + kwargs={"company_pk": company.pk, "job_seeker_public_id": job_seeker.public_id}, + ), } - start_url = add_url_params(reverse("job_seekers_views:update_job_seeker_start"), params) + start_url = add_url_params(reverse("job_seekers_views:start"), params) client.get(start_url) [job_seeker_session_name] = [k for k in client.session.keys() if k not in KNOWN_SESSION_KEYS] @@ -415,10 +640,14 @@ def test_birth_country_france_and_no_birthplace(self, client): # Init session params = { + "session_kind": "job-seeker-update", "job_seeker": job_seeker.public_id, - "company": company.pk, + "from_url": reverse( + "apply:application_jobs", + kwargs={"company_pk": company.pk, "job_seeker_public_id": job_seeker.public_id}, + ), } - start_url = add_url_params(reverse("job_seekers_views:update_job_seeker_start"), params) + start_url = add_url_params(reverse("job_seekers_views:start"), params) client.get(start_url) [job_seeker_session_name] = [k for k in client.session.keys() if k not in KNOWN_SESSION_KEYS]