diff --git a/.github/workflows/test_e2e.yml b/.github/workflows/test_e2e.yml index 35e338d..97570b7 100644 --- a/.github/workflows/test_e2e.yml +++ b/.github/workflows/test_e2e.yml @@ -32,11 +32,11 @@ jobs: - name: Install dependencies run: npm ci - # - name: Install Playwright browsers - # run: npm run test:install + - name: Install Playwright browsers + run: npm run test:install - # - name: Run E2E tests - # run: npm run test:e2e + - name: Run E2E tests + run: npm run test:e2e - name: Upload test results to Datadog if: always() diff --git a/test/ui/pages/3dsGatewayPage.ts b/test/ui/pages/3dsGatewayPage.ts new file mode 100644 index 0000000..a937f85 --- /dev/null +++ b/test/ui/pages/3dsGatewayPage.ts @@ -0,0 +1,28 @@ +import { expect, Page } from "@playwright/test"; +import { SELECTORS } from "../util/test-constants"; + +export const threeDSGatewayPage = { + + selectTheTransactionAmount: async (page: Page, amount: string) => { + const amountInput = page.locator(`input[value="${amount}"]`); + await expect(amountInput).toBeVisible(); + await amountInput.click(); + }, + + waitForAcsChallengeForm: async (page: Page) => { + await page.locator(SELECTORS.THREE_DS_GATEWAY_SPECIFIC_ACS_SIMULATOR_IFRAME).waitFor({ state: 'visible' }); + }, + + clickOnAllowButton: async (page: Page) => { + const challengeFrame = page.frameLocator(SELECTORS.THREE_DS_GATEWAY_SPECIFIC_ACS_SIMULATOR_IFRAME); + await expect(challengeFrame.locator(SELECTORS.THREE_DS_GATEWAY_SPECIFIC_ACS_SIMULATOR_ALLOW_BUTTON)).toBeVisible(); + await challengeFrame.locator(SELECTORS.THREE_DS_GATEWAY_SPECIFIC_ACS_SIMULATOR_ALLOW_BUTTON).click(); + }, + + clickOnDenyButton: async (page: Page) => { + const challengeFrame = page.frameLocator(SELECTORS.THREE_DS_GATEWAY_SPECIFIC_ACS_SIMULATOR_IFRAME); + await expect(challengeFrame.locator(SELECTORS.THREE_DS_GATEWAY_SPECIFIC_ACS_SIMULATOR_DENY_BUTTON)).toBeVisible(); + await challengeFrame.locator(SELECTORS.THREE_DS_GATEWAY_SPECIFIC_ACS_SIMULATOR_DENY_BUTTON).click(); + }, + +}; \ No newline at end of file diff --git a/test/ui/pages/3dsPage.ts b/test/ui/pages/3dsPage.ts index adc61ab..d808895 100644 --- a/test/ui/pages/3dsPage.ts +++ b/test/ui/pages/3dsPage.ts @@ -108,7 +108,7 @@ export const purchasePage = { await expect(challengeOverlay).toHaveClass(/hidden/, { timeout }); }, - waitForResultPage: async (page: Page, timeout: number = 15000) => { + waitForResultPage: async (page: Page, timeout: number = 30000) => { await purchasePage.waitForChallengeModalToHide(page, timeout); const resultSection = page.locator(THREE_DS_SELECTORS.RESULT_SECTION); await expect(resultSection).toBeVisible({ timeout }); @@ -127,7 +127,8 @@ export const purchasePage = { return 'success'; } else if (await errorTitle.count() > 0 && await errorTitle.isVisible()) { return 'error'; - } else { + } + else { throw new Error('Unable to determine result page type'); } }, diff --git a/test/ui/pages/landingPage.ts b/test/ui/pages/landingPage.ts index cc4ff2f..95fde99 100644 --- a/test/ui/pages/landingPage.ts +++ b/test/ui/pages/landingPage.ts @@ -20,4 +20,15 @@ export const landingPage = { await expect(threeDSButton).toBeVisible(); await threeDSButton.click(); }, -} \ No newline at end of file + + clickOn3DSGatewaySpecificButton: async (page: Page) => { + const threeDSGatewaySpecificButton = page.locator(SELECTORS.THREE_DS_GATEWAY_SPECIFIC_BUTTON); + await expect(threeDSGatewaySpecificButton).toBeVisible(); + await threeDSGatewaySpecificButton.click(); +}, + clickOnOffsitePaymentsButton: async (page: Page) => { + const offsitePaymentsButton = page.locator(SELECTORS.OFFSITE_PAYMENTS_BUTTON); + await expect(offsitePaymentsButton).toBeVisible(); + await offsitePaymentsButton.click(); +}, +} diff --git a/test/ui/pages/offsitePaymentsPage.ts b/test/ui/pages/offsitePaymentsPage.ts new file mode 100644 index 0000000..add82c9 --- /dev/null +++ b/test/ui/pages/offsitePaymentsPage.ts @@ -0,0 +1,153 @@ +import { expect, Page } from "@playwright/test"; +import { PLACEHOLDERS, SELECTORS } from "../util/test-constants"; + +export const paymentPage = { + selectStripeMethod: async (page: Page, method: string) => { + await page.waitForTimeout(3000); + const stripeFrame = page.frameLocator(SELECTORS.STRIPE_APM_FRAME_LOCATOR); + const paymentMethod = stripeFrame.locator(`button[data-testid='${method}']`); + await paymentMethod.click(); + }, + + selectOffsitePaymentMethod: async (page: Page, method: string) => { + const paymentMethod = await page.locator(`.payment-method-name:has-text("${method}")`); + await paymentMethod.click(); + }, + + clickSubmitButton: async (page: Page) => { + const submitButton = page.locator(SELECTORS.HOSTED_SUBMIT_BUTTON); + await submitButton.scrollIntoViewIfNeeded(); + await submitButton.click(); + }, + + fillPaymentForm: async (page: Page,name: string, IBAN?: string, email?: string, country?: string, address?: string, city?: string, countryState?:string, zip?: string, bank?: string) => { + const stripeFrame = page.frameLocator(SELECTORS.STRIPE_APM_FRAME_LOCATOR); + const nameField = stripeFrame.getByPlaceholder(PLACEHOLDERS.STRIPE_APM_NAME).last(); + await nameField.fill(name); + if (IBAN) { + const ibanField = await stripeFrame.getByPlaceholder(PLACEHOLDERS.STRIPE_APM_IBAN); + await ibanField.fill(IBAN); + } + if (email) { + const emailField = await stripeFrame.locator(SELECTORS.STRIPE_APM_EMAIL_FIELD); + await emailField.fill(email); + } + if (country) { + const countryField = await stripeFrame.locator(SELECTORS.STRIPE_APM_COUNTRY_SELECTOR); + await countryField.selectOption(country); + } + if (address) { + const addressField = await stripeFrame.locator(SELECTORS.STRIPE_APM_ADDRESS_FIELD); + await addressField.fill(address); + } + if (city) { + const cityField = await stripeFrame.locator(SELECTORS.STRIPE_APM_CITY_FIELD); + await cityField.fill(city); + } + if (countryState) { + const stateField = await stripeFrame.locator(SELECTORS.STRIPE_APM_COUNTRY_STATE_FIELD); + await stateField.selectOption(countryState); + } + if (zip) { + const zipField = await stripeFrame.locator(SELECTORS.STRIPE_APM_ZIP_FIELD); + await zipField.fill(zip); + } + if (bank) { + const bankField = await stripeFrame.locator(SELECTORS.STRIPE_APM_BANK_FIELD); + await bankField.selectOption(bank); + } + }, + + selectAdditionalPaymentMethod: async (page: Page, method: string) => { + const stripeFrame = await page.frameLocator(SELECTORS.STRIPE_APM_FRAME_LOCATOR); + const additionalPaymentMethod = await stripeFrame.locator(SELECTORS.ADDITIONAL_PAYMENT_METHOD_DROP_DOWN); + await additionalPaymentMethod.selectOption(method); + }, + + selectEbanxPaymentMethod: async (page: Page, method: string) => { + const paymentMethod = await page.locator(SELECTORS.EBANX_PAYMENT_METHOD_DROP_DOWN); + await paymentMethod.selectOption(method); + } +} + +export const authorizationPage = { + clickOnAuthorizeButton: async (page: Page) => { + await page.waitForTimeout(3000); + const authorizeButton = await page.locator(SELECTORS.AUTHORIZE_BUTTON); + await expect(authorizeButton).toBeVisible({ timeout: 10000 }); + await authorizeButton.click(); + }, + clickOnDenyButton: async (page: Page) => { + await page.waitForTimeout(3000); + const denyButton = await page.locator(SELECTORS.DENY_BUTTON); + await expect(denyButton).toBeVisible({ timeout: 10000 }); + await denyButton.click(); + }, + clickOnNupayAuthorizeYesButton: async (page: Page) => { + await expect(page.locator(SELECTORS.NUPAY_TEST_ENVIRONMENT_SIMULATOR)).toBeVisible({ timeout: 10000 }); + const nupayAuthorizeYesButton = await page.locator(SELECTORS.NUPAY_AUTHORIZE_YES_BUTTON); + await expect(nupayAuthorizeYesButton).toBeVisible({ timeout: 10000 }); + await nupayAuthorizeYesButton.click(); + }, + clickOnNupayAuthorizeNoButton: async (page: Page) => { + await expect(page.locator(SELECTORS.NUPAY_TEST_ENVIRONMENT_SIMULATOR)).toBeVisible({ timeout: 10000 }); + const nupayAuthorizeNoButton = await page.locator(SELECTORS.NUPAY_AUTHORIZE_NO_BUTTON); + await expect(nupayAuthorizeNoButton).toBeVisible({ timeout: 10000 }); + await nupayAuthorizeNoButton.click(); + }, + clickOnNupayAuthorizePendingButton: async (page: Page) => { + await expect(page.locator(SELECTORS.NUPAY_TEST_ENVIRONMENT_SIMULATOR)).toBeVisible({ timeout: 10000 }); + const nupayAuthorizePendingButton = await page.locator(SELECTORS.NUPAY_AUTHORIZE_PENDING_BUTTON); + await expect(nupayAuthorizePendingButton).toBeVisible({ timeout: 10000 }); + await nupayAuthorizePendingButton.click(); + } +} + +export const redirectResultPage = { + waitForRedirectResultPage: async (page: Page) => { + await page.waitForTimeout(5000); + await expect(page.locator(SELECTORS.REDIRECT_TITLE)).toBeVisible({ timeout: 10000 }); + }, + + getRedirectResultPageType: async (page: Page): Promise<'success' | 'failed' | 'pending'> => { + await page.waitForTimeout(5000); + await redirectResultPage.waitForRedirectResultPage(page); + const redirectTitle = await page.locator(SELECTORS.REDIRECT_TITLE); + const redirectMessage = await redirectTitle.textContent(); + if (await redirectTitle.count() > 0 && await redirectMessage=='Payment Successful') { + return 'success'; + + } + else if (await redirectTitle.count() > 0 && await redirectMessage=='Payment Failed') { + return 'failed'; + } + else if (await redirectTitle.count() > 0 && await redirectMessage=='Payment Pending') { + return 'pending'; + } + else { + throw new Error('Unable to determine redirect result page type'); + } + }, + + getTransactionDetailsRow: async (page: Page, row: string) => { + return page.locator(`.detail-label:text-is("${row}") + .detail-value` ) + }, + + getStatusRow: async (page: Page) => { + return page.locator(`.detail-label:has-text("Status") + .status-badge` ) + }, + + verifyTransactionDetails: async (page: Page, paymentMethod: string, gatewayMethod: string, resultStatus: string) => { + const paymentMethodRow = await redirectResultPage.getTransactionDetailsRow(page, 'Payment Method'); + const paymentMethodValue = await paymentMethodRow.textContent(); + await expect(paymentMethodValue).toBe(paymentMethod); + const gatewayRow = await redirectResultPage.getTransactionDetailsRow(page, 'Gateway'); + const gatewayValue = await gatewayRow.textContent(); + await expect(gatewayValue).toBe(gatewayMethod); + const statusRow = await redirectResultPage.getStatusRow(page); + const statusValue = await statusRow.textContent(); + await expect(statusValue).toBe(resultStatus); + }, + + +} diff --git a/test/ui/testCases/3ds-gateway-specific.spec.ts b/test/ui/testCases/3ds-gateway-specific.spec.ts new file mode 100644 index 0000000..7fc929e --- /dev/null +++ b/test/ui/testCases/3ds-gateway-specific.spec.ts @@ -0,0 +1,410 @@ +import { purchasePage } from "../pages/3dsPage"; +import { landingPage } from "../pages/landingPage"; +import { test, expect } from "../util/fixtures"; +import { TEST_DATA, waitForAuthParams, getValidYearString, SELECTORS } from "../util/test-constants"; +import { MONOREPO_URLS } from "../util/urls"; +import { helperFunctions } from "../util/utils"; +import { tokenizePage } from "../pages/tokenizePage"; +import { threeDSGatewayPage } from "../pages/3dsGatewayPage"; + +test.describe('3DS gateway specific flow', () => { + test('3DS gateway specific flow for hosted fields Frictionless Flow (3001) case', async ({ page }) => { + await page.goto(MONOREPO_URLS.BASE); + await landingPage.clickOn3DSGatewaySpecificButton(page); + await waitForAuthParams(page); + await threeDSGatewayPage.selectTheTransactionAmount(page, '3001'); + await helperFunctions.clickOnNewCardButton(page); + await helperFunctions.fillHostedFieldsForm(page, TEST_DATA.THREE_DS2_GATEWAY_SPECIFIC_VALID_CARD_NUMBER, { + firstName: TEST_DATA.FIRST_NAME, + lastName: TEST_DATA.LAST_NAME, + cvv: TEST_DATA.CVV, + expiryMonth: TEST_DATA.EXPIRY_MONTH, + expiryYear: getValidYearString(), + }); + await helperFunctions.verifyFormFieldsHostedFields(page, TEST_DATA.THREE_DS2_GATEWAY_SPECIFIC_VALID_CARD_NUMBER, { + firstName: TEST_DATA.FIRST_NAME, + lastName: TEST_DATA.LAST_NAME, + cvv: TEST_DATA.CVV, + expiryMonth: TEST_DATA.EXPIRY_MONTH, + expiryYear: getValidYearString(), + }); + let apiResponse: any = null; + page.on('response', async (response) => { + const url = response.url(); + if (url.includes('/status.json')) { + try { + apiResponse = await response.json(); + console.log('API Request URL:', url); + } catch (error) { + console.log('Response is not JSON or empty'); + } + } + }); + await helperFunctions.clickOnThreeDS2PayButton(page); + await purchasePage.waitForResultPage(page); + const resultPageType = await purchasePage.getResultPageType(page); + expect(resultPageType).toBe('success'); + if (apiResponse) { + expect(apiResponse).toBeDefined(); + expect(apiResponse).not.toBeNull(); + const state = apiResponse.transaction.state; + expect(state).toBe('succeeded'); + } + }) + + test('3DS gateway specific flow for hosted fields Challenge Flow (3003) Fingerprint authorize case', async ({ page }) => { + await page.goto(MONOREPO_URLS.BASE); + await landingPage.clickOn3DSGatewaySpecificButton(page); + await waitForAuthParams(page); + await threeDSGatewayPage.selectTheTransactionAmount(page, '3003'); + await helperFunctions.clickOnNewCardButton(page); + await helperFunctions.fillHostedFieldsForm(page, TEST_DATA.THREE_DS2_GATEWAY_SPECIFIC_VALID_CARD_NUMBER, { + firstName: TEST_DATA.FIRST_NAME, + lastName: TEST_DATA.LAST_NAME, + cvv: TEST_DATA.CVV, + expiryMonth: TEST_DATA.EXPIRY_MONTH, + expiryYear: getValidYearString(), + }); + await helperFunctions.verifyFormFieldsHostedFields(page, TEST_DATA.THREE_DS2_GATEWAY_SPECIFIC_VALID_CARD_NUMBER, { + firstName: TEST_DATA.FIRST_NAME, + lastName: TEST_DATA.LAST_NAME, + cvv: TEST_DATA.CVV, + expiryMonth: TEST_DATA.EXPIRY_MONTH, + expiryYear: getValidYearString(), + }); + let apiResponse: any = null; + page.on('response', async (response) => { + const url = response.url(); + if (url.includes('/complete')) { + try { + apiResponse = await response.json(); + } catch (error) { + console.log('Response is not JSON or empty'); + } + } + }); + await helperFunctions.clickOnThreeDS2PayButton(page); + await purchasePage.waitForResultPage(page); + const resultPageType = await purchasePage.getResultPageType(page); + expect(resultPageType).toBe('success'); + if (apiResponse) { + expect(apiResponse).toBeDefined(); + expect(apiResponse).not.toBeNull(); + const state = apiResponse.transaction.state; + expect(state).toBe('succeeded'); + } + }) + + test('3DS gateway specific flow for hosted fields Challenge Flow (3004) Fingerprint challenge success case', async ({ page }) => { + await page.goto(MONOREPO_URLS.BASE); + await landingPage.clickOn3DSGatewaySpecificButton(page); + await waitForAuthParams(page); + await threeDSGatewayPage.selectTheTransactionAmount(page, '3004'); + await helperFunctions.clickOnNewCardButton(page); + await helperFunctions.fillHostedFieldsForm(page, TEST_DATA.THREE_DS2_GATEWAY_SPECIFIC_VALID_CARD_NUMBER, { + firstName: TEST_DATA.FIRST_NAME, + lastName: TEST_DATA.LAST_NAME, + cvv: TEST_DATA.CVV, + expiryMonth: TEST_DATA.EXPIRY_MONTH, + expiryYear: getValidYearString(), + }); + await helperFunctions.verifyFormFieldsHostedFields(page, TEST_DATA.THREE_DS2_GATEWAY_SPECIFIC_VALID_CARD_NUMBER, { + firstName: TEST_DATA.FIRST_NAME, + lastName: TEST_DATA.LAST_NAME, + cvv: TEST_DATA.CVV, + expiryMonth: TEST_DATA.EXPIRY_MONTH, + expiryYear: getValidYearString(), + }); + let apiResponse: any = null; + page.on('response', async (response) => { + const url = response.url(); + if (url.includes('/status.json')) { + try { + apiResponse = await response.json(); + } catch (error) { + console.log('Response is not JSON or empty'); + } + } + }); + await helperFunctions.clickOnThreeDS2PayButton(page); + await threeDSGatewayPage.waitForAcsChallengeForm(page); + await threeDSGatewayPage.clickOnAllowButton(page); + await purchasePage.waitForResultPage(page); + const resultPageType = await purchasePage.getResultPageType(page); + expect(resultPageType).toBe('success'); + if (apiResponse) { + expect(apiResponse).toBeDefined(); + expect(apiResponse).not.toBeNull(); + const state = apiResponse.transaction.state; + expect(state).toBe('succeeded'); + } + }) + + test('3DS gateway specific flow for hosted fields Challenge Flow (3004) Fingerprint challenge failure case', async ({ page }) => { + await page.goto(MONOREPO_URLS.BASE); + await landingPage.clickOn3DSGatewaySpecificButton(page); + await waitForAuthParams(page); + await threeDSGatewayPage.selectTheTransactionAmount(page, '3004'); + await helperFunctions.clickOnNewCardButton(page); + await helperFunctions.fillHostedFieldsForm(page, TEST_DATA.THREE_DS2_GATEWAY_SPECIFIC_VALID_CARD_NUMBER, { + firstName: TEST_DATA.FIRST_NAME, + lastName: TEST_DATA.LAST_NAME, + cvv: TEST_DATA.CVV, + expiryMonth: TEST_DATA.EXPIRY_MONTH, + expiryYear: getValidYearString(), + }); + await helperFunctions.verifyFormFieldsHostedFields(page, TEST_DATA.THREE_DS2_GATEWAY_SPECIFIC_VALID_CARD_NUMBER, { + firstName: TEST_DATA.FIRST_NAME, + lastName: TEST_DATA.LAST_NAME, + cvv: TEST_DATA.CVV, + expiryMonth: TEST_DATA.EXPIRY_MONTH, + expiryYear: getValidYearString(), + }); + let apiResponse: any = null; + page.on('response', async (response) => { + const url = response.url(); + if (url.includes('/status.json')) { + try { + apiResponse = await response.json(); + } catch (error) { + console.log('Response is not JSON or empty'); + } + } + }); + await helperFunctions.clickOnThreeDS2PayButton(page); + await threeDSGatewayPage.waitForAcsChallengeForm(page); + await threeDSGatewayPage.clickOnDenyButton(page); + await purchasePage.waitForResultPage(page); + const resultPageType = await purchasePage.getResultPageType(page); + expect(resultPageType).toBe('error'); + if (apiResponse) { + expect(apiResponse).toBeDefined(); + expect(apiResponse).not.toBeNull(); + const state = apiResponse.transaction.state; + expect(state).toBe('gateway_processing_failed'); + } + }) + + test('3DS gateway specific flow for hosted fields Challenge Flow (3005) Direct challenge success case', async ({ page }) => { + await page.goto(MONOREPO_URLS.BASE); + await landingPage.clickOn3DSGatewaySpecificButton(page); + await waitForAuthParams(page); + await threeDSGatewayPage.selectTheTransactionAmount(page, '3005'); + await helperFunctions.clickOnNewCardButton(page); + await helperFunctions.fillHostedFieldsForm(page, TEST_DATA.THREE_DS2_GATEWAY_SPECIFIC_VALID_CARD_NUMBER, { + firstName: TEST_DATA.FIRST_NAME, + lastName: TEST_DATA.LAST_NAME, + cvv: TEST_DATA.CVV, + expiryMonth: TEST_DATA.EXPIRY_MONTH, + expiryYear: getValidYearString(), + }); + await helperFunctions.verifyFormFieldsHostedFields(page, TEST_DATA.THREE_DS2_GATEWAY_SPECIFIC_VALID_CARD_NUMBER, { + firstName: TEST_DATA.FIRST_NAME, + lastName: TEST_DATA.LAST_NAME, + cvv: TEST_DATA.CVV, + expiryMonth: TEST_DATA.EXPIRY_MONTH, + expiryYear: getValidYearString(), + }); + let apiResponse: any = null; + page.on('response', async (response) => { + const url = response.url(); + if (url.includes('/status.json')) { + try { + apiResponse = await response.json(); + } catch (error) { + console.log('Response is not JSON or empty'); + } + } + }); + await helperFunctions.clickOnThreeDS2PayButton(page); + await threeDSGatewayPage.waitForAcsChallengeForm(page); + await threeDSGatewayPage.clickOnAllowButton(page); + await purchasePage.waitForResultPage(page); + const resultPageType = await purchasePage.getResultPageType(page); + expect(resultPageType).toBe('success'); + if (apiResponse) { + expect(apiResponse).toBeDefined(); + expect(apiResponse).not.toBeNull(); + const state = apiResponse.transaction.state; + expect(state).toBe('succeeded'); + } + }) + + test('3DS gateway specific flow for hosted fields Challenge Flow (3005) Direct challenge failure case', async ({ page }) => { + await page.goto(MONOREPO_URLS.BASE); + await landingPage.clickOn3DSGatewaySpecificButton(page); + await waitForAuthParams(page); + await threeDSGatewayPage.selectTheTransactionAmount(page, '3005'); + await helperFunctions.clickOnNewCardButton(page); + await helperFunctions.fillHostedFieldsForm(page, TEST_DATA.THREE_DS2_GATEWAY_SPECIFIC_VALID_CARD_NUMBER, { + firstName: TEST_DATA.FIRST_NAME, + lastName: TEST_DATA.LAST_NAME, + cvv: TEST_DATA.CVV, + expiryMonth: TEST_DATA.EXPIRY_MONTH, + expiryYear: getValidYearString(), + }); + await helperFunctions.verifyFormFieldsHostedFields(page, TEST_DATA.THREE_DS2_GATEWAY_SPECIFIC_VALID_CARD_NUMBER, { + firstName: TEST_DATA.FIRST_NAME, + lastName: TEST_DATA.LAST_NAME, + cvv: TEST_DATA.CVV, + expiryMonth: TEST_DATA.EXPIRY_MONTH, + expiryYear: getValidYearString(), + }); + let apiResponse: any = null; + page.on('response', async (response) => { + const url = response.url(); + if (url.includes('/status.json')) { + try { + apiResponse = await response.json(); + } catch (error) { + console.log('Response is not JSON or empty'); + } + } + }); + await helperFunctions.clickOnThreeDS2PayButton(page); + await threeDSGatewayPage.waitForAcsChallengeForm(page); + await threeDSGatewayPage.clickOnDenyButton(page); + await purchasePage.waitForResultPage(page); + const resultPageType = await purchasePage.getResultPageType(page); + expect(resultPageType).toBe('error'); + if (apiResponse) { + expect(apiResponse).toBeDefined(); + expect(apiResponse).not.toBeNull(); + const state = apiResponse.transaction.state; + expect(state).toBe('gateway_processing_failed'); + } + }) + + test('3DS gateway specific flow for hosted fields Challenge Flow (3103) Fingerprint authorize failure case', async ({ page }) => { + await page.goto(MONOREPO_URLS.BASE); + await landingPage.clickOn3DSGatewaySpecificButton(page); + await waitForAuthParams(page); + await threeDSGatewayPage.selectTheTransactionAmount(page, '3103'); + await helperFunctions.clickOnNewCardButton(page); + await helperFunctions.fillHostedFieldsForm(page, TEST_DATA.THREE_DS2_GATEWAY_SPECIFIC_VALID_CARD_NUMBER, { + firstName: TEST_DATA.FIRST_NAME, + lastName: TEST_DATA.LAST_NAME, + cvv: TEST_DATA.CVV, + expiryMonth: TEST_DATA.EXPIRY_MONTH, + expiryYear: getValidYearString(), + }); + await helperFunctions.verifyFormFieldsHostedFields(page, TEST_DATA.THREE_DS2_GATEWAY_SPECIFIC_VALID_CARD_NUMBER, { + firstName: TEST_DATA.FIRST_NAME, + lastName: TEST_DATA.LAST_NAME, + cvv: TEST_DATA.CVV, + expiryMonth: TEST_DATA.EXPIRY_MONTH, + expiryYear: getValidYearString(), + }); + let apiResponse: any = null; + page.on('response', async (response) => { + const url = response.url(); + if (url.includes('/complete')) { + try { + apiResponse = await response.json(); + } catch (error) { + console.log('Response is not JSON or empty'); + } + } + }); + await helperFunctions.clickOnThreeDS2PayButton(page); + await purchasePage.waitForResultPage(page); + const resultPageType = await purchasePage.getResultPageType(page); + expect(resultPageType).toBe('error'); + if (apiResponse) { + expect(apiResponse).toBeDefined(); + expect(apiResponse).not.toBeNull(); + const state = apiResponse.transaction.state; + expect(state).toBe('gateway_processing_failed'); + } + }) + + test('3DS gateway specific flow for hosted fields Challenge Flow (3104) challenge failure allow case', async ({ page }) => { + await page.goto(MONOREPO_URLS.BASE); + await landingPage.clickOn3DSGatewaySpecificButton(page); + await waitForAuthParams(page); + await threeDSGatewayPage.selectTheTransactionAmount(page, '3104'); + await helperFunctions.clickOnNewCardButton(page); + await helperFunctions.fillHostedFieldsForm(page, TEST_DATA.THREE_DS2_GATEWAY_SPECIFIC_VALID_CARD_NUMBER, { + firstName: TEST_DATA.FIRST_NAME, + lastName: TEST_DATA.LAST_NAME, + cvv: TEST_DATA.CVV, + expiryMonth: TEST_DATA.EXPIRY_MONTH, + expiryYear: getValidYearString(), + }); + await helperFunctions.verifyFormFieldsHostedFields(page, TEST_DATA.THREE_DS2_GATEWAY_SPECIFIC_VALID_CARD_NUMBER, { + firstName: TEST_DATA.FIRST_NAME, + lastName: TEST_DATA.LAST_NAME, + cvv: TEST_DATA.CVV, + expiryMonth: TEST_DATA.EXPIRY_MONTH, + expiryYear: getValidYearString(), + }); + let apiResponse: any = null; + page.on('response', async (response) => { + const url = response.url(); + if (url.includes('/status.json')) { + try { + apiResponse = await response.json(); + } catch (error) { + console.log('Response is not JSON or empty'); + } + } + }); + await helperFunctions.clickOnThreeDS2PayButton(page); + await threeDSGatewayPage.waitForAcsChallengeForm(page); + await threeDSGatewayPage.clickOnAllowButton(page); + await purchasePage.waitForResultPage(page); + const resultPageType = await purchasePage.getResultPageType(page); + expect(resultPageType).toBe('error'); + if (apiResponse) { + expect(apiResponse).toBeDefined(); + expect(apiResponse).not.toBeNull(); + const state = apiResponse.transaction.state; + expect(state).toBe('gateway_processing_failed'); + } + }) + + test('3DS gateway specific flow for hosted fields Challenge Flow (3104) challenge failure deny case', async ({ page }) => { + await page.goto(MONOREPO_URLS.BASE); + await landingPage.clickOn3DSGatewaySpecificButton(page); + await waitForAuthParams(page); + await threeDSGatewayPage.selectTheTransactionAmount(page, '3104'); + await helperFunctions.clickOnNewCardButton(page); + await helperFunctions.fillHostedFieldsForm(page, TEST_DATA.THREE_DS2_GATEWAY_SPECIFIC_VALID_CARD_NUMBER, { + firstName: TEST_DATA.FIRST_NAME, + lastName: TEST_DATA.LAST_NAME, + cvv: TEST_DATA.CVV, + expiryMonth: TEST_DATA.EXPIRY_MONTH, + expiryYear: getValidYearString(), + }); + await helperFunctions.verifyFormFieldsHostedFields(page, TEST_DATA.THREE_DS2_GATEWAY_SPECIFIC_VALID_CARD_NUMBER, { + firstName: TEST_DATA.FIRST_NAME, + lastName: TEST_DATA.LAST_NAME, + cvv: TEST_DATA.CVV, + expiryMonth: TEST_DATA.EXPIRY_MONTH, + expiryYear: getValidYearString(), + }); + let apiResponse: any = null; + page.on('response', async (response) => { + const url = response.url(); + if (url.includes('/status.json')) { + try { + apiResponse = await response.json(); + } catch (error) { + console.log('Response is not JSON or empty'); + } + } + }); + await helperFunctions.clickOnThreeDS2PayButton(page); + await threeDSGatewayPage.waitForAcsChallengeForm(page); + await threeDSGatewayPage.clickOnDenyButton(page); + await purchasePage.waitForResultPage(page); + const resultPageType = await purchasePage.getResultPageType(page); + expect(resultPageType).toBe('error'); + if (apiResponse) { + expect(apiResponse).toBeDefined(); + expect(apiResponse).not.toBeNull(); + const state = apiResponse.transaction.state; + expect(state).toBe('gateway_processing_failed'); + } + }) +}) \ No newline at end of file diff --git a/test/ui/testCases/offsite-payments.spec.ts b/test/ui/testCases/offsite-payments.spec.ts new file mode 100644 index 0000000..cfd45b3 --- /dev/null +++ b/test/ui/testCases/offsite-payments.spec.ts @@ -0,0 +1,278 @@ +import { test, expect } from '../util/fixtures'; +import { landingPage } from '../pages/landingPage'; +import { SELECTORS } from '../util/test-constants'; +import { MONOREPO_URLS } from '../util/urls'; +import { authorizationPage, paymentPage, redirectResultPage } from '../pages/offsitePaymentsPage'; +import { TEST_DATA, waitForAuthParams } from '../util/test-constants'; + +test.describe('offsite payments flow', () => { + + test('offsite payments flow for hosted fields PayPal success case', async ({ page }) => { + await page.goto(MONOREPO_URLS.BASE); + await landingPage.clickOnExpressCheckoutButton(page); + await landingPage.clickOnOffsitePaymentsButton(page); + await waitForAuthParams(page); + await page.locator(SELECTORS.PAYPAL_BUTTON).first().click(); + await page.locator(SELECTORS.HOSTED_SUBMIT_BUTTON).click(); + await expect(page.getByPlaceholder('Email or mobile number')).toBeVisible({ timeout: 10000 }); + // await page.getByPlaceholder('Email or mobile number').fill('.example.com'); + // await page.locator('#btnNext').click(); + // await page.getByPlaceholder('Password').fill(''); + // const paypalPasswordSubmit = page + // .locator('#btnLogin') + // .or(page.locator('button[type="submit"][value="submitPassword"]')); + // await expect(paypalPasswordSubmit).toBeEnabled(); + // await paypalPasswordSubmit.click(); + // await expect(page.getByTestId('submit-button-initial')).toBeVisible(); + // await page.getByTestId('submit-button-initial').click(); + // const redirectResultPageType = await redirectResultPage.getRedirectResultPageType(page); + // expect(redirectResultPageType).toBe('success'); + }) + + test('offsite payments flow for hosted fields Stripe APM SEPA Debit', async ({ page }) => { + await page.goto(MONOREPO_URLS.BASE); + await landingPage.clickOnOffsitePaymentsButton(page); + await waitForAuthParams(page); + await paymentPage.selectOffsitePaymentMethod(page, 'Stripe APM'); + await paymentPage.clickSubmitButton(page); + await paymentPage.selectStripeMethod(page, 'sepa_debit'); + await paymentPage.fillPaymentForm(page, TEST_DATA.STRIPE_APM_NAME, TEST_DATA.STRIPE_APM_IBAN, TEST_DATA.STRIPE_APM_EMAIL, TEST_DATA.STRIPE_APM_SEPA_COUNTRY, TEST_DATA.SHIPPING_ADDRESS, TEST_DATA.STRIPE_APM_CITY, TEST_DATA.STRIPE_APM_SEPA_COUNTRY_STATE, TEST_DATA.STRIPE_APM_ZIP, ); + await paymentPage.clickSubmitButton(page); + await redirectResultPage.waitForRedirectResultPage(page); + const redirectResultPageType = await redirectResultPage.getRedirectResultPageType(page); + expect(redirectResultPageType).toBe('success'); + await redirectResultPage.verifyTransactionDetails(page, 'Stripe APM', 'stripe_payment_intents', 'succeeded'); + }) + + test('offsite payments flow for hosted fields Stripe APM SEPA Debit deny case', async ({ page }) => { + await page.goto(MONOREPO_URLS.BASE); + await landingPage.clickOnOffsitePaymentsButton(page); + await waitForAuthParams(page); + await paymentPage.selectOffsitePaymentMethod(page, 'Stripe APM'); + await paymentPage.clickSubmitButton(page); + await paymentPage.selectStripeMethod(page, 'sepa_debit'); + await paymentPage.fillPaymentForm(page, TEST_DATA.STRIPE_APM_NAME, TEST_DATA.STRIPE_APM_IBAN, TEST_DATA.STRIPE_APM_EMAIL, TEST_DATA.STRIPE_APM_SEPA_COUNTRY, TEST_DATA.SHIPPING_ADDRESS, TEST_DATA.STRIPE_APM_CITY, TEST_DATA.STRIPE_APM_SEPA_COUNTRY_STATE, TEST_DATA.STRIPE_APM_ZIP, ); + await paymentPage.clickSubmitButton(page); + await expect(page.locator(SELECTORS.DENY_BUTTON)).toBeVisible(); + await authorizationPage.clickOnDenyButton(page); + await redirectResultPage.waitForRedirectResultPage(page); + const redirectResultPageType = await redirectResultPage.getRedirectResultPageType(page); + expect(redirectResultPageType).toBe('failed'); + await redirectResultPage.verifyTransactionDetails(page, 'Stripe APM', 'stripe_payment_intents', 'failed'); + }) + + test('offsite payments flow for hosted fields Stripe APM iDEAL Wero authorize case', async ({ page }) => { + await page.goto(MONOREPO_URLS.BASE); + await landingPage.clickOnOffsitePaymentsButton(page); + await waitForAuthParams(page); + await paymentPage.selectOffsitePaymentMethod(page, 'Stripe APM'); + await paymentPage.clickSubmitButton(page); + await paymentPage.selectStripeMethod(page, 'ideal'); + await paymentPage.fillPaymentForm(page, TEST_DATA.STRIPE_APM_NAME) + await paymentPage.clickSubmitButton(page); + await expect(page.locator(SELECTORS.AUTHORIZE_BUTTON)).toBeVisible(); + await authorizationPage.clickOnAuthorizeButton(page); + const redirectResultPageType = await redirectResultPage.getRedirectResultPageType(page); + expect(redirectResultPageType).toBe('success'); + await redirectResultPage.verifyTransactionDetails(page, 'Stripe APM', 'stripe_payment_intents', 'succeeded'); + }) + + test('offsite payments flow for hosted fields Stripe APM iDEAL Wero deny case', async ({ page }) => { + await page.goto(MONOREPO_URLS.BASE); + await landingPage.clickOnOffsitePaymentsButton(page); + await waitForAuthParams(page); + await paymentPage.selectOffsitePaymentMethod(page, 'Stripe APM'); + await paymentPage.clickSubmitButton(page); + await paymentPage.selectStripeMethod(page, 'ideal'); + await paymentPage.fillPaymentForm(page, TEST_DATA.STRIPE_APM_NAME) + await paymentPage.clickSubmitButton(page); + await expect(page.locator(SELECTORS.DENY_BUTTON)).toBeVisible(); + await authorizationPage.clickOnDenyButton(page); + const redirectResultPageType = await redirectResultPage.getRedirectResultPageType(page); + await expect(redirectResultPageType).toBe('failed'); + await redirectResultPage.verifyTransactionDetails(page, 'Stripe APM', 'stripe_payment_intents', 'failed'); + }) + + test('offsite payments flow for hosted fields Stripe APM Bancontact authorize case', async ({ page }) => { + await page.goto(MONOREPO_URLS.BASE); + await landingPage.clickOnOffsitePaymentsButton(page); + await waitForAuthParams(page); + await paymentPage.selectOffsitePaymentMethod(page, 'Stripe APM'); + await paymentPage.clickSubmitButton(page); + await paymentPage.selectStripeMethod(page, 'bancontact'); + await paymentPage.fillPaymentForm(page, TEST_DATA.STRIPE_APM_NAME) + await paymentPage.clickSubmitButton(page); + await expect(page.locator(SELECTORS.AUTHORIZE_BUTTON)).toBeVisible(); + await authorizationPage.clickOnAuthorizeButton(page); + const redirectResultPageType = await redirectResultPage.getRedirectResultPageType(page); + await expect(redirectResultPageType).toBe('success'); + await redirectResultPage.verifyTransactionDetails(page, 'Stripe APM', 'stripe_payment_intents', 'succeeded'); + }) + + test('offsite payments flow for hosted fields Stripe APM Bancontact deny case', async ({ page }) => { + await page.goto(MONOREPO_URLS.BASE); + await landingPage.clickOnOffsitePaymentsButton(page); + await waitForAuthParams(page); + await paymentPage.selectOffsitePaymentMethod(page, 'Stripe APM'); + await paymentPage.clickSubmitButton(page); + await paymentPage.selectStripeMethod(page, 'bancontact'); + await paymentPage.fillPaymentForm(page, TEST_DATA.STRIPE_APM_NAME) + await paymentPage.clickSubmitButton(page); + await expect(page.locator(SELECTORS.DENY_BUTTON)).toBeVisible(); + await authorizationPage.clickOnDenyButton(page); + const redirectResultPageType = await redirectResultPage.getRedirectResultPageType(page); + await expect(redirectResultPageType).toBe('failed'); + await redirectResultPage.verifyTransactionDetails(page, 'Stripe APM', 'stripe_payment_intents', 'failed'); + }) + + test('offsite payments flow for hosted fields Stripe APM EPS authorize case', async ({ page }) => { + await page.goto(MONOREPO_URLS.BASE); + await landingPage.clickOnOffsitePaymentsButton(page); + await waitForAuthParams(page); + await paymentPage.selectOffsitePaymentMethod(page, 'Stripe APM'); + await paymentPage.clickSubmitButton(page); + await paymentPage.selectStripeMethod(page, 'eps'); + await paymentPage.fillPaymentForm(page, TEST_DATA.STRIPE_APM_NAME,undefined,undefined,undefined,undefined,undefined, + undefined,undefined,TEST_DATA.STRIPE_APM_BANK_NAME_EPS); + await paymentPage.clickSubmitButton(page); + await expect(page.locator(SELECTORS.AUTHORIZE_BUTTON)).toBeVisible(); + await authorizationPage.clickOnAuthorizeButton(page); + const redirectResultPageType = await redirectResultPage.getRedirectResultPageType(page); + await expect(redirectResultPageType).toBe('success'); + await redirectResultPage.verifyTransactionDetails(page, 'Stripe APM', 'stripe_payment_intents', 'succeeded'); + }) + + test('offsite payments flow for hosted fields Stripe APM EPS deny case', async ({ page }) => { + await page.goto(MONOREPO_URLS.BASE); + await landingPage.clickOnOffsitePaymentsButton(page); + await waitForAuthParams(page); + await paymentPage.selectOffsitePaymentMethod(page, 'Stripe APM'); + await paymentPage.clickSubmitButton(page); + await paymentPage.selectStripeMethod(page, 'eps'); + await paymentPage.fillPaymentForm(page, TEST_DATA.STRIPE_APM_NAME,undefined,undefined,undefined,undefined,undefined, + undefined,undefined,TEST_DATA.STRIPE_APM_BANK_NAME_EPS); + await paymentPage.clickSubmitButton(page); + await expect(page.locator(SELECTORS.DENY_BUTTON)).toBeVisible(); + await authorizationPage.clickOnDenyButton(page); + const redirectResultPageType = await redirectResultPage.getRedirectResultPageType(page); + await expect(redirectResultPageType).toBe('failed'); + await redirectResultPage.verifyTransactionDetails(page, 'Stripe APM', 'stripe_payment_intents', 'failed'); + }) + + test('offsite payments flow for hosted fields Stripe APM Przelewy24 authorize case', async ({ page }) => { + await page.goto(MONOREPO_URLS.BASE); + await landingPage.clickOnOffsitePaymentsButton(page); + await waitForAuthParams(page); + await paymentPage.selectOffsitePaymentMethod(page, 'Stripe APM'); + await paymentPage.clickSubmitButton(page); + await paymentPage.selectAdditionalPaymentMethod(page, 'Przelewy24'); + await paymentPage.fillPaymentForm(page, TEST_DATA.STRIPE_APM_NAME,undefined,TEST_DATA.STRIPE_APM_EMAIL,undefined,undefined,undefined, + undefined,undefined,TEST_DATA.STRIPE_APM_BANK_NAME_PRZELEWY24); + await page.waitForTimeout(5000); + await paymentPage.clickSubmitButton(page); + await page.waitForTimeout(10000); + await expect(page.locator(SELECTORS.AUTHORIZE_BUTTON)).toBeVisible(); + await authorizationPage.clickOnAuthorizeButton(page); + const redirectResultPageType = await redirectResultPage.getRedirectResultPageType(page); + await expect(redirectResultPageType).toBe('success'); + await redirectResultPage.verifyTransactionDetails(page, 'Stripe APM', 'stripe_payment_intents', 'succeeded'); + }) + + test('offsite payments flow for hosted fields Stripe APM Przelewy24 deny case', async ({ page }) => { + await page.goto(MONOREPO_URLS.BASE); + await landingPage.clickOnOffsitePaymentsButton(page); + await waitForAuthParams(page); + await paymentPage.selectOffsitePaymentMethod(page, 'Stripe APM'); + await paymentPage.clickSubmitButton(page); + await paymentPage.selectAdditionalPaymentMethod(page, 'Przelewy24'); + await paymentPage.fillPaymentForm(page, TEST_DATA.STRIPE_APM_NAME,undefined,TEST_DATA.STRIPE_APM_EMAIL,undefined,undefined,undefined, + undefined,undefined,TEST_DATA.STRIPE_APM_BANK_NAME_PRZELEWY24); + await paymentPage.clickSubmitButton(page); + await expect(page.locator(SELECTORS.DENY_BUTTON)).toBeVisible(); + await authorizationPage.clickOnDenyButton(page); + const redirectResultPageType = await redirectResultPage.getRedirectResultPageType(page); + await expect(redirectResultPageType).toBe('failed'); + await redirectResultPage.verifyTransactionDetails(page, 'Stripe APM', 'stripe_payment_intents', 'failed'); + }) + + test('offsite payments flow for hosted fields ebanx oxxo', async ({ page }) => { + await page.goto(MONOREPO_URLS.BASE); + await landingPage.clickOnOffsitePaymentsButton(page); + await waitForAuthParams(page); + await paymentPage.selectOffsitePaymentMethod(page, 'EBANX'); + await paymentPage.clickSubmitButton(page); + await paymentPage.selectEbanxPaymentMethod(page, 'oxxo'); + await paymentPage.clickSubmitButton(page); + await expect(page.locator(SELECTORS.EBANX_OXXO_REDIRECT_PAGE_IMAGE)).toBeVisible(); + await expect(page.locator('h1:has-text("BOLETA EBANX")')).toBeVisible(); + }) + + test('offsite payments flow for hosted fields ebanx boleto bancario', async ({ page }) => { + await page.goto(MONOREPO_URLS.BASE); + await landingPage.clickOnOffsitePaymentsButton(page); + await waitForAuthParams(page); + await paymentPage.selectOffsitePaymentMethod(page, 'EBANX'); + await paymentPage.clickSubmitButton(page); + await paymentPage.selectEbanxPaymentMethod(page, 'boleto_bancario'); + await paymentPage.clickSubmitButton(page); + const redirectPageImage = await page.locator(SELECTORS.EBANX_BOLETO_BANCARIO_REDIRECT_PAGE_IMAGE).last(); + await expect(redirectPageImage).toBeVisible(); + const redirectPageTitle = await page.locator('h3:has-text("Banco Itaú S.A. | 341-7"),h3:has-text("Itaú Bank SA | 341-7")').last(); + await expect(redirectPageTitle).toBeVisible(); + }) + + test('offsite payments flow for hosted fields ebanx pix', async ({ page }) => { + await page.goto(MONOREPO_URLS.BASE); + await landingPage.clickOnOffsitePaymentsButton(page); + await waitForAuthParams(page); + await paymentPage.selectOffsitePaymentMethod(page, 'EBANX'); + await paymentPage.clickSubmitButton(page); + await paymentPage.selectEbanxPaymentMethod(page, 'pix'); + await paymentPage.clickSubmitButton(page); + await expect(page.locator(SELECTORS.EBANX_PIX_REDIRECT_PAGE_IMAGE)).toBeVisible(); + await expect(page.locator('h2:has-text("Código Pix gerado!"),h2:has-text("Pix code generated!")')).toBeVisible(); + }) + + test('offsite payments flow for hosted fields ebanx nupay authorize case yes case', async ({ page }) => { + await page.goto(MONOREPO_URLS.BASE); + await landingPage.clickOnOffsitePaymentsButton(page); + await waitForAuthParams(page); + await paymentPage.selectOffsitePaymentMethod(page, 'EBANX'); + await paymentPage.clickSubmitButton(page); + await paymentPage.selectEbanxPaymentMethod(page, 'nupay'); + await paymentPage.clickSubmitButton(page); + await authorizationPage.clickOnNupayAuthorizeYesButton(page); + const redirectResultPageType = await redirectResultPage.getRedirectResultPageType(page); + await expect(redirectResultPageType).toBe('success'); + await redirectResultPage.verifyTransactionDetails(page, 'NuPay (EBANX)', 'ebanx', 'succeeded'); + }) + + test('offsite payments flow for hosted fields ebanx nupay authorize case no case', async ({ page }) => { + await page.goto(MONOREPO_URLS.BASE); + await landingPage.clickOnOffsitePaymentsButton(page); + await waitForAuthParams(page); + await paymentPage.selectOffsitePaymentMethod(page, 'EBANX'); + await paymentPage.clickSubmitButton(page); + await paymentPage.selectEbanxPaymentMethod(page, 'nupay'); + await paymentPage.clickSubmitButton(page); + await authorizationPage.clickOnNupayAuthorizeNoButton(page); + const redirectResultPageType = await redirectResultPage.getRedirectResultPageType(page); + await expect(redirectResultPageType).toBe('failed'); + await redirectResultPage.verifyTransactionDetails(page, 'NuPay (EBANX)', 'ebanx', 'gateway_processing_failed'); + }) + + test('offsite payments flow for hosted fields ebanx nupay authorize case pending case', async ({ page }) => { + await page.goto(MONOREPO_URLS.BASE); + await landingPage.clickOnOffsitePaymentsButton(page); + await waitForAuthParams(page); + await paymentPage.selectOffsitePaymentMethod(page, 'EBANX'); + await paymentPage.clickSubmitButton(page); + await paymentPage.selectEbanxPaymentMethod(page, 'nupay'); + await paymentPage.clickSubmitButton(page); + await authorizationPage.clickOnNupayAuthorizePendingButton(page); + const redirectResultPageType = await redirectResultPage.getRedirectResultPageType(page); + await expect(redirectResultPageType).toBe('pending'); + await redirectResultPage.verifyTransactionDetails(page, 'NuPay (EBANX)', 'ebanx', 'gateway_processing_pending'); + }) + +}) \ No newline at end of file diff --git a/test/ui/util/fixtures.ts b/test/ui/util/fixtures.ts index 1183bdf..213ab4c 100644 --- a/test/ui/util/fixtures.ts +++ b/test/ui/util/fixtures.ts @@ -1,5 +1,4 @@ import { test as base, expect } from '@playwright/test'; -import { waitForAuthParams } from '../test-constants'; export const test = base; @@ -8,4 +7,4 @@ test.afterEach(async ({ page, context }) => { await context.clearPermissions(); }); -export { expect }; \ No newline at end of file +export { expect }; diff --git a/test/ui/util/test-constants.ts b/test/ui/util/test-constants.ts index 32e2cdb..8f61c85 100644 --- a/test/ui/util/test-constants.ts +++ b/test/ui/util/test-constants.ts @@ -72,6 +72,36 @@ export const SELECTORS = { THREE_DS2_PAY_BUTTON: ".btn-text", THREE_DS2_AUTHENTICATING_TEXT: '.btn-text:has-text("Authenticating...")', THREE_DS2_BUTTON_TEXT: '.btn-text', + THREE_DS_GATEWAY_SPECIFIC_ACS_SIMULATOR_IFRAME: 'iframe.challenge-iframe', + THREE_DS_GATEWAY_SPECIFIC_BUTTON: '[data-flow="purchase-with-3ds-gateway-specific"]', + THREE_DS_GATEWAY_SPECIFIC_ACS_SIMULATOR_FORM: 'h2:has-text("Spreedly ACS Simulator")', + THREE_DS_GATEWAY_SPECIFIC_ACS_SIMULATOR_ALLOW_BUTTON: 'input[value="Allow"]', + THREE_DS_GATEWAY_SPECIFIC_ACS_SIMULATOR_DENY_BUTTON: 'input[value="Deny"]', + STRIPE_APM_FRAME_LOCATOR: '.__PrivateStripeElement iframe', + OFFSITE_PAYMENTS_BUTTON: '[data-flow="offsite-payments"]', + PAYPAL_BUTTON: '.payment-method-name:has-text("PayPal")', + STRIPE_APM_BUTTON: '.payment-method-name:has-text("Stripe APM")', + STRIPE_APM_ADDRESS_FIELD: '#payment-addressLine1Input', + STRIPE_APM_CITY_FIELD: '#payment-localityInput', + STRIPE_APM_ZIP_FIELD: '#payment-postalCodeInput', + STRIPE_APM_COUNTRY_SELECTOR: '#payment-countryInput', + STRIPE_APM_COUNTRY_STATE_FIELD: '#payment-administrativeAreaInput', + STRIPE_APM_BANK_FIELD: '#payment-bankInput', + AUTHORIZE_BUTTON: 'a[data-testid="authorize-test-payment-button"]', + DENY_BUTTON: 'a[data-testid="fail-test-payment-button"]', + REDIRECT_TITLE: '#redirect-title', + ADDITIONAL_PAYMENT_METHOD_DROP_DOWN: '.p-AdditionalPaymentMethods-menu', + STRIPE_APM_EMAIL_FIELD: '#payment-emailInput', + EBANX_PAYMENT_METHOD_DROP_DOWN: '#payment-method-select', + EBANX_OXXO_REDIRECT_PAGE_IMAGE: '.oxxo-logo-img', + EBANX_BOLETO_BANCARIO_REDIRECT_PAGE_IMAGE: 'img[src*="logo_ebanx"]', + EBANX_PIX_REDIRECT_PAGE_IMAGE: 'img.voucher-header__logo[alt="Pix"]', + EBANX_PIX_REDIRECT_QR_CODE_IMAGE: 'img.qrc-code-img[alt="QR Code"]', + EBANX_NUPAY_REDIRECT_PAGE_IMAGE: 'p.nupay img[alt="NuPay"]', + NUPAY_TEST_ENVIRONMENT_SIMULATOR: 'h2:has-text("Test Environment Simulator")', + NUPAY_AUTHORIZE_YES_BUTTON: 'a:has-text("Authorized = YES")', + NUPAY_AUTHORIZE_NO_BUTTON: 'a:has-text("Authorized = NO")', + NUPAY_AUTHORIZE_PENDING_BUTTON: 'a:has-text("Leave Pending")', } as const; export const THREE_DS_SELECTORS = { @@ -108,6 +138,7 @@ export const THREE_DS_SELECTORS = { RESULT_ICON_SUCCESS: '.result-icon.success', RESULT_ICON_ERROR: '.result-icon.error', RESULT_TITLE_ERROR: '.result-title:has-text("Payment Failed")', + RESULT_TITLE_PENDING: '.result-title:has-text("Payment Pending")', MAKE_ANOTHER_PURCHASE_BUTTON: 'button:has-text("Make Another Purchase")', TRY_AGAIN_BUTTON: 'button:has-text("Try Again")', START_OVER_BUTTON: 'button:has-text("Start Over")', @@ -126,6 +157,11 @@ export const PLACEHOLDERS = { // Hosted Fields HOSTED_FIRST_NAME: "Enter first name", HOSTED_LAST_NAME: "Enter last name", + + // stripe apm + STRIPE_APM_IBAN: "DE00 0000 0000 0000 0000 00", + STRIPE_APM_NAME: "First and last name", + STRIPE_APM_EMAIL: "you@example.com", }; export const LABELS = { @@ -176,6 +212,17 @@ export const TEST_DATA = { THREE_DS2_FRUCTIONLESS_FAILURE_CARD_NUMBER: "5248 4811 1120 0179", THREE_DS2_CHALLENGE_FLOW_SUCCESS_PIN: "1234", THREE_DS2_CHALLENGE_FLOW_FAILED_PIN: "4567", + THREE_DS2_GATEWAY_SPECIFIC_VALID_CARD_NUMBER: "4556 7610 2998 3886", + THREE_DS2_GATEWAY_SPECIFIC_INVALID_CARD_NUMBER: "4024 0071 0193 4890", + STRIPE_APM_IBAN: "IE64 IRCE 9205 0112 3456 78", + STRIPE_APM_NAME: "John Doe", + STRIPE_APM_EMAIL: "john.doe@example.com", + STRIPE_APM_CITY: "Dublin", + STRIPE_APM_ZIP: "d02af30", + STRIPE_APM_SEPA_COUNTRY: "IE", + STRIPE_APM_SEPA_COUNTRY_STATE: "Dublin", + STRIPE_APM_BANK_NAME_EPS: "Bank Austria", + STRIPE_APM_BANK_NAME_PRZELEWY24: "alior_bank" }; export const HEADINGS = { diff --git a/test/ui/util/utils.ts b/test/ui/util/utils.ts index dcc5acd..2df76f9 100644 --- a/test/ui/util/utils.ts +++ b/test/ui/util/utils.ts @@ -235,7 +235,7 @@ export const PLACEHOLDERS = { return `${month}/${year.slice(-2)}`; }, - verifyResultCard: async (page: Page, cardFirstSixDigits, cardLastFourDigits, storageState: string, options?: { + verifyResultCard: async (page: Page, cardFirstSixDigits: string, cardLastFourDigits: string, storageState: string, options?: { expiryDate?: { year: string, month: string }; }) => { await expect(page.locator('.result-card')).toBeVisible(); @@ -332,4 +332,4 @@ export const PLACEHOLDERS = { expect(paymentMethod.managed).toBe(managed); expect(paymentMethod.number).toMatch(new RegExp(`XXXX-XXXX-XXXX-${number.slice(-4)}`)); }, -} \ No newline at end of file +}