diff --git a/package-lock.json b/package-lock.json index 831e305..332210e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,19 +1,20 @@ { "name": "statsig-react", - "version": "1.21.1", + "version": "1.22.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "statsig-react", - "version": "1.21.1", + "version": "1.22.0", "license": "ISC", "dependencies": { "statsig-js": "^4.28.1" }, "devDependencies": { "@testing-library/jest-dom": "^5.14.1", - "@testing-library/react": "^12.1.2", + "@testing-library/react": "^12.1.5", + "@testing-library/user-event": "^14.4.3", "@types/jest": "^27.0.2", "@types/node": "^16.7.9", "@types/react": "^17.0.9", @@ -1068,20 +1069,34 @@ } }, "node_modules/@testing-library/react": { - "version": "12.1.2", - "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-12.1.2.tgz", - "integrity": "sha512-ihQiEOklNyHIpo2Y8FREkyD1QAea054U0MVbwH1m8N9TxeFz+KoJ9LkqoKqJlzx2JDm56DVwaJ1r36JYxZM05g==", + "version": "12.1.5", + "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-12.1.5.tgz", + "integrity": "sha512-OfTXCJUFgjd/digLUuPxa0+/3ZxsQmE7ub9kcbW/wi96Bh3o/p5vrETcBGfP17NWPGqeYYl5LTRpwyGoMC4ysg==", "dev": true, "dependencies": { "@babel/runtime": "^7.12.5", - "@testing-library/dom": "^8.0.0" + "@testing-library/dom": "^8.0.0", + "@types/react-dom": "<18.0.0" }, "engines": { "node": ">=12" }, "peerDependencies": { - "react": "*", - "react-dom": "*" + "react": "<18.0.0", + "react-dom": "<18.0.0" + } + }, + "node_modules/@testing-library/user-event": { + "version": "14.4.3", + "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.4.3.tgz", + "integrity": "sha512-kCUc5MEwaEMakkO5x7aoD+DLi02ehmEM2QCGWvNqAS1dV/fAvORWEjnjsEIvml59M7Y5kCkWN6fCCyPOe8OL6Q==", + "dev": true, + "engines": { + "node": ">=12", + "npm": ">=6" + }, + "peerDependencies": { + "@testing-library/dom": ">=7.21.4" } }, "node_modules/@tootallnate/once": { @@ -1862,9 +1877,9 @@ "dev": true }, "node_modules/decode-uri-component": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", + "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==", "dev": true, "engines": { "node": ">=0.10" @@ -3677,9 +3692,9 @@ } }, "node_modules/minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "dependencies": { "brace-expansion": "^1.1.7" @@ -3754,6 +3769,14 @@ "integrity": "sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==", "dev": true }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -3977,28 +4000,30 @@ } }, "node_modules/react": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", - "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz", + "integrity": "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==", "peer": true, "dependencies": { - "loose-envify": "^1.1.0" + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" }, "engines": { "node": ">=0.10.0" } }, "node_modules/react-dom": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", - "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz", + "integrity": "sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==", "dev": true, "dependencies": { "loose-envify": "^1.1.0", - "scheduler": "^0.23.0" + "object-assign": "^4.1.1", + "scheduler": "^0.20.2" }, "peerDependencies": { - "react": "^18.2.0" + "react": "17.0.2" } }, "node_modules/react-is": { @@ -4118,12 +4143,13 @@ } }, "node_modules/scheduler": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", - "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz", + "integrity": "sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==", "dev": true, "dependencies": { - "loose-envify": "^1.1.0" + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" } }, "node_modules/semver": { @@ -5585,15 +5611,23 @@ } }, "@testing-library/react": { - "version": "12.1.2", - "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-12.1.2.tgz", - "integrity": "sha512-ihQiEOklNyHIpo2Y8FREkyD1QAea054U0MVbwH1m8N9TxeFz+KoJ9LkqoKqJlzx2JDm56DVwaJ1r36JYxZM05g==", + "version": "12.1.5", + "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-12.1.5.tgz", + "integrity": "sha512-OfTXCJUFgjd/digLUuPxa0+/3ZxsQmE7ub9kcbW/wi96Bh3o/p5vrETcBGfP17NWPGqeYYl5LTRpwyGoMC4ysg==", "dev": true, "requires": { "@babel/runtime": "^7.12.5", - "@testing-library/dom": "^8.0.0" + "@testing-library/dom": "^8.0.0", + "@types/react-dom": "<18.0.0" } }, + "@testing-library/user-event": { + "version": "14.4.3", + "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.4.3.tgz", + "integrity": "sha512-kCUc5MEwaEMakkO5x7aoD+DLi02ehmEM2QCGWvNqAS1dV/fAvORWEjnjsEIvml59M7Y5kCkWN6fCCyPOe8OL6Q==", + "dev": true, + "requires": {} + }, "@tootallnate/once": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", @@ -6238,9 +6272,9 @@ "dev": true }, "decode-uri-component": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", + "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==", "dev": true }, "dedent": { @@ -7608,9 +7642,9 @@ "dev": true }, "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "requires": { "brace-expansion": "^1.1.7" @@ -7673,6 +7707,11 @@ "integrity": "sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==", "dev": true }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" + }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -7838,22 +7877,24 @@ "dev": true }, "react": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", - "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz", + "integrity": "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==", "peer": true, "requires": { - "loose-envify": "^1.1.0" + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" } }, "react-dom": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", - "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz", + "integrity": "sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==", "dev": true, "requires": { "loose-envify": "^1.1.0", - "scheduler": "^0.23.0" + "object-assign": "^4.1.1", + "scheduler": "^0.20.2" } }, "react-is": { @@ -7946,12 +7987,13 @@ } }, "scheduler": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", - "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz", + "integrity": "sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==", "dev": true, "requires": { - "loose-envify": "^1.1.0" + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" } }, "semver": { diff --git a/package.json b/package.json index a5f3cf1..746c6c2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "statsig-react", - "version": "1.21.1", + "version": "1.22.0", "description": "An SDK for using Statsig Feature Management and Experimentation platform in React clients", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -27,7 +27,8 @@ "homepage": "https://github.com/statsig-io/react-sdk#readme", "devDependencies": { "@testing-library/jest-dom": "^5.14.1", - "@testing-library/react": "^12.1.2", + "@testing-library/react": "^12.1.5", + "@testing-library/user-event": "^14.4.3", "@types/jest": "^27.0.2", "@types/node": "^16.7.9", "@types/react": "^17.0.9", diff --git a/src/Statsig.ts b/src/Statsig.ts index af7ed78..43cf80a 100644 --- a/src/Statsig.ts +++ b/src/Statsig.ts @@ -23,6 +23,13 @@ import type { } from 'statsig-js'; import { staticImplements, StatsigStatic } from './StatsigStatic'; +declare global { + interface Window { + __STATSIG_SDK__: Statsig; + __STATSIG_RERENDER_OVERRIDE__: () => void; + } +} + export type CheckGateOptions = { ignoreOverrides?: boolean; }; @@ -37,6 +44,8 @@ export type GetLayerOptions = { keepDeviceValue?: boolean; }; +export type StatsigReactContextUpdater = () => void; + @staticImplements() export default class Statsig { private static instance: StatsigClient; @@ -51,6 +60,7 @@ export default class Statsig { private static expoConstants?: ExpoConstants; private static expoDevice?: ExpoDevice; private static uuid?: UUID; + private static reactContextUpdater: StatsigReactContextUpdater | null = null; public static async initialize( sdkKey: string, @@ -296,7 +306,11 @@ export default class Statsig { if (!this.isInitialized()) { return; } + if (Statsig.getAllOverrides()["gates"]?.[gateName] === value) { + return; + } Statsig.instance.overrideGate(gateName, value); + Statsig.updateContext(); } /** @@ -308,7 +322,11 @@ export default class Statsig { if (!this.isInitialized()) { return; } + if (Statsig.getAllOverrides()["configs"]?.[configName] === value) { + return; + } Statsig.instance.overrideConfig(configName, value); + Statsig.updateContext(); } /** @@ -320,7 +338,11 @@ export default class Statsig { if (!this.isInitialized()) { return; } + if (Statsig.getAllOverrides()["layers"]?.[layerName] === value) { + return; + } Statsig.instance.overrideLayer(layerName, value); + Statsig.updateContext(); } /** @@ -331,6 +353,7 @@ export default class Statsig { return; } Statsig.instance.removeGateOverride(name); + Statsig.updateContext(); } /** @@ -341,6 +364,7 @@ export default class Statsig { return; } Statsig.instance.removeConfigOverride(name); + Statsig.updateContext(); } /** @@ -351,6 +375,7 @@ export default class Statsig { return; } Statsig.instance.removeLayerOverride(name); + Statsig.updateContext(); } /** @@ -443,6 +468,10 @@ export default class Statsig { } } + public static setReactContextUpdater(fn: (() => void) | null) { + Statsig.reactContextUpdater = fn; + } + private static isInitialized(): boolean { if (Statsig.instance) { return true; @@ -468,6 +497,12 @@ export default class Statsig { Statsig.instance = new StatsigClient(sdkKey, user, options); } + private static updateContext() { + if (Statsig.reactContextUpdater != null) { + Statsig.reactContextUpdater(); + } + } + private static canThrow() { return ( typeof process === 'undefined' || diff --git a/src/StatsigContext.ts b/src/StatsigContext.ts index 558c5bc..a162aae 100644 --- a/src/StatsigContext.ts +++ b/src/StatsigContext.ts @@ -1,11 +1,14 @@ import React from 'react'; -import { IStatsig, StatsigClient } from 'statsig-js'; +import { StatsigUser } from 'statsig-js'; + +export type UpdateUserFunc = React.Dispatch>; export interface TStatsigContext { initialized: boolean; statsigPromise: React.MutableRefObject> | null; userVersion: number; initStarted: boolean; + updateUser: UpdateUserFunc; } /** @@ -16,4 +19,5 @@ export default React.createContext({ statsigPromise: null, userVersion: 0, initStarted: false, + updateUser: () => {}, }); diff --git a/src/StatsigProvider.tsx b/src/StatsigProvider.tsx index e8393bb..2547afc 100644 --- a/src/StatsigProvider.tsx +++ b/src/StatsigProvider.tsx @@ -1,18 +1,18 @@ -import React, { useRef, useEffect, useState, useMemo } from 'react'; -import StatsigContext from './StatsigContext'; -import { StatsigOptions } from './StatsigOptions'; -import { StatsigUser, _SDKPackageInfo } from 'statsig-js'; -import Statsig from './Statsig'; - import type { - NativeModules, - Platform, + AsyncStorage, DeviceInfo, ExpoConstants, ExpoDevice, - AsyncStorage, + NativeModules, + Platform, UUID, } from 'statsig-js'; +import React, { useEffect, useMemo, useRef, useState } from 'react'; +import StatsigContext, { UpdateUserFunc } from './StatsigContext'; +import { StatsigUser, _SDKPackageInfo } from 'statsig-js'; + +import Statsig from './Statsig'; +import { StatsigOptions } from './StatsigOptions'; /** * Properties required to initialize the Statsig React SDK @@ -30,6 +30,12 @@ type Props = { */ user: StatsigUser; + /** + * A function to keep your reference to a StatsigUser in-sync with Statsig's reference. + * This is required if you want to use the useUpdateUser hook. + */ + setUser?: UpdateUserFunc; + /** * Options for initializing the SDK, shared with the statsig-js SDK */ @@ -94,6 +100,7 @@ export default function StatsigProvider({ children, sdkKey, user, + setUser, options, waitForInitialization, initializingComponent, @@ -104,6 +111,7 @@ export default function StatsigProvider({ const [initialized, setInitialized] = useState(false); const resolver = useRef<(() => void) | null>(null); const [userVersion, setUserVersion] = useState(0); + let statsigPromise = useRef>( new Promise((resolve, _reject) => { resolver.current = resolve; @@ -128,7 +136,7 @@ export default function StatsigProvider({ Statsig.updateUser(user).then(() => { resolver.current && resolver.current(); - setUserVersion(userVersion + 1); + setUserVersion((version) => version + 1); if (unmount) { setInitialized(true); } @@ -162,13 +170,21 @@ export default function StatsigProvider({ setInitialized(true); resolver.current && resolver.current(); }); + if (typeof window !== 'undefined') { + window.__STATSIG_SDK__ = Statsig; + window.__STATSIG_RERENDER_OVERRIDE__ = () => { + setUserVersion(userVersion + 1); + }; + } }, [userMemo]); useEffect(() => { + Statsig.setReactContextUpdater(() => setUserVersion((version) => version + 1)); return () => { if (shutdownOnUnmount) { Statsig.shutdown(); } + Statsig.setReactContextUpdater(null) }; }, []); @@ -181,15 +197,24 @@ export default function StatsigProvider({ child = initializingComponent; } + const contextValue = useMemo( + () => ({ + initialized, + statsigPromise, + userVersion, + initStarted: Statsig.initializeCalled(), + updateUser: setUser ?? (() => {}), + }), + [ + initialized, + statsigPromise, + userVersion, + Statsig.initializeCalled(), + setUser, + ], + ); return ( - + {child} ); diff --git a/src/StatsigSynchronousProvider.tsx b/src/StatsigSynchronousProvider.tsx index 017123e..300e76a 100644 --- a/src/StatsigSynchronousProvider.tsx +++ b/src/StatsigSynchronousProvider.tsx @@ -1,8 +1,9 @@ import React, { useEffect, useMemo, useRef, useState } from 'react'; -import StatsigContext from './StatsigContext'; -import { StatsigOptions } from './StatsigOptions'; +import StatsigContext, { UpdateUserFunc } from './StatsigContext'; import { StatsigUser, _SDKPackageInfo } from 'statsig-js'; + import Statsig from './Statsig'; +import { StatsigOptions } from './StatsigOptions'; /** * Properties required to initialize the Statsig React SDK @@ -20,6 +21,12 @@ type Props = { */ user: StatsigUser; + /** + * A function to keep your reference to a StatsigUser in-sync with Statsig's reference. + * This is required if you want to use the useUpdateUser hook. + */ + setUser?: UpdateUserFunc; + /** * The values to initialize the SDK with. Required for this provider. For non server side rendered use cases, * @see StatsigProvider.tsx @@ -31,6 +38,9 @@ type Props = { * */ options?: StatsigOptions; + + + shutdownOnUnmount?: boolean; }; /** @@ -51,6 +61,8 @@ export default function StatsigSynchronousProvider({ user, options, initializeValues, + setUser, + shutdownOnUnmount, }: Props): JSX.Element { const [userVersion, setUserVersion] = useState(0); const [initialized, setInitialized] = useState(true); @@ -67,6 +79,13 @@ export default function StatsigSynchronousProvider({ // we dont want to modify state and trigger a rerender // and the SDK is already initialized/usable firstUpdate.current = false; + + if (typeof window !== 'undefined') { + window.__STATSIG_SDK__ = Statsig; + window.__STATSIG_RERENDER_OVERRIDE__ = () => { + setUserVersion(userVersion + 1); + }; + } return; } // subsequent runs should update the user @@ -77,15 +96,28 @@ export default function StatsigSynchronousProvider({ }); }, [userMemo]); + useEffect(() => { + Statsig.setReactContextUpdater(() => setUserVersion((version) => version + 1)); + return () => { + if (shutdownOnUnmount) { + Statsig.shutdown(); + } + Statsig.setReactContextUpdater(null) + }; + }, []); + + + const contextValue = useMemo(() => { + return { + initialized: initialized, + statsigPromise: null, + userVersion: userVersion, + initStarted: Statsig.initializeCalled(), + updateUser: setUser ?? (() => {}), + }; + }, [initialized, userVersion, Statsig.initializeCalled(), setUser]); return ( - + {children} ); diff --git a/src/__tests__/StatsigProvider.test.tsx b/src/__tests__/StatsigProvider.test.tsx new file mode 100644 index 0000000..f223af6 --- /dev/null +++ b/src/__tests__/StatsigProvider.test.tsx @@ -0,0 +1,156 @@ +/** + * @jest-environment jsdom + */ + +import '@testing-library/jest-dom'; +import { render, screen, waitFor } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import React, { useState } from 'react'; +import StatsigJS, { StatsigUser } from 'statsig-js'; +import StatsigProvider from '../StatsigProvider'; +import useUpdateUser from '../useUpdateUser'; + +const TID_USER_VALUE = 'statsig-user-object'; +const TID_SET_USER_STATE = 'update-via-set-state'; +const TID_UPDATE_USER_HOOK = 'update-via-hook'; +const TID_PARTIAL_UPDATE_USER_HOOK = 'partial-update-via-hook'; + +StatsigJS.encodeIntializeCall = false; + +function UpdateUserHookTestComponent(props: { userID: string }) { + const updateUser = useUpdateUser(); + + return ( + <> +