feat: Add comprehensive test suite and misc improvements
- Add frontend unit tests with Vitest for components, hooks, pages, and utilities - Add backend tests for webhooks, notifications, middleware, and edge cases - Add ForgotPassword, NotFound, and ResetPassword pages - Add migration for orphaned staff resources conversion - Add coverage directory to gitignore (generated reports) - Various bug fixes and improvements from previous work 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
729
frontend/src/hooks/__tests__/useBusinessOAuth.test.ts
Normal file
729
frontend/src/hooks/__tests__/useBusinessOAuth.test.ts
Normal file
@@ -0,0 +1,729 @@
|
||||
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 business API
|
||||
vi.mock('../../api/business', () => ({
|
||||
getBusinessOAuthSettings: vi.fn(),
|
||||
updateBusinessOAuthSettings: vi.fn(),
|
||||
}));
|
||||
|
||||
import {
|
||||
useBusinessOAuthSettings,
|
||||
useUpdateBusinessOAuthSettings,
|
||||
} from '../useBusinessOAuth';
|
||||
import * as businessApi from '../../api/business';
|
||||
|
||||
// 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('useBusinessOAuth hooks', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('useBusinessOAuthSettings', () => {
|
||||
it('fetches business OAuth settings successfully', async () => {
|
||||
const mockResponse = {
|
||||
settings: {
|
||||
enabledProviders: ['google', 'microsoft'],
|
||||
allowRegistration: true,
|
||||
autoLinkByEmail: false,
|
||||
useCustomCredentials: false,
|
||||
},
|
||||
availableProviders: [
|
||||
{
|
||||
id: 'google',
|
||||
name: 'Google',
|
||||
icon: 'google-icon',
|
||||
description: 'Sign in with Google',
|
||||
},
|
||||
{
|
||||
id: 'microsoft',
|
||||
name: 'Microsoft',
|
||||
icon: 'microsoft-icon',
|
||||
description: 'Sign in with Microsoft',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
vi.mocked(businessApi.getBusinessOAuthSettings).mockResolvedValue(mockResponse);
|
||||
|
||||
const { result } = renderHook(() => useBusinessOAuthSettings(), {
|
||||
wrapper: createWrapper(),
|
||||
});
|
||||
|
||||
// Initially loading
|
||||
expect(result.current.isLoading).toBe(true);
|
||||
|
||||
// Wait for success
|
||||
await waitFor(() => {
|
||||
expect(result.current.isSuccess).toBe(true);
|
||||
});
|
||||
|
||||
expect(businessApi.getBusinessOAuthSettings).toHaveBeenCalledTimes(1);
|
||||
expect(result.current.data).toEqual(mockResponse);
|
||||
expect(result.current.data?.settings.enabledProviders).toHaveLength(2);
|
||||
expect(result.current.data?.availableProviders).toHaveLength(2);
|
||||
});
|
||||
|
||||
it('handles empty enabled providers', async () => {
|
||||
const mockResponse = {
|
||||
settings: {
|
||||
enabledProviders: [],
|
||||
allowRegistration: false,
|
||||
autoLinkByEmail: false,
|
||||
useCustomCredentials: false,
|
||||
},
|
||||
availableProviders: [
|
||||
{
|
||||
id: 'google',
|
||||
name: 'Google',
|
||||
icon: 'google-icon',
|
||||
description: 'Sign in with Google',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
vi.mocked(businessApi.getBusinessOAuthSettings).mockResolvedValue(mockResponse);
|
||||
|
||||
const { result } = renderHook(() => useBusinessOAuthSettings(), {
|
||||
wrapper: createWrapper(),
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.isSuccess).toBe(true);
|
||||
});
|
||||
|
||||
expect(result.current.data?.settings.enabledProviders).toEqual([]);
|
||||
expect(result.current.data?.availableProviders).toHaveLength(1);
|
||||
});
|
||||
|
||||
it('handles custom credentials enabled', async () => {
|
||||
const mockResponse = {
|
||||
settings: {
|
||||
enabledProviders: ['google'],
|
||||
allowRegistration: true,
|
||||
autoLinkByEmail: true,
|
||||
useCustomCredentials: true,
|
||||
},
|
||||
availableProviders: [
|
||||
{
|
||||
id: 'google',
|
||||
name: 'Google',
|
||||
icon: 'google-icon',
|
||||
description: 'Sign in with Google',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
vi.mocked(businessApi.getBusinessOAuthSettings).mockResolvedValue(mockResponse);
|
||||
|
||||
const { result } = renderHook(() => useBusinessOAuthSettings(), {
|
||||
wrapper: createWrapper(),
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.isSuccess).toBe(true);
|
||||
});
|
||||
|
||||
expect(result.current.data?.settings.useCustomCredentials).toBe(true);
|
||||
expect(result.current.data?.settings.autoLinkByEmail).toBe(true);
|
||||
});
|
||||
|
||||
it('handles API error gracefully', async () => {
|
||||
const mockError = new Error('Failed to fetch OAuth settings');
|
||||
vi.mocked(businessApi.getBusinessOAuthSettings).mockRejectedValue(mockError);
|
||||
|
||||
const { result } = renderHook(() => useBusinessOAuthSettings(), {
|
||||
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(businessApi.getBusinessOAuthSettings).mockRejectedValue(
|
||||
new Error('404 Not Found')
|
||||
);
|
||||
|
||||
const { result } = renderHook(() => useBusinessOAuthSettings(), {
|
||||
wrapper: createWrapper(),
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.isError).toBe(true);
|
||||
});
|
||||
|
||||
// Should be called only once (no retries)
|
||||
expect(businessApi.getBusinessOAuthSettings).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('caches data with 5 minute stale time', async () => {
|
||||
const mockResponse = {
|
||||
settings: {
|
||||
enabledProviders: ['google'],
|
||||
allowRegistration: true,
|
||||
autoLinkByEmail: false,
|
||||
useCustomCredentials: false,
|
||||
},
|
||||
availableProviders: [
|
||||
{
|
||||
id: 'google',
|
||||
name: 'Google',
|
||||
icon: 'google-icon',
|
||||
description: 'Sign in with Google',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
vi.mocked(businessApi.getBusinessOAuthSettings).mockResolvedValue(mockResponse);
|
||||
|
||||
const { result, rerender } = renderHook(() => useBusinessOAuthSettings(), {
|
||||
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(businessApi.getBusinessOAuthSettings).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('useUpdateBusinessOAuthSettings', () => {
|
||||
it('updates enabled providers successfully', async () => {
|
||||
const mockResponse = {
|
||||
settings: {
|
||||
enabledProviders: ['google', 'microsoft', 'github'],
|
||||
allowRegistration: true,
|
||||
autoLinkByEmail: false,
|
||||
useCustomCredentials: false,
|
||||
},
|
||||
availableProviders: [
|
||||
{
|
||||
id: 'google',
|
||||
name: 'Google',
|
||||
icon: 'google-icon',
|
||||
description: 'Sign in with Google',
|
||||
},
|
||||
{
|
||||
id: 'microsoft',
|
||||
name: 'Microsoft',
|
||||
icon: 'microsoft-icon',
|
||||
description: 'Sign in with Microsoft',
|
||||
},
|
||||
{
|
||||
id: 'github',
|
||||
name: 'GitHub',
|
||||
icon: 'github-icon',
|
||||
description: 'Sign in with GitHub',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
vi.mocked(businessApi.updateBusinessOAuthSettings).mockResolvedValue(mockResponse);
|
||||
|
||||
const { result } = renderHook(() => useUpdateBusinessOAuthSettings(), {
|
||||
wrapper: createWrapper(),
|
||||
});
|
||||
|
||||
await act(async () => {
|
||||
await result.current.mutateAsync({
|
||||
enabledProviders: ['google', 'microsoft', 'github'],
|
||||
});
|
||||
});
|
||||
|
||||
expect(businessApi.updateBusinessOAuthSettings).toHaveBeenCalledWith({
|
||||
enabledProviders: ['google', 'microsoft', 'github'],
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.isSuccess).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
it('updates allowRegistration flag', async () => {
|
||||
const mockResponse = {
|
||||
settings: {
|
||||
enabledProviders: ['google'],
|
||||
allowRegistration: false,
|
||||
autoLinkByEmail: false,
|
||||
useCustomCredentials: false,
|
||||
},
|
||||
availableProviders: [
|
||||
{
|
||||
id: 'google',
|
||||
name: 'Google',
|
||||
icon: 'google-icon',
|
||||
description: 'Sign in with Google',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
vi.mocked(businessApi.updateBusinessOAuthSettings).mockResolvedValue(mockResponse);
|
||||
|
||||
const { result } = renderHook(() => useUpdateBusinessOAuthSettings(), {
|
||||
wrapper: createWrapper(),
|
||||
});
|
||||
|
||||
await act(async () => {
|
||||
await result.current.mutateAsync({
|
||||
allowRegistration: false,
|
||||
});
|
||||
});
|
||||
|
||||
expect(businessApi.updateBusinessOAuthSettings).toHaveBeenCalledWith({
|
||||
allowRegistration: false,
|
||||
});
|
||||
});
|
||||
|
||||
it('updates autoLinkByEmail flag', async () => {
|
||||
const mockResponse = {
|
||||
settings: {
|
||||
enabledProviders: ['google'],
|
||||
allowRegistration: true,
|
||||
autoLinkByEmail: true,
|
||||
useCustomCredentials: false,
|
||||
},
|
||||
availableProviders: [
|
||||
{
|
||||
id: 'google',
|
||||
name: 'Google',
|
||||
icon: 'google-icon',
|
||||
description: 'Sign in with Google',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
vi.mocked(businessApi.updateBusinessOAuthSettings).mockResolvedValue(mockResponse);
|
||||
|
||||
const { result } = renderHook(() => useUpdateBusinessOAuthSettings(), {
|
||||
wrapper: createWrapper(),
|
||||
});
|
||||
|
||||
await act(async () => {
|
||||
await result.current.mutateAsync({
|
||||
autoLinkByEmail: true,
|
||||
});
|
||||
});
|
||||
|
||||
expect(businessApi.updateBusinessOAuthSettings).toHaveBeenCalledWith({
|
||||
autoLinkByEmail: true,
|
||||
});
|
||||
});
|
||||
|
||||
it('updates useCustomCredentials flag', async () => {
|
||||
const mockResponse = {
|
||||
settings: {
|
||||
enabledProviders: ['google'],
|
||||
allowRegistration: true,
|
||||
autoLinkByEmail: false,
|
||||
useCustomCredentials: true,
|
||||
},
|
||||
availableProviders: [
|
||||
{
|
||||
id: 'google',
|
||||
name: 'Google',
|
||||
icon: 'google-icon',
|
||||
description: 'Sign in with Google',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
vi.mocked(businessApi.updateBusinessOAuthSettings).mockResolvedValue(mockResponse);
|
||||
|
||||
const { result } = renderHook(() => useUpdateBusinessOAuthSettings(), {
|
||||
wrapper: createWrapper(),
|
||||
});
|
||||
|
||||
await act(async () => {
|
||||
await result.current.mutateAsync({
|
||||
useCustomCredentials: true,
|
||||
});
|
||||
});
|
||||
|
||||
expect(businessApi.updateBusinessOAuthSettings).toHaveBeenCalledWith({
|
||||
useCustomCredentials: true,
|
||||
});
|
||||
});
|
||||
|
||||
it('updates multiple settings at once', async () => {
|
||||
const mockResponse = {
|
||||
settings: {
|
||||
enabledProviders: ['google', 'microsoft'],
|
||||
allowRegistration: false,
|
||||
autoLinkByEmail: true,
|
||||
useCustomCredentials: true,
|
||||
},
|
||||
availableProviders: [
|
||||
{
|
||||
id: 'google',
|
||||
name: 'Google',
|
||||
icon: 'google-icon',
|
||||
description: 'Sign in with Google',
|
||||
},
|
||||
{
|
||||
id: 'microsoft',
|
||||
name: 'Microsoft',
|
||||
icon: 'microsoft-icon',
|
||||
description: 'Sign in with Microsoft',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
vi.mocked(businessApi.updateBusinessOAuthSettings).mockResolvedValue(mockResponse);
|
||||
|
||||
const { result } = renderHook(() => useUpdateBusinessOAuthSettings(), {
|
||||
wrapper: createWrapper(),
|
||||
});
|
||||
|
||||
await act(async () => {
|
||||
await result.current.mutateAsync({
|
||||
enabledProviders: ['google', 'microsoft'],
|
||||
allowRegistration: false,
|
||||
autoLinkByEmail: true,
|
||||
useCustomCredentials: true,
|
||||
});
|
||||
});
|
||||
|
||||
expect(businessApi.updateBusinessOAuthSettings).toHaveBeenCalledWith({
|
||||
enabledProviders: ['google', 'microsoft'],
|
||||
allowRegistration: false,
|
||||
autoLinkByEmail: true,
|
||||
useCustomCredentials: true,
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.isSuccess).toBe(true);
|
||||
});
|
||||
|
||||
expect(result.current.data?.settings.enabledProviders).toHaveLength(2);
|
||||
expect(result.current.data?.settings.allowRegistration).toBe(false);
|
||||
expect(result.current.data?.settings.autoLinkByEmail).toBe(true);
|
||||
expect(result.current.data?.settings.useCustomCredentials).toBe(true);
|
||||
});
|
||||
|
||||
it('updates query cache on success', async () => {
|
||||
const mockResponse = {
|
||||
settings: {
|
||||
enabledProviders: ['google'],
|
||||
allowRegistration: true,
|
||||
autoLinkByEmail: false,
|
||||
useCustomCredentials: false,
|
||||
},
|
||||
availableProviders: [
|
||||
{
|
||||
id: 'google',
|
||||
name: 'Google',
|
||||
icon: 'google-icon',
|
||||
description: 'Sign in with Google',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
vi.mocked(businessApi.updateBusinessOAuthSettings).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(() => useUpdateBusinessOAuthSettings(), {
|
||||
wrapper,
|
||||
});
|
||||
|
||||
await act(async () => {
|
||||
await result.current.mutateAsync({
|
||||
enabledProviders: ['google'],
|
||||
});
|
||||
});
|
||||
|
||||
// Verify cache was updated
|
||||
const cachedData = queryClient.getQueryData(['businessOAuthSettings']);
|
||||
expect(cachedData).toEqual(mockResponse);
|
||||
});
|
||||
|
||||
it('handles update error gracefully', async () => {
|
||||
const mockError = new Error('Failed to update settings');
|
||||
vi.mocked(businessApi.updateBusinessOAuthSettings).mockRejectedValue(mockError);
|
||||
|
||||
const { result } = renderHook(() => useUpdateBusinessOAuthSettings(), {
|
||||
wrapper: createWrapper(),
|
||||
});
|
||||
|
||||
let caughtError: any = null;
|
||||
|
||||
await act(async () => {
|
||||
try {
|
||||
await result.current.mutateAsync({
|
||||
allowRegistration: 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 partial update with only enabledProviders', async () => {
|
||||
const mockResponse = {
|
||||
settings: {
|
||||
enabledProviders: ['github'],
|
||||
allowRegistration: true,
|
||||
autoLinkByEmail: false,
|
||||
useCustomCredentials: false,
|
||||
},
|
||||
availableProviders: [
|
||||
{
|
||||
id: 'github',
|
||||
name: 'GitHub',
|
||||
icon: 'github-icon',
|
||||
description: 'Sign in with GitHub',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
vi.mocked(businessApi.updateBusinessOAuthSettings).mockResolvedValue(mockResponse);
|
||||
|
||||
const { result } = renderHook(() => useUpdateBusinessOAuthSettings(), {
|
||||
wrapper: createWrapper(),
|
||||
});
|
||||
|
||||
await act(async () => {
|
||||
await result.current.mutateAsync({
|
||||
enabledProviders: ['github'],
|
||||
});
|
||||
});
|
||||
|
||||
expect(businessApi.updateBusinessOAuthSettings).toHaveBeenCalledWith({
|
||||
enabledProviders: ['github'],
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.isSuccess).toBe(true);
|
||||
});
|
||||
|
||||
expect(result.current.data?.settings.enabledProviders).toEqual(['github']);
|
||||
});
|
||||
|
||||
it('handles empty enabled providers array', async () => {
|
||||
const mockResponse = {
|
||||
settings: {
|
||||
enabledProviders: [],
|
||||
allowRegistration: true,
|
||||
autoLinkByEmail: false,
|
||||
useCustomCredentials: false,
|
||||
},
|
||||
availableProviders: [
|
||||
{
|
||||
id: 'google',
|
||||
name: 'Google',
|
||||
icon: 'google-icon',
|
||||
description: 'Sign in with Google',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
vi.mocked(businessApi.updateBusinessOAuthSettings).mockResolvedValue(mockResponse);
|
||||
|
||||
const { result } = renderHook(() => useUpdateBusinessOAuthSettings(), {
|
||||
wrapper: createWrapper(),
|
||||
});
|
||||
|
||||
await act(async () => {
|
||||
await result.current.mutateAsync({
|
||||
enabledProviders: [],
|
||||
});
|
||||
});
|
||||
|
||||
expect(businessApi.updateBusinessOAuthSettings).toHaveBeenCalledWith({
|
||||
enabledProviders: [],
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.isSuccess).toBe(true);
|
||||
});
|
||||
|
||||
expect(result.current.data?.settings.enabledProviders).toEqual([]);
|
||||
});
|
||||
|
||||
it('preserves availableProviders from backend response', async () => {
|
||||
const mockResponse = {
|
||||
settings: {
|
||||
enabledProviders: ['google'],
|
||||
allowRegistration: true,
|
||||
autoLinkByEmail: false,
|
||||
useCustomCredentials: false,
|
||||
},
|
||||
availableProviders: [
|
||||
{
|
||||
id: 'google',
|
||||
name: 'Google',
|
||||
icon: 'google-icon',
|
||||
description: 'Sign in with Google',
|
||||
},
|
||||
{
|
||||
id: 'microsoft',
|
||||
name: 'Microsoft',
|
||||
icon: 'microsoft-icon',
|
||||
description: 'Sign in with Microsoft',
|
||||
},
|
||||
{
|
||||
id: 'github',
|
||||
name: 'GitHub',
|
||||
icon: 'github-icon',
|
||||
description: 'Sign in with GitHub',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
vi.mocked(businessApi.updateBusinessOAuthSettings).mockResolvedValue(mockResponse);
|
||||
|
||||
const { result } = renderHook(() => useUpdateBusinessOAuthSettings(), {
|
||||
wrapper: createWrapper(),
|
||||
});
|
||||
|
||||
await act(async () => {
|
||||
await result.current.mutateAsync({
|
||||
enabledProviders: ['google'],
|
||||
});
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.isSuccess).toBe(true);
|
||||
});
|
||||
|
||||
expect(result.current.data?.availableProviders).toHaveLength(3);
|
||||
expect(result.current.data?.availableProviders.map(p => p.id)).toEqual([
|
||||
'google',
|
||||
'microsoft',
|
||||
'github',
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('integration tests', () => {
|
||||
it('fetches settings then updates them', async () => {
|
||||
const initialResponse = {
|
||||
settings: {
|
||||
enabledProviders: ['google'],
|
||||
allowRegistration: true,
|
||||
autoLinkByEmail: false,
|
||||
useCustomCredentials: false,
|
||||
},
|
||||
availableProviders: [
|
||||
{
|
||||
id: 'google',
|
||||
name: 'Google',
|
||||
icon: 'google-icon',
|
||||
description: 'Sign in with Google',
|
||||
},
|
||||
{
|
||||
id: 'microsoft',
|
||||
name: 'Microsoft',
|
||||
icon: 'microsoft-icon',
|
||||
description: 'Sign in with Microsoft',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const updatedResponse = {
|
||||
settings: {
|
||||
enabledProviders: ['google', 'microsoft'],
|
||||
allowRegistration: true,
|
||||
autoLinkByEmail: true,
|
||||
useCustomCredentials: false,
|
||||
},
|
||||
availableProviders: [
|
||||
{
|
||||
id: 'google',
|
||||
name: 'Google',
|
||||
icon: 'google-icon',
|
||||
description: 'Sign in with Google',
|
||||
},
|
||||
{
|
||||
id: 'microsoft',
|
||||
name: 'Microsoft',
|
||||
icon: 'microsoft-icon',
|
||||
description: 'Sign in with Microsoft',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
vi.mocked(businessApi.getBusinessOAuthSettings).mockResolvedValue(initialResponse);
|
||||
vi.mocked(businessApi.updateBusinessOAuthSettings).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(() => useBusinessOAuthSettings(), {
|
||||
wrapper,
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
expect(fetchResult.current.isSuccess).toBe(true);
|
||||
});
|
||||
|
||||
expect(fetchResult.current.data?.settings.enabledProviders).toEqual(['google']);
|
||||
expect(fetchResult.current.data?.settings.autoLinkByEmail).toBe(false);
|
||||
|
||||
// Update settings
|
||||
const { result: updateResult } = renderHook(() => useUpdateBusinessOAuthSettings(), {
|
||||
wrapper,
|
||||
});
|
||||
|
||||
await act(async () => {
|
||||
await updateResult.current.mutateAsync({
|
||||
enabledProviders: ['google', 'microsoft'],
|
||||
autoLinkByEmail: true,
|
||||
});
|
||||
});
|
||||
|
||||
// Verify cache was updated
|
||||
const cachedData = queryClient.getQueryData(['businessOAuthSettings']);
|
||||
expect(cachedData).toEqual(updatedResponse);
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user