diff --git a/cypress-tests/cypress/e2e/external-3DS-netcetera-e2e-test.cy.ts b/cypress-tests/cypress/e2e/external-3DS-netcetera-e2e-test.cy.ts new file mode 100644 index 00000000..333ceb20 --- /dev/null +++ b/cypress-tests/cypress/e2e/external-3DS-netcetera-e2e-test.cy.ts @@ -0,0 +1,81 @@ +import * as testIds from "../../../src/Utilities/TestUtils.bs"; +import { getClientURL, netceteraChallengeTestCard, createPaymentBody, changeObjectKeyValue, connectorProfileIdMapping, connectorEnum } from "../support/utils"; +describe("External 3DS using Netcetera Checks", () => { + let getIframeBody: () => Cypress.Chainable>; + const publishableKey = Cypress.env('HYPERSWITCH_PUBLISHABLE_KEY') + const secretKey = Cypress.env('HYPERSWITCH_SECRET_KEY') + changeObjectKeyValue(createPaymentBody, "profile_id", connectorProfileIdMapping.get(connectorEnum.NETCETERA)) + changeObjectKeyValue(createPaymentBody, "request_external_three_ds_authentication", true) + changeObjectKeyValue(createPaymentBody, "authentication_type", "three_ds") + let iframeSelector = + "#orca-payment-element-iframeRef-orca-elements-payment-element-payment-element"; + + beforeEach(() => { + getIframeBody = () => cy.iframe(iframeSelector); + cy.createPaymentIntent(secretKey, createPaymentBody).then(() => { + cy.getGlobalState("clientSecret").then((clientSecret) => { + + cy.visit(getClientURL(clientSecret, publishableKey)); + }); + + }) + }); + + + it("title rendered correctly", () => { + cy.contains("Hyperswitch Unified Checkout").should("be.visible"); + }); + + it("orca-payment-element iframe loaded", () => { + cy.get( + "#orca-payment-element-iframeRef-orca-elements-payment-element-payment-element" + ) + .should("be.visible") + .its("0.contentDocument") + .its("body"); + }); + + + it('If the user completes the challenge, the payment should be successful.', () => { + getIframeBody().find(`[data-testid=${testIds.addNewCardIcon}]`).click() + getIframeBody().find(`[data-testid=${testIds.cardNoInputTestId}]`).type(netceteraChallengeTestCard) + getIframeBody().find(`[data-testid=${testIds.expiryInputTestId}]`).type("0444") + cy.wait(1000) + getIframeBody().find(`[data-testid=${testIds.cardCVVInputTestId}]`).type("1234") + getIframeBody().get("#submit").click(); + cy.wait(4000) + + cy.nestedIFrame("#threeDsAuthFrame", ($body) => { + cy.wrap($body).find('#otp') + .type('1234') + + cy.wrap($body).find('#sendOtp') + .click() + cy.contains("Thanks for your order!").should("be.visible"); + }) + + }) + + it('If the user closes the challenge, the payment should fail.', () => { + getIframeBody().find(`[data-testid=${testIds.addNewCardIcon}]`).click() + getIframeBody().find(`[data-testid=${testIds.cardNoInputTestId}]`).type(netceteraChallengeTestCard) + getIframeBody().find(`[data-testid=${testIds.expiryInputTestId}]`).type("0444") + cy.wait(1000) + getIframeBody().find(`[data-testid=${testIds.cardCVVInputTestId}]`).type("1234") + getIframeBody().get("#submit").click(); + cy.wait(4000) + + cy.nestedIFrame("#threeDsAuthFrame", ($body) => { + cy.wrap($body) + .find('#cancel') + .click() + cy.contains("Payment Failed!").should("be.visible"); + }) + }) + + +}) + + + + diff --git a/cypress-tests/cypress/support/commands.ts b/cypress-tests/cypress/support/commands.ts index 5a3fe36e..e04b93f6 100644 --- a/cypress-tests/cypress/support/commands.ts +++ b/cypress-tests/cypress/support/commands.ts @@ -173,3 +173,11 @@ Cypress.Commands.add("createPaymentIntent", (secretKey: string, createPaymentBod Cypress.Commands.add("getGlobalState", (key: any) => { return globalState[key]; }); + +Cypress.Commands.add("nestedIFrame", (selector, callback) => { + cy.iframe("#orca-fullscreen").find(selector).should("exist").should("be.visible").then(($ele) => { + const $body = + $ele.contents().find('body') + callback($body); + }) +}); \ No newline at end of file diff --git a/cypress-tests/cypress/support/types.ts b/cypress-tests/cypress/support/types.ts index d1db388d..1ad709b5 100644 --- a/cypress-tests/cypress/support/types.ts +++ b/cypress-tests/cypress/support/types.ts @@ -26,6 +26,7 @@ declare global { ): Chainable> createPaymentIntent(secretKey: string, createPaymentBody: Record): Chainable> getGlobalState(key: string): Chainable> + nestedIFrame(selector: string, callback: (body: Chainable>) => void): Chainable; } } } \ No newline at end of file diff --git a/cypress-tests/cypress/support/utils.ts b/cypress-tests/cypress/support/utils.ts index 496d5560..18a484a0 100644 --- a/cypress-tests/cypress/support/utils.ts +++ b/cypress-tests/cypress/support/utils.ts @@ -6,15 +6,17 @@ export const getClientURL = (clientSecret, publishableKey) => { return `${CLIENT_BASE_URL}?isCypressTestMode=true&clientSecret=${clientSecret}&publishableKey=${publishableKey}`; } -export const enum connectorEnum{ +export const enum connectorEnum { TRUSTPAY, ADYEN, - STRIPE + STRIPE, + NETCETERA } export const connectorProfileIdMapping = new Map([ [connectorEnum.TRUSTPAY, "pro_eP323T9e4ApKpilWBfPA"], [connectorEnum.ADYEN, "pro_Kvqzu8WqBZsT1OjHlCj4"], [connectorEnum.STRIPE, "pro_5fVcCxU8MFTYozgtf0P8"], + [connectorEnum.NETCETERA, "pro_h9VHXnJx8s6W4KSZfSUL"] ]); export const createPaymentBody = { @@ -78,7 +80,7 @@ export const createPaymentBody = { } -export const changeObjectKeyValue = (object: Record, key: string, value: string) => { +export const changeObjectKeyValue = (object: Record, key: string, value: boolean | string) => { object[key] = value } @@ -128,3 +130,4 @@ export const adyenTestCard = "4917610000000000"; export const bluesnapTestCard = "4000000000001091"; export const amexTestCard = "378282246310005" export const visaTestCard = "4242424242424242"; +export const netceteraChallengeTestCard = "348638267931507"; \ No newline at end of file