Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: add 3DS flow E2E test for card payments for Adyen connector #754

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import {
adyenTestCard,
changeObjectKeyValue,
confirmBody,
createPaymentBody,
getClientURL,
} from "cypress/support/utils";
import { CardData } from "cypress/support/types";

describe("Card Payment for Adyen Connector for 3DS Flow Test", () => {
const publishableKey = Cypress.env("HYPERSWITCH_PUBLISHABLE_KEY");
const secretKey = Cypress.env("HYPERSWITCH_SECRET_KEY");
let getIframeBody: () => Cypress.Chainable<JQuery<HTMLBodyElement>>;
const iframeSelector =
"#orca-payment-element-iframeRef-orca-elements-payment-element-payment-element";

const cardData: CardData = {
cardNo: adyenTestCard,
expiryDate: "03/30",
cvc: "737",
};
Comment on lines +17 to +21
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move this to support/utils.ts

// const cardData: CardData = {
// cardNo: adyenTestCard,
// expiryDate: adyenExpiryDate,
// cvc: adyenCvc,
// }
Comment on lines +22 to +26
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove the comments

changeObjectKeyValue(
createPaymentBody,
"profile_id",
Cypress.env("PROFILE_ID")
);
changeObjectKeyValue(createPaymentBody, "authentication_type", "three_ds");
createPaymentBody["request_external_three_ds_authentication"] = true;

beforeEach(() => {
getIframeBody = () => cy.iframe(iframeSelector);
cy.createPaymentIntent(secretKey, createPaymentBody).then(() => {
cy.getGlobalState("clientSecret").then((clientSecret) => {
cy.visit(getClientURL(clientSecret, publishableKey));
});
});
});

// Test for rendering the correct page title
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");
});

// Test to fill in card details and complete payment
it("should check card payment for adyen connector 3DS flow", function () {
cy.fillCardDetails(iframeSelector, cardData);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
cy.fillCardDetails(iframeSelector, cardData);
getIframeBody().find(`[data-testid=${testIds.addNewCardIcon}]`).click();
getIframeBody()
.find(`[data-testid=${testIds.cardNoInputTestId}]`)
.type(cardData.cardNo);
getIframeBody()
.find(`[data-testid=${testIds.expiryInputTestId}]`)
.type(cardData.expiryDate);
getIframeBody()
.find(`[data-testid=${testIds.cardCVVInputTestId}]`)
.should("be.ok")
.type(cardData.cvc);
getIframeBody().get("#submit").click();


// Validate URL redirection to Adyen connector for 3DS Auth
cy.url()
.should("include", "adyen.com")
.then((url) => {
// Log the URL to the Cypress command log
cy.log(`Current URL: ${url}`);
});

cy.wait(5000);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
cy.wait(5000);

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this required? Can we please remove this?

cy.get("#root").should("be.ok");

// Interact with the 3DS secure authentication iframe
cy.iframe(".adyen-checkout__iframe").find("[name=answer]").type("password");

cy.iframe(".adyen-checkout__iframe").find("#buttonSubmit").click();
cy.wait(2000); // Wait for confirmation message to display
cy.contains("Thanks for your order!").should("be.visible");
});
});
73 changes: 49 additions & 24 deletions cypress-tests/cypress/support/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
// -- This will overwrite an existing command --
// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
import "cypress-iframe";
import { createPaymentBody } from "./utils"
import { createPaymentBody } from "./utils";
import * as testIds from "../../../src/Utilities/TestUtils.bs";
// commands.js or your custom support file
const iframeSelector =
Expand Down Expand Up @@ -146,30 +146,55 @@ Cypress.Commands.add(
}
);


