Skip to content

Commit

Permalink
Merge pull request #55 from alovajs/release/v1.4.x
Browse files Browse the repository at this point in the history
fix(authentication): login and logout interceptor support asynchoronous function
  • Loading branch information
JOU-amjs committed Mar 4, 2024
2 parents 71dc38f + f94913f commit 164fbe8
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 10 deletions.
10 changes: 5 additions & 5 deletions src/functions/tokenAuthentication/createTokenAuthentication.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,9 @@ export const createClientTokenAuthentication = ({
const respondedRecord = onResponded2Record(onRespondedHandlers);
return {
...respondedRecord,
onSuccess: (response, method) => {
callHandlerIfMatchesMeta(method, login, defaultLoginMeta, response);
callHandlerIfMatchesMeta(method, logout, defaultLogoutMeta, response);
onSuccess: async (response, method) => {
await callHandlerIfMatchesMeta(method, login, defaultLoginMeta, response);
await callHandlerIfMatchesMeta(method, logout, defaultLogoutMeta, response);
return (respondedRecord.onSuccess || __self)(response, method);
}
};
Expand Down Expand Up @@ -138,8 +138,8 @@ export const createServerTokenAuthentication = ({
}
}

callHandlerIfMatchesMeta(method, login, defaultLoginMeta, response);
callHandlerIfMatchesMeta(method, logout, defaultLogoutMeta, response);
await callHandlerIfMatchesMeta(method, login, defaultLoginMeta, response);
await callHandlerIfMatchesMeta(method, logout, defaultLogoutMeta, response);
return (respondedRecord.onSuccess || __self)(response, method);
},
onError: async (error, method) => {
Expand Down
2 changes: 1 addition & 1 deletion src/functions/tokenAuthentication/helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ export const defaultVisitorMeta = {
isFn(authorizationInterceptor.handler)
? authorizationInterceptor.handler
: noop;
handler(response, method);
return handler(response, method);
}
},
refreshTokenIfExpired = async (
Expand Down
57 changes: 55 additions & 2 deletions test/functions/createClientTokenAuthentication.spec.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { createAlova, Method } from 'alova';
import { createAlova, Method, useRequest } from 'alova';
import VueHook from 'alova/vue';
import { createClientTokenAuthentication } from '../../packages/scene-vue';
import { mockRequestAdapter } from '../mockData';
import { generateContinuousNumbers } from '../utils';
import { generateContinuousNumbers, untilCbCalled } from '../utils';

interface ListResponse {
total: number;
Expand Down Expand Up @@ -188,6 +188,59 @@ describe('createClientTokenAuthentication', () => {
expect(res2.list).toStrictEqual(generateContinuousNumbers(9));
expect(logoutInterceptorFn).toHaveBeenCalledTimes(2);
});

test('The async functions runing order should be `login -> logout -> global.onSuccess -> useHook.onSuccess`', async () => {
let orderAry = [] as string[];
const { onAuthRequired, onResponseRefreshToken } = createClientTokenAuthentication<
typeof VueHook,
typeof mockRequestAdapter
>({
async login() {
await untilCbCalled(setTimeout, 100);
orderAry.push('login');
},
async logout() {
await untilCbCalled(setTimeout, 100);
orderAry.push('logout');
}
});
const alovaInst = createAlova({
statesHook: VueHook,
requestAdapter: mockRequestAdapter,
localCache: null,
beforeRequest: onAuthRequired(),
responded: onResponseRefreshToken(response => {
orderAry.push('global.onSuccess');
return response;
})
});
const loginMethod = alovaInst.Get<ListResponse>('/list');
loginMethod.meta = {
authRole: 'login'
};
const { onSuccess } = useRequest(loginMethod);
onSuccess(() => {
orderAry.push('useHook.onSuccess');
});

await untilCbCalled(onSuccess);
expect(orderAry).toStrictEqual(['login', 'global.onSuccess', 'useHook.onSuccess']);

// 测试logout
orderAry = [];
const logoutMethod = alovaInst.Get<ListResponse>('/list');
logoutMethod.meta = {
authRole: 'logout'
};
const { onSuccess: onLogoutSuccess } = useRequest(logoutMethod);
onLogoutSuccess(() => {
orderAry.push('useHook.onSuccess');
});

await untilCbCalled(onLogoutSuccess);
expect(orderAry).toStrictEqual(['logout', 'global.onSuccess', 'useHook.onSuccess']);
});

test('should refresh token first when it is expired', async () => {
let token = '';
const refreshTokenFn = jest.fn();
Expand Down
57 changes: 55 additions & 2 deletions test/functions/createServerTokenAuthentication.spec.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { createAlova, Method } from 'alova';
import { createAlova, Method, useRequest } from 'alova';
import VueHook from 'alova/vue';
import { createServerTokenAuthentication } from '../../packages/scene-vue';
import { mockRequestAdapter } from '../mockData';
import { generateContinuousNumbers } from '../utils';
import { generateContinuousNumbers, untilCbCalled } from '../utils';

interface ListResponse {
total: number;
Expand Down Expand Up @@ -188,6 +188,59 @@ describe('createServerTokenAuthentication', () => {
expect(res2.list).toStrictEqual(generateContinuousNumbers(9));
expect(logoutInterceptorFn).toHaveBeenCalledTimes(2);
});

test('The async functions runing order should be `login -> logout -> global.onSuccess -> useHook.onSuccess`', async () => {
let orderAry = [] as string[];
const { onAuthRequired, onResponseRefreshToken } = createServerTokenAuthentication<
typeof VueHook,
typeof mockRequestAdapter
>({
async login() {
await untilCbCalled(setTimeout, 100);
orderAry.push('login');
},
async logout() {
await untilCbCalled(setTimeout, 100);
orderAry.push('logout');
}
});
const alovaInst = createAlova({
statesHook: VueHook,
requestAdapter: mockRequestAdapter,
localCache: null,
beforeRequest: onAuthRequired(),
responded: onResponseRefreshToken(response => {
orderAry.push('global.onSuccess');
return response;
})
});
const loginMethod = alovaInst.Get<ListResponse>('/list');
loginMethod.meta = {
authRole: 'login'
};
const { onSuccess } = useRequest(loginMethod);
onSuccess(() => {
orderAry.push('useHook.onSuccess');
});

await untilCbCalled(onSuccess);
expect(orderAry).toStrictEqual(['login', 'global.onSuccess', 'useHook.onSuccess']);

// 测试logout
orderAry = [];
const logoutMethod = alovaInst.Get<ListResponse>('/list');
logoutMethod.meta = {
authRole: 'logout'
};
const { onSuccess: onLogoutSuccess } = useRequest(logoutMethod);
onLogoutSuccess(() => {
orderAry.push('useHook.onSuccess');
});

await untilCbCalled(onLogoutSuccess);
expect(orderAry).toStrictEqual(['logout', 'global.onSuccess', 'useHook.onSuccess']);
});

test('should refresh token first on error event when it is expired', async () => {
let token = '';
const expireFn = jest.fn();
Expand Down

0 comments on commit 164fbe8

Please sign in to comment.