From ba7fd0d0a60a61cfe0a142b21d989e76f2a8af30 Mon Sep 17 00:00:00 2001 From: Shraddha Shah Date: Tue, 17 Dec 2024 09:11:29 -0800 Subject: [PATCH] tests, make show async --- src/three-domain-secure/api.test.js | 25 +--- src/three-domain-secure/component.jsx | 10 +- src/three-domain-secure/component.test.js | 142 ++++++++++++++++------ src/three-domain-secure/utils.test.js | 22 ---- 4 files changed, 113 insertions(+), 86 deletions(-) diff --git a/src/three-domain-secure/api.test.js b/src/three-domain-secure/api.test.js index 045140fb5..fc6aa3e1d 100644 --- a/src/three-domain-secure/api.test.js +++ b/src/three-domain-secure/api.test.js @@ -5,7 +5,7 @@ import { request } from "@krakenjs/belter/src"; import { callRestAPI } from "../lib"; import { HEADERS } from "../constants/api"; -import { RestClient, GraphQLClient, callGraphQLAPI, HTTPClient } from "./api"; +import { RestClient, callGraphQLAPI, HTTPClient } from "./api"; vi.mock("@krakenjs/belter/src", async () => { return { @@ -28,7 +28,7 @@ vi.mock("../lib", () => ({ describe("API", () => { const accessToken = "access_token"; - const baseURL = "http://localhost.paypal.com:8080"; + const baseURL = "http://test.paypal.com:port"; afterEach(() => { vi.clearAllMocks(); @@ -64,27 +64,6 @@ describe("API", () => { }); }); - describe("GraphQLClient", () => { - const query = { test: "data" }; - const data = { query }; - const headers = { "Content-Type": "application/json" }; - - it.skip("should make a GraphQL API call with correct params", () => { - vi.spyOn({ callGraphQLAPI }, "callGraphQLAPI").mockResolvedValue({ - data: { test: "data" }, - }); - const client = new GraphQLClient({ accessToken, baseURL }); - client.request({ data, headers }).then(() => { - expect(callGraphQLAPI).toHaveBeenCalledWith({ - accessToken, - baseURL, - data, - headers, - }); - }); - }); - }); - describe("callGraphQLAPI", () => { const query = '{ "test": "data" }'; const variables = { option: "param1" }; diff --git a/src/three-domain-secure/component.jsx b/src/three-domain-secure/component.jsx index 495893c22..cfa6688a6 100644 --- a/src/three-domain-secure/component.jsx +++ b/src/three-domain-secure/component.jsx @@ -63,7 +63,7 @@ const parseMerchantPayload = ({ export interface ThreeDomainSecureComponentInterface { isEligible(payload: MerchantPayloadData): Promise; - show(): ZalgoPromise; + show(): Promise; } export class ThreeDomainSecureComponent { @@ -131,11 +131,9 @@ export class ThreeDomainSecureComponent { } } - show(): ZalgoPromise { + async show(): Promise { if (!this.threeDSIframe) { - return ZalgoPromise.reject( - new ValidationError(`Ineligible for three domain secure`) - ); + throw new ValidationError(`Ineligible for three domain secure`); } const promise = new ZalgoPromise(); const cancelThreeDS = () => { @@ -147,7 +145,7 @@ export class ThreeDomainSecureComponent { }); }; // $FlowFixMe - const instance = this.threeDSIframe({ + const instance = await this.threeDSIframe({ payerActionUrl: this.authenticationURL, onSuccess: async (res) => { const { reference_id, authentication_status, liability_shift } = res; diff --git a/src/three-domain-secure/component.test.js b/src/three-domain-secure/component.test.js index 98e811da2..68bb4a9b6 100644 --- a/src/three-domain-secure/component.test.js +++ b/src/three-domain-secure/component.test.js @@ -1,7 +1,8 @@ /* @flow */ /* eslint-disable eslint-comments/disable-enable-pair */ -/* eslint-disable no-restricted-globals, promise/no-native, compat/compat */ -import { describe, expect, vi } from "vitest"; +import { describe, expect, vi, afterEach } from "vitest"; +import { getEnv } from "@paypal/sdk-client/src"; +import { FPTI_KEY } from "@paypal/sdk-constants/src"; import { ThreeDomainSecureComponent } from "./component"; @@ -11,9 +12,18 @@ const defaultSdkConfig = { vi.mock("./utils", async () => { return { ...(await vi.importActual("./utils")), - getThreeDomainSecureComponent: vi.fn(), + getFastlaneThreeDS: vi.fn(() => ({ + render: vi.fn().mockResolvedValue({}), + close: vi.fn().mockResolvedValue({}), + })), }; }); +const mockThreeDSIframe = vi.fn(() => ({ + render: vi.fn().mockResolvedValue({}), + close: vi.fn().mockResolvedValue({}), +})); +vi.mock("@paypal/sdk-client/src"); +vi.mocked(getEnv).mockReturnValue("stage"); const defaultEligibilityResponse = { status: "PAYER_ACTION_REQUIRED", links: [{ href: "https://testurl.com", rel: "payer-action" }], @@ -23,6 +33,20 @@ const defaultMerchantPayload = { amount: "1.00", currency: "USD", nonce: "test-nonce", + transactionContext: {}, +}; + +const mockRestClient = { + setAccessToken: vi.fn().mockResolvedValue({}), + request: vi.fn().mockResolvedValue({ + status: "PAYER_ACTION_REQUIRED", + links: [ + { + href: "https://paypal.com/auth", + rel: "payer-action", + }, + ], + }), }; const mockEligibilityRequest = (body = defaultEligibilityResponse) => { @@ -31,7 +55,7 @@ const mockEligibilityRequest = (body = defaultEligibilityResponse) => { const createThreeDomainSecureComponent = ({ sdkConfig = defaultSdkConfig, - restClient = mockEligibilityRequest(), + restClient = mockRestClient, graphQLClient = vi.fn(), logger = { info: vi.fn().mockReturnThis(), @@ -56,8 +80,9 @@ afterEach(() => { vi.clearAllMocks(); }); -describe.skip("three domain secure component - isEligible method", () => { +describe("three domain secure component - isEligible method", () => { test("should return true if payer action required", async () => { + mockRestClient.request = mockEligibilityRequest(); const threeDomainSecureClient = createThreeDomainSecureComponent(); const eligibility = await threeDomainSecureClient.isEligible( defaultMerchantPayload @@ -66,10 +91,12 @@ describe.skip("three domain secure component - isEligible method", () => { }); test("should return false if payer action is not returned", async () => { - const threeDomainSecureClient = createThreeDomainSecureComponent({ - restClient: () => - Promise.resolve({ ...defaultEligibilityResponse, status: "SUCCESS" }), - }); + const inEligibilityResponse = { + status: "SUCCESS", + links: [{ href: "https://testurl.com", rel: "order" }], + }; + mockRestClient.request = mockEligibilityRequest(inEligibilityResponse); + const threeDomainSecureClient = createThreeDomainSecureComponent(); const eligibility = await threeDomainSecureClient.isEligible( defaultMerchantPayload ); @@ -77,31 +104,21 @@ describe.skip("three domain secure component - isEligible method", () => { }); test("should assign correct URL to authenticationURL", async () => { - const threeDomainSecureClient = createThreeDomainSecureComponent({ - restClient: () => - Promise.resolve({ - ...defaultEligibilityResponse, - links: [ - { href: "https://not-payer-action.com", rel: "not-payer-action" }, - ...defaultEligibilityResponse.links, - ], - }), - }); + mockRestClient.request = mockEligibilityRequest(defaultEligibilityResponse); + const threeDomainSecureClient = createThreeDomainSecureComponent(); await threeDomainSecureClient.isEligible(defaultMerchantPayload); expect(threeDomainSecureClient.authenticationURL).toEqual( "https://testurl.com" ); }); - test("create payload with correctly parameters", async () => { - const mockedRequest = mockEligibilityRequest(); - const threeDomainSecureClient = createThreeDomainSecureComponent({ - restClient: mockedRequest, - }); + test("create payload with correct parameters", async () => { + mockRestClient.request = mockEligibilityRequest(); + const threeDomainSecureClient = createThreeDomainSecureComponent(); await threeDomainSecureClient.isEligible(defaultMerchantPayload); - expect(mockedRequest).toHaveBeenCalledWith( + expect(mockRestClient.request).toHaveBeenCalledWith( expect.objectContaining({ data: expect.objectContaining({ intent: "THREE_DS_VERIFICATION", @@ -120,25 +137,66 @@ describe.skip("three domain secure component - isEligible method", () => { ); }); - test.skip("catch errors from the API", async () => { - const mockRequest = vi.fn().mockRejectedValue(new Error("Error with API")); - const threeDomainSecureClient = createThreeDomainSecureComponent({ - restClient: mockRequest, - }); + test("catch errors from the API", async () => { + mockRestClient.request = vi + .fn() + .mockRejectedValue(new Error("Error with API")); + const threeDomainSecureClient = createThreeDomainSecureComponent(); expect.assertions(2); await expect(() => threeDomainSecureClient.isEligible(defaultMerchantPayload) ).rejects.toThrow(new Error("Error with API")); - expect(mockRequest).toHaveBeenCalled(); + expect(mockRestClient.request).toHaveBeenCalled(); }); }); -describe("three domain descure component - show method", () => { - test.todo("should return a zoid component", () => { +describe.todo("three domain descure component - show method", () => { + test("should resolve successfully when threeDSIframe onSuccess is called", async () => { + mockRestClient.request = mockEligibilityRequest(); + const threeDomainSecureClient = createThreeDomainSecureComponent(); + await threeDomainSecureClient.isEligible(defaultMerchantPayload); + // Arrange + const mockSuccessResponse = { + reference_id: "ref-123", + authentication_status: "authenticated", + liability_shift: true, + }; + + const mockClose = vi.fn(); + + mockThreeDSIframe.mockImplementation(({ onSuccess }) => { + setTimeout(() => onSuccess(mockSuccessResponse), 0); + return { close: mockClose }; + }); + const promise = threeDomainSecureClient.show(); + + await expect(promise).resolves.toBeUndefined(); + expect(mockThreeDSIframe).toHaveBeenCalledWith({ + payerActionUrl: "test-url", + onSuccess: expect.any(Function), + }); + }); + test("should create a zoid component and assign to threeDSIframe", async () => { + mockRestClient.request = mockEligibilityRequest(); + const threeDomainSecureClient = createThreeDomainSecureComponent(); + await threeDomainSecureClient.isEligible(defaultMerchantPayload); + expect(threeDomainSecureClient.threeDSIframe).toBeDefined(); + threeDomainSecureClient.threeDSIframe = mockThreeDSIframe; + expect(await threeDomainSecureClient.show()).toEqual({ + liabilityShift: undefined, + authenticationStatus: undefined, + nonce: "test_nonce", + }); + }); + + test("should render threeDS Iframe", async () => { + mockRestClient.request = mockEligibilityRequest(); const threeDomainSecureClient = createThreeDomainSecureComponent(); - threeDomainSecureClient.show(); - // create test for zoid component + await threeDomainSecureClient.isEligible(defaultMerchantPayload); + + await threeDomainSecureClient.show(); + expect(threeDomainSecureClient.threeDSIframe).toBeCalled(); }); }); @@ -155,4 +213,18 @@ describe("three domain secure component - initialization", () => { `script data attribute sdk-client-token is required but was not passed` ); }); + + test("should log FPTI info on initialization", () => { + const logger = { + info: vi.fn().mockReturnThis(), + track: vi.fn().mockReturnThis(), + }; + createThreeDomainSecureComponent({ + logger, + }); + expect(logger.info).toHaveBeenCalledWith("three domain secure v2 invoked"); + expect(logger.track).toHaveBeenCalledWith({ + [FPTI_KEY.TRANSITION]: "three_DS_auth_v2", + }); + }); }); diff --git a/src/three-domain-secure/utils.test.js b/src/three-domain-secure/utils.test.js index 1b5a75e6a..f5fb7d315 100644 --- a/src/three-domain-secure/utils.test.js +++ b/src/three-domain-secure/utils.test.js @@ -32,28 +32,6 @@ describe("Three Domain Secure Utils", () => { // expect(createMock).toHaveBeenCalledTimes(1); }); - it.skip("Should call zoid create with correct params", () => { - vi.resetModules(); - const createMock = vi.fn(); - - vi.doMock("@krakenjs/zoid/src", () => ({ - create: createMock, - type: "zoidComponent", - })); - - // const { create } = await import("@krakenjs/zoid/src"); - - getFastlaneThreeDS(); - - expect(createMock).toHaveBeenCalledTimes(1); - expect(createMock).toHaveBeenCalledWith( - expect.objectContaining({ - tag: "fastlane-threeds", - url: expect.any(Function), - }) - ); - }); - it("Should set window.xchild if component is child", () => { vi.mock("@krakenjs/zoid/src", () => ({ create: vi.fn(() => ({