Skip to content

Commit 249f1e3

Browse files
feat: update loadCoreSdkScript to handle dataNamespace option (#719)
* add data-namespace attribute handling * add tests and update options validation * add changeset
1 parent 03b0069 commit 249f1e3

File tree

4 files changed

+78
-8
lines changed

4 files changed

+78
-8
lines changed

.changeset/shiny-wasps-start.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@paypal/paypal-js": patch
3+
---
4+
5+
Update loadCoreSdkScript function to handle data-namespace attribute.

packages/paypal-js/src/v6/index.test.ts

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,52 @@ describe("loadCoreSdkScript()", () => {
4949
expect(mockedInsertScriptElement).toHaveBeenCalledTimes(1);
5050
});
5151

52-
test("should error due to unvalid input", async () => {
52+
describe("dataNamespace option", () => {
53+
test("should support custom data-namespace attribute", async () => {
54+
const customNamespace = "myCustomNamespace";
55+
56+
// Update mock to set the custom namespace instead of window.paypal
57+
mockedInsertScriptElement.mockImplementationOnce(
58+
({ onSuccess }: ScriptElement) => {
59+
vi.stubGlobal(customNamespace, { version: "6" });
60+
process.nextTick(() => onSuccess());
61+
},
62+
);
63+
64+
const result = await loadCoreSdkScript({
65+
dataNamespace: customNamespace,
66+
});
67+
68+
expect(mockedInsertScriptElement.mock.calls[0][0].url).toEqual(
69+
"https://www.sandbox.paypal.com/web-sdk/v6/core",
70+
);
71+
expect(
72+
mockedInsertScriptElement.mock.calls[0][0].attributes,
73+
).toEqual({
74+
"data-namespace": customNamespace,
75+
});
76+
expect(mockedInsertScriptElement).toHaveBeenCalledTimes(1);
77+
expect(result).toBeDefined();
78+
});
79+
80+
test("should error when dataNamespace is an empty string", async () => {
81+
expect(async () => {
82+
await loadCoreSdkScript({ dataNamespace: "" });
83+
}).rejects.toThrowError(
84+
'The "dataNamespace" option cannot be an empty string',
85+
);
86+
});
87+
88+
test("should error when dataNamespace is only whitespace", async () => {
89+
expect(async () => {
90+
await loadCoreSdkScript({ dataNamespace: " " });
91+
}).rejects.toThrowError(
92+
'The "dataNamespace" option cannot be an empty string',
93+
);
94+
});
95+
});
96+
97+
test("should error due to invalid input", async () => {
5398
expect(async () => {
5499
// @ts-expect-error invalid arguments
55100
await loadCoreSdkScript(123);

packages/paypal-js/src/v6/index.ts

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ const version = "__VERSION__";
88

99
function loadCoreSdkScript(options: LoadCoreSdkScriptOptions = {}) {
1010
validateArguments(options);
11-
const { environment, debug } = options;
11+
const { environment, debug, dataNamespace } = options;
12+
const attributes: Record<string, string> = {};
1213

1314
const baseURL =
1415
environment === "production"
@@ -20,16 +21,27 @@ function loadCoreSdkScript(options: LoadCoreSdkScriptOptions = {}) {
2021
url.searchParams.append("debug", "true");
2122
}
2223

24+
if (dataNamespace) {
25+
attributes["data-namespace"] = dataNamespace;
26+
}
27+
2328
return new Promise<PayPalV6Namespace>((resolve, reject) => {
2429
insertScriptElement({
2530
url: url.toString(),
31+
attributes,
2632
onSuccess: () => {
27-
if (!window.paypal) {
33+
const namespace = dataNamespace ?? "paypal";
34+
const paypalSDK = Reflect.get(
35+
window,
36+
namespace,
37+
) as PayPalV6Namespace;
38+
39+
if (!paypalSDK) {
2840
return reject(
29-
"The window.paypal global variable is not available",
41+
`The window.${namespace} global variable is not available`,
3042
);
3143
}
32-
return resolve(window.paypal as unknown as PayPalV6Namespace);
44+
return resolve(paypalSDK);
3345
},
3446
onError: () => {
3547
const defaultError = new Error(
@@ -46,7 +58,7 @@ function validateArguments(options: unknown) {
4658
if (typeof options !== "object" || options === null) {
4759
throw new Error("Expected an options object");
4860
}
49-
const { environment } = options as LoadCoreSdkScriptOptions;
61+
const { environment, dataNamespace } = options as LoadCoreSdkScriptOptions;
5062

5163
if (
5264
environment &&
@@ -57,6 +69,10 @@ function validateArguments(options: unknown) {
5769
'The "environment" option must be either "production" or "sandbox"',
5870
);
5971
}
72+
73+
if (dataNamespace !== undefined && dataNamespace.trim() === "") {
74+
throw new Error('The "dataNamespace" option cannot be an empty string');
75+
}
6076
}
6177

6278
export { loadCoreSdkScript, version };

packages/paypal-js/types/v6/index.d.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -171,10 +171,14 @@ export interface BaseInstance {
171171
updateLocale: (locale: string) => void;
172172
}
173173

174-
export type LoadCoreSdkScriptOptions = {
174+
interface CoreSdkScriptDataAttributes {
175+
dataNamespace?: string;
176+
}
177+
178+
export interface LoadCoreSdkScriptOptions extends CoreSdkScriptDataAttributes {
175179
environment?: "production" | "sandbox";
176180
debug?: boolean;
177-
};
181+
}
178182

179183
export function loadCoreSdkScript(
180184
options: LoadCoreSdkScriptOptions,

0 commit comments

Comments
 (0)