import { describe, it, expect, vi, beforeEach } from 'vitest'; import { renderHook, waitFor, act } from '@testing-library/react'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import React from 'react'; // Mock the platformOAuth API vi.mock('../../api/platformOAuth', () => ({ getPlatformOAuthSettings: vi.fn(), updatePlatformOAuthSettings: vi.fn(), })); import { usePlatformOAuthSettings, useUpdatePlatformOAuthSettings, } from '../usePlatformOAuth'; import * as platformOAuthApi from '../../api/platformOAuth'; // Create wrapper for React Query const createWrapper = () => { const queryClient = new QueryClient({ defaultOptions: { queries: { retry: false }, mutations: { retry: false }, }, }); return function Wrapper({ children }: { children: React.ReactNode }) { return React.createElement(QueryClientProvider, { client: queryClient }, children); }; }; describe('usePlatformOAuth hooks', () => { beforeEach(() => { vi.clearAllMocks(); }); // ============================================================================ // usePlatformOAuthSettings Query Hook // ============================================================================ describe('usePlatformOAuthSettings', () => { it('fetches platform OAuth settings successfully', async () => { const mockResponse = { oauth_allow_registration: true, google: { enabled: true, client_id: 'google-client-id', client_secret: 'google-secret', }, apple: { enabled: false, client_id: '', client_secret: '', team_id: '', key_id: '', }, facebook: { enabled: true, client_id: 'facebook-client-id', client_secret: 'facebook-secret', }, linkedin: { enabled: false, client_id: '', client_secret: '', }, microsoft: { enabled: true, client_id: 'microsoft-client-id', client_secret: 'microsoft-secret', tenant_id: 'microsoft-tenant-id', }, twitter: { enabled: false, client_id: '', client_secret: '', }, twitch: { enabled: false, client_id: '', client_secret: '', }, }; vi.mocked(platformOAuthApi.getPlatformOAuthSettings).mockResolvedValue(mockResponse); const { result } = renderHook(() => usePlatformOAuthSettings(), { wrapper: createWrapper(), }); // Initially loading expect(result.current.isLoading).toBe(true); // Wait for success await waitFor(() => { expect(result.current.isSuccess).toBe(true); }); expect(platformOAuthApi.getPlatformOAuthSettings).toHaveBeenCalledTimes(1); expect(result.current.data).toEqual(mockResponse); expect(result.current.data?.oauth_allow_registration).toBe(true); expect(result.current.data?.google.enabled).toBe(true); expect(result.current.data?.facebook.enabled).toBe(true); expect(result.current.data?.microsoft.enabled).toBe(true); }); it('handles all providers disabled', async () => { const mockResponse = { oauth_allow_registration: false, google: { enabled: false, client_id: '', client_secret: '', }, apple: { enabled: false, client_id: '', client_secret: '', team_id: '', key_id: '', }, facebook: { enabled: false, client_id: '', client_secret: '', }, linkedin: { enabled: false, client_id: '', client_secret: '', }, microsoft: { enabled: false, client_id: '', client_secret: '', tenant_id: '', }, twitter: { enabled: false, client_id: '', client_secret: '', }, twitch: { enabled: false, client_id: '', client_secret: '', }, }; vi.mocked(platformOAuthApi.getPlatformOAuthSettings).mockResolvedValue(mockResponse); const { result } = renderHook(() => usePlatformOAuthSettings(), { wrapper: createWrapper(), }); await waitFor(() => { expect(result.current.isSuccess).toBe(true); }); expect(result.current.data?.oauth_allow_registration).toBe(false); expect(result.current.data?.google.enabled).toBe(false); expect(result.current.data?.apple.enabled).toBe(false); expect(result.current.data?.facebook.enabled).toBe(false); expect(result.current.data?.linkedin.enabled).toBe(false); expect(result.current.data?.microsoft.enabled).toBe(false); expect(result.current.data?.twitter.enabled).toBe(false); expect(result.current.data?.twitch.enabled).toBe(false); }); it('handles all providers enabled with credentials', async () => { const mockResponse = { oauth_allow_registration: true, google: { enabled: true, client_id: 'google-id', client_secret: 'google-secret', }, apple: { enabled: true, client_id: 'apple-id', client_secret: 'apple-secret', team_id: 'apple-team', key_id: 'apple-key', }, facebook: { enabled: true, client_id: 'fb-id', client_secret: 'fb-secret', }, linkedin: { enabled: true, client_id: 'linkedin-id', client_secret: 'linkedin-secret', }, microsoft: { enabled: true, client_id: 'ms-id', client_secret: 'ms-secret', tenant_id: 'ms-tenant', }, twitter: { enabled: true, client_id: 'twitter-id', client_secret: 'twitter-secret', }, twitch: { enabled: true, client_id: 'twitch-id', client_secret: 'twitch-secret', }, }; vi.mocked(platformOAuthApi.getPlatformOAuthSettings).mockResolvedValue(mockResponse); const { result } = renderHook(() => usePlatformOAuthSettings(), { wrapper: createWrapper(), }); await waitFor(() => { expect(result.current.isSuccess).toBe(true); }); expect(result.current.data?.google.enabled).toBe(true); expect(result.current.data?.apple.enabled).toBe(true); expect(result.current.data?.apple.team_id).toBe('apple-team'); expect(result.current.data?.apple.key_id).toBe('apple-key'); expect(result.current.data?.facebook.enabled).toBe(true); expect(result.current.data?.linkedin.enabled).toBe(true); expect(result.current.data?.microsoft.enabled).toBe(true); expect(result.current.data?.microsoft.tenant_id).toBe('ms-tenant'); expect(result.current.data?.twitter.enabled).toBe(true); expect(result.current.data?.twitch.enabled).toBe(true); }); it('handles API error gracefully', async () => { const mockError = new Error('Failed to fetch OAuth settings'); vi.mocked(platformOAuthApi.getPlatformOAuthSettings).mockRejectedValue(mockError); const { result } = renderHook(() => usePlatformOAuthSettings(), { wrapper: createWrapper(), }); await waitFor(() => { expect(result.current.isError).toBe(true); }); expect(result.current.error).toEqual(mockError); expect(result.current.data).toBeUndefined(); }); it('does not retry on failure', async () => { vi.mocked(platformOAuthApi.getPlatformOAuthSettings).mockRejectedValue( new Error('401 Unauthorized') ); const { result } = renderHook(() => usePlatformOAuthSettings(), { wrapper: createWrapper(), }); await waitFor(() => { expect(result.current.isError).toBe(true); }); // Should be called only once (no retries) expect(platformOAuthApi.getPlatformOAuthSettings).toHaveBeenCalledTimes(1); }); it('caches data with 5 minute stale time', async () => { const mockResponse = { oauth_allow_registration: true, google: { enabled: true, client_id: 'google-id', client_secret: 'google-secret', }, apple: { enabled: false, client_id: '', client_secret: '', team_id: '', key_id: '', }, facebook: { enabled: false, client_id: '', client_secret: '', }, linkedin: { enabled: false, client_id: '', client_secret: '', }, microsoft: { enabled: false, client_id: '', client_secret: '', tenant_id: '', }, twitter: { enabled: false, client_id: '', client_secret: '', }, twitch: { enabled: false, client_id: '', client_secret: '', }, }; vi.mocked(platformOAuthApi.getPlatformOAuthSettings).mockResolvedValue(mockResponse); const { result, rerender } = renderHook(() => usePlatformOAuthSettings(), { wrapper: createWrapper(), }); await waitFor(() => { expect(result.current.isSuccess).toBe(true); }); // Rerender should use cached data (within stale time) rerender(); // Should still only be called once expect(platformOAuthApi.getPlatformOAuthSettings).toHaveBeenCalledTimes(1); }); it('handles partial provider configuration', async () => { const mockResponse = { oauth_allow_registration: true, google: { enabled: true, client_id: 'google-id', client_secret: '', }, apple: { enabled: true, client_id: 'apple-id', client_secret: 'apple-secret', team_id: '', key_id: 'apple-key', }, facebook: { enabled: false, client_id: 'fb-id', client_secret: '', }, linkedin: { enabled: false, client_id: '', client_secret: '', }, microsoft: { enabled: false, client_id: '', client_secret: '', tenant_id: '', }, twitter: { enabled: false, client_id: '', client_secret: '', }, twitch: { enabled: false, client_id: '', client_secret: '', }, }; vi.mocked(platformOAuthApi.getPlatformOAuthSettings).mockResolvedValue(mockResponse); const { result } = renderHook(() => usePlatformOAuthSettings(), { wrapper: createWrapper(), }); await waitFor(() => { expect(result.current.isSuccess).toBe(true); }); expect(result.current.data?.google.client_id).toBe('google-id'); expect(result.current.data?.google.client_secret).toBe(''); expect(result.current.data?.apple.team_id).toBe(''); expect(result.current.data?.apple.key_id).toBe('apple-key'); }); }); // ============================================================================ // useUpdatePlatformOAuthSettings Mutation Hook // ============================================================================ describe('useUpdatePlatformOAuthSettings', () => { it('updates global oauth_allow_registration flag', async () => { const mockResponse = { oauth_allow_registration: false, google: { enabled: true, client_id: 'google-id', client_secret: 'google-secret', }, apple: { enabled: false, client_id: '', client_secret: '', team_id: '', key_id: '', }, facebook: { enabled: false, client_id: '', client_secret: '', }, linkedin: { enabled: false, client_id: '', client_secret: '', }, microsoft: { enabled: false, client_id: '', client_secret: '', tenant_id: '', }, twitter: { enabled: false, client_id: '', client_secret: '', }, twitch: { enabled: false, client_id: '', client_secret: '', }, }; vi.mocked(platformOAuthApi.updatePlatformOAuthSettings).mockResolvedValue(mockResponse); const { result } = renderHook(() => useUpdatePlatformOAuthSettings(), { wrapper: createWrapper(), }); await act(async () => { await result.current.mutateAsync({ oauth_allow_registration: false, }); }); expect(platformOAuthApi.updatePlatformOAuthSettings).toHaveBeenCalledWith( { oauth_allow_registration: false, }, expect.anything() ); await waitFor(() => { expect(result.current.isSuccess).toBe(true); }); }); it('updates Google OAuth settings', async () => { const mockResponse = { oauth_allow_registration: true, google: { enabled: true, client_id: 'new-google-id', client_secret: 'new-google-secret', }, apple: { enabled: false, client_id: '', client_secret: '', team_id: '', key_id: '', }, facebook: { enabled: false, client_id: '', client_secret: '', }, linkedin: { enabled: false, client_id: '', client_secret: '', }, microsoft: { enabled: false, client_id: '', client_secret: '', tenant_id: '', }, twitter: { enabled: false, client_id: '', client_secret: '', }, twitch: { enabled: false, client_id: '', client_secret: '', }, }; vi.mocked(platformOAuthApi.updatePlatformOAuthSettings).mockResolvedValue(mockResponse); const { result } = renderHook(() => useUpdatePlatformOAuthSettings(), { wrapper: createWrapper(), }); await act(async () => { await result.current.mutateAsync({ oauth_google_enabled: true, oauth_google_client_id: 'new-google-id', oauth_google_client_secret: 'new-google-secret', }); }); expect(platformOAuthApi.updatePlatformOAuthSettings).toHaveBeenCalledWith( { oauth_google_enabled: true, oauth_google_client_id: 'new-google-id', oauth_google_client_secret: 'new-google-secret', }, expect.anything() ); }); it('updates Apple OAuth settings with all fields', async () => { const mockResponse = { oauth_allow_registration: true, google: { enabled: false, client_id: '', client_secret: '', }, apple: { enabled: true, client_id: 'apple-id', client_secret: 'apple-secret', team_id: 'apple-team', key_id: 'apple-key', }, facebook: { enabled: false, client_id: '', client_secret: '', }, linkedin: { enabled: false, client_id: '', client_secret: '', }, microsoft: { enabled: false, client_id: '', client_secret: '', tenant_id: '', }, twitter: { enabled: false, client_id: '', client_secret: '', }, twitch: { enabled: false, client_id: '', client_secret: '', }, }; vi.mocked(platformOAuthApi.updatePlatformOAuthSettings).mockResolvedValue(mockResponse); const { result } = renderHook(() => useUpdatePlatformOAuthSettings(), { wrapper: createWrapper(), }); await act(async () => { await result.current.mutateAsync({ oauth_apple_enabled: true, oauth_apple_client_id: 'apple-id', oauth_apple_client_secret: 'apple-secret', oauth_apple_team_id: 'apple-team', oauth_apple_key_id: 'apple-key', }); }); expect(platformOAuthApi.updatePlatformOAuthSettings).toHaveBeenCalledWith( { oauth_apple_enabled: true, oauth_apple_client_id: 'apple-id', oauth_apple_client_secret: 'apple-secret', oauth_apple_team_id: 'apple-team', oauth_apple_key_id: 'apple-key', }, expect.anything() ); }); it('updates Microsoft OAuth settings with tenant_id', async () => { const mockResponse = { oauth_allow_registration: true, google: { enabled: false, client_id: '', client_secret: '', }, apple: { enabled: false, client_id: '', client_secret: '', team_id: '', key_id: '', }, facebook: { enabled: false, client_id: '', client_secret: '', }, linkedin: { enabled: false, client_id: '', client_secret: '', }, microsoft: { enabled: true, client_id: 'ms-id', client_secret: 'ms-secret', tenant_id: 'ms-tenant-123', }, twitter: { enabled: false, client_id: '', client_secret: '', }, twitch: { enabled: false, client_id: '', client_secret: '', }, }; vi.mocked(platformOAuthApi.updatePlatformOAuthSettings).mockResolvedValue(mockResponse); const { result } = renderHook(() => useUpdatePlatformOAuthSettings(), { wrapper: createWrapper(), }); await act(async () => { await result.current.mutateAsync({ oauth_microsoft_enabled: true, oauth_microsoft_client_id: 'ms-id', oauth_microsoft_client_secret: 'ms-secret', oauth_microsoft_tenant_id: 'ms-tenant-123', }); }); expect(platformOAuthApi.updatePlatformOAuthSettings).toHaveBeenCalledWith( { oauth_microsoft_enabled: true, oauth_microsoft_client_id: 'ms-id', oauth_microsoft_client_secret: 'ms-secret', oauth_microsoft_tenant_id: 'ms-tenant-123', }, expect.anything() ); }); it('updates Facebook OAuth settings', async () => { const mockResponse = { oauth_allow_registration: true, google: { enabled: false, client_id: '', client_secret: '', }, apple: { enabled: false, client_id: '', client_secret: '', team_id: '', key_id: '', }, facebook: { enabled: true, client_id: 'fb-id', client_secret: 'fb-secret', }, linkedin: { enabled: false, client_id: '', client_secret: '', }, microsoft: { enabled: false, client_id: '', client_secret: '', tenant_id: '', }, twitter: { enabled: false, client_id: '', client_secret: '', }, twitch: { enabled: false, client_id: '', client_secret: '', }, }; vi.mocked(platformOAuthApi.updatePlatformOAuthSettings).mockResolvedValue(mockResponse); const { result } = renderHook(() => useUpdatePlatformOAuthSettings(), { wrapper: createWrapper(), }); await act(async () => { await result.current.mutateAsync({ oauth_facebook_enabled: true, oauth_facebook_client_id: 'fb-id', oauth_facebook_client_secret: 'fb-secret', }); }); expect(platformOAuthApi.updatePlatformOAuthSettings).toHaveBeenCalledWith( { oauth_facebook_enabled: true, oauth_facebook_client_id: 'fb-id', oauth_facebook_client_secret: 'fb-secret', }, expect.anything() ); }); it('updates LinkedIn OAuth settings', async () => { const mockResponse = { oauth_allow_registration: true, google: { enabled: false, client_id: '', client_secret: '', }, apple: { enabled: false, client_id: '', client_secret: '', team_id: '', key_id: '', }, facebook: { enabled: false, client_id: '', client_secret: '', }, linkedin: { enabled: true, client_id: 'linkedin-id', client_secret: 'linkedin-secret', }, microsoft: { enabled: false, client_id: '', client_secret: '', tenant_id: '', }, twitter: { enabled: false, client_id: '', client_secret: '', }, twitch: { enabled: false, client_id: '', client_secret: '', }, }; vi.mocked(platformOAuthApi.updatePlatformOAuthSettings).mockResolvedValue(mockResponse); const { result } = renderHook(() => useUpdatePlatformOAuthSettings(), { wrapper: createWrapper(), }); await act(async () => { await result.current.mutateAsync({ oauth_linkedin_enabled: true, oauth_linkedin_client_id: 'linkedin-id', oauth_linkedin_client_secret: 'linkedin-secret', }); }); expect(platformOAuthApi.updatePlatformOAuthSettings).toHaveBeenCalledWith( { oauth_linkedin_enabled: true, oauth_linkedin_client_id: 'linkedin-id', oauth_linkedin_client_secret: 'linkedin-secret', }, expect.anything() ); }); it('updates Twitter OAuth settings', async () => { const mockResponse = { oauth_allow_registration: true, google: { enabled: false, client_id: '', client_secret: '', }, apple: { enabled: false, client_id: '', client_secret: '', team_id: '', key_id: '', }, facebook: { enabled: false, client_id: '', client_secret: '', }, linkedin: { enabled: false, client_id: '', client_secret: '', }, microsoft: { enabled: false, client_id: '', client_secret: '', tenant_id: '', }, twitter: { enabled: true, client_id: 'twitter-id', client_secret: 'twitter-secret', }, twitch: { enabled: false, client_id: '', client_secret: '', }, }; vi.mocked(platformOAuthApi.updatePlatformOAuthSettings).mockResolvedValue(mockResponse); const { result } = renderHook(() => useUpdatePlatformOAuthSettings(), { wrapper: createWrapper(), }); await act(async () => { await result.current.mutateAsync({ oauth_twitter_enabled: true, oauth_twitter_client_id: 'twitter-id', oauth_twitter_client_secret: 'twitter-secret', }); }); expect(platformOAuthApi.updatePlatformOAuthSettings).toHaveBeenCalledWith( { oauth_twitter_enabled: true, oauth_twitter_client_id: 'twitter-id', oauth_twitter_client_secret: 'twitter-secret', }, expect.anything() ); }); it('updates Twitch OAuth settings', async () => { const mockResponse = { oauth_allow_registration: true, google: { enabled: false, client_id: '', client_secret: '', }, apple: { enabled: false, client_id: '', client_secret: '', team_id: '', key_id: '', }, facebook: { enabled: false, client_id: '', client_secret: '', }, linkedin: { enabled: false, client_id: '', client_secret: '', }, microsoft: { enabled: false, client_id: '', client_secret: '', tenant_id: '', }, twitter: { enabled: false, client_id: '', client_secret: '', }, twitch: { enabled: true, client_id: 'twitch-id', client_secret: 'twitch-secret', }, }; vi.mocked(platformOAuthApi.updatePlatformOAuthSettings).mockResolvedValue(mockResponse); const { result } = renderHook(() => useUpdatePlatformOAuthSettings(), { wrapper: createWrapper(), }); await act(async () => { await result.current.mutateAsync({ oauth_twitch_enabled: true, oauth_twitch_client_id: 'twitch-id', oauth_twitch_client_secret: 'twitch-secret', }); }); expect(platformOAuthApi.updatePlatformOAuthSettings).toHaveBeenCalledWith( { oauth_twitch_enabled: true, oauth_twitch_client_id: 'twitch-id', oauth_twitch_client_secret: 'twitch-secret', }, expect.anything() ); }); it('updates multiple provider settings at once', async () => { const mockResponse = { oauth_allow_registration: false, google: { enabled: true, client_id: 'google-id', client_secret: 'google-secret', }, apple: { enabled: false, client_id: '', client_secret: '', team_id: '', key_id: '', }, facebook: { enabled: true, client_id: 'fb-id', client_secret: 'fb-secret', }, linkedin: { enabled: false, client_id: '', client_secret: '', }, microsoft: { enabled: true, client_id: 'ms-id', client_secret: 'ms-secret', tenant_id: 'ms-tenant', }, twitter: { enabled: false, client_id: '', client_secret: '', }, twitch: { enabled: false, client_id: '', client_secret: '', }, }; vi.mocked(platformOAuthApi.updatePlatformOAuthSettings).mockResolvedValue(mockResponse); const { result } = renderHook(() => useUpdatePlatformOAuthSettings(), { wrapper: createWrapper(), }); await act(async () => { await result.current.mutateAsync({ oauth_allow_registration: false, oauth_google_enabled: true, oauth_google_client_id: 'google-id', oauth_google_client_secret: 'google-secret', oauth_facebook_enabled: true, oauth_facebook_client_id: 'fb-id', oauth_facebook_client_secret: 'fb-secret', oauth_microsoft_enabled: true, oauth_microsoft_client_id: 'ms-id', oauth_microsoft_client_secret: 'ms-secret', oauth_microsoft_tenant_id: 'ms-tenant', }); }); expect(platformOAuthApi.updatePlatformOAuthSettings).toHaveBeenCalledWith( { oauth_allow_registration: false, oauth_google_enabled: true, oauth_google_client_id: 'google-id', oauth_google_client_secret: 'google-secret', oauth_facebook_enabled: true, oauth_facebook_client_id: 'fb-id', oauth_facebook_client_secret: 'fb-secret', oauth_microsoft_enabled: true, oauth_microsoft_client_id: 'ms-id', oauth_microsoft_client_secret: 'ms-secret', oauth_microsoft_tenant_id: 'ms-tenant', }, expect.anything() ); await waitFor(() => { expect(result.current.isSuccess).toBe(true); }); }); it('disables a provider by setting enabled to false', async () => { const mockResponse = { oauth_allow_registration: true, google: { enabled: false, client_id: 'google-id', client_secret: 'google-secret', }, apple: { enabled: false, client_id: '', client_secret: '', team_id: '', key_id: '', }, facebook: { enabled: false, client_id: '', client_secret: '', }, linkedin: { enabled: false, client_id: '', client_secret: '', }, microsoft: { enabled: false, client_id: '', client_secret: '', tenant_id: '', }, twitter: { enabled: false, client_id: '', client_secret: '', }, twitch: { enabled: false, client_id: '', client_secret: '', }, }; vi.mocked(platformOAuthApi.updatePlatformOAuthSettings).mockResolvedValue(mockResponse); const { result } = renderHook(() => useUpdatePlatformOAuthSettings(), { wrapper: createWrapper(), }); await act(async () => { await result.current.mutateAsync({ oauth_google_enabled: false, }); }); expect(platformOAuthApi.updatePlatformOAuthSettings).toHaveBeenCalledWith( { oauth_google_enabled: false, }, expect.anything() ); }); it('updates query cache on success', async () => { const mockResponse = { oauth_allow_registration: true, google: { enabled: true, client_id: 'updated-google-id', client_secret: 'updated-google-secret', }, apple: { enabled: false, client_id: '', client_secret: '', team_id: '', key_id: '', }, facebook: { enabled: false, client_id: '', client_secret: '', }, linkedin: { enabled: false, client_id: '', client_secret: '', }, microsoft: { enabled: false, client_id: '', client_secret: '', tenant_id: '', }, twitter: { enabled: false, client_id: '', client_secret: '', }, twitch: { enabled: false, client_id: '', client_secret: '', }, }; vi.mocked(platformOAuthApi.updatePlatformOAuthSettings).mockResolvedValue(mockResponse); const queryClient = new QueryClient({ defaultOptions: { queries: { retry: false }, mutations: { retry: false }, }, }); const wrapper = ({ children }: { children: React.ReactNode }) => React.createElement(QueryClientProvider, { client: queryClient }, children); const { result } = renderHook(() => useUpdatePlatformOAuthSettings(), { wrapper, }); await act(async () => { await result.current.mutateAsync({ oauth_google_enabled: true, oauth_google_client_id: 'updated-google-id', oauth_google_client_secret: 'updated-google-secret', }); }); // Verify cache was updated const cachedData = queryClient.getQueryData(['platformOAuthSettings']); expect(cachedData).toEqual(mockResponse); }); it('handles update error gracefully', async () => { const mockError = new Error('Failed to update settings'); vi.mocked(platformOAuthApi.updatePlatformOAuthSettings).mockRejectedValue(mockError); const { result } = renderHook(() => useUpdatePlatformOAuthSettings(), { wrapper: createWrapper(), }); let caughtError: any = null; await act(async () => { try { await result.current.mutateAsync({ oauth_google_enabled: true, }); } catch (error) { caughtError = error; } }); expect(caughtError).toEqual(mockError); await waitFor(() => { expect(result.current.isError).toBe(true); }); expect(result.current.error).toEqual(mockError); }); it('handles validation error from backend', async () => { const mockError = new Error('Invalid client_id format'); vi.mocked(platformOAuthApi.updatePlatformOAuthSettings).mockRejectedValue(mockError); const { result } = renderHook(() => useUpdatePlatformOAuthSettings(), { wrapper: createWrapper(), }); let caughtError: any = null; await act(async () => { try { await result.current.mutateAsync({ oauth_google_client_id: 'invalid-format', }); } catch (error) { caughtError = error; } }); expect(caughtError).toEqual(mockError); }); it('handles partial update with only one field', async () => { const mockResponse = { oauth_allow_registration: false, google: { enabled: true, client_id: 'google-id', client_secret: 'google-secret', }, apple: { enabled: false, client_id: '', client_secret: '', team_id: '', key_id: '', }, facebook: { enabled: false, client_id: '', client_secret: '', }, linkedin: { enabled: false, client_id: '', client_secret: '', }, microsoft: { enabled: false, client_id: '', client_secret: '', tenant_id: '', }, twitter: { enabled: false, client_id: '', client_secret: '', }, twitch: { enabled: false, client_id: '', client_secret: '', }, }; vi.mocked(platformOAuthApi.updatePlatformOAuthSettings).mockResolvedValue(mockResponse); const { result } = renderHook(() => useUpdatePlatformOAuthSettings(), { wrapper: createWrapper(), }); await act(async () => { await result.current.mutateAsync({ oauth_allow_registration: false, }); }); expect(platformOAuthApi.updatePlatformOAuthSettings).toHaveBeenCalledWith( { oauth_allow_registration: false, }, expect.anything() ); await waitFor(() => { expect(result.current.isSuccess).toBe(true); }); expect(result.current.data?.oauth_allow_registration).toBe(false); }); }); // ============================================================================ // Integration Tests // ============================================================================ describe('integration tests', () => { it('fetches settings then updates them', async () => { const initialResponse = { oauth_allow_registration: true, google: { enabled: false, client_id: '', client_secret: '', }, apple: { enabled: false, client_id: '', client_secret: '', team_id: '', key_id: '', }, facebook: { enabled: false, client_id: '', client_secret: '', }, linkedin: { enabled: false, client_id: '', client_secret: '', }, microsoft: { enabled: false, client_id: '', client_secret: '', tenant_id: '', }, twitter: { enabled: false, client_id: '', client_secret: '', }, twitch: { enabled: false, client_id: '', client_secret: '', }, }; const updatedResponse = { oauth_allow_registration: true, google: { enabled: true, client_id: 'new-google-id', client_secret: 'new-google-secret', }, apple: { enabled: false, client_id: '', client_secret: '', team_id: '', key_id: '', }, facebook: { enabled: true, client_id: 'new-fb-id', client_secret: 'new-fb-secret', }, linkedin: { enabled: false, client_id: '', client_secret: '', }, microsoft: { enabled: false, client_id: '', client_secret: '', tenant_id: '', }, twitter: { enabled: false, client_id: '', client_secret: '', }, twitch: { enabled: false, client_id: '', client_secret: '', }, }; vi.mocked(platformOAuthApi.getPlatformOAuthSettings).mockResolvedValue(initialResponse); vi.mocked(platformOAuthApi.updatePlatformOAuthSettings).mockResolvedValue(updatedResponse); const queryClient = new QueryClient({ defaultOptions: { queries: { retry: false }, mutations: { retry: false }, }, }); const wrapper = ({ children }: { children: React.ReactNode }) => React.createElement(QueryClientProvider, { client: queryClient }, children); // Fetch initial settings const { result: fetchResult } = renderHook(() => usePlatformOAuthSettings(), { wrapper, }); await waitFor(() => { expect(fetchResult.current.isSuccess).toBe(true); }); expect(fetchResult.current.data?.google.enabled).toBe(false); expect(fetchResult.current.data?.facebook.enabled).toBe(false); // Update settings const { result: updateResult } = renderHook(() => useUpdatePlatformOAuthSettings(), { wrapper, }); await act(async () => { await updateResult.current.mutateAsync({ oauth_google_enabled: true, oauth_google_client_id: 'new-google-id', oauth_google_client_secret: 'new-google-secret', oauth_facebook_enabled: true, oauth_facebook_client_id: 'new-fb-id', oauth_facebook_client_secret: 'new-fb-secret', }); }); // Verify cache was updated const cachedData = queryClient.getQueryData(['platformOAuthSettings']); expect(cachedData).toEqual(updatedResponse); }); it('enables all providers in sequence', async () => { const initialResponse = { oauth_allow_registration: true, google: { enabled: false, client_id: '', client_secret: '', }, apple: { enabled: false, client_id: '', client_secret: '', team_id: '', key_id: '', }, facebook: { enabled: false, client_id: '', client_secret: '', }, linkedin: { enabled: false, client_id: '', client_secret: '', }, microsoft: { enabled: false, client_id: '', client_secret: '', tenant_id: '', }, twitter: { enabled: false, client_id: '', client_secret: '', }, twitch: { enabled: false, client_id: '', client_secret: '', }, }; const allEnabledResponse = { oauth_allow_registration: true, google: { enabled: true, client_id: 'google-id', client_secret: 'google-secret', }, apple: { enabled: true, client_id: 'apple-id', client_secret: 'apple-secret', team_id: 'apple-team', key_id: 'apple-key', }, facebook: { enabled: true, client_id: 'fb-id', client_secret: 'fb-secret', }, linkedin: { enabled: true, client_id: 'linkedin-id', client_secret: 'linkedin-secret', }, microsoft: { enabled: true, client_id: 'ms-id', client_secret: 'ms-secret', tenant_id: 'ms-tenant', }, twitter: { enabled: true, client_id: 'twitter-id', client_secret: 'twitter-secret', }, twitch: { enabled: true, client_id: 'twitch-id', client_secret: 'twitch-secret', }, }; vi.mocked(platformOAuthApi.getPlatformOAuthSettings).mockResolvedValue(initialResponse); vi.mocked(platformOAuthApi.updatePlatformOAuthSettings).mockResolvedValue(allEnabledResponse); const queryClient = new QueryClient({ defaultOptions: { queries: { retry: false }, mutations: { retry: false }, }, }); const wrapper = ({ children }: { children: React.ReactNode }) => React.createElement(QueryClientProvider, { client: queryClient }, children); // Fetch initial settings const { result: fetchResult } = renderHook(() => usePlatformOAuthSettings(), { wrapper, }); await waitFor(() => { expect(fetchResult.current.isSuccess).toBe(true); }); // Update all providers const { result: updateResult } = renderHook(() => useUpdatePlatformOAuthSettings(), { wrapper, }); await act(async () => { await updateResult.current.mutateAsync({ oauth_google_enabled: true, oauth_google_client_id: 'google-id', oauth_google_client_secret: 'google-secret', oauth_apple_enabled: true, oauth_apple_client_id: 'apple-id', oauth_apple_client_secret: 'apple-secret', oauth_apple_team_id: 'apple-team', oauth_apple_key_id: 'apple-key', oauth_facebook_enabled: true, oauth_facebook_client_id: 'fb-id', oauth_facebook_client_secret: 'fb-secret', oauth_linkedin_enabled: true, oauth_linkedin_client_id: 'linkedin-id', oauth_linkedin_client_secret: 'linkedin-secret', oauth_microsoft_enabled: true, oauth_microsoft_client_id: 'ms-id', oauth_microsoft_client_secret: 'ms-secret', oauth_microsoft_tenant_id: 'ms-tenant', oauth_twitter_enabled: true, oauth_twitter_client_id: 'twitter-id', oauth_twitter_client_secret: 'twitter-secret', oauth_twitch_enabled: true, oauth_twitch_client_id: 'twitch-id', oauth_twitch_client_secret: 'twitch-secret', }); }); // Verify cache reflects all enabled const cachedData = queryClient.getQueryData(['platformOAuthSettings']); expect(cachedData).toEqual(allEnabledResponse); }); }); });