Skip to content

Commit

Permalink
Merge branch 'main' into cypress-automation-sdk
Browse files Browse the repository at this point in the history
  • Loading branch information
Sanskar2001 authored Nov 7, 2024
2 parents c43ab40 + b40ed76 commit 2bce06c
Show file tree
Hide file tree
Showing 28 changed files with 486 additions and 539 deletions.
24 changes: 24 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,27 @@
## [0.101.3](https://github.com/juspay/hyperswitch-web/compare/v0.101.2...v0.101.3) (2024-11-07)

## [0.101.2](https://github.com/juspay/hyperswitch-web/compare/v0.101.1...v0.101.2) (2024-11-07)

## [0.101.1](https://github.com/juspay/hyperswitch-web/compare/v0.101.0...v0.101.1) (2024-11-07)

# [0.101.0](https://github.com/juspay/hyperswitch-web/compare/v0.100.1...v0.101.0) (2024-11-07)


### Features

* added dynamic fields support for sepa bank transfer ([#775](https://github.com/juspay/hyperswitch-web/issues/775)) ([52d2d15](https://github.com/juspay/hyperswitch-web/commit/52d2d15ed2b2b8ed364a81fe9bbd3dfbd64c0cec))

## [0.100.1](https://github.com/juspay/hyperswitch-web/compare/v0.100.0...v0.100.1) (2024-11-06)

# [0.100.0](https://github.com/juspay/hyperswitch-web/compare/v0.99.6...v0.100.0) (2024-11-06)


### Features

* add dynamic fields support for affirm ([#776](https://github.com/juspay/hyperswitch-web/issues/776)) ([e55e533](https://github.com/juspay/hyperswitch-web/commit/e55e533a197efad11c9b8cceb4b06c672a365dfe))

## [0.99.6](https://github.com/juspay/hyperswitch-web/compare/v0.99.5...v0.99.6) (2024-11-06)

## [0.99.5](https://github.com/juspay/hyperswitch-web/compare/v0.99.4...v0.99.5) (2024-11-06)

## [0.99.4](https://github.com/juspay/hyperswitch-web/compare/v0.99.3...v0.99.4) (2024-11-05)
Expand Down
81 changes: 81 additions & 0 deletions cypress-tests/cypress/e2e/external-3DS-netcetera-e2e-test.cy.ts
Original file line number Diff line number Diff line change
@@ -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<JQuery<HTMLBodyElement>>;
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");
})
})


})




8 changes: 8 additions & 0 deletions cypress-tests/cypress/support/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
})
});
1 change: 1 addition & 0 deletions cypress-tests/cypress/support/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ declare global {
): Chainable<JQuery<HTMLElement>>
createPaymentIntent(secretKey: string, createPaymentBody: Record<string, any>): Chainable<Response<any>>
getGlobalState(key: string): Chainable<Response<any>>
nestedIFrame(selector: string, callback: (body: Chainable<JQuery<HTMLElement>>) => void): Chainable<void>;
}
}
}
9 changes: 6 additions & 3 deletions cypress-tests/cypress/support/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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, string>([
[connectorEnum.TRUSTPAY, "pro_eP323T9e4ApKpilWBfPA"],
[connectorEnum.ADYEN, "pro_Kvqzu8WqBZsT1OjHlCj4"],
[connectorEnum.STRIPE, "pro_5fVcCxU8MFTYozgtf0P8"],
[connectorEnum.NETCETERA, "pro_h9VHXnJx8s6W4KSZfSUL"]
]);

