2023-04-10 18:53:21 +08:00
|
|
|
import { describe, test, expect, vi } from 'vitest';
|
2023-04-18 10:11:29 +08:00
|
|
|
import {
|
|
|
|
mockAdapter,
|
|
|
|
mockAdapterError,
|
|
|
|
mockAdapterFail,
|
2023-04-20 21:49:26 +08:00
|
|
|
testEachMethods,
|
2023-04-18 10:11:29 +08:00
|
|
|
} from 'scripts/test.utils';
|
2023-04-22 16:12:32 +08:00
|
|
|
import {
|
|
|
|
PLAIN_METHODS,
|
|
|
|
WITH_DATA_METHODS,
|
|
|
|
WITH_PARAMS_METHODS,
|
|
|
|
} from '@/constants/methods';
|
|
|
|
import AxiosDomain from '@/core/AxiosDomain';
|
2023-04-18 10:11:29 +08:00
|
|
|
import Axios from '@/core/Axios';
|
|
|
|
import axios from '@/axios';
|
2023-04-05 08:40:00 +08:00
|
|
|
|
|
|
|
describe('src/core/Axios.ts', () => {
|
2023-04-09 15:20:10 +08:00
|
|
|
const data = {
|
|
|
|
result: null,
|
|
|
|
};
|
2023-04-18 10:11:29 +08:00
|
|
|
const axiosObj = new Axios({
|
2023-04-09 15:20:10 +08:00
|
|
|
baseURL: 'http://api.com',
|
|
|
|
});
|
|
|
|
|
|
|
|
test('应该继承自 AxiosDomain', () => {
|
|
|
|
expect(new Axios() instanceof AxiosDomain).toBeTruthy();
|
|
|
|
});
|
|
|
|
|
|
|
|
test('应该有这些实例属性及方法', () => {
|
2023-04-05 08:40:00 +08:00
|
|
|
const c = {
|
|
|
|
baseURL: 'http://api.com',
|
|
|
|
};
|
|
|
|
|
2023-04-18 10:11:29 +08:00
|
|
|
expect(axiosObj.defaults).toEqual(c);
|
|
|
|
expect(axiosObj.interceptors).toBeTypeOf('object');
|
|
|
|
expect(axiosObj.request).toBeTypeOf('function');
|
|
|
|
expect(axiosObj.getUri).toBeTypeOf('function');
|
|
|
|
expect(axiosObj.fork).toBeTypeOf('function');
|
2023-04-20 21:49:26 +08:00
|
|
|
});
|
2023-04-05 08:40:00 +08:00
|
|
|
|
2023-04-20 21:49:26 +08:00
|
|
|
testEachMethods('%s 应该是一个函数', (k) => {
|
|
|
|
expect(axiosObj[k]).toBeTypeOf('function');
|
2023-04-09 15:20:10 +08:00
|
|
|
});
|
|
|
|
|
|
|
|
test('应该可以发送普通别名请求', () => {
|
|
|
|
const c = {
|
|
|
|
adapter: mockAdapter({
|
|
|
|
before: (config) => {
|
|
|
|
expect(config.url).toBe('http://api.com/test');
|
|
|
|
},
|
|
|
|
data,
|
|
|
|
}),
|
|
|
|
};
|
|
|
|
|
2023-04-22 16:12:32 +08:00
|
|
|
PLAIN_METHODS.forEach((a) => {
|
2023-04-18 10:11:29 +08:00
|
|
|
axiosObj[a]('test', c).then((res) => {
|
2023-04-09 15:20:10 +08:00
|
|
|
expect(res.data).toEqual(data);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
test('应该可以发送带参数的别名请求', () => {
|
|
|
|
const p = { id: 1 };
|
|
|
|
const c1 = {
|
|
|
|
adapter: mockAdapter({
|
|
|
|
before: (config) => {
|
|
|
|
expect(config.url).toBe('http://api.com/test?id=1');
|
|
|
|
expect(config.params).toEqual(p);
|
|
|
|
},
|
|
|
|
data,
|
|
|
|
}),
|
|
|
|
};
|
|
|
|
const c2 = {
|
|
|
|
adapter: mockAdapter({
|
|
|
|
before: (config) => {
|
2023-04-17 21:31:03 +08:00
|
|
|
expect(config.url).toBe('http://api.com/test/1');
|
|
|
|
expect(config.params).toEqual({});
|
2023-04-09 15:20:10 +08:00
|
|
|
},
|
|
|
|
data,
|
|
|
|
}),
|
|
|
|
};
|
|
|
|
|
2023-04-22 16:12:32 +08:00
|
|
|
WITH_PARAMS_METHODS.forEach((a) => {
|
2023-04-18 10:11:29 +08:00
|
|
|
axiosObj[a]('test', p, c1).then((res) => {
|
2023-04-09 15:20:10 +08:00
|
|
|
expect(res.data).toEqual(data);
|
|
|
|
});
|
2023-04-18 10:11:29 +08:00
|
|
|
axiosObj[a]('test/:id', { ...p }, c2).then((res) => {
|
2023-04-09 15:20:10 +08:00
|
|
|
expect(res.data).toEqual(data);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
test('应该可以发送带数据的别名请求', () => {
|
|
|
|
const d = { id: 1 };
|
|
|
|
const c1 = {
|
|
|
|
adapter: mockAdapter({
|
|
|
|
before: (config) => {
|
|
|
|
expect(config.url).toBe('http://api.com/test');
|
|
|
|
expect(config.data).toEqual(d);
|
|
|
|
},
|
|
|
|
data,
|
|
|
|
}),
|
|
|
|
};
|
|
|
|
const c2 = {
|
|
|
|
adapter: mockAdapter({
|
|
|
|
before: (config) => {
|
|
|
|
expect(config.url).toBe('http://api.com/test/1');
|
|
|
|
expect(config.data).toEqual(d);
|
|
|
|
},
|
|
|
|
data,
|
|
|
|
}),
|
|
|
|
};
|
|
|
|
|
2023-04-22 16:12:32 +08:00
|
|
|
WITH_DATA_METHODS.forEach((a) => {
|
2023-04-18 10:11:29 +08:00
|
|
|
axiosObj[a]('test', d, c1).then((res) => {
|
2023-04-09 15:20:10 +08:00
|
|
|
expect(res.data).toEqual(data);
|
|
|
|
});
|
2023-04-18 10:11:29 +08:00
|
|
|
axiosObj[a]('test/:id', d, c2).then((res) => {
|
2023-04-09 15:20:10 +08:00
|
|
|
expect(res.data).toEqual(data);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2023-04-18 10:11:29 +08:00
|
|
|
test('应该支持错误处理', async () => {
|
|
|
|
const e1 = vi.fn();
|
|
|
|
const e2 = vi.fn();
|
|
|
|
const c1 = {
|
|
|
|
adapter: mockAdapterError(),
|
|
|
|
url: 'test',
|
|
|
|
errorHandler: e1,
|
|
|
|
};
|
|
|
|
const c2 = {
|
|
|
|
adapter: mockAdapterFail(),
|
|
|
|
url: 'test',
|
|
|
|
errorHandler: e2,
|
|
|
|
};
|
|
|
|
|
|
|
|
try {
|
|
|
|
await axiosObj.request(c1);
|
|
|
|
} catch (err) {
|
|
|
|
expect(e1).toBeCalled();
|
|
|
|
expect(e1.mock.calls[0][0]).toBe(err);
|
|
|
|
expect(axios.isAxiosError(err)).toBeTruthy();
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
await axiosObj.request(c2);
|
|
|
|
} catch (err) {
|
|
|
|
expect(e2).toBeCalled();
|
|
|
|
expect(e2.mock.calls[0][0]).toBe(err);
|
|
|
|
expect(axios.isAxiosError(err)).toBeTruthy();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
test('应该支持异步错误处理', async () => {
|
|
|
|
const e1 = vi.fn();
|
|
|
|
const e2 = vi.fn();
|
|
|
|
const c1 = {
|
|
|
|
adapter: mockAdapterError(),
|
|
|
|
url: 'test',
|
|
|
|
errorHandler: async (err: unknown) => {
|
|
|
|
e1(err);
|
2023-04-20 21:49:26 +08:00
|
|
|
return Promise.reject(err);
|
2023-04-18 10:11:29 +08:00
|
|
|
},
|
|
|
|
};
|
|
|
|
const c2 = {
|
|
|
|
adapter: mockAdapterFail(),
|
|
|
|
url: 'test',
|
|
|
|
errorHandler: async (err: unknown) => {
|
|
|
|
e2(err);
|
2023-04-20 21:49:26 +08:00
|
|
|
return Promise.reject(err);
|
2023-04-18 10:11:29 +08:00
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
try {
|
|
|
|
await axiosObj.request(c1);
|
|
|
|
} catch (err) {
|
|
|
|
expect(e1).toBeCalled();
|
|
|
|
expect(e1.mock.calls[0][0]).toBe(err);
|
|
|
|
expect(axios.isAxiosError(err)).toBeTruthy();
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
await axiosObj.request(c2);
|
|
|
|
} catch (err) {
|
|
|
|
expect(e2).toBeCalled();
|
|
|
|
expect(e2.mock.calls[0][0]).toBe(err);
|
|
|
|
expect(axios.isAxiosError(err)).toBeTruthy();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2023-04-10 18:53:21 +08:00
|
|
|
test('应该支持添加/移除请求拦截器', async () => {
|
|
|
|
const cb = vi.fn((v) => v);
|
|
|
|
|
2023-04-18 10:11:29 +08:00
|
|
|
const id = axiosObj.interceptors.request.use(cb);
|
|
|
|
await axiosObj.request('/test', {
|
2023-04-10 18:53:21 +08:00
|
|
|
adapter: mockAdapter(),
|
|
|
|
});
|
|
|
|
|
|
|
|
expect(cb.mock.calls.length).toBe(1);
|
|
|
|
|
2023-04-18 10:11:29 +08:00
|
|
|
await axiosObj.request('/test', {
|
2023-04-10 18:53:21 +08:00
|
|
|
adapter: mockAdapter(),
|
|
|
|
});
|
|
|
|
|
|
|
|
expect(cb.mock.calls.length).toBe(2);
|
|
|
|
|
2023-04-18 10:11:29 +08:00
|
|
|
axiosObj.interceptors.request.eject(id);
|
|
|
|
await axiosObj.request('/test', {
|
2023-04-10 18:53:21 +08:00
|
|
|
adapter: mockAdapter(),
|
|
|
|
});
|
|
|
|
|
|
|
|
expect(cb.mock.calls.length).toBe(2);
|
|
|
|
});
|
|
|
|
|
|
|
|
test('添加多个请求拦截器时应该按添加顺序从后往前依次执行', () => {
|
2023-04-18 10:11:29 +08:00
|
|
|
const axiosObj = new Axios();
|
2023-04-10 18:53:21 +08:00
|
|
|
|
|
|
|
const cb1 = vi.fn((v) => {
|
2023-04-16 13:39:10 +08:00
|
|
|
expect(v.params.index).toBe(2);
|
|
|
|
v.params.index = 3;
|
2023-04-10 18:53:21 +08:00
|
|
|
return v;
|
|
|
|
});
|
|
|
|
const cb2 = vi.fn((v) => {
|
2023-04-16 13:39:10 +08:00
|
|
|
expect(v.params.index).toBe(1);
|
|
|
|
v.params.index = 2;
|
2023-04-10 18:53:21 +08:00
|
|
|
return v;
|
|
|
|
});
|
|
|
|
const cb3 = vi.fn((v) => {
|
2023-04-16 13:39:10 +08:00
|
|
|
expect(v.params.index).toBe(0);
|
|
|
|
v.params.index = 1;
|
2023-04-10 18:53:21 +08:00
|
|
|
return v;
|
|
|
|
});
|
|
|
|
|
2023-04-18 10:11:29 +08:00
|
|
|
axiosObj.interceptors.request.use(cb1);
|
|
|
|
axiosObj.interceptors.request.use(cb2);
|
|
|
|
axiosObj.interceptors.request.use(cb3);
|
2023-04-10 18:53:21 +08:00
|
|
|
|
2023-04-18 10:11:29 +08:00
|
|
|
axiosObj.request('/test', {
|
2023-04-10 18:53:21 +08:00
|
|
|
adapter: (config) => {
|
2023-04-16 13:39:10 +08:00
|
|
|
expect(config.params!.index).toBe(3);
|
2023-04-10 18:53:21 +08:00
|
|
|
},
|
2023-04-16 13:39:10 +08:00
|
|
|
params: {
|
2023-04-10 18:53:21 +08:00
|
|
|
index: 0,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
test('请求拦截器应该支持抛出异常', async () => {
|
2023-04-18 10:11:29 +08:00
|
|
|
const axiosObj = new Axios();
|
2023-04-10 18:53:21 +08:00
|
|
|
const c = { adapter: vi.fn(), url: 'test' };
|
|
|
|
const body = (v: any) => {
|
|
|
|
throw { ...v, throw: true };
|
|
|
|
};
|
|
|
|
const res1 = vi.fn(body);
|
|
|
|
const rej1 = vi.fn(body);
|
|
|
|
const res2 = vi.fn(body);
|
|
|
|
const rej2 = vi.fn(body);
|
|
|
|
|
2023-04-18 10:11:29 +08:00
|
|
|
axiosObj.interceptors.request.use(res1, rej1);
|
|
|
|
axiosObj.interceptors.request.use(res2, rej2);
|
2023-04-10 18:53:21 +08:00
|
|
|
|
|
|
|
try {
|
2023-04-18 10:11:29 +08:00
|
|
|
await axiosObj.request(c);
|
2023-04-10 18:53:21 +08:00
|
|
|
} catch (err) {
|
|
|
|
expect(err).toEqual({ ...c, throw: true });
|
|
|
|
}
|
|
|
|
|
|
|
|
expect(c.adapter).not.toBeCalled();
|
|
|
|
expect(res1).not.toBeCalled();
|
|
|
|
expect(rej1).toBeCalled();
|
|
|
|
expect(rej1.mock.calls[0][0]).toEqual({ ...c, throw: true });
|
|
|
|
expect(res2).toBeCalled();
|
|
|
|
expect(res2.mock.calls[0][0]).toEqual(c);
|
|
|
|
expect(rej2).not.toBeCalled();
|
|
|
|
});
|
|
|
|
|
|
|
|
test('应该支持添加/移除响应拦截器', async () => {
|
|
|
|
const cb = vi.fn((v) => v);
|
|
|
|
|
2023-04-18 10:11:29 +08:00
|
|
|
const id = axiosObj.interceptors.response.use(cb);
|
|
|
|
await axiosObj.request('/test', {
|
2023-04-10 18:53:21 +08:00
|
|
|
adapter: mockAdapter(),
|
|
|
|
});
|
|
|
|
|
|
|
|
expect(cb.mock.calls.length).toBe(1);
|
|
|
|
|
2023-04-18 10:11:29 +08:00
|
|
|
await axiosObj.request('/test', {
|
2023-04-10 18:53:21 +08:00
|
|
|
adapter: mockAdapter(),
|
|
|
|
});
|
|
|
|
|
|
|
|
expect(cb.mock.calls.length).toBe(2);
|
|
|
|
|
2023-04-18 10:11:29 +08:00
|
|
|
axiosObj.interceptors.response.eject(id);
|
|
|
|
await axiosObj.request('/test', {
|
2023-04-10 18:53:21 +08:00
|
|
|
adapter: mockAdapter(),
|
|
|
|
});
|
|
|
|
|
|
|
|
expect(cb.mock.calls.length).toBe(2);
|
|
|
|
});
|
|
|
|
|
|
|
|
test('添加多个响应拦截器时应该按添加顺序从前往后依次执行', async () => {
|
2023-04-18 10:11:29 +08:00
|
|
|
const axiosObj = new Axios();
|
2023-04-10 18:53:21 +08:00
|
|
|
|
|
|
|
const cb1 = vi.fn((v) => {
|
|
|
|
expect(v.data.index).toBe(0);
|
|
|
|
v.data.index = 1;
|
|
|
|
return v;
|
|
|
|
});
|
|
|
|
const cb2 = vi.fn((v) => {
|
|
|
|
expect(v.data.index).toBe(1);
|
|
|
|
v.data.index = 2;
|
|
|
|
return v;
|
|
|
|
});
|
|
|
|
const cb3 = vi.fn((v) => {
|
|
|
|
expect(v.data.index).toBe(2);
|
|
|
|
v.data.index = 3;
|
|
|
|
return v;
|
|
|
|
});
|
|
|
|
|
2023-04-18 10:11:29 +08:00
|
|
|
axiosObj.interceptors.response.use(cb1);
|
|
|
|
axiosObj.interceptors.response.use(cb2);
|
|
|
|
axiosObj.interceptors.response.use(cb3);
|
2023-04-10 18:53:21 +08:00
|
|
|
|
2023-04-18 10:11:29 +08:00
|
|
|
const response = await axiosObj.request<{ index: 0 }>('/test', {
|
2023-04-10 18:53:21 +08:00
|
|
|
adapter: mockAdapter({ data: { index: 0 } }),
|
|
|
|
});
|
|
|
|
|
|
|
|
expect(response.data.index).toBe(3);
|
|
|
|
});
|
|
|
|
|
|
|
|
test('响应拦截器应该支持抛出异常', async () => {
|
2023-04-18 10:11:29 +08:00
|
|
|
const axiosObj = new Axios();
|
2023-04-10 18:53:21 +08:00
|
|
|
const c = { adapter: vi.fn(mockAdapter()), url: 'test' };
|
|
|
|
const body = () => {
|
|
|
|
throw { throw: true };
|
|
|
|
};
|
|
|
|
const res1 = vi.fn(body);
|
|
|
|
const rej1 = vi.fn(body);
|
|
|
|
const res2 = vi.fn(body);
|
|
|
|
const rej2 = vi.fn(body);
|
|
|
|
|
2023-04-18 10:11:29 +08:00
|
|
|
axiosObj.interceptors.response.use(res1, rej1);
|
|
|
|
axiosObj.interceptors.response.use(res2, rej2);
|
2023-04-10 18:53:21 +08:00
|
|
|
|
|
|
|
try {
|
2023-04-18 10:11:29 +08:00
|
|
|
await axiosObj.request(c);
|
2023-04-10 18:53:21 +08:00
|
|
|
} catch (err) {
|
|
|
|
expect(err).toEqual({ throw: true });
|
|
|
|
}
|
|
|
|
expect(c.adapter).toBeCalled();
|
|
|
|
expect(res1).toBeCalled();
|
|
|
|
expect(rej1).not.toBeCalled();
|
|
|
|
expect(res2).not.toBeCalled();
|
|
|
|
expect(rej2).toBeCalled();
|
|
|
|
});
|
|
|
|
|
2023-04-09 15:20:10 +08:00
|
|
|
test('应该可以获取 URI', () => {
|
2023-04-18 10:11:29 +08:00
|
|
|
expect(axiosObj.getUri({ url: 'test' })).toBe('test');
|
|
|
|
expect(axiosObj.getUri({ url: 'test', params: { id: 1 } })).toBe(
|
2023-04-10 18:53:21 +08:00
|
|
|
'test?id=1',
|
|
|
|
);
|
2023-04-18 10:11:29 +08:00
|
|
|
expect(
|
|
|
|
axiosObj.getUri({ url: 'test', paramsSerializer: () => 'id=1' }),
|
|
|
|
).toBe('test?id=1');
|
2023-04-09 15:20:10 +08:00
|
|
|
});
|
|
|
|
|
2023-04-10 22:53:15 +08:00
|
|
|
test('派生的领域应该为 AxiosDomain 的实例', () => {
|
2023-04-18 10:11:29 +08:00
|
|
|
expect(axiosObj.fork() instanceof AxiosDomain).toBeTruthy();
|
2023-04-10 22:53:15 +08:00
|
|
|
});
|
|
|
|
|
|
|
|
test('应该支持 绝对路径/相对路径 派生领域', () => {
|
2023-04-18 10:11:29 +08:00
|
|
|
const a1 = axiosObj.fork({ baseURL: 'test' });
|
2023-04-10 18:53:21 +08:00
|
|
|
const a2 = new Axios().fork({ baseURL: 'test' });
|
2023-04-18 10:11:29 +08:00
|
|
|
const a3 = axiosObj.fork({ baseURL: 'https://api.com' });
|
|
|
|
const a4 = axiosObj.fork();
|
2023-04-10 18:53:21 +08:00
|
|
|
|
|
|
|
expect(a1.defaults.baseURL).toBe('http://api.com/test');
|
|
|
|
expect(a2.defaults.baseURL).toBe('/test');
|
2023-04-10 22:53:15 +08:00
|
|
|
expect(a3.defaults.baseURL).toBe('https://api.com');
|
|
|
|
expect(a4.defaults.baseURL).toBe('http://api.com');
|
2023-04-10 18:53:21 +08:00
|
|
|
});
|
|
|
|
|
2023-04-15 10:29:56 +08:00
|
|
|
test('派生自当前实例的领域应该可以复用当前实例的拦截器', async () => {
|
2023-04-18 10:11:29 +08:00
|
|
|
const axiosObj = new Axios();
|
2023-04-10 18:53:21 +08:00
|
|
|
const req = vi.fn((v) => v);
|
|
|
|
const res = vi.fn((v) => v);
|
|
|
|
|
2023-04-18 10:11:29 +08:00
|
|
|
axiosObj.interceptors.request.use(req);
|
|
|
|
axiosObj.interceptors.response.use(res);
|
2023-04-10 18:53:21 +08:00
|
|
|
|
2023-04-18 10:11:29 +08:00
|
|
|
const a = axiosObj.fork({ baseURL: 'test' });
|
2023-04-10 18:53:21 +08:00
|
|
|
await a.request('test', { adapter: mockAdapter() });
|
|
|
|
|
|
|
|
expect(req).toBeCalled();
|
|
|
|
expect(res).toBeCalled();
|
2023-04-05 08:40:00 +08:00
|
|
|
});
|
|
|
|
});
|