fix: 控制台没有输出适配器错误

pull/49/head
zjx0905 2023-04-20 10:57:10 +08:00
parent d021996c40
commit 258954afc1
6 changed files with 142 additions and 129 deletions

View File

@ -1,4 +1,10 @@
import { AxiosAdapterRequestConfig } from 'src'; import { test } from 'vitest';
import {
requestMethodNames,
requestMethodWithParamsNames,
requestMethodWithDataNames,
} from '@/core/AxiosDomain';
import { AxiosAdapterRequestConfig } from '@/adapter';
export function asyncNext() { export function asyncNext() {
return Promise.resolve().then; return Promise.resolve().then;
@ -106,3 +112,9 @@ export function mockAdapterError(options: MockAdapterOptions = {}) {
export function mockAdapterFail(options: MockAdapterOptions = {}) { export function mockAdapterFail(options: MockAdapterOptions = {}) {
return mockAdapterBase('fail', options); return mockAdapterBase('fail', options);
} }
export const testEachMethods = test.each([
...requestMethodNames,
...requestMethodWithParamsNames,
...requestMethodWithDataNames,
]);

View File

@ -4,7 +4,7 @@ import { Cancel, isCancel, isCancelToken } from './cancel';
import { flattenHeaders } from './flattenHeaders'; import { flattenHeaders } from './flattenHeaders';
import { AxiosTransformer, transformData } from './transformData'; import { AxiosTransformer, transformData } from './transformData';
import { request } from './request'; import { request } from './request';
import { AxiosRequestConfig, AxiosResponse } from './Axios'; import { AxiosRequestConfig, AxiosRequestMethod, AxiosResponse } from './Axios';
import { transformURL } from './transformURL'; import { transformURL } from './transformURL';
import { AxiosErrorResponse } from './createError'; import { AxiosErrorResponse } from './createError';
import { requestMethodWithDataNames } from './AxiosDomain'; import { requestMethodWithDataNames } from './AxiosDomain';
@ -32,6 +32,7 @@ export function dispatchRequest(config: AxiosRequestConfig) {
assert(isString(config.method), 'method 不是一个 string'); assert(isString(config.method), 'method 不是一个 string');
config.url = transformURL(config); config.url = transformURL(config);
config.method = config.method!.toUpperCase() as AxiosRequestMethod;
config.headers = flattenHeaders(config); config.headers = flattenHeaders(config);
// 可以携带 data 的请求方法,转换 data // 可以携带 data 的请求方法,转换 data
@ -49,13 +50,13 @@ export function dispatchRequest(config: AxiosRequestConfig) {
return response; return response;
} }
function onError(reason: Cancel | AxiosErrorResponse) { function onError(error: Cancel | AxiosErrorResponse) {
if (!isCancel(reason)) { if (!isCancel(error)) {
throwIfCancellationRequested(config); throwIfCancellationRequested(config);
dataTransformer(reason.response, config.transformResponse); dataTransformer(error.response, config.transformResponse);
} }
return Promise.reject(reason); return Promise.reject(error);
} }
function dataTransformer<TData = unknown>( function dataTransformer<TData = unknown>(

View File

@ -31,7 +31,7 @@ export function request(config: AxiosRequestConfig) {
...config, ...config,
url: url!, url: url!,
type: generateType(config), type: generateType(config),
method: method!.toUpperCase() as AxiosAdapterRequestMethod, method: method as AxiosAdapterRequestMethod,
success, success,
fail, fail,
}; };
@ -44,6 +44,8 @@ export function request(config: AxiosRequestConfig) {
status: 400, status: 400,
statusText: 'Bad Adapter', statusText: 'Bad Adapter',
}); });
console.error(err);
} }
function success(baseResponse: AxiosAdapterResponse): void { function success(baseResponse: AxiosAdapterResponse): void {

View File

@ -19,8 +19,8 @@ describe.each(platforms)('src/adapter.ts', (p) => {
beforeEach(() => { beforeEach(() => {
vi.stubGlobal(p, { vi.stubGlobal(p, {
request: vi.fn(), request: vi.fn(),
uploadFile: vi.fn(),
downloadFile: vi.fn(), downloadFile: vi.fn(),
uploadFile: vi.fn(),
}); });
}); });
@ -32,7 +32,6 @@ describe.each(platforms)('src/adapter.ts', (p) => {
const a = getDefaultAdapter(); const a = getDefaultAdapter();
if (p !== 'unknown') { if (p !== 'unknown') {
expect(a).toBeTypeOf('function'); expect(a).toBeTypeOf('function');
(expect(a).property('name') as any).toBe('adapter');
} else { } else {
// unknown 未知平台 // unknown 未知平台
expect(a).toBeUndefined(); expect(a).toBeUndefined();

View File

@ -1,14 +1,15 @@
import { describe, test, expect, vi } from 'vitest'; import { describe, test, expect, vi } from 'vitest';
import { asyncNext, mockAdapter } from 'scripts/test.utils'; import { asyncNext, mockAdapter } from 'scripts/test.utils';
import { dispatchRequest } from '@/core/dispatchRequest'; import { dispatchRequest } from '@/core/dispatchRequest';
import axios from '@/axios';
import _defaults from '@/defaults';
import { import {
requestMethodNames, requestMethodNames,
requestMethodWithDataNames, requestMethodWithDataNames,
requestMethodWithParamsNames, requestMethodWithParamsNames,
} from '@/core/AxiosDomain'; } from '@/core/AxiosDomain';
import axios from '@/axios';
import _defaults from '@/defaults';
describe('src/core/dispatchRequest.ts', () => { describe('src/core/dispatchRequest.ts', () => {
const defaults = { const defaults = {
..._defaults, ..._defaults,
@ -37,6 +38,22 @@ describe('src/core/dispatchRequest.ts', () => {
).not.toThrowError(); ).not.toThrowError();
}); });
test.each([
...requestMethodNames,
...requestMethodWithDataNames,
...requestMethodWithParamsNames,
])('应该支持 %s 转全大写', (k) => {
const c = {
adapter: mockAdapter(),
url: '/',
method: k,
};
dispatchRequest(c);
expect(c.method).toBe(k.toUpperCase());
});
test('坏的适配器应该抛出异常', () => { test('坏的适配器应该抛出异常', () => {
expect( expect(
dispatchRequest({ dispatchRequest({
@ -51,7 +68,7 @@ describe('src/core/dispatchRequest.ts', () => {
"config": { "config": {
"adapter": [Function], "adapter": [Function],
"headers": {}, "headers": {},
"method": "get", "method": "GET",
"url": "", "url": "",
}, },
"request": undefined, "request": undefined,
@ -59,7 +76,7 @@ describe('src/core/dispatchRequest.ts', () => {
"config": { "config": {
"adapter": [Function], "adapter": [Function],
"headers": {}, "headers": {},
"method": "get", "method": "GET",
"url": "", "url": "",
}, },
"data": undefined, "data": undefined,
@ -126,19 +143,18 @@ describe('src/core/dispatchRequest.ts', () => {
}); });
}); });
test('应该支持转换请求数据', () => { test.each(requestMethodWithDataNames)('%s 方法应该支持转换请求数据', (k) => {
const c = { const c = {
...defaults, ...defaults,
url: 'test', url: 'test',
method: k,
data: {}, data: {},
transformRequest: () => ({ id: 1 }), transformRequest: () => ({ id: 1 }),
}; };
requestMethodWithDataNames.forEach((k) => { dispatchRequest(c);
const s = { ...c, method: k };
dispatchRequest(s); expect(c.data).toEqual({ id: 1 });
expect(s.data).toEqual({ id: 1 });
});
}); });
test('不能带数据的请求方法应该删除数据', () => { test('不能带数据的请求方法应该删除数据', () => {

View File

@ -4,6 +4,7 @@ import {
mockAdapter, mockAdapter,
mockAdapterError, mockAdapterError,
mockAdapterFail, mockAdapterFail,
testEachMethods,
} from 'scripts/test.utils'; } from 'scripts/test.utils';
import { request } from '@/core/request'; import { request } from '@/core/request';
import { import {
@ -14,128 +15,110 @@ import {
import axios from '@/axios'; import axios from '@/axios';
describe('src/core/request.ts', () => { describe('src/core/request.ts', () => {
test('应该返回正确的响应体结构', () => { testEachMethods('%s 方法应该返回正确的响应体结构', (k) => {
[ const c = {
...requestMethodNames, adapter: mockAdapter(),
...requestMethodWithDataNames, url: '/test',
...requestMethodWithParamsNames, method: k,
].forEach((k) => { };
request({
adapter: mockAdapter(), request(c).then((response) => {
url: '/test', expect(response.status).toBeTypeOf('number');
method: k, expect(response.statusText).toBeTypeOf('string');
}).then((response) => { expect(response.headers).toBeTypeOf('object');
expect(response.status).toBeTypeOf('number'); expect(response.data).toBeTypeOf('object');
expect(response.statusText).toBeTypeOf('string'); expect(response.config).toBeTypeOf('object');
expect(response.headers).toBeTypeOf('object'); expect(response.request).toBeTypeOf('object');
expect(response.data).toBeTypeOf('object');
expect(response.config).toBeTypeOf('object');
expect(response.request).toBeTypeOf('object');
});
}); });
}); });
test('应该支持补全响应体结构', () => { testEachMethods('%s 方法应该支持补全响应体结构', (k) => {
[ const c = {
...requestMethodNames, // @ts-ignore
...requestMethodWithDataNames, adapter: ({ success }) => {
...requestMethodWithParamsNames, success({
].forEach((k) => { data: {},
request({ });
adapter: ({ success }) => { },
success({ url: '/test',
data: {}, method: k,
}); };
},
url: '/test', request(c).then((response) => {
method: k, expect(response.status).toBeTypeOf('number');
}).then((response) => { expect(response.statusText).toBeTypeOf('string');
expect(response.status).toBeTypeOf('number'); expect(response.headers).toBeTypeOf('object');
expect(response.statusText).toBeTypeOf('string'); expect(response.data).toBeTypeOf('object');
expect(response.headers).toBeTypeOf('object'); expect(response.isFail).toBeTypeOf('undefined');
expect(response.data).toBeTypeOf('object'); expect(response.config).toBeTypeOf('object');
expect(response.isFail).toBeTypeOf('undefined'); expect(response.request).toBeTypeOf('undefined');
expect(response.config).toBeTypeOf('object');
expect(response.request).toBeTypeOf('undefined');
});
}); });
}); });
test('应该返回正确的响应错误结构', () => { testEachMethods('%s 方法应该返回正确的响应错误结构', (k) => {
[ const c = {
...requestMethodNames, adapter: mockAdapterError(),
...requestMethodWithDataNames, validateStatus: () => false,
...requestMethodWithParamsNames, url: '/test',
].forEach((k) => { method: k,
request({ };
adapter: mockAdapterError(),
validateStatus: () => false, request(c).catch((error) => {
url: '/test', expect(error.message).toBeTypeOf('string');
method: k, expect(error.config).toBeTypeOf('object');
}).catch((error) => { expect(error.request).toBeTypeOf('object');
expect(error.message).toBeTypeOf('string'); expect(error.response.status).toBeTypeOf('number');
expect(error.config).toBeTypeOf('object'); expect(error.response.statusText).toBeTypeOf('string');
expect(error.request).toBeTypeOf('object'); expect(error.response.headers).toBeTypeOf('object');
expect(error.response.status).toBeTypeOf('number'); expect(error.response.data).toBeTypeOf('object');
expect(error.response.statusText).toBeTypeOf('string'); expect(error.response.isFail).toBeTypeOf('undefined');
expect(error.response.headers).toBeTypeOf('object'); expect(error.response.config).toBeTypeOf('object');
expect(error.response.data).toBeTypeOf('object'); expect(error.response.request).toBeTypeOf('object');
expect(error.response.isFail).toBeTypeOf('undefined');
expect(error.response.config).toBeTypeOf('object');
expect(error.response.request).toBeTypeOf('object');
});
}); });
}); });
test('应该返回正确的平台错误结构', () => { testEachMethods('%s 方法应该返回正确的平台错误结构', (k) => {
[ const c = {
...requestMethodNames, adapter: mockAdapterFail(),
...requestMethodWithDataNames, validateStatus: () => false,
...requestMethodWithParamsNames, url: '/test',
].forEach((k) => { method: k,
request({ };
adapter: mockAdapterFail(),
validateStatus: () => false, request(c).catch((error) => {
url: '/test', expect(error.message).toBeTypeOf('string');
method: k, expect(error.config).toBeTypeOf('object');
}).catch((error) => { expect(error.request).toBeTypeOf('object');
expect(error.message).toBeTypeOf('string'); expect(error.response.status).toBeTypeOf('number');
expect(error.config).toBeTypeOf('object'); expect(error.response.statusText).toBeTypeOf('string');
expect(error.request).toBeTypeOf('object'); expect(error.response.headers).toBeTypeOf('object');
expect(error.response.status).toBeTypeOf('number'); expect(error.response.data).toBeTypeOf('object');
expect(error.response.statusText).toBeTypeOf('string'); expect(error.response.isFail).toBeTruthy();
expect(error.response.headers).toBeTypeOf('object'); expect(error.response.config).toBeTypeOf('object');
expect(error.response.data).toBeTypeOf('object'); expect(error.response.request).toBeTypeOf('object');
expect(error.response.isFail).toBeTruthy();
expect(error.response.config).toBeTypeOf('object');
expect(error.response.request).toBeTypeOf('object');
});
}); });
}); });
test('应该支持补全错误体结构', () => { testEachMethods('%s 方法应该支持补全错误体结构', (k) => {
[ const c = {
...requestMethodNames, // @ts-ignore
...requestMethodWithDataNames, adapter: ({ fail }) => {
...requestMethodWithParamsNames, fail({
].forEach((k) => { data: {},
request({ });
adapter: ({ fail }) => { },
fail({ url: '/test',
data: {}, method: k,
}); };
},
url: '/test', request(c).catch((error) => {
method: k, expect(error.response.status).toBeTypeOf('number');
}).catch((error) => { expect(error.response.statusText).toBeTypeOf('string');
expect(error.response.status).toBeTypeOf('number'); expect(error.response.headers).toBeTypeOf('object');
expect(error.response.statusText).toBeTypeOf('string'); expect(error.response.data).toBeTypeOf('object');
expect(error.response.headers).toBeTypeOf('object'); expect(error.response.isFail).toBeTruthy();
expect(error.response.data).toBeTypeOf('object'); expect(error.response.config).toBeTypeOf('object');
expect(error.response.isFail).toBeTruthy(); expect(error.response.request).toBeTypeOf('undefined');
expect(error.response.config).toBeTypeOf('object');
expect(error.response.request).toBeTypeOf('undefined');
});
}); });
}); });