diff --git a/package.json b/package.json index e7dd987..41e7b74 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "karma": "cross-env NODE_ENV=test babel-node --plugins=transform-es2015-modules-commonjs ./node_modules/.bin/karma start", "babel": "babel src/ --out-dir dist/module", "webpack": "babel-node --plugins=transform-es2015-modules-commonjs ./node_modules/.bin/webpack --progress", - "test": "npm run format:check && npm run lint && npm run flow-typed && npm run flow && npm run karma", + "test": "npm run format:check && npm run lint && npm run flow-typed && npm run flow && npm run vitest && npm run karma", "build": "npm run test && npm run babel && npm run webpack", "clean": "rimraf dist coverage", "reinstall": "rimraf flow-typed && rimraf node_modules && npm install && flow-typed install", @@ -21,7 +21,8 @@ "prepare": "husky install", "prerelease": "npm run clean && npm run build && git add dist && git commit -m 'ci: check in dist folder' || echo 'Nothing to distribute'", "release": "standard-version", - "postrelease": "git push && git push --follow-tags && npm publish" + "postrelease": "git push && git push --follow-tags && npm publish", + "vitest": "vitest" }, "standard-version": { "types": [ @@ -86,6 +87,7 @@ "license": "Apache-2.0", "readmeFilename": "README.md", "devDependencies": { + "@bunchtogether/vite-plugin-flow": "^1.0.2", "@commitlint/cli": "^16.2.1", "@commitlint/config-conventional": "^16.2.1", "@krakenjs/grumbler-scripts": "^8.0.5", @@ -93,10 +95,13 @@ "flow-bin": "0.155.0", "flow-typed": "^3.8.0", "husky": "^7.0.4", + "jsdom": "^22.1.0", "lint-staged": "^12.4.0", "mocha": "^4.1.0", "prettier": "^2.6.2", - "standard-version": "^9.3.2" + "standard-version": "^9.3.2", + "vite": "^4.5.0", + "vitest": "^0.34.6" }, "dependencies": { "@krakenjs/cross-domain-safe-weakmap": "^2.0.2", diff --git a/src/storage.js b/src/storage.js index 173fddb..be13481 100644 --- a/src/storage.js +++ b/src/storage.js @@ -18,9 +18,13 @@ const DEFAULT_SESSION_STORAGE = 20 * 60 * 1000; export function getStorage({ name, lifetime = DEFAULT_SESSION_STORAGE, + // a sticky session id helps to identify sdk sessions that were created by other sdks + // like the situation where the Braintree SDK loads the PP SDK + stickySessionId, }: {| name: string, lifetime?: number, + stickySessionId?: string, |}): Storage { return inlineMemoize( getStorage, @@ -94,7 +98,7 @@ export function getStorage({ if (!session) { session = { - guid: uniqueID(), + guid: stickySessionId || uniqueID(), created: now, }; } diff --git a/src/storage.test.js b/src/storage.test.js new file mode 100644 index 0000000..2f3b7f2 --- /dev/null +++ b/src/storage.test.js @@ -0,0 +1,49 @@ +/* @flow */ +import { vi, describe, test, expect, beforeEach } from "vitest"; + +import { getStorage } from "./storage"; +import { uniqueID } from "./util"; + +vi.mock("./util", async () => { + const actual = await vi.importActual("./util"); + + return { + ...actual, + uniqueID: vi.fn(() => "unique-id-123"), + getGlobal: vi.fn(() => ({})), + inlineMemoize: vi.fn((_, impl) => impl()), + }; +}); + +describe("storage", () => { + beforeEach(() => { + window.localStorage.clear(); + }); + + test("happy path works", () => { + // $FlowIssue mock + uniqueID.mockReturnValue("fake-id"); + const { getID } = getStorage({ name: "test" }); + + expect(getID()).toEqual("fake-id"); + }); + + test("unique id is used for session id", () => { + // $FlowIssue mock + uniqueID.mockReturnValue("fake-session-id"); + const { getSessionID } = getStorage({ name: "test" }); + + expect(getSessionID()).toEqual("fake-session-id"); + }); + + test("sticky session id is used for session id", () => { + // $FlowIssue mock + uniqueID.mockReturnValue("fake-session-id"); + const { getSessionID } = getStorage({ + name: "test", + stickySessionId: "sticky-session-id", + }); + + expect(getSessionID()).toEqual("sticky-session-id"); + }); +}); diff --git a/vite.config.js b/vite.config.js new file mode 100644 index 0000000..dca910f --- /dev/null +++ b/vite.config.js @@ -0,0 +1,31 @@ +/* eslint-disable eslint-comments/disable-enable-pair */ +/* eslint-disable spaced-comment */ +/* eslint-disable import/no-default-export */ +/// + +// Configure Vitest (https://vitest.dev/config/) + +/* @flow */ + +import { defineConfig } from "vite"; +import { flowPlugin, esbuildFlowPlugin } from "@bunchtogether/vite-plugin-flow"; + +// $FlowIssue +export default defineConfig({ + test: { + environment: "jsdom", + clearMocks: true, + include: ["**/src/**/*.test.js"], + }, + optimizeDeps: { + esbuildOptions: { + plugins: [esbuildFlowPlugin()], + }, + }, + plugins: [ + // $FlowIssue + flowPlugin({ + exclude: "", + }), + ], +});