test: 测试 generateType
parent
0cfb3e1ff0
commit
ce12a83873
|
@ -1,3 +1,5 @@
|
|||
import { AxiosAdapterRequestConfig } from 'src';
|
||||
|
||||
export function asyncNext() {
|
||||
return Promise.resolve().then;
|
||||
}
|
||||
|
@ -47,3 +49,38 @@ export function mockSuccess(headers: AnyObject = {}, data: AnyObject = {}) {
|
|||
export function mockFail(headers: AnyObject = {}, data: AnyObject = {}) {
|
||||
return mockResponse(400, 'FAIL', headers, data);
|
||||
}
|
||||
|
||||
export interface MockAdapterOptions {
|
||||
headers?: AnyObject;
|
||||
data?: AnyObject;
|
||||
delay?: number;
|
||||
before?: (config: AxiosAdapterRequestConfig) => void;
|
||||
after?: () => void;
|
||||
}
|
||||
|
||||
export function mockAdapter(
|
||||
type: 'success' | 'fail',
|
||||
options: MockAdapterOptions = {},
|
||||
) {
|
||||
const { headers = {}, data = {}, delay = 0, before, after } = options;
|
||||
|
||||
return (config: AxiosAdapterRequestConfig) => {
|
||||
before?.(config);
|
||||
setTimeout(() => {
|
||||
if (type === 'success') {
|
||||
config.success(mockSuccess(headers, data));
|
||||
} else {
|
||||
config.fail(mockFail(headers, data));
|
||||
}
|
||||
after?.();
|
||||
}, delay);
|
||||
};
|
||||
}
|
||||
|
||||
export function mockAdapterSuccess(options: MockAdapterOptions = {}) {
|
||||
return mockAdapter('success', options);
|
||||
}
|
||||
|
||||
export function mockAdapterFail(options: MockAdapterOptions = {}) {
|
||||
return mockAdapter('fail', options);
|
||||
}
|
||||
|
|
|
@ -138,6 +138,10 @@ export interface AxiosConstructor {
|
|||
}
|
||||
|
||||
export default class Axios {
|
||||
public static as = ['options', 'trace', 'connect'] as const;
|
||||
public static pas = ['head', 'get', 'delete'] as const;
|
||||
public static das = ['post', 'put'] as const;
|
||||
|
||||
public defaults: AxiosRequestConfig;
|
||||
|
||||
public interceptors = {
|
||||
|
@ -145,8 +149,71 @@ export default class Axios {
|
|||
response: new InterceptorManager<AxiosResponse>(),
|
||||
};
|
||||
|
||||
public options!: <TData = unknown>(
|
||||
url: string,
|
||||
config?: AxiosRequestConfig,
|
||||
) => Promise<AxiosResponse<TData>>;
|
||||
|
||||
public get!: <TData = unknown>(
|
||||
url: string,
|
||||
params?: AnyObject,
|
||||
config?: AxiosRequestConfig,
|
||||
) => Promise<AxiosResponse<TData>>;
|
||||
|
||||
public head!: <TData = unknown>(
|
||||
url: string,
|
||||
params?: AnyObject,
|
||||
config?: AxiosRequestConfig,
|
||||
) => Promise<AxiosResponse<TData>>;
|
||||
|
||||
public post!: <TData = unknown>(
|
||||
url: string,
|
||||
data?: AnyObject | AxiosRequestFormData,
|
||||
config?: AxiosRequestConfig,
|
||||
) => Promise<AxiosResponse<TData>>;
|
||||
|
||||
public put!: <TData = unknown>(
|
||||
url: string,
|
||||
data?: AnyObject | AxiosRequestFormData,
|
||||
config?: AxiosRequestConfig,
|
||||
) => Promise<AxiosResponse<TData>>;
|
||||
|
||||
public delete!: <TData = unknown>(
|
||||
url: string,
|
||||
params?: AnyObject,
|
||||
config?: AxiosRequestConfig,
|
||||
) => Promise<AxiosResponse<TData>>;
|
||||
|
||||
public trace!: <TData = unknown>(
|
||||
url: string,
|
||||
config?: AxiosRequestConfig,
|
||||
) => Promise<AxiosResponse<TData>>;
|
||||
|
||||
public connect!: <TData = unknown>(
|
||||
url: string,
|
||||
config?: AxiosRequestConfig,
|
||||
) => Promise<AxiosResponse<TData>>;
|
||||
|
||||
public constructor(defaults: AxiosRequestConfig = {}) {
|
||||
this.defaults = defaults;
|
||||
|
||||
for (const alias of Axios.as) {
|
||||
this[alias] = (url, config) => {
|
||||
return this._req(alias, url, undefined, config);
|
||||
};
|
||||
}
|
||||
|
||||
for (const alias of Axios.pas) {
|
||||
this[alias] = (url, params, config) => {
|
||||
return this._req(alias, url, params, config);
|
||||
};
|
||||
}
|
||||
|
||||
for (const alias of Axios.das) {
|
||||
this[alias] = (url, data, config) => {
|
||||
return this._reqWithData(alias, url, data, config);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public getUri(config: AxiosRequestConfig): string {
|
||||
|
@ -183,67 +250,6 @@ export default class Axios {
|
|||
return promiseResponse as Promise<AxiosResponse<TData>>;
|
||||
}
|
||||
|
||||
public options<TData = unknown>(
|
||||
url: string,
|
||||
config?: AxiosRequestConfig,
|
||||
): Promise<AxiosResponse<TData>> {
|
||||
return this._req<TData>('options', url, undefined, config);
|
||||
}
|
||||
|
||||
public get<TData = unknown>(
|
||||
url: string,
|
||||
params?: AnyObject,
|
||||
config?: AxiosRequestConfig,
|
||||
): Promise<AxiosResponse<TData>> {
|
||||
return this._req<TData>('get', url, params, config);
|
||||
}
|
||||
|
||||
public head<TData = unknown>(
|
||||
url: string,
|
||||
params?: AnyObject,
|
||||
config?: AxiosRequestConfig,
|
||||
): Promise<AxiosResponse<TData>> {
|
||||
return this._req<TData>('head', url, params, config);
|
||||
}
|
||||
|
||||
public post<TData = unknown>(
|
||||
url: string,
|
||||
data?: AnyObject | AxiosRequestFormData,
|
||||
config?: AxiosRequestConfig,
|
||||
): Promise<AxiosResponse<TData>> {
|
||||
return this._reqWithData<TData>('post', url, data, config);
|
||||
}
|
||||
|
||||
public put<TData = unknown>(
|
||||
url: string,
|
||||
data?: AnyObject | AxiosRequestFormData,
|
||||
config?: AxiosRequestConfig,
|
||||
): Promise<AxiosResponse<TData>> {
|
||||
return this._reqWithData<TData>('put', url, data, config);
|
||||
}
|
||||
|
||||
public delete<TData = unknown>(
|
||||
url: string,
|
||||
params?: AnyObject,
|
||||
config?: AxiosRequestConfig,
|
||||
): Promise<AxiosResponse<TData>> {
|
||||
return this._req<TData>('delete', url, params, config);
|
||||
}
|
||||
|
||||
public trace<TData = unknown>(
|
||||
url: string,
|
||||
config?: AxiosRequestConfig,
|
||||
): Promise<AxiosResponse<TData>> {
|
||||
return this._req<TData>('trace', url, undefined, config);
|
||||
}
|
||||
|
||||
public connect<TData = unknown>(
|
||||
url: string,
|
||||
config?: AxiosRequestConfig,
|
||||
): Promise<AxiosResponse<TData>> {
|
||||
return this._req<TData>('connect', url, undefined, config);
|
||||
}
|
||||
|
||||
private _req<TData = unknown>(
|
||||
method: AxiosRequestMethod,
|
||||
url: string,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { isPlainObject } from '../helpers/isTypes';
|
||||
import { isCancel } from './cancel';
|
||||
import { isCancel, isCancelToken } from './cancel';
|
||||
import { flattenHeaders } from './flattenHeaders';
|
||||
import { transformData } from './transformData';
|
||||
import { request } from './request';
|
||||
|
@ -7,8 +7,9 @@ import { AxiosRequestConfig, AxiosResponse } from './Axios';
|
|||
import { transformURL } from './transformURL';
|
||||
|
||||
function throwIfCancellationRequested(config: AxiosRequestConfig) {
|
||||
if (config.cancelToken) {
|
||||
config.cancelToken.throwIfRequested();
|
||||
const { cancelToken } = config;
|
||||
if (isCancelToken(cancelToken)) {
|
||||
cancelToken.throwIfRequested();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ export function request<TData = unknown>(
|
|||
fail,
|
||||
};
|
||||
|
||||
const adapterTask = config.adapter?.(adapterConfig) as
|
||||
const adapterTask = config.adapter!(adapterConfig) as
|
||||
| AxiosAdapterTask
|
||||
| undefined;
|
||||
|
||||
|
@ -83,8 +83,9 @@ export function request<TData = unknown>(
|
|||
tryToggleProgressUpdate(adapterConfig, adapterTask.onProgressUpdate);
|
||||
}
|
||||
|
||||
if (isCancelToken(config.cancelToken)) {
|
||||
config.cancelToken.onCancel((reason: unknown) => {
|
||||
const { cancelToken } = config;
|
||||
if (isCancelToken(cancelToken)) {
|
||||
cancelToken.onCancel((reason) => {
|
||||
if (isPlainObject(adapterTask)) {
|
||||
tryToggleProgressUpdate(adapterConfig, adapterTask.offProgressUpdate);
|
||||
|
||||
|
|
|
@ -13,9 +13,8 @@ export function throwError(msg: string): void {
|
|||
export function cleanStack(error: Error) {
|
||||
if (error.stack) {
|
||||
const start = error.stack.indexOf('at');
|
||||
const end = error.stack.indexOf('at /');
|
||||
|
||||
if (start !== end) {
|
||||
const end = error.stack.search(/at ([\w-_.]+:)?\//i);
|
||||
if (start < end) {
|
||||
const removed = error.stack.slice(start, end);
|
||||
error.stack = error.stack.replace(removed, '');
|
||||
}
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
import { describe, test, expect } from 'vitest';
|
||||
import axios from 'src/axios';
|
||||
import { mockAdapterFail, mockAdapterSuccess } from 'scripts/test.utils';
|
||||
|
||||
describe('src/axios.ts', () => {
|
||||
test('应该处理成功和失败', () => {
|
||||
axios({
|
||||
adapter: mockAdapterSuccess({
|
||||
headers: { type: 'json' },
|
||||
data: { v1: 1 },
|
||||
before: (config) => {
|
||||
expect(config.url).toBe('http://api.com/user/1?id=1');
|
||||
},
|
||||
}),
|
||||
baseURL: 'http://api.com',
|
||||
url: 'user/:id',
|
||||
params: {
|
||||
id: 1,
|
||||
},
|
||||
}).then((response) => {
|
||||
expect(response.headers).toEqual({ type: 'json' });
|
||||
expect(response.data).toEqual({ v1: 1 });
|
||||
});
|
||||
|
||||
axios('user/:id', {
|
||||
adapter: mockAdapterFail({
|
||||
headers: { type: 'json' },
|
||||
data: { v1: 1 },
|
||||
before: (config) => {
|
||||
expect(config.url).toBe('http://api.com/user/1');
|
||||
},
|
||||
}),
|
||||
baseURL: 'http://api.com',
|
||||
data: {
|
||||
id: 1,
|
||||
},
|
||||
}).catch((error) => {
|
||||
expect(error.response.headers).toEqual({ type: 'json' });
|
||||
expect(error.response.data).toEqual({ v1: 1 });
|
||||
});
|
||||
});
|
||||
});
|
|
@ -2,12 +2,17 @@ import { describe, test, expect, vi } from 'vitest';
|
|||
import {
|
||||
asyncNext,
|
||||
captureError,
|
||||
mockSuccess,
|
||||
mockAdapterSuccess,
|
||||
noop,
|
||||
asyncTimeout,
|
||||
} from 'scripts/test.utils';
|
||||
import axios from 'src/axios';
|
||||
import { Cancel, isCancel, CancelToken, isCancelToken } from 'src/core/cancel';
|
||||
import {
|
||||
Cancel,
|
||||
isCancel,
|
||||
CancelToken,
|
||||
isCancelToken,
|
||||
} from '../../src/core/cancel';
|
||||
|
||||
describe('src/helpers/cancel.ts', () => {
|
||||
test('应该支持空参数', () => {
|
||||
|
@ -100,7 +105,7 @@ describe('src/helpers/cancel.ts', () => {
|
|||
|
||||
source.cancel();
|
||||
axios({
|
||||
adapter: ({ success }) => success(mockSuccess()),
|
||||
adapter: mockAdapterSuccess(),
|
||||
cancelToken: source.token,
|
||||
}).catch(canceled);
|
||||
|
||||
|
@ -114,7 +119,7 @@ describe('src/helpers/cancel.ts', () => {
|
|||
const source = CancelToken.source();
|
||||
|
||||
axios({
|
||||
adapter: ({ success }) => success(mockSuccess()),
|
||||
adapter: mockAdapterSuccess(),
|
||||
cancelToken: source.token,
|
||||
}).catch(canceled);
|
||||
source.cancel();
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
import { describe, test, expect } from 'vitest';
|
||||
import { mockAdapterSuccess } from 'scripts/test.utils';
|
||||
import { generateType } from 'src/core/generateType';
|
||||
import Axios from 'src/core/Axios';
|
||||
import axios from 'src/axios';
|
||||
|
||||
describe('src/core/generateType.ts', () => {
|
||||
test('应该是一个 reuqest', () => {
|
||||
for (const alias of [...Axios.as, ...Axios.pas, ...Axios.das]) {
|
||||
expect(generateType({ method: alias })).toBe('request');
|
||||
|
||||
axios({
|
||||
adapter: mockAdapterSuccess({
|
||||
before: (config) => {
|
||||
expect(config.type).toBe('request');
|
||||
},
|
||||
}),
|
||||
method: alias,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
test('应该是一个 upload', () => {
|
||||
expect(generateType({ method: 'post', upload: true })).toBe('upload');
|
||||
|
||||
axios({
|
||||
adapter: mockAdapterSuccess({
|
||||
before: (config) => {
|
||||
expect(config.type).toBe('upload');
|
||||
},
|
||||
}),
|
||||
method: 'post',
|
||||
upload: true,
|
||||
});
|
||||
});
|
||||
|
||||
test('应该是一个 download', () => {
|
||||
expect(generateType({ method: 'get', download: true })).toBe('download');
|
||||
|
||||
axios({
|
||||
adapter: mockAdapterSuccess({
|
||||
before: (config) => {
|
||||
expect(config.type).toBe('download');
|
||||
},
|
||||
}),
|
||||
method: 'get',
|
||||
download: true,
|
||||
});
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue