@dbs-portal/core-api
Version:
HTTP client and API utilities for DBS Portal
188 lines • 7.04 kB
JavaScript
/**
* Tests for the Axios-based HTTP client
*/
import { describe, it, expect, beforeEach, vi } from 'vitest';
import axios from 'axios';
import { HttpClient } from '../client/http-client';
// Mock axios
vi.mock('axios');
const mockedAxios = vi.mocked(axios);
describe('HttpClient', () => {
let httpClient;
let mockAxiosInstance;
beforeEach(() => {
mockAxiosInstance = {
request: vi.fn(),
interceptors: {
request: { use: vi.fn(), eject: vi.fn() },
response: { use: vi.fn(), eject: vi.fn() },
},
};
vi.mock('axios');
const mockedAxios = vi.mocked(axios, true);
mockedAxios.create.mockReturnValue(mockAxiosInstance);
httpClient = new HttpClient();
});
describe('constructor', () => {
it('should create axios instance with default config', () => {
expect(mockedAxios.create).toHaveBeenCalledWith({
timeout: 30000,
responseType: 'json',
validateStatus: expect.any(Function),
});
});
it('should create axios instance with custom config', () => {
const config = {
timeout: 5000,
baseURL: 'https://api.example.com',
headers: { Authorization: 'Bearer token' },
};
new HttpClient(config);
expect(mockedAxios.create).toHaveBeenCalledWith(expect.objectContaining({
timeout: 5000,
baseURL: 'https://api.example.com',
headers: { Authorization: 'Bearer token' },
}));
});
});
describe('request', () => {
it('should make a successful request', async () => {
const mockResponse = {
data: { message: 'success' },
status: 200,
statusText: 'OK',
headers: { 'content-type': 'application/json' },
config: {},
request: {},
};
mockAxiosInstance.request.mockResolvedValue(mockResponse);
const result = await httpClient.request({
url: '/test',
method: 'GET',
});
expect(result).toEqual({
data: { message: 'success' },
status: 200,
statusText: 'OK',
headers: { 'content-type': 'application/json' },
config: {},
request: {},
});
});
it('should handle axios errors', async () => {
const axiosError = {
message: 'Network Error',
code: 'NETWORK_ERROR',
config: {},
request: {},
response: {
data: { error: 'Not found' },
status: 404,
statusText: 'Not Found',
headers: {},
config: {},
request: {},
},
isAxiosError: true,
};
mockAxiosInstance.request.mockRejectedValue(axiosError);
await expect(httpClient.request({ url: '/test', method: 'GET' })).rejects.toMatchObject({
message: 'Network Error',
code: 'NETWORK_ERROR',
isAxiosError: true,
});
});
it('should map arrayBuffer responseType to arraybuffer', async () => {
const mockResponse = {
data: new ArrayBuffer(8),
status: 200,
statusText: 'OK',
headers: {},
config: {},
request: {},
};
mockAxiosInstance.request.mockResolvedValue(mockResponse);
await httpClient.request({
url: '/test',
method: 'GET',
responseType: 'arrayBuffer',
});
expect(mockAxiosInstance.request).toHaveBeenCalledWith(expect.objectContaining({
responseType: 'arraybuffer',
}));
});
});
describe('HTTP methods', () => {
beforeEach(() => {
vi.spyOn(httpClient, 'request').mockResolvedValue({
data: {},
status: 200,
statusText: 'OK',
headers: {},
config: {},
request: {},
});
});
it('should make GET request', async () => {
await httpClient.get('/test');
expect(httpClient.request).toHaveBeenCalledWith({
url: '/test',
method: 'GET',
});
});
it('should make POST request with data', async () => {
const data = { name: 'test' };
await httpClient.post('/test', data);
expect(httpClient.request).toHaveBeenCalledWith({
url: '/test',
method: 'POST',
data,
});
});
it('should make PUT request with data', async () => {
const data = { name: 'updated' };
await httpClient.put('/test', data);
expect(httpClient.request).toHaveBeenCalledWith({
url: '/test',
method: 'PUT',
data,
});
});
it('should make DELETE request', async () => {
await httpClient.delete('/test');
expect(httpClient.request).toHaveBeenCalledWith({
url: '/test',
method: 'DELETE',
});
});
});
describe('interceptors', () => {
it('should add request interceptor', () => {
const onFulfilled = vi.fn();
const onRejected = vi.fn();
httpClient.addRequestInterceptor(onFulfilled, onRejected);
expect(mockAxiosInstance.interceptors.request.use).toHaveBeenCalledWith(onFulfilled, onRejected);
});
it('should add response interceptor', () => {
const onFulfilled = vi.fn();
const onRejected = vi.fn();
httpClient.addResponseInterceptor(onFulfilled, onRejected);
expect(mockAxiosInstance.interceptors.response.use).toHaveBeenCalledWith(onFulfilled, onRejected);
});
it('should remove request interceptor', () => {
httpClient.removeRequestInterceptor(1);
expect(mockAxiosInstance.interceptors.request.eject).toHaveBeenCalledWith(1);
});
it('should remove response interceptor', () => {
httpClient.removeResponseInterceptor(1);
expect(mockAxiosInstance.interceptors.response.eject).toHaveBeenCalledWith(1);
});
});
describe('getAxiosInstance', () => {
it('should return the underlying axios instance', () => {
const instance = httpClient.getAxiosInstance();
expect(instance).toBe(mockAxiosInstance);
});
});
});
//# sourceMappingURL=http-client.test.js.map