From 2737c6502b1e01de7cad75f6edbbaa62112b6229 Mon Sep 17 00:00:00 2001 From: SleepWalker Date: Sun, 5 Jun 2016 15:06:14 +0300 Subject: [PATCH] #125: make activation page available for all guests and innactive users --- src/components/user/User.js | 2 +- src/services/authFlow/AuthFlow.js | 14 +++++++---- .../authFlow/ResendActivationState.js | 8 +++---- .../services/authFlow/ActivationState.test.js | 2 -- tests/services/authFlow/AuthFlow.test.js | 24 ++++++++++++++++--- .../authFlow/ResendActivationState.test.js | 21 ++++------------ 6 files changed, 38 insertions(+), 33 deletions(-) diff --git a/src/components/user/User.js b/src/components/user/User.js index 8dc4a08..4a3b2bd 100644 --- a/src/components/user/User.js +++ b/src/components/user/User.js @@ -28,7 +28,7 @@ export default class User { lang: '', goal: null, // the goal with wich user entered site isGuest: true, - isActive: true, + isActive: false, shouldChangePassword: false, // TODO: нужно ещё пробросить причину необходимости смены passwordChangedAt: null, hasMojangUsernameCollision: false, diff --git a/src/services/authFlow/AuthFlow.js b/src/services/authFlow/AuthFlow.js index 2656908..b9b4737 100644 --- a/src/services/authFlow/AuthFlow.js +++ b/src/services/authFlow/AuthFlow.js @@ -5,6 +5,7 @@ import LoginState from './LoginState'; import OAuthState from './OAuthState'; import ForgotPasswordState from './ForgotPasswordState'; import RecoverPasswordState from './RecoverPasswordState'; +import ActivationState from './ActivationState'; import ResendActivationState from './ResendActivationState'; // TODO: a way to unload service (when we are on account page) @@ -70,12 +71,13 @@ export default class AuthFlow { throw new Error('State is required'); } - // if (this.state instanceof state.constructor) { - // // already in this state - // return; - // } + if (this.state instanceof state.constructor) { + // already in this state + return; + } this.state && this.state.leave(this); + this.prevState = this.state; this.state = state; const resp = this.state.enter(this); @@ -129,7 +131,6 @@ export default class AuthFlow { case '/': case '/login': case '/password': - case '/activation': case '/change-password': case '/oauth/permissions': case '/oauth/finish': @@ -138,6 +139,9 @@ export default class AuthFlow { default: switch (path.replace(/(.)\/.+/, '$1')) { // use only first part of an url + case '/activation': + this.setState(new ActivationState()); + break; case '/recover-password': this.setState(new RecoverPasswordState()); break; diff --git a/src/services/authFlow/ResendActivationState.js b/src/services/authFlow/ResendActivationState.js index 4d65447..7eb01ff 100644 --- a/src/services/authFlow/ResendActivationState.js +++ b/src/services/authFlow/ResendActivationState.js @@ -7,7 +7,7 @@ export default class ResendActivationState extends AbstractState { enter(context) { const {user} = context.getState(); - if (user.isActive && !user.isGuest) { + if (user.isActive) { context.setState(new CompleteState()); } else { context.navigate('/resend-activation'); @@ -16,13 +16,11 @@ export default class ResendActivationState extends AbstractState { resolve(context, payload) { context.run('resendActivation', payload) - .then(() => context.setState(new CompleteState())); + .then(() => context.setState(new ActivationState())); } goBack(context) { - const {user} = context.getState(); - - if (user.isGuest) { + if (context.prevState instanceof RegisterState) { context.setState(new RegisterState()); } else { context.setState(new ActivationState()); diff --git a/tests/services/authFlow/ActivationState.test.js b/tests/services/authFlow/ActivationState.test.js index a6e922f..3d6545f 100644 --- a/tests/services/authFlow/ActivationState.test.js +++ b/tests/services/authFlow/ActivationState.test.js @@ -25,7 +25,6 @@ describe('ActivationState', () => { it('should navigate to /activation', () => { context.getState.returns({ user: { - isGuest: false, isActive: false } }); @@ -38,7 +37,6 @@ describe('ActivationState', () => { it('should transition to complete state if account activated', () => { context.getState.returns({ user: { - isGuest: false, isActive: true } }); diff --git a/tests/services/authFlow/AuthFlow.test.js b/tests/services/authFlow/AuthFlow.test.js index 1f7d7e8..7bbcc9c 100644 --- a/tests/services/authFlow/AuthFlow.test.js +++ b/tests/services/authFlow/AuthFlow.test.js @@ -5,6 +5,7 @@ import OAuthState from 'services/authFlow/OAuthState'; import RegisterState from 'services/authFlow/RegisterState'; import RecoverPasswordState from 'services/authFlow/RecoverPasswordState'; import ForgotPasswordState from 'services/authFlow/ForgotPasswordState'; +import ActivationState from 'services/authFlow/ActivationState'; import ResendActivationState from 'services/authFlow/ResendActivationState'; import LoginState from 'services/authFlow/LoginState'; @@ -49,8 +50,11 @@ describe('AuthFlow', () => { }); it('should call `leave` on previous state if any', () => { - const state1 = new AbstractState(); - const state2 = new AbstractState(); + class State1 extends AbstractState {} + class State2 extends AbstractState {} + + const state1 = new State1(); + const state2 = new State2(); const spy1 = sinon.spy(state1, 'leave'); const spy2 = sinon.spy(state2, 'leave'); @@ -62,6 +66,20 @@ describe('AuthFlow', () => { sinon.assert.notCalled(spy2); }); + it('should not change state, if current state is of same type', () => { + const state1 = new AbstractState(); + const state2 = new AbstractState(); + const spy1 = sinon.spy(state1, 'enter'); + const spy2 = sinon.spy(state2, 'enter'); + + flow.setState(state1); + flow.setState(state2); + + sinon.assert.calledWith(spy1, flow); + sinon.assert.calledOnce(spy1); + sinon.assert.notCalled(spy2); + }); + it('should return promise, if #enter returns it', () => { const state = new AbstractState(); const expected = Promise.resolve(); @@ -169,7 +187,6 @@ describe('AuthFlow', () => { '/': LoginState, '/login': LoginState, '/password': LoginState, - '/activation': LoginState, '/change-password': LoginState, '/oauth/permissions': LoginState, '/oauth/finish': LoginState, @@ -178,6 +195,7 @@ describe('AuthFlow', () => { '/recover-password': RecoverPasswordState, '/recover-password/key123': RecoverPasswordState, '/forgot-password': ForgotPasswordState, + '/activation': ActivationState, '/resend-activation': ResendActivationState }).forEach(([path, type]) => { it(`should transition to ${type.name} if ${path}`, () => { diff --git a/tests/services/authFlow/ResendActivationState.test.js b/tests/services/authFlow/ResendActivationState.test.js index 9273de6..bae5c14 100644 --- a/tests/services/authFlow/ResendActivationState.test.js +++ b/tests/services/authFlow/ResendActivationState.test.js @@ -26,7 +26,6 @@ describe('ResendActivationState', () => { it('should navigate to /resend-activation', () => { context.getState.returns({ user: { - isGuest: false, isActive: false } }); @@ -40,7 +39,7 @@ describe('ResendActivationState', () => { context.getState.returns({ user: { isGuest: true, - isActive: true + isActive: false } }); @@ -52,7 +51,6 @@ describe('ResendActivationState', () => { it('should transition to complete state if account activated', () => { context.getState.returns({ user: { - isGuest: false, isActive: true } }); @@ -80,7 +78,7 @@ describe('ResendActivationState', () => { const promise = Promise.resolve(); mock.expects('run').returns(promise); - expectState(mock, CompleteState); + expectState(mock, ActivationState); state.resolve(context); @@ -101,26 +99,15 @@ describe('ResendActivationState', () => { describe('#goBack', () => { it('should transition to activation', () => { - context.getState.returns({ - user: { - isGuest: false - } - }); - expectState(mock, ActivationState); state.goBack(context); }); - it('should transition to register if guest', () => { - context.getState.returns({ - user: { - isGuest: true - } - }); - + it('should transition to register if it was active previousely', () => { expectState(mock, RegisterState); + context.prevState = new RegisterState(); state.goBack(context); }); });