Skip to content

Commit 298f1d2

Browse files
authored
Adding globalSession to maintain the global_paypal storage (#228)
* Adding globalSession to maintain the global_paypal storage * Improving error handling capability on globalSession
1 parent 4672a1d commit 298f1d2

File tree

3 files changed

+167
-0
lines changed

3 files changed

+167
-0
lines changed

src/globalSession.js

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/* @flow */
2+
3+
import { getStorage, type Storage } from "@krakenjs/belter/src";
4+
import { ZalgoPromise } from "@krakenjs/zalgo-promise/src";
5+
6+
import { getVersion } from "./global";
7+
import { getLogger } from "./logger";
8+
9+
const GLOBAL_SESSION_ID_KEY = "globalSessionID";
10+
11+
export function getGlobalSessionName(): string {
12+
let version = getVersion();
13+
if (!version) {
14+
getLogger().warn("global_session_no_sdk_version");
15+
version = "unknown";
16+
}
17+
const sdkVersion = String(version).replace(/[\W]+/g, "_");
18+
return `paypal_global_${sdkVersion}`;
19+
}
20+
21+
function getGlobalSessionStorage(): Storage {
22+
return getStorage({ name: getGlobalSessionName() });
23+
}
24+
25+
function getGlobalStorageState<T>(handler: (storage: Object) => T): T {
26+
return getGlobalSessionStorage().getState(handler);
27+
}
28+
29+
export function getGlobalSessionID(): string | void {
30+
const globalSessionID = getGlobalStorageState((state) => {
31+
if (
32+
!state ||
33+
typeof state !== "object" ||
34+
!state.hasOwnProperty(GLOBAL_SESSION_ID_KEY)
35+
) {
36+
getLogger().warn("global_session_not_found");
37+
return undefined;
38+
}
39+
return ZalgoPromise.resolve(state[GLOBAL_SESSION_ID_KEY]);
40+
});
41+
return globalSessionID?.value;
42+
}
43+
44+
export function setGlobalSessionID(sessionID: string): void {
45+
getGlobalSessionStorage().getState((state) => {
46+
if (!state || typeof state !== "object") {
47+
getLogger().warn("global_session_no_storage_state_found");
48+
state = {};
49+
}
50+
state[GLOBAL_SESSION_ID_KEY] = sessionID;
51+
return ZalgoPromise.resolve();
52+
});
53+
}

src/globalSession.test.js

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
/* @flow */
2+
import { describe, it, afterEach, expect, vi } from "vitest";
3+
4+
import {
5+
getGlobalSessionName,
6+
getGlobalSessionID,
7+
setGlobalSessionID,
8+
} from "./globalSession";
9+
10+
let storageState = {};
11+
12+
vi.mock("@krakenjs/belter/src", async () => {
13+
const actual = await vi.importActual("@krakenjs/belter/src");
14+
return {
15+
...actual,
16+
getStorage: vi.fn(() => ({
17+
getState: (handler) => handler(storageState),
18+
setState: (newState) => {
19+
storageState = { ...storageState, ...newState };
20+
},
21+
})),
22+
};
23+
});
24+
25+
vi.mock("./global", () => ({
26+
getVersion: vi.fn(() => "5.0.500"),
27+
}));
28+
29+
describe("globalSession", () => {
30+
afterEach(() => {
31+
vi.clearAllMocks();
32+
});
33+
34+
it("should generate the correct global session storage name", () => {
35+
const expectedName = "paypal_global_5_0_500";
36+
37+
const name = getGlobalSessionName();
38+
39+
expect(name).toBe(expectedName);
40+
});
41+
42+
it("should return undefined if globalSessionID is not set", () => {
43+
const globalSessionID = getGlobalSessionID();
44+
45+
expect(globalSessionID).toBeUndefined();
46+
});
47+
48+
it("should set and get the globalSessionID", () => {
49+
const testID = "uid_123456";
50+
setGlobalSessionID(testID);
51+
52+
const globalSessionID = getGlobalSessionID();
53+
54+
expect(globalSessionID).toBe(testID);
55+
});
56+
57+
it("should overwrite the globalSessionID if set multiple times", () => {
58+
const firstID = "uid_first";
59+
const secondID = "uid_second";
60+
61+
setGlobalSessionID(firstID);
62+
setGlobalSessionID(secondID);
63+
const globalSessionID = getGlobalSessionID();
64+
65+
expect(globalSessionID).toBe(secondID);
66+
});
67+
68+
it("should handle setting globalSessionID to an empty string", () => {
69+
const emptyID = "";
70+
71+
setGlobalSessionID(emptyID);
72+
const globalSessionID = getGlobalSessionID();
73+
74+
expect(globalSessionID).toBe(emptyID);
75+
});
76+
77+
it("should return undefined if state is not an object", () => {
78+
storageState = null;
79+
const globalSessionID = getGlobalSessionID();
80+
expect(globalSessionID).toBeUndefined();
81+
});
82+
83+
it("should warn if state is not an object when setting globalSessionID", async () => {
84+
const logger = await import("./logger");
85+
storageState = null;
86+
const warnSpy = vi.spyOn(logger, "getLogger").mockReturnValue({
87+
warn: vi.fn(),
88+
});
89+
90+
setGlobalSessionID("uid_error");
91+
92+
expect(warnSpy().warn).toHaveBeenCalledWith(
93+
"global_session_no_storage_state_found"
94+
);
95+
});
96+
97+
it("should warn if version is not defined", async () => {
98+
const logger = await import("./logger");
99+
const { getVersion } = await import("./global");
100+
// $FlowFixMe
101+
getVersion.mockImplementation(() => undefined);
102+
103+
const warnSpy = vi.spyOn(logger, "getLogger").mockReturnValue({
104+
warn: vi.fn(),
105+
});
106+
107+
getGlobalSessionName();
108+
109+
expect(warnSpy().warn).toHaveBeenCalledWith(
110+
"global_session_no_sdk_version"
111+
);
112+
});
113+
});

src/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,5 @@ export * from "./graphql";
1717
export * from "./domains";
1818
export * from "./tracking";
1919
export * from "./utils";
20+
export * from "./globalSession";
2021
export { buildDPoPHeaders } from "./dpop";

0 commit comments

Comments
 (0)