mirror of
https://github.com/elyby/accounts-frontend.git
synced 2025-05-31 14:11:58 +05:30
#48: add/remove accounts from account switcher. Allow authorized users to log in into another account
This commit is contained in:
@@ -22,7 +22,7 @@ const user = {
|
||||
lang: 'be'
|
||||
};
|
||||
|
||||
describe('Accounts actions', () => {
|
||||
describe('components/accounts/actions', () => {
|
||||
let dispatch;
|
||||
let getState;
|
||||
|
||||
@@ -109,19 +109,15 @@ describe('Accounts actions', () => {
|
||||
});
|
||||
|
||||
describe('#revoke()', () => {
|
||||
it(`should dispatch ${REMOVE} action`, () => {
|
||||
revoke(account)(dispatch, getState);
|
||||
|
||||
expect(dispatch, 'to have a call satisfying', [
|
||||
remove(account)
|
||||
]);
|
||||
});
|
||||
|
||||
it('should switch next account if available', () => {
|
||||
const account2 = {...account, id: 2};
|
||||
|
||||
getState.returns({
|
||||
accounts: [account]
|
||||
accounts: {
|
||||
active: account2,
|
||||
available: [account]
|
||||
},
|
||||
user
|
||||
});
|
||||
|
||||
return revoke(account2)(dispatch, getState).then(() => {
|
||||
@@ -143,10 +139,15 @@ describe('Accounts actions', () => {
|
||||
});
|
||||
|
||||
it('should logout if no other accounts available', () => {
|
||||
getState.returns({
|
||||
accounts: {
|
||||
active: account,
|
||||
available: []
|
||||
},
|
||||
user
|
||||
});
|
||||
|
||||
revoke(account)(dispatch, getState).then(() => {
|
||||
expect(dispatch, 'to have a call satisfying', [
|
||||
remove(account)
|
||||
]);
|
||||
expect(dispatch, 'to have a call satisfying', [
|
||||
{payload: {isGuest: true}}
|
||||
// updateUser({isGuest: true})
|
||||
|
||||
@@ -45,11 +45,23 @@ describe('Accounts reducer', () => {
|
||||
})
|
||||
);
|
||||
|
||||
it('should not add the same account twice', () =>
|
||||
expect(accounts({...initial, available: [account]}, add(account)), 'to satisfy', {
|
||||
available: [account]
|
||||
})
|
||||
);
|
||||
it('should replace if account was added for the second time', () => {
|
||||
const outdatedAccount = {
|
||||
...account,
|
||||
someShit: true
|
||||
};
|
||||
|
||||
const updatedAccount = {
|
||||
...account,
|
||||
token: 'newToken'
|
||||
};
|
||||
|
||||
return expect(
|
||||
accounts({...initial, available: [outdatedAccount]}, add(updatedAccount)),
|
||||
'to satisfy', {
|
||||
available: [updatedAccount]
|
||||
});
|
||||
});
|
||||
|
||||
it('throws, when account is invalid', () => {
|
||||
expect(() => accounts(initial, add()),
|
||||
|
||||
@@ -10,7 +10,9 @@ import {
|
||||
setOAuthRequest,
|
||||
setScopes,
|
||||
setOAuthCode,
|
||||
requirePermissionsAccept
|
||||
requirePermissionsAccept,
|
||||
login,
|
||||
setLogin
|
||||
} from 'components/auth/actions';
|
||||
|
||||
const oauthData = {
|
||||
@@ -22,8 +24,8 @@ const oauthData = {
|
||||
};
|
||||
|
||||
describe('components/auth/actions', () => {
|
||||
const dispatch = sinon.stub().named('dispatch');
|
||||
const getState = sinon.stub().named('getState');
|
||||
const dispatch = sinon.stub().named('store.dispatch');
|
||||
const getState = sinon.stub().named('store.getState');
|
||||
|
||||
function callThunk(fn, ...args) {
|
||||
const thunk = fn(...args);
|
||||
@@ -67,21 +69,21 @@ describe('components/auth/actions', () => {
|
||||
request.get.returns(Promise.resolve(resp));
|
||||
});
|
||||
|
||||
it('should send get request to an api', () => {
|
||||
return callThunk(oAuthValidate, oauthData).then(() => {
|
||||
it('should send get request to an api', () =>
|
||||
callThunk(oAuthValidate, oauthData).then(() => {
|
||||
expect(request.get, 'to have a call satisfying', ['/api/oauth2/v1/validate', {}]);
|
||||
});
|
||||
});
|
||||
})
|
||||
);
|
||||
|
||||
it('should dispatch setClient, setOAuthRequest and setScopes', () => {
|
||||
return callThunk(oAuthValidate, oauthData).then(() => {
|
||||
it('should dispatch setClient, setOAuthRequest and setScopes', () =>
|
||||
callThunk(oAuthValidate, oauthData).then(() => {
|
||||
expectDispatchCalls([
|
||||
[setClient(resp.client)],
|
||||
[setOAuthRequest(resp.oAuth)],
|
||||
[setScopes(resp.session.scopes)]
|
||||
]);
|
||||
});
|
||||
});
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
describe('#oAuthComplete()', () => {
|
||||
@@ -160,4 +162,24 @@ describe('components/auth/actions', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#login()', () => {
|
||||
describe('when correct login was entered', () => {
|
||||
beforeEach(() => {
|
||||
request.post.returns(Promise.reject({
|
||||
errors: {
|
||||
password: 'error.password_required'
|
||||
}
|
||||
}));
|
||||
});
|
||||
|
||||
it('should set login', () =>
|
||||
callThunk(login, {login: 'foo'}).then(() => {
|
||||
expectDispatchCalls([
|
||||
[setLogin('foo')]
|
||||
]);
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
16
tests/components/auth/reducer.test.js
Normal file
16
tests/components/auth/reducer.test.js
Normal file
@@ -0,0 +1,16 @@
|
||||
import expect from 'unexpected';
|
||||
|
||||
import auth from 'components/auth/reducer';
|
||||
import { setLogin, SET_LOGIN } from 'components/auth/actions';
|
||||
|
||||
describe('auth reducer', () => {
|
||||
describe(SET_LOGIN, () => {
|
||||
it('should set login', () => {
|
||||
const expectedLogin = 'foo';
|
||||
|
||||
expect(auth(undefined, setLogin(expectedLogin)), 'to satisfy', {
|
||||
login: expectedLogin
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -68,7 +68,7 @@ describe('refreshTokenMiddleware', () => {
|
||||
});
|
||||
|
||||
it('should not apply to refresh-token request', () => {
|
||||
const data = {url: '/refresh-token'};
|
||||
const data = {url: '/refresh-token', options: {}};
|
||||
const resp = middleware.before(data);
|
||||
|
||||
expect(resp, 'to satisfy', data);
|
||||
|
||||
@@ -47,6 +47,9 @@ describe('AuthFlow.functional', () => {
|
||||
state.user = {
|
||||
isGuest: true
|
||||
};
|
||||
state.auth = {
|
||||
login: null
|
||||
};
|
||||
});
|
||||
|
||||
it('should redirect guest / -> /login', () => {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import LoginState from 'services/authFlow/LoginState';
|
||||
import PasswordState from 'services/authFlow/PasswordState';
|
||||
import ForgotPasswordState from 'services/authFlow/ForgotPasswordState';
|
||||
|
||||
import { bootstrap, expectState, expectNavigate, expectRun } from './helpers';
|
||||
|
||||
@@ -24,7 +23,8 @@ describe('LoginState', () => {
|
||||
describe('#enter', () => {
|
||||
it('should navigate to /login', () => {
|
||||
context.getState.returns({
|
||||
user: {isGuest: true}
|
||||
user: {isGuest: true},
|
||||
auth: {login: null}
|
||||
});
|
||||
|
||||
expectNavigate(mock, '/login');
|
||||
@@ -32,22 +32,15 @@ describe('LoginState', () => {
|
||||
state.enter(context);
|
||||
});
|
||||
|
||||
const testTransitionToPassword = (user) => {
|
||||
it('should transition to password if login was set', () => {
|
||||
context.getState.returns({
|
||||
user: user
|
||||
user: {isGuest: true},
|
||||
auth: {login: 'foo'}
|
||||
});
|
||||
|
||||
expectState(mock, PasswordState);
|
||||
|
||||
state.enter(context);
|
||||
};
|
||||
|
||||
it('should transition to password if has email', () => {
|
||||
testTransitionToPassword({email: 'foo'});
|
||||
});
|
||||
|
||||
it('should transition to password if has username', () => {
|
||||
testTransitionToPassword({username: 'foo'});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -25,7 +25,8 @@ describe('PasswordState', () => {
|
||||
describe('#enter', () => {
|
||||
it('should navigate to /password', () => {
|
||||
context.getState.returns({
|
||||
user: {isGuest: true}
|
||||
user: {isGuest: true},
|
||||
auth: {login: 'foo'}
|
||||
});
|
||||
|
||||
expectNavigate(mock, '/password');
|
||||
@@ -35,7 +36,8 @@ describe('PasswordState', () => {
|
||||
|
||||
it('should transition to complete if not guest', () => {
|
||||
context.getState.returns({
|
||||
user: {isGuest: false}
|
||||
user: {isGuest: false},
|
||||
auth: {login: null}
|
||||
});
|
||||
|
||||
expectState(mock, CompleteState);
|
||||
@@ -45,42 +47,29 @@ describe('PasswordState', () => {
|
||||
});
|
||||
|
||||
describe('#resolve', () => {
|
||||
(function() {
|
||||
const expectedLogin = 'login';
|
||||
const expectedPassword = 'password';
|
||||
it('should call login with login and password', () => {
|
||||
const expectedLogin = 'foo';
|
||||
const expectedPassword = 'bar';
|
||||
const expectedRememberMe = true;
|
||||
|
||||
const testWith = (user) => {
|
||||
it(`should call login with email or username and password. User: ${JSON.stringify(user)}`, () => {
|
||||
context.getState.returns({user});
|
||||
|
||||
expectRun(
|
||||
mock,
|
||||
'login',
|
||||
sinon.match({
|
||||
login: expectedLogin,
|
||||
password: expectedPassword,
|
||||
rememberMe: expectedRememberMe,
|
||||
})
|
||||
).returns({then() {}});
|
||||
|
||||
state.resolve(context, {password: expectedPassword, rememberMe: expectedRememberMe});
|
||||
});
|
||||
};
|
||||
|
||||
testWith({
|
||||
email: expectedLogin
|
||||
context.getState.returns({
|
||||
auth: {
|
||||
login: expectedLogin
|
||||
}
|
||||
});
|
||||
|
||||
testWith({
|
||||
username: expectedLogin
|
||||
});
|
||||
expectRun(
|
||||
mock,
|
||||
'login',
|
||||
sinon.match({
|
||||
login: expectedLogin,
|
||||
password: expectedPassword,
|
||||
rememberMe: expectedRememberMe,
|
||||
})
|
||||
).returns({then() {}});
|
||||
|
||||
testWith({
|
||||
email: expectedLogin,
|
||||
username: expectedLogin
|
||||
});
|
||||
}());
|
||||
state.resolve(context, {password: expectedPassword, rememberMe: expectedRememberMe});
|
||||
});
|
||||
|
||||
it('should transition to complete state on successfull login', () => {
|
||||
const promise = Promise.resolve();
|
||||
@@ -88,8 +77,8 @@ describe('PasswordState', () => {
|
||||
const expectedPassword = 'password';
|
||||
|
||||
context.getState.returns({
|
||||
user: {
|
||||
email: expectedLogin
|
||||
auth: {
|
||||
login: expectedLogin
|
||||
}
|
||||
});
|
||||
|
||||
@@ -111,8 +100,8 @@ describe('PasswordState', () => {
|
||||
});
|
||||
|
||||
describe('#goBack', () => {
|
||||
it('should transition to forgot password state', () => {
|
||||
expectRun(mock, 'logout');
|
||||
it('should transition to login state', () => {
|
||||
expectRun(mock, 'setLogin', null);
|
||||
expectState(mock, LoginState);
|
||||
|
||||
state.goBack(context);
|
||||
|
||||
Reference in New Issue
Block a user