- 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>
794 lines
26 KiB
TypeScript
794 lines
26 KiB
TypeScript
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
|
|
vi.mock('../client', () => ({
|
|
default: {
|
|
get: vi.fn(),
|
|
post: vi.fn(),
|
|
patch: vi.fn(),
|
|
delete: vi.fn(),
|
|
},
|
|
}));
|
|
|
|
import {
|
|
getTicketEmailAddresses,
|
|
getTicketEmailAddress,
|
|
createTicketEmailAddress,
|
|
updateTicketEmailAddress,
|
|
deleteTicketEmailAddress,
|
|
testImapConnection,
|
|
testSmtpConnection,
|
|
fetchEmailsNow,
|
|
setAsDefault,
|
|
TicketEmailAddressListItem,
|
|
TicketEmailAddress,
|
|
TicketEmailAddressCreate,
|
|
TestConnectionResponse,
|
|
FetchEmailsResponse,
|
|
} from '../ticketEmailAddresses';
|
|
import apiClient from '../client';
|
|
|
|
describe('ticketEmailAddresses API', () => {
|
|
beforeEach(() => {
|
|
vi.clearAllMocks();
|
|
});
|
|
|
|
describe('getTicketEmailAddresses', () => {
|
|
it('should fetch all ticket email addresses', async () => {
|
|
const mockAddresses: TicketEmailAddressListItem[] = [
|
|
{
|
|
id: 1,
|
|
display_name: 'Support',
|
|
email_address: 'support@example.com',
|
|
color: '#FF5733',
|
|
is_active: true,
|
|
is_default: true,
|
|
last_check_at: '2025-12-07T10:00:00Z',
|
|
emails_processed_count: 42,
|
|
created_at: '2025-12-01T10:00:00Z',
|
|
updated_at: '2025-12-07T10:00:00Z',
|
|
},
|
|
{
|
|
id: 2,
|
|
display_name: 'Sales',
|
|
email_address: 'sales@example.com',
|
|
color: '#3357FF',
|
|
is_active: true,
|
|
is_default: false,
|
|
emails_processed_count: 15,
|
|
created_at: '2025-12-02T10:00:00Z',
|
|
updated_at: '2025-12-05T10:00:00Z',
|
|
},
|
|
];
|
|
|
|
vi.mocked(apiClient.get).mockResolvedValue({ data: mockAddresses });
|
|
|
|
const result = await getTicketEmailAddresses();
|
|
|
|
expect(apiClient.get).toHaveBeenCalledWith('/tickets/email-addresses/');
|
|
expect(result).toEqual(mockAddresses);
|
|
expect(result).toHaveLength(2);
|
|
});
|
|
|
|
it('should return empty array when no addresses exist', async () => {
|
|
vi.mocked(apiClient.get).mockResolvedValue({ data: [] });
|
|
|
|
const result = await getTicketEmailAddresses();
|
|
|
|
expect(apiClient.get).toHaveBeenCalledWith('/tickets/email-addresses/');
|
|
expect(result).toEqual([]);
|
|
expect(result).toHaveLength(0);
|
|
});
|
|
|
|
it('should throw error when API call fails', async () => {
|
|
const mockError = new Error('Network error');
|
|
vi.mocked(apiClient.get).mockRejectedValue(mockError);
|
|
|
|
await expect(getTicketEmailAddresses()).rejects.toThrow('Network error');
|
|
expect(apiClient.get).toHaveBeenCalledWith('/tickets/email-addresses/');
|
|
});
|
|
});
|
|
|
|
describe('getTicketEmailAddress', () => {
|
|
it('should fetch a specific ticket email address by ID', async () => {
|
|
const mockAddress: TicketEmailAddress = {
|
|
id: 1,
|
|
tenant: 100,
|
|
tenant_name: 'Test Business',
|
|
display_name: 'Support',
|
|
email_address: 'support@example.com',
|
|
color: '#FF5733',
|
|
imap_host: 'imap.gmail.com',
|
|
imap_port: 993,
|
|
imap_use_ssl: true,
|
|
imap_username: 'support@example.com',
|
|
imap_folder: 'INBOX',
|
|
smtp_host: 'smtp.gmail.com',
|
|
smtp_port: 587,
|
|
smtp_use_tls: true,
|
|
smtp_use_ssl: false,
|
|
smtp_username: 'support@example.com',
|
|
is_active: true,
|
|
is_default: true,
|
|
last_check_at: '2025-12-07T10:00:00Z',
|
|
emails_processed_count: 42,
|
|
created_at: '2025-12-01T10:00:00Z',
|
|
updated_at: '2025-12-07T10:00:00Z',
|
|
is_imap_configured: true,
|
|
is_smtp_configured: true,
|
|
is_fully_configured: true,
|
|
};
|
|
|
|
vi.mocked(apiClient.get).mockResolvedValue({ data: mockAddress });
|
|
|
|
const result = await getTicketEmailAddress(1);
|
|
|
|
expect(apiClient.get).toHaveBeenCalledWith('/tickets/email-addresses/1/');
|
|
expect(result).toEqual(mockAddress);
|
|
expect(result.id).toBe(1);
|
|
expect(result.email_address).toBe('support@example.com');
|
|
});
|
|
|
|
it('should handle fetching with different IDs', async () => {
|
|
const mockAddress: TicketEmailAddress = {
|
|
id: 999,
|
|
tenant: 100,
|
|
tenant_name: 'Test Business',
|
|
display_name: 'Sales',
|
|
email_address: 'sales@example.com',
|
|
color: '#3357FF',
|
|
imap_host: 'imap.example.com',
|
|
imap_port: 993,
|
|
imap_use_ssl: true,
|
|
imap_username: 'sales@example.com',
|
|
imap_folder: 'INBOX',
|
|
smtp_host: 'smtp.example.com',
|
|
smtp_port: 587,
|
|
smtp_use_tls: true,
|
|
smtp_use_ssl: false,
|
|
smtp_username: 'sales@example.com',
|
|
is_active: true,
|
|
is_default: false,
|
|
emails_processed_count: 0,
|
|
created_at: '2025-12-01T10:00:00Z',
|
|
updated_at: '2025-12-01T10:00:00Z',
|
|
is_imap_configured: true,
|
|
is_smtp_configured: true,
|
|
is_fully_configured: true,
|
|
};
|
|
|
|
vi.mocked(apiClient.get).mockResolvedValue({ data: mockAddress });
|
|
|
|
const result = await getTicketEmailAddress(999);
|
|
|
|
expect(apiClient.get).toHaveBeenCalledWith('/tickets/email-addresses/999/');
|
|
expect(result.id).toBe(999);
|
|
});
|
|
|
|
it('should throw error when address not found', async () => {
|
|
const mockError = new Error('Not found');
|
|
vi.mocked(apiClient.get).mockRejectedValue(mockError);
|
|
|
|
await expect(getTicketEmailAddress(999)).rejects.toThrow('Not found');
|
|
expect(apiClient.get).toHaveBeenCalledWith('/tickets/email-addresses/999/');
|
|
});
|
|
});
|
|
|
|
describe('createTicketEmailAddress', () => {
|
|
it('should create a new ticket email address', async () => {
|
|
const createData: TicketEmailAddressCreate = {
|
|
display_name: 'Support',
|
|
email_address: 'support@example.com',
|
|
color: '#FF5733',
|
|
imap_host: 'imap.gmail.com',
|
|
imap_port: 993,
|
|
imap_use_ssl: true,
|
|
imap_username: 'support@example.com',
|
|
imap_password: 'secure_password',
|
|
imap_folder: 'INBOX',
|
|
smtp_host: 'smtp.gmail.com',
|
|
smtp_port: 587,
|
|
smtp_use_tls: true,
|
|
smtp_use_ssl: false,
|
|
smtp_username: 'support@example.com',
|
|
smtp_password: 'secure_password',
|
|
is_active: true,
|
|
is_default: false,
|
|
};
|
|
|
|
const mockResponse: TicketEmailAddress = {
|
|
id: 1,
|
|
tenant: 100,
|
|
tenant_name: 'Test Business',
|
|
...createData,
|
|
imap_password: undefined, // Passwords are not returned in response
|
|
smtp_password: undefined,
|
|
last_check_at: undefined,
|
|
last_error: undefined,
|
|
emails_processed_count: 0,
|
|
created_at: '2025-12-07T10:00:00Z',
|
|
updated_at: '2025-12-07T10:00:00Z',
|
|
is_imap_configured: true,
|
|
is_smtp_configured: true,
|
|
is_fully_configured: true,
|
|
};
|
|
|
|
vi.mocked(apiClient.post).mockResolvedValue({ data: mockResponse });
|
|
|
|
const result = await createTicketEmailAddress(createData);
|
|
|
|
expect(apiClient.post).toHaveBeenCalledWith('/tickets/email-addresses/', createData);
|
|
expect(result).toEqual(mockResponse);
|
|
expect(result.id).toBe(1);
|
|
expect(result.display_name).toBe('Support');
|
|
});
|
|
|
|
it('should handle creating with minimal required fields', async () => {
|
|
const createData: TicketEmailAddressCreate = {
|
|
display_name: 'Minimal',
|
|
email_address: 'minimal@example.com',
|
|
color: '#000000',
|
|
imap_host: 'imap.example.com',
|
|
imap_port: 993,
|
|
imap_use_ssl: true,
|
|
imap_username: 'minimal@example.com',
|
|
imap_password: 'password',
|
|
imap_folder: 'INBOX',
|
|
smtp_host: 'smtp.example.com',
|
|
smtp_port: 587,
|
|
smtp_use_tls: false,
|
|
smtp_use_ssl: false,
|
|
smtp_username: 'minimal@example.com',
|
|
smtp_password: 'password',
|
|
is_active: false,
|
|
is_default: false,
|
|
};
|
|
|
|
const mockResponse: TicketEmailAddress = {
|
|
id: 2,
|
|
tenant: 100,
|
|
tenant_name: 'Test Business',
|
|
...createData,
|
|
imap_password: undefined,
|
|
smtp_password: undefined,
|
|
emails_processed_count: 0,
|
|
created_at: '2025-12-07T10:00:00Z',
|
|
updated_at: '2025-12-07T10:00:00Z',
|
|
is_imap_configured: true,
|
|
is_smtp_configured: true,
|
|
is_fully_configured: true,
|
|
};
|
|
|
|
vi.mocked(apiClient.post).mockResolvedValue({ data: mockResponse });
|
|
|
|
const result = await createTicketEmailAddress(createData);
|
|
|
|
expect(apiClient.post).toHaveBeenCalledWith('/tickets/email-addresses/', createData);
|
|
expect(result.id).toBe(2);
|
|
});
|
|
|
|
it('should throw error when validation fails', async () => {
|
|
const invalidData: TicketEmailAddressCreate = {
|
|
display_name: '',
|
|
email_address: 'invalid-email',
|
|
color: '#FF5733',
|
|
imap_host: '',
|
|
imap_port: 993,
|
|
imap_use_ssl: true,
|
|
imap_username: '',
|
|
imap_password: '',
|
|
imap_folder: 'INBOX',
|
|
smtp_host: '',
|
|
smtp_port: 587,
|
|
smtp_use_tls: true,
|
|
smtp_use_ssl: false,
|
|
smtp_username: '',
|
|
smtp_password: '',
|
|
is_active: true,
|
|
is_default: false,
|
|
};
|
|
|
|
const mockError = new Error('Validation error');
|
|
vi.mocked(apiClient.post).mockRejectedValue(mockError);
|
|
|
|
await expect(createTicketEmailAddress(invalidData)).rejects.toThrow('Validation error');
|
|
expect(apiClient.post).toHaveBeenCalledWith('/tickets/email-addresses/', invalidData);
|
|
});
|
|
});
|
|
|
|
describe('updateTicketEmailAddress', () => {
|
|
it('should update an existing ticket email address', async () => {
|
|
const updateData: Partial<TicketEmailAddressCreate> = {
|
|
display_name: 'Updated Support',
|
|
color: '#00FF00',
|
|
};
|
|
|
|
const mockResponse: TicketEmailAddress = {
|
|
id: 1,
|
|
tenant: 100,
|
|
tenant_name: 'Test Business',
|
|
display_name: 'Updated Support',
|
|
email_address: 'support@example.com',
|
|
color: '#00FF00',
|
|
imap_host: 'imap.gmail.com',
|
|
imap_port: 993,
|
|
imap_use_ssl: true,
|
|
imap_username: 'support@example.com',
|
|
imap_folder: 'INBOX',
|
|
smtp_host: 'smtp.gmail.com',
|
|
smtp_port: 587,
|
|
smtp_use_tls: true,
|
|
smtp_use_ssl: false,
|
|
smtp_username: 'support@example.com',
|
|
is_active: true,
|
|
is_default: true,
|
|
emails_processed_count: 42,
|
|
created_at: '2025-12-01T10:00:00Z',
|
|
updated_at: '2025-12-07T11:00:00Z',
|
|
is_imap_configured: true,
|
|
is_smtp_configured: true,
|
|
is_fully_configured: true,
|
|
};
|
|
|
|
vi.mocked(apiClient.patch).mockResolvedValue({ data: mockResponse });
|
|
|
|
const result = await updateTicketEmailAddress(1, updateData);
|
|
|
|
expect(apiClient.patch).toHaveBeenCalledWith('/tickets/email-addresses/1/', updateData);
|
|
expect(result).toEqual(mockResponse);
|
|
expect(result.display_name).toBe('Updated Support');
|
|
expect(result.color).toBe('#00FF00');
|
|
});
|
|
|
|
it('should update IMAP configuration', async () => {
|
|
const updateData: Partial<TicketEmailAddressCreate> = {
|
|
imap_host: 'imap.newserver.com',
|
|
imap_port: 993,
|
|
imap_password: 'new_password',
|
|
};
|
|
|
|
const mockResponse: TicketEmailAddress = {
|
|
id: 1,
|
|
tenant: 100,
|
|
tenant_name: 'Test Business',
|
|
display_name: 'Support',
|
|
email_address: 'support@example.com',
|
|
color: '#FF5733',
|
|
imap_host: 'imap.newserver.com',
|
|
imap_port: 993,
|
|
imap_use_ssl: true,
|
|
imap_username: 'support@example.com',
|
|
imap_folder: 'INBOX',
|
|
smtp_host: 'smtp.gmail.com',
|
|
smtp_port: 587,
|
|
smtp_use_tls: true,
|
|
smtp_use_ssl: false,
|
|
smtp_username: 'support@example.com',
|
|
is_active: true,
|
|
is_default: true,
|
|
emails_processed_count: 42,
|
|
created_at: '2025-12-01T10:00:00Z',
|
|
updated_at: '2025-12-07T11:00:00Z',
|
|
is_imap_configured: true,
|
|
is_smtp_configured: true,
|
|
is_fully_configured: true,
|
|
};
|
|
|
|
vi.mocked(apiClient.patch).mockResolvedValue({ data: mockResponse });
|
|
|
|
const result = await updateTicketEmailAddress(1, updateData);
|
|
|
|
expect(apiClient.patch).toHaveBeenCalledWith('/tickets/email-addresses/1/', updateData);
|
|
expect(result.imap_host).toBe('imap.newserver.com');
|
|
});
|
|
|
|
it('should update SMTP configuration', async () => {
|
|
const updateData: Partial<TicketEmailAddressCreate> = {
|
|
smtp_host: 'smtp.newserver.com',
|
|
smtp_port: 465,
|
|
smtp_use_tls: false,
|
|
smtp_use_ssl: true,
|
|
};
|
|
|
|
const mockResponse: TicketEmailAddress = {
|
|
id: 1,
|
|
tenant: 100,
|
|
tenant_name: 'Test Business',
|
|
display_name: 'Support',
|
|
email_address: 'support@example.com',
|
|
color: '#FF5733',
|
|
imap_host: 'imap.gmail.com',
|
|
imap_port: 993,
|
|
imap_use_ssl: true,
|
|
imap_username: 'support@example.com',
|
|
imap_folder: 'INBOX',
|
|
smtp_host: 'smtp.newserver.com',
|
|
smtp_port: 465,
|
|
smtp_use_tls: false,
|
|
smtp_use_ssl: true,
|
|
smtp_username: 'support@example.com',
|
|
is_active: true,
|
|
is_default: true,
|
|
emails_processed_count: 42,
|
|
created_at: '2025-12-01T10:00:00Z',
|
|
updated_at: '2025-12-07T11:00:00Z',
|
|
is_imap_configured: true,
|
|
is_smtp_configured: true,
|
|
is_fully_configured: true,
|
|
};
|
|
|
|
vi.mocked(apiClient.patch).mockResolvedValue({ data: mockResponse });
|
|
|
|
const result = await updateTicketEmailAddress(1, updateData);
|
|
|
|
expect(apiClient.patch).toHaveBeenCalledWith('/tickets/email-addresses/1/', updateData);
|
|
expect(result.smtp_host).toBe('smtp.newserver.com');
|
|
expect(result.smtp_port).toBe(465);
|
|
expect(result.smtp_use_ssl).toBe(true);
|
|
});
|
|
|
|
it('should toggle is_active status', async () => {
|
|
const updateData: Partial<TicketEmailAddressCreate> = {
|
|
is_active: false,
|
|
};
|
|
|
|
const mockResponse: TicketEmailAddress = {
|
|
id: 1,
|
|
tenant: 100,
|
|
tenant_name: 'Test Business',
|
|
display_name: 'Support',
|
|
email_address: 'support@example.com',
|
|
color: '#FF5733',
|
|
imap_host: 'imap.gmail.com',
|
|
imap_port: 993,
|
|
imap_use_ssl: true,
|
|
imap_username: 'support@example.com',
|
|
imap_folder: 'INBOX',
|
|
smtp_host: 'smtp.gmail.com',
|
|
smtp_port: 587,
|
|
smtp_use_tls: true,
|
|
smtp_use_ssl: false,
|
|
smtp_username: 'support@example.com',
|
|
is_active: false,
|
|
is_default: true,
|
|
emails_processed_count: 42,
|
|
created_at: '2025-12-01T10:00:00Z',
|
|
updated_at: '2025-12-07T11:00:00Z',
|
|
is_imap_configured: true,
|
|
is_smtp_configured: true,
|
|
is_fully_configured: true,
|
|
};
|
|
|
|
vi.mocked(apiClient.patch).mockResolvedValue({ data: mockResponse });
|
|
|
|
const result = await updateTicketEmailAddress(1, updateData);
|
|
|
|
expect(apiClient.patch).toHaveBeenCalledWith('/tickets/email-addresses/1/', updateData);
|
|
expect(result.is_active).toBe(false);
|
|
});
|
|
|
|
it('should throw error when update fails', async () => {
|
|
const updateData: Partial<TicketEmailAddressCreate> = {
|
|
display_name: 'Invalid',
|
|
};
|
|
|
|
const mockError = new Error('Update failed');
|
|
vi.mocked(apiClient.patch).mockRejectedValue(mockError);
|
|
|
|
await expect(updateTicketEmailAddress(1, updateData)).rejects.toThrow('Update failed');
|
|
expect(apiClient.patch).toHaveBeenCalledWith('/tickets/email-addresses/1/', updateData);
|
|
});
|
|
});
|
|
|
|
describe('deleteTicketEmailAddress', () => {
|
|
it('should delete a ticket email address', async () => {
|
|
vi.mocked(apiClient.delete).mockResolvedValue({ data: undefined });
|
|
|
|
await deleteTicketEmailAddress(1);
|
|
|
|
expect(apiClient.delete).toHaveBeenCalledWith('/tickets/email-addresses/1/');
|
|
});
|
|
|
|
it('should handle deletion of different IDs', async () => {
|
|
vi.mocked(apiClient.delete).mockResolvedValue({ data: undefined });
|
|
|
|
await deleteTicketEmailAddress(999);
|
|
|
|
expect(apiClient.delete).toHaveBeenCalledWith('/tickets/email-addresses/999/');
|
|
});
|
|
|
|
it('should throw error when deletion fails', async () => {
|
|
const mockError = new Error('Cannot delete default address');
|
|
vi.mocked(apiClient.delete).mockRejectedValue(mockError);
|
|
|
|
await expect(deleteTicketEmailAddress(1)).rejects.toThrow('Cannot delete default address');
|
|
expect(apiClient.delete).toHaveBeenCalledWith('/tickets/email-addresses/1/');
|
|
});
|
|
|
|
it('should throw error when address not found', async () => {
|
|
const mockError = new Error('Not found');
|
|
vi.mocked(apiClient.delete).mockRejectedValue(mockError);
|
|
|
|
await expect(deleteTicketEmailAddress(999)).rejects.toThrow('Not found');
|
|
expect(apiClient.delete).toHaveBeenCalledWith('/tickets/email-addresses/999/');
|
|
});
|
|
});
|
|
|
|
describe('testImapConnection', () => {
|
|
it('should test IMAP connection successfully', async () => {
|
|
const mockResponse: TestConnectionResponse = {
|
|
success: true,
|
|
message: 'IMAP connection successful',
|
|
};
|
|
|
|
vi.mocked(apiClient.post).mockResolvedValue({ data: mockResponse });
|
|
|
|
const result = await testImapConnection(1);
|
|
|
|
expect(apiClient.post).toHaveBeenCalledWith('/tickets/email-addresses/1/test_imap/');
|
|
expect(result).toEqual(mockResponse);
|
|
expect(result.success).toBe(true);
|
|
expect(result.message).toBe('IMAP connection successful');
|
|
});
|
|
|
|
it('should handle failed IMAP connection', async () => {
|
|
const mockResponse: TestConnectionResponse = {
|
|
success: false,
|
|
message: 'Authentication failed: Invalid credentials',
|
|
};
|
|
|
|
vi.mocked(apiClient.post).mockResolvedValue({ data: mockResponse });
|
|
|
|
const result = await testImapConnection(1);
|
|
|
|
expect(apiClient.post).toHaveBeenCalledWith('/tickets/email-addresses/1/test_imap/');
|
|
expect(result.success).toBe(false);
|
|
expect(result.message).toContain('Invalid credentials');
|
|
});
|
|
|
|
it('should handle network errors during IMAP test', async () => {
|
|
const mockError = new Error('Network error');
|
|
vi.mocked(apiClient.post).mockRejectedValue(mockError);
|
|
|
|
await expect(testImapConnection(1)).rejects.toThrow('Network error');
|
|
expect(apiClient.post).toHaveBeenCalledWith('/tickets/email-addresses/1/test_imap/');
|
|
});
|
|
|
|
it('should test IMAP connection for different addresses', async () => {
|
|
const mockResponse: TestConnectionResponse = {
|
|
success: true,
|
|
message: 'IMAP connection successful',
|
|
};
|
|
|
|
vi.mocked(apiClient.post).mockResolvedValue({ data: mockResponse });
|
|
|
|
await testImapConnection(42);
|
|
|
|
expect(apiClient.post).toHaveBeenCalledWith('/tickets/email-addresses/42/test_imap/');
|
|
});
|
|
});
|
|
|
|
describe('testSmtpConnection', () => {
|
|
it('should test SMTP connection successfully', async () => {
|
|
const mockResponse: TestConnectionResponse = {
|
|
success: true,
|
|
message: 'SMTP connection successful',
|
|
};
|
|
|
|
vi.mocked(apiClient.post).mockResolvedValue({ data: mockResponse });
|
|
|
|
const result = await testSmtpConnection(1);
|
|
|
|
expect(apiClient.post).toHaveBeenCalledWith('/tickets/email-addresses/1/test_smtp/');
|
|
expect(result).toEqual(mockResponse);
|
|
expect(result.success).toBe(true);
|
|
expect(result.message).toBe('SMTP connection successful');
|
|
});
|
|
|
|
it('should handle failed SMTP connection', async () => {
|
|
const mockResponse: TestConnectionResponse = {
|
|
success: false,
|
|
message: 'Connection refused: Unable to connect to SMTP server',
|
|
};
|
|
|
|
vi.mocked(apiClient.post).mockResolvedValue({ data: mockResponse });
|
|
|
|
const result = await testSmtpConnection(1);
|
|
|
|
expect(apiClient.post).toHaveBeenCalledWith('/tickets/email-addresses/1/test_smtp/');
|
|
expect(result.success).toBe(false);
|
|
expect(result.message).toContain('Connection refused');
|
|
});
|
|
|
|
it('should handle TLS/SSL errors during SMTP test', async () => {
|
|
const mockResponse: TestConnectionResponse = {
|
|
success: false,
|
|
message: 'SSL certificate verification failed',
|
|
};
|
|
|
|
vi.mocked(apiClient.post).mockResolvedValue({ data: mockResponse });
|
|
|
|
const result = await testSmtpConnection(1);
|
|
|
|
expect(result.success).toBe(false);
|
|
expect(result.message).toContain('SSL certificate');
|
|
});
|
|
|
|
it('should handle network errors during SMTP test', async () => {
|
|
const mockError = new Error('Network error');
|
|
vi.mocked(apiClient.post).mockRejectedValue(mockError);
|
|
|
|
await expect(testSmtpConnection(1)).rejects.toThrow('Network error');
|
|
expect(apiClient.post).toHaveBeenCalledWith('/tickets/email-addresses/1/test_smtp/');
|
|
});
|
|
|
|
it('should test SMTP connection for different addresses', async () => {
|
|
const mockResponse: TestConnectionResponse = {
|
|
success: true,
|
|
message: 'SMTP connection successful',
|
|
};
|
|
|
|
vi.mocked(apiClient.post).mockResolvedValue({ data: mockResponse });
|
|
|
|
await testSmtpConnection(99);
|
|
|
|
expect(apiClient.post).toHaveBeenCalledWith('/tickets/email-addresses/99/test_smtp/');
|
|
});
|
|
});
|
|
|
|
describe('fetchEmailsNow', () => {
|
|
it('should fetch emails successfully', async () => {
|
|
const mockResponse: FetchEmailsResponse = {
|
|
success: true,
|
|
message: 'Successfully processed 5 emails',
|
|
processed: 5,
|
|
errors: 0,
|
|
};
|
|
|
|
vi.mocked(apiClient.post).mockResolvedValue({ data: mockResponse });
|
|
|
|
const result = await fetchEmailsNow(1);
|
|
|
|
expect(apiClient.post).toHaveBeenCalledWith('/tickets/email-addresses/1/fetch_now/');
|
|
expect(result).toEqual(mockResponse);
|
|
expect(result.success).toBe(true);
|
|
expect(result.processed).toBe(5);
|
|
expect(result.errors).toBe(0);
|
|
});
|
|
|
|
it('should handle fetching with no new emails', async () => {
|
|
const mockResponse: FetchEmailsResponse = {
|
|
success: true,
|
|
message: 'No new emails to process',
|
|
processed: 0,
|
|
errors: 0,
|
|
};
|
|
|
|
vi.mocked(apiClient.post).mockResolvedValue({ data: mockResponse });
|
|
|
|
const result = await fetchEmailsNow(1);
|
|
|
|
expect(apiClient.post).toHaveBeenCalledWith('/tickets/email-addresses/1/fetch_now/');
|
|
expect(result.success).toBe(true);
|
|
expect(result.processed).toBe(0);
|
|
});
|
|
|
|
it('should handle errors during email processing', async () => {
|
|
const mockResponse: FetchEmailsResponse = {
|
|
success: false,
|
|
message: 'Failed to connect to IMAP server',
|
|
processed: 0,
|
|
errors: 1,
|
|
};
|
|
|
|
vi.mocked(apiClient.post).mockResolvedValue({ data: mockResponse });
|
|
|
|
const result = await fetchEmailsNow(1);
|
|
|
|
expect(result.success).toBe(false);
|
|
expect(result.errors).toBe(1);
|
|
expect(result.message).toContain('Failed to connect');
|
|
});
|
|
|
|
it('should handle partial processing with errors', async () => {
|
|
const mockResponse: FetchEmailsResponse = {
|
|
success: true,
|
|
message: 'Processed 8 emails with 2 errors',
|
|
processed: 8,
|
|
errors: 2,
|
|
};
|
|
|
|
vi.mocked(apiClient.post).mockResolvedValue({ data: mockResponse });
|
|
|
|
const result = await fetchEmailsNow(1);
|
|
|
|
expect(result.success).toBe(true);
|
|
expect(result.processed).toBe(8);
|
|
expect(result.errors).toBe(2);
|
|
});
|
|
|
|
it('should handle network errors during fetch', async () => {
|
|
const mockError = new Error('Network error');
|
|
vi.mocked(apiClient.post).mockRejectedValue(mockError);
|
|
|
|
await expect(fetchEmailsNow(1)).rejects.toThrow('Network error');
|
|
expect(apiClient.post).toHaveBeenCalledWith('/tickets/email-addresses/1/fetch_now/');
|
|
});
|
|
|
|
it('should fetch emails for different addresses', async () => {
|
|
const mockResponse: FetchEmailsResponse = {
|
|
success: true,
|
|
message: 'Successfully processed 3 emails',
|
|
processed: 3,
|
|
errors: 0,
|
|
};
|
|
|
|
vi.mocked(apiClient.post).mockResolvedValue({ data: mockResponse });
|
|
|
|
await fetchEmailsNow(42);
|
|
|
|
expect(apiClient.post).toHaveBeenCalledWith('/tickets/email-addresses/42/fetch_now/');
|
|
});
|
|
});
|
|
|
|
describe('setAsDefault', () => {
|
|
it('should set email address as default successfully', async () => {
|
|
const mockResponse = {
|
|
success: true,
|
|
message: 'Email address set as default',
|
|
};
|
|
|
|
vi.mocked(apiClient.post).mockResolvedValue({ data: mockResponse });
|
|
|
|
const result = await setAsDefault(2);
|
|
|
|
expect(apiClient.post).toHaveBeenCalledWith('/tickets/email-addresses/2/set_as_default/');
|
|
expect(result).toEqual(mockResponse);
|
|
expect(result.success).toBe(true);
|
|
expect(result.message).toBe('Email address set as default');
|
|
});
|
|
|
|
it('should handle setting default for different addresses', async () => {
|
|
const mockResponse = {
|
|
success: true,
|
|
message: 'Email address set as default',
|
|
};
|
|
|
|
vi.mocked(apiClient.post).mockResolvedValue({ data: mockResponse });
|
|
|
|
await setAsDefault(99);
|
|
|
|
expect(apiClient.post).toHaveBeenCalledWith('/tickets/email-addresses/99/set_as_default/');
|
|
});
|
|
|
|
it('should handle failure to set as default', async () => {
|
|
const mockResponse = {
|
|
success: false,
|
|
message: 'Cannot set inactive email as default',
|
|
};
|
|
|
|
vi.mocked(apiClient.post).mockResolvedValue({ data: mockResponse });
|
|
|
|
const result = await setAsDefault(1);
|
|
|
|
expect(result.success).toBe(false);
|
|
expect(result.message).toContain('Cannot set inactive');
|
|
});
|
|
|
|
it('should handle network errors when setting default', async () => {
|
|
const mockError = new Error('Network error');
|
|
vi.mocked(apiClient.post).mockRejectedValue(mockError);
|
|
|
|
await expect(setAsDefault(1)).rejects.toThrow('Network error');
|
|
expect(apiClient.post).toHaveBeenCalledWith('/tickets/email-addresses/1/set_as_default/');
|
|
});
|
|
|
|
it('should handle not found errors', async () => {
|
|
const mockError = new Error('Email address not found');
|
|
vi.mocked(apiClient.post).mockRejectedValue(mockError);
|
|
|
|
await expect(setAsDefault(999)).rejects.toThrow('Email address not found');
|
|
expect(apiClient.post).toHaveBeenCalledWith('/tickets/email-addresses/999/set_as_default/');
|
|
});
|
|
});
|
|
});
|