test: 测试 generateType
parent
0cfb3e1ff0
commit
ce12a83873
|
@ -1,3 +1,5 @@
|
||||||
|
import { AxiosAdapterRequestConfig } from 'src';
|
||||||
|
|
||||||
export function asyncNext() {
|
export function asyncNext() {
|
||||||
return Promise.resolve().then;
|
return Promise.resolve().then;
|
||||||
}
|
}
|
||||||
|
@ -47,3 +49,38 @@ export function mockSuccess(headers: AnyObject = {}, data: AnyObject = {}) {
|
||||||
export function mockFail(headers: AnyObject = {}, data: AnyObject = {}) {
|
export function mockFail(headers: AnyObject = {}, data: AnyObject = {}) {
|
||||||
return mockResponse(400, 'FAIL', headers, data);
|
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 {
|
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 defaults: AxiosRequestConfig;
|
||||||
|
|
||||||
public interceptors = {
|
public interceptors = {
|
||||||
|
@ -145,8 +149,71 @@ export default class Axios {
|
||||||
response: new InterceptorManager<AxiosResponse>(),
|
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 = {}) {
|
public constructor(defaults: AxiosRequestConfig = {}) {
|
||||||
this.defaults = defaults;
|
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 {
|
public getUri(config: AxiosRequestConfig): string {
|
||||||
|
@ -183,67 +250,6 @@ export default class Axios {
|
||||||
return promiseResponse as Promise<AxiosResponse<TData>>;
|
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>(
|
private _req<TData = unknown>(
|
||||||
method: AxiosRequestMethod,
|
method: AxiosRequestMethod,
|
||||||
url: string,
|
url: string,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { isPlainObject } from '../helpers/isTypes';
|
import { isPlainObject } from '../helpers/isTypes';
|
||||||
import { isCancel } from './cancel';
|
import { isCancel, isCancelToken } from './cancel';
|
||||||
import { flattenHeaders } from './flattenHeaders';
|
import { flattenHeaders } from './flattenHeaders';
|
||||||
import { transformData } from './transformData';
|
import { transformData } from './transformData';
|
||||||
import { request } from './request';
|
import { request } from './request';
|
||||||
|
@ -7,8 +7,9 @@ import { AxiosRequestConfig, AxiosResponse } from './Axios';
|
||||||
import { transformURL } from './transformURL';
|
import { transformURL } from './transformURL';
|
||||||
|
|
||||||
function throwIfCancellationRequested(config: AxiosRequestConfig) {
|
function throwIfCancellationRequested(config: AxiosRequestConfig) {
|
||||||
if (config.cancelToken) {
|
const { cancelToken } = config;
|
||||||
config.cancelToken.throwIfRequested();
|
if (isCancelToken(cancelToken)) {
|
||||||
|
cancelToken.throwIfRequested();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -52,7 +52,7 @@ export function request<TData = unknown>(
|
||||||
fail,
|
fail,
|
||||||
};
|
};
|
||||||
|
|
||||||
const adapterTask = config.adapter?.(adapterConfig) as
|
const adapterTask = config.adapter!(adapterConfig) as
|
||||||
| AxiosAdapterTask
|
| AxiosAdapterTask
|
||||||
| undefined;
|
| undefined;
|
||||||
|
|
||||||
|
@ -83,8 +83,9 @@ export function request<TData = unknown>(
|
||||||
tryToggleProgressUpdate(adapterConfig, adapterTask.onProgressUpdate);
|
tryToggleProgressUpdate(adapterConfig, adapterTask.onProgressUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isCancelToken(config.cancelToken)) {
|
const { cancelToken } = config;
|
||||||
config.cancelToken.onCancel((reason: unknown) => {
|
if (isCancelToken(cancelToken)) {
|
||||||
|
cancelToken.onCancel((reason) => {
|
||||||
if (isPlainObject(adapterTask)) {
|
if (isPlainObject(adapterTask)) {
|
||||||
tryToggleProgressUpdate(adapterConfig, adapterTask.offProgressUpdate);
|
tryToggleProgressUpdate(adapterConfig, adapterTask.offProgressUpdate);
|
||||||
|
|
||||||
|
|
|
@ -13,9 +13,8 @@ export function throwError(msg: string): void {
|
||||||
export function cleanStack(error: Error) {
|
export function cleanStack(error: Error) {
|
||||||
if (error.stack) {
|
if (error.stack) {
|
||||||
const start = error.stack.indexOf('at');
|
const start = error.stack.indexOf('at');
|
||||||
const end = error.stack.indexOf('at /');
|
const end = error.stack.search(/at ([\w-_.]+:)?\//i);
|
||||||
|
if (start < end) {
|
||||||
if (start !== end) {
|
|
||||||
const removed = error.stack.slice(start, end);
|
const removed = error.stack.slice(start, end);
|
||||||
error.stack = error.stack.replace(removed, '');
|
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 {
|
import {
|
||||||
asyncNext,
|
asyncNext,
|
||||||
captureError,
|
captureError,
|
||||||
mockSuccess,
|
mockAdapterSuccess,
|
||||||
noop,
|
noop,
|
||||||
asyncTimeout,
|
asyncTimeout,
|
||||||
} from 'scripts/test.utils';
|
} from 'scripts/test.utils';
|
||||||
import axios from 'src/axios';
|
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', () => {
|
describe('src/helpers/cancel.ts', () => {
|
||||||
test('应该支持空参数', () => {
|
test('应该支持空参数', () => {
|
||||||
|
@ -100,7 +105,7 @@ describe('src/helpers/cancel.ts', () => {
|
||||||
|
|
||||||
source.cancel();
|
source.cancel();
|
||||||
axios({
|
axios({
|
||||||
adapter: ({ success }) => success(mockSuccess()),
|
adapter: mockAdapterSuccess(),
|
||||||
cancelToken: source.token,
|
cancelToken: source.token,
|
||||||
}).catch(canceled);
|
}).catch(canceled);
|
||||||
|
|
||||||
|
@ -114,7 +119,7 @@ describe('src/helpers/cancel.ts', () => {
|
||||||
const source = CancelToken.source();
|
const source = CancelToken.source();
|
||||||
|
|
||||||
axios({
|
axios({
|
||||||
adapter: ({ success }) => success(mockSuccess()),
|
adapter: mockAdapterSuccess(),
|
||||||
cancelToken: source.token,
|
cancelToken: source.token,
|
||||||
}).catch(canceled);
|
}).catch(canceled);
|
||||||
source.cancel();
|
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