mirror of
https://github.com/elyby/accounts-frontend.git
synced 2024-11-19 06:32:58 +05:30
Add tests for auth middlewares
This commit is contained in:
parent
5d054c3baa
commit
54664044eb
@ -4,6 +4,8 @@ import request from 'services/request';
|
|||||||
import bearerHeaderMiddleware from './middlewares/bearerHeaderMiddleware';
|
import bearerHeaderMiddleware from './middlewares/bearerHeaderMiddleware';
|
||||||
import refreshTokenMiddleware from './middlewares/refreshTokenMiddleware';
|
import refreshTokenMiddleware from './middlewares/refreshTokenMiddleware';
|
||||||
|
|
||||||
|
let promise;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes User state with the fresh data
|
* Initializes User state with the fresh data
|
||||||
*
|
*
|
||||||
@ -12,10 +14,14 @@ import refreshTokenMiddleware from './middlewares/refreshTokenMiddleware';
|
|||||||
* @return {Promise} - a promise, that resolves in User state
|
* @return {Promise} - a promise, that resolves in User state
|
||||||
*/
|
*/
|
||||||
export function factory(store) {
|
export function factory(store) {
|
||||||
|
if (promise) {
|
||||||
|
return promise;
|
||||||
|
}
|
||||||
|
|
||||||
request.addMiddleware(refreshTokenMiddleware(store));
|
request.addMiddleware(refreshTokenMiddleware(store));
|
||||||
request.addMiddleware(bearerHeaderMiddleware(store));
|
request.addMiddleware(bearerHeaderMiddleware(store));
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
promise = new Promise((resolve, reject) => {
|
||||||
const {user} = store.getState();
|
const {user} = store.getState();
|
||||||
|
|
||||||
if (user.token) {
|
if (user.token) {
|
||||||
@ -26,4 +32,6 @@ export function factory(store) {
|
|||||||
// auto-detect guests language
|
// auto-detect guests language
|
||||||
store.dispatch(changeLang(user.lang)).then(resolve, reject);
|
store.dispatch(changeLang(user.lang)).then(resolve, reject);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return promise;
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ export default function refreshTokenMiddleware({dispatch, getState}) {
|
|||||||
const {isGuest, refreshToken, token} = getState().user;
|
const {isGuest, refreshToken, token} = getState().user;
|
||||||
const isRefreshTokenRequest = data.url.includes('refresh-token');
|
const isRefreshTokenRequest = data.url.includes('refresh-token');
|
||||||
|
|
||||||
if (isGuest || isRefreshTokenRequest || !token) {
|
if (isGuest || isRefreshTokenRequest) {
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,14 +65,14 @@ export default function refreshTokenMiddleware({dispatch, getState}) {
|
|||||||
function requestAccessToken(refreshToken, dispatch) {
|
function requestAccessToken(refreshToken, dispatch) {
|
||||||
let promise;
|
let promise;
|
||||||
if (refreshToken) {
|
if (refreshToken) {
|
||||||
promise = authentication.refreshToken(refreshToken);
|
promise = authentication.requestToken(refreshToken);
|
||||||
} else {
|
} else {
|
||||||
promise = Promise.reject();
|
promise = Promise.reject();
|
||||||
}
|
}
|
||||||
|
|
||||||
return promise
|
return promise
|
||||||
.then((resp) => dispatch(updateUser({
|
.then(({token}) => dispatch(updateUser({
|
||||||
token: resp.access_token
|
token
|
||||||
})))
|
})))
|
||||||
.catch(() => dispatch(logout()));
|
.catch(() => dispatch(logout()));
|
||||||
}
|
}
|
||||||
|
@ -36,10 +36,19 @@ export default {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
refreshToken(refresh_token) {
|
/**
|
||||||
|
* Request new access token using a refreshToken
|
||||||
|
*
|
||||||
|
* @param {string} refreshToken
|
||||||
|
*
|
||||||
|
* @return {Promise} - resolves to {token}
|
||||||
|
*/
|
||||||
|
requestToken(refreshToken) {
|
||||||
return request.post(
|
return request.post(
|
||||||
'/api/authentication/refresh-token',
|
'/api/authentication/refresh-token',
|
||||||
{refresh_token}
|
{refresh_token: refreshToken}
|
||||||
);
|
).then((resp) => ({
|
||||||
|
token: resp.access_token
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -0,0 +1,44 @@
|
|||||||
|
import expect from 'unexpected';
|
||||||
|
|
||||||
|
import bearerHeaderMiddleware from 'components/user/middlewares/bearerHeaderMiddleware';
|
||||||
|
|
||||||
|
describe('bearerHeaderMiddleware', () => {
|
||||||
|
it('should set Authorization header', () => {
|
||||||
|
const token = 'foo';
|
||||||
|
const middleware = bearerHeaderMiddleware({
|
||||||
|
getState: () => ({
|
||||||
|
user: {token}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
options: {
|
||||||
|
headers: {}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
middleware.before(data);
|
||||||
|
|
||||||
|
expect(data.options.headers, 'to satisfy', {
|
||||||
|
Authorization: `Bearer ${token}`
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not set Authorization header if no token', () => {
|
||||||
|
const middleware = bearerHeaderMiddleware({
|
||||||
|
getState: () => ({
|
||||||
|
user: {}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
options: {
|
||||||
|
headers: {}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
middleware.before(data);
|
||||||
|
|
||||||
|
expect(data.options.headers.Authorization, 'to be undefined');
|
||||||
|
});
|
||||||
|
});
|
154
tests/components/user/middlewares/refreshTokenMiddleware.test.js
Normal file
154
tests/components/user/middlewares/refreshTokenMiddleware.test.js
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
import expect from 'unexpected';
|
||||||
|
|
||||||
|
import refreshTokenMiddleware from 'components/user/middlewares/refreshTokenMiddleware';
|
||||||
|
|
||||||
|
import authentication from 'services/api/authentication';
|
||||||
|
|
||||||
|
const refreshToken = 'foo';
|
||||||
|
const expiredToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYmYiOjE0NzA3NjE0NDMsImV4cCI6MTQ3MDc2MTQ0MywiaWF0IjoxNDcwNzYxNDQzLCJqdGkiOiJpZDEyMzQ1NiJ9.gWdnzfQQvarGpkbldUvB8qdJZSVkvdNtCbhbbl2yJW8';
|
||||||
|
// valid till 2100 year
|
||||||
|
const validToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYmYiOjE0NzA3NjE5NzcsImV4cCI6NDEwMjQ0NDgwMCwiaWF0IjoxNDcwNzYxOTc3LCJqdGkiOiJpZDEyMzQ1NiJ9.M4KY4QgHOUzhpAZjWoHJbGsEJPR-RBsJ1c1BKyxvAoU';
|
||||||
|
|
||||||
|
describe('refreshTokenMiddleware', () => {
|
||||||
|
let middleware;
|
||||||
|
let getState;
|
||||||
|
let dispatch;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
sinon.stub(authentication, 'requestToken').named('authentication.requestToken');
|
||||||
|
|
||||||
|
getState = sinon.stub().named('store.getState');
|
||||||
|
dispatch = sinon.stub().named('store.dispatch');
|
||||||
|
|
||||||
|
middleware = refreshTokenMiddleware({getState, dispatch});
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
authentication.requestToken.restore();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#before', () => {
|
||||||
|
it('should request new token', () => {
|
||||||
|
getState.returns({
|
||||||
|
user: {
|
||||||
|
token: expiredToken,
|
||||||
|
refreshToken,
|
||||||
|
isGuest: false
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
url: 'foo',
|
||||||
|
options: {
|
||||||
|
headers: {}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
authentication.requestToken.returns(Promise.resolve({token: validToken}));
|
||||||
|
|
||||||
|
return middleware.before(data).then((resp) => {
|
||||||
|
expect(resp, 'to satisfy', data);
|
||||||
|
|
||||||
|
expect(authentication.requestToken, 'to have a call satisfying', [
|
||||||
|
refreshToken
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not be applied for guests', () => {
|
||||||
|
getState.returns({
|
||||||
|
user: {
|
||||||
|
isGuest: true
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
authentication.requestToken.returns(Promise.resolve({token: validToken}));
|
||||||
|
|
||||||
|
const data = {url: 'foo'};
|
||||||
|
const resp = middleware.before(data);
|
||||||
|
|
||||||
|
expect(resp, 'to satisfy', data);
|
||||||
|
|
||||||
|
expect(authentication.requestToken, 'was not called');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not apply to refresh-token request', () => {
|
||||||
|
getState.returns({
|
||||||
|
user: {}
|
||||||
|
});
|
||||||
|
|
||||||
|
authentication.requestToken.returns(Promise.resolve({token: validToken}));
|
||||||
|
|
||||||
|
const data = {url: '/refresh-token'};
|
||||||
|
const resp = middleware.before(data);
|
||||||
|
|
||||||
|
expect(resp, 'to satisfy', data);
|
||||||
|
|
||||||
|
expect(authentication.requestToken, 'was not called');
|
||||||
|
});
|
||||||
|
|
||||||
|
xit('should update user with new token'); // TODO: need a way to test, that action was called
|
||||||
|
|
||||||
|
xit('should logout if token request failed', () => {
|
||||||
|
getState.returns({
|
||||||
|
user: {
|
||||||
|
token: expiredToken,
|
||||||
|
refreshToken,
|
||||||
|
isGuest: false
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
authentication.requestToken.returns(Promise.reject());
|
||||||
|
|
||||||
|
return middleware.before({url: 'foo'}).then((resp) => {
|
||||||
|
// TODO: need a way to test, that action was called
|
||||||
|
expect(dispatch, 'to have a call satisfying', logout);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#catch', () => {
|
||||||
|
it('should request new token', () => {
|
||||||
|
getState.returns({
|
||||||
|
user: {
|
||||||
|
refreshToken
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const restart = sinon.stub().named('restart');
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
url: 'foo',
|
||||||
|
options: {
|
||||||
|
headers: {}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
authentication.requestToken.returns(Promise.resolve({token: validToken}));
|
||||||
|
|
||||||
|
return middleware.catch({
|
||||||
|
status: 401,
|
||||||
|
message: 'Token expired'
|
||||||
|
}, restart).then(() => {
|
||||||
|
expect(authentication.requestToken, 'to have a call satisfying', [
|
||||||
|
refreshToken
|
||||||
|
]);
|
||||||
|
expect(restart, 'was called');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
xit('should logout user if token cannot be refreshed'); // TODO: need a way to test, that action was called
|
||||||
|
|
||||||
|
it('should pass the rest of failed requests through', () => {
|
||||||
|
const resp = {};
|
||||||
|
|
||||||
|
const promise = middleware.catch(resp);
|
||||||
|
|
||||||
|
expect(promise, 'to be rejected');
|
||||||
|
|
||||||
|
return promise.catch((actual) => {
|
||||||
|
expect(actual, 'to be', resp);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in New Issue
Block a user