diff --git a/.changeset/khaki-impalas-train.md b/.changeset/khaki-impalas-train.md new file mode 100644 index 000000000..9ae4e6487 --- /dev/null +++ b/.changeset/khaki-impalas-train.md @@ -0,0 +1,5 @@ +--- +'@scaleway/cookie-consent': minor +--- + +Add isSegmentIntegrationsLoading state to manage Segment integrations loading status diff --git a/packages/cookie-consent/src/CookieConsentProvider/CookieConsentProvider.tsx b/packages/cookie-consent/src/CookieConsentProvider/CookieConsentProvider.tsx index 36d6ea16b..a7f70b047 100644 --- a/packages/cookie-consent/src/CookieConsentProvider/CookieConsentProvider.tsx +++ b/packages/cookie-consent/src/CookieConsentProvider/CookieConsentProvider.tsx @@ -32,6 +32,7 @@ type Context = { integrations: Integrations needConsent: boolean isSegmentAllowed: boolean + isSegmentIntegrationsLoading: boolean segmentIntegrations: { All: boolean } & Record categoriesConsent: Partial saveConsent: (categoriesConsent: Partial) => void @@ -71,7 +72,10 @@ export const CookieConsentProvider = ({ const [needConsent, setNeedsConsent] = useState(false) const [cookies, setCookies] = useState>() - const segmentIntegrations = useSegmentIntegrations(config) + const { + integrations: segmentIntegrations, + isLoading: isSegmentIntegrationsLoading, + } = useSegmentIntegrations(config) useEffect(() => { setCookies(cookie.parse(document.cookie)) @@ -108,7 +112,7 @@ export const CookieConsentProvider = ({ useEffect(() => { // We set needConsent at false until we have an answer from segment // This is to avoid showing setting needConsent to true only to be set - // to false after receiving segment answer and flciker the UI + // to false after receiving segment answer and flicker the UI setNeedsConsent( isConsentRequired && cookies?.[HASH_COOKIE] !== integrationsHash.toString() && @@ -220,17 +224,19 @@ export const CookieConsentProvider = ({ integrations, needConsent, isSegmentAllowed, + isSegmentIntegrationsLoading, segmentIntegrations: segmentEnabledIntegrations, categoriesConsent: cookieConsent, saveConsent, }), [ integrations, - cookieConsent, - saveConsent, needConsent, isSegmentAllowed, + isSegmentIntegrationsLoading, segmentEnabledIntegrations, + cookieConsent, + saveConsent, ], ) diff --git a/packages/cookie-consent/src/CookieConsentProvider/__tests__/index.tsx b/packages/cookie-consent/src/CookieConsentProvider/__tests__/index.tsx index cb639d3ac..f8413293d 100644 --- a/packages/cookie-consent/src/CookieConsentProvider/__tests__/index.tsx +++ b/packages/cookie-consent/src/CookieConsentProvider/__tests__/index.tsx @@ -24,22 +24,27 @@ const wrapper = ) +const integrations = [ + { + category: 'analytics', + name: 'Google Universal Analytics', + }, + { + category: 'marketing', + name: 'Salesforce custom destination (Scaleway)', + }, + { + category: 'marketing', + name: 'Salesforce', + }, +] +const mockUseSegmentIntegrations = jest.fn().mockReturnValue({ + integrations, + isLoading: false, +}) jest.mock('../useSegmentIntegrations', () => ({ __esModule: true, - useSegmentIntegrations: () => [ - { - category: 'analytics', - name: 'Google Universal Analytics', - }, - { - category: 'marketing', - name: 'Salesforce custom destination (Scaleway)', - }, - { - category: 'marketing', - name: 'Salesforce', - }, - ], + useSegmentIntegrations: () => mockUseSegmentIntegrations(), })) describe('CookieConsent - CookieConsentProvider', () => { @@ -84,6 +89,34 @@ describe('CookieConsent - CookieConsentProvider', () => { Salesforce: true, 'Salesforce custom destination (Scaleway)': true, }) + expect(result.current.isSegmentIntegrationsLoading).toBe(false) + }) + + it('should know when integrations are loading', () => { + // simulate that Segment is loading + mockUseSegmentIntegrations.mockReturnValue({ + integrations: undefined, + isLoading: true, + }) + const { result } = renderHook(() => useCookieConsent(), { + wrapper: wrapper({ + isConsentRequired: true, + essentialIntegrations: ['Deskpro', 'Stripe', 'Sentry'], + config: { + segment: { + cdnURL: 'url', + writeKey: 'key', + }, + }, + }), + }) + expect(result.current.isSegmentIntegrationsLoading).toBe(true) + + // put mock back as if segment integrations are loaded + mockUseSegmentIntegrations.mockReturnValue({ + integrations, + isLoading: false, + }) }) it('should know to ask for content when no cookie is set and consent is required', () => { diff --git a/packages/cookie-consent/src/CookieConsentProvider/__tests__/useSegmentIntegrations/emptyConfig.tsx b/packages/cookie-consent/src/CookieConsentProvider/__tests__/useSegmentIntegrations/emptyConfig.tsx index af0764733..59822a5a8 100644 --- a/packages/cookie-consent/src/CookieConsentProvider/__tests__/useSegmentIntegrations/emptyConfig.tsx +++ b/packages/cookie-consent/src/CookieConsentProvider/__tests__/useSegmentIntegrations/emptyConfig.tsx @@ -9,7 +9,8 @@ describe('CookieConsent - useSegmentIntegrations', () => { ) await waitFor(() => { - expect(result.current).toStrictEqual([]) + expect(result.current.integrations).toStrictEqual([]) }) + expect(result.current.isLoading).toBe(false) }) }) diff --git a/packages/cookie-consent/src/CookieConsentProvider/__tests__/useSegmentIntegrations/fetchError.tsx b/packages/cookie-consent/src/CookieConsentProvider/__tests__/useSegmentIntegrations/fetchError.tsx index 73dc01a14..79c6847f7 100644 --- a/packages/cookie-consent/src/CookieConsentProvider/__tests__/useSegmentIntegrations/fetchError.tsx +++ b/packages/cookie-consent/src/CookieConsentProvider/__tests__/useSegmentIntegrations/fetchError.tsx @@ -16,11 +16,13 @@ describe('CookieConsent - useSegmentIntegrations', () => { ) await waitFor(() => { - expect(result.current).toStrictEqual([]) + expect(result.current.integrations).toStrictEqual([]) }) await waitFor(() => { expect(globalThis.fetch).toHaveBeenCalled() }) + + expect(result.current.isLoading).toBe(false) }) }) diff --git a/packages/cookie-consent/src/CookieConsentProvider/__tests__/useSegmentIntegrations/networkError.tsx b/packages/cookie-consent/src/CookieConsentProvider/__tests__/useSegmentIntegrations/networkError.tsx index 8d70c78da..696bbd3da 100644 --- a/packages/cookie-consent/src/CookieConsentProvider/__tests__/useSegmentIntegrations/networkError.tsx +++ b/packages/cookie-consent/src/CookieConsentProvider/__tests__/useSegmentIntegrations/networkError.tsx @@ -16,11 +16,12 @@ describe('CookieConsent - useSegmentIntegrations', () => { ) await waitFor(() => { - expect(result.current).toStrictEqual([]) + expect(result.current.integrations).toStrictEqual([]) }) await waitFor(() => { expect(globalThis.fetch).toHaveBeenCalled() }) + expect(result.current.isLoading).toBe(false) }) }) diff --git a/packages/cookie-consent/src/CookieConsentProvider/__tests__/useSegmentIntegrations/working.tsx b/packages/cookie-consent/src/CookieConsentProvider/__tests__/useSegmentIntegrations/working.tsx index 74e54d080..f4bb00a6e 100644 --- a/packages/cookie-consent/src/CookieConsentProvider/__tests__/useSegmentIntegrations/working.tsx +++ b/packages/cookie-consent/src/CookieConsentProvider/__tests__/useSegmentIntegrations/working.tsx @@ -64,8 +64,10 @@ describe('CookieConsent - useSegmentIntegrations', () => { }), ) + expect(result.current.isLoading).toBe(true) + await waitFor(() => { - expect(result.current).toStrictEqual([ + expect(result.current.integrations).toStrictEqual([ { category: 'functional', name: 'Segment.io', @@ -100,5 +102,6 @@ describe('CookieConsent - useSegmentIntegrations', () => { await waitFor(() => { expect(globalThis.fetch).toHaveBeenCalled() }) + expect(result.current.isLoading).toBe(false) }) }) diff --git a/packages/cookie-consent/src/CookieConsentProvider/useSegmentIntegrations.ts b/packages/cookie-consent/src/CookieConsentProvider/useSegmentIntegrations.ts index 64ceafc33..d31d54560 100644 --- a/packages/cookie-consent/src/CookieConsentProvider/useSegmentIntegrations.ts +++ b/packages/cookie-consent/src/CookieConsentProvider/useSegmentIntegrations.ts @@ -80,5 +80,8 @@ export const useSegmentIntegrations = (config: Config) => { }) }, [setIntegrations, config.segment]) - return integrations + return { + integrations, + isLoading: integrations === undefined, + } }