diff --git a/package.json b/package.json index 89e46bc..a003e92 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@flagship.io/react-sdk", "sideEffects": false, - "version": "5.2.2", + "version": "5.2.3", "license": "Apache-2.0", "description": "Flagship REACT SDK", "main": "dist/src/index.js", @@ -32,7 +32,7 @@ } }, "dependencies": { - "@flagship.io/js-sdk": "^5.1.7", + "@flagship.io/js-sdk": "^5.2.0", "encoding": "^0.1.13" }, "peerDependencies": { diff --git a/src/FlagshipProvider.tsx b/src/FlagshipProvider.tsx index afb8568..5a84ad3 100644 --- a/src/FlagshipProvider.tsx +++ b/src/FlagshipProvider.tsx @@ -205,7 +205,8 @@ export function FlagshipProvider({ // eslint-disable-next-line @typescript-eslint/no-explicit-any decisionMode: decisionMode as any, fetchNow: configRef.current.fetchNow, - onSdkStatusChanged: (...args) => handleSdkStatusChangeRef.current(...args), + onSdkStatusChanged: (...args) => + handleSdkStatusChangeRef.current(...args), onBucketingUpdated: (...args) => handleBucketingUpdateRef.current(...args), hitDeduplicationTime: configRef.current.hitDeduplicationTime, @@ -213,7 +214,7 @@ export function FlagshipProvider({ sdkVersion: configRef.current.sdkVersion, ...propsRef.current, }); - }, [envId, apiKey, decisionMode]); + }, [envId, apiKey, decisionMode, props.isQAModeEnabled]); const updateFlagshipVisitor = useCallback((): void => { if ( @@ -274,7 +275,12 @@ export function FlagshipProvider({ const handleDisplay = useMemo((): ReactNode => { const isFirstInit = !flagshipState.visitor; - if (flagshipState.isInitializing && loadingComponent && isFirstInit && fetchNow) { + if ( + flagshipState.isInitializing && + loadingComponent && + isFirstInit && + fetchNow + ) { return <>{loadingComponent}; } return <>{children}; @@ -303,6 +309,16 @@ export function FlagshipProvider({ INTERNAL_EVENTS.FsTriggerRendering, handleForcedVariations, ); + + globalThis.__abTastyOnTriggerRender__ = (arg: { + forcedReFetchFlags: boolean; + }) => { + const event = { + detail: arg, + } as CustomEvent<{ forcedReFetchFlags: boolean }>; + handleForcedVariations(event); + }; + return () => window?.removeEventListener?.( INTERNAL_EVENTS.FsTriggerRendering, diff --git a/src/sdkVersion.ts b/src/sdkVersion.ts index 18ec37e..65a919e 100644 --- a/src/sdkVersion.ts +++ b/src/sdkVersion.ts @@ -1,2 +1,2 @@ // Generated by genversion. -export const version = '5.2.2' +export const version = '5.2.3' diff --git a/src/type.local.ts b/src/type.local.ts new file mode 100644 index 0000000..1a1c6be --- /dev/null +++ b/src/type.local.ts @@ -0,0 +1,8 @@ + + + +declare global { + var __abTastyOnTriggerRender__: ((arg:{forcedReFetchFlags:boolean})=>void)|undefined +} + +export {}; \ No newline at end of file diff --git a/src/type.ts b/src/type.ts index 04ceef6..d9c2f0e 100644 --- a/src/type.ts +++ b/src/type.ts @@ -176,3 +176,4 @@ export type UseFlagshipOutput = { collectEAIEventsAsync(): Promise; }; + diff --git a/test/FlagshipProvider.integration.test.tsx b/test/FlagshipProvider.integration.test.tsx index af460e5..92d1dee 100644 --- a/test/FlagshipProvider.integration.test.tsx +++ b/test/FlagshipProvider.integration.test.tsx @@ -607,6 +607,111 @@ describe('FlagshipProvider Integration Tests', () => { }) }) + describe('globalThis.__abTastyOnTriggerRender__', () => { + it('should set globalThis.__abTastyOnTriggerRender__ on mount', async () => { + mockNewVisitor.mockReturnValue(createMockVisitor() as any) + + render( + +
Test
+
+ ) + + await waitFor(() => { + expect(globalThis.__abTastyOnTriggerRender__).toBeDefined() + expect(typeof globalThis.__abTastyOnTriggerRender__).toBe('function') + }) + }) + + it('should call fetchFlags when forcedReFetchFlags is true', async () => { + const fetchFlagsFn = jest.fn() + const mockVisitor = createMockVisitor({ fetchFlags: fetchFlagsFn }) + mockNewVisitor.mockReturnValue(mockVisitor as any) + + render( + +
Test
+
+ ) + + await waitFor(() => { + expect(mockNewVisitor).toHaveBeenCalled() + }) + + act(() => { + globalThis.__abTastyOnTriggerRender__!({ forcedReFetchFlags: true }) + }) + + expect(fetchFlagsFn).toHaveBeenCalled() + }) + + it('should toggle forced variations when forcedReFetchFlags is false', async () => { + const fetchFlagsFn = jest.fn() + const mockVisitor = createMockVisitor({ fetchFlags: fetchFlagsFn }) + mockNewVisitor.mockReturnValue(mockVisitor as any) + + render( + +
Test
+
+ ) + + await waitFor(() => { + expect(mockNewVisitor).toHaveBeenCalled() + }) + + act(() => { + globalThis.__abTastyOnTriggerRender__?.({ forcedReFetchFlags: false }) + }) + + expect(fetchFlagsFn).not.toHaveBeenCalled() + }) + + it('should clean up globalThis.__abTastyOnTriggerRender__ handler on unmount by removing event listener', async () => { + const removeEventListenerSpy = jest.spyOn(window, 'removeEventListener') + mockNewVisitor.mockReturnValue(createMockVisitor() as any) + + const { unmount } = render( + +
Test
+
+ ) + + await waitFor(() => { + expect(mockNewVisitor).toHaveBeenCalled() + }) + + unmount() + + expect(removeEventListenerSpy).toHaveBeenCalledWith( + 'FS_TRIGGER_RENDERING', + expect.any(Function) + ) + + removeEventListenerSpy.mockRestore() + }) + }) + describe('Context Deep Equality', () => { it('should not recreate visitor when context reference changes but content is same', async () => { const mockVisitor = createMockVisitor({ visitorId: 'visitor1' }) diff --git a/yarn.lock b/yarn.lock index 42d6c8e..c8de691 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1659,15 +1659,15 @@ __metadata: languageName: node linkType: hard -"@flagship.io/js-sdk@npm:^5.1.7": - version: 5.1.7 - resolution: "@flagship.io/js-sdk@npm:5.1.7" +"@flagship.io/js-sdk@npm:^5.2.0": + version: 5.2.0 + resolution: "@flagship.io/js-sdk@npm:5.2.0" dependencies: events: "npm:^3.3.0" follow-redirects: "npm:^1.15.9" node-abort-controller: "npm:^3.1.1" node-fetch: "npm:^2.6.7" - checksum: 10c0/b8dedcb22bb1300f4b8c4495bbdadeb3be341c399ff66e9e8c2f31cd1eb946817fd079403dca84cd7ca3bb0af8499f2808ffde14f5317058ae9f81f614879a16 + checksum: 10c0/cb11aebae792fb02dd892603f4b7cfe2f93ecf289578637095a2c68bab53a4c1e468f5bce8837af4b1696a6a2d0c12f2e3181417fe9f7cf7512f84fd8df0cd40 languageName: node linkType: hard @@ -1682,7 +1682,7 @@ __metadata: "@babel/preset-react": "npm:^7.24.1" "@babel/preset-typescript": "npm:^7.24.1" "@eslint/js": "npm:^9.23.0" - "@flagship.io/js-sdk": "npm:^5.1.7" + "@flagship.io/js-sdk": "npm:^5.2.0" "@testing-library/dom": "npm:^10.1.0" "@testing-library/jest-dom": "npm:^6.4.2" "@testing-library/react": "npm:^16.0.0"