diff --git a/README.md b/README.md index cb9a94b8..2bb9419d 100644 --- a/README.md +++ b/README.md @@ -71,7 +71,7 @@ The domains for giftaid are as follows To run PR Playwright Tests locally (after running `yarn playwright install` if you haven't previously), you need to first export `REACT_APP_ENDPOINT_URL=https://giftaid-sandbox.sls.comicrelief.com/` in your terminal for the form to get submitted and then run the script `test:playwright-local:local` found in package.json; this script starts the http://localhost:3000 server in the background, config for this is found in `playwright-local/playwright-local.config.js` file and runs the tests in headless mode. -To view a test in a headed mode locally, add `--headed` flag option to `"test:playwright-local:local": "playwright test --config=./playwright-local/playwright-local.config.js --project=chromium --headed"` script found in package.json. +To view a test in a _headed_ mode locally, use the according command; `test:playwright-local--h`. To run a single test, add `only` annotation diff --git a/playwright-local/tests/update/formValidation.spec.js b/playwright-local/tests/update/formValidation.spec.js index c8ad4eff..10dcc1b4 100644 --- a/playwright-local/tests/update/formValidation.spec.js +++ b/playwright-local/tests/update/formValidation.spec.js @@ -1,8 +1,8 @@ // @ts-check const { test, expect } = require('@playwright/test'); const { Commands } = require('../utils/commands'); -const { v4: uuidv4 } = require('uuid'); -const transactionId = uuidv4(); + +const email = `giftaid-staging-${Date.now().toString()}@email.sls.comicrelief.com`; test.describe('Giftaid update form validation', () => { @@ -16,9 +16,7 @@ test.describe('Giftaid update form validation', () => { // submit the form await page.locator('button[type=submit]').click(); - - await expect(page.locator('div#field-error--urlTransID > span')).toContainText('This transaction ID doesn\'t seem to be valid, please check your donation confirmation email or letter'); - await expect(page.locator('div#field-error--transactionId > span')).toContainText('Please fill in your transaction id'); + await expect(page.locator('div#field-error--firstname > span')).toContainText('Please fill in your first name'); await expect(page.locator('div#field-error--lastname > span')).toContainText('Please fill in your last name'); await expect(page.locator('div#field-error--postcode > span')).toContainText('Please enter your postcode'); @@ -31,40 +29,13 @@ test.describe('Giftaid update form validation', () => { // giftaid declaration error message await expect(page.locator('div#field-error--giftAidClaimChoice > span')).toContainText('This field is required'); + + // DonationType error message + await expect(page.locator('#field-error--donationType')).toContainText('This field is required'); await page.close(); }); - test('validate transaction ID field', async ({ page }) => { - - const commands = new Commands(page); - - await page.locator('input#field-input--transactionId').fill(transactionId); - await page.locator('input#field-input--transactionId').fill(''); - await expect(page.locator('div#field-error--transactionId > span')).toContainText('Please fill in your transaction id'); - - // transaction ID number with special characters should shows error message - await page.locator('input#field-input--transactionId').type('ea794dc3-35f8-4a87-bc94-14125fd480@$', {delay: 100}); - await page.waitForSelector('div#field-error--transactionId > span'); - await expect(page.locator('div#field-error--transactionId > span')).toContainText('This transaction ID doesn\'t seem to be valid, please check your donation confirmation email or letter'); - - // clear the transaction ID field and enter valid inputs and submit form - await page.locator('input#field-input--transactionId').fill(''); - - // entering valid input fields should be able to submit the form - await commands.populateUpdateFormFields(page); - - // select giftaid declaration - await page.locator('#giftAidClaimChoice>div:nth-child(2)>label').click(); - - // submit the form - await page.locator('button[type=submit]').click(); - - await expect(page.locator('div > h1')).toContainText('Thank you,\n' + - 'test!'); - - await page.close(); - }); test('validate first name field on giftaid update form', async ({ page }) => { @@ -93,7 +64,10 @@ test.describe('Giftaid update form validation', () => { // entering valid input fields should be able to submit the form await commands.populateUpdateFormFields(page); - + + // Select 'Online' donation type + await page.locator('#donationType>div:nth-child(3)>label').click(); + // select giftaid declaration await page.locator('#giftAidClaimChoice>div:nth-child(2)>label').click(); @@ -134,6 +108,9 @@ test.describe('Giftaid update form validation', () => { // entering valid input fields should be able to submit the form await commands.populateUpdateFormFields(page); + + // Select 'Online' donation type + await page.locator('#donationType>div:nth-child(3)>label').click(); // select giftaid declaration await page.locator('#giftAidClaimChoice>div:nth-child(2)>label').click(); @@ -182,10 +159,13 @@ test.describe('Giftaid update form validation', () => { // entering valid input fields should be able to submit the form await commands.populateUpdateFormFields(page); - + + // Select 'Online' donation type + await page.locator('#donationType>div:nth-child(3)>label').click(); + // select giftaid declaration await page.locator('#giftAidClaimChoice>div:nth-child(2)>label').click(); - + // submit the form await page.locator('button[type=submit]').click(); @@ -194,6 +174,38 @@ test.describe('Giftaid update form validation', () => { await page.close(); }); + + test('Validate mobile number field', async ({ page }) => { + const commands = new Commands(page); + + // Test cases for various mobile number validations + const mobileTestCases = [ + { input: '0712345678', error: 'Please enter a valid mobile phone number - it must be the same number associated with your donation.' }, + { input: '0712345678900', error: 'Please enter a valid mobile phone number - it must be the same number associated with your donation.' }, + { input: '0712 345 6789', error: 'Please enter a valid mobile phone number - it must be the same number associated with your donation.' }, + { input: '0780ab5694245', error: 'Please enter a valid mobile phone number - it must be the same number associated with your donation.' }, + ]; + + for (let testCase of mobileTestCases) { + await page.locator('#field-input--mobile').fill(''); // Clear the field before each test + await page.locator('#field-input--mobile').type(testCase.input, { delay: 100 }); + await expect(page.locator('div#field-error--mobile > span')).toHaveText(testCase.error); + } + + // Validate correct mobile number + await page.locator('#field-input--mobile').fill(''); // Ensure the field is cleared before filling with valid data + + await commands.populateUpdateFormFields(page); + + // Select yes for giftaid declaration to complete the form + await page.locator('#giftAidClaimChoice>div:nth-child(2)>label').click(); + + // Select 'Online' donation type + await page.locator('#donationType>div:nth-child(3)>label').click(); + + await page.locator('button[type=submit]').click(); + await expect(page.locator('div > h1')).toHaveText('Thank you, test!'); + }); test('postcode entered with extra spaces should show error message', async ({ page }) => { @@ -234,7 +246,6 @@ test.describe('Giftaid update form validation', () => { test('enter valid UK postcode on giftaid update form using postcode lookup should be able to submit the form', async ({ page }) => { // fill in all input fields - await page.locator('input#field-input--transactionId').fill(transactionId); await page.locator('#field-input--firstname').fill('test'); await page.locator('#field-input--lastname').fill('test lastname'); await page.locator('input#field-input--email').fill('giftaid-staging-@email.sls.comicrelief.com'); @@ -271,6 +282,9 @@ test.describe('Giftaid update form validation', () => { const town = await page.evaluate(() => document.querySelector('input#field-input--town').getAttribute('value')); console.log('Address line 1 field value is : ', town); + + // Select 'Online' donation type + await page.locator('#donationType>div:nth-child(3)>label').click(); // select giftaid declaration await page.locator('#giftAidClaimChoice>div:nth-child(2)>label').click(); @@ -288,6 +302,9 @@ test.describe('Giftaid update form validation', () => { await page.locator('#field-input--address2').type('CAMELFORD HOUSE 87-90'); await page.locator('#field-input--address3').type('ALBERT EMBANKMENT'); await page.locator('#field-input--town').type('LONDON'); + + // Select 'Online' donation type + await page.locator('#donationType>div:nth-child(3)>label').click(); // select giftaid declaration await page.locator('#giftAidClaimChoice>div:nth-child(2)>label').click(); diff --git a/playwright-local/tests/update/internationalAddressesValidation.spec.js b/playwright-local/tests/update/internationalAddressesValidation.spec.js index 0c58c187..a7f49fbe 100644 --- a/playwright-local/tests/update/internationalAddressesValidation.spec.js +++ b/playwright-local/tests/update/internationalAddressesValidation.spec.js @@ -1,7 +1,6 @@ // @ts-check const { test, expect } = require('@playwright/test'); const { v4: uuidv4 } = require('uuid'); -const transactionId = uuidv4(); test.describe('International addresses validation on update form', () => { test('selecting a non-UK country and entering a non-UK postcode should submit the update form', async ({ page }) => { @@ -11,7 +10,6 @@ test.describe('International addresses validation on update form', () => { await page.waitForLoadState('domcontentloaded'); /// fill in all input fields - await page.locator('input#field-input--transactionId').fill(transactionId); await page.locator('#field-input--firstname').fill('test'); await page.locator('#field-input--lastname').fill('test lastname'); await page.locator('input#field-input--email').fill('giftaid-staging-@email.sls.comicrelief.com'); @@ -42,6 +40,9 @@ test.describe('International addresses validation on update form', () => { // Select yes for giftaid declaration to complete the form await page.locator('#giftAidClaimChoice>div:nth-child(2)>label').click(); + + // Select 'Online' donation type + await page.locator('#donationType>div:nth-child(3)>label').click(); // Submitting the form with valid international details await page.locator('button[type=submit]').click(); diff --git a/playwright-local/tests/update/validFormSubmission.spec.js b/playwright-local/tests/update/validFormSubmission.spec.js index 03fa7ec2..a34b13b3 100644 --- a/playwright-local/tests/update/validFormSubmission.spec.js +++ b/playwright-local/tests/update/validFormSubmission.spec.js @@ -10,15 +10,15 @@ test('Valid Giftaid Update submission', async ({ page }) => { await page.waitForLoadState('domcontentloaded'); - // Ensure the transaction ID input is visible - await expect(page.locator('input#field-input--transactionId')).toBeVisible(); - // Populate all input fields with valid data await commands.populateUpdateFormFields(page); // Select 'Yes' for GiftAid declaration await page.locator('#giftAidClaimChoice>div:nth-child(2)>label').click(); + // Select 'Online' donation type + await page.locator('#donationType>div:nth-child(3)>label').click(); + // Submit the form and validate the thank you message await page.locator('button[type=submit]').click(); await expect(page.locator('div > h1')).toContainText('Thank you,\n' + diff --git a/playwright-local/tests/utils/commands.js b/playwright-local/tests/utils/commands.js index 000ce77d..516111e3 100644 --- a/playwright-local/tests/utils/commands.js +++ b/playwright-local/tests/utils/commands.js @@ -1,11 +1,9 @@ -const { v4: uuidv4 } = require('uuid'); const Chance = require('chance'); const chance = new Chance(); class Commands { constructor(page) { this.page = page; - this.transactionId = uuidv4(); } /** @@ -56,7 +54,6 @@ class Commands { * @param userData - Optional user data for form filling. */ async populateUpdateFormFields(page, { - transactionID = this.transactionId, firstName = 'test', lastName = chance.last(), email = `giftaid-update-staging-${chance.email()}`, @@ -65,9 +62,8 @@ class Commands { address2 = chance.street(), address3 = 'test address 3', town = chance.city(), + mobile = chance.phone({ country: 'uk', mobile: true }).replace(/\s/g, ''), // Remove spaces from the phone number } = {}) { - await page.locator('input#field-input--transactionId').fill(transactionID); - console.log('transactionId is:', transactionID); await page.locator('input#field-input--firstname').fill(firstName); await page.locator('input#field-input--lastname').fill(lastName); await page.locator('input#field-input--postcode').fill(postcode); @@ -77,6 +73,7 @@ class Commands { await page.locator('input#field-input--address2').fill(address2); await page.locator('input#field-input--address3').fill(address3); await page.locator('input#field-input--town').fill(town); + await page.locator('#field-input--mobile').type(mobile); } } diff --git a/playwright-staging/tests/update/formValidation.spec.js b/playwright-staging/tests/update/formValidation.spec.js index 4ccaf290..d6520009 100644 --- a/playwright-staging/tests/update/formValidation.spec.js +++ b/playwright-staging/tests/update/formValidation.spec.js @@ -7,14 +7,13 @@ const Chance = require('chance'); const chance = new Chance(); test.describe('Giftaid Update form validation @sanity @nightly-sanity', () => { - let commands, transactionId; + let commands; test.beforeEach(async ({ page }) => { - commands = new Commands(page); - transactionId = uuidv4(); // Ensure unique transaction ID for each test - + commands = new Commands(page); // Navigate to the Giftaid Update form - await page.goto(`${process.env.BASE_URL}update`, { waitUntil: 'networkidle' }); + await page.goto(`${process.env.BASE_URL}update`, { timeout: 30000 }); + await page.waitForLoadState('domcontentloaded'); }); test('empty input fields should show error messages', async ({ page }) => { @@ -22,44 +21,16 @@ test.describe('Giftaid Update form validation @sanity @nightly-sanity', () => { await page.click('button[type=submit]'); // Check for the error messages associated with each field - await expect(page.locator('div#field-error--transactionId > span')).toHaveText('Please fill in your transaction id'); + await expect(page.locator('div#field-error--donationType > span')).toHaveText('This field is required'); await expect(page.locator('div#field-error--firstname > span')).toHaveText('Please fill in your first name'); await expect(page.locator('div#field-error--lastname > span')).toHaveText('Please fill in your last name'); + await expect(page.locator('div#field-error--email > span')).toHaveText('Please fill in your email address'); await expect(page.locator('div#field-error--postcode > span')).toHaveText('Please enter your postcode'); await expect(page.locator('div#field-error--addressDetails > span')).toHaveText('Please fill in your address'); await expect(page.locator('div#field-error--giftAidClaimChoice > span')).toHaveText('This field is required'); await page.close(); }); - test('Validate transaction ID field', async ({ page }) => { - const commands = new Commands(page); - - // Test cases for various transaction ID validations - const transactionIDTestCases = [ - { input: '', error: 'Please fill in your transaction id' }, - { input: 'ea794dc3-35f8-4a87-bc94-14125fd480@$', error: 'This transaction ID doesn\'t seem to be valid, please check your donation confirmation email or letter' }, - { input: ' a0e9840d-b724-4868-9a68-06a86e0f0150 ', error: null } // Expects no error for valid input with spaces around it - ]; - - for (let testCase of transactionIDTestCases) { - await page.fill('input#field-input--transactionId', testCase.input); - await page.click('button[type=submit]'); // Trigger validation by attempting to submit the form - if (testCase.error) { - await expect(page.locator('div#field-error--transactionId > span')).toHaveText(testCase.error); - } else { - await expect(page.locator('div#field-error--transactionId > span')).toBeHidden(); - } - } - - // Enter a valid transaction ID and submit the form to validate successful submission - await page.fill('input#field-input--transactionId', ''); // clear the transaction field - await commands.populateUpdateFormFields(page); // populate giftaid update form - await page.locator('#giftAidClaimChoice>div:nth-child(2)>label').click(); // select giftaid declaration - await page.click('button[type=submit]'); // submit giftaid update form - await expect(page.locator('div > h1')).toHaveText('Thank you, test!'); - await page.close(); - }); - test('Validate first name field on Giftaid update form', async ({ page }) => { const commands = new Commands(page); @@ -80,8 +51,11 @@ test.describe('Giftaid Update form validation @sanity @nightly-sanity', () => { // Test for a valid first name await page.fill('#field-input--firstname', ''); // clear firstname field + await page.locator('.form__radio input[type="radio"][value="online"]').click(); await commands.populateUpdateFormFields(page, { firstName: 'John' }); await page.click('#giftAidClaimChoice>div:nth-child(2)>label'); // Select yes for declaration + // Select 'Online' donation type + await page.locator('#donationType>div:nth-child(3)>label').click(); await page.click('button[type=submit]'); // Submit the form await expect(page.locator('div > h1')).toHaveText('Thank you, John!'); @@ -115,6 +89,7 @@ test.describe('Giftaid Update form validation @sanity @nightly-sanity', () => { // Test for a valid email const validEmail = 'test@comicrelief.com'; await page.fill('input#field-input--email', ''); // clear email field + await page.locator('.form__radio input[type="radio"][value="sms"]').click(); await commands.populateUpdateFormFields(page, { email: validEmail }); await page.click('#giftAidClaimChoice>div:nth-child(3)>label'); // Select no for declaration await page.click('button[type=submit]'); // Submit the form @@ -123,6 +98,33 @@ test.describe('Giftaid Update form validation @sanity @nightly-sanity', () => { await page.close(); }); + test.only('Validate mobile number field on giftaid update form', async ({ page }) => { + const commands = new Commands(page); + + // Test cases for various mobile number validations + const mobileTestCases = [ + { input: '0712345678', error: 'Please enter a valid mobile phone number - it must be the same number associated with your donation.' }, + { input: '0712345678900', error: 'Please enter a valid mobile phone number - it must be the same number associated with your donation.' }, + { input: '0712 345 6789', error: 'Please enter a valid mobile phone number - it must be the same number associated with your donation.' }, + { input: '0780ab5694245', error: 'Please enter a valid mobile phone number - it must be the same number associated with your donation.' }, + ]; + + for (let testCase of mobileTestCases) { + await page.locator('#field-input--mobile').fill(''); // Clear the field before each test + await page.locator('#field-input--mobile').type(testCase.input, { delay: 100 }); + await expect(page.locator('div#field-error--mobile > span')).toHaveText(testCase.error); + } + + // Validate correct mobile number + await page.locator('#field-input--mobile').fill(''); // Ensure the field is cleared and filled with valid data + await page.locator('.form__radio input[type="radio"][value="call centre"]').click(); + await commands.populateUpdateFormFields(page, { mobile: '07123456789' }); + await page.click('#giftAidClaimChoice>div:nth-child(2)>label'); // Select yes for declaration + await page.click('button[type=submit]'); // Submit the form + + await expect(page.locator('div > h1')).toHaveText('Thank you, test!'); + }); + test('Postcode validation and form submission', async ({ page }) => { // Define postcodes and expected error messages const postcodes = [ @@ -160,12 +162,13 @@ test.describe('Giftaid Update form validation @sanity @nightly-sanity', () => { await page.click('button[type=submit]'); } - await page.locator('input#field-input--transactionId').fill(transactionId); await page.locator('input#field-input--firstname').fill('test'); await page.locator('input#field-input--lastname').fill(chance.last()); await page.locator('input#field-input--email').fill(`giftaid-update-staging-${chance.email()}`); await page.fill('input#field-input--postcode', 'SE1 7TP'); await page.click('#giftAidClaimChoice>div:nth-child(2)>label'); // Select yes for declaration + // Select 'Online' donation type + await page.locator('#donationType>div:nth-child(3)>label').click(); await page.click('button[type=submit]'); // Submit the form await expect(page.locator('div > h1')).toHaveText('Thank you, test!'); diff --git a/playwright-staging/tests/update/giftaidDeclarationOptions.spec.js b/playwright-staging/tests/update/giftaidDeclarationOptions.spec.js index 45c8139d..c29d045e 100644 --- a/playwright-staging/tests/update/giftaidDeclarationOptions.spec.js +++ b/playwright-staging/tests/update/giftaidDeclarationOptions.spec.js @@ -8,9 +8,6 @@ test('Validate Giftaid declaration claim selections @sanity @nightly-sanity', as await page.goto(process.env.BASE_URL + 'update', { timeout: 30000 }); await page.waitForLoadState('domcontentloaded'); - // Ensure transaction ID field is visible as expected - await expect(page.locator('input#field-input--transactionId')).toBeVisible(); - // Populate fields and submit the form to get to the Giftaid declaration part await commands.populateUpdateFormFields(page); await page.locator('button[type=submit]').click(); @@ -24,6 +21,11 @@ test('Validate Giftaid declaration claim selections @sanity @nightly-sanity', as await page.locator('#giftAidClaimChoice>div:nth-child(3)>label').click(); expect(await page.locator('#giftAidClaimChoice>div:nth-child(3)>input').isChecked()).toBeTruthy(); expect(await page.locator('#giftAidClaimChoice>div:nth-child(2)>input').isChecked()).toBeFalsy(); + + // Select 'Online' donation type + await page.locator('#donationType>div:nth-child(3)>label').click(); + expect(await page.locator('#donationType>div:nth-child(3)>input').isChecked()).toBeTruthy(); + expect(await page.locator('#donationType>div:nth-child(2)>input').isChecked()).toBeFalsy(); await page.locator('button[type=submit]').click(); await expect(page.locator('div > h1')).toHaveText('Thanks for letting us know'); diff --git a/playwright-staging/tests/update/internationalAddressesValidation.spec.js b/playwright-staging/tests/update/internationalAddressesValidation.spec.js index af67b815..eafc456e 100644 --- a/playwright-staging/tests/update/internationalAddressesValidation.spec.js +++ b/playwright-staging/tests/update/internationalAddressesValidation.spec.js @@ -2,16 +2,16 @@ const { expect } = require('@playwright/test'); const { test } = require('../../browserstack'); const { v4: uuidv4 } = require('uuid'); -const transactionId = uuidv4(); test.describe('International addresses validation on update form @sanity @nightly-sanity', () => { test('selecting a non-UK country and entering a non-UK postcode should submit the update form', async ({ page }) => { await page.goto(process.env.BASE_URL + 'update', { timeout: 30000 }); await page.waitForLoadState('domcontentloaded'); + await page.locator('.form__radio input[type="radio"][value="call centre"]').click(); // fill in all input fields - await page.locator('input#field-input--transactionId').fill(transactionId); + // await page.locator('input#field-input--transactionId').fill(transactionId); await page.locator('#field-input--firstname').fill('test'); await page.locator('#field-input--lastname').fill('test lastname'); await page.locator('input#field-input--email').fill('giftaid-staging-@email.sls.comicrelief.com'); diff --git a/playwright-staging/tests/update/updateSuccessRedirect.spec.js b/playwright-staging/tests/update/updateSuccessRedirect.spec.js index 237f76c8..098bb7b0 100644 --- a/playwright-staging/tests/update/updateSuccessRedirect.spec.js +++ b/playwright-staging/tests/update/updateSuccessRedirect.spec.js @@ -12,10 +12,6 @@ test.describe('Success page redirect @sanity @nightly-sanity', () => { const pageTitle = await page.locator('h1[class="giftaid-title"]').textContent(); expect(pageTitle).toContain('Giftaid it'); - // Verify that the transaction ID input is visible - const transactionIdInputVisible = await page.locator('input#field-input--transactionId').isVisible(); - expect(transactionIdInputVisible).toBeTruthy(); - await page.close(); }); }); diff --git a/playwright-staging/tests/update/validFormSubmission.spec.js b/playwright-staging/tests/update/validFormSubmission.spec.js index 199e5279..bd7b9938 100644 --- a/playwright-staging/tests/update/validFormSubmission.spec.js +++ b/playwright-staging/tests/update/validFormSubmission.spec.js @@ -10,14 +10,14 @@ test('Valid giftaid update submission @sanity @nightly-sanity', async ({ page }) await page.goto(`${process.env.BASE_URL}update`, { timeout: 30000 }); await page.waitForLoadState('domcontentloaded'); - // Ensure the transaction ID input is visible - await expect(page.locator('input#field-input--transactionId')).toBeVisible(); - // Populate all input fields with valid data await commands.populateUpdateFormFields(page); // Select 'Yes' for GiftAid declaration await page.locator('#giftAidClaimChoice>div:nth-child(2)>label').click(); + + // Select 'Online' donation type + await page.locator('#donationType>div:nth-child(3)>label').click(); // Submit the form and validate the thank you message await page.locator('button[type=submit]').click(); diff --git a/playwright-staging/tests/utils/commands.js b/playwright-staging/tests/utils/commands.js index ff2fdc92..08ef6bf7 100644 --- a/playwright-staging/tests/utils/commands.js +++ b/playwright-staging/tests/utils/commands.js @@ -1,11 +1,9 @@ -const { v4: uuidv4 } = require('uuid'); const Chance = require('chance'); const chance = new Chance(); class Commands { constructor(page) { this.page = page; - this.transactionId = uuidv4(); } /** @@ -56,22 +54,21 @@ class Commands { * @param userData - Optional user data for form filling. */ async populateUpdateFormFields(page, { - transactionID = this.transactionId, firstName = 'test', lastName = chance.last(), email = `giftaid-update-staging-${chance.email()}`, + mobile = '07123456789', postcode = chance.postcode(), address1 = chance.address(), address2 = chance.street(), address3 = 'test address 3', town = chance.city(), } = {}) { - await page.locator('input#field-input--transactionId').fill(transactionID); - console.log('transactionId is:', transactionID); await page.locator('input#field-input--firstname').fill(firstName); await page.locator('input#field-input--lastname').fill(lastName); await page.locator('input#field-input--postcode').fill(postcode); await page.locator('input#field-input--email').fill(email); + await page.locator('#field-input--mobile').fill(mobile); await page.locator('a[aria-describedby=field-error--addressDetails]').click(); await page.locator('input#field-input--address1').fill(address1); await page.locator('input#field-input--address2').fill(address2); diff --git a/src/components/App/App.js b/src/components/App/App.js index 9449947d..87553355 100644 --- a/src/components/App/App.js +++ b/src/components/App/App.js @@ -128,11 +128,7 @@ function App(props) { path='/update/sorry' render={(props) => } /> - + diff --git a/src/components/Buttons/DonationTypeButtons/DonationTypeButtons.js b/src/components/Buttons/DonationTypeButtons/DonationTypeButtons.js index 4d7e8769..f8413034 100644 --- a/src/components/Buttons/DonationTypeButtons/DonationTypeButtons.js +++ b/src/components/Buttons/DonationTypeButtons/DonationTypeButtons.js @@ -7,13 +7,11 @@ const DonationTypeButtons = (props) => { // initialise context const { - urlTransactionId, formValidityState, refs, setFieldValidity, } = useContext(FormContext); // get props from context - if (urlTransactionId) { return (

@@ -32,8 +30,6 @@ const DonationTypeButtons = (props) => { />

); - } - return null; }; export default DonationTypeButtons; diff --git a/src/components/FormHeader/UpdateHeader/index.js b/src/components/FormHeader/UpdateHeader/index.js index 5171cbdd..575bc179 100644 --- a/src/components/FormHeader/UpdateHeader/index.js +++ b/src/components/FormHeader/UpdateHeader/index.js @@ -1,11 +1,9 @@ import React, { useContext } from 'react'; -import FormContext from "../../../context/FormContext"; import SiteService from '../../../service/Site.service'; const UpdateHeader = (props) => { - - const { urlTransactionId } = useContext(FormContext); // get states from context + const site = new SiteService(); let claimCopy = null; switch(site.getSite()) { @@ -25,13 +23,6 @@ const UpdateHeader = (props) => {

{claimCopy}

- {typeof urlTransactionId !== 'undefined' && urlTransactionId !== null ? -

- Transaction ID: {urlTransactionId} -

- : - '' - } ); diff --git a/src/pages/GiftAid/GiftAid.js b/src/pages/GiftAid/GiftAid.js index a9727751..f8c0f71d 100644 --- a/src/pages/GiftAid/GiftAid.js +++ b/src/pages/GiftAid/GiftAid.js @@ -32,11 +32,11 @@ function GiftAid(props) { const { setIsCompleted, setSuccessState } = useContext(AppContext); // Declare states - const update = props.location.pathname.includes("update"); // initialise updating param state - const [updating, setUpdating] = useState(update); // set to true if path contains the string update + const isUpdate = props.location.pathname.includes("update"); // initialise updating param state + const [isUpdateForm, setIsUpdateForm] = useState(isUpdate); // set to true if path contains the string update const [pathParams, setPathParams] = useState({}); // initialise submit path param state const [formValidityState, setFormValidityState] = useState(initialFormValidity); // intitialise form validity states - const [fieldValidation, setFieldValidation] = useState(getFieldValidations(update)); // intitialise field validation state based on form type + const [fieldValidation, setFieldValidation] = useState(getFieldValidations(isUpdate)); // intitialise field validation state based on form type const [isSubmitting, setIsSubmitting] = useState(false); const inputRef = useRef(null); @@ -46,16 +46,12 @@ function GiftAid(props) { // initialise MSISDN state const [msisdn, setMSISDN] = useState(null); - // initialise URL transaction id state if available - const [urlTransactionId, setUrlTransactionId] = useState(props.match.params.transaction_id); - /** * GiftAid component mounts */ useEffect(() => { - setPathParams(getPathParams(updating)); // update path states + setPathParams(getPathParams(isUpdateForm)); // update path states setToken(props.match.params.token); // update token state - setUrlTransactionId(props.match.params.transaction_id); // update url transaction id state if (token) { decryptToken(token); // decrypt token to MSISDN } @@ -64,8 +60,7 @@ function GiftAid(props) { // reset states setFormValidityState(initialFormValidity); setFieldValidation({}); - setUpdating(false); - setUrlTransactionId(null); + setIsUpdateForm(false); setToken(null); setMSISDN(null); } @@ -93,8 +88,7 @@ function GiftAid(props) { */ useEffect(() => { // Update validation accordingly on update - if ((formValidityState.showErrorMessages && !formValidityState.formValidity - && formValidityState.validating) || formValidityState.urlTransactionId.valid === false ) { + if ((formValidityState.showErrorMessages && !formValidityState.formValidity && formValidityState.validating)) { // update validation state setFormValidityState({ ...formValidityState, @@ -120,17 +114,21 @@ function GiftAid(props) { (thisFieldsState.fieldValidation !== thisFieldsPreviousState.fieldValidation); if ((thisFieldsPreviousState && isUpdatedState) || marketingConsentFieldsChanged === true) { - // Reset url transaction Id state - if (thisFieldsName === 'transactionId' && thisFieldsState.valid) { - setFormValidityState({ - ...formValidityState, - urlTransactionId: { - ...formValidityState.urlTransactionId, - valid: true, - } - }); - } fieldValidation[thisFieldsName] = thisFieldsState; + + // Currently, on mount, each field's current 'valid' value is an empty string, rather than the boolean value it SHOULD be. + // + // Long story short, if the field isn't interacted with (like our optional Mobile field here potentially), it means the whole + // form validation check fails due to that empty string. + // + // Additionally, there's an issue around non-required fields. We do actually set the appropriate config in SubmitFormFields and + // UpdateFormFields, but it's not being used at all for reasons I haven't uncovered yet, very helpfully doing nothing with the 'required' flag. + // + // This short-term fix below effectively shortcircuits the validation for our non-required 'mobile' UpdateForm field when it's empty: + if (isUpdate && thisFieldsName === 'mobile' && thisFieldsState.value === '' ) { + fieldValidation[thisFieldsName].valid = true; + } + setFieldValidation({...fieldValidation}); return { @@ -146,7 +144,7 @@ function GiftAid(props) { */ const submitForm = (e) => { e.preventDefault(); - const formValues = getFormValues(fieldValidation, urlTransactionId, updating); // get form values + const formValues = getFormValues(fieldValidation); // get form values const { validity, validationState } = validateForm(fieldValidation, formValues, formValidityState); // validate form setFormValidityState(validationState); // update form validation state @@ -154,9 +152,7 @@ function GiftAid(props) { setIsSubmitting(true); // Update state that's passed down to disable button during submission // Rather than mess with the input field value itself (crummy UX), just sanitise the value on submission, // removing any leading or trailing whitespace that the new regex brings allows for (see ENG-3193) - if (formValues.donationID) formValues.donationID = formValues.donationID.trim(); - if (formValues.transactionId) formValues.transactionId = formValues.transactionId.trim(); - + axios.post(pathParams.endpoint, formValues) // post form data and settings to endpoint .then(() => { setIsCompleted(true); // set completed state @@ -184,7 +180,6 @@ function GiftAid(props) { // Pass context props to child components const contextProps = { - urlTransactionId, hiddenFields, justInTimeLinkText, formValidityState, @@ -199,10 +194,9 @@ function GiftAid(props) { return ( - { updating ? ( + { isUpdateForm ? ( ) : ( { - // Delete if url trans Id if present - // on component mount or update - if (urlTransactionId !== undefined) { - // Delete transactionId form field - delete inputFieldProps.transactionId; - delete fieldValidation.transactionId; - } else { - // Else, delete the donation type radiobuttons - delete fieldValidation.donationType; - } setFieldValidation(fieldValidation); // Reset states on component unmount + + // ADDING THIS EVERYWHERE TO /UPDATE NOW SO DON'T DELETE IT + // delete fieldValidation.donationType; return () => { setInputFieldProps([]); } @@ -65,8 +54,6 @@ function UpdateForm(props) { - -
diff --git a/src/pages/GiftAid/UpdateForm/UpdateFormFields.js b/src/pages/GiftAid/UpdateForm/UpdateFormFields.js index bd270d91..858fb84d 100644 --- a/src/pages/GiftAid/UpdateForm/UpdateFormFields.js +++ b/src/pages/GiftAid/UpdateForm/UpdateFormFields.js @@ -53,17 +53,7 @@ export const giftAidButtonChoices = [ * Default Update Form Fields */ export const updateFormFields = { - - transactionId: { - id: 'transactionId', - type: 'text', - name: 'transactionId', - label: 'Transaction ID', - required: true, - invalidErrorText: 'This transaction ID doesn\'t seem to be valid, please check your donation confirmation email or letter', - pattern: '^\\s*[a-zA-Z0-9-_]{5,}\\s*$', - tooltip: 'This is found at the bottom of your donation confirmation email' - }, + firstName: { id: 'firstname', type: 'text', @@ -86,7 +76,20 @@ export const updateFormFields = { id: 'email', type: 'email', name: 'email', - label: 'Email address', + required: true, + label: 'Email address' + }, + mobile: { + id: 'mobile', + type: 'tel', + name: 'mobile', + placeholder: 'In the format 07123456789', + label: 'Mobile number', required: false, + pattern: '^07[0-9]{9}$', // Matches the validation in the main 'submit' form + helpText: 'Enter the one associated with your donation', + emptyFieldErrorText: 'Please fill in your mobile number', + invalidErrorText: 'Please enter a valid mobile phone number - it must be the same number associated with your donation.', + additionalText: 'Please note: if you donated via SMS, we DO require your number here, in order to match it to this submission.', } }; diff --git a/src/pages/GiftAid/utils/Utils.js b/src/pages/GiftAid/utils/Utils.js index d21a5f71..2a19232d 100644 --- a/src/pages/GiftAid/utils/Utils.js +++ b/src/pages/GiftAid/utils/Utils.js @@ -11,11 +11,6 @@ const ENDPOINT_URL = process.env.REACT_APP_ENDPOINT_URL; * @param state Object */ export const scrollToError = (state = {}) => { - // Scroll to transactionId field / url parameter error message - // if present - if (state.urlTransactionId.valid === false) { - document.querySelector('#field-error--urlTransID').scrollIntoView({ behavior: 'smooth' }); - } // Scroll to the first erroring field and focus on its input field const errorWrapper = document.querySelectorAll('.form__field--erroring')[0]; if (errorWrapper) { @@ -38,6 +33,7 @@ export const mergeInputFieldProps = (defaultInputFieldsProps, props) => { Object.entries(overrides).forEach(([key]) => { Object.assign(inputFields[key], overrides[key]); }); + return inputFields; }; @@ -63,7 +59,7 @@ export const getPathParams = (update = false) => { * @param urlId String - url Transaction Id * @param update Boolean - Form type */ -export const getFormValues = (validation, urlId = null, update = false) => { +export const getFormValues = (validation, update = false) => { // create field values const fieldValues = {}; @@ -89,17 +85,9 @@ export const getFormValues = (validation, urlId = null, update = false) => { return fieldValues[key] = value; }); - // Create a Donation id field for Update Form - if ((typeof validation.transactionId !== 'undefined' && validation.transactionId) || urlId !== null) { - - fieldValues.donationID = typeof validation.transactionId !== 'undefined' - && validation.transactionId - ? validation.transactionId.value : urlId; - } - // Create donation type field for Update Form fieldValues.donationType = typeof validation.donationType !== 'undefined' - && validation.donationType + && validation.donationType ? validation.donationType.value : DONATION_TYPES.ONLINE; // Create name based on Form type @@ -144,12 +132,6 @@ export const hiddenFields = ['field-input--address1', 'field-input--town', 'fiel */ export const justInTimeLinkText = 'Why do we collect this info?'; -/* -* REGEX for transactionId -* -*/ -const transactionIdPattern = '^\\s*[a-zA-Z0-9-_]{5,}\\s*$'; - /** * Function to validate form * @param validation Object @@ -159,11 +141,6 @@ const transactionIdPattern = '^\\s*[a-zA-Z0-9-_]{5,}\\s*$'; */ export const validateForm = (validation, formValues = {}, formValidity = {}) => { - const donationId = formValues.donationID !== undefined ? formValues.donationID : null; - - // validate donation id if present - const transIdValidity = donationId !== null ? validateTransactionId(donationId) : null; - // validate form fields const fieldValidity = getValidation(validation); @@ -172,13 +149,10 @@ export const validateForm = (validation, formValues = {}, formValidity = {}) => formValidity: true, showErrorMessages: false, validating: false, - urlTransactionId: { - ...formValidity.urlTransactionId, - valid: true, - } }; - // Validation fails for fields or transactionId - if (fieldValidity !== true || (transIdValidity !== true && transIdValidity !== null) ) { + + // Validation fails for fields + if (fieldValidity !== true) { // set failed fields state validationState = { @@ -187,16 +161,9 @@ export const validateForm = (validation, formValues = {}, formValidity = {}) => showErrorMessages: true, validating: true, }; - if (transIdValidity !== null && !transIdValidity && donationId !== undefined && donationId !== null) { - - // set transaction id failed state - validationState.urlTransactionId = { - ...formValidity.urlTransactionId, - valid: false, - } - } } const email = formValues.email && formValues.email !== "" ? formValues.email : 'N'; + TagManager.dataLayer({ dataLayer: { user: { @@ -206,19 +173,11 @@ export const validateForm = (validation, formValues = {}, formValidity = {}) => }, }); return { - validity: fieldValidity && (transIdValidity === null || transIdValidity), + validity: fieldValidity, validationState, }; }; -/** - * Validates transactionId using REGEX pattern - * @param donationID - * @returns Boolean - */ -const validateTransactionId = (donationID) => new RegExp(transactionIdPattern).test(donationID); - - /** * Checks if any field is invalid. * If invalid fields: shows error sets state to show errorMessages. @@ -229,19 +188,13 @@ const getValidation = (validation) => { let validity = true; let thisField; - Object.keys(validation).map((key) => { - + for (const [key] of Object.entries(validation)) { thisField = validation[key]; - /** - * As we're not passing any 'required' flags to this function, a quick fix to wave our - * optional email field through, but only if it's valid or empty - */ - if (thisField.valid !== true && ( key !== 'email' || thisField.showErrorMessage === true )) { + if (thisField.valid !== true || thisField.showErrorMessage === true) { validity = false; } - return true; - }); + }; return validity; }; @@ -254,10 +207,6 @@ export const initialFormValidity = { showErrorMessages: false, formDataError: null, formDataSuccess: null, - urlTransactionId: { - valid: true, - errorMessage: 'This transaction ID doesn\'t seem to be valid, please check your donation confirmation email or letter' - } }; /** @@ -371,7 +320,7 @@ export const defaultUpdateFormFieldValidations = { message: '', }, email: { - valid: true, + valid: false, value: undefined, message: '', }, @@ -415,8 +364,8 @@ export const defaultUpdateFormFieldValidations = { value: undefined, message: '', }, - transactionId: { - valid: false, + mobile: { + valid: true, value: undefined, message: '', }, @@ -426,9 +375,3 @@ export const defaultUpdateFormFieldValidations = { export const getRoute = (route) => { return `${process.env.REACT_APP_ENDPOINT_URL}${route}`; }; - - - - - - diff --git a/src/styles/UpdateForm.scss b/src/styles/UpdateForm.scss index 078c4f27..796477d0 100644 --- a/src/styles/UpdateForm.scss +++ b/src/styles/UpdateForm.scss @@ -1,5 +1,6 @@ $colour-dove-grey: #666666; $colour-scorpion-grey: #595959; +$color-cr-red: #e52630; .update-giftaid__form { @include container; @@ -69,6 +70,13 @@ $colour-scorpion-grey: #595959; font-family:$font-bold; } } + + #field-wrapper--mobile { + .form__field-additional-text { + color: $color-cr-red; + font-size: 14px; + } + } } .form__field-additional-text { @@ -127,10 +135,6 @@ button[type="submit"].btn.btn--red { margin: 40px 0; } -.transaction-id { - color: $colour-scorpion-grey; -} - .form--update__title { margin: 60px 0 25px; } @@ -225,5 +229,4 @@ textarea { height:19px; } } - }