Skip to content

Commit

Permalink
feat(测试): 测试并修复完成
Browse files Browse the repository at this point in the history
  • Loading branch information
mengxinssfd committed Apr 19, 2022
1 parent f0524b2 commit 5811c58
Show file tree
Hide file tree
Showing 6 changed files with 185 additions and 32 deletions.
11 changes: 11 additions & 0 deletions __test__/Cache.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,15 @@ describe('Cache', () => {
expect(cache.get(key)).toEqual(null);
expect(cache.has(key)).toBeFalsy();
});
test('遍历删除过期缓存', async () => {
const cache = new Cache<object, object>();
const key = { a: 123 };
cache.set(key, { a: 123 }, { timeout: 200 });

await sleep(300);

cache.set({ b: 123 }, { b: 222 }, { timeout: 200 });
expect(cache.get(key)).toEqual(null);
expect(cache.get({ b: 123 })).toEqual({ b: 222 });
});
});
98 changes: 85 additions & 13 deletions __test__/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,29 @@ import { routers } from './mock-server';
import { StatusHandlers } from '../src/types';

jest.mock('axios');
(axios as any).create.mockReturnValue(
jest.fn(function ({ url, data, params }) {
return (routers[url] || routers['404'])(data || params);
}),
);
const mockCreate = (/*config: AxiosRequestConfig*/) => {
// console.log(config);
return function ({ url, data, params, method }) {
return (routers[url] || routers['404'])(data || params, method);
};
};

(axios as any).create.mockImplementation(mockCreate);

describe('AxiosWrapper', () => {
const statusHandlers: StatusHandlers = {
200: (res, data, customConfig) => {
return customConfig.returnRes ? res : data;
},
};
const req = new AxiosWrapper({}, { statusHandlers });
const req = new AxiosWrapper({ baseURL: '/' }, { statusHandlers });
const get = AxiosWrapper.methodFactory('get', req);
const post = AxiosWrapper.methodFactory('post', req);

test('base', async () => {
// console.log((axios.create({ url: 'test' }) as any)(1, 2, 3), Req);
const res = await get<{ username: string; id: number }>('/user');
expect(res).toEqual({ code: 200, data: { username: 'test', id: 1 }, msg: 'success' });
expect(res).toEqual({ code: 200, data: { username: 'get', id: 1 }, msg: 'success' });

const res2 = await get<{ username: string; id: number }, true>(
'/user',
Expand All @@ -32,7 +35,7 @@ describe('AxiosWrapper', () => {
);
expect(res2).toEqual({
status: 200,
data: { code: 200, data: { username: 'test', id: 1 }, msg: 'success' },
data: { code: 200, data: { username: 'get', id: 1 }, msg: 'success' },
});

const res3 = await post('/login', { username: 'foo', password: 'bar' });
Expand All @@ -46,27 +49,96 @@ describe('AxiosWrapper', () => {
});
test('no cache', async () => {
const res = await get<{ username: string; id: number }>('/user');
expect(res).toEqual({ code: 200, data: { username: 'test', id: 1 }, msg: 'success' });
expect(res).toEqual({ code: 200, data: { username: 'get', id: 1 }, msg: 'success' });
const res2 = await get<{ username: string; id: number }>('/user');
expect(res2).toEqual(res);
expect(res2).not.toBe(res);
});
test('cache', async () => {
const res = await get<{ username: string; id: number }>('/user', undefined, { useCache: true });
expect(res).toEqual({ code: 200, data: { username: 'test', id: 1 }, msg: 'success' });
expect(res).toEqual({ code: 200, data: { username: 'get', id: 1 }, msg: 'success' });
const res2 = await get<{ username: string; id: number }>('/user', undefined, {
useCache: true,
useCache: { timeout: 1000 },
});
expect(res2).toEqual(res);
expect(res2).toBe(res);
});
test('serve error', async () => {
test('serve 404', async () => {
try {
await get<{ username: string; id: number }>('/test');
await get('/test');
} catch (e) {
expect(e).toBe('404');
}
const res = await post<{ username: string; id: number }>('/test', { returnRes: 1 });
expect(res).toEqual({ code: 200 });
});
test('default constructor params', async () => {
const req = new AxiosWrapper();
const get = AxiosWrapper.methodFactory('get', req);
const res = await get<{ username: string; id: number }>(
'/user',
{},
{
statusHandlers: { '200': (res) => res },
},
);
expect(res).toEqual({
data: { code: 200, data: { username: 'get', id: 1 }, msg: 'success' },
status: 200,
});
// 不传method时默认为get
const defGet = AxiosWrapper.methodFactory(undefined as any, req);
const res1 = await defGet<{ username: string; id: number }>(
'/user',
{},
{
statusHandlers: { '200': (res) => res },
},
// 改为post,无效;
// methodFactory优先级更高,除了method,url,data其他的axios配置优先级都是这里的高
{ method: 'post' },
);
expect(res1).toEqual({
data: { code: 200, data: { username: 'get', id: 1 }, msg: 'success' },
status: 200,
});

// 不传method时默认为get
const res2 = await req.request<{ username: string; id: number }>(
'/user',
{},
{
statusHandlers: { '200': (res) => res },
},
);
expect(res2).toEqual({
data: { code: 200, data: { username: 'get', id: 1 }, msg: 'success' },
status: 200,
});

const res3 = await req.request<{ username: string; id: number }>(
'/user',
{},
{
statusHandlers: { '200': (res) => res },
},
{ method: 'post' },
);
expect(res3).toEqual({
data: { code: 200, data: { username: 'post', id: 2 }, msg: 'success' },
status: 200,
});
});
test('nocode', async () => {
try {
await get('/nocode');
} catch (e) {
expect(e).toBe('1');
}
try {
await get('/nocode', {}, { returnRes: true });
} catch (e) {
expect(e).toEqual({ data: '1', status: 200 });
}
});
});
10 changes: 8 additions & 2 deletions __test__/mock-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@ function buildRes(res: { code: number; data?: any; msg: string }) {
}

export const routers = {
'/user'() {
return buildRes({ code: 200, data: { username: 'test', id: 1 }, msg: 'success' });
'/user'(data: any, method: string) {
if (method === 'post') {
return buildRes({ code: 200, data: { username: 'post', id: 2 }, msg: 'success' });
}
return buildRes({ code: 200, data: { username: 'get', id: 1 }, msg: 'success' });
},
'/login'(data: string) {
const d: any = Qs.parse(data);
Expand All @@ -21,4 +24,7 @@ export const routers = {
}
return Promise.reject('404');
},
'/nocode'() {
return Promise.resolve({ status: 200, data: '1' });
},
};
56 changes: 56 additions & 0 deletions __test__/primary.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import axios, { AxiosRequestConfig } from 'axios';
import { routers } from './mock-server';

jest.mock('axios');
const mockCreate = (config: AxiosRequestConfig) => {
type InterceptorCB = (config: AxiosRequestConfig) => AxiosRequestConfig | void;
const interceptors = {
request: [] as InterceptorCB[],
};
function AxiosIns({ url, data, params }) {
const cfg = interceptors.request.reduce((prev, cur) => {
return cur(config) || config;
}, config);
if (cfg) Object.assign(config, cfg);
return (routers[url] || routers['404'])(data || params);
}
AxiosIns.interceptors = {
request: {
use: (cb: InterceptorCB) => {
interceptors.request.push(cb);
},
},
};
return AxiosIns;
};

(axios as any).create.mockImplementation(mockCreate);
import Primary from './primary';

describe('Primary', () => {
const { get, post } = Primary;

test('base', async () => {
const res = await get<{ username: string; id: number }>('/user');
expect(res).toEqual({ code: 200, data: { username: 'get', id: 1 }, msg: 'success' });

const res2 = await get<{ username: string; id: number }, true>(
'/user',
{},
{ returnRes: true },
);
expect(res2).toEqual({
status: 200,
data: { code: 200, data: { username: 'get', id: 1 }, msg: 'success' },
});

const res3 = await post('/login', { username: 'foo', password: 'bar' });
expect(res3).toEqual({ code: 200, msg: 'success' });

try {
await post('/login', { username: 'foo' });
} catch (e) {
expect(e).toEqual({ code: 0, msg: '账号或密码错误' });
}
});
});
22 changes: 17 additions & 5 deletions __test__/primary.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// 主域名请求
import { StatusHandlers } from '../src/types';
import AxiosWrapper from '../src';

Expand All @@ -6,11 +7,22 @@ const statusHandlers: StatusHandlers = {
return customConfig.returnRes ? res : data;
},
};
export class Req extends AxiosWrapper {
static readonly ins = new Req();
static readonly get = AxiosWrapper.methodFactory('get', Req.ins);
static readonly post = AxiosWrapper.methodFactory('post', Req.ins);
constructor() {
export default class Primary extends AxiosWrapper {
static readonly ins = new Primary();
static readonly get = AxiosWrapper.methodFactory('get', Primary.ins);
static readonly post = AxiosWrapper.methodFactory('post', Primary.ins);

private constructor() {
super({ baseURL: 'http://test.test' }, { statusHandlers });
}

protected setInterceptors() {
this.interceptors.request.use((config) => {
if (!config.headers) config.headers = {};
const headers = config.headers;
// Token.exists() && (headers.authorization = `Bearer ${Token.get()}`);
headers.authorization = `Bearer 123123123123123123`;
// headers.uuid = getUUID();
});
}
}
20 changes: 8 additions & 12 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import Cache from './Cache';
export default class AxiosWrapper {
private readonly axios: AxiosInstance;
private readonly cache: Cache<AxiosRequestConfig, AxiosPromise>;
constructor(config: AxiosRequestConfig = {}, private customConfig: CustomConfig<boolean>) {
constructor(config: AxiosRequestConfig = {}, private customConfig: CustomConfig<boolean> = {}) {
// 1、保存基础配置
this.axios = axios.create(config);
this.setInterceptors();
Expand Down Expand Up @@ -63,7 +63,7 @@ export default class AxiosWrapper {
data: ResType<any>,
customConfig: CustomConfig<boolean>,
): Promise<ResType<T>> {
const code = data.code ?? 'default';
const code = data?.code ?? 'default';
const handlers = {
default: (res, data, customConfig) => Promise.reject(customConfig.returnRes ? res : data),
...this.customConfig.statusHandlers,
Expand All @@ -74,7 +74,7 @@ export default class AxiosWrapper {
return statusHandler(res, data, customConfig as CustomConfig);
}

private _request(customConfig: CustomConfig = {}, axiosConfig: AxiosRequestConfig = {}) {
private _request(customConfig: CustomConfig, axiosConfig: AxiosRequestConfig) {
if (customConfig.useCache) {
const c = this.cache.get(axiosConfig);
if (c) {
Expand All @@ -85,11 +85,7 @@ export default class AxiosWrapper {

const useCache = customConfig.useCache;
if (useCache) {
this.cache.set(
axiosConfig,
res,
useCache === true ? undefined : { timeout: useCache.timeout },
);
this.cache.set(axiosConfig, res, typeof useCache === 'object' ? useCache : undefined);
}

return res;
Expand All @@ -98,7 +94,7 @@ export default class AxiosWrapper {
request<T = never>(url: string, data?: {}): Promise<ResType<T>>;
request<T = never, RC extends boolean = false>(
url: string,
data: {},
data?: {},
customConfig?: CustomConfig<RC>,
axiosConfig?: AxiosRequestConfig,
): Promise<RC extends true ? AxiosResponse<ResType<T>> : ResType<T>>;
Expand Down Expand Up @@ -133,9 +129,9 @@ export default class AxiosWrapper {
static methodFactory(method: Method, ins: AxiosWrapper) {
return function <T = never, RC extends boolean = false>(
url: string,
data = {},
customConfig: CustomConfig<RC> = {},
axiosConfig: AxiosRequestConfig = {},
data?: {},
customConfig?: CustomConfig<RC>,
axiosConfig?: AxiosRequestConfig,
) {
return ins.request<T, RC>(url, data, customConfig, { ...axiosConfig, method });
};
Expand Down

0 comments on commit 5811c58

Please sign in to comment.