diff --git a/apps/studio/hooks/misc/__tests__/useEnabledIdentityProviders.test.ts b/apps/studio/hooks/misc/__tests__/useEnabledIdentityProviders.test.ts index b82728b4227..38ef4892467 100644 --- a/apps/studio/hooks/misc/__tests__/useEnabledIdentityProviders.test.ts +++ b/apps/studio/hooks/misc/__tests__/useEnabledIdentityProviders.test.ts @@ -1,5 +1,5 @@ import { renderHook } from '@testing-library/react' -import { describe, expect, it, vi } from 'vitest' +import { beforeEach, describe, expect, it, vi } from 'vitest' import { useEnabledIdentityProviders } from '../useEnabledIdentityProviders' import { @@ -9,6 +9,7 @@ import { const mockIsFeatureEnabled = vi.hoisted(() => vi.fn()) const mockUseLocalStorageQuery = vi.hoisted(() => vi.fn()) +const mockUseFlag = vi.hoisted(() => vi.fn()) vi.mock('../useIsFeatureEnabled', () => ({ useIsFeatureEnabled: mockIsFeatureEnabled, @@ -18,13 +19,22 @@ vi.mock('../useLocalStorage', () => ({ useLocalStorageQuery: mockUseLocalStorageQuery, })) +vi.mock('common', async (importOriginal) => ({ + ...(await importOriginal()), + useFlag: mockUseFlag, +})) + describe('useEnabledIdentityProviders', () => { + beforeEach(() => { + mockUseFlag.mockReset() + }) + it('returns every provider when all flags are enabled', () => { mockIsFeatureEnabled.mockReturnValue({ dashboardAuthSignInWithGithub: true, - dashboardAuthSignInWithChatgpt: true, }) mockUseLocalStorageQuery.mockReturnValue([true]) + mockUseFlag.mockReturnValue(true) const { result } = renderHook(() => useEnabledIdentityProviders()) @@ -34,45 +44,69 @@ describe('useEnabledIdentityProviders', () => { it('returns no providers when all flags are disabled', () => { mockIsFeatureEnabled.mockReturnValue({ dashboardAuthSignInWithGithub: false, - dashboardAuthSignInWithChatgpt: false, }) mockUseLocalStorageQuery.mockReturnValue([false]) + mockUseFlag.mockReturnValue(false) const { result } = renderHook(() => useEnabledIdentityProviders()) expect(result.current).toEqual([]) }) - it('includes ChatGPT when its flag is enabled and the local storage switch is truthy', () => { - mockIsFeatureEnabled.mockReturnValue({ - dashboardAuthSignInWithGithub: false, - dashboardAuthSignInWithChatgpt: true, - }) + it('includes ChatGPT when localStorage is true and configcat is true', () => { + mockIsFeatureEnabled.mockReturnValue({ dashboardAuthSignInWithGithub: false }) mockUseLocalStorageQuery.mockReturnValue([true]) + mockUseFlag.mockReturnValue(true) const { result } = renderHook(() => useEnabledIdentityProviders()) expect(result.current).toEqual([CHATGPT_IDENTITY_PROVIDER]) }) - it('excludes ChatGPT when its flag is enabled but the local storage switch is unset', () => { - mockIsFeatureEnabled.mockReturnValue({ - dashboardAuthSignInWithGithub: false, - dashboardAuthSignInWithChatgpt: true, - }) + it('includes ChatGPT when localStorage is true and configcat is false', () => { + mockIsFeatureEnabled.mockReturnValue({ dashboardAuthSignInWithGithub: false }) + mockUseLocalStorageQuery.mockReturnValue([true]) + mockUseFlag.mockReturnValue(false) + + const { result } = renderHook(() => useEnabledIdentityProviders()) + + expect(result.current).toEqual([CHATGPT_IDENTITY_PROVIDER]) + }) + + it('includes ChatGPT when localStorage is false and configcat is true', () => { + mockIsFeatureEnabled.mockReturnValue({ dashboardAuthSignInWithGithub: false }) mockUseLocalStorageQuery.mockReturnValue([false]) + mockUseFlag.mockReturnValue(true) + + const { result } = renderHook(() => useEnabledIdentityProviders()) + + expect(result.current).toEqual([CHATGPT_IDENTITY_PROVIDER]) + }) + + it('excludes ChatGPT when localStorage is false and configcat is false', () => { + mockIsFeatureEnabled.mockReturnValue({ dashboardAuthSignInWithGithub: false }) + mockUseLocalStorageQuery.mockReturnValue([false]) + mockUseFlag.mockReturnValue(false) const { result } = renderHook(() => useEnabledIdentityProviders()) expect(result.current).toEqual([]) }) - it('excludes ChatGPT when the local storage switch is truthy but its flag is disabled', () => { - mockIsFeatureEnabled.mockReturnValue({ - dashboardAuthSignInWithGithub: false, - dashboardAuthSignInWithChatgpt: false, - }) - mockUseLocalStorageQuery.mockReturnValue([true]) + it('includes GitHub when its feature flag is enabled', () => { + mockIsFeatureEnabled.mockReturnValue({ dashboardAuthSignInWithGithub: true }) + mockUseLocalStorageQuery.mockReturnValue([false]) + mockUseFlag.mockReturnValue(false) + + const { result } = renderHook(() => useEnabledIdentityProviders()) + + expect(result.current).toEqual([GITHUB_IDENTITY_PROVIDER]) + }) + + it('excludes GitHub when its feature flag is disabled', () => { + mockIsFeatureEnabled.mockReturnValue({ dashboardAuthSignInWithGithub: false }) + mockUseLocalStorageQuery.mockReturnValue([false]) + mockUseFlag.mockReturnValue(false) const { result } = renderHook(() => useEnabledIdentityProviders()) diff --git a/apps/studio/hooks/misc/useEnabledIdentityProviders.ts b/apps/studio/hooks/misc/useEnabledIdentityProviders.ts index 83aa7c1b18d..939a7e0e9ff 100644 --- a/apps/studio/hooks/misc/useEnabledIdentityProviders.ts +++ b/apps/studio/hooks/misc/useEnabledIdentityProviders.ts @@ -1,4 +1,4 @@ -import { LOCAL_STORAGE_KEYS } from 'common' +import { LOCAL_STORAGE_KEYS, useFlag } from 'common' import { useMemo } from 'react' import { useIsFeatureEnabled } from './useIsFeatureEnabled' @@ -14,28 +14,28 @@ import { * To add a provider: declare its config in `lib/external-identity-providers.ts`, add a * `dashboard_auth:sign_in_with_*` flag, and gate it here. * - * ChatGPT is a deliberate exception: it's also gated behind a manual, localStorage-only rollout - * switch (`LOCAL_STORAGE_KEYS.SIGN_IN_CHATGPT_ENABLED`) on top of its feature flag, since it's WIP. + * ChatGPT is a deliberate exception: it's rolled out via the `ShowSignInWithChatGptButton` + * ConfigCat flag OR'd with a manual, localStorage-only opt-in switch + * (`LOCAL_STORAGE_KEYS.SIGN_IN_CHATGPT_ENABLED`, flippable via the `?siwc-enabled=1` query param — + * see `useSiwcQueryParamOptIn`), instead of the static `dashboard_auth:sign_in_with_*` pattern. */ export function useEnabledIdentityProviders(): ExternalIdentityProviderConfig[] { const { dashboardAuthSignInWithGithub: githubEnabled } = useIsFeatureEnabled([ 'dashboard_auth:sign_in_with_github', ]) - const { dashboardAuthSignInWithChatgpt: chatgptEnabled } = useIsFeatureEnabled([ - 'dashboard_auth:sign_in_with_chatgpt', - ]) const [chatgptLocalStorageEnabled] = useLocalStorageQuery( LOCAL_STORAGE_KEYS.SIGN_IN_CHATGPT_ENABLED, false ) + const chatGptConfigCatFlagEnabled = useFlag('ShowSignInWithChatGptButton') return useMemo( () => [ githubEnabled && GITHUB_IDENTITY_PROVIDER, - chatgptEnabled && chatgptLocalStorageEnabled && CHATGPT_IDENTITY_PROVIDER, + (chatgptLocalStorageEnabled || chatGptConfigCatFlagEnabled) && CHATGPT_IDENTITY_PROVIDER, ].filter((p): p is ExternalIdentityProviderConfig => Boolean(p)), - [githubEnabled, chatgptEnabled, chatgptLocalStorageEnabled] + [githubEnabled, chatgptLocalStorageEnabled, chatGptConfigCatFlagEnabled] ) } diff --git a/packages/common/enabled-features/enabled-features.json b/packages/common/enabled-features/enabled-features.json index bdf512b1e13..7e4fcb40075 100644 --- a/packages/common/enabled-features/enabled-features.json +++ b/packages/common/enabled-features/enabled-features.json @@ -34,7 +34,6 @@ "dashboard_auth:sign_up": true, "dashboard_auth:sign_in_with_github": true, - "dashboard_auth:sign_in_with_chatgpt": true, "dashboard_auth:sign_in_with_sso": true, "dashboard_auth:sign_in_with_email": true, "dashboard_auth:show_testimonial": true, diff --git a/packages/common/enabled-features/enabled-features.schema.json b/packages/common/enabled-features/enabled-features.schema.json index 4b4694ad13f..0a63c3e2b63 100644 --- a/packages/common/enabled-features/enabled-features.schema.json +++ b/packages/common/enabled-features/enabled-features.schema.json @@ -115,10 +115,6 @@ "type": "boolean", "description": "Enable the sign in with github provider" }, - "dashboard_auth:sign_in_with_chatgpt": { - "type": "boolean", - "description": "Enable the sign in with chatgpt provider" - }, "dashboard_auth:sign_in_with_sso": { "type": "boolean", "description": "Enable the sign in with sso provider" @@ -472,7 +468,6 @@ "billing:all", "dashboard_auth:sign_up", "dashboard_auth:sign_in_with_github", - "dashboard_auth:sign_in_with_chatgpt", "dashboard_auth:sign_in_with_sso", "dashboard_auth:sign_in_with_email", "dashboard_auth:show_tos",