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

refactor(cypress): move memory cache tests out of payment for misc #6992

Merged
merged 21 commits into from
Jan 24, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
9106d49
test(cypress): Add Test for In Memory Cache
Dec 27, 2024
f287080
fix: address lints
Dec 30, 2024
484d842
chore(cypress): run formatter and address lints
hyperswitch-bot[bot] Dec 30, 2024
003cf1c
fix: Spell check
sumitdahiya125 Dec 30, 2024
84df059
Merge branch 'main' into add-cypress-test-for-in-memory-cache
dracarys18 Jan 7, 2025
c18cdbd
redo: resolve conflicts
pixincreate Jan 7, 2025
931d5c0
fix: session call webpack failure
pixincreate Jan 7, 2025
852a447
Merge branch 'main' of github.com:juspay/hyperswitch into refactor-ad…
pixincreate Jan 9, 2025
968d6ff
feat: introduce health check to `misc`
pixincreate Jan 9, 2025
7e77c1c
refactor: add validations around login
pixincreate Jan 10, 2025
1fab8aa
Merge branch 'main' of github.com:juspay/hyperswitch into refactor-ad…
pixincreate Jan 10, 2025
ca7768b
chore: rename file
pixincreate Jan 10, 2025
2bb382d
revert v2 changes
pixincreate Jan 10, 2025
1e51907
rename
pixincreate Jan 13, 2025
75337d8
docs(cypress): update file structure (#7016)
pixincreate Jan 13, 2025
325f6c9
Merge branch 'main' into refactor-add-memory-cache
pixincreate Jan 13, 2025
d14c9ac
refactor: remove `beforeEach()`
pixincreate Jan 13, 2025
533bf92
Merge branch 'refactor-add-memory-cache' of github.com:juspay/hypersw…
pixincreate Jan 13, 2025
4407c72
Merge branch 'main' of github.com:juspay/hyperswitch into refactor-ad…
pixincreate Jan 13, 2025
cbe621c
Merge branch 'main' of github.com:juspay/hyperswitch into refactor-ad…
pixincreate Jan 24, 2025
b91367a
good catch
pixincreate Jan 24, 2025
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
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
Loading