From c2040c8539c9f461c70d03391ad8d3edf654ffcf Mon Sep 17 00:00:00 2001 From: nicholas Date: Fri, 22 Nov 2024 17:26:12 +0100 Subject: [PATCH 1/8] Confirming that .fill triggers required events in SF --- .../panLength/panLength.focus.kcp.spec.ts | 19 ++----- .../panLength/panLength.focus.regular.spec.ts | 28 ++++++----- .../binLookup/plcc/plcc.luhn.paste.spec.ts | 50 +++++++++++++++++++ .../unsupported.card.number.spec.ts | 47 ++++++++++++++++- .../e2e-playwright/tests/utils/constants.ts | 3 +- .../internal/SecuredFields/lib/constants.ts | 2 +- .../storybook/stories/cards/Card.stories.tsx | 2 +- 7 files changed, 120 insertions(+), 31 deletions(-) create mode 100644 packages/e2e-playwright/tests/ui/card/binLookup/plcc/plcc.luhn.paste.spec.ts diff --git a/packages/e2e-playwright/tests/ui/card/binLookup/panLength/panLength.focus.kcp.spec.ts b/packages/e2e-playwright/tests/ui/card/binLookup/panLength/panLength.focus.kcp.spec.ts index 5ea9ced85..3f6806a83 100644 --- a/packages/e2e-playwright/tests/ui/card/binLookup/panLength/panLength.focus.kcp.spec.ts +++ b/packages/e2e-playwright/tests/ui/card/binLookup/panLength/panLength.focus.kcp.spec.ts @@ -3,7 +3,7 @@ import { getStoryUrl } from '../../../../utils/getStoryUrl'; import { URL_MAP } from '../../../../../fixtures/URL_MAP'; import { binLookupMock } from '../../../../../mocks/binLookup/binLookup.mock'; import { kcpMockOptionalDateAndCvcWithPanLengthMock } from '../../../../../mocks/binLookup/binLookup.data'; -import { REGULAR_TEST_CARD } from '../../../../utils/constants'; +import { CARD_WITH_PAN_LENGTH, REGULAR_TEST_CARD } from '../../../../utils/constants'; const componentConfig = { brands: ['mc', 'visa', 'amex', 'korean_local_card'], @@ -30,24 +30,15 @@ test.describe('Test how Card Component handles binLookup returning a panLength p }); test('#2 Paste non KCP PAN and see focus move to date field', async ({ cardWithKCP, page, browserName }) => { - test.skip(browserName === 'webkit', 'This test is not run for Safari because it always fails on the CI due to the "pasting"'); + // test.skip(browserName === 'webkit', 'This test is not run for Safari because it always fails on the CI due to the "pasting"'); await cardWithKCP.goto(getStoryUrl({ baseUrl: URL_MAP.card, componentConfig })); await cardWithKCP.isComponentVisible(); - // Place focus on the input - await cardWithKCP.cardNumberLabelElement.click(); - - // Copy text to clipboard - await page.evaluate(() => navigator.clipboard.writeText('4000620000000007')); // Can't use the constant for some reason - - await page.waitForTimeout(1000); - - // Paste text from clipboard - await page.keyboard.press('ControlOrMeta+V'); - - await page.waitForTimeout(1000); + // "Paste" number + await cardWithKCP.fillCardNumber(CARD_WITH_PAN_LENGTH); + await page.waitForTimeout(100); // Expect UI change - expiryDate field has focus await expect(cardWithKCP.cardNumberInput).not.toBeFocused(); diff --git a/packages/e2e-playwright/tests/ui/card/binLookup/panLength/panLength.focus.regular.spec.ts b/packages/e2e-playwright/tests/ui/card/binLookup/panLength/panLength.focus.regular.spec.ts index 3b80c2719..c80821857 100644 --- a/packages/e2e-playwright/tests/ui/card/binLookup/panLength/panLength.focus.regular.spec.ts +++ b/packages/e2e-playwright/tests/ui/card/binLookup/panLength/panLength.focus.regular.spec.ts @@ -118,24 +118,26 @@ test.describe('Test Card, & binLookup w. panLength property', () => { }); test('#6 Fill out PAN by **pasting** number & see that that focus moves to expiryDate', async ({ card, page, browserName }) => { - test.skip(browserName === 'webkit', 'This test is not run for Safari because it always fails on the CI due to the "pasting"'); - await card.goto(URL_MAP.card); await card.isComponentVisible(); // Place focus on the input - await card.cardNumberLabelElement.click(); - - // Copy text to clipboard - await page.evaluate(() => navigator.clipboard.writeText('4000620000000007')); // Can't use the constant for some reason - - await page.waitForTimeout(1000); - - // Paste text from clipboard - await page.keyboard.press('ControlOrMeta+V'); - - await page.waitForTimeout(1000); + // await card.cardNumberLabelElement.click(); + // + // // Copy text to clipboard + // await page.evaluate(() => navigator.clipboard.writeText('4000620000000007')); // Can't use the constant for some reason + // + // await page.waitForTimeout(1000); + // + // // Paste text from clipboard + // await page.keyboard.press('ControlOrMeta+V'); + // + // await page.waitForTimeout(1000); + + // "Paste" number + await card.fillCardNumber(CARD_WITH_PAN_LENGTH); + await page.waitForTimeout(100); // Expect UI change - expiryDate field has focus await expect(card.cardNumberInput).not.toBeFocused(); diff --git a/packages/e2e-playwright/tests/ui/card/binLookup/plcc/plcc.luhn.paste.spec.ts b/packages/e2e-playwright/tests/ui/card/binLookup/plcc/plcc.luhn.paste.spec.ts new file mode 100644 index 000000000..60fda1e02 --- /dev/null +++ b/packages/e2e-playwright/tests/ui/card/binLookup/plcc/plcc.luhn.paste.spec.ts @@ -0,0 +1,50 @@ +import { test, expect } from '../../../../../fixtures/card.fixture'; +import { getStoryUrl } from '../../../../utils/getStoryUrl'; +import { PLCC_NO_LUHN_NO_DATE, PLCC_WITH_LUHN_NO_DATE_WOULD_FAIL_LUHN, TEST_CVC_VALUE, TEST_DATE_VALUE } from '../../../../utils/constants'; +import { URL_MAP } from '../../../../../fixtures/URL_MAP'; +import LANG from '../../../../../../server/translations/en-US.json'; + +const PAN_ERROR_NOT_VALID = LANG['cc.num.902']; + +test.describe('Testing binLookup/plcc/pasting fny: test what happens when cards that do, or do not, require a luhn check, are pasted in', () => { + test('#1 Test that the paste event triggers the correct response and the validation rules are updated accordingly', async ({ card, page }) => { + // + const componentConfig = { brands: ['mc', 'visa', 'amex', 'bcmc', 'synchrony_plcc'] }; + + await card.goto(getStoryUrl({ baseUrl: URL_MAP.card, componentConfig })); + + await card.isComponentVisible(); + + /** + * Type number that identifies as plcc, no luhn required, but that fails luhn + */ + await card.fillCardNumber(PLCC_WITH_LUHN_NO_DATE_WOULD_FAIL_LUHN); + await page.waitForTimeout(100); + + await card.typeExpiryDate(TEST_DATE_VALUE); + await card.typeCvc(TEST_CVC_VALUE); + + // Expect the card not to be valid + await card.pay(); + + await expect(card.cardNumberErrorElement).toBeVisible(); + await expect(card.cardNumberErrorElement).toHaveText(PAN_ERROR_NOT_VALID); + + /** + * Paste number that identifies as plcc, luhn required + */ + // await card.cardNumberInput.focus(); + // await page.keyboard.press('ControlOrMeta+A'); + // await page.evaluate(() => navigator.clipboard.writeText('6044100018023838')); // PLCC_NO_LUHN_NO_DATE + // await page.waitForTimeout(100); + // await page.keyboard.press('ControlOrMeta+V'); + // await page.waitForTimeout(100); + + await card.fillCardNumber(PLCC_NO_LUHN_NO_DATE); + await page.waitForTimeout(100); + + // If correct events have fired expect the card to be valid i.e. no error message when pressing pay + await card.pay(); + await expect(card.cardNumberErrorElement).not.toBeVisible(); + }); +}); diff --git a/packages/e2e-playwright/tests/ui/card/cardNumber/unsupported.card.number.spec.ts b/packages/e2e-playwright/tests/ui/card/cardNumber/unsupported.card.number.spec.ts index bf42e2415..d76f95ce8 100644 --- a/packages/e2e-playwright/tests/ui/card/cardNumber/unsupported.card.number.spec.ts +++ b/packages/e2e-playwright/tests/ui/card/cardNumber/unsupported.card.number.spec.ts @@ -1,4 +1,10 @@ -import { test } from '../../../../fixtures/card.fixture'; +import { expect, test } from '../../../../fixtures/card.fixture'; +import { getStoryUrl } from '../../../utils/getStoryUrl'; +import { URL_MAP } from '../../../../fixtures/URL_MAP'; +import { PAYMENT_RESULT, REGULAR_TEST_CARD, TEST_CVC_VALUE, TEST_DATE_VALUE, VISA_CARD } from '../../../utils/constants'; +import LANG from '../../../../../server/translations/en-US.json'; + +const PAN_ERROR_NOT_SUPPORTED = LANG['cc.num.903']; test( '#1 Enter number of unsupported card, ' + 'then check UI shows an error ' + 'then PASTE supported card & check UI error is cleared', @@ -43,3 +49,42 @@ test('#4 Enter number of unsupported card, ' + 'then check UI shows an error ' + // delete card number // Test UI shows "Unsupported card" error has gone }); + +test.only('#2 Test that after an unsupported card has been entered PASTING in full supported card makes it possible to pay', async ({ + card, + page +}) => { + // + const componentConfig = { brands: ['mc'] }; + + await card.goto(getStoryUrl({ baseUrl: URL_MAP.card, componentConfig })); + + await card.isComponentVisible(); + + // Fill unsupported card + await card.fillCardNumber(VISA_CARD); + await page.waitForTimeout(100); + + await card.typeExpiryDate(TEST_DATE_VALUE); + await card.typeCvc(TEST_CVC_VALUE); + + await expect(card.cardNumberErrorElement).toBeVisible(); + await expect(card.cardNumberErrorElement).toHaveText(PAN_ERROR_NOT_SUPPORTED); + + /** + * Paste number that is supported + */ + // await card.cardNumberInput.focus(); + // await page.keyboard.press('ControlOrMeta+A'); + // await page.evaluate(() => navigator.clipboard.writeText('5500000000000004')); + // await page.waitForTimeout(100); + // await page.keyboard.press('ControlOrMeta+V'); + // await page.waitForTimeout(100); + + await card.fillCardNumber(REGULAR_TEST_CARD); + await page.waitForTimeout(100); + + // If correct events have fired expect the card to be valid + await card.pay(); + await expect(card.paymentResult).toHaveText(PAYMENT_RESULT.authorised); +}); diff --git a/packages/e2e-playwright/tests/utils/constants.ts b/packages/e2e-playwright/tests/utils/constants.ts index e524d25ad..21f7f10eb 100644 --- a/packages/e2e-playwright/tests/utils/constants.ts +++ b/packages/e2e-playwright/tests/utils/constants.ts @@ -24,7 +24,8 @@ export const UNKNOWN_VISA_CARD = '41111111'; // card is now in the test DBs (vis export const PLCC_NO_LUHN_NO_DATE = '6044100018023838'; // binLookup gives luhn check and date not required export const PLCC_WITH_LUHN_NO_DATE = '6044141000018769'; // binLookup gives luhn check required but date not required -export const PLCC_NO_LUHN_NO_DATE_WOULD_FAIL_LUHN = '6044100033327222'; // A PAN that identifies as a plcc that doesn't require a luhn check BUT that would fail the luhn check if it was required_ +export const PLCC_WITH_LUHN_NO_DATE_WOULD_FAIL_LUHN = '6044141000018768'; // binLookup gives luhn check required, date not required, BUT that will fail the luhn check +export const PLCC_NO_LUHN_NO_DATE_WOULD_FAIL_LUHN = '6044100033327222'; // A PAN that identifies as a plcc that doesn't require a luhn check BUT that would fail the luhn check if it was required // intersolve (plastix) export const GIFTCARD_NUMBER = '4010100000000000000'; diff --git a/packages/lib/src/components/internal/SecuredFields/lib/constants.ts b/packages/lib/src/components/internal/SecuredFields/lib/constants.ts index 9ba2c9e39..72ebfb1b6 100644 --- a/packages/lib/src/components/internal/SecuredFields/lib/constants.ts +++ b/packages/lib/src/components/internal/SecuredFields/lib/constants.ts @@ -17,7 +17,7 @@ export const ENCRYPTED_SECURITY_CODE_4_DIGITS = 'encryptedSecurityCode4digits'; export const GIFT_CARD = 'giftcard'; -export const SF_VERSION = '5.3.1'; +export const SF_VERSION = '5.3.2'; export const DEFAULT_CARD_GROUP_TYPES = ['amex', 'mc', 'visa']; diff --git a/packages/lib/storybook/stories/cards/Card.stories.tsx b/packages/lib/storybook/stories/cards/Card.stories.tsx index 2741afcb5..1cead0671 100644 --- a/packages/lib/storybook/stories/cards/Card.stories.tsx +++ b/packages/lib/storybook/stories/cards/Card.stories.tsx @@ -19,7 +19,7 @@ export const Default: CardStory = { componentConfiguration: getComponentConfigFromUrl() ?? { _disableClickToPay: true, autoFocus: true, - // brands: ['mc'], + // brands: ['mc', 'synchrony_plcc'], // brandsConfiguration: { visa: { icon: 'http://localhost:3000/nocard.svg', name: 'altVisa' } }, challengeWindowSize: '02', // configuration: {socialSecurityNumberMode: 'auto'} From 1b9c41bae0755fbe023010f6f844b167597500bf Mon Sep 17 00:00:00 2001 From: nicholas Date: Fri, 22 Nov 2024 17:32:39 +0100 Subject: [PATCH 2/8] Cleanup --- .../panLength/panLength.focus.regular.spec.ts | 13 ------------- .../card/binLookup/plcc/plcc.luhn.paste.spec.ts | 11 +---------- .../cardNumber/unsupported.card.number.spec.ts | 16 ++-------------- 3 files changed, 3 insertions(+), 37 deletions(-) diff --git a/packages/e2e-playwright/tests/ui/card/binLookup/panLength/panLength.focus.regular.spec.ts b/packages/e2e-playwright/tests/ui/card/binLookup/panLength/panLength.focus.regular.spec.ts index c80821857..14ca940d7 100644 --- a/packages/e2e-playwright/tests/ui/card/binLookup/panLength/panLength.focus.regular.spec.ts +++ b/packages/e2e-playwright/tests/ui/card/binLookup/panLength/panLength.focus.regular.spec.ts @@ -122,19 +122,6 @@ test.describe('Test Card, & binLookup w. panLength property', () => { await card.isComponentVisible(); - // Place focus on the input - // await card.cardNumberLabelElement.click(); - // - // // Copy text to clipboard - // await page.evaluate(() => navigator.clipboard.writeText('4000620000000007')); // Can't use the constant for some reason - // - // await page.waitForTimeout(1000); - // - // // Paste text from clipboard - // await page.keyboard.press('ControlOrMeta+V'); - // - // await page.waitForTimeout(1000); - // "Paste" number await card.fillCardNumber(CARD_WITH_PAN_LENGTH); await page.waitForTimeout(100); diff --git a/packages/e2e-playwright/tests/ui/card/binLookup/plcc/plcc.luhn.paste.spec.ts b/packages/e2e-playwright/tests/ui/card/binLookup/plcc/plcc.luhn.paste.spec.ts index 60fda1e02..6134bc142 100644 --- a/packages/e2e-playwright/tests/ui/card/binLookup/plcc/plcc.luhn.paste.spec.ts +++ b/packages/e2e-playwright/tests/ui/card/binLookup/plcc/plcc.luhn.paste.spec.ts @@ -30,16 +30,7 @@ test.describe('Testing binLookup/plcc/pasting fny: test what happens when cards await expect(card.cardNumberErrorElement).toBeVisible(); await expect(card.cardNumberErrorElement).toHaveText(PAN_ERROR_NOT_VALID); - /** - * Paste number that identifies as plcc, luhn required - */ - // await card.cardNumberInput.focus(); - // await page.keyboard.press('ControlOrMeta+A'); - // await page.evaluate(() => navigator.clipboard.writeText('6044100018023838')); // PLCC_NO_LUHN_NO_DATE - // await page.waitForTimeout(100); - // await page.keyboard.press('ControlOrMeta+V'); - // await page.waitForTimeout(100); - + // "Paste" number that identifies as plcc, luhn required await card.fillCardNumber(PLCC_NO_LUHN_NO_DATE); await page.waitForTimeout(100); diff --git a/packages/e2e-playwright/tests/ui/card/cardNumber/unsupported.card.number.spec.ts b/packages/e2e-playwright/tests/ui/card/cardNumber/unsupported.card.number.spec.ts index d76f95ce8..95c36513a 100644 --- a/packages/e2e-playwright/tests/ui/card/cardNumber/unsupported.card.number.spec.ts +++ b/packages/e2e-playwright/tests/ui/card/cardNumber/unsupported.card.number.spec.ts @@ -50,10 +50,7 @@ test('#4 Enter number of unsupported card, ' + 'then check UI shows an error ' + // Test UI shows "Unsupported card" error has gone }); -test.only('#2 Test that after an unsupported card has been entered PASTING in full supported card makes it possible to pay', async ({ - card, - page -}) => { +test('#2 Test that after an unsupported card has been entered PASTING in full supported card makes it possible to pay', async ({ card, page }) => { // const componentConfig = { brands: ['mc'] }; @@ -71,16 +68,7 @@ test.only('#2 Test that after an unsupported card has been entered PASTING in fu await expect(card.cardNumberErrorElement).toBeVisible(); await expect(card.cardNumberErrorElement).toHaveText(PAN_ERROR_NOT_SUPPORTED); - /** - * Paste number that is supported - */ - // await card.cardNumberInput.focus(); - // await page.keyboard.press('ControlOrMeta+A'); - // await page.evaluate(() => navigator.clipboard.writeText('5500000000000004')); - // await page.waitForTimeout(100); - // await page.keyboard.press('ControlOrMeta+V'); - // await page.waitForTimeout(100); - + // "Paste" number that is supported await card.fillCardNumber(REGULAR_TEST_CARD); await page.waitForTimeout(100); From 24e2debf55a22031b9989e2148be59b54c11d6bd Mon Sep 17 00:00:00 2001 From: nicholas Date: Fri, 22 Nov 2024 19:22:51 +0100 Subject: [PATCH 3/8] removing clipboard permissions --- packages/e2e-playwright/playwright.config.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/packages/e2e-playwright/playwright.config.ts b/packages/e2e-playwright/playwright.config.ts index 9b02ffb09..7e4d8679b 100644 --- a/packages/e2e-playwright/playwright.config.ts +++ b/packages/e2e-playwright/playwright.config.ts @@ -51,11 +51,7 @@ const config: PlaywrightTestConfig = { { name: 'chromium', use: { - ...devices['Desktop Chrome'], - contextOptions: { - // chromium-specific permissions - permissions: ['clipboard-read', 'clipboard-write'] - } + ...devices['Desktop Chrome'] } }, From 3f705a5f81e6036830ab6e63091c820a53d73edf Mon Sep 17 00:00:00 2001 From: nicholas Date: Fri, 22 Nov 2024 19:24:37 +0100 Subject: [PATCH 4/8] reverting value for sf version --- .../lib/src/components/internal/SecuredFields/lib/constants.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/lib/src/components/internal/SecuredFields/lib/constants.ts b/packages/lib/src/components/internal/SecuredFields/lib/constants.ts index 72ebfb1b6..9ba2c9e39 100644 --- a/packages/lib/src/components/internal/SecuredFields/lib/constants.ts +++ b/packages/lib/src/components/internal/SecuredFields/lib/constants.ts @@ -17,7 +17,7 @@ export const ENCRYPTED_SECURITY_CODE_4_DIGITS = 'encryptedSecurityCode4digits'; export const GIFT_CARD = 'giftcard'; -export const SF_VERSION = '5.3.2'; +export const SF_VERSION = '5.3.1'; export const DEFAULT_CARD_GROUP_TYPES = ['amex', 'mc', 'visa']; From 55338fbfa995281e6d5f953fc96172f2424d209f Mon Sep 17 00:00:00 2001 From: nicholas Date: Mon, 25 Nov 2024 10:48:34 +0100 Subject: [PATCH 5/8] Add extra check that card is valid --- .../tests/ui/card/cardNumber/unsupported.card.number.spec.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/e2e-playwright/tests/ui/card/cardNumber/unsupported.card.number.spec.ts b/packages/e2e-playwright/tests/ui/card/cardNumber/unsupported.card.number.spec.ts index 95c36513a..40402d7fa 100644 --- a/packages/e2e-playwright/tests/ui/card/cardNumber/unsupported.card.number.spec.ts +++ b/packages/e2e-playwright/tests/ui/card/cardNumber/unsupported.card.number.spec.ts @@ -50,7 +50,7 @@ test('#4 Enter number of unsupported card, ' + 'then check UI shows an error ' + // Test UI shows "Unsupported card" error has gone }); -test('#2 Test that after an unsupported card has been entered PASTING in full supported card makes it possible to pay', async ({ card, page }) => { +test('#5 Test that after an unsupported card has been entered PASTING in full supported card makes it possible to pay', async ({ card, page }) => { // const componentConfig = { brands: ['mc'] }; @@ -73,6 +73,7 @@ test('#2 Test that after an unsupported card has been entered PASTING in full su await page.waitForTimeout(100); // If correct events have fired expect the card to be valid + await expect(card.cardNumberErrorElement).not.toBeVisible(); await card.pay(); await expect(card.paymentResult).toHaveText(PAYMENT_RESULT.authorised); }); From 7be6248dca56c314289b9642e6574930aceec35a Mon Sep 17 00:00:00 2001 From: nicholas Date: Mon, 25 Nov 2024 14:58:12 +0100 Subject: [PATCH 6/8] Added (or moved) remaining tests related to unsupported.card.number.spec.ts --- .../unsupported.card.number.spec.ts | 106 ++++++++++-------- .../tests/ui/card/errors/card.errors.spec.ts | 37 ++++++ 2 files changed, 96 insertions(+), 47 deletions(-) create mode 100644 packages/e2e-playwright/tests/ui/card/errors/card.errors.spec.ts diff --git a/packages/e2e-playwright/tests/ui/card/cardNumber/unsupported.card.number.spec.ts b/packages/e2e-playwright/tests/ui/card/cardNumber/unsupported.card.number.spec.ts index 40402d7fa..125245f42 100644 --- a/packages/e2e-playwright/tests/ui/card/cardNumber/unsupported.card.number.spec.ts +++ b/packages/e2e-playwright/tests/ui/card/cardNumber/unsupported.card.number.spec.ts @@ -1,56 +1,15 @@ import { expect, test } from '../../../../fixtures/card.fixture'; import { getStoryUrl } from '../../../utils/getStoryUrl'; import { URL_MAP } from '../../../../fixtures/URL_MAP'; -import { PAYMENT_RESULT, REGULAR_TEST_CARD, TEST_CVC_VALUE, TEST_DATE_VALUE, VISA_CARD } from '../../../utils/constants'; +import { PAYMENT_RESULT, REGULAR_TEST_CARD, TEST_CVC_VALUE, TEST_DATE_VALUE, UNKNOWN_BIN_CARD, VISA_CARD } from '../../../utils/constants'; import LANG from '../../../../../server/translations/en-US.json'; const PAN_ERROR_NOT_SUPPORTED = LANG['cc.num.903']; -test( - '#1 Enter number of unsupported card, ' + 'then check UI shows an error ' + 'then PASTE supported card & check UI error is cleared', - async () => { - // Wait for field to appear in DOM - // Fill card field with unsupported number - // Test UI shows "Unsupported card" error - // Past card field with supported number - // Test UI shows "Unsupported card" error has gone - } -); - -test( - '#2 Enter number of unsupported card, ' + - 'then check UI shows an error ' + - 'then press the Pay button ' + - 'then check UI shows more errors ' + - 'then PASTE supported card & check PAN UI errors are cleared whilst others persist', - async () => { - // Wait for field to appear in DOM - // Fill card field with unsupported number - // Test UI shows "Unsupported card" error - // Click Pay (which will call showValidation on all fields) - // Past card field with supported number - // Test UI shows "Unsupported card" error has gone - // PAN error cleared but other errors persist - } -); - -test('#3 Enter number of unsupported card, ' + 'then check UI shows an error ' + 'then PASTE card not in db check UI error is cleared', async () => { - // Wait for field to appear in DOM - // Fill card field with unsupported number - // Test UI shows "Unsupported card" error - // Past card field with supported number - // Test UI shows "Unsupported card" error has gone -}); - -test('#4 Enter number of unsupported card, ' + 'then check UI shows an error ' + 'then delete PAN & check UI error is cleared', async () => { - // Wait for field to appear in DOM - // Fill card field with unsupported number - // Test UI shows "Unsupported card" error - // delete card number - // Test UI shows "Unsupported card" error has gone -}); - -test('#5 Test that after an unsupported card has been entered PASTING in full supported card makes it possible to pay', async ({ card, page }) => { +test('#1 Test that after an unsupported card has been entered we see errors, PASTING in a full supported card clears errors & makes it possible to pay', async ({ + card, + page +}) => { // const componentConfig = { brands: ['mc'] }; @@ -72,8 +31,61 @@ test('#5 Test that after an unsupported card has been entered PASTING in full su await card.fillCardNumber(REGULAR_TEST_CARD); await page.waitForTimeout(100); - // If correct events have fired expect the card to be valid + // If correct events have fired expect the card to not have errors await expect(card.cardNumberErrorElement).not.toBeVisible(); + + // And to be valid await card.pay(); await expect(card.paymentResult).toHaveText(PAYMENT_RESULT.authorised); }); + +test( + '#2 Enter number of unsupported card, ' + 'then check UI shows an error ' + 'then PASTE card not in db & check UI error is cleared', + async ({ card, page }) => { + const componentConfig = { brands: ['mc'] }; + + await card.goto(getStoryUrl({ baseUrl: URL_MAP.card, componentConfig })); + + await card.isComponentVisible(); + + // Fill unsupported card + await card.fillCardNumber(VISA_CARD); + await page.waitForTimeout(100); + + await card.typeExpiryDate(TEST_DATE_VALUE); + await card.typeCvc(TEST_CVC_VALUE); + + await expect(card.cardNumberErrorElement).toBeVisible(); + await expect(card.cardNumberErrorElement).toHaveText(PAN_ERROR_NOT_SUPPORTED); + + // "Paste" number that is unknown + await card.fillCardNumber(UNKNOWN_BIN_CARD); + await page.waitForTimeout(100); + + // If correct events have fired expect the card to not have errors + await expect(card.cardNumberErrorElement).not.toBeVisible(); + } +); + +test( + '#3 Enter number of unsupported card, ' + 'then check UI shows an error ' + 'then delete PAN & check UI error is cleared', + async ({ card, page }) => { + const componentConfig = { brands: ['mc'] }; + + await card.goto(getStoryUrl({ baseUrl: URL_MAP.card, componentConfig })); + + await card.isComponentVisible(); + + // Fill unsupported card + await card.fillCardNumber(VISA_CARD); + await page.waitForTimeout(100); + + await expect(card.cardNumberErrorElement).toBeVisible(); + await expect(card.cardNumberErrorElement).toHaveText(PAN_ERROR_NOT_SUPPORTED); + + await page.waitForTimeout(300); // leave time for focus to shift + + await card.deleteCardNumber(); + await expect(card.cardNumberErrorElement).not.toBeVisible(); + } +); diff --git a/packages/e2e-playwright/tests/ui/card/errors/card.errors.spec.ts b/packages/e2e-playwright/tests/ui/card/errors/card.errors.spec.ts new file mode 100644 index 000000000..f09d02186 --- /dev/null +++ b/packages/e2e-playwright/tests/ui/card/errors/card.errors.spec.ts @@ -0,0 +1,37 @@ +import { test, expect } from '../../../../fixtures/card.fixture'; +import { REGULAR_TEST_CARD, TEST_CVC_VALUE, TEST_DATE_VALUE } from '../../../utils/constants'; +import { URL_MAP } from '../../../../fixtures/URL_MAP'; +import LANG from '../../../../../server/translations/en-US.json'; + +const ERROR_ENTER_PAN = LANG['cc.num.900']; +const ERROR_ENTER_DATE = LANG['cc.dat.910']; +const ERROR_ENTER_CVC = LANG['cc.cvc.920']; + +test.describe('Card - UI errors', () => { + test('#1 Not filling in card fields should lead to errors, which are cleared when fields are filled', async ({ card, page }) => { + await card.goto(URL_MAP.card); + await card.isComponentVisible(); + await card.pay(); + + // Expect errors + await expect(card.cardNumberErrorElement).toBeVisible(); + await expect(card.cardNumberErrorElement).toHaveText(ERROR_ENTER_PAN); + + await expect(card.expiryDateErrorElement).toBeVisible(); + await expect(card.expiryDateErrorElement).toHaveText(ERROR_ENTER_DATE); + + await expect(card.cvcErrorElement).toBeVisible(); + await expect(card.cvcErrorElement).toHaveText(ERROR_ENTER_CVC); + + await page.waitForTimeout(300); // leave time for focus to shift + + await card.typeCardNumber(REGULAR_TEST_CARD); + await card.typeExpiryDate(TEST_DATE_VALUE); + await card.typeCvc(TEST_CVC_VALUE); + + // Expect no errors + await expect(card.cardNumberErrorElement).not.toBeVisible(); + await expect(card.expiryDateErrorElement).not.toBeVisible(); + await expect(card.cvcErrorElement).not.toBeVisible(); + }); +}); From 2f6cc6be73e01fd5557119ce5ca6a9484aea1f5d Mon Sep 17 00:00:00 2001 From: nicholas Date: Tue, 26 Nov 2024 11:24:44 +0100 Subject: [PATCH 7/8] Slow down typing on test that is always flaky (because PAN doesn't fill properly on Webkit) --- packages/e2e-playwright/models/card.ts | 4 ++-- .../card/binLookup/panLength/panLength.focus.regular.spec.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/e2e-playwright/models/card.ts b/packages/e2e-playwright/models/card.ts index b1fb901d3..74ef31475 100644 --- a/packages/e2e-playwright/models/card.ts +++ b/packages/e2e-playwright/models/card.ts @@ -143,8 +143,8 @@ class Card extends Base { await this.cardNumberInput.fill(cardNumber); } - async typeCardNumber(cardNumber: string) { - await this.cardNumberInput.pressSequentially(cardNumber, { delay: USER_TYPE_DELAY }); + async typeCardNumber(cardNumber: string, delay = USER_TYPE_DELAY) { + await this.cardNumberInput.pressSequentially(cardNumber, { delay }); } async deleteCardNumber() { diff --git a/packages/e2e-playwright/tests/ui/card/binLookup/panLength/panLength.focus.regular.spec.ts b/packages/e2e-playwright/tests/ui/card/binLookup/panLength/panLength.focus.regular.spec.ts index 14ca940d7..11ffff877 100644 --- a/packages/e2e-playwright/tests/ui/card/binLookup/panLength/panLength.focus.regular.spec.ts +++ b/packages/e2e-playwright/tests/ui/card/binLookup/panLength/panLength.focus.regular.spec.ts @@ -108,9 +108,9 @@ test.describe('Test Card, & binLookup w. panLength property', () => { // Card out of date await card.fillExpiryDate('12/90'); - await card.typeCardNumber(CARD_WITH_PAN_LENGTH); + await card.typeCardNumber(CARD_WITH_PAN_LENGTH, 300); - await page.waitForTimeout(500); + // await page.waitForTimeout(300); // Expect UI change - expiryDate field has focus await expect(card.cardNumberInput).not.toBeFocused(); From a237b6372e8cd206e7abeed8072656909d16beeb Mon Sep 17 00:00:00 2001 From: nicholas Date: Tue, 26 Nov 2024 14:12:15 +0100 Subject: [PATCH 8/8] Removed commented out line --- .../ui/card/binLookup/panLength/panLength.focus.regular.spec.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/e2e-playwright/tests/ui/card/binLookup/panLength/panLength.focus.regular.spec.ts b/packages/e2e-playwright/tests/ui/card/binLookup/panLength/panLength.focus.regular.spec.ts index 11ffff877..f107a9148 100644 --- a/packages/e2e-playwright/tests/ui/card/binLookup/panLength/panLength.focus.regular.spec.ts +++ b/packages/e2e-playwright/tests/ui/card/binLookup/panLength/panLength.focus.regular.spec.ts @@ -110,8 +110,6 @@ test.describe('Test Card, & binLookup w. panLength property', () => { await card.typeCardNumber(CARD_WITH_PAN_LENGTH, 300); - // await page.waitForTimeout(300); - // Expect UI change - expiryDate field has focus await expect(card.cardNumberInput).not.toBeFocused(); await expect(card.expiryDateInput).toBeFocused();