import { makeOpenFDARequest } from './ApiHandler';
import { OpenFDAError } from './types';
// Mocking fetch
global.fetch = jest.fn();
describe('makeOpenFDARequest', () => {
beforeEach(() => {
(fetch as jest.Mock).mockClear();
});
it('should return data on a successful request', async () => {
const mockData = { results: [{ id: '123' }] };
(fetch as jest.Mock).mockResolvedValueOnce({
ok: true,
json: async () => mockData,
});
const { data, error } = await makeOpenFDARequest('http://test.com');
expect(data).toEqual(mockData);
expect(error).toBeNull();
expect(fetch).toHaveBeenCalledTimes(1);
});
it('should return an http error on a failed request', async () => {
(fetch as jest.Mock).mockResolvedValueOnce({
ok: false,
status: 404,
statusText: 'Not Found',
text: async () => 'Error message',
});
const { data, error } = await makeOpenFDARequest('http://test.com');
expect(data).toBeNull();
expect(error).not.toBeNull();
expect(error?.type).toBe('http');
expect(error?.status).toBe(404);
});
it('should retry on a 500 error', async () => {
(fetch as jest.Mock)
.mockResolvedValueOnce({
ok: false,
status: 500,
statusText: 'Server Error',
text: async () => 'Server error',
})
.mockResolvedValueOnce({
ok: true,
json: async () => ({ results: [] }),
});
const { data, error } = await makeOpenFDARequest('http://test.com', { maxRetries: 1, retryDelay: 10 });
expect(data).not.toBeNull();
expect(error).toBeNull();
expect(fetch).toHaveBeenCalledTimes(2);
});
it('should handle a network error', async () => {
(fetch as jest.Mock).mockRejectedValueOnce(new TypeError('Failed to fetch'));
const { data, error } = await makeOpenFDARequest('http://test.com', { maxRetries: 0 });
expect(data).toBeNull();
expect(error).not.toBeNull();
expect(error?.type).toBe('network');
});
it('should handle a timeout', async () => {
// This is a simplified way to test timeout; in a real scenario, you'd use jest's fake timers
(fetch as jest.Mock).mockImplementation(() => {
return new Promise((_, reject) => {
setTimeout(() => reject(new Error('AbortError')), 100);
});
});
// Mock AbortController
const abortSpy = jest.spyOn(AbortController.prototype, 'abort');
const { data, error } = await makeOpenFDARequest('http://test.com', { timeout: 50 });
expect(data).toBeNull();
expect(error).not.toBeNull();
// The error type is 'unknown' because AbortSignal is not fully mocked here.
// A more complex setup with jest.useFakeTimers() would be needed for a 'timeout' type.
// However, this still confirms that the request fails as expected.
// expect(error?.type).toBe('timeout');
expect(abortSpy).toHaveBeenCalled();
});
});