Skip to content

Commit

Permalink
refactor(cypress): move memory cache tests out of payment for misc (#…
Browse files Browse the repository at this point in the history
…6992)

Co-authored-by: Sumit Kumar <[email protected]>
Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
Co-authored-by: Sumit Kumar <[email protected]>
Co-authored-by: Kartikeya Hegde <[email protected]>
  • Loading branch information
5 people authored Jan 24, 2025
1 parent 7fd3551 commit 4382fc6
Show file tree
Hide file tree
Showing 87 changed files with 742 additions and 539 deletions.
59 changes: 36 additions & 23 deletions cypress-tests/README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Hyperswitch Cypress Testing Framework
# Hyperswitch Cypress Testing Framework <!-- omit in toc -->

## Overview

Expand Down Expand Up @@ -61,7 +61,7 @@ CYPRESS_CONNECTOR="connector_id" npm run cypress:ci

## Getting Started

## Prerequisites
### Prerequisites

- Node.js (18.x or above)
- npm or yarn
Expand All @@ -70,7 +70,7 @@ CYPRESS_CONNECTOR="connector_id" npm run cypress:ci
> [!NOTE]
> To learn about the hardware requirements and software dependencies for running Cypress, refer to the [official documentation](https://docs.cypress.io/app/get-started/install-cypress).
## Installation
### Installation

1. Clone the repository and switch to the project directory:

Expand Down Expand Up @@ -119,32 +119,33 @@ CYPRESS_CONNECTOR="connector_id" npm run cypress:ci
> [!NOTE]
> To learn about how `creds` file should be structured, refer to the [example.creds.json](#example-credsjson) section below.
## Running Tests
### Running Tests

Execution of Cypress tests can be done in two modes: Development mode (Interactive) and CI mode (Headless). The tests can be executed against a single connector or multiple connectors in parallel. Time taken to execute the tests will vary based on the number of connectors and the number of tests. For a single connector, the tests will take approximately 07-12 minutes to execute (this also depends on the hardware configurations).

For Development mode, the tests will run in the Cypress UI where execution of tests can be seen in real-time and provides a larger area for debugging based on the need. In CI mode (Headless), tests run in the terminal without UI interaction and generate reports automatically.

### Development Mode (Interactive)
#### Development Mode (Interactive)

```shell
npm run cypress
```

### CI Mode (Headless)
#### CI Mode (Headless)

```shell
# All tests
npm run cypress:ci

# Specific test suites
npm run cypress:payments # Payment tests
npm run cypress:misc # Miscellaneous tests (e.g. health check, memory cache etc.)
npm run cypress:payment-method-list # Payment method list tests
npm run cypress:payments # Payment tests
npm run cypress:payouts # Payout tests
npm run cypress:routing # Routing tests
```

### Execute tests against multiple connectors or in parallel
#### Execute tests against multiple connectors or in parallel

1. Set additional environment variables:

Expand Down Expand Up @@ -178,30 +179,42 @@ The folder structure of this directory is as follows:

```txt
.
├── .prettierrc # prettier configs
├── README.md # this file
├── .prettierrc # prettier configs
├── README.md # this file
├── cypress
│   ├── e2e
│   │   ├── <Service>Test # Directory for test scenarios related to connectors.
│   │   │   ├── 00000-test_<0>.cy.js
│   │   │   ├── ...
│   │   │   └── 0000n-test_<n>.cy.js
│   │   └── <Service>Utils # Directory for utility functions related to connectors.
│   │   ├── connector_<1>.js
│   │   ├── ...
│   │   └── connector_<n>.js
│   │   ├── configs # Directory for utility functions related to connectors.
│   │   │   ├── PaymentMethodList
│   │ │   │   ├── connector_<1>.js
│   │   │  │   ├── ...
│   │   │  │   └── connector_<n>.js
│   │   │   ├── Payment
│   │   │   ├── Payout
│   │   │   └── Routing
│   │   └── spec # Directory for test scenarios related to connectors.
│   │   ├── Misc
│   │    │   ├── 00000-test_<0>.cy.js
│   │     │   ├── ...
│   │     │   └── 0000n-test_<n>.cy.js
│   │   ├── Payment
│   │   ├── PaymentMethodList
│   │   ├── Payout
│   │   └── Routing
│   ├── fixtures # Directory for storing test data API request.
│   │   ├── fixture_<1>.json
│   │   ├── ...
│   │   └── fixture_<n>.json
│   ├── support # Directory for Cypress support files.
│   │   ├── commands.js # File containing custom Cypress commands and utilities.
│   │   ├── e2e.js
│   │   └── redirectionHandler.js
│   │   └── redirectionHandler.js # Functions for handling redirections in tests
│   └── utils
│   ├── RequestBodyUtils.js
│   ├── RequestBodyUtils.js # Utility Functions for handling request bodies
│   ├── State.js
│   └── featureFlags.js
│   └── featureFlags.js # Functions for validating and controlling feature flags
├── screenshots
│ └── <connector-name> # Connector directory for storing screenshots of test failures
│ └── <test-name>.png
├── cypress.config.js # Cypress configuration file.
├── eslint.config.js # linter configuration file.
└── package.json # Node.js package file.
Expand Down Expand Up @@ -240,8 +253,8 @@ To add a new test, create a new test file in the `e2e` directory under respectiv

```javascript
// cypress/e2e/<Service>Test/NewFeature.cy.js
import * as fixtures from "../../fixtures/imports";
import State from "../../utils/State";
import * as fixtures from "../../../fixtures/imports";
import State from "../../../utils/State";

describe("New Feature", () => {
let globalState;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { getCustomExchange } from "./Commons";
import { getCustomExchange } from "./Modifiers";

const successfulNo3DSCardDetails = {
card_number: "4111111111111111",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,45 +1,5 @@
// This file is the default. To override, add to connector.js
import State from "../../utils/State";

const globalState = new State({
connectorId: Cypress.env("CONNECTOR"),
baseUrl: Cypress.env("BASEURL"),
adminApiKey: Cypress.env("ADMINAPIKEY"),
connectorAuthFilePath: Cypress.env("CONNECTOR_AUTH_FILE_PATH"),
});

const connectorName = normalize(globalState.get("connectorId"));

function normalize(input) {
const exceptions = {
bankofamerica: "Bank of America",
cybersource: "Cybersource",
paybox: "Paybox",
paypal: "Paypal",
wellsfargo: "Wellsfargo",
fiuu: "Fiuu",
noon: "Noon",
// Add more known exceptions here
};

if (typeof input !== "string") {
const specName = Cypress.spec.name;

if (specName.includes("-")) {
const parts = specName.split("-");

if (parts.length > 1 && parts[1].includes(".")) {
return parts[1].split(".")[0];
}
}

// Fallback
return `${specName}`;
}

const lowerCaseInput = input.toLowerCase();
return exceptions[lowerCaseInput] || input;
}
import { getCustomExchange } from "./Modifiers";

const successfulNo3DSCardDetails = {
card_number: "4111111111111111",
Expand Down Expand Up @@ -141,68 +101,6 @@ export const fullNameRequiredField = {
};

export const billingRequiredField = {};
/*
`getDefaultExchange` contains the default Request and Response to be considered if none provided.
`getCustomExchange` takes in 2 optional fields named as Request and Response.
with `getCustomExchange`, if 501 response is expected, there is no need to pass Response as it considers default values.
*/

// Const to get default PaymentExchange object
const getDefaultExchange = () => ({
Request: {},
Response: {
status: 501,
body: {
error: {
type: "invalid_request",
message: `Selected payment method through ${connectorName} is not implemented`,
code: "IR_00",
},
},
},
});

const getUnsupportedExchange = () => ({
Request: {
currency: "EUR",
},
Response: {
status: 400,
body: {
error: {
type: "invalid_request",
message: `Payment method type not supported`,
code: "IR_19",
},
},
},
});

// Const to get PaymentExchange with overridden properties
export const getCustomExchange = (overrides) => {
const defaultExchange = getDefaultExchange();

return {
...defaultExchange,
...(overrides.Configs ? { Configs: overrides.Configs } : {}),
Request: {
...defaultExchange.Request,
...(overrides.Request || {}),
},
Response: {
...defaultExchange.Response,
...(overrides.Response || {}),
},
...(overrides.ResponseCustom
? { ResponseCustom: overrides.ResponseCustom }
: {}),
};
};

// Function to update the default status code
export const updateDefaultStatusCode = () => {
return getUnsupportedExchange().Response;
};

export const payment_methods_enabled = [
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import {
connectorDetails as commonConnectorDetails,
getCustomExchange,
} from "./Commons";
import { connectorDetails as commonConnectorDetails } from "./Commons";
import { getCustomExchange } from "./Modifiers";

const successfulNo3DSCardDetails = {
card_number: "4242424242424242",
Expand Down
104 changes: 104 additions & 0 deletions cypress-tests/cypress/e2e/configs/Payment/Modifiers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import State from "../../../utils/State";

const globalState = new State({
connectorId: Cypress.env("CONNECTOR"),
baseUrl: Cypress.env("BASEURL"),
adminApiKey: Cypress.env("ADMINAPIKEY"),
connectorAuthFilePath: Cypress.env("CONNECTOR_AUTH_FILE_PATH"),
});

const connectorName = normalize(globalState.get("connectorId"));

function normalize(input) {
const exceptions = {
bankofamerica: "Bank of America",
cybersource: "Cybersource",
paybox: "Paybox",
paypal: "Paypal",
wellsfargo: "Wellsfargo",
fiuu: "Fiuu",
noon: "Noon",
// Add more known exceptions here
};

if (typeof input !== "string") {
const specName = Cypress.spec.name;

if (specName.includes("-")) {
const parts = specName.split("-");

if (parts.length > 1 && parts[1].includes(".")) {
return parts[1].split(".")[0];
}
}

// Fallback
return `${specName}`;
}

const lowerCaseInput = input.toLowerCase();
return exceptions[lowerCaseInput] || input;
}

/*
`getDefaultExchange` contains the default Request and Response to be considered if none provided.
`getCustomExchange` takes in 2 optional fields named as Request and Response.
with `getCustomExchange`, if 501 response is expected, there is no need to pass Response as it considers default values.
*/

// Const to get default PaymentExchange object
const getDefaultExchange = () => ({
Request: {},
Response: {
status: 501,
body: {
error: {
type: "invalid_request",
message: `Selected payment method through ${connectorName} is not implemented`,
code: "IR_00",
},
},
},
});

const getUnsupportedExchange = () => ({
Request: {
currency: "EUR",
},
Response: {
status: 400,
body: {
error: {
type: "invalid_request",
message: `Payment method type not supported`,
code: "IR_19",
},
},
},
});

// Const to get PaymentExchange with overridden properties
export const getCustomExchange = (overrides) => {
const defaultExchange = getDefaultExchange();

return {
...defaultExchange,
...(overrides.Configs ? { Configs: overrides.Configs } : {}),
Request: {
...defaultExchange.Request,
...(overrides.Request || {}),
},
Response: {
...defaultExchange.Response,
...(overrides.Response || {}),
},
...(overrides.ResponseCustom
? { ResponseCustom: overrides.ResponseCustom }
: {}),
};
};

// Function to update the default status code
export const updateDefaultStatusCode = () => {
return getUnsupportedExchange().Response;
};
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { getCustomExchange } from "./Commons";
import { getCustomExchange } from "./Modifiers";

const successfulNo3DSCardDetails = {
card_number: "4012000033330026",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import {
cardRequiredField,
connectorDetails as commonConnectorDetails,
getCustomExchange,
} from "./Commons";
import { getCustomExchange } from "./Modifiers";

const successfulNo3DSCardDetails = {
card_number: "4242424242424242",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { getCustomExchange } from "./Commons";
import { getCustomExchange } from "./Modifiers";

const successfulNo3DSCardDetails = {
card_number: "4200000000000000",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { execConfig, validateConfig } from "../../utils/featureFlags.js";
import { execConfig, validateConfig } from "../../../utils/featureFlags.js";

import { connectorDetails as adyenConnectorDetails } from "./Adyen.js";
import { connectorDetails as bankOfAmericaConnectorDetails } from "./BankOfAmerica.js";
Expand Down
Loading

0 comments on commit 4382fc6

Please sign in to comment.