Skip to content

Commit

Permalink
Chore/bin lookup pan length tests (#2956)
Browse files Browse the repository at this point in the history
* Refactoring panLength.focus.regular.spec.ts to work in new framework

* Refactoring panLength.focus.regular.spec.ts to work in new framework - test 7/9

* Refactoring panLength.focus.regular.spec.ts to work in new framework - test 8/9

* Refactoring panLength.focus.regular.spec.ts to work in new framework - test 9/9

* Cleaning up unused params

* Skip "paste" tet until it works in Firefox and Webkit

* Make clipboard permissions browser specific

* Added pauses for test that behaved oddly in webkit

* Refactoring panLength.focus.ssn.spec.ts to work in new framework

* Shortened test descriptions

* Refactoring panLength.focus.avs.spec.ts to work in new framework

* Use correct mock in avs.a11y.spec.ts

* Refactoring panLength.focus.kcp.spec.ts to work in new framework

* Deleting old, testcafe, clientScripts files

* Refactoring to make better use of the testing API and other models - part 1

* Fix typo

* Refactoring to make better use of the testing API and other models - part 2

* Refactoring to make better use of the testing API and other models - part 3

* Changing test PAN to see if it is less flaky in Webkit CI
  • Loading branch information
sponglord authored Nov 18, 2024
1 parent 8b10acb commit 8c169e2
Show file tree
Hide file tree
Showing 16 changed files with 442 additions and 384 deletions.
12 changes: 12 additions & 0 deletions packages/e2e-playwright/fixtures/card.fixture.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,14 @@ import { Card } from '../models/card';
import { BCMC } from '../models/bcmc';
import { URL_MAP } from './URL_MAP';
import { CardWithAvs } from '../models/card-avs';
import { CardWithKCP } from '../models/card-kcp';
import { CardWithSSN } from '../models/card-ssn';

type Fixture = {
card: Card;
cardWithAvs: CardWithAvs;
cardWithKCP: CardWithKCP;
cardWithSSN: CardWithSSN;
bcmc: BCMC;
};

Expand All @@ -19,6 +23,14 @@ const test = base.extend<Fixture>({
const cardPage = new CardWithAvs(page);
await use(cardPage);
},
cardWithKCP: async ({ page }, use) => {
const cardPage = new CardWithKCP(page);
await use(cardPage);
},
cardWithSSN: async ({ page }, use) => {
const cardPage = new CardWithSSN(page);
await use(cardPage);
},
bcmc: async ({ page }, use) => {
const bcmc = new BCMC(page);
await bcmc.goto(URL_MAP.bcmc);
Expand Down
100 changes: 99 additions & 1 deletion packages/e2e-playwright/mocks/binLookup/binLookup.data.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,18 @@
const optionalDateAndCvcMock = {
brands: [
{
brand: 'mc',
enableLuhnCheck: true,
supported: true,
cvcPolicy: 'optional',
expiryDatePolicy: 'optional'
}
],
issuingCountryCode: 'US',
requestedId: null
};

const optionalDateAndCvcWithPanLengthMock = {
brands: [
{
brand: 'mc',
Expand Down Expand Up @@ -27,4 +41,88 @@ const hiddenDateAndCvcMock = {
requestedId: null
};

export { optionalDateAndCvcMock, hiddenDateAndCvcMock };
const optionalDateWithPanLengthMock = {
brands: [
{
brand: 'mc',
enableLuhnCheck: true,
supported: true,
cvcPolicy: 'required',
expiryDatePolicy: 'optional',
panLength: 16
}
],
issuingCountryCode: 'US',
requestedId: null
};

const hiddenDateWithPanLengthMock = {
brands: [
{
brand: 'mc',
enableLuhnCheck: true,
supported: true,
cvcPolicy: 'required',
expiryDatePolicy: 'hidden',
panLength: 16
}
],
issuingCountryCode: 'US',
requestedId: null
};

const multiLengthMaestroWithPanLengthMock = {
brands: [
{
enableLuhnCheck: true,
supported: true,
brand: 'maestro',
cvcPolicy: 'required',
expiryDatePolicy: 'required',
panLength: 18
}
],
issuingCountryCode: 'US',
requestedId: null
};

const amexWithPanLengthMock = {
brands: [
{
enableLuhnCheck: true,
supported: true,
brand: 'amex',
cvcPolicy: 'required',
expiryDatePolicy: 'required',
panLength: 15
}
],
issuingCountryCode: 'US',
requestedId: null
};

const kcpMockOptionalDateAndCvcWithPanLengthMock = {
brands: [
{
enableLuhnCheck: true,
supported: true,
brand: 'korean_local_card',
cvcPolicy: 'optional',
expiryDatePolicy: 'optional',
panLength: 16
}
],
requestedId: null,
issuingCountryCode: 'KR'
};

export {
optionalDateAndCvcMock,
hiddenDateAndCvcMock,
optionalDateWithPanLengthMock,
hiddenDateWithPanLengthMock,
optionalDateAndCvcWithPanLengthMock,
multiLengthMaestroWithPanLengthMock,
amexWithPanLengthMock,
kcpMockOptionalDateAndCvcWithPanLengthMock
};
17 changes: 17 additions & 0 deletions packages/e2e-playwright/models/card-kcp.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { Card } from './card';
import { type Locator, Page } from '@playwright/test';

class CardWithKCP extends Card {
readonly kcpTaxNumberField: Locator;

constructor(page: Page) {
super(page);
this.kcpTaxNumberField = this.rootElement.locator('.adyen-checkout__field--kcp-taxNumber'); // Holder
}

get taxNumberInput() {
return this.kcpTaxNumberField.getByRole('textbox', { name: /Cardholder birthdate/i });
}
}

export { CardWithKCP };
17 changes: 17 additions & 0 deletions packages/e2e-playwright/models/card-ssn.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { Card } from './card';
import { type Locator, Page } from '@playwright/test';

class CardWithSSN extends Card {
readonly ssnField: Locator;

constructor(page: Page) {
super(page);
this.ssnField = this.rootElement.locator('.adyen-checkout__field--socialSecurityNumber'); // Holder
}

get ssnInput() {
return this.ssnField.getByRole('textbox', { name: /CPF\/CNPJ/i });
}
}

export { CardWithSSN };
13 changes: 13 additions & 0 deletions packages/e2e-playwright/models/card.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,19 +27,24 @@ class Card extends Base {
readonly brandingIcon: Locator;

readonly expiryDateField: Locator;
readonly expiryDateLabelElement: Locator;
readonly expiryDateLabelText: Locator;
readonly expiryDateContextualElement: Locator;
readonly expiryDateInput: Locator;
readonly expiryDateIframeContextualElement: Locator;
readonly expiryDateErrorElement: Locator;

readonly cvcField: Locator;
readonly cvcLabelElement: Locator;
readonly cvcLabelText: Locator;
readonly cvcErrorElement: Locator;
readonly cvcContextualElement: Locator;
readonly cvcInput: Locator;
readonly cvcIframeContextualElement: Locator;

readonly holderNameField: Locator;
readonly holderNameInput: Locator;

readonly installmentsPaymentLabel: Locator;
readonly revolvingPaymentLabel: Locator;
readonly installmentsDropdown: Locator;
Expand Down Expand Up @@ -72,6 +77,7 @@ class Card extends Base {
* Expiry Date elements, in Checkout
*/
this.expiryDateField = this.rootElement.locator('.adyen-checkout__field--expiryDate'); // Holder
this.expiryDateLabelElement = this.expiryDateField.locator('.adyen-checkout__label');
this.expiryDateLabelText = this.expiryDateField.locator('.adyen-checkout__label__text');
this.expiryDateContextualElement = this.expiryDateField.locator('.adyen-checkout-contextual-text'); // Related contextual element
this.expiryDateErrorElement = this.expiryDateField.locator('.adyen-checkout-contextual-text--error'); // Related error element
Expand All @@ -87,6 +93,7 @@ class Card extends Base {
* Security code elements, in Checkout
*/
this.cvcField = this.rootElement.locator('.adyen-checkout__field--securityCode'); // Holder
this.cvcLabelElement = this.cvcField.locator('.adyen-checkout__label');
this.cvcLabelText = this.cvcField.locator('.adyen-checkout__label__text');
this.cvcContextualElement = this.cvcField.locator('.adyen-checkout-contextual-text'); // Related contextual element
this.cvcErrorElement = this.cvcField.locator('.adyen-checkout-contextual-text--error'); // Related error element
Expand All @@ -98,6 +105,12 @@ class Card extends Base {
this.cvcInput = cvcIframe.locator(`input[aria-label="${CVC_IFRAME_LABEL}"]`);
this.cvcIframeContextualElement = cvcIframe.locator('.aria-context');

/**
* HolderName elements, in Checkout
*/
this.holderNameField = this.rootElement.locator('.adyen-checkout__card__holderName'); // Holder
this.holderNameInput = this.holderNameField.getByRole('textbox', { name: /name on card/i });

/**
* Installments related elements
*/
Expand Down
6 changes: 5 additions & 1 deletion packages/e2e-playwright/playwright.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,11 @@ const config: PlaywrightTestConfig = {
{
name: 'chromium',
use: {
...devices['Desktop Chrome']
...devices['Desktop Chrome'],
contextOptions: {
// chromium-specific permissions
permissions: ['clipboard-read', 'clipboard-write']
}
}
},

Expand Down
4 changes: 2 additions & 2 deletions packages/e2e-playwright/tests/a11y/card/avs.a11y.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { test as base, expect } from '@playwright/test';
import { binLookupMock } from '../../../mocks/binLookup/binLookup.mock';
import { optionalDateAndCvcMock } from '../../../mocks/binLookup/binLookup.data';
import { optionalDateAndCvcWithPanLengthMock } from '../../../mocks/binLookup/binLookup.data';
import { REGULAR_TEST_CARD } from '../../utils/constants';
import { CardWithAvs } from '../../../models/card-avs';
import { getStoryUrl } from '../../utils/getStoryUrl';
Expand All @@ -15,7 +15,7 @@ const test = base.extend<Fixture>({
const cardPage = new CardWithAvs(page);
const componentConfig = { billingAddressRequired: true, billingAddressRequiredFields: ['street', 'houseNumberOrName', 'postalCode', 'city'] };
await cardPage.goto(getStoryUrl({ baseUrl: URL_MAP.card, componentConfig }));
await binLookupMock(page, optionalDateAndCvcMock);
await binLookupMock(page, optionalDateAndCvcWithPanLengthMock);
await use(cardPage);
}
});
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,44 +1,27 @@
import { test } from '@playwright/test';
import { mocks } from './mocks';
import { binLookupUrl, getBinLookupMock, turnOffSDKMocking } from '../../cardMocks';
import { mergeTests, expect } from '@playwright/test';
import { test as cardWithAvs } from '../../../../../fixtures/card.fixture';
import { getStoryUrl } from '../../../../utils/getStoryUrl';
import { URL_MAP } from '../../../../../fixtures/URL_MAP';
import { binLookupMock } from '../../../../../mocks/binLookup/binLookup.mock';
import { optionalDateAndCvcWithPanLengthMock } from '../../../../../mocks/binLookup/binLookup.data';
import { REGULAR_TEST_CARD } from '../../../../utils/constants';

/**
* NOTE - we are mocking the response until such time as we have a genuine card that returns the properties we want to test
*/
const test = mergeTests(cardWithAvs);

let currentMock = null;
test.describe('Test Card, binLookup w. panLength property & address fields', () => {
test('#1 Fill out PAN & see that focus moves to an address field since expiryDate & cvc are optional', async ({ cardWithAvs, page }) => {
await binLookupMock(page, optionalDateAndCvcWithPanLengthMock);

const getMock = val => {
const mock = mocks[val];
currentMock = getBinLookupMock(binLookupUrl, mock);
return currentMock;
};
const componentConfig = { billingAddressRequired: true, billingAddressRequiredFields: ['street', 'houseNumberOrName', 'postalCode', 'city'] };

test.describe('Test how Card Component handles binLookup returning a panLength property for a card with address fields', () => {
// use config from panLength.avs.clientScripts.js
await cardWithAvs.goto(getStoryUrl({ baseUrl: URL_MAP.card, componentConfig }));

test.beforeEach(async () => {
// todo: go to the card page
// For individual test suites (that rely on binLookup & perhaps are being run in isolation)
// - provide a way to ensure SDK bin mocking is turned off
await turnOffSDKMocking();
});
await cardWithAvs.isComponentVisible();

await cardWithAvs.typeCardNumber(REGULAR_TEST_CARD);

test('#1 Fill out PAN (binLookup w. panLength) see that focus moves to an address field since expiryDate & cvc are optional', async () => {
// use mock await t.addRequestHooks(getMock('optionalDateAndCVC'));
// Wait for field to appear in DOM
// await cardPage.numHolder();
//
// const firstDigits = REGULAR_TEST_CARD.substring(0, 15);
// const lastDigits = REGULAR_TEST_CARD.substring(15, 16);
//
// await cardPage.cardUtils.fillCardNumber(t, firstDigits);
//
// await t.wait(INPUT_DELAY);
//
// await cardPage.cardUtils.fillCardNumber(t, lastDigits);
//
// // Expect focus to be place on address (street) field
// await t.expect(cardPage.addressLabelWithFocus.exists).ok();
// Expect focus to be place on address (street) field
await expect(cardWithAvs.cardNumberInput).not.toBeFocused();
await expect(cardWithAvs.billingAddress.streetInput).toBeFocused();
});
});
Loading

0 comments on commit 8c169e2

Please sign in to comment.