import { describe, it, expect, vi, beforeEach } from 'vitest'; // Mock apiClient vi.mock('../client', () => ({ default: { get: vi.fn(), post: vi.fn(), patch: vi.fn(), delete: vi.fn(), }, })); import { getResources, getBusinessUsers, getBusinessOAuthSettings, updateBusinessOAuthSettings, getBusinessOAuthCredentials, updateBusinessOAuthCredentials, } from '../business'; import apiClient from '../client'; describe('business API', () => { beforeEach(() => { vi.clearAllMocks(); }); describe('getResources', () => { it('fetches all resources from API', async () => { const mockResources = [ { id: '1', name: 'Resource 1', type: 'STAFF', maxConcurrentEvents: 1, }, { id: '2', name: 'Resource 2', type: 'EQUIPMENT', maxConcurrentEvents: 3, }, ]; vi.mocked(apiClient.get).mockResolvedValue({ data: mockResources }); const result = await getResources(); expect(apiClient.get).toHaveBeenCalledWith('/resources/'); expect(result).toEqual(mockResources); }); it('returns empty array when no resources exist', async () => { vi.mocked(apiClient.get).mockResolvedValue({ data: [] }); const result = await getResources(); expect(result).toEqual([]); }); }); describe('getBusinessUsers', () => { it('fetches all business users from API', async () => { const mockUsers = [ { id: '1', email: 'owner@example.com', name: 'Business Owner', role: 'owner', }, { id: '2', email: 'staff@example.com', name: 'Staff Member', role: 'staff', }, ]; vi.mocked(apiClient.get).mockResolvedValue({ data: mockUsers }); const result = await getBusinessUsers(); expect(apiClient.get).toHaveBeenCalledWith('/business/users/'); expect(result).toEqual(mockUsers); }); it('returns empty array when no users exist', async () => { vi.mocked(apiClient.get).mockResolvedValue({ data: [] }); const result = await getBusinessUsers(); expect(result).toEqual([]); }); }); describe('getBusinessOAuthSettings', () => { it('fetches OAuth settings and transforms snake_case to camelCase', async () => { const mockBackendResponse = { settings: { enabled_providers: ['google', 'microsoft'], allow_registration: true, auto_link_by_email: false, use_custom_credentials: true, }, available_providers: [ { 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(apiClient.get).mockResolvedValue({ data: mockBackendResponse }); const result = await getBusinessOAuthSettings(); expect(apiClient.get).toHaveBeenCalledWith('/business/oauth-settings/'); expect(result).toEqual({ settings: { enabledProviders: ['google', 'microsoft'], allowRegistration: true, autoLinkByEmail: false, 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', }, ], }); }); it('handles empty enabled providers array', async () => { const mockBackendResponse = { settings: { enabled_providers: [], allow_registration: false, auto_link_by_email: false, use_custom_credentials: false, }, available_providers: [], }; vi.mocked(apiClient.get).mockResolvedValue({ data: mockBackendResponse }); const result = await getBusinessOAuthSettings(); expect(result.settings.enabledProviders).toEqual([]); expect(result.availableProviders).toEqual([]); }); it('handles undefined enabled_providers by using empty array', async () => { const mockBackendResponse = { settings: { allow_registration: true, auto_link_by_email: true, use_custom_credentials: false, }, available_providers: [ { id: 'google', name: 'Google', icon: 'google-icon', description: 'Google OAuth', }, ], }; vi.mocked(apiClient.get).mockResolvedValue({ data: mockBackendResponse }); const result = await getBusinessOAuthSettings(); expect(result.settings.enabledProviders).toEqual([]); }); it('handles undefined available_providers by using empty array', async () => { const mockBackendResponse = { settings: { enabled_providers: ['google'], allow_registration: true, auto_link_by_email: true, use_custom_credentials: false, }, }; vi.mocked(apiClient.get).mockResolvedValue({ data: mockBackendResponse }); const result = await getBusinessOAuthSettings(); expect(result.availableProviders).toEqual([]); }); }); describe('updateBusinessOAuthSettings', () => { it('updates OAuth settings and transforms camelCase to snake_case', async () => { const frontendSettings = { enabledProviders: ['google', 'microsoft'], allowRegistration: true, autoLinkByEmail: false, useCustomCredentials: true, }; const mockBackendResponse = { settings: { enabled_providers: ['google', 'microsoft'], allow_registration: true, auto_link_by_email: false, use_custom_credentials: true, }, available_providers: [ { id: 'google', name: 'Google', icon: 'google-icon', description: 'Google OAuth', }, ], }; vi.mocked(apiClient.patch).mockResolvedValue({ data: mockBackendResponse }); const result = await updateBusinessOAuthSettings(frontendSettings); expect(apiClient.patch).toHaveBeenCalledWith('/business/oauth-settings/', { enabled_providers: ['google', 'microsoft'], allow_registration: true, auto_link_by_email: false, use_custom_credentials: true, }); expect(result).toEqual({ settings: { enabledProviders: ['google', 'microsoft'], allowRegistration: true, autoLinkByEmail: false, useCustomCredentials: true, }, availableProviders: [ { id: 'google', name: 'Google', icon: 'google-icon', description: 'Google OAuth', }, ], }); }); it('sends only provided fields to backend', async () => { const partialSettings = { enabledProviders: ['google'], }; const mockBackendResponse = { settings: { enabled_providers: ['google'], allow_registration: true, auto_link_by_email: false, use_custom_credentials: false, }, available_providers: [], }; vi.mocked(apiClient.patch).mockResolvedValue({ data: mockBackendResponse }); await updateBusinessOAuthSettings(partialSettings); expect(apiClient.patch).toHaveBeenCalledWith('/business/oauth-settings/', { enabled_providers: ['google'], }); }); it('handles updating only allowRegistration', async () => { const partialSettings = { allowRegistration: false, }; const mockBackendResponse = { settings: { enabled_providers: [], allow_registration: false, auto_link_by_email: true, use_custom_credentials: false, }, available_providers: [], }; vi.mocked(apiClient.patch).mockResolvedValue({ data: mockBackendResponse }); await updateBusinessOAuthSettings(partialSettings); expect(apiClient.patch).toHaveBeenCalledWith('/business/oauth-settings/', { allow_registration: false, }); }); it('handles updating only autoLinkByEmail', async () => { const partialSettings = { autoLinkByEmail: true, }; const mockBackendResponse = { settings: { enabled_providers: [], allow_registration: false, auto_link_by_email: true, use_custom_credentials: false, }, available_providers: [], }; vi.mocked(apiClient.patch).mockResolvedValue({ data: mockBackendResponse }); await updateBusinessOAuthSettings(partialSettings); expect(apiClient.patch).toHaveBeenCalledWith('/business/oauth-settings/', { auto_link_by_email: true, }); }); it('handles updating only useCustomCredentials', async () => { const partialSettings = { useCustomCredentials: true, }; const mockBackendResponse = { settings: { enabled_providers: [], allow_registration: false, auto_link_by_email: false, use_custom_credentials: true, }, available_providers: [], }; vi.mocked(apiClient.patch).mockResolvedValue({ data: mockBackendResponse }); await updateBusinessOAuthSettings(partialSettings); expect(apiClient.patch).toHaveBeenCalledWith('/business/oauth-settings/', { use_custom_credentials: true, }); }); it('handles boolean false values correctly', async () => { const settings = { allowRegistration: false, autoLinkByEmail: false, useCustomCredentials: false, }; const mockBackendResponse = { settings: { enabled_providers: [], allow_registration: false, auto_link_by_email: false, use_custom_credentials: false, }, available_providers: [], }; vi.mocked(apiClient.patch).mockResolvedValue({ data: mockBackendResponse }); await updateBusinessOAuthSettings(settings); expect(apiClient.patch).toHaveBeenCalledWith('/business/oauth-settings/', { allow_registration: false, auto_link_by_email: false, use_custom_credentials: false, }); }); it('does not send undefined fields', async () => { const settings = {}; const mockBackendResponse = { settings: { enabled_providers: [], allow_registration: true, auto_link_by_email: true, use_custom_credentials: false, }, available_providers: [], }; vi.mocked(apiClient.patch).mockResolvedValue({ data: mockBackendResponse }); await updateBusinessOAuthSettings(settings); expect(apiClient.patch).toHaveBeenCalledWith('/business/oauth-settings/', {}); }); }); describe('getBusinessOAuthCredentials', () => { it('fetches OAuth credentials from API', async () => { const mockBackendResponse = { credentials: { google: { client_id: 'google-client-id', client_secret: 'google-secret', has_secret: true, }, microsoft: { client_id: 'microsoft-client-id', client_secret: '', has_secret: false, }, }, use_custom_credentials: true, }; vi.mocked(apiClient.get).mockResolvedValue({ data: mockBackendResponse }); const result = await getBusinessOAuthCredentials(); expect(apiClient.get).toHaveBeenCalledWith('/business/oauth-credentials/'); expect(result).toEqual({ credentials: { google: { client_id: 'google-client-id', client_secret: 'google-secret', has_secret: true, }, microsoft: { client_id: 'microsoft-client-id', client_secret: '', has_secret: false, }, }, useCustomCredentials: true, }); }); it('handles empty credentials object', async () => { const mockBackendResponse = { credentials: {}, use_custom_credentials: false, }; vi.mocked(apiClient.get).mockResolvedValue({ data: mockBackendResponse }); const result = await getBusinessOAuthCredentials(); expect(result.credentials).toEqual({}); expect(result.useCustomCredentials).toBe(false); }); it('handles undefined credentials by using empty object', async () => { const mockBackendResponse = { use_custom_credentials: false, }; vi.mocked(apiClient.get).mockResolvedValue({ data: mockBackendResponse }); const result = await getBusinessOAuthCredentials(); expect(result.credentials).toEqual({}); }); }); describe('updateBusinessOAuthCredentials', () => { it('updates OAuth credentials', async () => { const credentials = { credentials: { google: { client_id: 'new-google-client-id', client_secret: 'new-google-secret', }, }, useCustomCredentials: true, }; const mockBackendResponse = { credentials: { google: { client_id: 'new-google-client-id', client_secret: 'new-google-secret', has_secret: true, }, }, use_custom_credentials: true, }; vi.mocked(apiClient.patch).mockResolvedValue({ data: mockBackendResponse }); const result = await updateBusinessOAuthCredentials(credentials); expect(apiClient.patch).toHaveBeenCalledWith('/business/oauth-credentials/', { credentials: { google: { client_id: 'new-google-client-id', client_secret: 'new-google-secret', }, }, use_custom_credentials: true, }); expect(result).toEqual({ credentials: { google: { client_id: 'new-google-client-id', client_secret: 'new-google-secret', has_secret: true, }, }, useCustomCredentials: true, }); }); it('updates only credentials without useCustomCredentials', async () => { const data = { credentials: { microsoft: { client_id: 'microsoft-id', }, }, }; const mockBackendResponse = { credentials: { microsoft: { client_id: 'microsoft-id', client_secret: '', has_secret: false, }, }, use_custom_credentials: false, }; vi.mocked(apiClient.patch).mockResolvedValue({ data: mockBackendResponse }); await updateBusinessOAuthCredentials(data); expect(apiClient.patch).toHaveBeenCalledWith('/business/oauth-credentials/', { credentials: { microsoft: { client_id: 'microsoft-id', }, }, }); }); it('updates only useCustomCredentials without credentials', async () => { const data = { useCustomCredentials: false, }; const mockBackendResponse = { credentials: {}, use_custom_credentials: false, }; vi.mocked(apiClient.patch).mockResolvedValue({ data: mockBackendResponse }); await updateBusinessOAuthCredentials(data); expect(apiClient.patch).toHaveBeenCalledWith('/business/oauth-credentials/', { use_custom_credentials: false, }); }); it('handles partial credential updates', async () => { const data = { credentials: { google: { client_id: 'updated-id', }, microsoft: { client_secret: 'updated-secret', }, }, }; const mockBackendResponse = { credentials: { google: { client_id: 'updated-id', client_secret: 'existing-secret', has_secret: true, }, microsoft: { client_id: 'existing-id', client_secret: 'updated-secret', has_secret: true, }, }, use_custom_credentials: true, }; vi.mocked(apiClient.patch).mockResolvedValue({ data: mockBackendResponse }); const result = await updateBusinessOAuthCredentials(data); expect(apiClient.patch).toHaveBeenCalledWith('/business/oauth-credentials/', { credentials: { google: { client_id: 'updated-id', }, microsoft: { client_secret: 'updated-secret', }, }, }); expect(result.credentials.google.client_id).toBe('updated-id'); expect(result.credentials.microsoft.client_secret).toBe('updated-secret'); }); it('handles empty data object', async () => { const data = {}; const mockBackendResponse = { credentials: {}, use_custom_credentials: false, }; vi.mocked(apiClient.patch).mockResolvedValue({ data: mockBackendResponse }); await updateBusinessOAuthCredentials(data); expect(apiClient.patch).toHaveBeenCalledWith('/business/oauth-credentials/', {}); }); it('handles undefined credentials in response by using empty object', async () => { const data = { useCustomCredentials: true, }; const mockBackendResponse = { use_custom_credentials: true, }; vi.mocked(apiClient.patch).mockResolvedValue({ data: mockBackendResponse }); const result = await updateBusinessOAuthCredentials(data); expect(result.credentials).toEqual({}); }); }); });