From 5fdec1c5e174dbb69838d90f93326f5ea577149c Mon Sep 17 00:00:00 2001
From: Tore Brede <Tore.Brede@uib.no>
Date: Tue, 15 Mar 2022 17:48:52 +0100
Subject: [PATCH] GREG-233: Prohibiting user form continuing with invalid phone
 number

---
 .../guest/register/steps/register.test.tsx    | 108 ++++++++++++++++++
 .../routes/guest/register/steps/register.tsx  |  35 +++++-
 2 files changed, 137 insertions(+), 6 deletions(-)

diff --git a/frontend/src/routes/guest/register/steps/register.test.tsx b/frontend/src/routes/guest/register/steps/register.test.tsx
index bb090e97..dfecd65c 100644
--- a/frontend/src/routes/guest/register/steps/register.test.tsx
+++ b/frontend/src/routes/guest/register/steps/register.test.tsx
@@ -288,3 +288,111 @@ test('Gender not required to be set if gender field is not showing', async () =>
     }
   )
 })
+
+test('Guest not allowed to proceed in wizard if phone number is not valid', async () => {
+  const nextHandler = jest.fn()
+
+  const allFeaturesOn = {
+    displayContactAtUnit: true,
+    displayComment: true,
+    displayContactAtUnitGuestInput: true,
+    showGenderFieldForGuest: true,
+  }
+
+  const formData: GuestRegisterData = {
+    firstName: 'Test',
+    lastName: 'Test2',
+    mobilePhoneCountry: 'NO',
+    mobilePhone: '50',
+    nationalIdNumber: '',
+    passportNumber: '12345678',
+    passportNationality: 'NO',
+    dateOfBirth: addYears(-20)(new Date()),
+    gender: 'male',
+  }
+
+  const testData = getEmptyGuestData()
+  testData.gender = 'male'
+  const submitMock = jest.fn()
+
+  // Need this to be able to call on the submit-method on the form
+  const reference = {
+    current: {
+      doSubmit: submitMock,
+    },
+  }
+
+  render(
+    <FeatureContext.Provider value={allFeaturesOn}>
+      <LocalizationProvider dateAdapter={AdapterDateFns}>
+        <GuestRegisterStep
+          nextHandler={nextHandler}
+          initialGuestData={testData}
+          registerData={formData}
+          ref={reference}
+        />
+      </LocalizationProvider>
+    </FeatureContext.Provider>
+  )
+
+  reference.current?.doSubmit()
+
+  // TODO It is stupid to wait like this, but I have not found a wait-for function in jest
+  await new Promise((r) => setTimeout(r, 500))
+
+  expect(nextHandler.mock.calls.length).toBe(0)
+})
+
+test('Guest allowed to proceed in wizard if data is valid', async () => {
+  const nextHandler = jest.fn()
+
+  const allFeaturesOn = {
+    displayContactAtUnit: true,
+    displayComment: true,
+    displayContactAtUnitGuestInput: true,
+    showGenderFieldForGuest: true,
+  }
+
+  const formData: GuestRegisterData = {
+    firstName: 'Test',
+    lastName: 'Test2',
+    mobilePhoneCountry: 'NO',
+    mobilePhone: '97543992',
+    nationalIdNumber: '',
+    passportNumber: '12345678',
+    passportNationality: 'NO',
+    dateOfBirth: addYears(-20)(new Date()),
+    gender: 'male',
+  }
+
+  const testData = getEmptyGuestData()
+  testData.gender = 'male'
+  const submitMock = jest.fn()
+
+  // Need this to be able to call on the submit-method on the form
+  const reference = {
+    current: {
+      doSubmit: submitMock,
+    },
+  }
+
+  render(
+    <FeatureContext.Provider value={allFeaturesOn}>
+      <LocalizationProvider dateAdapter={AdapterDateFns}>
+        <GuestRegisterStep
+          nextHandler={nextHandler}
+          initialGuestData={testData}
+          registerData={formData}
+          ref={reference}
+        />
+      </LocalizationProvider>
+    </FeatureContext.Provider>
+  )
+
+  reference.current?.doSubmit()
+
+  // TODO It is stupid to wait like this, but I have not found a wait-for function in jest
+  await new Promise((r) => setTimeout(r, 500))
+
+  expect(nextHandler.mock.calls.length).toBe(1)
+})
diff --git a/frontend/src/routes/guest/register/steps/register.tsx b/frontend/src/routes/guest/register/steps/register.tsx
index c14ad288..5463e401 100644
--- a/frontend/src/routes/guest/register/steps/register.tsx
+++ b/frontend/src/routes/guest/register/steps/register.tsx
@@ -108,6 +108,16 @@ const GuestRegisterStep = forwardRef(
       }
     }
 
+    const validatePhoneNumber = (
+      countryCodeCallingCode: CountryCallingCode | undefined,
+      phoneNumberToValidate: string
+    ) => {
+      const phoneNumberWithCountryCode = `+${getCountryCallingCode(
+        countryCodeCallingCode as CountryCode
+      )}${phoneNumberToValidate}`
+      return isValidMobilePhoneNumber(phoneNumberWithCountryCode)
+    }
+
     const submit: SubmitHandler<GuestRegisterData> = async (data) => {
       console.log('submit data is', data)
       const result = await trigger()
@@ -122,6 +132,22 @@ const GuestRegisterStep = forwardRef(
       // Phone checks passed, clear error message
       setPhoneErrorState('')
 
+      // Because the phone number validation is handled outside the hook form validation
+      // it is necessary to do another pass here to make sure the phone number entered
+      // really is valid
+      const validationMessage = validatePhoneNumber(
+        countryCode,
+        data.mobilePhone
+      )
+
+      if (validationMessage !== true) {
+        setError('mobilePhone', {
+          type: 'manual',
+          message: validationMessage || undefined,
+        })
+        return
+      }
+
       if (
         !data.nationalIdNumber &&
         !data.passportNumber &&
@@ -196,12 +222,9 @@ const GuestRegisterStep = forwardRef(
         // The country code and the rest of the mobile number are in two fields, so cannot
         // register the field directly in form, but need to have extra logic defined
         // to combine the values before writing them to the form handling
-
-        const phoneNumberWithCountryCode = `+${getCountryCallingCode(
-          countryCode as CountryCode
-        )}${value.target.value}`
-        const isValidPhoneNumber = isValidMobilePhoneNumber(
-          phoneNumberWithCountryCode
+        const isValidPhoneNumber = validatePhoneNumber(
+          countryCode,
+          value.target.value
         )
 
         if (isValidPhoneNumber === true) {
-- 
GitLab