Skip to content

Commit f94913f

Browse files
committed
fix(authentication): login and logout interceptor support asynchoronous function
1 parent 7c5132a commit f94913f

File tree

4 files changed

+116
-10
lines changed

4 files changed

+116
-10
lines changed

src/functions/tokenAuthentication/createTokenAuthentication.ts

+5-5
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,9 @@ export const createClientTokenAuthentication = ({
6868
const respondedRecord = onResponded2Record(onRespondedHandlers);
6969
return {
7070
...respondedRecord,
71-
onSuccess: (response, method) => {
72-
callHandlerIfMatchesMeta(method, login, defaultLoginMeta, response);
73-
callHandlerIfMatchesMeta(method, logout, defaultLogoutMeta, response);
71+
onSuccess: async (response, method) => {
72+
await callHandlerIfMatchesMeta(method, login, defaultLoginMeta, response);
73+
await callHandlerIfMatchesMeta(method, logout, defaultLogoutMeta, response);
7474
return (respondedRecord.onSuccess || __self)(response, method);
7575
}
7676
};
@@ -138,8 +138,8 @@ export const createServerTokenAuthentication = ({
138138
}
139139
}
140140

141-
callHandlerIfMatchesMeta(method, login, defaultLoginMeta, response);
142-
callHandlerIfMatchesMeta(method, logout, defaultLogoutMeta, response);
141+
await callHandlerIfMatchesMeta(method, login, defaultLoginMeta, response);
142+
await callHandlerIfMatchesMeta(method, logout, defaultLogoutMeta, response);
143143
return (respondedRecord.onSuccess || __self)(response, method);
144144
},
145145
onError: async (error, method) => {

src/functions/tokenAuthentication/helper.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ export const defaultVisitorMeta = {
6666
isFn(authorizationInterceptor.handler)
6767
? authorizationInterceptor.handler
6868
: noop;
69-
handler(response, method);
69+
return handler(response, method);
7070
}
7171
},
7272
refreshTokenIfExpired = async (

test/functions/createClientTokenAuthentication.spec.ts

+55-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import { createAlova, Method } from 'alova';
1+
import { createAlova, Method, useRequest } from 'alova';
22
import VueHook from 'alova/vue';
33
import { createClientTokenAuthentication } from '../../packages/scene-vue';
44
import { mockRequestAdapter } from '../mockData';
5-
import { generateContinuousNumbers } from '../utils';
5+
import { generateContinuousNumbers, untilCbCalled } from '../utils';
66

77
interface ListResponse {
88
total: number;
@@ -188,6 +188,59 @@ describe('createClientTokenAuthentication', () => {
188188
expect(res2.list).toStrictEqual(generateContinuousNumbers(9));
189189
expect(logoutInterceptorFn).toHaveBeenCalledTimes(2);
190190
});
191+
192+
test('The async functions runing order should be `login -> logout -> global.onSuccess -> useHook.onSuccess`', async () => {
193+
let orderAry = [] as string[];
194+
const { onAuthRequired, onResponseRefreshToken } = createClientTokenAuthentication<
195+
typeof VueHook,
196+
typeof mockRequestAdapter
197+
>({
198+
async login() {
199+
await untilCbCalled(setTimeout, 100);
200+
orderAry.push('login');
201+
},
202+
async logout() {
203+
await untilCbCalled(setTimeout, 100);
204+
orderAry.push('logout');
205+
}
206+
});
207+
const alovaInst = createAlova({
208+
statesHook: VueHook,
209+
requestAdapter: mockRequestAdapter,
210+
localCache: null,
211+
beforeRequest: onAuthRequired(),
212+
responded: onResponseRefreshToken(response => {
213+
orderAry.push('global.onSuccess');
214+
return response;
215+
})
216+
});
217+
const loginMethod = alovaInst.Get<ListResponse>('/list');
218+
loginMethod.meta = {
219+
authRole: 'login'
220+
};
221+
const { onSuccess } = useRequest(loginMethod);
222+
onSuccess(() => {
223+
orderAry.push('useHook.onSuccess');
224+
});
225+
226+
await untilCbCalled(onSuccess);
227+
expect(orderAry).toStrictEqual(['login', 'global.onSuccess', 'useHook.onSuccess']);
228+
229+
// 测试logout
230+
orderAry = [];
231+
const logoutMethod = alovaInst.Get<ListResponse>('/list');
232+
logoutMethod.meta = {
233+
authRole: 'logout'
234+
};
235+
const { onSuccess: onLogoutSuccess } = useRequest(logoutMethod);
236+
onLogoutSuccess(() => {
237+
orderAry.push('useHook.onSuccess');
238+
});
239+
240+
await untilCbCalled(onLogoutSuccess);
241+
expect(orderAry).toStrictEqual(['logout', 'global.onSuccess', 'useHook.onSuccess']);
242+
});
243+
191244
test('should refresh token first when it is expired', async () => {
192245
let token = '';
193246
const refreshTokenFn = jest.fn();

test/functions/createServerTokenAuthentication.spec.ts

+55-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import { createAlova, Method } from 'alova';
1+
import { createAlova, Method, useRequest } from 'alova';
22
import VueHook from 'alova/vue';
33
import { createServerTokenAuthentication } from '../../packages/scene-vue';
44
import { mockRequestAdapter } from '../mockData';
5-
import { generateContinuousNumbers } from '../utils';
5+
import { generateContinuousNumbers, untilCbCalled } from '../utils';
66

77
interface ListResponse {
88
total: number;
@@ -188,6 +188,59 @@ describe('createServerTokenAuthentication', () => {
188188
expect(res2.list).toStrictEqual(generateContinuousNumbers(9));
189189
expect(logoutInterceptorFn).toHaveBeenCalledTimes(2);
190190
});
191+
192+
test('The async functions runing order should be `login -> logout -> global.onSuccess -> useHook.onSuccess`', async () => {
193+
let orderAry = [] as string[];
194+
const { onAuthRequired, onResponseRefreshToken } = createServerTokenAuthentication<
195+
typeof VueHook,
196+
typeof mockRequestAdapter
197+
>({
198+
async login() {
199+
await untilCbCalled(setTimeout, 100);
200+
orderAry.push('login');
201+
},
202+
async logout() {
203+
await untilCbCalled(setTimeout, 100);
204+
orderAry.push('logout');
205+
}
206+
});
207+
const alovaInst = createAlova({
208+
statesHook: VueHook,
209+
requestAdapter: mockRequestAdapter,
210+
localCache: null,
211+
beforeRequest: onAuthRequired(),
212+
responded: onResponseRefreshToken(response => {
213+
orderAry.push('global.onSuccess');
214+
return response;
215+
})
216+
});
217+
const loginMethod = alovaInst.Get<ListResponse>('/list');
218+
loginMethod.meta = {
219+
authRole: 'login'
220+
};
221+
const { onSuccess } = useRequest(loginMethod);
222+
onSuccess(() => {
223+
orderAry.push('useHook.onSuccess');
224+
});
225+
226+
await untilCbCalled(onSuccess);
227+
expect(orderAry).toStrictEqual(['login', 'global.onSuccess', 'useHook.onSuccess']);
228+
229+
// 测试logout
230+
orderAry = [];
231+
const logoutMethod = alovaInst.Get<ListResponse>('/list');
232+
logoutMethod.meta = {
233+
authRole: 'logout'
234+
};
235+
const { onSuccess: onLogoutSuccess } = useRequest(logoutMethod);
236+
onLogoutSuccess(() => {
237+
orderAry.push('useHook.onSuccess');
238+
});
239+
240+
await untilCbCalled(onLogoutSuccess);
241+
expect(orderAry).toStrictEqual(['logout', 'global.onSuccess', 'useHook.onSuccess']);
242+
});
243+
191244
test('should refresh token first on error event when it is expired', async () => {
192245
let token = '';
193246
const expireFn = jest.fn();

0 commit comments

Comments
 (0)