Skip to content

Commit ce12a83

Browse files
committed
test: 测试 generateType
1 parent 0cfb3e1 commit ce12a83

File tree

8 files changed

+215
-74
lines changed

8 files changed

+215
-74
lines changed

scripts/test.utils.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { AxiosAdapterRequestConfig } from 'src';
2+
13
export function asyncNext() {
24
return Promise.resolve().then;
35
}
@@ -47,3 +49,38 @@ export function mockSuccess(headers: AnyObject = {}, data: AnyObject = {}) {
4749
export function mockFail(headers: AnyObject = {}, data: AnyObject = {}) {
4850
return mockResponse(400, 'FAIL', headers, data);
4951
}
52+
53+
export interface MockAdapterOptions {
54+
headers?: AnyObject;
55+
data?: AnyObject;
56+
delay?: number;
57+
before?: (config: AxiosAdapterRequestConfig) => void;
58+
after?: () => void;
59+
}
60+
61+
export function mockAdapter(
62+
type: 'success' | 'fail',
63+
options: MockAdapterOptions = {},
64+
) {
65+
const { headers = {}, data = {}, delay = 0, before, after } = options;
66+
67+
return (config: AxiosAdapterRequestConfig) => {
68+
before?.(config);
69+
setTimeout(() => {
70+
if (type === 'success') {
71+
config.success(mockSuccess(headers, data));
72+
} else {
73+
config.fail(mockFail(headers, data));
74+
}
75+
after?.();
76+
}, delay);
77+
};
78+
}
79+
80+
export function mockAdapterSuccess(options: MockAdapterOptions = {}) {
81+
return mockAdapter('success', options);
82+
}
83+
84+
export function mockAdapterFail(options: MockAdapterOptions = {}) {
85+
return mockAdapter('fail', options);
86+
}

src/core/Axios.ts

Lines changed: 67 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -138,15 +138,82 @@ export interface AxiosConstructor {
138138
}
139139

140140
export default class Axios {
141+
public static as = ['options', 'trace', 'connect'] as const;
142+
public static pas = ['head', 'get', 'delete'] as const;
143+
public static das = ['post', 'put'] as const;
144+
141145
public defaults: AxiosRequestConfig;
142146

143147
public interceptors = {
144148
request: new InterceptorManager<AxiosRequestConfig>(),
145149
response: new InterceptorManager<AxiosResponse>(),
146150
};
147151

152+
public options!: <TData = unknown>(
153+
url: string,
154+
config?: AxiosRequestConfig,
155+
) => Promise<AxiosResponse<TData>>;
156+
157+
public get!: <TData = unknown>(
158+
url: string,
159+
params?: AnyObject,
160+
config?: AxiosRequestConfig,
161+
) => Promise<AxiosResponse<TData>>;
162+
163+
public head!: <TData = unknown>(
164+
url: string,
165+
params?: AnyObject,
166+
config?: AxiosRequestConfig,
167+
) => Promise<AxiosResponse<TData>>;
168+
169+
public post!: <TData = unknown>(
170+
url: string,
171+
data?: AnyObject | AxiosRequestFormData,
172+
config?: AxiosRequestConfig,
173+
) => Promise<AxiosResponse<TData>>;
174+
175+
public put!: <TData = unknown>(
176+
url: string,
177+
data?: AnyObject | AxiosRequestFormData,
178+
config?: AxiosRequestConfig,
179+
) => Promise<AxiosResponse<TData>>;
180+
181+
public delete!: <TData = unknown>(
182+
url: string,
183+
params?: AnyObject,
184+
config?: AxiosRequestConfig,
185+
) => Promise<AxiosResponse<TData>>;
186+
187+
public trace!: <TData = unknown>(
188+
url: string,
189+
config?: AxiosRequestConfig,
190+
) => Promise<AxiosResponse<TData>>;
191+
192+
public connect!: <TData = unknown>(
193+
url: string,
194+
config?: AxiosRequestConfig,
195+
) => Promise<AxiosResponse<TData>>;
196+
148197
public constructor(defaults: AxiosRequestConfig = {}) {
149198
this.defaults = defaults;
199+
200+
for (const alias of Axios.as) {
201+
this[alias] = (url, config) => {
202+
return this._req(alias, url, undefined, config);
203+
};
204+
}
205+
206+
for (const alias of Axios.pas) {
207+
this[alias] = (url, params, config) => {
208+
return this._req(alias, url, params, config);
209+
};
210+
}
211+
212+
for (const alias of Axios.das) {
213+
this[alias] = (url, data, config) => {
214+
return this._reqWithData(alias, url, data, config);
215+
};
216+
}
150217
}
151218

152219
public getUri(config: AxiosRequestConfig): string {
@@ -183,67 +250,6 @@ export default class Axios {
183250
return promiseResponse as Promise<AxiosResponse<TData>>;
184251
}
185252

186-
public options<TData = unknown>(
187-
url: string,
188-
config?: AxiosRequestConfig,
189-
): Promise<AxiosResponse<TData>> {
190-
return this._req<TData>('options', url, undefined, config);
191-
}
192-
193-
public get<TData = unknown>(
194-
url: string,
195-
params?: AnyObject,
196-
config?: AxiosRequestConfig,
197-
): Promise<AxiosResponse<TData>> {
198-
return this._req<TData>('get', url, params, config);
199-
}
200-
201-
public head<TData = unknown>(
202-
url: string,
203-
params?: AnyObject,
204-
config?: AxiosRequestConfig,
205-
): Promise<AxiosResponse<TData>> {
206-
return this._req<TData>('head', url, params, config);
207-
}
208-
209-
public post<TData = unknown>(
210-
url: string,
211-
data?: AnyObject | AxiosRequestFormData,
212-
config?: AxiosRequestConfig,
213-
): Promise<AxiosResponse<TData>> {
214-
return this._reqWithData<TData>('post', url, data, config);
215-
}
216-
217-
public put<TData = unknown>(
218-
url: string,
219-
data?: AnyObject | AxiosRequestFormData,
220-
config?: AxiosRequestConfig,
221-
): Promise<AxiosResponse<TData>> {
222-
return this._reqWithData<TData>('put', url, data, config);
223-
}
224-
225-
public delete<TData = unknown>(
226-
url: string,
227-
params?: AnyObject,
228-
config?: AxiosRequestConfig,
229-
): Promise<AxiosResponse<TData>> {
230-
return this._req<TData>('delete', url, params, config);
231-
}
232-
233-
public trace<TData = unknown>(
234-
url: string,
235-
config?: AxiosRequestConfig,
236-
): Promise<AxiosResponse<TData>> {
237-
return this._req<TData>('trace', url, undefined, config);
238-
}
239-
240-
public connect<TData = unknown>(
241-
url: string,
242-
config?: AxiosRequestConfig,
243-
): Promise<AxiosResponse<TData>> {
244-
return this._req<TData>('connect', url, undefined, config);
245-
}
246-
247253
private _req<TData = unknown>(
248254
method: AxiosRequestMethod,
249255
url: string,

src/core/dispatchRequest.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
import { isPlainObject } from '../helpers/isTypes';
2-
import { isCancel } from './cancel';
2+
import { isCancel, isCancelToken } from './cancel';
33
import { flattenHeaders } from './flattenHeaders';
44
import { transformData } from './transformData';
55
import { request } from './request';
66
import { AxiosRequestConfig, AxiosResponse } from './Axios';
77
import { transformURL } from './transformURL';
88

99
function throwIfCancellationRequested(config: AxiosRequestConfig) {
10-
if (config.cancelToken) {
11-
config.cancelToken.throwIfRequested();
10+
const { cancelToken } = config;
11+
if (isCancelToken(cancelToken)) {
12+
cancelToken.throwIfRequested();
1213
}
1314
}
1415

src/core/request.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ export function request<TData = unknown>(
5252
fail,
5353
};
5454

55-
const adapterTask = config.adapter?.(adapterConfig) as
55+
const adapterTask = config.adapter!(adapterConfig) as
5656
| AxiosAdapterTask
5757
| undefined;
5858

@@ -83,8 +83,9 @@ export function request<TData = unknown>(
8383
tryToggleProgressUpdate(adapterConfig, adapterTask.onProgressUpdate);
8484
}
8585

86-
if (isCancelToken(config.cancelToken)) {
87-
config.cancelToken.onCancel((reason: unknown) => {
86+
const { cancelToken } = config;
87+
if (isCancelToken(cancelToken)) {
88+
cancelToken.onCancel((reason) => {
8889
if (isPlainObject(adapterTask)) {
8990
tryToggleProgressUpdate(adapterConfig, adapterTask.offProgressUpdate);
9091

src/helpers/error.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,8 @@ export function throwError(msg: string): void {
1313
export function cleanStack(error: Error) {
1414
if (error.stack) {
1515
const start = error.stack.indexOf('at');
16-
const end = error.stack.indexOf('at /');
17-
18-
if (start !== end) {
16+
const end = error.stack.search(/at ([\w-_.]+:)?\//i);
17+
if (start < end) {
1918
const removed = error.stack.slice(start, end);
2019
error.stack = error.stack.replace(removed, '');
2120
}

test/axios.test.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { describe, test, expect } from 'vitest';
2+
import axios from 'src/axios';
3+
import { mockAdapterFail, mockAdapterSuccess } from 'scripts/test.utils';
4+
5+
describe('src/axios.ts', () => {
6+
test('应该处理成功和失败', () => {
7+
axios({
8+
adapter: mockAdapterSuccess({
9+
headers: { type: 'json' },
10+
data: { v1: 1 },
11+
before: (config) => {
12+
expect(config.url).toBe('http://api.com/user/1?id=1');
13+
},
14+
}),
15+
baseURL: 'http://api.com',
16+
url: 'user/:id',
17+
params: {
18+
id: 1,
19+
},
20+
}).then((response) => {
21+
expect(response.headers).toEqual({ type: 'json' });
22+
expect(response.data).toEqual({ v1: 1 });
23+
});
24+
25+
axios('user/:id', {
26+
adapter: mockAdapterFail({
27+
headers: { type: 'json' },
28+
data: { v1: 1 },
29+
before: (config) => {
30+
expect(config.url).toBe('http://api.com/user/1');
31+
},
32+
}),
33+
baseURL: 'http://api.com',
34+
data: {
35+
id: 1,
36+
},
37+
}).catch((error) => {
38+
expect(error.response.headers).toEqual({ type: 'json' });
39+
expect(error.response.data).toEqual({ v1: 1 });
40+
});
41+
});
42+
});

test/core/cancel.test.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,17 @@ import { describe, test, expect, vi } from 'vitest';
22
import {
33
asyncNext,
44
captureError,
5-
mockSuccess,
5+
mockAdapterSuccess,
66
noop,
77
asyncTimeout,
88
} from 'scripts/test.utils';
99
import axios from 'src/axios';
10-
import { Cancel, isCancel, CancelToken, isCancelToken } from 'src/core/cancel';
10+
import {
11+
Cancel,
12+
isCancel,
13+
CancelToken,
14+
isCancelToken,
15+
} from '../../src/core/cancel';
1116

1217
describe('src/helpers/cancel.ts', () => {
1318
test('应该支持空参数', () => {
@@ -100,7 +105,7 @@ describe('src/helpers/cancel.ts', () => {
100105

101106
source.cancel();
102107
axios({
103-
adapter: ({ success }) => success(mockSuccess()),
108+
adapter: mockAdapterSuccess(),
104109
cancelToken: source.token,
105110
}).catch(canceled);
106111

@@ -114,7 +119,7 @@ describe('src/helpers/cancel.ts', () => {
114119
const source = CancelToken.source();
115120

116121
axios({
117-
adapter: ({ success }) => success(mockSuccess()),
122+
adapter: mockAdapterSuccess(),
118123
cancelToken: source.token,
119124
}).catch(canceled);
120125
source.cancel();

test/core/generateType.test.ts

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import { describe, test, expect } from 'vitest';
2+
import { mockAdapterSuccess } from 'scripts/test.utils';
3+
import { generateType } from 'src/core/generateType';
4+
import Axios from 'src/core/Axios';
5+
import axios from 'src/axios';
6+
7+
describe('src/core/generateType.ts', () => {
8+
test('应该是一个 reuqest', () => {
9+
for (const alias of [...Axios.as, ...Axios.pas, ...Axios.das]) {
10+
expect(generateType({ method: alias })).toBe('request');
11+
12+
axios({
13+
adapter: mockAdapterSuccess({
14+
before: (config) => {
15+
expect(config.type).toBe('request');
16+
},
17+
}),
18+
method: alias,
19+
});
20+
}
21+
});
22+
23+
test('应该是一个 upload', () => {
24+
expect(generateType({ method: 'post', upload: true })).toBe('upload');
25+
26+
axios({
27+
adapter: mockAdapterSuccess({
28+
before: (config) => {
29+
expect(config.type).toBe('upload');
30+
},
31+
}),
32+
method: 'post',
33+
upload: true,
34+
});
35+
});
36+
37+
test('应该是一个 download', () => {
38+
expect(generateType({ method: 'get', download: true })).toBe('download');
39+
40+
axios({
41+
adapter: mockAdapterSuccess({
42+
before: (config) => {
43+
expect(config.type).toBe('download');
44+
},
45+
}),
46+
method: 'get',
47+
download: true,
48+
});
49+
});
50+
});

0 commit comments

Comments
 (0)