Cypress.Commands.add("createPaymentIntent", (secretKey: string, createPaymentBody: any) => {
return cy
.request({
method: "POST",
url: "https://sandbox.hyperswitch.io/payments",
headers: {
"Content-Type": "application/json",
Accept: "application/json",
"api-key": secretKey,
},
body: JSON.stringify(createPaymentBody),
})
.then((response) => {
expect(response.headers["content-type"]).to.include("application/json");
expect(response.body).to.have.property("client_secret");
const clientSecret = response.body.client_secret;
cy.log(clientSecret);
cy.log(response.toString());

globalState["clientSecret"] = clientSecret;
});
});
Cypress.Commands.add(
"createPaymentIntent",
(secretKey: string, createPaymentBody: any) => {
return cy
.request({
method: "POST",
url: "https://sandbox.hyperswitch.io/payments",
headers: {
"Content-Type": "application/json",
Accept: "application/json",
"api-key": secretKey,
},
body: JSON.stringify(createPaymentBody),
})
.then((response) => {
expect(response.headers["content-type"]).to.include("application/json");
expect(response.body).to.have.property("client_secret");
const clientSecret = response.body.client_secret;
cy.log(clientSecret);
cy.log(response.toString());

globalState["clientSecret"] = clientSecret;
});
}
);
Comment on lines +149 to +173
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not needed, please revert this change

Comment on lines +149 to +173
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Cypress.Commands.add(
"createPaymentIntent",
(secretKey: string, createPaymentBody: any) => {
return cy
.request({
method: "POST",
url: "https://sandbox.hyperswitch.io/payments",
headers: {
"Content-Type": "application/json",
Accept: "application/json",
"api-key": secretKey,
},
body: JSON.stringify(createPaymentBody),
})
.then((response) => {
expect(response.headers["content-type"]).to.include("application/json");
expect(response.body).to.have.property("client_secret");
const clientSecret = response.body.client_secret;
cy.log(clientSecret);
cy.log(response.toString());
globalState["clientSecret"] = clientSecret;
});
}
);


Cypress.Commands.add("getGlobalState", (key: any) => {
return globalState[key];
});

Cypress.Commands.add(
"fillCardDetails",
(iframeSelector: string, cardData: any) => {
const getIframeBody = () => cy.iframe(iframeSelector);

// Find and interact with card details input fields within the iframe
getIframeBody().find(`[data-testid=${testIds.addNewCardIcon}]`).click();
getIframeBody()
.find(`[data-testid=${testIds.cardNoInputTestId}]`)
.type(cardData.cardNo);
getIframeBody()
.find(`[data-testid=${testIds.expiryInputTestId}]`)
.type(cardData.expiryDate);
getIframeBody()
.find(`[data-testid=${testIds.cardCVVInputTestId}]`)
.should("be.ok")
.type(cardData.cvc);

// Submit the payment details
getIframeBody().get("#submit").click();
}
);
Comment on lines +179 to +200
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Cypress.Commands.add(
"fillCardDetails",
(iframeSelector: string, cardData: any) => {
const getIframeBody = () => cy.iframe(iframeSelector);
// Find and interact with card details input fields within the iframe
getIframeBody().find(`[data-testid=${testIds.addNewCardIcon}]`).click();
getIframeBody()
.find(`[data-testid=${testIds.cardNoInputTestId}]`)
.type(cardData.cardNo);
getIframeBody()
.find(`[data-testid=${testIds.expiryInputTestId}]`)
.type(cardData.expiryDate);
getIframeBody()
.find(`[data-testid=${testIds.cardCVVInputTestId}]`)
.should("be.ok")
.type(cardData.cvc);
// Submit the payment details
getIframeBody().get("#submit").click();
}
);

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not needed, please revert this change

10 changes: 10 additions & 0 deletions cypress-tests/cypress/support/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ export type CustomerData = {
threeDSCardNo: string
}

export type CardData = {
cardNo: string;
cvc: string;
expiryDate: string;
};

declare global {
namespace Cypress {
interface Chainable {
Expand All @@ -26,6 +32,10 @@ declare global {
): Chainable<JQuery<HTMLElement>>
createPaymentIntent(secretKey: string, createPaymentBody: Record<string, any>): Chainable<Response<any>>
getGlobalState(key: string): Chainable<Response<any>>
fillCardDetails(
selector: string,
cardData: CardData
): Chainable<Response<any>>
Comment on lines +35 to +38
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
fillCardDetails(
selector: string,
cardData: CardData
): Chainable<Response<any>>

}
}
}
Loading
Loading