-
Notifications
You must be signed in to change notification settings - Fork 563
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
Defining ThreeDomainSecureClient component interface #2447
Changes from 9 commits
2a9545d
dd3c570
673d98d
71c8127
62afa53
89020d4
93e1b36
c718c95
295d091
4fd9cef
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,30 +1,52 @@ | ||
/* @flow */ | ||
import { getLogger, getSDKToken } from "@paypal/sdk-client/src"; | ||
import { type LoggerType } from "@krakenjs/beaver-logger/src"; | ||
import { FPTI_KEY } from "@paypal/sdk-constants/src"; | ||
|
||
import { ValidationError } from "../lib"; | ||
|
||
export const getThreeDomainSecure = (): Function => { | ||
const sdkToken = getSDKToken(); | ||
const ThreeDomainSecureAuth = () => { | ||
if (sdkToken) { | ||
// eslint-disable-next-line no-console | ||
console.log("Three Domain Secure Called"); | ||
// Make a Zoid component and introduce methods here | ||
// onSuccess | ||
// onCancel | ||
// onClose | ||
getLogger() | ||
.info("three domain secure v2 invoked") | ||
.track({ | ||
[FPTI_KEY.TRANSITION]: "three_DS_auth_v2", | ||
}); | ||
} else { | ||
throw new ValidationError( | ||
`script data attribute sdk-client-token is required but was not passed` | ||
); | ||
} | ||
}; | ||
|
||
return ThreeDomainSecureAuth; | ||
type SdkConfig = {| | ||
sdkToken: ?string, | ||
|}; | ||
|
||
const parseSdkConfig = ({ sdkConfig, logger }): SdkConfig => { | ||
if (!sdkConfig.sdkToken) { | ||
throw new ValidationError( | ||
`script data attribute sdk-client-token is required but was not passed` | ||
); | ||
} | ||
|
||
logger.info("three domain secure v2 invoked").track({ | ||
[FPTI_KEY.TRANSITION]: "three_DS_auth_v2", | ||
}); | ||
|
||
return sdkConfig; | ||
}; | ||
export interface ThreeDomainSecureComponentInterface { | ||
isEligible(): void; | ||
mchoun marked this conversation as resolved.
Show resolved
Hide resolved
|
||
show(): void; | ||
} | ||
export class ThreeDomainSecureComponent { | ||
logger: LoggerType; | ||
sdkConfig: SdkConfig; | ||
|
||
constructor({ | ||
logger, | ||
sdkConfig, | ||
}: {| | ||
logger: LoggerType, | ||
sdkConfig: SdkConfig, | ||
|}) { | ||
this.logger = logger; | ||
this.sdkConfig = parseSdkConfig({ sdkConfig, logger }); | ||
} | ||
|
||
isEligible() { | ||
// eslint-disable-next-line no-console | ||
console.log("eligible"); | ||
} | ||
|
||
show() { | ||
// eslint-disable-next-line no-console | ||
console.log("show"); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,44 +1,61 @@ | ||
/* @flow */ | ||
import { describe, expect, it, vi } from "vitest"; | ||
import { getSDKToken } from "@paypal/sdk-client/src"; | ||
import { describe, expect, vi } from "vitest"; | ||
|
||
import { ValidationError } from "../lib"; | ||
import { ThreeDomainSecureComponent } from "./component"; | ||
|
||
import { getThreeDomainSecure } from "./component"; | ||
const defaultSdkConfig = { | ||
sdkToken: "sdk-client-token", | ||
}; | ||
|
||
vi.mock("@paypal/sdk-client/src", () => ({ | ||
getSDKToken: vi.fn(), | ||
getLogger: vi.fn(() => ({ | ||
const createThreeDomainSecureComponent = ({ | ||
sdkConfig = defaultSdkConfig, | ||
logger = { | ||
info: vi.fn().mockReturnThis(), | ||
warn: vi.fn().mockReturnThis(), | ||
error: vi.fn().mockReturnThis(), | ||
track: vi.fn().mockReturnThis(), | ||
flush: vi.fn().mockReturnThis(), | ||
})), | ||
})); | ||
vi.mock("../lib", () => ({ | ||
ValidationError: vi.fn(), | ||
})); | ||
describe("getThreeDomainSecure returns ThreeDomainSecureComponent", () => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we still want to keep this test? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I moved this test further down on Line 46 as a general initialization test. Instead of mocking the ValidationError I'm just asserting that it would throw an error. Is this OK or does it change the test? I wasn't entirely sure. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see, yeah that should work too. My idea with that test was to capture |
||
it("should throw an error if sdkToken is not present", () => { | ||
// $FlowFixMe prop missing error | ||
getSDKToken.mockReturnValue(undefined); | ||
const ThreeDomainSecureComponent = getThreeDomainSecure(); | ||
expect(() => ThreeDomainSecureComponent()).toThrowError(ValidationError); | ||
expect(ValidationError).toHaveBeenCalledWith( | ||
`script data attribute sdk-client-token is required but was not passed` | ||
); | ||
metricCounter: vi.fn().mockReturnThis(), | ||
}, | ||
} = {}) => | ||
new ThreeDomainSecureComponent({ | ||
sdkConfig, | ||
// $FlowIssue | ||
logger, | ||
}); | ||
it("should return the ThreeDomainSecure component and log the correct message", async () => { | ||
// eslint-disable-next-line no-empty-function | ||
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => {}); | ||
// $FlowFixMe prop missing error | ||
getSDKToken.mockReturnValue("84ghb8984"); | ||
const ThreeDomainSecureComponent = getThreeDomainSecure(); | ||
expect(typeof ThreeDomainSecureComponent).toBe("function"); | ||
|
||
// Call the returned component and check the console log | ||
await ThreeDomainSecureComponent(); | ||
expect(consoleSpy).toHaveBeenCalledWith("Three Domain Secure Called"); | ||
afterEach(() => { | ||
vi.clearAllMocks(); | ||
}); | ||
|
||
describe("three domain secure component - isEligible method", () => { | ||
test("should console log eligible", () => { | ||
const consoleSpy = vi.spyOn(console, "log"); | ||
const threeDomainSecuretClient = createThreeDomainSecureComponent(); | ||
threeDomainSecuretClient.isEligible(); | ||
expect(consoleSpy).toHaveBeenCalledWith("eligible"); | ||
}); | ||
}); | ||
|
||
consoleSpy.mockRestore(); | ||
describe("three domain descure component - show method", () => { | ||
test("should console log show", () => { | ||
const consoleSpy = vi.spyOn(console, "log"); | ||
const threeDomainSecuretClient = createThreeDomainSecureComponent(); | ||
threeDomainSecuretClient.show(); | ||
expect(consoleSpy).toHaveBeenCalledWith("show"); | ||
}); | ||
}); | ||
|
||
describe("three domain secure component - initialization", () => { | ||
test("should throw an error if sdkToken is not present", () => { | ||
expect(() => | ||
createThreeDomainSecureComponent({ | ||
sdkConfig: { | ||
...defaultSdkConfig, | ||
sdkToken: "", | ||
}, | ||
}) | ||
).toThrowError( | ||
`script data attribute sdk-client-token is required but was not passed` | ||
); | ||
}); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,26 @@ | ||
/* @flow */ | ||
import { type ZoidComponent } from "@krakenjs/zoid/src"; | ||
import { getLogger, getSDKToken } from "@paypal/sdk-client/src"; | ||
|
||
import type { LazyExport } from "../types"; | ||
import { protectedExport } from "../lib"; | ||
|
||
import { getThreeDomainSecure } from "./component"; | ||
import { | ||
ThreeDomainSecureComponent, | ||
type ThreeDomainSecureComponentInterface, | ||
} from "./component"; | ||
|
||
type ThreeDomainSecureAuth = ZoidComponent<void>; | ||
|
||
export const ThreeDomainSecureComponent: LazyExport<ThreeDomainSecureAuth> = { | ||
__get__: () => protectedExport(getThreeDomainSecure()), | ||
}; | ||
export const ThreeDomainSecureClient: LazyExport<ThreeDomainSecureComponentInterface> = | ||
{ | ||
__get__: () => { | ||
const threeDomainSecureInstance = new ThreeDomainSecureComponent({ | ||
logger: getLogger(), | ||
sdkConfig: { | ||
sdkToken: getSDKToken(), | ||
}, | ||
}); | ||
return protectedExport({ | ||
isEligible: () => threeDomainSecureInstance.isEligible(), | ||
show: () => threeDomainSecureInstance.show(), | ||
}); | ||
}, | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -48,11 +48,11 @@ const CARD_FIELD_TYPE = { | |
}; | ||
|
||
type InstallmentsConfiguration = {| | ||
financingCountryCode : string, | ||
currencyCode : string, | ||
billingCountryCode : string, | ||
amount : string, | ||
includeBuyerInstallments ? : boolean | ||
financingCountryCode: string, | ||
currencyCode: string, | ||
billingCountryCode: string, | ||
amount: string, | ||
includeBuyerInstallments?: boolean, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: do we want to remove the lint updates out of this PR for clarity? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good call. I can create a separate PR for the lint commits. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We can leave it in for this one. But also the comment, so it is easier to trace back that it is simply a lint update and not actual code changes. |
||
|}; | ||
|
||
type CardFieldsProps = {| | ||
|
@@ -109,10 +109,12 @@ type CardFieldsProps = {| | |
hcfSessionID: string, | ||
partnerAttributionID: string, | ||
merchantID: $ReadOnlyArray<string>, | ||
installments? : {| | ||
onInstallmentsRequested : () => InstallmentsConfiguration | ZalgoPromise<InstallmentsConfiguration>, | ||
onInstallmentsAvailable : (Object) => void, | ||
onInstallmentsError? : (Object) => void | ||
installments?: {| | ||
onInstallmentsRequested: () => | ||
| InstallmentsConfiguration | ||
| ZalgoPromise<InstallmentsConfiguration>, | ||
onInstallmentsAvailable: (Object) => void, | ||
onInstallmentsError?: (Object) => void, | ||
|}, | ||
|}; | ||
|
||
|
@@ -445,7 +447,7 @@ export const getCardFieldsComponent: () => CardFieldsComponent = memoize( | |
installments: { | ||
type: "object", | ||
required: false, | ||
value: ({ props }) => props.parent.props.installments | ||
value: ({ props }) => props.parent.props.installments, | ||
}, | ||
}, | ||
}); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: We can probably remove the
?
here. It is required to be a stringThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removing this creates a flow error. I believe that it is possible for null or undefined to be returned by
getSDKToken
which is why it should be optional