export const createPaymentBody = {
Expand Down Expand Up @@ -78,7 +80,7 @@ export const createPaymentBody = {

}

export const changeObjectKeyValue = (object: Record<string, any>, key: string, value: string) => {
export const changeObjectKeyValue = (object: Record<string, any>, key: string, value: boolean | string) => {
object[key] = value
}

Expand Down Expand Up @@ -128,3 +130,4 @@ export const adyenTestCard = "4917610000000000";
export const bluesnapTestCard = "4000000000001091";
export const amexTestCard = "378282246310005"
export const visaTestCard = "4242424242424242";
export const netceteraChallengeTestCard = "348638267931507";
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "orca-payment-page",
"version": "0.99.5",
"version": "0.101.3",
"main": "index.js",
"private": true,
"dependencies": {
Expand Down
27 changes: 12 additions & 15 deletions src/Components/DynamicFields.res
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
open RecoilAtoms
@react.component
let make = (
~paymentType,
Expand All @@ -12,7 +11,9 @@ let make = (
~cvcProps=None,
~isBancontact=false,
) => {
open DynamicFieldsUtils
open Utils
open RecoilAtoms
let paymentMethodListValue = Recoil.useRecoilValueFromAtom(PaymentUtils.paymentMethodListValue)

React.useEffect(() => {
Expand Down Expand Up @@ -41,20 +42,16 @@ let make = (

paymentMethodTypes.required_fields
->Array.concat(creditRequiredFields)
->DynamicFieldsUtils.removeRequiredFieldsDuplicates
} else if (
PaymentMethodsRecord.dynamicFieldsEnabledPaymentMethods->Array.includes(paymentMethodType)
) {
->removeRequiredFieldsDuplicates
} else if dynamicFieldsEnabledPaymentMethods->Array.includes(paymentMethodType) {
paymentMethodTypes.required_fields
} else {
[]
}
}, (paymentMethod, paymentMethodTypes.required_fields, paymentMethodType))

let requiredFields = React.useMemo(() => {
requiredFieldsWithBillingDetails->DynamicFieldsUtils.removeBillingDetailsIfUseBillingAddress(
billingAddress,
)
requiredFieldsWithBillingDetails->removeBillingDetailsIfUseBillingAddress(billingAddress)
}, [requiredFieldsWithBillingDetails])

let isAllStoredCardsHaveName = React.useMemo(() => {
Expand All @@ -69,7 +66,7 @@ let make = (
~isSavedCardFlow,
~isAllStoredCardsHaveName,
)
->DynamicFieldsUtils.updateDynamicFields(billingAddress)
->updateDynamicFields(billingAddress)
->Belt.SortArray.stableSortBy(PaymentMethodsRecord.sortPaymentMethodFields)
//<...>//
}, (requiredFields, isAllStoredCardsHaveName, isSavedCardFlow))
Expand Down Expand Up @@ -255,7 +252,7 @@ let make = (
}
}

DynamicFieldsUtils.useRequiredFieldsEmptyAndValid(
useRequiredFieldsEmptyAndValid(
~requiredFields,
~fieldsArr,
~countryNames,
Expand All @@ -268,14 +265,14 @@ let make = (
~cvcNumber,
)

DynamicFieldsUtils.useSetInitialRequiredFields(
useSetInitialRequiredFields(
~requiredFields={
billingAddress.usePrefilledValues === Auto ? requiredFieldsWithBillingDetails : requiredFields
},
~paymentMethodType,
)

DynamicFieldsUtils.useRequiredFieldsBody(
useRequiredFieldsBody(
~requiredFields,
~paymentMethodType,
~cardNumber,
Expand All @@ -286,7 +283,7 @@ let make = (
~setRequiredFieldsBody,
)

let submitCallback = DynamicFieldsUtils.useSubmitCallback()
let submitCallback = useSubmitCallback()
useSubmitPaymentData(submitCallback)

let bottomElement = <InfoElement />
Expand All @@ -307,11 +304,11 @@ let make = (
}

let dynamicFieldsToRenderOutsideBilling = React.useMemo(() => {
fieldsArr->Array.filter(DynamicFieldsUtils.isFieldTypeToRenderOutsideBilling)
fieldsArr->Array.filter(isFieldTypeToRenderOutsideBilling)
}, [fieldsArr])

let dynamicFieldsToRenderInsideBilling = React.useMemo(() => {
fieldsArr->Array.filter(field => !(field->DynamicFieldsUtils.isFieldTypeToRenderOutsideBilling))
fieldsArr->Array.filter(field => !(field->isFieldTypeToRenderOutsideBilling))
}, [fieldsArr])

let isInfoElementPresent = dynamicFieldsToRenderInsideBilling->Array.includes(InfoElement)
Expand Down
18 changes: 3 additions & 15 deletions src/Components/SavedMethods.res
Original file line number Diff line number Diff line change
Expand Up @@ -147,11 +147,7 @@ let make = (
| _ =>
// TODO - To be replaced with proper error message
intent(
~bodyArr=savedPaymentMethodBody
->getJsonFromArrayOfJson
->flattenObject(true)
->mergeTwoFlattenedJsonDicts(requiredFieldsBody)
->getArrayOfTupleFromDict,
~bodyArr=savedPaymentMethodBody->mergeAndFlattenToTuples(requiredFieldsBody),
~confirmParam=confirm.confirmParams,
~handleUserError=false,
~manualRetry=isManualRetryEnabled,
Expand All @@ -168,23 +164,15 @@ let make = (
| _ =>
// TODO - To be replaced with proper error message
intent(
~bodyArr=savedPaymentMethodBody
->getJsonFromArrayOfJson
->flattenObject(true)
->mergeTwoFlattenedJsonDicts(requiredFieldsBody)
->getArrayOfTupleFromDict,
~bodyArr=savedPaymentMethodBody->mergeAndFlattenToTuples(requiredFieldsBody),
~confirmParam=confirm.confirmParams,
~handleUserError=false,
~manualRetry=isManualRetryEnabled,
)
}
| _ =>
intent(
~bodyArr=savedPaymentMethodBody
->getJsonFromArrayOfJson
->flattenObject(true)
->mergeTwoFlattenedJsonDicts(requiredFieldsBody)
->getArrayOfTupleFromDict,
~bodyArr=savedPaymentMethodBody->mergeAndFlattenToTuples(requiredFieldsBody),
~confirmParam=confirm.confirmParams,
~handleUserError=false,
~manualRetry=isManualRetryEnabled,
Expand Down
22 changes: 0 additions & 22 deletions src/Hooks/Fetcher.res

This file was deleted.

2 changes: 1 addition & 1 deletion src/PaymentMethodCollectElement.res
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ let make = (~integrateError, ~logger) => {
setTimeout(() => {
clearInterval(interval)
// Append query params and redirect
let url = PaymentHelpers.urlSearch(returnUrl)
let url = URLModule.makeUrl(returnUrl)
url.searchParams.set("payout_id", options.payoutId)
url.searchParams.set("status", statusInfo.status->getPayoutStatusString)
Utils.openUrl(url.href)
Expand Down
14 changes: 10 additions & 4 deletions src/Payments/ACHBankTransfer.res
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ let make = (~paymentType: CardThemeType.mode) => {
let intent = PaymentHelpers.usePaymentIntent(Some(loggerState), BankTransfer)
let (email, _) = Recoil.useLoggedRecoilState(userEmailAddress, "email", loggerState)
let setComplete = Recoil.useSetRecoilState(fieldsComplete)
let paymentMethodListValue = Recoil.useRecoilValueFromAtom(PaymentUtils.paymentMethodListValue)

let (requiredFieldsBody, setRequiredFieldsBody) = React.useState(_ => Dict.make())

let complete = email.value != "" && email.isValid->Option.getOr(false)
let empty = email.value == ""
Expand All @@ -27,9 +28,12 @@ let make = (~paymentType: CardThemeType.mode) => {
let confirm = json->getDictFromJson->ConfirmType.itemToObjMapper
if confirm.doSubmit {
if complete {
let (connectors, _) = paymentMethodListValue->PaymentUtils.getConnectors(BankTransfer(ACH))
let bodyArr =
PaymentBody.dynamicPaymentBody("bank_transfer", "ach")->mergeAndFlattenToTuples(
requiredFieldsBody,
)
intent(
~bodyArr=PaymentBody.achBankTransferBody(~email=email.value, ~connectors),
~bodyArr,
~confirmParam=confirm.confirmParams,
~handleUserError=false,
~iframeId,
Expand All @@ -43,7 +47,9 @@ let make = (~paymentType: CardThemeType.mode) => {
useSubmitPaymentData(submitCallback)

<div className="flex flex-col animate-slowShow" style={gridGap: themeObj.spacingTab}>
<EmailPaymentInput paymentType />
<DynamicFields
paymentType paymentMethod="bank_transfer" paymentMethodType="ach" setRequiredFieldsBody
/>
<Surcharge paymentMethod="bank_transfer" paymentMethodType="ach" />
<InfoElement />
</div>
Expand Down
Loading

0 comments on commit 2bce06c

Please sign in to comment.