From 2ae95a1f9c527eac24951d3066ee137dad735c45 Mon Sep 17 00:00:00 2001 From: vasileios Date: Fri, 6 Dec 2024 16:37:11 +0100 Subject: [PATCH] [#3283] Fixed/removed/updated tests --- docs/developers/backend/core/submissions.rst | 7 +- .../_assets/appointment_creation_2_2.png | Bin 17739 -> 0 bytes .../forms/examples/appointment_creation.rst | 83 --- docs/manual/forms/examples/index.rst | 12 - .../contrib/demo/tests/test_endpoints.py | 2 +- .../contrib/jcc/tests/test_api_endpoints.py | 16 +- .../contrib/jcc/tests/test_plugin.py | 23 +- .../qmatic/tests/test_api_endpoints.py | 16 +- .../contrib/qmatic/tests/test_plugin.py | 23 +- .../appointments/tests/test_admin.py | 31 +- .../appointments/tests/test_api_products.py | 5 +- src/openforms/appointments/tests/test_base.py | 17 - .../tests/test_booking_appointment.py | 53 +- .../tests/test_confirmation_emails.py | 5 +- .../tests/test_tasks_appointments.py | 148 ---- .../appointments/tests/test_utils.py | 638 +----------------- .../appointments/tests/test_views.py | 556 +-------------- .../emails/tests/test_confirmation_email.py | 7 - .../formatters/tests/test_kitchensink.py | 21 - .../submissions/tests/test_models.py | 131 ---- .../tests/test_post_submission_event.py | 15 - .../tests/test_tasks_confirmation_emails.py | 41 -- 22 files changed, 72 insertions(+), 1778 deletions(-) delete mode 100644 docs/manual/forms/examples/_assets/appointment_creation_2_2.png delete mode 100644 docs/manual/forms/examples/appointment_creation.rst delete mode 100644 src/openforms/appointments/tests/test_tasks_appointments.py diff --git a/docs/developers/backend/core/submissions.rst b/docs/developers/backend/core/submissions.rst index 8767e521e8..9089db6ea3 100644 --- a/docs/developers/backend/core/submissions.rst +++ b/docs/developers/backend/core/submissions.rst @@ -17,7 +17,7 @@ Globally, the various actions and plugin categories are processed in order: #. If applicable, an :ref:`appointment ` is created. If this fails, the submission is blocked and the user sees an error - message and can try again (note: this step is deprecated and not needed for the new appointment flow). + message and can try again. #. Pre-registration step. Each :ref:`registration plugin ` can perform pre-registration task, like for example generating and setting a submission reference ID. If no registration backend is configured, then an internal ID is generated and set on the submission. @@ -39,9 +39,8 @@ Globally, the various actions and plugin categories are processed in order: the previous actions, the confirmation email shows different contents. The confirmation email can show submission details, appointment details -(including links to cancel or change the appointment), payment details -(including a link to pay if not done so already), cosign details and custom information as part -of the form. +(including links to cancel the appointment), payment details(including a link to pay if not done so already), +cosign details and custom information as part of the form. Under the hood -------------- diff --git a/docs/manual/forms/examples/_assets/appointment_creation_2_2.png b/docs/manual/forms/examples/_assets/appointment_creation_2_2.png deleted file mode 100644 index a0beddfb626f87df964ffc98abc653f5af28bde9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17739 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 gebruiken. - -In dit voorbeeld tonen we u hoe u een formulier kan maken zodat de gebruikers een afspraak -kan maken met het formulier. - -In dit voorbeeld gaan we er van uit dat u een -:ref:`eenvoudig formulier ` kan maken. - -Configuratie -============ - -* :ref:`Appointment configuratie ` - -Formulier maken -=============== - -1. Maak een formulier aan met de volgende gegevens: - - * **Naam**: Afspraak demo - -2. Klik op het tabblad **Stappen en velden**. -3. Klik aan de linkerkant op **Stap toevoegen** en selecteer **Maak een nieuwe - formulierdefinitie**. -4. Onder de sectie **(Herbruikbare) stapgegevens** vul het volgende in: - - * **Naam**: Afspraakgegevens - -5. Scroll naar de sectie **Velden**. -6. Sleep een **Select** component op het witte vlak, vul de volgende - gegevens in en druk daarna op **Opslaan**: - - * **Label**: Producten - -7. Sleep een **Select** component op het witte vlak, vul de volgende - gegevens in en druk daarna op **Opslaan**: - - * **Label**: Locaties - -8. Sleep een **Select** component op het witte vlak, vul de volgende - gegevens in en druk daarna op **Opslaan**: - - * **Label**: Datums - -9. Sleep een **Select** component op het witte vlak, vul de volgende - gegevens in en druk daarna op **Opslaan**: - - * **Label**: Tijden - -10. Sleep een **Tekstveld** component op het witte vlak, vul de volgende - gegevens in en druk daarna op **Opslaan**: - - * **Label**: Achternaam - -11. Sleep een **Datum** component op het witte vlak, vul de volgende - gegevens in en druk daarna op **Opslaan**: - - * **Label**: Geboortedatum - -12. (Optioneel) Sleep een **Telefoonnummer** component op het witte vlak, vul de volgende - gegevens in en druk daarna op **Opslaan**: - - * **Label**: Telefoonnummer - -13. Klik op het tabblad **Afspraken**. -14. Kies de juiste componenten voor elke veld in dit tabblad. - -.. image:: _assets/appointment_creation_2_2.png - -15. Klik onderaan op **Opslaan** om het formulier volledig op te slaan. - - -.. note:: - - De velden *Achternaam*, *Geboortedatum*, en *Telefoonnummer* mogen in een aparte formulierdefinitie (stap) - aanwezig zijn maar de velden *Producten*, *Locaties*, *Datums*, en *Tijden* moeten in dezelfde - formulierdefinitie (stap) aanwezig zijn. - diff --git a/docs/manual/forms/examples/index.rst b/docs/manual/forms/examples/index.rst index 47beeb3821..ed10944d6d 100644 --- a/docs/manual/forms/examples/index.rst +++ b/docs/manual/forms/examples/index.rst @@ -24,15 +24,3 @@ Voorbeelden suwinet form_with_geometry camunda7 - -====================== -Verouderde voorbeelden -====================== - -Deze voorbeelden beschrijven functionaliteit die uitgefaseerd wordt. We raden af om nog -nieuwe formulieren hiermee te bouwen. - -.. toctree:: - :maxdepth: 1 - - appointment_creation diff --git a/src/openforms/appointments/contrib/demo/tests/test_endpoints.py b/src/openforms/appointments/contrib/demo/tests/test_endpoints.py index 8cd8063aaa..dab878cce6 100644 --- a/src/openforms/appointments/contrib/demo/tests/test_endpoints.py +++ b/src/openforms/appointments/contrib/demo/tests/test_endpoints.py @@ -71,7 +71,7 @@ def test_times_list(self): self.assertEqual(response.status_code, status.HTTP_200_OK) times = response.json() - self.assertEqual(len(times), 3) + self.assertEqual(len(times), 4) def test_required_customer_fields_list(self): endpoint = reverse("api:appointments-customer-fields") diff --git a/src/openforms/appointments/contrib/jcc/tests/test_api_endpoints.py b/src/openforms/appointments/contrib/jcc/tests/test_api_endpoints.py index c013d116eb..0aafab55a1 100644 --- a/src/openforms/appointments/contrib/jcc/tests/test_api_endpoints.py +++ b/src/openforms/appointments/contrib/jcc/tests/test_api_endpoints.py @@ -93,8 +93,8 @@ def test_get_locations_multiple_products(self, m): def test_get_locations_returns_400_when_no_product_id_is_given(self): response = self.client.get(self.endpoint) - self.assertEqual(response.status_code, 200) - self.assertEqual(response.json(), []) + self.assertEqual(response.status_code, 400) + self.assertEqual(response.json()["invalidParams"][0]["code"], "required") def test_get_locations_returns_403_when_no_active_sessions(self): self._clear_session() @@ -165,8 +165,10 @@ def test_get_dates_returns_400_when_missing_query_params(self): for query_param in [{}, {"product_id": 79}, {"location_id": 1}]: with self.subTest(query_param=query_param): response = self.client.get(self.endpoint, query_param) - self.assertEqual(response.status_code, 200) - self.assertEqual(response.json(), []) + self.assertEqual(response.status_code, 400) + self.assertEqual( + response.json()["invalidParams"][0]["code"], "required" + ) def test_get_dates_returns_403_when_no_active_sessions(self): self._clear_session() @@ -242,8 +244,10 @@ def test_get_times_returns_400_when_missing_query_params(self): ]: with self.subTest(query_param=query_param): response = self.client.get(self.endpoint, query_param) - self.assertEqual(response.status_code, 200) - self.assertEqual(response.json(), []) + self.assertEqual(response.status_code, 400) + self.assertEqual( + response.json()["invalidParams"][0]["code"], "required" + ) def test_get_times_returns_403_when_no_active_sessions(self): self._clear_session() diff --git a/src/openforms/appointments/contrib/jcc/tests/test_plugin.py b/src/openforms/appointments/contrib/jcc/tests/test_plugin.py index 18b91eb21a..5153b45b81 100644 --- a/src/openforms/appointments/contrib/jcc/tests/test_plugin.py +++ b/src/openforms/appointments/contrib/jcc/tests/test_plugin.py @@ -15,7 +15,7 @@ from openforms.utils.xml import fromstring from soap.tests.factories import SoapServiceFactory -from ....base import AppointmentDetails, Customer, CustomerDetails, Location, Product +from ....base import AppointmentDetails, CustomerDetails, Location, Product from ....core import book from ....exceptions import ( AppointmentCreateFailed, @@ -251,7 +251,12 @@ def test_get_required_customer_fields(self, m): def test_create_appointment(self, m): product = Product(identifier="1", code="PASAAN", name="Paspoort aanvraag") location = Location(identifier="1", name="Maykin Media") - client = Customer(last_name="Doe", birthdate=date(1980, 1, 1)) + client = CustomerDetails( + details={ + CustomerFields.last_name: "Doe", + CustomerFields.birthday: "1980-01-01", + } + ) m.post( "http://example.com/soap11", @@ -665,7 +670,12 @@ def test_get_times_unexpected_exception(self, m): def test_create_appointment_failure(self, m): product = Product(identifier="1", code="PASAAN", name="Paspoort aanvraag") location = Location(identifier="1", name="Maykin Media") - client = Customer(last_name="Doe", birthdate=date(1980, 1, 1)) + client = CustomerDetails( + details={ + CustomerFields.last_name: "Doe", + CustomerFields.birthday: "1980-01-01", + } + ) start_at = datetime(2021, 8, 23, 6, 0, 0).replace(tzinfo=timezone.utc) m.post( "http://example.com/soap11", @@ -681,7 +691,12 @@ def test_create_appointment_failure(self, m): def test_create_appointment_unexpected_exception(self, m): product = Product(identifier="1", code="PASAAN", name="Paspoort aanvraag") location = Location(identifier="1", name="Maykin Media") - client = Customer(last_name="Doe", birthdate=date(1980, 1, 1)) + client = CustomerDetails( + details={ + CustomerFields.last_name: "Doe", + CustomerFields.birthday: "1980-01-01", + } + ) start_at = datetime(2021, 8, 23, 6, 0, 0).replace(tzinfo=timezone.utc) m.post(requests_mock.ANY, exc=IOError("tubes are closed")) diff --git a/src/openforms/appointments/contrib/qmatic/tests/test_api_endpoints.py b/src/openforms/appointments/contrib/qmatic/tests/test_api_endpoints.py index 25494c48f6..74577a85ac 100644 --- a/src/openforms/appointments/contrib/qmatic/tests/test_api_endpoints.py +++ b/src/openforms/appointments/contrib/qmatic/tests/test_api_endpoints.py @@ -84,8 +84,8 @@ def test_get_locations_returns_all_locations_for_a_product(self, m): def test_get_locations_returns_400_when_no_product_id_is_given(self): response = self.client.get(self.endpoint) - self.assertEqual(response.status_code, 200) - self.assertEqual(response.json(), []) + self.assertEqual(response.status_code, 400) + self.assertEqual(response.json()["invalidParams"][0]["code"], "required") def test_get_locations_returns_403_when_no_active_sessions(self): self._clear_session() @@ -156,8 +156,10 @@ def test_get_dates_returns_400_when_missing_query_params(self): for query_param in [{}, {"product_id": 79}, {"location_id": 1}]: with self.subTest(query_param=query_param): response = self.client.get(self.endpoint, query_param) - self.assertEqual(response.status_code, 200) - self.assertEqual(response.json(), []) + self.assertEqual(response.status_code, 400) + self.assertEqual( + response.json()["invalidParams"][0]["code"], "required" + ) def test_get_dates_returns_403_when_no_active_sessions(self): self._clear_session() @@ -232,8 +234,10 @@ def test_get_times_returns_400_when_missing_query_params(self): ]: with self.subTest(query_param=query_param): response = self.client.get(self.endpoint, query_param) - self.assertEqual(response.status_code, 200) - self.assertEqual(response.json(), []) + self.assertEqual(response.status_code, 400) + self.assertEqual( + response.json()["invalidParams"][0]["code"], "required" + ) def test_get_times_returns_403_when_no_active_sessions(self): self._clear_session() diff --git a/src/openforms/appointments/contrib/qmatic/tests/test_plugin.py b/src/openforms/appointments/contrib/qmatic/tests/test_plugin.py index ec98262675..5e94a00b21 100644 --- a/src/openforms/appointments/contrib/qmatic/tests/test_plugin.py +++ b/src/openforms/appointments/contrib/qmatic/tests/test_plugin.py @@ -15,7 +15,7 @@ ) from openforms.utils.tests.logging import disable_logging -from ....base import AppointmentDetails, Customer, Location, Product +from ....base import AppointmentDetails, CustomerDetails, Location, Product from ....core import book from ....exceptions import ( AppointmentCreateFailed, @@ -247,7 +247,12 @@ def test_create_appointment(self, m): location = Location( identifier="f364d92b7fa07a48c4ecc862de30c47", name="Branch 1" ) - client = Customer(last_name="Doe", birthdate=date(1980, 1, 1)) + client = CustomerDetails( + details={ + CustomerFields.last_name: "Doe", + CustomerFields.birthday: "1980-01-01", + } + ) day = datetime(2016, 12, 6, 9, 0, 0) m.get( @@ -529,7 +534,12 @@ def test_get_times_unexpected_exception(self, m): def test_create_appointment_failure(self, m): product = Product(identifier="1", code="PASAAN", name="Paspoort aanvraag") location = Location(identifier="1", name="Maykin Media") - client = Customer(last_name="Doe", birthdate=date(1980, 1, 1)) + client = CustomerDetails( + details={ + CustomerFields.last_name: "Doe", + CustomerFields.birthday: "1980-01-01", + } + ) start_at = timezone.make_aware(datetime(2021, 8, 23, 6, 0, 0)) m.get( f"{self.api_root}v1/branches/1", @@ -576,7 +586,12 @@ def test_create_appointment_failure(self, m): def test_create_appointment_unexpected_exception(self, m): product = Product(identifier="1", code="PASAAN", name="Paspoort aanvraag") location = Location(identifier="1", name="Maykin Media") - client = Customer(last_name="Doe", birthdate=date(1980, 1, 1)) + client = CustomerDetails( + details={ + CustomerFields.last_name: "Doe", + CustomerFields.birthday: "1980-01-01", + } + ) start_at = datetime(2021, 8, 23, 6, 0, 0).replace(tzinfo=timezone.utc) m.get( f"{self.api_root}v1/branches/1", diff --git a/src/openforms/appointments/tests/test_admin.py b/src/openforms/appointments/tests/test_admin.py index b01a871218..62fc10a9cd 100644 --- a/src/openforms/appointments/tests/test_admin.py +++ b/src/openforms/appointments/tests/test_admin.py @@ -52,7 +52,7 @@ class TestPlugin(DemoAppointment): @disable_admin_mfa() class AppointmentInfoAdminTests(WebTest): @freeze_time("2021-11-26T17:00:00+01:00") - def test_cancel_and_change_links_only_for_superuser(self): + def test_cancel_link_only_for_superuser(self): normal, staff = [ UserFactory.create(user_permissions=["view_appointmentinfo"]), StaffUserFactory.create(user_permissions=["view_appointmentinfo"]), @@ -84,34 +84,7 @@ def test_cancel_and_change_links_only_for_superuser(self): self.assertFalse(object_actions_col) @freeze_time("2021-11-26T17:00:00+01:00") - def test_cancel_and_change_links_legacy(self): - user = SuperUserFactory.create() - # appointment in the past - AppointmentInfoFactory.create( - registration_ok=True, start_time="2021-11-01T17:00:00+01:00" - ) - # appointment in the future - AppointmentInfoFactory.create( - registration_ok=True, start_time="2021-11-30T17:00:00+01:00" - ) - - changelist = self.app.get( - reverse("admin:appointments_appointmentinfo_changelist"), user=user - ) - - self.assertEqual(changelist.status_code, 200) - object_actions_col = changelist.pyquery(".field-get_object_actions") - - # future appointment - app1_links = object_actions_col.eq(0).find("a") - self.assertEqual(len(app1_links), 2) - - # past appointment - app2_links = object_actions_col.eq(1).find("a") - self.assertEqual(len(app2_links), 0) - - @freeze_time("2021-11-26T17:00:00+01:00") - def test_cancel_and_change_links(self): + def test_cancel_link(self): user = SuperUserFactory.create() # appointment in the past diff --git a/src/openforms/appointments/tests/test_api_products.py b/src/openforms/appointments/tests/test_api_products.py index 9863111f99..0f0eb05a83 100644 --- a/src/openforms/appointments/tests/test_api_products.py +++ b/src/openforms/appointments/tests/test_api_products.py @@ -65,6 +65,5 @@ def test_list_products_with_existing_product_invalid_query_param(self): response = self.client.get(self.endpoint, {"product_id": [""]}) - # XXX in 3.0, this will become HTTP 400 - self.assertEqual(response.status_code, 200) - self.assertEqual(response.json(), []) + self.assertEqual(response.status_code, 400) + self.assertEqual(response.json()["invalidParams"][0]["code"], "blank") diff --git a/src/openforms/appointments/tests/test_base.py b/src/openforms/appointments/tests/test_base.py index c3d208250a..bbb069c61f 100644 --- a/src/openforms/appointments/tests/test_base.py +++ b/src/openforms/appointments/tests/test_base.py @@ -32,20 +32,3 @@ def test_get_cancel_link(self): ) cancel_url = f"https://example.com{cancel_path}" self.assertEqual(cancel_url, result) - - @override_settings(BASE_URL="https://example.com/") - def test_get_change_link(self): - submission = SubmissionFactory.create(completed=True) - AppointmentInfoFactory.create(submission=submission, registration_ok=True) - - result = self.plugin.get_change_link(submission) - - change_path = reverse( - "appointments:appointments-verify-change-appointment-link", - kwargs={ - "token": submission_appointment_token_generator.make_token(submission), - "submission_uuid": submission.uuid, - }, - ) - change_url = f"https://example.com{change_path}" - self.assertEqual(change_url, result) diff --git a/src/openforms/appointments/tests/test_booking_appointment.py b/src/openforms/appointments/tests/test_booking_appointment.py index b3c474aacb..c6efb77af4 100644 --- a/src/openforms/appointments/tests/test_booking_appointment.py +++ b/src/openforms/appointments/tests/test_booking_appointment.py @@ -1,6 +1,6 @@ import os import sys -from datetime import datetime, timedelta +from datetime import datetime from unittest.mock import patch from django.test import TestCase @@ -21,11 +21,7 @@ ) from ..models import AppointmentInfo from ..registry import Registry -from .factories import ( - AppointmentFactory, - AppointmentInfoFactory, - AppointmentProductFactory, -) +from .factories import AppointmentFactory, AppointmentProductFactory register = Registry() register("demo")(DemoAppointment) @@ -155,48 +151,3 @@ def test_plugin_invocation(self): ), remarks="", ) - - def test_cancels_previous_appointment(self): - new_completed_on = timezone.now() - timedelta(hours=1) - # new submission, to replace the previous one - submission = SubmissionFactory.create( - form__is_appointment_form=True, - has_previous_submission=True, - previous_submission__completed=True, - previous_submission__completed_on=new_completed_on - timedelta(hours=12), - ) - AppointmentFactory.create(submission=submission, plugin="demo") - # set the data of the previous submission - AppointmentFactory.create( - submission=submission.previous_submission, plugin="demo" - ) - AppointmentInfoFactory.create( - submission=submission.previous_submission, - registration_ok=True, - appointment_id="98765", - ) - - with patch("openforms.appointments.core.register", new=register): - with supress_output(sys.stdout, os.devnull): - book_for_submission(submission) - - info_by_id = { - info.appointment_id: info for info in AppointmentInfo.objects.all() - } - with self.subTest("New submissions/appointment"): - self.assertIn("test 1", info_by_id) - self.assertEqual( - info_by_id["test 1"].status, AppointmentDetailsStatus.success - ) - - with self.subTest("Cancelled submission/appointment"): - self.assertIn("98765", info_by_id) - self.assertEqual( - info_by_id["98765"].status, AppointmentDetailsStatus.cancelled - ) - - with self.subTest("Audit logging"): - log_records = TimelineLogProxy.objects.all() - events = {lr.event for lr in log_records} - self.assertIn("appointment_cancel_start", events) - self.assertIn("appointment_cancel_success", events) diff --git a/src/openforms/appointments/tests/test_confirmation_emails.py b/src/openforms/appointments/tests/test_confirmation_emails.py index bba646d163..be806a825d 100644 --- a/src/openforms/appointments/tests/test_confirmation_emails.py +++ b/src/openforms/appointments/tests/test_confirmation_emails.py @@ -270,7 +270,7 @@ def test_appointment_data_present_in_confirmation_email(self): self.assertTagWithTextIn("td", "Email", message_html) self.assertTagWithTextIn("td", "austin@powers.net", message_html) - def test_cancel_and_change_instructions(self): + def test_cancel_instructions(self): appointment = AppointmentFactory.create( plugin="with-email", submission__language_code="nl", @@ -293,12 +293,9 @@ def test_cancel_and_change_instructions(self): plugin = register["with-email"] cancel_link = plugin.get_cancel_link(appointment.submission) - change_link = plugin.get_change_link(appointment.submission) with self.subTest(type="HTML"): self.assertIn(cancel_link, message_html) - self.assertNotIn(change_link, message_html) with self.subTest(type="plain text"): self.assertIn(cancel_link, message_text) - self.assertNotIn(change_link, message_text) diff --git a/src/openforms/appointments/tests/test_tasks_appointments.py b/src/openforms/appointments/tests/test_tasks_appointments.py deleted file mode 100644 index 60d1e3bb16..0000000000 --- a/src/openforms/appointments/tests/test_tasks_appointments.py +++ /dev/null @@ -1,148 +0,0 @@ -from unittest.mock import patch - -from django.test import TestCase - -from ..exceptions import AppointmentRegistrationFailed -from ..tasks import maybe_register_appointment -from .factories import AppointmentInfoFactory, SubmissionFactory - - -class LegacyAppointmentRegistrationTaskTests(TestCase): - def test_happy_flow(self): - submission = SubmissionFactory.create(completed=True) - - with patch( - "openforms.appointments.tasks.book_appointment_for_submission" - ) as mock_book: - maybe_register_appointment(submission.id) - - mock_book.assert_called_once() - - submission.refresh_from_db() - self.assertFalse(submission.needs_on_completion_retry) - - def test_appointment_registration_fails(self): - submission = SubmissionFactory.create(completed=True) - - with patch( - "openforms.appointments.tasks.book_appointment_for_submission" - ) as mock_book: - mock_book.side_effect = AppointmentRegistrationFailed("Failed") - with self.assertRaises(AppointmentRegistrationFailed): - maybe_register_appointment(submission.id) - - mock_book.assert_called_once() - - submission.refresh_from_db() - # NO automatic retry - user gets feedback and needs to correct/retry - self.assertFalse(submission.needs_on_completion_retry) - - def test_no_appointment_registered_yet(self): - submission = SubmissionFactory.create(completed=True) - - with patch( - "openforms.appointments.tasks.book_appointment_for_submission" - ) as mock_book: - maybe_register_appointment(submission.id) - - mock_book.assert_called_once_with(submission) - - def test_appointment_was_already_registered(self): - appointment_info = AppointmentInfoFactory.create( - submission__completed=True, - registration_ok=True, - ) - - with patch( - "openforms.appointments.tasks.book_appointment_for_submission" - ) as mock_book: - maybe_register_appointment(appointment_info.submission.id) - - mock_book.assert_not_called() - - def test_previous_registration_failed(self): - appointment_info = AppointmentInfoFactory.create( - submission__completed=True, - registration_failed=True, - ) - - with patch( - "openforms.appointments.tasks.book_appointment_for_submission" - ) as mock_book: - maybe_register_appointment(appointment_info.submission.id) - - mock_book.assert_called_once_with(appointment_info.submission) - - -class AppointmentRegistrationTaskTests(TestCase): - def test_happy_flow(self): - submission = SubmissionFactory.create( - completed=True, form__is_appointment_form=True - ) - - with patch("openforms.appointments.tasks.book_for_submission") as mock_book: - maybe_register_appointment(submission.id) - - mock_book.assert_called_once() - - submission.refresh_from_db() - self.assertFalse(submission.needs_on_completion_retry) - - def test_form_not_marked_as_appointment_form(self): - submission = SubmissionFactory.create( - completed=True, form__is_appointment_form=False - ) - with patch( - "openforms.appointments.tasks.book_appointment_for_submission" - ) as mock_legacy_book: - maybe_register_appointment(submission.id) - - mock_legacy_book.assert_called_once_with(submission) - - def test_appointment_registration_fails(self): - submission = SubmissionFactory.create( - completed=True, form__is_appointment_form=True - ) - - with patch("openforms.appointments.tasks.book_for_submission") as mock_book: - mock_book.side_effect = AppointmentRegistrationFailed("Failed") - with self.assertRaises(AppointmentRegistrationFailed): - maybe_register_appointment(submission.id) - - mock_book.assert_called_once() - - submission.refresh_from_db() - # NO automatic retry - user gets feedback and needs to correct/retry - self.assertFalse(submission.needs_on_completion_retry) - - def test_no_appointment_registered_yet(self): - submission = SubmissionFactory.create( - completed=True, form__is_appointment_form=True - ) - - with patch("openforms.appointments.tasks.book_for_submission") as mock_book: - maybe_register_appointment(submission.id) - - mock_book.assert_called_once_with(submission=submission) - - def test_appointment_was_already_registered(self): - appointment_info = AppointmentInfoFactory.create( - submission__completed=True, - registration_ok=True, - ) - - with patch("openforms.appointments.tasks.book_for_submission") as mock_book: - maybe_register_appointment(appointment_info.submission.id) - - mock_book.assert_not_called() - - def test_previous_registration_failed(self): - appointment_info = AppointmentInfoFactory.create( - submission__completed=True, - registration_failed=True, - ) - - with patch("openforms.appointments.tasks.book_for_submission") as mock_book: - maybe_register_appointment(appointment_info.submission.id) - - mock_book.assert_called_once_with(submission=appointment_info.submission) diff --git a/src/openforms/appointments/tests/test_utils.py b/src/openforms/appointments/tests/test_utils.py index 775c8213b2..478482b410 100644 --- a/src/openforms/appointments/tests/test_utils.py +++ b/src/openforms/appointments/tests/test_utils.py @@ -1,605 +1,6 @@ -from datetime import timedelta - from django.test import TestCase -from django.utils import timezone -from django.utils.translation import gettext as _ - -import requests_mock -from freezegun import freeze_time - -from openforms.forms.tests.factories import ( - FormDefinitionFactory, - FormFactory, - FormStepFactory, -) -from openforms.logging.models import TimelineLogProxy -from openforms.submissions.tests.factories import ( - SubmissionFactory, - SubmissionStepFactory, -) - -from ..constants import AppointmentDetailsStatus -from ..contrib.jcc.tests.test_plugin import mock_response -from ..exceptions import AppointmentCreateFailed, AppointmentRegistrationFailed -from ..models import AppointmentInfo -from ..utils import ( - book_appointment_for_submission, - cancel_previous_submission_appointment, - create_base64_qrcode, - find_first_appointment_step, - get_formatted_phone_number, -) -from .factories import AppointmentInfoFactory -from .utils import setup_jcc - - -# Deprecated/legacy tests -class BookAppointmentForSubmissionTest(TestCase): - @classmethod - def setUpTestData(cls): - super().setUpTestData() - - setup_jcc() - - def test_creating_appointment_with_no_appointment_information_does_nothing(self): - submission = SubmissionFactory.create() - book_appointment_for_submission(submission) - submission.refresh_from_db() - self.assertFalse(AppointmentInfo.objects.exists()) - self.assertFalse(TimelineLogProxy.objects.exists()) - - def test_appointment_step_not_applicable(self): - form = FormFactory.create() - step = FormStepFactory.create( - form=form, - form_definition__configuration={ - "display": "form", - "components": [ - { - "key": "product", - "type": "textfield", - "appointments": {"showProducts": True}, - "label": "Product", - }, - { - "key": "location", - "type": "textfield", - "appointments": {"showLocations": True}, - "label": "Location", - }, - { - "key": "time", - "type": "textfield", - "appointments": {"showTimes": True}, - "label": "Time", - }, - ], - }, - ) - submission = SubmissionFactory.create(form=form) - SubmissionStepFactory.create( - submission=submission, - data={}, - form_step=step, - ) - - book_appointment_for_submission(submission) - self.assertFalse(AppointmentInfo.objects.exists()) - self.assertFalse(TimelineLogProxy.objects.exists()) - - def test_creating_appointment_with_missing_or_not_filled_in_appointment_information_adds_error_message( - self, - ): - form = FormFactory.create() - form_definition_1 = FormDefinitionFactory.create( - configuration={ - "display": "form", - "components": [ - { - "key": "product", - "type": "textfield", - "appointments": {"showProducts": True}, - "label": "Product", - }, - { - "key": "time", - "type": "textfield", - "appointments": {"showTimes": True}, - "label": "Time", - }, - ], - } - ) - form_definition_2 = FormDefinitionFactory.create( - configuration={ - "display": "form", - "components": [ - { - "key": "lastName", - "type": "textfield", - "appointments": {"lastName": True}, - "label": "Last Name", - }, - { - "key": "birthDate", - "type": "textfield", - "appointments": {"birthDate": True}, - "label": "Date of Birth", - }, - ], - } - ) - form_step_1 = FormStepFactory.create( - form=form, form_definition=form_definition_1 - ) - form_step_2 = FormStepFactory.create( - form=form, form_definition=form_definition_2 - ) - submission = SubmissionFactory.create(form=form) - SubmissionStepFactory.create( - submission=submission, - data={ - "product": {"identifier": "79", "name": "Paspoort"}, - "time": "2021-08-25T17:00:00", - }, - form_step=form_step_1, - ) - SubmissionStepFactory.create( - submission=submission, - data={ - "lastName": "Maykin", - "birthDate": "", - }, - form_step=form_step_2, - ) - - with self.assertRaises(AppointmentRegistrationFailed): - book_appointment_for_submission(submission) - - info = AppointmentInfo.objects.filter( - submission=submission, - status=AppointmentDetailsStatus.missing_info, - ).get() - - self.assertEqual( - info.error_information, - _("The following appointment fields should be filled out: {fields}").format( - fields="Date of Birth, locationIDAndName" - ), - ) - self.assertEqual( - TimelineLogProxy.objects.filter( - template="logging/events/appointment_register_skip.txt" - ).count(), - 1, - ) - - @requests_mock.Mocker() - def test_creating_appointment_properly_creates_appointment_and_adds_appointment_information( - self, m - ): - form = FormFactory.create() - form_definition_1 = FormDefinitionFactory.create( - configuration={ - "display": "form", - "components": [ - { - "key": "product", - "type": "textfield", - "appointments": {"showProducts": True}, - "label": "Product", - }, - { - "key": "location", - "type": "textfield", - "appointments": {"showLocations": True}, - "label": "Location", - }, - { - "key": "time", - "type": "textfield", - "appointments": {"showTimes": True}, - "label": "Time", - }, - ], - } - ) - form_definition_2 = FormDefinitionFactory.create( - configuration={ - "display": "form", - "components": [ - { - "key": "lastName", - "type": "textfield", - "appointments": {"lastName": True}, - "label": "Last Name", - }, - { - "key": "birthDate", - "type": "textfield", - "appointments": {"birthDate": True}, - "label": "Date of Birth", - }, - ], - } - ) - form_step_1 = FormStepFactory.create( - form=form, form_definition=form_definition_1 - ) - form_step_2 = FormStepFactory.create( - form=form, form_definition=form_definition_2 - ) - submission = SubmissionFactory.create(form=form) - SubmissionStepFactory.create( - submission=submission, - data={ - "product": {"identifier": "79", "name": "Paspoort"}, - "location": {"identifier": "1", "name": "Amsterdam"}, - "time": "2021-08-25T17:00:00+02:00", - }, - form_step=form_step_1, - ) - SubmissionStepFactory.create( - submission=submission, - data={ - "lastName": "Maykin", - "birthDate": "1990-08-01", - }, - form_step=form_step_2, - ) - - m.post( - "http://example.com/soap11", - text=mock_response("bookGovAppointmentResponse.xml"), - ) - - book_appointment_for_submission(submission) - self.assertTrue( - AppointmentInfo.objects.filter( - appointment_id="1234567890", - submission=submission, - status=AppointmentDetailsStatus.success, - ).exists() - ) - self.assertEqual( - TimelineLogProxy.objects.filter( - template="logging/events/appointment_register_start.txt" - ).count(), - 1, - ) - self.assertEqual( - TimelineLogProxy.objects.filter( - template="logging/events/appointment_register_success.txt" - ).count(), - 1, - ) - - @freeze_time("2021-08-21T18:00:00+02:00") - @requests_mock.Mocker() - def test_creating_appointment_deletes_previous_appointment_when_one_exists(self, m): - new_completed_on = timezone.now() - timedelta(hours=1) - base_data = { - "product": {"identifier": "79", "name": "Paspoort"}, - "location": {"identifier": "1", "name": "Amsterdam"}, - "lastName": "Maykin", - "birthDate": "1990-08-01", - } - submission = SubmissionFactory.from_components( - completed=True, - completed_on=new_completed_on, - components_list=[ - { - "key": "product", - "type": "textfield", - "appointments": {"showProducts": True}, - "label": "Product", - }, - { - "key": "location", - "type": "textfield", - "appointments": {"showLocations": True}, - "label": "Location", - }, - { - "key": "time", - "type": "textfield", - "appointments": {"showTimes": True}, - "label": "Time", - }, - { - "key": "lastName", - "type": "textfield", - "appointments": {"lastName": True}, - "label": "Last Name", - }, - { - "key": "birthDate", - "type": "textfield", - "appointments": {"birthDate": True}, - "label": "Date of Birth", - }, - ], - submitted_data={**base_data, "time": "2021-08-26T17:00:00+02:00"}, - has_previous_submission=True, - previous_submission__completed=True, - previous_submission__completed_on=new_completed_on - timedelta(hours=12), - ) - - # set the data of the previous submission - appointment_info = AppointmentInfoFactory.create( - submission=submission.previous_submission, - registration_ok=True, - appointment_id="98765", - ) - SubmissionStepFactory.create( - submission=submission.previous_submission, - form_step=submission.form.formstep_set.get(), - data={**base_data, "time": "2021-08-25T17:00:00+02:00"}, - ) - m.post( - "http://example.com/soap11", - [ - {"text": mock_response("bookGovAppointmentResponse.xml")}, - {"text": mock_response("deleteGovAppointmentResponse.xml")}, - ], - ) - - book_appointment_for_submission(submission) - - self.assertTrue( - AppointmentInfo.objects.filter( - appointment_id="1234567890", - submission=submission, - status=AppointmentDetailsStatus.success, - ).exists() - ) - - appointment_info.refresh_from_db() - self.assertEqual(appointment_info.status, AppointmentDetailsStatus.cancelled) - self.assertEqual( - TimelineLogProxy.objects.filter( - template="logging/events/appointment_register_start.txt" - ).count(), - 1, - ) - self.assertEqual( - TimelineLogProxy.objects.filter( - template="logging/events/appointment_register_success.txt" - ).count(), - 1, - ) - - @requests_mock.Mocker() - def test_failed_creating_appointment_adds_error_message_to_submission(self, m): - form = FormFactory.create() - form_definition_1 = FormDefinitionFactory.create( - configuration={ - "display": "form", - "components": [ - { - "key": "product", - "type": "textfield", - "appointments": {"showProducts": True}, - "label": "Product", - }, - { - "key": "location", - "type": "textfield", - "appointments": {"showLocations": True}, - "label": "Location", - }, - { - "key": "time", - "type": "textfield", - "appointments": {"showTimes": True}, - "label": "Time", - }, - ], - } - ) - form_definition_2 = FormDefinitionFactory.create( - configuration={ - "display": "form", - "components": [ - { - "key": "lastName", - "type": "textfield", - "appointments": {"lastName": True}, - "label": "Last Name", - }, - { - "key": "birthDate", - "type": "textfield", - "appointments": {"birthDate": True}, - "label": "Date of Birth", - }, - ], - } - ) - form_step_1 = FormStepFactory.create( - form=form, form_definition=form_definition_1 - ) - form_step_2 = FormStepFactory.create( - form=form, form_definition=form_definition_2 - ) - submission = SubmissionFactory.create(form=form) - SubmissionStepFactory.create( - submission=submission, - data={ - "product": {"identifier": "79", "name": "Paspoort"}, - "location": {"identifier": "1", "name": "Amsterdam"}, - "time": "2021-08-25T17:00:00+02:00", - }, - form_step=form_step_1, - ) - SubmissionStepFactory.create( - submission=submission, - data={ - "lastName": "Maykin", - "birthDate": "1990-08-01", - }, - form_step=form_step_2, - ) - - m.post( - "http://example.com/soap11", - exc=AppointmentCreateFailed, - ) - - with self.assertRaises(AppointmentRegistrationFailed): - book_appointment_for_submission(submission) - - self.assertTrue( - AppointmentInfo.objects.filter( - submission=submission, - status=AppointmentDetailsStatus.failed, - ).exists() - ) - self.assertEqual( - TimelineLogProxy.objects.filter( - template="logging/events/appointment_register_start.txt" - ).count(), - 1, - ) - self.assertEqual( - TimelineLogProxy.objects.filter( - template="logging/events/appointment_register_failure.txt" - ).count(), - 1, - ) - - @requests_mock.Mocker() - def test_failed_creating_appointment_when_submission_previously_failed(self, m): - form = FormFactory.create() - form_definition_1 = FormDefinitionFactory.create( - configuration={ - "display": "form", - "components": [ - { - "key": "product", - "type": "textfield", - "appointments": {"showProducts": True}, - "label": "Product", - }, - { - "key": "location", - "type": "textfield", - "appointments": {"showLocations": True}, - "label": "Location", - }, - { - "key": "time", - "type": "textfield", - "appointments": {"showTimes": True}, - "label": "Time", - }, - ], - } - ) - form_definition_2 = FormDefinitionFactory.create( - configuration={ - "display": "form", - "components": [ - { - "key": "lastName", - "type": "textfield", - "appointments": {"lastName": True}, - "label": "Last Name", - }, - { - "key": "birthDate", - "type": "textfield", - "appointments": {"birthDate": True}, - "label": "Date of Birth", - }, - ], - } - ) - form_step_1 = FormStepFactory.create( - form=form, form_definition=form_definition_1 - ) - form_step_2 = FormStepFactory.create( - form=form, form_definition=form_definition_2 - ) - submission = SubmissionFactory.create(form=form) - first_appointment_info = AppointmentInfoFactory.create( - status=AppointmentDetailsStatus.failed, - error_information="Failed to make appointment", - submission=submission, - ) - SubmissionStepFactory.create( - submission=submission, - data={ - "product": {"identifier": "79", "name": "Paspoort"}, - "location": {"identifier": "1", "name": "Amsterdam"}, - "time": "2021-08-25T17:00:00+02:00", - }, - form_step=form_step_1, - ) - SubmissionStepFactory.create( - submission=submission, - data={ - "lastName": "Maykin", - "birthDate": "1990-08-01", - }, - form_step=form_step_2, - ) - - m.post( - "http://example.com/soap11", - exc=AppointmentCreateFailed, - ) - - with self.assertRaises(AppointmentRegistrationFailed): - book_appointment_for_submission(submission) - - submission.refresh_from_db() - second_appointment_info = submission.appointment_info - - self.assertNotEqual(first_appointment_info.pk, second_appointment_info.pk) - - self.assertEqual( - TimelineLogProxy.objects.filter( - template="logging/events/appointment_register_start.txt" - ).count(), - 1, - ) - self.assertEqual( - TimelineLogProxy.objects.filter( - template="logging/events/appointment_register_failure.txt" - ).count(), - 1, - ) - - def test_cancelling_previous_appointments_nothing_to_cancel(self): - submission1 = SubmissionFactory.create(has_previous_submission=True) - AppointmentInfoFactory.create( - submission=submission1.previous_submission, - registration_failed=True, - ) - submission2 = SubmissionFactory.create(has_previous_submission=True) - AppointmentInfoFactory.create( - submission=submission2.previous_submission, - registration_ok=True, - appointment_id="", - ) - submissions = [ - ("no previous", SubmissionFactory.create(has_previous_submission=False)), - ( - "no appointment info", - SubmissionFactory.create(has_previous_submission=True), - ), - ("failed registration", submission1), - ("succeeded registration but no id", submission2), - ] - - for label, submission in submissions: - with self.subTest(type=label): - with requests_mock.Mocker() as m: - cancel_previous_submission_appointment(submission) - - self.assertFalse(m.called) +from ..utils import create_base64_qrcode, get_formatted_phone_number class UtilsTests(TestCase): @@ -626,43 +27,6 @@ def test_create_base64_qrcode(self): self.assertEqual(result, expected) - def test_find_first_appointment_step_returns_None_for_no_appointment_data(self): - submission = SubmissionFactory.from_components( - components_list=[ - { - "type": "textfield", - "key": "placeholder", - } - ] - ) - - step = find_first_appointment_step(submission.form) - - self.assertIsNone(step) - - def test_find_first_appointment_step_finds_correct_step(self): - submission = SubmissionFactory.from_components( - components_list=[ - { - "key": "product", - "type": "textfield", - "appointments": {"showProducts": True}, - "label": "Product", - }, - { - "key": "time", - "type": "textfield", - "appointments": {"showTimes": True}, - "label": "Time", - }, - ] - ) - - step = find_first_appointment_step(submission.form) - - self.assertIsNotNone(step) - self.assertEqual(step, submission.submissionstep_set.get().form_step) - class GetFormattedPhoneNumberTest(TestCase): def test_get_formatted_phone_number_returns_expected_format(self): diff --git a/src/openforms/appointments/tests/test_views.py b/src/openforms/appointments/tests/test_views.py index f14b713419..926e5e0d43 100644 --- a/src/openforms/appointments/tests/test_views.py +++ b/src/openforms/appointments/tests/test_views.py @@ -1,6 +1,5 @@ import uuid from datetime import datetime, timezone -from decimal import Decimal from django.test import TestCase from django.urls import reverse @@ -10,20 +9,12 @@ from openforms.authentication.contrib.digid.constants import DIGID_DEFAULT_LOA from openforms.authentication.service import FORM_AUTH_SESSION_KEY, AuthAttribute -from openforms.forms.tests.factories import FormFactory from openforms.frontend.tests import FrontendRedirectMixin -from openforms.logging.models import TimelineLogProxy -from openforms.payments.constants import PaymentStatus -from openforms.payments.tests.factories import SubmissionPaymentFactory from openforms.submissions.constants import SUBMISSIONS_SESSION_KEY -from openforms.submissions.models import Submission -from openforms.submissions.tests.factories import ( - SubmissionFactory, - SubmissionStepFactory, -) +from openforms.submissions.tests.factories import SubmissionFactory from ..tokens import submission_appointment_token_generator -from .factories import AppointmentFactory, AppointmentInfoFactory +from .factories import AppointmentInfoFactory @freeze_time("2021-07-15T21:15:00Z") @@ -338,546 +329,3 @@ def test_invalid_auth_value_raises_exception(self): self.assertEqual(403, response.status_code) self.assertNotIn(SUBMISSIONS_SESSION_KEY, self.client.session) - - -@freeze_time("2021-07-15T21:15:00Z") -class VerifyChangeAppointmentLinkViewTests(FrontendRedirectMixin, TestCase): - def test_good_token_and_submission_redirect_and_add_submission_to_session(self): - submission = SubmissionFactory.from_components( - completed=True, - components_list=[ - { - "key": "product", - "appointments": {"showProducts": True}, - "label": "Product", - }, - { - "key": "time", - "appointments": {"showTimes": True}, - "label": "Time", - }, - ], - submitted_data={ - "product": {"identifier": "79", "name": "Paspoort"}, - "time": "2021-08-25T17:00:00", - }, - form_url="http://maykinmedia.nl/myform/", - bsn="000000000", - ) - form_definition = submission.form.formstep_set.get().form_definition - AppointmentInfoFactory.create( - submission=submission, - registration_ok=True, - start_time=datetime(2021, 7, 21, 12, 00, 00, tzinfo=timezone.utc), - ) - - endpoint = reverse( - "appointments:appointments-verify-change-appointment-link", - kwargs={ - "token": submission_appointment_token_generator.make_token(submission), - "submission_uuid": submission.uuid, - }, - ) - # Add form_auth to session, as the authentication plugin would do it - session = self.client.session - session[FORM_AUTH_SESSION_KEY] = { - "plugin": "digid", - "attribute": AuthAttribute.bsn, - "value": "000000000", - "loa": DIGID_DEFAULT_LOA, - } - session.save() - - # one day after token generation - with freeze_time("2021-07-16T21:15:00Z"): - response = self.client.get(endpoint) - - new_submission = Submission.objects.exclude(id=submission.id).get() - # after initiating change, we expect the bsn to be stored in plain text (again) - self.assertEqual(new_submission.auth_info.value, "000000000") - - self.assertRedirectsToFrontend( - response, - frontend_base_url=submission.form_url, - action="resume", - action_params={ - "step_slug": form_definition.slug, - "submission_uuid": str(new_submission.uuid), - }, - fetch_redirect_response=False, - ) - - # Assert new submission was created - self.assertEqual(Submission.objects.count(), 2) - # Assert old submission not stored in session - self.assertNotIn( - str(submission.uuid), self.client.session[SUBMISSIONS_SESSION_KEY] - ) - # Assert new submission is stored in session - self.assertIn( - str(new_submission.uuid), self.client.session[SUBMISSIONS_SESSION_KEY] - ) - - def test_403_response_with_unfound_submission(self): - endpoint = reverse( - "appointments:appointments-verify-change-appointment-link", - kwargs={ - "token": "irrelevant", - "submission_uuid": uuid.uuid4(), - }, - ) - - response = self.client.get(endpoint) - - self.assertEqual(response.status_code, 403) - - def test_403_response_with_bad_token(self): - submission = SubmissionFactory.create(completed=True) - AppointmentInfoFactory.create( - submission=submission, - registration_ok=True, - start_time=datetime(2021, 7, 21, 12, 00, 00, tzinfo=timezone.utc), - ) - - endpoint = reverse( - "appointments:appointments-verify-change-appointment-link", - kwargs={ - "token": "bad", - "submission_uuid": submission.uuid, - }, - ) - - response = self.client.get(endpoint) - - self.assertEqual(response.status_code, 403) - - def test_token_invalid_after_appointment_time(self): - submission = SubmissionFactory.create(completed=True) - AppointmentInfoFactory.create( - submission=submission, - registration_ok=True, - start_time=datetime(2021, 7, 21, 12, 00, 00, tzinfo=timezone.utc), - ) - - endpoint = reverse( - "appointments:appointments-verify-change-appointment-link", - kwargs={ - "token": submission_appointment_token_generator.make_token(submission), - "submission_uuid": submission.uuid, - }, - ) - - with freeze_time("2021-07-22T12:00:00Z"): - response = self.client.get(endpoint) - - self.assertEqual(response.status_code, 403) - - def test_token_valid_on_same_day_appointment(self): - submission = SubmissionFactory.from_components( - completed=True, - components_list=[ - { - "key": "product", - "appointments": {"showProducts": True}, - "label": "Product", - }, - { - "key": "time", - "appointments": {"showTimes": True}, - "label": "Time", - }, - ], - submitted_data={ - "product": {"identifier": "79", "name": "Paspoort"}, - "time": "2021-08-25T17:00:00", - }, - form_url="http://maykinmedia.nl/myform/", - ) - AppointmentInfoFactory.create( - submission=submission, - registration_ok=True, - start_time=datetime(2021, 7, 21, 12, 00, 00, tzinfo=timezone.utc), - ) - - endpoint = reverse( - "appointments:appointments-verify-change-appointment-link", - kwargs={ - "token": submission_appointment_token_generator.make_token(submission), - "submission_uuid": submission.uuid, - }, - ) - - with freeze_time("2021-07-21T11:59:59Z"): - response = self.client.get(endpoint) - - self.assertEqual(response.status_code, 302) - - def test_redirect_to_first_step_when_appointment_form_definition_can_not_be_found( - self, - ): - form = FormFactory.create() - submission = SubmissionFactory.create( - form=form, completed=True, form_url="http://maykinmedia.nl/myform/" - ) - SubmissionStepFactory.create( - form_step__form=form, - form_step__form_definition__slug="step-1", - form_step__form_definition__configuration={ - "display": "form", - "components": [ - { - "key": "name", - "label": "Name", - "type": "textfield", - }, - ], - }, - submission=submission, - data={ - "Name": "Maykin", - }, - ) - SubmissionStepFactory.create( - submission=submission, - form_step__form=form, - form_step__form_definition__slug="step-2", - form_step__form_definition__configuration={ - "display": "form", - "components": [ - { - "key": "product", - "appointments": {"showProducts": False}, - "label": "Product", - "type": "select", - }, - { - "key": "time", - "appointments": {"showTimes": False}, - "label": "Time", - "type": "select", - }, - ], - }, - data={ - "product": {"identifier": "79", "name": "Paspoort"}, - "time": "2021-08-25T17:00:00", - }, - ) - AppointmentInfoFactory.create( - submission=submission, - registration_ok=True, - start_time=datetime(2021, 7, 21, 12, 00, 00, tzinfo=timezone.utc), - ) - - endpoint = reverse( - "appointments:appointments-verify-change-appointment-link", - kwargs={ - "token": submission_appointment_token_generator.make_token(submission), - "submission_uuid": submission.uuid, - }, - ) - - # one day after token generation - with freeze_time("2021-07-16T21:15:00Z"): - response = self.client.get(endpoint) - - new_submission = Submission.objects.exclude(id=submission.id).get() - - self.assertRedirectsToFrontend( - response, - frontend_base_url=submission.form_url, - action="resume", - action_params={ - "step_slug": "step-1", - "submission_uuid": str(new_submission.uuid), - }, - fetch_redirect_response=False, - ) - - def test_redirects_to_auth_if_form_requires_login(self): - submission = SubmissionFactory.create( - form__generate_minimal_setup=True, - form__formstep__form_definition__login_required=True, - auth_info__plugin="digid", - completed=True, - ) - AppointmentInfoFactory.create( - submission=submission, - registration_ok=True, - start_time=datetime(2021, 7, 21, 12, 00, 00, tzinfo=timezone.utc), - ) - - endpoint = reverse( - "appointments:appointments-verify-change-appointment-link", - kwargs={ - "token": submission_appointment_token_generator.make_token(submission), - "submission_uuid": submission.uuid, - }, - ) - expected_redirect_url = furl( - f"http://testserver/auth/{submission.form.slug}/digid/start" - ) - expected_redirect_url.args["next"] = f"http://testserver{endpoint}" - - response = self.client.get(endpoint) - - self.assertRedirects( - response, expected_redirect_url.url, fetch_redirect_response=False - ) - self.assertNotIn(SUBMISSIONS_SESSION_KEY, self.client.session) - - def test_after_successful_auth_redirects_to_form(self): - submission = SubmissionFactory.create( - form__generate_minimal_setup=True, - form__formstep__form_definition__login_required=True, - form__formstep__form_definition__slug="test-step", - auth_info__plugin="digid", - form_url="http://testserver/myform/", - completed=True, - auth_info__value="123456782", - ) - AppointmentInfoFactory.create( - submission=submission, - registration_ok=True, - start_time=datetime(2021, 7, 21, 12, 00, 00, tzinfo=timezone.utc), - ) - - endpoint = reverse( - "appointments:appointments-verify-change-appointment-link", - kwargs={ - "token": submission_appointment_token_generator.make_token(submission), - "submission_uuid": submission.uuid, - }, - ) - - # Add form_auth to session, as the authentication plugin would do it - session = self.client.session - session[FORM_AUTH_SESSION_KEY] = { - "plugin": "digid", - "attribute": AuthAttribute.bsn, - "value": "123456782", - "loa": DIGID_DEFAULT_LOA, - } - session.save() - - response = self.client.get(endpoint) - new_submission = Submission.objects.filter( - previous_submission=submission - ).first() - - self.assertIsNotNone(new_submission) - - self.assertRedirectsToFrontend( - response, - frontend_base_url=submission.form_url, - action="resume", - action_params={ - "step_slug": "test-step", - "submission_uuid": str(new_submission.uuid), - }, - fetch_redirect_response=False, - ) - - self.assertIn(SUBMISSIONS_SESSION_KEY, self.client.session) - self.assertIn( - str(new_submission.uuid), self.client.session[SUBMISSIONS_SESSION_KEY] - ) - - def test_invalid_auth_plugin_raises_exception(self): - submission = SubmissionFactory.create( - form__generate_minimal_setup=True, - form__formstep__form_definition__login_required=True, - form__formstep__form_definition__slug="test-step", - auth_info__plugin="wrong-plugin", - form_url="http://testserver/myform/", - completed=True, - auth_info__value="123456782", - ) - AppointmentInfoFactory.create( - submission=submission, - registration_ok=True, - start_time=datetime(2021, 7, 21, 12, 00, 00, tzinfo=timezone.utc), - ) - - endpoint = reverse( - "appointments:appointments-verify-change-appointment-link", - kwargs={ - "token": submission_appointment_token_generator.make_token(submission), - "submission_uuid": submission.uuid, - }, - ) - - # Add form_auth to session, as the authentication plugin would do it - session = self.client.session - session[FORM_AUTH_SESSION_KEY] = { - "plugin": "digid", - "attribute": AuthAttribute.bsn, - "value": "123456782", - "loa": DIGID_DEFAULT_LOA, - } - session.save() - - response = self.client.get(endpoint) - - self.assertEqual(403, response.status_code) - self.assertNotIn(SUBMISSIONS_SESSION_KEY, self.client.session) - - def test_invalid_auth_attribute_raises_exception(self): - submission = SubmissionFactory.create( - form__generate_minimal_setup=True, - form__formstep__form_definition__login_required=True, - form__formstep__form_definition__slug="test-step", - auth_info__plugin="digid", - form_url="http://testserver/myform/", - completed=True, - auth_info__value="123456782", - auth_info__attribute=AuthAttribute.kvk, - ) - AppointmentInfoFactory.create( - submission=submission, - registration_ok=True, - start_time=datetime(2021, 7, 21, 12, 00, 00, tzinfo=timezone.utc), - ) - - endpoint = reverse( - "appointments:appointments-verify-change-appointment-link", - kwargs={ - "token": submission_appointment_token_generator.make_token(submission), - "submission_uuid": submission.uuid, - }, - ) - - # Add form_auth to session, as the authentication plugin would do it - session = self.client.session - session[FORM_AUTH_SESSION_KEY] = { - "plugin": "digid", - "attribute": AuthAttribute.bsn, - "value": "123456782", - "loa": DIGID_DEFAULT_LOA, - } - session.save() - - response = self.client.get(endpoint) - - self.assertEqual(403, response.status_code) - self.assertNotIn(SUBMISSIONS_SESSION_KEY, self.client.session) - - def test_invalid_auth_value_raises_exception(self): - submission = SubmissionFactory.create( - form__generate_minimal_setup=True, - form__formstep__form_definition__login_required=True, - form__formstep__form_definition__slug="test-step", - auth_info__plugin="digid", - form_url="http://testserver/myform/", - completed=True, - auth_info__value="wrong-bsn", - ) - AppointmentInfoFactory.create( - submission=submission, - registration_ok=True, - start_time=datetime(2021, 7, 21, 12, 00, 00, tzinfo=timezone.utc), - ) - - endpoint = reverse( - "appointments:appointments-verify-change-appointment-link", - kwargs={ - "token": submission_appointment_token_generator.make_token(submission), - "submission_uuid": submission.uuid, - }, - ) - - # Add form_auth to session, as the authentication plugin would do it - session = self.client.session - session[FORM_AUTH_SESSION_KEY] = { - "plugin": "digid", - "attribute": AuthAttribute.bsn, - "value": "123456782", - "loa": DIGID_DEFAULT_LOA, - } - session.save() - - response = self.client.get(endpoint) - - self.assertEqual(403, response.status_code) - self.assertNotIn(SUBMISSIONS_SESSION_KEY, self.client.session) - - def test_change_appointment_details_after_payment(self): - submission = SubmissionFactory.from_components( - with_public_registration_reference=True, - components_list=[ - { - "key": "product", - "appointments": {"showProducts": True}, - "label": "Product", - }, - { - "key": "time", - "appointments": {"showTimes": True}, - "label": "Time", - }, - ], - submitted_data={ - "product": {"identifier": "79", "name": "Paspoort"}, - "time": "2021-08-25T17:00:00", - }, - form_url="http://maykinmedia.nl/myform/", - form__product__price=Decimal("12.34"), - form__payment_backend="test", - ) - submission_payment = SubmissionPaymentFactory.for_submission( - submission, status=PaymentStatus.completed - ) - AppointmentInfoFactory.create( - submission=submission, - registration_ok=True, - start_time=datetime(2021, 7, 21, 12, 00, 00, tzinfo=timezone.utc), - ) - - endpoint = reverse( - "appointments:appointments-verify-change-appointment-link", - kwargs={ - "token": submission_appointment_token_generator.make_token(submission), - "submission_uuid": submission.uuid, - }, - ) - - self.assertTrue(submission.payment_required) - self.assertTrue(submission.payment_user_has_paid) - - # one day after token generation - with freeze_time("2021-07-16T21:15:00Z"): - self.client.get(endpoint) - - new_submission = Submission.objects.exclude(id=submission.id).get() - submission_payment.refresh_from_db() - - self.assertTrue(new_submission.payment_required) - self.assertTrue(new_submission.payment_user_has_paid) - self.assertEqual(submission_payment.submission, new_submission) - self.assertEqual( - TimelineLogProxy.objects.filter( - template="logging/events/transfer_payment_to_submission_copy.txt" - ).count(), - 1, - ) - - def test_change_new_style_appointment(self): - appointment = AppointmentFactory.create( - appointment_info__registration_ok=True, - appointment_info__start_time=datetime( - 2021, 7, 21, 12, 00, 00, tzinfo=timezone.utc - ), - ) - submission = appointment.submission - url = reverse( - "appointments:appointments-verify-change-appointment-link", - kwargs={ - "token": submission_appointment_token_generator.make_token(submission), - "submission_uuid": submission.uuid, - }, - ) - - # one day after token generation - with freeze_time("2021-07-16T21:15:00Z"): - with self.assertRaises(RuntimeError): - self.client.get(url) diff --git a/src/openforms/emails/tests/test_confirmation_email.py b/src/openforms/emails/tests/test_confirmation_email.py index 2c58b64b84..e29f69c77f 100644 --- a/src/openforms/emails/tests/test_confirmation_email.py +++ b/src/openforms/emails/tests/test_confirmation_email.py @@ -274,13 +274,6 @@ def test_appointment_information(self, get_plugin_mock): rendered_content, ) - self.assertInHTML( - '' - + _("Change appointment") - + "", - rendered_content, - ) - def test_appointment_information_with_no_appointment_id(self): submission = SubmissionFactory.create() AppointmentInfoFactory.create( diff --git a/src/openforms/formio/formatters/tests/test_kitchensink.py b/src/openforms/formio/formatters/tests/test_kitchensink.py index 82029675b1..02ddf5b90f 100644 --- a/src/openforms/formio/formatters/tests/test_kitchensink.py +++ b/src/openforms/formio/formatters/tests/test_kitchensink.py @@ -106,24 +106,3 @@ def run_kitchensink_test(self, name_data, name_printable): for label, value in text_printed.items(): with self.subTest(f"{label} -> '{value}'"): self.assertEqual(value, text_values[label]) - - def test_appointments_formio(self): - configuration = load_json("appointments_components.json") - data = load_json("appointments_data.json") - text_printed = load_json("appointments_printable_text.json") - - # for sanity - self.assertFlatConfiguration(configuration) - - self.assertEqual(len(text_printed), len(data)) - - submission = SubmissionFactory.from_components( - configuration["components"], submitted_data=data, completed=True - ) - - printable_data = _get_printable_data(submission) - text_values = dict(printable_data) - - for label, value in text_printed.items(): - with self.subTest(f"{label} -> '{value}'"): - self.assertEqual(value, text_values[label]) diff --git a/src/openforms/submissions/tests/test_models.py b/src/openforms/submissions/tests/test_models.py index 4f6b5ca2ce..bc74be0b7a 100644 --- a/src/openforms/submissions/tests/test_models.py +++ b/src/openforms/submissions/tests/test_models.py @@ -225,137 +225,6 @@ def test_submission_delete_file_uploads_cascade_file_already_gone(self): ) self.assertFalse(attachment.content.storage.exists(attachment.content.path)) - def test_get_merged_appointment_data(self): - form = FormFactory.create() - form_definition_1 = FormDefinitionFactory.create( - configuration={ - "display": "form", - "components": [ - { - "key": "product", - "type": "textfield", - "appointments": {"showProducts": True}, - "label": "Product", - }, - { - "key": "location", - "type": "textfield", - "appointments": {"showLocations": True}, - "label": "Location", - }, - { - "key": "time", - "type": "textfield", - "appointments": {"showTimes": True}, - "label": "Time", - }, - ], - } - ) - form_definition_2 = FormDefinitionFactory.create( - configuration={ - "display": "form", - "components": [ - { - "key": "lastName", - "type": "textfield", - "appointments": {"lastName": True}, - "label": "Last Name", - }, - { - "key": "birthDate", - "type": "date", - "appointments": {"birthDate": True}, - "label": "Date of Birth", - }, - { - "key": "phoneNumber", - "type": "textfield", - "appointments": {"phoneNumber": True}, - "label": "Phone Number", - }, - { - "key": "randomAttribute", - "type": "textfield", - "appointments": {"birthDate": False}, - "label": "Random attribute", - }, - ], - } - ) - form_step_1 = FormStepFactory.create( - form=form, form_definition=form_definition_1 - ) - form_step_2 = FormStepFactory.create( - form=form, form_definition=form_definition_2 - ) - submission = SubmissionFactory.create(form=form) - SubmissionStepFactory.create( - submission=submission, - data={ - "product": {"identifier": "79", "name": "Paspoort"}, - "location": {"identifier": "1", "name": "Amsterdam"}, - "time": "2021-08-25T17:00:00", - }, - form_step=form_step_1, - ) - SubmissionStepFactory.create( - submission=submission, - data={ - "lastName": "Maykin", - "birthDate": "1990-08-01", - "phoneNumber": "+31 20 753 05 23", - "randomAttribute": "This is some random stuff", - }, - form_step=form_step_2, - ) - - self.assertEqual( - submission.get_merged_appointment_data(), - { - "productIDAndName": { - "label": "Product", - "value": {"identifier": "79", "name": "Paspoort"}, - }, - "locationIDAndName": { - "label": "Location", - "value": {"identifier": "1", "name": "Amsterdam"}, - }, - "appStartTime": {"label": "Time", "value": "2021-08-25T17:00:00"}, - "clientLastName": {"label": "Last Name", "value": "Maykin"}, - "clientDateOfBirth": {"label": "Date of Birth", "value": "1990-08-01"}, - "clientPhoneNumber": { - "label": "Phone Number", - "value": "+31 20 753 05 23", - }, - }, - ) - - def test_copy_submission(self): - submission = SubmissionFactory.create(auth_info__value="bsn1") - SubmissionStepFactory.create( - submission=submission, - data={"key1": "value1", "key2": "value2"}, - form_step=FormStepFactory.create(), - ) - SubmissionStepFactory.create( - submission=submission, - data={"key3": "value-b"}, - form_step=FormStepFactory.create(), - ) - - new_submission = Submission.objects.copy(submission) - - self.assertEqual(new_submission.form, submission.form) - self.assertEqual(new_submission.form_url, submission.form_url) - self.assertEqual(new_submission.previous_submission, submission) - self.assertEqual(new_submission.data, submission.data) - self.assertEqual(new_submission.auth_info.value, "bsn1") - self.assertEqual(new_submission.auth_info.plugin, "digid") - self.assertEqual(new_submission.auth_info.attribute, AuthAttribute.bsn) - self.assertNotEqual(new_submission.id, submission.id) - self.assertNotEqual(new_submission.uuid, submission.uuid) - @override_settings(CORS_ALLOW_ALL_ORIGINS=True) def test_co_sign_data_validation(self): extra_fields = { diff --git a/src/openforms/submissions/tests/test_post_submission_event.py b/src/openforms/submissions/tests/test_post_submission_event.py index bffe0ecab4..9f3a9ef5dc 100644 --- a/src/openforms/submissions/tests/test_post_submission_event.py +++ b/src/openforms/submissions/tests/test_post_submission_event.py @@ -849,21 +849,6 @@ def test_payment_status_update_retry_flow(self): self.assertEqual(len(mails), 0) self.assertNotEqual(submission.auth_info.value, "111222333") - def test_submission_completed_incomplete_appointment(self): - setup_jcc() - components = FormDefinitionFactory.build(is_appointment=True).configuration[ - "components" - ] - submission = SubmissionFactory.from_components( - completed=True, - form__registration_backend="", - components_list=components, - submitted_data={"product": {"identifier": "79", "name": "Paspoort"}}, - ) - - with self.assertRaises(AppointmentRegistrationFailed): - on_post_submission_event(submission.id, PostSubmissionEvents.on_completion) - def test_cosign_not_required_and_not_filled_in_proceeds_with_registration(self): submission = SubmissionFactory.from_components( components_list=[ diff --git a/src/openforms/submissions/tests/test_tasks_confirmation_emails.py b/src/openforms/submissions/tests/test_tasks_confirmation_emails.py index a5b6363816..7781098802 100644 --- a/src/openforms/submissions/tests/test_tasks_confirmation_emails.py +++ b/src/openforms/submissions/tests/test_tasks_confirmation_emails.py @@ -477,47 +477,6 @@ def test_completed_submission_after_timeout_with_confirmation_email_when_already # assert that no e-mail was sent self.assertEqual(len(mail.outbox), 0) - @override_settings(DEFAULT_FROM_EMAIL="info@open-forms.nl") - def test_send_confirmation_email_when_appointment_is_changed(self): - submission = SubmissionFactory.from_components( - completed=True, - components_list=[ - { - "key": "email", - "type": "email", - "label": "Email", - "confirmationRecipient": True, - }, - ], - submitted_data={"email": "test@test.nl"}, - has_previous_submission=True, - ) - AppointmentInfoFactory.create( - submission=submission.previous_submission, - status=AppointmentDetailsStatus.cancelled, - ) - # add a second step - SubmissionStepFactory.create( - submission=submission, - form_step__form=submission.form, - data={"foo": "bar"}, - ) - ConfirmationEmailTemplateFactory.create( - form=submission.form, - subject="Confirmation mail", - content="Information filled in: {{foo}}", - ) - - # "execute" the celery task - with override_settings(CELERY_TASK_ALWAYS_EAGER=True): - schedule_emails(submission.id) - - # Verify that email was sent - self.assertEqual(len(mail.outbox), 1) - - message = mail.outbox[0] - self.assertEqual(message.subject, f"Confirmation mail {_('(updated)')}") - def test_template_is_rendered_in_submission_language(self): """ Assert a subset of the components with particularly weird APIs is translated correctly.