test(cypress): add cypress tests for void payment in v2 (#9646)

This commit is contained in:
Ayush Anand
2025-10-07 22:14:37 +05:30
committed by GitHub
parent 286e18b226
commit d98adb2e03
9 changed files with 522 additions and 174 deletions

View File

@ -27,7 +27,10 @@
// cy.task can only be used in support files (spec files or commands file)
import { nanoid } from "nanoid";
import { getValueByKey } from "../e2e/configs/Payment/Utils.js";
import {
defaultErrorHandler,
getValueByKey,
} from "../e2e/configs/Payment/Utils.js";
import { isoTimeTomorrow, validateEnv } from "../utils/RequestBodyUtils.js";
function logRequestId(xRequestId) {
@ -55,7 +58,7 @@ Cypress.Commands.add(
url: url,
headers: {
"Content-Type": "application/json",
"Authorization": `admin-api-key=${api_key}`,
Authorization: `admin-api-key=${api_key}`,
},
body: organizationCreateBody,
failOnStatusCode: false,
@ -91,7 +94,7 @@ Cypress.Commands.add("organizationRetrieveCall", (globalState) => {
url: url,
headers: {
"Content-Type": "application/json",
"Authorization": `admin-api-key=${api_key}`,
Authorization: `admin-api-key=${api_key}`,
},
failOnStatusCode: false,
}).then((response) => {
@ -135,7 +138,7 @@ Cypress.Commands.add(
url: url,
headers: {
"Content-Type": "application/json",
"Authorization": `admin-api-key=${api_key}`,
Authorization: `admin-api-key=${api_key}`,
},
body: organizationUpdateBody,
failOnStatusCode: false,
@ -185,7 +188,7 @@ Cypress.Commands.add(
url: url,
headers: {
"Content-Type": "application/json",
"Authorization": `admin-api-key=${api_key}`,
Authorization: `admin-api-key=${api_key}`,
"X-Organization-Id": organization_id,
},
body: merchantAccountCreateBody,
@ -230,7 +233,7 @@ Cypress.Commands.add("merchantAccountRetrieveCall", (globalState) => {
url: url,
headers: {
"Content-Type": "application/json",
"Authorization": `admin-api-key=${api_key}`,
Authorization: `admin-api-key=${api_key}`,
},
failOnStatusCode: false,
}).then((response) => {
@ -274,7 +277,7 @@ Cypress.Commands.add(
url: url,
headers: {
"Content-Type": "application/json",
"Authorization": `admin-api-key=${api_key}`,
Authorization: `admin-api-key=${api_key}`,
},
body: merchantAccountUpdateBody,
failOnStatusCode: false,
@ -324,7 +327,7 @@ Cypress.Commands.add(
url: url,
headers: {
"Content-Type": "application/json",
"Authorization": `admin-api-key=${api_key}`,
Authorization: `admin-api-key=${api_key}`,
"x-merchant-id": merchant_id,
...customHeaders,
},
@ -369,7 +372,7 @@ Cypress.Commands.add("businessProfileRetrieveCall", (globalState) => {
url: url,
headers: {
"Content-Type": "application/json",
"Authorization": `admin-api-key=${api_key}`,
Authorization: `admin-api-key=${api_key}`,
...customHeaders,
},
failOnStatusCode: false,
@ -411,7 +414,7 @@ Cypress.Commands.add(
url: url,
headers: {
"Content-Type": "application/json",
"Authorization": `admin-api-key=${api_key}`,
Authorization: `admin-api-key=${api_key}`,
...customHeaders,
},
body: businessProfileUpdateBody,
@ -503,7 +506,7 @@ Cypress.Commands.add(
url: url,
headers: {
"Content-Type": "application/json",
"Authorization": `admin-api-key=${api_key}`,
Authorization: `admin-api-key=${api_key}`,
...customHeaders,
},
body: mcaCreateBody,
@ -551,7 +554,7 @@ Cypress.Commands.add("mcaRetrieveCall", (globalState) => {
url: url,
headers: {
"Content-Type": "application/json",
"Authorization": `admin-api-key=${api_key}`,
Authorization: `admin-api-key=${api_key}`,
...customHeaders,
},
failOnStatusCode: false,
@ -611,7 +614,7 @@ Cypress.Commands.add(
url: url,
headers: {
"Content-Type": "application/json",
"Authorization": `admin-api-key=${api_key}`,
Authorization: `admin-api-key=${api_key}`,
...customHeaders,
},
body: mcaUpdateBody,
@ -671,7 +674,7 @@ Cypress.Commands.add("apiKeyCreateCall", (apiKeyCreateBody, globalState) => {
url: url,
headers: {
"Content-Type": "application/json",
"Authorization": `admin-api-key=${api_key}`,
Authorization: `admin-api-key=${api_key}`,
...customHeaders,
},
body: apiKeyCreateBody,
@ -718,7 +721,7 @@ Cypress.Commands.add("apiKeyRetrieveCall", (globalState) => {
url: url,
headers: {
"Content-Type": "application/json",
"Authorization": `admin-api-key=${api_key}`,
Authorization: `admin-api-key=${api_key}`,
...customHeaders,
},
failOnStatusCode: false,
@ -768,7 +771,7 @@ Cypress.Commands.add("apiKeyUpdateCall", (apiKeyUpdateBody, globalState) => {
url: url,
headers: {
"Content-Type": "application/json",
"Authorization": `admin-api-key=${api_key}`,
Authorization: `admin-api-key=${api_key}`,
...customHeaders,
},
body: apiKeyUpdateBody,
@ -1176,7 +1179,7 @@ Cypress.Commands.add("merchantAccountsListCall", (globalState) => {
method: "GET",
url: url,
headers: {
"Authorization": `admin-api-key=${api_key}`,
Authorization: `admin-api-key=${api_key}`,
"Content-Type": "application/json",
},
failOnStatusCode: false,
@ -1218,7 +1221,7 @@ Cypress.Commands.add("businessProfilesListCall", (globalState) => {
method: "GET",
url: url,
headers: {
"Authorization": `admin-api-key=${api_key}`,
Authorization: `admin-api-key=${api_key}`,
"Content-Type": "application/json",
...customHeaders,
},
@ -1261,7 +1264,7 @@ Cypress.Commands.add("mcaListCall", (globalState, service_type) => {
method: "GET",
url: url,
headers: {
"Authorization": `admin-api-key=${api_key}`,
Authorization: `admin-api-key=${api_key}`,
"Content-Type": "application/json",
...customHeaders,
},
@ -1323,7 +1326,7 @@ Cypress.Commands.add("apiKeysListCall", (globalState) => {
method: "GET",
url: url,
headers: {
"Authorization": `admin-api-key=${api_key}`,
Authorization: `admin-api-key=${api_key}`,
"Content-Type": "application/json",
...customHeaders,
},
@ -1354,23 +1357,23 @@ Cypress.Commands.add("apiKeysListCall", (globalState) => {
// Payment API calls
// Update the below commands while following the conventions
// Below is an example of how the payment intent create call should look like (update the below command as per the need)
Cypress.Commands.add(
"paymentIntentCreateCall",
(
globalState,
paymentRequestBody,
paymentResponseBody
/* Add more variables based on the need*/
) => {
"paymentVoidCall",
(globalState, voidRequestBody, data) => {
const { Request: reqData = {}, Response: resData } = data || {};
// Define the necessary variables and constants at the top
// Also construct the URL here
const api_key = globalState.get("apiKey");
const base_url = globalState.get("baseUrl");
const profile_id = globalState.get("profileId");
const url = `${base_url}/v2/payments/create-intent`;
const payment_id = globalState.get("paymentID");
const url = `${base_url}/v2/payments/${payment_id}/cancel`;
// Update request body if needed
paymentRequestBody = {};
// Apply connector-specific request data (including cancellation_reason)
for (const key in reqData) {
voidRequestBody[key] = reqData[key];
}
// Pass Custom Headers
const customHeaders = {
@ -1381,7 +1384,59 @@ Cypress.Commands.add(
method: "POST",
url: url,
headers: {
"api-key": api_key,
Authorization: `api-key=${api_key}`,
"Content-Type": "application/json",
...customHeaders,
},
body: voidRequestBody,
failOnStatusCode: false,
}).then((response) => {
// Logging x-request-id is mandatory
logRequestId(response.headers["x-request-id"]);
cy.wrap(response).then(() => {
expect(response.headers["content-type"]).to.include("application/json");
if (response.status === 200) {
for (const key in resData.body) {
expect(resData.body[key]).to.equal(response.body[key]);
}
} else {
defaultErrorHandler(response, resData);
}
});
});
}
);
Cypress.Commands.add(
"paymentIntentCreateCall",
(
globalState,
paymentRequestBody,
paymentResponseBody,
authentication_type,
capture_method
) => {
// Define the necessary variables and constants at the top
// Also construct the URL here
const api_key = globalState.get("apiKey");
const base_url = globalState.get("baseUrl");
const profile_id = globalState.get("profileId");
const url = `${base_url}/v2/payments/create-intent`;
// Set capture_method and authentication_type as parameters (like V1)
paymentRequestBody.authentication_type = authentication_type;
paymentRequestBody.capture_method = capture_method;
// Pass Custom Headers
const customHeaders = {
"x-profile-id": profile_id,
};
cy.request({
method: "POST",
url: url,
headers: {
Authorization: `api-key=${api_key}`,
"Content-Type": "application/json",
...customHeaders,
},
@ -1391,28 +1446,113 @@ Cypress.Commands.add(
// Logging x-request-id is mandatory
logRequestId(response.headers["x-request-id"]);
if (response.status === 200) {
// Update the assertions based on the need
expect(response.body).to.deep.equal(paymentResponseBody);
} else if (response.status === 400) {
// Add 4xx validations here
expect(response.body).to.deep.equal(paymentResponseBody);
} else if (response.status === 500) {
// Add 5xx validations here
expect(response.body).to.deep.equal(paymentResponseBody);
} else {
// If status code is other than the ones mentioned above, default should be thrown
throw new Error(
`Payment intent create call failed with status ${response.status} and message: "${response.body.error.message}"`
);
}
cy.wrap(response).then(() => {
expect(response.headers["content-type"]).to.include("application/json");
if (response.status === 200) {
// Validate the payment create response - V2 uses different ID format
expect(response.body).to.have.property("id").and.to.be.a("string").and
.not.be.empty;
expect(response.body).to.have.property("status");
// Store the payment ID for future use
globalState.set("paymentID", response.body.id);
// Log payment creation success
cy.task(
"cli_log",
`Payment created with ID: ${response.body.id}, Status: ${response.body.status}`
);
if (paymentResponseBody && paymentResponseBody.body) {
for (const key in paymentResponseBody.body) {
if (paymentResponseBody.body[key] !== null) {
expect(response.body[key]).to.equal(
paymentResponseBody.body[key]
);
}
}
}
} else {
defaultErrorHandler(response, paymentResponseBody);
}
});
});
}
);
Cypress.Commands.add("paymentIntentConfirmCall", (globalState) => {});
Cypress.Commands.add("paymentIntentRetrieveCall", (globalState) => {});
Cypress.Commands.add(
"paymentConfirmCall",
(globalState, paymentConfirmRequestBody, data) => {
const { Request: reqData = {}, Response: resData } = data || {};
// templates for future use
Cypress.Commands.add("", () => {
cy.request({}).then((response) => {});
});
// Define the necessary variables and constants at the top
const api_key = globalState.get("apiKey");
const base_url = globalState.get("baseUrl");
const profile_id = globalState.get("profileId");
const payment_id = globalState.get("paymentID");
const url = `${base_url}/v2/payments/${payment_id}/confirm-intent`;
// Apply connector-specific request data
for (const key in reqData) {
paymentConfirmRequestBody[key] = reqData[key];
}
// Pass Custom Headers
const customHeaders = {
"x-profile-id": profile_id,
};
cy.request({
method: "POST",
url: url,
headers: {
Authorization: `api-key=${api_key}`,
"Content-Type": "application/json",
...customHeaders,
},
body: paymentConfirmRequestBody,
failOnStatusCode: false,
}).then((response) => {
// Logging x-request-id is mandatory
logRequestId(response.headers["x-request-id"]);
cy.wrap(response).then(() => {
expect(response.headers["content-type"]).to.include("application/json");
if (response.status === 200) {
// Validate the payment confirm response
expect(response.body).to.have.property("id").and.to.be.a("string").and
.not.be.empty;
expect(response.body).to.have.property("status");
globalState.set("paymentID", response.body.id);
// Validate response body against expected data
if (resData && resData.body) {
for (const key in resData.body) {
// Skip validation if expected value is null or undefined
if (resData.body[key] == null) {
continue;
}
// Only validate if the field exists in the response and has a non-null value
if (
response.body.hasOwnProperty(key) &&
response.body[key] != null
) {
// Use deep equal for object comparison, regular equal for primitives
if (
typeof resData.body[key] === "object" &&
typeof response.body[key] === "object"
) {
expect(response.body[key]).to.deep.equal(resData.body[key]);
} else {
expect(response.body[key]).to.equal(resData.body[key]);
}
}
}
}
} else {
defaultErrorHandler(response, resData);
}
});
});
}
);