parent
ce12a83873
commit
4409a5720b
|
@ -13,6 +13,8 @@ axios.defaults.adapter = function adapter(adapterConfig) {
|
||||||
url,
|
url,
|
||||||
// 请求方法
|
// 请求方法
|
||||||
method,
|
method,
|
||||||
|
// 请求参数
|
||||||
|
params,
|
||||||
// 请求数据
|
// 请求数据
|
||||||
data,
|
data,
|
||||||
// 请求头 同 headers
|
// 请求头 同 headers
|
||||||
|
@ -53,7 +55,7 @@ axios.defaults.adapter = function adapter(adapterConfig) {
|
||||||
return wx.downloadFile({
|
return wx.downloadFile({
|
||||||
url,
|
url,
|
||||||
method,
|
method,
|
||||||
filePath: data.filePath,
|
filePath: params.filePath,
|
||||||
header: headers,
|
header: headers,
|
||||||
success,
|
success,
|
||||||
fail,
|
fail,
|
||||||
|
|
|
@ -1,12 +1 @@
|
||||||
declare const uni: unknown;
|
|
||||||
declare const wx: unknown;
|
|
||||||
declare const my: unknown;
|
|
||||||
declare const swan: unknown;
|
|
||||||
declare const tt: unknown;
|
|
||||||
declare const qq: unknown;
|
|
||||||
declare const qh: unknown;
|
|
||||||
declare const ks: unknown;
|
|
||||||
declare const dd: unknown;
|
|
||||||
declare const jd: unknown;
|
|
||||||
|
|
||||||
type AnyObject<T = any> = Record<string, T>;
|
type AnyObject<T = any> = Record<string, T>;
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
declare const uni: unknown;
|
||||||
|
declare const wx: unknown;
|
||||||
|
declare const my: unknown;
|
||||||
|
declare const swan: unknown;
|
||||||
|
declare const tt: unknown;
|
||||||
|
declare const qq: unknown;
|
||||||
|
declare const qh: unknown;
|
||||||
|
declare const ks: unknown;
|
||||||
|
declare const dd: unknown;
|
||||||
|
declare const jd: unknown;
|
|
@ -23,7 +23,7 @@ function main() {
|
||||||
function buildConfig(format) {
|
function buildConfig(format) {
|
||||||
const isDts = format === 'dts';
|
const isDts = format === 'dts';
|
||||||
const output = {
|
const output = {
|
||||||
file: resolvePath(format, isDts),
|
file: resolveOutput(format, isDts),
|
||||||
format: isDts ? 'es' : format,
|
format: isDts ? 'es' : format,
|
||||||
name: pkg.name,
|
name: pkg.name,
|
||||||
exports: 'default',
|
exports: 'default',
|
||||||
|
@ -51,7 +51,7 @@ function buildConfig(format) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function resolvePath(format, isDts) {
|
function resolveOutput(format, isDts) {
|
||||||
return path.resolve(
|
return path.resolve(
|
||||||
distPath,
|
distPath,
|
||||||
`${pkg.name}${isDts ? '.d.ts' : `.${format}.js`}`,
|
`${pkg.name}${isDts ? '.d.ts' : `.${format}.js`}`,
|
||||||
|
|
|
@ -8,7 +8,7 @@ export function asyncTimeout(delay = 0) {
|
||||||
return new Promise((resolve) => setTimeout(resolve, delay));
|
return new Promise((resolve) => setTimeout(resolve, delay));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function captureError<T = any>(fn: () => void): T {
|
export function captureError<T = any>(fn: () => void) {
|
||||||
try {
|
try {
|
||||||
fn();
|
fn();
|
||||||
throw new Error('without Error');
|
throw new Error('without Error');
|
||||||
|
@ -17,7 +17,7 @@ export function captureError<T = any>(fn: () => void): T {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function cleanedStack(error: Error) {
|
export function checkStack(error: Error) {
|
||||||
if (error.stack) {
|
if (error.stack) {
|
||||||
return error.stack.indexOf('at') === error.stack.indexOf('at /');
|
return error.stack.indexOf('at') === error.stack.indexOf('at /');
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@ export function noop() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function mockResponse(
|
export function mockResponseBase(
|
||||||
status: number,
|
status: number,
|
||||||
statusText: string,
|
statusText: string,
|
||||||
headers: AnyObject,
|
headers: AnyObject,
|
||||||
|
@ -42,12 +42,15 @@ export function mockResponse(
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function mockSuccess(headers: AnyObject = {}, data: AnyObject = {}) {
|
export function mockResponse(headers: AnyObject = {}, data: AnyObject = {}) {
|
||||||
return mockResponse(200, 'OK', headers, data);
|
return mockResponseBase(200, 'OK', headers, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function mockFail(headers: AnyObject = {}, data: AnyObject = {}) {
|
export function mockResponseError(
|
||||||
return mockResponse(400, 'FAIL', headers, data);
|
headers: AnyObject = {},
|
||||||
|
data: AnyObject = {},
|
||||||
|
) {
|
||||||
|
return mockResponseBase(400, 'FAIL', headers, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface MockAdapterOptions {
|
export interface MockAdapterOptions {
|
||||||
|
@ -58,8 +61,8 @@ export interface MockAdapterOptions {
|
||||||
after?: () => void;
|
after?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function mockAdapter(
|
export function mockAdapterBase(
|
||||||
type: 'success' | 'fail',
|
type: 'success' | 'error' | 'fail' = 'success',
|
||||||
options: MockAdapterOptions = {},
|
options: MockAdapterOptions = {},
|
||||||
) {
|
) {
|
||||||
const { headers = {}, data = {}, delay = 0, before, after } = options;
|
const { headers = {}, data = {}, delay = 0, before, after } = options;
|
||||||
|
@ -67,20 +70,30 @@ export function mockAdapter(
|
||||||
return (config: AxiosAdapterRequestConfig) => {
|
return (config: AxiosAdapterRequestConfig) => {
|
||||||
before?.(config);
|
before?.(config);
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
if (type === 'success') {
|
switch (type) {
|
||||||
config.success(mockSuccess(headers, data));
|
case 'success':
|
||||||
} else {
|
config.success(mockResponse(headers, data));
|
||||||
config.fail(mockFail(headers, data));
|
break;
|
||||||
|
case 'error':
|
||||||
|
config.success(mockResponseError(headers, data));
|
||||||
|
break;
|
||||||
|
case 'fail':
|
||||||
|
config.fail(mockResponseError(headers));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
after?.();
|
after?.();
|
||||||
}, delay);
|
}, delay);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function mockAdapterSuccess(options: MockAdapterOptions = {}) {
|
export function mockAdapter(options: MockAdapterOptions = {}) {
|
||||||
return mockAdapter('success', options);
|
return mockAdapterBase('success', options);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function mockAdapterError(options: MockAdapterOptions = {}) {
|
||||||
|
return mockAdapterBase('error', options);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function mockAdapterFail(options: MockAdapterOptions = {}) {
|
export function mockAdapterFail(options: MockAdapterOptions = {}) {
|
||||||
return mockAdapter('fail', options);
|
return mockAdapterBase('fail', options);
|
||||||
}
|
}
|
||||||
|
|
|
@ -198,20 +198,34 @@ export default class Axios {
|
||||||
this.defaults = defaults;
|
this.defaults = defaults;
|
||||||
|
|
||||||
for (const alias of Axios.as) {
|
for (const alias of Axios.as) {
|
||||||
this[alias] = (url, config) => {
|
this[alias] = (url, config = {}) => {
|
||||||
return this._req(alias, url, undefined, config);
|
return this.request({
|
||||||
|
...config,
|
||||||
|
method: alias,
|
||||||
|
url,
|
||||||
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const alias of Axios.pas) {
|
for (const alias of Axios.pas) {
|
||||||
this[alias] = (url, params, config) => {
|
this[alias] = (url, params, config = {}) => {
|
||||||
return this._req(alias, url, params, config);
|
return this.request({
|
||||||
|
...config,
|
||||||
|
method: alias,
|
||||||
|
params,
|
||||||
|
url,
|
||||||
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const alias of Axios.das) {
|
for (const alias of Axios.das) {
|
||||||
this[alias] = (url, data, config) => {
|
this[alias] = (url, data, config) => {
|
||||||
return this._reqWithData(alias, url, data, config);
|
return this.request({
|
||||||
|
...config,
|
||||||
|
method: alias,
|
||||||
|
data,
|
||||||
|
url,
|
||||||
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -249,32 +263,4 @@ export default class Axios {
|
||||||
|
|
||||||
return promiseResponse as Promise<AxiosResponse<TData>>;
|
return promiseResponse as Promise<AxiosResponse<TData>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _req<TData = unknown>(
|
|
||||||
method: AxiosRequestMethod,
|
|
||||||
url: string,
|
|
||||||
params?: AnyObject,
|
|
||||||
config?: AxiosRequestConfig,
|
|
||||||
): Promise<AxiosResponse<TData>> {
|
|
||||||
return this.request<TData>({
|
|
||||||
...(config ?? {}),
|
|
||||||
method,
|
|
||||||
url,
|
|
||||||
params,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private _reqWithData<TData = unknown>(
|
|
||||||
method: AxiosRequestMethod,
|
|
||||||
url: string,
|
|
||||||
data?: AnyObject | AxiosRequestFormData,
|
|
||||||
config?: AxiosRequestConfig,
|
|
||||||
): Promise<AxiosResponse<TData>> {
|
|
||||||
return this.request<TData>({
|
|
||||||
...(config ?? {}),
|
|
||||||
method,
|
|
||||||
url,
|
|
||||||
data,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,32 +27,28 @@ export default function dispatchRequest<TData = unknown>(
|
||||||
config.transformRequest,
|
config.transformRequest,
|
||||||
);
|
);
|
||||||
|
|
||||||
return request<TData>(config).then(
|
function transformer(response: AxiosResponse<TData>) {
|
||||||
(response: AxiosResponse<TData>) => {
|
response.data = transformData(
|
||||||
|
response.data as AnyObject,
|
||||||
|
response.headers,
|
||||||
|
config.transformResponse,
|
||||||
|
) as TData;
|
||||||
|
}
|
||||||
|
|
||||||
|
return request<TData>(config)
|
||||||
|
.then((response: AxiosResponse<TData>) => {
|
||||||
throwIfCancellationRequested(config);
|
throwIfCancellationRequested(config);
|
||||||
|
transformer(response);
|
||||||
response.data = transformData(
|
|
||||||
response.data as AnyObject,
|
|
||||||
response.headers,
|
|
||||||
config.transformResponse,
|
|
||||||
) as TData;
|
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
},
|
})
|
||||||
(reason: unknown) => {
|
.catch((reason: unknown) => {
|
||||||
if (!isCancel(reason)) {
|
if (!isCancel(reason)) {
|
||||||
throwIfCancellationRequested(config);
|
throwIfCancellationRequested(config);
|
||||||
|
const response = (reason as AnyObject)?.response;
|
||||||
if (isPlainObject(reason) && isPlainObject(reason.response)) {
|
if (isPlainObject(response)) {
|
||||||
reason.response.data = transformData(
|
transformer(response as AxiosResponse<TData>);
|
||||||
reason.response.data,
|
|
||||||
reason.response.headers,
|
|
||||||
config.transformResponse,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
throw config.errorHandler?.(reason) ?? reason;
|
throw config.errorHandler?.(reason) ?? reason;
|
||||||
},
|
});
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,35 +2,17 @@ import { isUndefined, isPlainObject } from '../helpers/isTypes';
|
||||||
import { deepMerge } from '../helpers/deepMerge';
|
import { deepMerge } from '../helpers/deepMerge';
|
||||||
import { AxiosRequestConfig } from './Axios';
|
import { AxiosRequestConfig } from './Axios';
|
||||||
|
|
||||||
type AxiosRequestConfigKey = keyof AxiosRequestConfig;
|
const fromConfig2Map: Record<string, boolean> = {
|
||||||
|
url: true,
|
||||||
const onlyFromConfig2Keys: AxiosRequestConfigKey[] = [
|
method: true,
|
||||||
'url',
|
data: true,
|
||||||
'method',
|
upload: true,
|
||||||
'data',
|
download: true,
|
||||||
'upload',
|
};
|
||||||
'download',
|
const deepMergeConfigMap: Record<string, boolean> = {
|
||||||
];
|
headers: true,
|
||||||
const priorityFromConfig2Keys: AxiosRequestConfigKey[] = [
|
params: true,
|
||||||
'adapter',
|
};
|
||||||
'baseURL',
|
|
||||||
'paramsSerializer',
|
|
||||||
'transformRequest',
|
|
||||||
'transformResponse',
|
|
||||||
'errorHandler',
|
|
||||||
'cancelToken',
|
|
||||||
'dataType',
|
|
||||||
'responseType',
|
|
||||||
'timeout',
|
|
||||||
'enableHttp2',
|
|
||||||
'enableQuic',
|
|
||||||
'enableCache',
|
|
||||||
'sslVerify',
|
|
||||||
'validateStatus',
|
|
||||||
'onUploadProgress',
|
|
||||||
'onDownloadProgress',
|
|
||||||
];
|
|
||||||
const deepMergeConfigKeys: AxiosRequestConfigKey[] = ['headers', 'params'];
|
|
||||||
|
|
||||||
export function mergeConfig(
|
export function mergeConfig(
|
||||||
config1: AxiosRequestConfig = {},
|
config1: AxiosRequestConfig = {},
|
||||||
|
@ -38,33 +20,36 @@ export function mergeConfig(
|
||||||
): AxiosRequestConfig {
|
): AxiosRequestConfig {
|
||||||
const config: AxiosRequestConfig = {};
|
const config: AxiosRequestConfig = {};
|
||||||
|
|
||||||
for (const key of onlyFromConfig2Keys) {
|
// 所有已知键名
|
||||||
const value = config2[key];
|
const keysSet = Array.from(
|
||||||
|
new Set([...Object.keys(config1), ...Object.keys(config2)]),
|
||||||
|
);
|
||||||
|
|
||||||
if (!isUndefined(value)) {
|
for (const key of keysSet) {
|
||||||
config[key] = value as any;
|
const val1 = config1[key] as any;
|
||||||
|
const val2 = config2[key] as any;
|
||||||
|
|
||||||
|
// 只从 config2 中取值
|
||||||
|
if (fromConfig2Map[key]) {
|
||||||
|
if (!isUndefined(val2)) config[key] = val2;
|
||||||
}
|
}
|
||||||
}
|
// 深度合并 config1 和 config2 中的对象
|
||||||
|
else if (deepMergeConfigMap[key]) {
|
||||||
for (const key of priorityFromConfig2Keys) {
|
if (isPlainObject(val1) && isPlainObject(val2)) {
|
||||||
const value1 = config1[key];
|
config[key] = deepMerge(val1, val2);
|
||||||
const value2 = config2[key];
|
} else if (isPlainObject(val1)) {
|
||||||
|
config[key] = deepMerge(val1);
|
||||||
if (!isUndefined(value2)) {
|
} else if (isPlainObject(val2)) {
|
||||||
config[key] = value2 as any;
|
config[key] = deepMerge(val2);
|
||||||
} else if (!isUndefined(value1)) {
|
}
|
||||||
config[key] = value1 as any;
|
|
||||||
}
|
}
|
||||||
}
|
// 优先从 config2 中取值,如果没有值就从 config1 中取值
|
||||||
|
else {
|
||||||
for (const key of deepMergeConfigKeys) {
|
if (!isUndefined(val2)) {
|
||||||
const value1 = config1[key];
|
config[key] = val2;
|
||||||
const value2 = config2[key];
|
} else if (!isUndefined(val1)) {
|
||||||
|
config[key] = val1;
|
||||||
if (isPlainObject(value2)) {
|
}
|
||||||
config[key] = deepMerge(value1 ?? {}, value2) as any;
|
|
||||||
} else if (isPlainObject(value1)) {
|
|
||||||
config[key] = deepMerge(value1) as any;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { isFunction, isPlainObject } from '../helpers/isTypes';
|
import { isFunction, isPlainObject, isString } from '../helpers/isTypes';
|
||||||
import { assert } from '../helpers/error';
|
import { assert } from '../helpers/error';
|
||||||
import {
|
import {
|
||||||
AxiosAdapterRequestConfig,
|
AxiosAdapterRequestConfig,
|
||||||
|
@ -42,10 +42,12 @@ export function request<TData = unknown>(
|
||||||
): Promise<AxiosResponse<TData>> {
|
): Promise<AxiosResponse<TData>> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
assert(isFunction(config.adapter), 'adapter 不是一个 function');
|
assert(isFunction(config.adapter), 'adapter 不是一个 function');
|
||||||
|
assert(isString(config.url), 'url 不是一个 string');
|
||||||
|
assert(isString(config.method), 'method 不是一个 string');
|
||||||
|
|
||||||
const adapterConfig: AxiosAdapterRequestConfig = {
|
const adapterConfig: AxiosAdapterRequestConfig = {
|
||||||
...config,
|
...config,
|
||||||
url: config.url ?? '',
|
url: config.url,
|
||||||
type: generateType(config),
|
type: generateType(config),
|
||||||
method: config.method!.toUpperCase() as AxiosAdapterRequestMethod,
|
method: config.method!.toUpperCase() as AxiosAdapterRequestMethod,
|
||||||
success,
|
success,
|
||||||
|
|
|
@ -11,12 +11,13 @@ export function throwError(msg: string): void {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function cleanStack(error: Error) {
|
export function cleanStack(error: Error) {
|
||||||
if (error.stack) {
|
const { stack } = error;
|
||||||
const start = error.stack.indexOf('at');
|
if (stack) {
|
||||||
const end = error.stack.search(/at ([\w-_.]+:)?\//i);
|
const start = stack.indexOf('at');
|
||||||
|
const end = stack.search(/at ([\w-_.]+:)?\//i);
|
||||||
if (start < end) {
|
if (start < end) {
|
||||||
const removed = error.stack.slice(start, end);
|
const removed = stack.slice(start, end);
|
||||||
error.stack = error.stack.replace(removed, '');
|
error.stack = stack.replace(removed, '');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,42 +1,42 @@
|
||||||
import { describe, test, expect } from 'vitest';
|
import { describe, test, expect } from 'vitest';
|
||||||
import axios from 'src/axios';
|
import axios from 'src/axios';
|
||||||
import { mockAdapterFail, mockAdapterSuccess } from 'scripts/test.utils';
|
import { mockAdapter, mockAdapterError } from 'scripts/test.utils';
|
||||||
|
|
||||||
describe('src/axios.ts', () => {
|
describe('src/axios.ts', () => {
|
||||||
test('应该处理成功和失败', () => {
|
test('应该处理成功和失败', () => {
|
||||||
axios({
|
axios({
|
||||||
adapter: mockAdapterSuccess({
|
adapter: mockAdapter({
|
||||||
headers: { type: 'json' },
|
headers: { type: 'json' },
|
||||||
data: { v1: 1 },
|
data: { v1: 1 },
|
||||||
before: (config) => {
|
before: (config) => {
|
||||||
expect(config.url).toBe('http://api.com/user/1?id=1');
|
expect(config.url).toBe('http://api.com/test/1?id=1');
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
baseURL: 'http://api.com',
|
baseURL: 'http://api.com',
|
||||||
url: 'user/:id',
|
url: 'test/:id',
|
||||||
params: {
|
params: {
|
||||||
id: 1,
|
id: 1,
|
||||||
},
|
},
|
||||||
}).then((response) => {
|
}).then((res) => {
|
||||||
expect(response.headers).toEqual({ type: 'json' });
|
expect(res.headers).toEqual({ type: 'json' });
|
||||||
expect(response.data).toEqual({ v1: 1 });
|
expect(res.data).toEqual({ v1: 1 });
|
||||||
});
|
});
|
||||||
|
|
||||||
axios('user/:id', {
|
axios('test/:id', {
|
||||||
adapter: mockAdapterFail({
|
adapter: mockAdapterError({
|
||||||
headers: { type: 'json' },
|
headers: { type: 'json' },
|
||||||
data: { v1: 1 },
|
data: { v1: 1 },
|
||||||
before: (config) => {
|
before: (config) => {
|
||||||
expect(config.url).toBe('http://api.com/user/1');
|
expect(config.url).toBe('http://api.com/test/1');
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
baseURL: 'http://api.com',
|
baseURL: 'http://api.com',
|
||||||
data: {
|
data: {
|
||||||
id: 1,
|
id: 1,
|
||||||
},
|
},
|
||||||
}).catch((error) => {
|
}).catch((err) => {
|
||||||
expect(error.response.headers).toEqual({ type: 'json' });
|
expect(err.response.headers).toEqual({ type: 'json' });
|
||||||
expect(error.response.data).toEqual({ v1: 1 });
|
expect(err.response.data).toEqual({ v1: 1 });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { describe, test, expect, vi } from 'vitest';
|
||||||
import {
|
import {
|
||||||
asyncNext,
|
asyncNext,
|
||||||
captureError,
|
captureError,
|
||||||
mockAdapterSuccess,
|
mockAdapter,
|
||||||
noop,
|
noop,
|
||||||
asyncTimeout,
|
asyncTimeout,
|
||||||
} from 'scripts/test.utils';
|
} from 'scripts/test.utils';
|
||||||
|
@ -16,17 +16,17 @@ import {
|
||||||
|
|
||||||
describe('src/helpers/cancel.ts', () => {
|
describe('src/helpers/cancel.ts', () => {
|
||||||
test('应该支持空参数', () => {
|
test('应该支持空参数', () => {
|
||||||
const cancel = new Cancel();
|
const c = new Cancel();
|
||||||
|
|
||||||
expect(cancel.message).toBeUndefined();
|
expect(c.message).toBeUndefined();
|
||||||
expect(cancel.toString()).toBe('Cancel');
|
expect(c.toString()).toBe('Cancel');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('传入参数时应该有正确的返回结果', () => {
|
test('传入参数时应该有正确的返回结果', () => {
|
||||||
const cancel = new Cancel('error');
|
const c = new Cancel('error');
|
||||||
|
|
||||||
expect(cancel.message).toBe('error');
|
expect(c.message).toBe('error');
|
||||||
expect(cancel.toString()).toBe('Cancel: error');
|
expect(c.toString()).toBe('Cancel: error');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('应该正确判断 Cancel', () => {
|
test('应该正确判断 Cancel', () => {
|
||||||
|
@ -36,44 +36,47 @@ describe('src/helpers/cancel.ts', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
test('应该可以取消', () => {
|
test('应该可以取消', () => {
|
||||||
let cancelAction!: () => void;
|
let ca!: () => void;
|
||||||
const cancelToken = new CancelToken((action) => {
|
const ct = new CancelToken((a) => (ca = a));
|
||||||
cancelAction = action;
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(cancelToken.throwIfRequested()).toBeUndefined();
|
expect(ct.throwIfRequested()).toBeUndefined();
|
||||||
cancelAction();
|
|
||||||
expect(() => cancelToken.throwIfRequested()).toThrowError();
|
ca();
|
||||||
|
|
||||||
|
expect(() => ct.throwIfRequested()).toThrowError();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('应该抛出正确的异常信息', async () => {
|
test('应该抛出正确的异常信息', async () => {
|
||||||
let cancelAction!: (msg: string) => void;
|
let ca!: (msg: string) => void;
|
||||||
const cancelToken = new CancelToken((action) => {
|
const ct = new CancelToken((a) => (ca = a));
|
||||||
cancelAction = action;
|
|
||||||
});
|
|
||||||
|
|
||||||
cancelAction('stop');
|
const te = () => ct.throwIfRequested();
|
||||||
const error = captureError<Cancel>(() => cancelToken.throwIfRequested());
|
|
||||||
expect(error.message).toBe('stop');
|
ca('stop');
|
||||||
expect(error.toString()).toBe('Cancel: stop');
|
|
||||||
|
expect(te).toThrowErrorMatchingInlineSnapshot(`
|
||||||
|
Cancel {
|
||||||
|
"message": "stop",
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
expect(captureError<Cancel>(te).toString()).toBe('Cancel: stop');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('回调函数应该被异步执行', async () => {
|
test('回调函数应该被异步执行', async () => {
|
||||||
const canceled = vi.fn();
|
const cb = vi.fn();
|
||||||
let cancelAction!: () => void;
|
let ca!: () => void;
|
||||||
const cancelToken = new CancelToken((action) => {
|
const ct = new CancelToken((a) => (ca = a));
|
||||||
cancelAction = action;
|
|
||||||
});
|
|
||||||
cancelToken.onCancel(canceled);
|
|
||||||
expect(canceled).not.toBeCalled();
|
|
||||||
|
|
||||||
cancelAction();
|
ct.onCancel(cb);
|
||||||
|
expect(cb).not.toBeCalled();
|
||||||
|
|
||||||
expect(canceled).not.toBeCalled();
|
ca();
|
||||||
|
|
||||||
|
expect(cb).not.toBeCalled();
|
||||||
|
|
||||||
await asyncNext();
|
await asyncNext();
|
||||||
expect(canceled).toBeCalled();
|
expect(cb).toBeCalled();
|
||||||
expect(isCancel(canceled.mock.calls[0][0])).toBeTruthy();
|
expect(isCancel(cb.mock.calls[0][0])).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('应该正确判断 CancelToken', () => {
|
test('应该正确判断 CancelToken', () => {
|
||||||
|
@ -83,49 +86,51 @@ describe('src/helpers/cancel.ts', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
test('应该有正确返回结果', () => {
|
test('应该有正确返回结果', () => {
|
||||||
const source = CancelToken.source();
|
const s = CancelToken.source();
|
||||||
|
|
||||||
expect(source.cancel).toBeTypeOf('function');
|
expect(s.cancel).toBeTypeOf('function');
|
||||||
expect(isCancelToken(source.token)).toBeTruthy();
|
expect(isCancelToken(s.token)).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('应该可以取消', () => {
|
test('应该可以取消', () => {
|
||||||
const source = CancelToken.source();
|
const s = CancelToken.source();
|
||||||
|
|
||||||
expect(source.token.throwIfRequested()).toBeUndefined();
|
expect(s.token.throwIfRequested()).toBeUndefined();
|
||||||
|
|
||||||
source.cancel();
|
s.cancel();
|
||||||
|
|
||||||
expect(() => source.token.throwIfRequested()).toThrowError();
|
expect(() => s.token.throwIfRequested()).toThrowError();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('应该可以在请求发出之前取消', async () => {
|
test('应该可以在请求发出之前取消', async () => {
|
||||||
const canceled = vi.fn();
|
const cb = vi.fn();
|
||||||
const source = CancelToken.source();
|
const s = CancelToken.source();
|
||||||
|
|
||||||
|
s.cancel();
|
||||||
|
|
||||||
source.cancel();
|
|
||||||
axios({
|
axios({
|
||||||
adapter: mockAdapterSuccess(),
|
adapter: mockAdapter(),
|
||||||
cancelToken: source.token,
|
cancelToken: s.token,
|
||||||
}).catch(canceled);
|
}).catch(cb);
|
||||||
|
|
||||||
await asyncTimeout();
|
await asyncTimeout();
|
||||||
expect(canceled).toBeCalled();
|
expect(cb).toBeCalled();
|
||||||
expect(isCancel(canceled.mock.calls[0][0])).toBeTruthy();
|
expect(isCancel(cb.mock.calls[0][0])).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('应该可以在请求发出之后取消', async () => {
|
test('应该可以在请求发出之后取消', async () => {
|
||||||
const canceled = vi.fn();
|
const cb = vi.fn();
|
||||||
const source = CancelToken.source();
|
const s = CancelToken.source();
|
||||||
|
|
||||||
axios({
|
axios({
|
||||||
adapter: mockAdapterSuccess(),
|
adapter: mockAdapter(),
|
||||||
cancelToken: source.token,
|
cancelToken: s.token,
|
||||||
}).catch(canceled);
|
}).catch(cb);
|
||||||
source.cancel();
|
|
||||||
|
s.cancel();
|
||||||
|
|
||||||
await asyncTimeout();
|
await asyncTimeout();
|
||||||
expect(canceled).toBeCalled();
|
expect(cb).toBeCalled();
|
||||||
expect(isCancel(canceled.mock.calls[0][0])).toBeTruthy();
|
expect(isCancel(cb.mock.calls[0][0])).toBeTruthy();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,27 +1,27 @@
|
||||||
import { describe, test, expect } from 'vitest';
|
import { describe, test, expect } from 'vitest';
|
||||||
import { cleanedStack } from 'scripts/test.utils';
|
import { checkStack } from 'scripts/test.utils';
|
||||||
import { createError } from 'src/core/createError';
|
import { createError } from 'src/core/createError';
|
||||||
|
|
||||||
describe('src/core/createError.ts', () => {
|
describe('src/core/createError.ts', () => {
|
||||||
test('应该支持空参数', () => {
|
test('应该支持空参数', () => {
|
||||||
const config = {};
|
const c = {};
|
||||||
const axiosError = createError('error', config);
|
const err = createError('error', c);
|
||||||
|
|
||||||
expect(axiosError.isAxiosError).toBeTruthy();
|
expect(err.isAxiosError).toBeTruthy();
|
||||||
expect(axiosError.message).toBe('error');
|
expect(err.message).toBe('error');
|
||||||
expect(axiosError.config).toBe(config);
|
expect(err.config).toBe(c);
|
||||||
expect(cleanedStack(axiosError)).toBeTruthy();
|
expect(checkStack(err)).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('应该支持传入更多参数', () => {
|
test('应该支持传入更多参数', () => {
|
||||||
const config = {};
|
const c = {};
|
||||||
const request = {};
|
const req = {};
|
||||||
const response = {};
|
const res = {};
|
||||||
const axiosError = createError('error', config, request, response as any);
|
const err = createError('error', c, req, res as any);
|
||||||
|
|
||||||
expect(axiosError.message).toBe('error');
|
expect(err.message).toBe('error');
|
||||||
expect(axiosError.config).toBe(config);
|
expect(err.config).toBe(c);
|
||||||
expect(axiosError.request).toBe(request);
|
expect(err.request).toBe(req);
|
||||||
expect(axiosError.response).toBe(response);
|
expect(err.response).toBe(res);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,115 @@
|
||||||
|
import { describe, test, expect } from 'vitest';
|
||||||
|
import { flattenHeaders } from 'src/core/flattenHeaders';
|
||||||
|
import Axios from 'src/core/Axios';
|
||||||
|
|
||||||
|
describe('src/core/flattenHeaders.ts', () => {
|
||||||
|
const keys = [...Axios.as, ...Axios.pas, ...Axios.das];
|
||||||
|
const baseHeaders = {
|
||||||
|
options: {
|
||||||
|
v1: 'options1',
|
||||||
|
v2: 'options2',
|
||||||
|
},
|
||||||
|
trace: {
|
||||||
|
v1: 'trace1',
|
||||||
|
v2: 'trace2',
|
||||||
|
},
|
||||||
|
connect: {
|
||||||
|
v1: 'connect1',
|
||||||
|
v2: 'connect2',
|
||||||
|
},
|
||||||
|
head: {
|
||||||
|
v1: 'head1',
|
||||||
|
v2: 'head2',
|
||||||
|
},
|
||||||
|
get: {
|
||||||
|
v1: 'get1',
|
||||||
|
v2: 'get2',
|
||||||
|
},
|
||||||
|
delete: {
|
||||||
|
v1: 'delete1',
|
||||||
|
v2: 'delete2',
|
||||||
|
},
|
||||||
|
post: {
|
||||||
|
v1: 'post1',
|
||||||
|
v2: 'post2',
|
||||||
|
},
|
||||||
|
put: {
|
||||||
|
v1: 'put1',
|
||||||
|
v2: 'put2',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
test('应该支持空配置', () => {
|
||||||
|
expect(flattenHeaders({})).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('应该支持自定义 headers', () => {
|
||||||
|
const h = {
|
||||||
|
v1: '1',
|
||||||
|
v2: '2',
|
||||||
|
};
|
||||||
|
expect(flattenHeaders({ headers: h, method: 'get' })).toEqual(h);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('应该支持别名 headers,并且自定义 headers 优先级应该高于别名 headers', () => {
|
||||||
|
const h1 = baseHeaders;
|
||||||
|
const h2 = { v1: 1, v2: 2 };
|
||||||
|
const h3 = { ...h1, ...h2 };
|
||||||
|
|
||||||
|
keys.forEach((a) => {
|
||||||
|
expect(flattenHeaders({ headers: h1, method: a })).toEqual(h1[a]);
|
||||||
|
expect(flattenHeaders({ headers: h3, method: a })).toEqual(h2);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('应该支持通用 headers,并且别名 headers 优先级应该高于通用 headers', () => {
|
||||||
|
const h1 = {
|
||||||
|
common: {
|
||||||
|
v1: 'common1',
|
||||||
|
v2: 'common2',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const h2 = { ...baseHeaders, ...h1 };
|
||||||
|
|
||||||
|
keys.forEach((a) => {
|
||||||
|
expect(flattenHeaders({ headers: h1, method: a })).toEqual(h1.common);
|
||||||
|
expect(flattenHeaders({ headers: h2, method: a })).toEqual(h2[a]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test.each(
|
||||||
|
keys.map((k) => [
|
||||||
|
k,
|
||||||
|
{
|
||||||
|
common: {
|
||||||
|
v1: 'common1',
|
||||||
|
v2: 'common1',
|
||||||
|
},
|
||||||
|
[k]: {
|
||||||
|
v3: `${k}1`,
|
||||||
|
v4: `${k}2`,
|
||||||
|
},
|
||||||
|
v5: 5,
|
||||||
|
v6: 6,
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
)('应该获取到完整的 %s headers', (k, h) => {
|
||||||
|
const h1 = {
|
||||||
|
v1: 'common1',
|
||||||
|
v2: 'common1',
|
||||||
|
v5: 5,
|
||||||
|
v6: 6,
|
||||||
|
};
|
||||||
|
const h2 = {
|
||||||
|
...h1,
|
||||||
|
v3: `${k}1`,
|
||||||
|
v4: `${k}2`,
|
||||||
|
};
|
||||||
|
|
||||||
|
keys.forEach((a) => {
|
||||||
|
expect(flattenHeaders({ headers: h, method: a })).toEqual(
|
||||||
|
a !== k ? h1 : h2,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -1,50 +1,19 @@
|
||||||
import { describe, test, expect } from 'vitest';
|
import { describe, test, expect } from 'vitest';
|
||||||
import { mockAdapterSuccess } from 'scripts/test.utils';
|
|
||||||
import { generateType } from 'src/core/generateType';
|
import { generateType } from 'src/core/generateType';
|
||||||
import Axios from 'src/core/Axios';
|
import Axios from 'src/core/Axios';
|
||||||
import axios from 'src/axios';
|
|
||||||
|
|
||||||
describe('src/core/generateType.ts', () => {
|
describe('src/core/generateType.ts', () => {
|
||||||
test('应该是一个 reuqest', () => {
|
test('应该是一个 reuqest', () => {
|
||||||
for (const alias of [...Axios.as, ...Axios.pas, ...Axios.das]) {
|
for (const a of [...Axios.as, ...Axios.pas, ...Axios.das]) {
|
||||||
expect(generateType({ method: alias })).toBe('request');
|
expect(generateType({ method: a })).toBe('request');
|
||||||
|
|
||||||
axios({
|
|
||||||
adapter: mockAdapterSuccess({
|
|
||||||
before: (config) => {
|
|
||||||
expect(config.type).toBe('request');
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
method: alias,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
test('应该是一个 upload', () => {
|
test('应该是一个 upload', () => {
|
||||||
expect(generateType({ method: 'post', upload: true })).toBe('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', () => {
|
test('应该是一个 download', () => {
|
||||||
expect(generateType({ method: 'get', download: true })).toBe('download');
|
expect(generateType({ method: 'get', download: true })).toBe('download');
|
||||||
|
|
||||||
axios({
|
|
||||||
adapter: mockAdapterSuccess({
|
|
||||||
before: (config) => {
|
|
||||||
expect(config.type).toBe('download');
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
method: 'get',
|
|
||||||
download: true,
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,173 @@
|
||||||
|
import { describe, test, expect, vi } from 'vitest';
|
||||||
|
import { ignore } from 'src/helpers/ignore';
|
||||||
|
import { mergeConfig } from 'src/core/mergeConfig';
|
||||||
|
import { CancelToken } from 'src/core/cancel';
|
||||||
|
|
||||||
|
describe('src/core/mergeConfig.ts', () => {
|
||||||
|
test('应该支持空参数', () => {
|
||||||
|
expect(mergeConfig()).toEqual({});
|
||||||
|
expect(mergeConfig({ baseURL: '/api' })).toEqual({ baseURL: '/api' });
|
||||||
|
});
|
||||||
|
|
||||||
|
test('应该只取 config2', () => {
|
||||||
|
const c1 = {
|
||||||
|
url: 'a',
|
||||||
|
method: 'get' as const,
|
||||||
|
data: {},
|
||||||
|
upload: true,
|
||||||
|
download: true,
|
||||||
|
};
|
||||||
|
const c2 = {
|
||||||
|
url: 'b',
|
||||||
|
method: 'post' as const,
|
||||||
|
data: {},
|
||||||
|
upload: false,
|
||||||
|
download: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(mergeConfig(c1, {})).toEqual({});
|
||||||
|
expect(mergeConfig({}, c2)).toEqual(c2);
|
||||||
|
expect(mergeConfig(c1, c2)).toEqual(c2);
|
||||||
|
|
||||||
|
Object.keys(c2).forEach((_) => {
|
||||||
|
const key = _ as keyof typeof c2;
|
||||||
|
expect(mergeConfig(ignore(c1, key), c2)).toEqual(c2);
|
||||||
|
expect(mergeConfig(c1, ignore(c2, key))).toEqual(ignore(c2, key));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('应该深度合并', () => {
|
||||||
|
const c1 = {
|
||||||
|
headers: {
|
||||||
|
common: {
|
||||||
|
v1: 1,
|
||||||
|
},
|
||||||
|
v1: 1,
|
||||||
|
},
|
||||||
|
params: {
|
||||||
|
v1: 1,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const c2 = {
|
||||||
|
headers: {
|
||||||
|
common: {
|
||||||
|
v2: 2,
|
||||||
|
},
|
||||||
|
v2: 2,
|
||||||
|
},
|
||||||
|
params: {
|
||||||
|
v2: 2,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const mc = {
|
||||||
|
headers: {
|
||||||
|
common: {
|
||||||
|
v1: 1,
|
||||||
|
v2: 2,
|
||||||
|
},
|
||||||
|
v1: 1,
|
||||||
|
v2: 2,
|
||||||
|
},
|
||||||
|
params: {
|
||||||
|
v1: 1,
|
||||||
|
v2: 2,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(mergeConfig(c1, {})).toEqual(c1);
|
||||||
|
expect(mergeConfig({}, c2)).toEqual(c2);
|
||||||
|
expect(mergeConfig(c1, c2)).toEqual(mc);
|
||||||
|
|
||||||
|
Object.keys(c2).forEach((_) => {
|
||||||
|
const key = _ as keyof typeof c2;
|
||||||
|
expect(mergeConfig(ignore(c1, key), c2)).toEqual({
|
||||||
|
...mc,
|
||||||
|
[key]: c2[key],
|
||||||
|
});
|
||||||
|
expect(mergeConfig(c1, ignore(c2, key))).toEqual({
|
||||||
|
...mc,
|
||||||
|
[key]: c1[key],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('应该优先取 config2', () => {
|
||||||
|
const c1 = {
|
||||||
|
adapter: vi.fn(),
|
||||||
|
baseURL: 'https://c1.com',
|
||||||
|
paramsSerializer: vi.fn(),
|
||||||
|
transformRequest: vi.fn(),
|
||||||
|
transformResponse: vi.fn(),
|
||||||
|
errorHandler: vi.fn(),
|
||||||
|
cancelToken: CancelToken.source().token,
|
||||||
|
dataType: 'json',
|
||||||
|
responseType: 'json',
|
||||||
|
timeout: 1000,
|
||||||
|
validateStatus: vi.fn(),
|
||||||
|
onUploadProgress: vi.fn(),
|
||||||
|
onDownloadProgress: vi.fn(),
|
||||||
|
};
|
||||||
|
const c2 = {
|
||||||
|
adapter: vi.fn(),
|
||||||
|
baseURL: 'https://c2.com',
|
||||||
|
paramsSerializer: vi.fn(),
|
||||||
|
transformRequest: vi.fn(),
|
||||||
|
transformResponse: vi.fn(),
|
||||||
|
errorHandler: vi.fn(),
|
||||||
|
cancelToken: CancelToken.source().token,
|
||||||
|
dataType: 'json',
|
||||||
|
responseType: 'json',
|
||||||
|
timeout: 1000,
|
||||||
|
validateStatus: vi.fn(),
|
||||||
|
onUploadProgress: vi.fn(),
|
||||||
|
onDownloadProgress: vi.fn(),
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(mergeConfig(c1, {})).toEqual(c1);
|
||||||
|
expect(mergeConfig({}, c2)).toEqual(c2);
|
||||||
|
expect(mergeConfig(c1, c2)).toEqual(c2);
|
||||||
|
|
||||||
|
Object.keys(c2).forEach((_) => {
|
||||||
|
const key = _ as keyof typeof c2;
|
||||||
|
expect(mergeConfig(ignore(c1, key), c2)).toEqual(c2);
|
||||||
|
expect(mergeConfig(c1, ignore(c2, key))).toEqual({
|
||||||
|
...c2,
|
||||||
|
[key]: c1[key],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('应该支持自定义配置', () => {
|
||||||
|
const c1 = {
|
||||||
|
custom1: 1,
|
||||||
|
custom2: 'c1',
|
||||||
|
custom3: vi.fn(),
|
||||||
|
custom4: { c1: 1 },
|
||||||
|
custom5: ['c1'],
|
||||||
|
custom6: new Date(),
|
||||||
|
custom7: () => 1,
|
||||||
|
};
|
||||||
|
const c2 = {
|
||||||
|
custom1: 2,
|
||||||
|
custom2: 'c2',
|
||||||
|
custom3: vi.fn(),
|
||||||
|
custom4: { c2: 2 },
|
||||||
|
custom5: ['c2'],
|
||||||
|
custom6: new Date(),
|
||||||
|
custom7: () => 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(mergeConfig(c1, {})).toEqual(c1);
|
||||||
|
expect(mergeConfig({}, c2)).toEqual(c2);
|
||||||
|
expect(mergeConfig(c1, c2)).toEqual(c2);
|
||||||
|
|
||||||
|
Object.keys(c2).forEach((_) => {
|
||||||
|
const key = _ as keyof typeof c2;
|
||||||
|
expect(mergeConfig(ignore(c1, key), c2)).toEqual(c2);
|
||||||
|
expect(mergeConfig(c1, ignore(c2, key))).toEqual({
|
||||||
|
...c2,
|
||||||
|
[key]: c1[key],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,75 @@
|
||||||
|
import { describe, test, expect } from 'vitest';
|
||||||
|
import { request } from 'src/core/request';
|
||||||
|
import {
|
||||||
|
mockAdapter,
|
||||||
|
mockAdapterError,
|
||||||
|
mockAdapterFail,
|
||||||
|
} from 'scripts/test.utils';
|
||||||
|
|
||||||
|
describe('src/core/request.ts', () => {
|
||||||
|
test('应该抛出异常', async () => {
|
||||||
|
await expect(request({})).rejects.toThrowErrorMatchingInlineSnapshot(
|
||||||
|
'"[axios-miniprogram]: adapter 不是一个 function"',
|
||||||
|
);
|
||||||
|
await expect(
|
||||||
|
request({ adapter: mockAdapter() }),
|
||||||
|
).rejects.toThrowErrorMatchingInlineSnapshot(
|
||||||
|
'"[axios-miniprogram]: url 不是一个 string"',
|
||||||
|
);
|
||||||
|
await expect(
|
||||||
|
request({ adapter: mockAdapter(), url: 'test' }),
|
||||||
|
).rejects.toThrowErrorMatchingInlineSnapshot(
|
||||||
|
'"[axios-miniprogram]: method 不是一个 string"',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('应该能够取到数据', async () => {
|
||||||
|
await expect(
|
||||||
|
request({
|
||||||
|
adapter: mockAdapter(),
|
||||||
|
url: '/test',
|
||||||
|
method: 'get',
|
||||||
|
}),
|
||||||
|
).resolves.toMatchInlineSnapshot(`
|
||||||
|
{
|
||||||
|
"config": {
|
||||||
|
"adapter": [Function],
|
||||||
|
"method": "get",
|
||||||
|
"url": "/test",
|
||||||
|
},
|
||||||
|
"data": {},
|
||||||
|
"headers": {},
|
||||||
|
"request": undefined,
|
||||||
|
"status": 200,
|
||||||
|
"statusText": "OK",
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
await expect(
|
||||||
|
request({
|
||||||
|
adapter: mockAdapterError(),
|
||||||
|
url: '/test',
|
||||||
|
method: 'get',
|
||||||
|
}),
|
||||||
|
).resolves.toMatchInlineSnapshot(`
|
||||||
|
{
|
||||||
|
"config": {
|
||||||
|
"adapter": [Function],
|
||||||
|
"method": "get",
|
||||||
|
"url": "/test",
|
||||||
|
},
|
||||||
|
"data": {},
|
||||||
|
"headers": {},
|
||||||
|
"request": undefined,
|
||||||
|
"status": 400,
|
||||||
|
"statusText": "FAIL",
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
await expect(
|
||||||
|
request({
|
||||||
|
adapter: mockAdapterFail(),
|
||||||
|
url: '/test',
|
||||||
|
method: 'get',
|
||||||
|
}),
|
||||||
|
).rejects.toThrowErrorMatchingInlineSnapshot('"网络错误"');
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,58 @@
|
||||||
|
import { describe, test, expect } from 'vitest';
|
||||||
|
import { transformData } from 'src/core/transformData';
|
||||||
|
|
||||||
|
describe('src/core/transformData.ts', () => {
|
||||||
|
test('应该支持空配置', () => {
|
||||||
|
expect(transformData()).toBeUndefined();
|
||||||
|
expect(transformData({})).toEqual({});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('应该支持转换器', () => {
|
||||||
|
const h = {
|
||||||
|
type: 0,
|
||||||
|
};
|
||||||
|
const d = {
|
||||||
|
v1: 1,
|
||||||
|
};
|
||||||
|
const t = {
|
||||||
|
v2: 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
const fn = (data: any, headers: any) => {
|
||||||
|
expect(data).toEqual(d);
|
||||||
|
expect(headers).toEqual(h);
|
||||||
|
return t;
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(transformData(d, h, fn)).toEqual(t);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('应该支持转换器数组', () => {
|
||||||
|
const h = {
|
||||||
|
type: 0,
|
||||||
|
};
|
||||||
|
const d = {
|
||||||
|
v1: 1,
|
||||||
|
};
|
||||||
|
const t1 = {
|
||||||
|
v2: 2,
|
||||||
|
};
|
||||||
|
const t2 = {
|
||||||
|
v3: 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
const fn1 = (data: any, headers: any) => {
|
||||||
|
expect(data).toEqual(d);
|
||||||
|
expect(headers).toEqual(h);
|
||||||
|
return t1;
|
||||||
|
};
|
||||||
|
|
||||||
|
const fn2 = (data: any, headers: any) => {
|
||||||
|
expect(data).toEqual(t1);
|
||||||
|
expect(headers).toEqual(h);
|
||||||
|
return t2;
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(transformData(d, h, [fn1, fn2])).toEqual(t2);
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,74 @@
|
||||||
|
import { describe, test, expect } from 'vitest';
|
||||||
|
import { transformURL } from 'src/core/transformURL';
|
||||||
|
|
||||||
|
describe('src/core/transformURL.ts', () => {
|
||||||
|
test('应该支持空配置', () => {
|
||||||
|
expect(transformURL({})).toBe('');
|
||||||
|
expect(transformURL({ baseURL: 'http://api.com' })).toBe('http://api.com');
|
||||||
|
expect(transformURL({ url: 'test' })).toBe('/test');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('应该合并 URL', () => {
|
||||||
|
expect(
|
||||||
|
transformURL({
|
||||||
|
baseURL: 'http://api.com',
|
||||||
|
url: 'test',
|
||||||
|
}),
|
||||||
|
).toBe('http://api.com/test');
|
||||||
|
expect(
|
||||||
|
transformURL({
|
||||||
|
baseURL: 'http://api.com',
|
||||||
|
url: '/test',
|
||||||
|
}),
|
||||||
|
).toBe('http://api.com/test');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('应该支持绝对路径', () => {
|
||||||
|
expect(
|
||||||
|
transformURL({
|
||||||
|
baseURL: 'http://api.com',
|
||||||
|
url: 'http://api2.com',
|
||||||
|
}),
|
||||||
|
).toBe('http://api2.com');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('应该支持动态 URL', () => {
|
||||||
|
expect(
|
||||||
|
transformURL({
|
||||||
|
baseURL: 'http://api.com',
|
||||||
|
url: 'test/:name/:type',
|
||||||
|
params: {
|
||||||
|
name: 'axios',
|
||||||
|
type: 0,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
).toBe('http://api.com/test/axios/0?name=axios&type=0');
|
||||||
|
expect(
|
||||||
|
transformURL({
|
||||||
|
baseURL: 'http://api.com',
|
||||||
|
url: 'test/:name/:type',
|
||||||
|
data: {
|
||||||
|
name: 'axios',
|
||||||
|
type: 0,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
).toBe('http://api.com/test/axios/0');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('应该支持自定义参数系列化器', () => {
|
||||||
|
expect(
|
||||||
|
transformURL({
|
||||||
|
baseURL: 'http://api.com',
|
||||||
|
url: 'test',
|
||||||
|
paramsSerializer: () => 'type=0',
|
||||||
|
}),
|
||||||
|
).toBe('http://api.com/test?type=0');
|
||||||
|
expect(
|
||||||
|
transformURL({
|
||||||
|
baseURL: 'http://api.com',
|
||||||
|
url: 'test?name=axios',
|
||||||
|
paramsSerializer: () => 'type=0',
|
||||||
|
}),
|
||||||
|
).toBe('http://api.com/test?name=axios&type=0');
|
||||||
|
});
|
||||||
|
});
|
|
@ -3,61 +3,61 @@ import { buildURL } from 'src/helpers/buildURL';
|
||||||
|
|
||||||
describe('src/helpers/buildURL.ts', () => {
|
describe('src/helpers/buildURL.ts', () => {
|
||||||
test('应该支持空参数', () => {
|
test('应该支持空参数', () => {
|
||||||
expect(buildURL('/user')).toBe('/user');
|
expect(buildURL('/test')).toBe('/test');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('应该清理哈希值', () => {
|
test('应该清理哈希值', () => {
|
||||||
expect(buildURL('/user#hash')).toBe('/user');
|
expect(buildURL('/test#hash')).toBe('/test');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('应该对参数进行系列化', () => {
|
test('应该对参数进行系列化', () => {
|
||||||
expect(
|
expect(
|
||||||
buildURL('/user#hash', {
|
buildURL('/test#hash', {
|
||||||
v1: 1,
|
v1: 1,
|
||||||
v2: undefined,
|
v2: undefined,
|
||||||
v3: null,
|
v3: null,
|
||||||
v4: '4',
|
v4: '4',
|
||||||
v5: NaN,
|
v5: NaN,
|
||||||
}),
|
}),
|
||||||
).toBe('/user?v1=1&v4=4');
|
).toBe('/test?v1=1&v4=4');
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
buildURL('/user?v1=1', {
|
buildURL('/test?v1=1', {
|
||||||
v2: 2,
|
v2: 2,
|
||||||
}),
|
}),
|
||||||
).toBe('/user?v1=1&v2=2');
|
).toBe('/test?v1=1&v2=2');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('应该对数组进行系列化', () => {
|
test('应该对数组进行系列化', () => {
|
||||||
expect(
|
expect(
|
||||||
buildURL('/user', {
|
buildURL('/test', {
|
||||||
arr: [1, 2],
|
arr: [1, 2],
|
||||||
}),
|
}),
|
||||||
).toBe('/user?arr[]=1&arr[]=2');
|
).toBe('/test?arr[]=1&arr[]=2');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('应该对对象进行系列化', () => {
|
test('应该对对象进行系列化', () => {
|
||||||
expect(
|
expect(
|
||||||
buildURL('/user', {
|
buildURL('/test', {
|
||||||
obj: {
|
obj: {
|
||||||
k1: 1,
|
k1: 1,
|
||||||
k2: 2,
|
k2: 2,
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
).toBe('/user?obj[k1]=1&obj[k2]=2');
|
).toBe('/test?obj[k1]=1&obj[k2]=2');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('应该对日期进行系列化', () => {
|
test('应该对日期进行系列化', () => {
|
||||||
const date = new Date();
|
const d = new Date();
|
||||||
expect(buildURL('/user', { date })).toBe(
|
expect(buildURL('/test', { date: d })).toBe(
|
||||||
`/user?date=${date.toISOString()}`,
|
`/test?date=${d.toISOString()}`,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('应该支持自定义序列化器', () => {
|
test('应该支持自定义序列化器', () => {
|
||||||
expect(buildURL('/user', {}, () => 'v1=1&v2=2')).toBe('/user?v1=1&v2=2');
|
expect(buildURL('/test', {}, () => 'v1=1&v2=2')).toBe('/test?v1=1&v2=2');
|
||||||
expect(buildURL('/user?v1=1', {}, () => 'v2=2&v3=3')).toBe(
|
expect(buildURL('/test?v1=1', {}, () => 'v2=2&v3=3')).toBe(
|
||||||
'/user?v1=1&v2=2&v3=3',
|
'/test?v1=1&v2=2&v3=3',
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -9,17 +9,17 @@ describe('src/helpers/combineURL.ts', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
test('应该得到拼接后的结果', () => {
|
test('应该得到拼接后的结果', () => {
|
||||||
expect(combineURL('http://api.com', '/user')).toBe('http://api.com/user');
|
expect(combineURL('http://api.com', '/test')).toBe('http://api.com/test');
|
||||||
expect(combineURL('file://api.com', '/user')).toBe('file://api.com/user');
|
expect(combineURL('file://api.com', '/test')).toBe('file://api.com/test');
|
||||||
expect(combineURL('unknow://api.com', '/user')).toBe(
|
expect(combineURL('unknow://api.com', '/test')).toBe(
|
||||||
'unknow://api.com/user',
|
'unknow://api.com/test',
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('应该清理多余的斜线', () => {
|
test('应该清理多余的斜线', () => {
|
||||||
expect(combineURL('//api//', '//user//')).toBe('/api/user/');
|
expect(combineURL('//api//', '//test//')).toBe('/api/test/');
|
||||||
expect(combineURL('http://api.com//', '//user//')).toBe(
|
expect(combineURL('http://api.com//', '//test//')).toBe(
|
||||||
'http://api.com/user/',
|
'http://api.com/test/',
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -3,66 +3,50 @@ import { deepMerge } from 'src/helpers/deepMerge';
|
||||||
|
|
||||||
describe('src/helpers/deepMerge.ts', () => {
|
describe('src/helpers/deepMerge.ts', () => {
|
||||||
test('应该支持空参数', () => {
|
test('应该支持空参数', () => {
|
||||||
expect(deepMerge()).toEqual({});
|
const o = {
|
||||||
});
|
|
||||||
|
|
||||||
test('应该直接返回第一个参数', () => {
|
|
||||||
expect(
|
|
||||||
deepMerge({
|
|
||||||
v1: 1,
|
|
||||||
v2: [1],
|
|
||||||
v3: { v: 'v3' },
|
|
||||||
v4: undefined,
|
|
||||||
v5: null,
|
|
||||||
v6: 'v6',
|
|
||||||
}),
|
|
||||||
).toEqual({
|
|
||||||
v1: 1,
|
v1: 1,
|
||||||
v2: [1],
|
v2: [1],
|
||||||
v3: { v: 'v3' },
|
v3: { v: 'v3' },
|
||||||
v4: undefined,
|
v4: undefined,
|
||||||
v5: null,
|
v5: null,
|
||||||
v6: 'v6',
|
v6: 'v6',
|
||||||
});
|
};
|
||||||
|
|
||||||
|
expect(deepMerge()).toEqual({});
|
||||||
|
expect(deepMerge(o)).toEqual(o);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('应该进行合并', () => {
|
test('应该进行合并', () => {
|
||||||
expect(
|
const o1 = {
|
||||||
deepMerge(
|
|
||||||
{
|
|
||||||
v1: 1,
|
|
||||||
v2: 2,
|
|
||||||
v3: 3,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
v2: 22,
|
|
||||||
v3: undefined,
|
|
||||||
v4: 4,
|
|
||||||
},
|
|
||||||
),
|
|
||||||
).toEqual({
|
|
||||||
v1: 1,
|
v1: 1,
|
||||||
|
v2: 2,
|
||||||
|
v3: 3,
|
||||||
|
};
|
||||||
|
const o2 = {
|
||||||
v2: 22,
|
v2: 22,
|
||||||
v3: undefined,
|
v3: undefined,
|
||||||
v4: 4,
|
v4: 4,
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(deepMerge<AnyObject>(o1, o2)).toEqual({
|
||||||
|
...o1,
|
||||||
|
...o2,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test('应该合并对象里的对象', () => {
|
test('应该合并对象里的对象', () => {
|
||||||
expect(
|
const o1 = {
|
||||||
deepMerge(
|
v1: { v: 1 },
|
||||||
{
|
v2: { v: 2 },
|
||||||
v1: { v: 1 },
|
v3: 3,
|
||||||
v2: { v: 2 },
|
};
|
||||||
v3: 3,
|
const o2 = {
|
||||||
},
|
v1: { vv: 11 },
|
||||||
{
|
v2: 2,
|
||||||
v1: { vv: 11 },
|
v3: { v: 3 },
|
||||||
v2: 2,
|
};
|
||||||
v3: { v: 3 },
|
|
||||||
},
|
expect(deepMerge<AnyObject>(o1, o2)).toEqual({
|
||||||
),
|
|
||||||
).toEqual({
|
|
||||||
v1: { v: 1, vv: 11 },
|
v1: { v: 1, vv: 11 },
|
||||||
v2: 2,
|
v2: 2,
|
||||||
v3: { v: 3 },
|
v3: { v: 3 },
|
||||||
|
|
|
@ -3,20 +3,20 @@ import { dynamicURL } from 'src/helpers/dynamicURL';
|
||||||
|
|
||||||
describe('src/helpers/dynamicURL.ts', () => {
|
describe('src/helpers/dynamicURL.ts', () => {
|
||||||
test('应该替换关键字', () => {
|
test('应该替换关键字', () => {
|
||||||
expect(dynamicURL('http://api.com/user/:id', {})).toBe(
|
expect(dynamicURL('http://api.com/test/:id', {})).toBe(
|
||||||
'http://api.com/user/undefined',
|
'http://api.com/test/undefined',
|
||||||
);
|
);
|
||||||
expect(dynamicURL('http://api.com/user/:id', { id: 1 })).toBe(
|
expect(dynamicURL('http://api.com/test/:id', { id: 1 })).toBe(
|
||||||
'http://api.com/user/1',
|
'http://api.com/test/1',
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('应该支持多个关键字', () => {
|
test('应该支持多个关键字', () => {
|
||||||
expect(
|
expect(
|
||||||
dynamicURL('http://api.com/users/name/:name/age/:age/list', {
|
dynamicURL('http://api.com/tests/name/:name/type/:type/list', {
|
||||||
name: 'my',
|
name: 'axios',
|
||||||
age: 18,
|
type: 0,
|
||||||
}),
|
}),
|
||||||
).toBe('http://api.com/users/name/my/age/18/list');
|
).toBe('http://api.com/tests/name/axios/type/0/list');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { describe, test, expect } from 'vitest';
|
import { describe, test, expect } from 'vitest';
|
||||||
import { captureError, cleanedStack } from 'scripts/test.utils';
|
import { captureError, checkStack } from 'scripts/test.utils';
|
||||||
import { assert, throwError, cleanStack } from 'src/helpers/error';
|
import { assert, throwError, cleanStack } from 'src/helpers/error';
|
||||||
|
|
||||||
describe('src/helpers/error.ts', () => {
|
describe('src/helpers/error.ts', () => {
|
||||||
|
@ -9,25 +9,27 @@ describe('src/helpers/error.ts', () => {
|
||||||
|
|
||||||
test('第一个参数为 false 时应该抛出异常', () => {
|
test('第一个参数为 false 时应该抛出异常', () => {
|
||||||
expect(() => assert(false, '')).toThrowError();
|
expect(() => assert(false, '')).toThrowError();
|
||||||
expect(cleanedStack(captureError(() => assert(false, '')))).toBeTruthy();
|
expect(checkStack(captureError(() => assert(false, '')))).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('应该抛出异常', () => {
|
test('应该抛出异常', () => {
|
||||||
expect(() => throwError('')).toThrowError('[axios-miniprogram]: ');
|
expect(() => throwError('')).toThrowErrorMatchingInlineSnapshot(
|
||||||
expect(() => throwError('error')).toThrowError(
|
'"[axios-miniprogram]: "',
|
||||||
'[axios-miniprogram]: error',
|
|
||||||
);
|
);
|
||||||
expect(cleanedStack(captureError(() => throwError('error')))).toBeTruthy();
|
expect(() => throwError('error')).toThrowErrorMatchingInlineSnapshot(
|
||||||
|
'"[axios-miniprogram]: error"',
|
||||||
|
);
|
||||||
|
expect(checkStack(captureError(() => throwError('error')))).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('应该清掉多余的错误栈', () => {
|
test('应该清掉多余的错误栈', () => {
|
||||||
const ce = () => new Error();
|
const ce = () => new Error();
|
||||||
const error = ce();
|
const error = ce();
|
||||||
|
|
||||||
expect(cleanedStack(error)).toBeFalsy();
|
expect(checkStack(error)).toBeFalsy();
|
||||||
|
|
||||||
cleanStack(error);
|
cleanStack(error);
|
||||||
|
|
||||||
expect(cleanedStack(error)).toBeTruthy();
|
expect(checkStack(error)).toBeTruthy();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -3,31 +3,37 @@ import { ignore } from 'src/helpers/ignore';
|
||||||
|
|
||||||
describe('src/helpers/ignore.ts', () => {
|
describe('src/helpers/ignore.ts', () => {
|
||||||
test('不应该改变传入的对象', () => {
|
test('不应该改变传入的对象', () => {
|
||||||
expect(
|
expect(ignore({ v1: 1 })).toEqual({ v1: 1 });
|
||||||
ignore({
|
|
||||||
v1: 1,
|
|
||||||
}),
|
|
||||||
).toEqual({
|
|
||||||
v1: 1,
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('应该忽略指定键值', () => {
|
test('应该忽略指定键值', () => {
|
||||||
expect(
|
const o = {
|
||||||
ignore(
|
v1: 1,
|
||||||
{
|
v2: {},
|
||||||
v1: 1,
|
v3: [],
|
||||||
v2: {},
|
};
|
||||||
v3: [],
|
|
||||||
v4: undefined,
|
expect(ignore(o, 'v1')).toEqual({
|
||||||
v5: 5,
|
v2: {},
|
||||||
v6: null,
|
v3: [],
|
||||||
},
|
});
|
||||||
'v1',
|
expect(ignore(o, 'v2')).toEqual({
|
||||||
'v2',
|
v1: 1,
|
||||||
'v3',
|
v3: [],
|
||||||
'v4',
|
});
|
||||||
),
|
expect(ignore(o, 'v3')).toEqual({
|
||||||
).toEqual({ v5: 5, v6: null });
|
v1: 1,
|
||||||
|
v2: {},
|
||||||
|
});
|
||||||
|
expect(ignore(o, 'v1', 'v2')).toEqual({
|
||||||
|
v3: [],
|
||||||
|
});
|
||||||
|
expect(ignore(o, 'v2', 'v3')).toEqual({
|
||||||
|
v1: 1,
|
||||||
|
});
|
||||||
|
expect(ignore(o, 'v1', 'v3')).toEqual({
|
||||||
|
v2: {},
|
||||||
|
});
|
||||||
|
expect(ignore(o, 'v1', 'v2', 'v3')).toEqual({});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -4,17 +4,17 @@ import { isAbsoluteURL } from 'src/helpers/isAbsoluteURL';
|
||||||
describe('src/helpers/isAbsoluteURL.ts', () => {
|
describe('src/helpers/isAbsoluteURL.ts', () => {
|
||||||
test('应该不是绝对路径', () => {
|
test('应该不是绝对路径', () => {
|
||||||
expect(isAbsoluteURL('user')).toBeFalsy();
|
expect(isAbsoluteURL('user')).toBeFalsy();
|
||||||
expect(isAbsoluteURL('/user')).toBeFalsy();
|
expect(isAbsoluteURL('/test')).toBeFalsy();
|
||||||
expect(isAbsoluteURL('//user')).toBeFalsy();
|
expect(isAbsoluteURL('//test')).toBeFalsy();
|
||||||
expect(isAbsoluteURL('://user')).toBeFalsy();
|
expect(isAbsoluteURL('://test')).toBeFalsy();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('应该是绝对路径', () => {
|
test('应该是绝对路径', () => {
|
||||||
expect(isAbsoluteURL('http://user')).toBeTruthy();
|
expect(isAbsoluteURL('http://test')).toBeTruthy();
|
||||||
expect(isAbsoluteURL('HTTP://user')).toBeTruthy();
|
expect(isAbsoluteURL('HTTP://test')).toBeTruthy();
|
||||||
expect(isAbsoluteURL('https://user')).toBeTruthy();
|
expect(isAbsoluteURL('https://test')).toBeTruthy();
|
||||||
expect(isAbsoluteURL('custom://user')).toBeTruthy();
|
expect(isAbsoluteURL('custom://test')).toBeTruthy();
|
||||||
expect(isAbsoluteURL('custom-v1.0://user')).toBeTruthy();
|
expect(isAbsoluteURL('custom-v1.0://test')).toBeTruthy();
|
||||||
expect(isAbsoluteURL('custom_v1.0://user')).toBeTruthy();
|
expect(isAbsoluteURL('custom_v1.0://test')).toBeTruthy();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -9,6 +9,6 @@
|
||||||
"noEmit": true,
|
"noEmit": true,
|
||||||
"moduleResolution": "node"
|
"moduleResolution": "node"
|
||||||
},
|
},
|
||||||
"include": ["./src", "./test", "./global.d.ts"],
|
"include": ["./src", "./test", "./global.d.ts", "./global.variables.d.ts"],
|
||||||
"exclude": ["node_modules"]
|
"exclude": ["node_modules"]
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue