mirror of
				https://github.com/elyby/accounts-frontend.git
				synced 2025-05-31 14:11:58 +05:30 
			
		
		
		
	Тесты для стейтов AuthFlow
This commit is contained in:
		
							
								
								
									
										11
									
								
								tests/.eslintrc.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								tests/.eslintrc.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| { | ||||
|     "env": { | ||||
|         "browser": true, | ||||
|         "es6": true, | ||||
|         "mocha": true | ||||
|     }, | ||||
|  | ||||
|     "globals": { | ||||
|         "sinon": true | ||||
|     } | ||||
| } | ||||
							
								
								
									
										4
									
								
								tests/index.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								tests/index.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,4 @@ | ||||
| // require all modules ending in "_test" from the | ||||
| // current directory and all subdirectories | ||||
| var testsContext = require.context(".", true, /\.test\.js$/); | ||||
| testsContext.keys().forEach(testsContext); | ||||
							
								
								
									
										86
									
								
								tests/services/authFlow/ActivationState.test.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								tests/services/authFlow/ActivationState.test.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,86 @@ | ||||
| import ActivationState from 'services/authFlow/ActivationState'; | ||||
| import CompleteState from 'services/authFlow/CompleteState'; | ||||
|  | ||||
| import { bootstrap, expectState, expectNavigate, expectRun } from './helpers'; | ||||
|  | ||||
| describe('ActivationState', () => { | ||||
|     let state; | ||||
|     let context; | ||||
|     let mock; | ||||
|  | ||||
|     beforeEach(() => { | ||||
|         state = new ActivationState(); | ||||
|  | ||||
|         const data = bootstrap(); | ||||
|         context = data.context; | ||||
|         mock = data.mock; | ||||
|     }); | ||||
|  | ||||
|     afterEach(() => { | ||||
|         mock.verify(); | ||||
|     }); | ||||
|  | ||||
|     describe('#enter', () => { | ||||
|         it('should navigate to /activation', () => { | ||||
|             context.getState.returns({ | ||||
|                 user: { | ||||
|                     isGuest: false, | ||||
|                     isActive: false | ||||
|                 } | ||||
|             }); | ||||
|  | ||||
|             expectNavigate(mock, '/activation'); | ||||
|  | ||||
|             state.enter(context); | ||||
|         }); | ||||
|  | ||||
|         it('should transition to complete state if account activated', () => { | ||||
|             context.getState.returns({ | ||||
|                 user: { | ||||
|                     isGuest: false, | ||||
|                     isActive: true | ||||
|                 } | ||||
|             }); | ||||
|  | ||||
|             expectState(mock, CompleteState); | ||||
|  | ||||
|             state.enter(context); | ||||
|         }); | ||||
|     }); | ||||
|  | ||||
|     describe('#resolve', () => { | ||||
|         it('should call activate with payload', () => { | ||||
|             const payload = {}; | ||||
|  | ||||
|             expectRun( | ||||
|                 mock, | ||||
|                 'activate', | ||||
|                 sinon.match.same(payload) | ||||
|             ).returns({then() {}}); | ||||
|  | ||||
|             state.resolve(context, payload); | ||||
|         }); | ||||
|  | ||||
|         it('should transition to complete state on success', () => { | ||||
|             const promise = Promise.resolve(); | ||||
|  | ||||
|             mock.expects('run').returns(promise); | ||||
|             expectState(mock, CompleteState); | ||||
|  | ||||
|             state.resolve(context); | ||||
|  | ||||
|             return promise; | ||||
|         }); | ||||
|  | ||||
|         it('should NOT transition to complete state on fail', () => { | ||||
|             const promise = Promise.reject(); | ||||
|  | ||||
|             mock.expects('run').returns(promise); | ||||
|             mock.expects('setState').never(); | ||||
|  | ||||
|             state.resolve(context); | ||||
|  | ||||
|             return promise.catch(mock.verify.bind(mock)); | ||||
|         }); | ||||
|     }); | ||||
| }); | ||||
							
								
								
									
										86
									
								
								tests/services/authFlow/ChangePasswordState.test.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								tests/services/authFlow/ChangePasswordState.test.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,86 @@ | ||||
| import ChangePasswordState from 'services/authFlow/ChangePasswordState'; | ||||
| import CompleteState from 'services/authFlow/CompleteState'; | ||||
|  | ||||
| import { bootstrap, expectState, expectNavigate, expectRun } from './helpers'; | ||||
|  | ||||
| describe('ChangePasswordState', () => { | ||||
|     let state; | ||||
|     let context; | ||||
|     let mock; | ||||
|  | ||||
|     beforeEach(() => { | ||||
|         state = new ChangePasswordState(); | ||||
|  | ||||
|         const data = bootstrap(); | ||||
|         context = data.context; | ||||
|         mock = data.mock; | ||||
|     }); | ||||
|  | ||||
|     afterEach(() => { | ||||
|         mock.verify(); | ||||
|     }); | ||||
|  | ||||
|     describe('#enter', () => { | ||||
|         it('should navigate to /change-password', () => { | ||||
|             context.getState.returns({ | ||||
|                 user: {isGuest: true} | ||||
|             }); | ||||
|  | ||||
|             expectNavigate(mock, '/change-password'); | ||||
|  | ||||
|             state.enter(context); | ||||
|         }); | ||||
|     }); | ||||
|  | ||||
|     describe('#resolve', () => { | ||||
|         it('should call changePassword with payload', () => { | ||||
|             const payload = {}; | ||||
|  | ||||
|             expectRun( | ||||
|                 mock, | ||||
|                 'changePassword', | ||||
|                 sinon.match.same(payload) | ||||
|             ).returns({then() {}}); | ||||
|  | ||||
|             state.resolve(context, payload); | ||||
|         }); | ||||
|  | ||||
|         it('should transition to complete state on success', () => { | ||||
|             const promise = Promise.resolve(); | ||||
|  | ||||
|             mock.expects('run').returns(promise); | ||||
|             expectState(mock, CompleteState); | ||||
|  | ||||
|             state.resolve(context); | ||||
|  | ||||
|             return promise; | ||||
|         }); | ||||
|  | ||||
|         it('should NOT transition to complete state on fail', () => { | ||||
|             const promise = Promise.reject(); | ||||
|  | ||||
|             mock.expects('run').returns(promise); | ||||
|             mock.expects('setState').never(); | ||||
|  | ||||
|             state.resolve(context); | ||||
|  | ||||
|             return promise.catch(mock.verify.bind(mock)); | ||||
|         }); | ||||
|     }); | ||||
|  | ||||
|     describe('#reject', () => { | ||||
|         it('should transition to complete state and mark that password should not be changed', () => { | ||||
|             expectRun( | ||||
|                 mock, | ||||
|                 'updateUser', | ||||
|                 sinon.match({ | ||||
|                     shouldChangePassword: false | ||||
|                 }) | ||||
|             ); | ||||
|  | ||||
|             expectState(mock, CompleteState); | ||||
|  | ||||
|             state.reject(context); | ||||
|         }); | ||||
|     }); | ||||
| }); | ||||
							
								
								
									
										305
									
								
								tests/services/authFlow/CompleteState.test.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										305
									
								
								tests/services/authFlow/CompleteState.test.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,305 @@ | ||||
| import CompleteState from 'services/authFlow/CompleteState'; | ||||
| import LoginState from 'services/authFlow/LoginState'; | ||||
| import ActivationState from 'services/authFlow/ActivationState'; | ||||
| import ChangePasswordState from 'services/authFlow/ChangePasswordState'; | ||||
| import FinishState from 'services/authFlow/FinishState'; | ||||
| import PermissionsState from 'services/authFlow/PermissionsState'; | ||||
|  | ||||
| import { bootstrap, expectState, expectNavigate, expectRun } from './helpers'; | ||||
|  | ||||
| describe('CompleteState', () => { | ||||
|     let state; | ||||
|     let context; | ||||
|     let mock; | ||||
|  | ||||
|     beforeEach(() => { | ||||
|         state = new CompleteState(); | ||||
|  | ||||
|         const data = bootstrap(); | ||||
|         context = data.context; | ||||
|         mock = data.mock; | ||||
|     }); | ||||
|  | ||||
|     afterEach(() => { | ||||
|         mock.verify(); | ||||
|     }); | ||||
|  | ||||
|     describe('#enter', () => { | ||||
|         it('should navigate to / for authenticated', () => { | ||||
|             context.getState.returns({ | ||||
|                 user: { | ||||
|                     isActive: true, | ||||
|                     isGuest: false | ||||
|                 }, | ||||
|                 auth: {} | ||||
|             }); | ||||
|  | ||||
|             expectNavigate(mock, '/'); | ||||
|  | ||||
|             state.enter(context); | ||||
|         }); | ||||
|  | ||||
|         it('should transition to login for guests', () => { | ||||
|             context.getState.returns({ | ||||
|                 user: { | ||||
|                     isGuest: true | ||||
|                 }, | ||||
|                 auth: {} | ||||
|             }); | ||||
|  | ||||
|             expectState(mock, LoginState); | ||||
|  | ||||
|             state.enter(context); | ||||
|         }); | ||||
|  | ||||
|         it('should transition to activation if account is not activated', () => { | ||||
|             context.getState.returns({ | ||||
|                 user: { | ||||
|                     isGuest: false | ||||
|                 }, | ||||
|                 auth: {} | ||||
|             }); | ||||
|  | ||||
|             expectState(mock, ActivationState); | ||||
|  | ||||
|             state.enter(context); | ||||
|         }); | ||||
|  | ||||
|         it('should transition to change-password if shouldChangePassword', () => { | ||||
|             context.getState.returns({ | ||||
|                 user: { | ||||
|                     shouldChangePassword: true, | ||||
|                     isActive: true, | ||||
|                     isGuest: false | ||||
|                 }, | ||||
|                 auth: {} | ||||
|             }); | ||||
|  | ||||
|             expectState(mock, ChangePasswordState); | ||||
|  | ||||
|             state.enter(context); | ||||
|         }); | ||||
|  | ||||
|         it('should transition to activation with higher priority than shouldChangePassword', () => { | ||||
|             context.getState.returns({ | ||||
|                 user: { | ||||
|                     shouldChangePassword: true, | ||||
|                     isGuest: false | ||||
|                 }, | ||||
|                 auth: {} | ||||
|             }); | ||||
|  | ||||
|             expectState(mock, ActivationState); | ||||
|  | ||||
|             state.enter(context); | ||||
|         }); | ||||
|  | ||||
|         it('should transition to finish state if code is present', () => { | ||||
|             context.getState.returns({ | ||||
|                 user: { | ||||
|                     isActive: true, | ||||
|                     isGuest: false | ||||
|                 }, | ||||
|                 auth: { | ||||
|                     oauth: { | ||||
|                         clientId: 'ely.by', | ||||
|                         code: 'XXX' | ||||
|                     } | ||||
|                 } | ||||
|             }); | ||||
|  | ||||
|             expectState(mock, FinishState); | ||||
|  | ||||
|             state.enter(context); | ||||
|         }); | ||||
|     }); | ||||
|  | ||||
|     describe('oAuthComplete', () => { | ||||
|         it('should run oAuthComplete', () => { | ||||
|             context.getState.returns({ | ||||
|                 user: { | ||||
|                     isActive: true, | ||||
|                     isGuest: false | ||||
|                 }, | ||||
|                 auth: { | ||||
|                     oauth: { | ||||
|                         clientId: 'ely.by' | ||||
|                     } | ||||
|                 } | ||||
|             }); | ||||
|  | ||||
|             expectRun( | ||||
|                 mock, | ||||
|                 'oAuthComplete', | ||||
|                 sinon.match.object | ||||
|             ).returns({then() {}}); | ||||
|  | ||||
|             state.enter(context); | ||||
|         }); | ||||
|  | ||||
|         it('should listen for auth success/failure', () => { | ||||
|             context.getState.returns({ | ||||
|                 user: { | ||||
|                     isActive: true, | ||||
|                     isGuest: false | ||||
|                 }, | ||||
|                 auth: { | ||||
|                     oauth: { | ||||
|                         clientId: 'ely.by' | ||||
|                     } | ||||
|                 } | ||||
|             }); | ||||
|  | ||||
|             expectRun( | ||||
|                 mock, | ||||
|                 'oAuthComplete', | ||||
|                 sinon.match.object | ||||
|             ).returns({then(success, fail) { | ||||
|                 expect(success).to.be.a('function'); | ||||
|                 expect(fail).to.be.a('function'); | ||||
|             }}); | ||||
|  | ||||
|             state.enter(context); | ||||
|         }); | ||||
|  | ||||
|         it('should transition run redirect by default', () => { | ||||
|             const expectedUrl = 'foo/bar'; | ||||
|             const promise = Promise.resolve({redirectUri: expectedUrl}); | ||||
|  | ||||
|             context.getState.returns({ | ||||
|                 user: { | ||||
|                     isActive: true, | ||||
|                     isGuest: false | ||||
|                 }, | ||||
|                 auth: { | ||||
|                     oauth: { | ||||
|                         clientId: 'ely.by' | ||||
|                     } | ||||
|                 } | ||||
|             }); | ||||
|  | ||||
|             expectRun( | ||||
|                 mock, | ||||
|                 'oAuthComplete', | ||||
|                 sinon.match.object | ||||
|             ).returns(promise); | ||||
|             expectRun( | ||||
|                 mock, | ||||
|                 'redirect', | ||||
|                 expectedUrl | ||||
|             ); | ||||
|  | ||||
|             state.enter(context); | ||||
|  | ||||
|             return promise.catch(mock.verify.bind(mock)); | ||||
|         }); | ||||
|  | ||||
|         const testOAuth = (type, resp, expectedInstance) => { | ||||
|             const promise = Promise[type](resp); | ||||
|  | ||||
|             context.getState.returns({ | ||||
|                 user: { | ||||
|                     isActive: true, | ||||
|                     isGuest: false | ||||
|                 }, | ||||
|                 auth: { | ||||
|                     oauth: { | ||||
|                         clientId: 'ely.by' | ||||
|                     } | ||||
|                 } | ||||
|             }); | ||||
|  | ||||
|             expectRun( | ||||
|                 mock, | ||||
|                 'oAuthComplete', | ||||
|                 sinon.match.object | ||||
|             ).returns(promise); | ||||
|             expectState(mock, expectedInstance); | ||||
|  | ||||
|             state.enter(context); | ||||
|  | ||||
|             return promise.catch(mock.verify.bind(mock)); | ||||
|         }; | ||||
|  | ||||
|         it('should transition to finish state if rejected with static_page', () => { | ||||
|             return testOAuth('resolve', {redirectUri: 'static_page'}, FinishState); | ||||
|         }); | ||||
|  | ||||
|         it('should transition to finish state if rejected with static_page_with_code', () => { | ||||
|             return testOAuth('resolve', {redirectUri: 'static_page_with_code'}, FinishState); | ||||
|         }); | ||||
|  | ||||
|         it('should transition to login state if rejected with unauthorized', () => { | ||||
|             return testOAuth('reject', {unauthorized: true}, LoginState); | ||||
|         }); | ||||
|  | ||||
|         it('should transition to permissions state if rejected with acceptRequired', () => { | ||||
|             return testOAuth('reject', {acceptRequired: true}, PermissionsState); | ||||
|         }); | ||||
|     }) | ||||
|  | ||||
|     describe('permissions accept', () => { | ||||
|         it('should set flags, when user accepted permissions', () => { | ||||
|             state = new CompleteState(); | ||||
|             expect(state.isPermissionsAccepted).to.be.undefined; | ||||
|  | ||||
|             state = new CompleteState({accept: undefined}); | ||||
|             expect(state.isPermissionsAccepted).to.be.undefined; | ||||
|  | ||||
|             state = new CompleteState({accept: true}); | ||||
|             expect(state.isPermissionsAccepted).to.be.true; | ||||
|  | ||||
|             state = new CompleteState({accept: false}); | ||||
|             expect(state.isPermissionsAccepted).to.be.false; | ||||
|         }); | ||||
|  | ||||
|         it('should run oAuthComplete passing accept: true', () => { | ||||
|             const expected = {accept: true}; | ||||
|  | ||||
|             state = new CompleteState(expected); | ||||
|             context.getState.returns({ | ||||
|                 user: { | ||||
|                     isActive: true, | ||||
|                     isGuest: false | ||||
|                 }, | ||||
|                 auth: { | ||||
|                     oauth: { | ||||
|                         clientId: 'ely.by' | ||||
|                     } | ||||
|                 } | ||||
|             }); | ||||
|  | ||||
|             mock.expects('run').once().withExactArgs( | ||||
|                 'oAuthComplete', | ||||
|                 sinon.match(expected) | ||||
|             ).returns({then() {}}); | ||||
|  | ||||
|             state.enter(context); | ||||
|         }); | ||||
|  | ||||
|         it('should run oAuthComplete passing accept: false', () => { | ||||
|             const expected = {accept: false}; | ||||
|  | ||||
|             state = new CompleteState(expected); | ||||
|             context.getState.returns({ | ||||
|                 user: { | ||||
|                     isActive: true, | ||||
|                     isGuest: false | ||||
|                 }, | ||||
|                 auth: { | ||||
|                     oauth: { | ||||
|                         clientId: 'ely.by' | ||||
|                     } | ||||
|                 } | ||||
|             }); | ||||
|  | ||||
|             expectRun( | ||||
|                 mock, | ||||
|                 'oAuthComplete', | ||||
|                 sinon.match(expected) | ||||
|             ).returns({then() {}}); | ||||
|  | ||||
|             state.enter(context); | ||||
|         }); | ||||
|     }); | ||||
| }); | ||||
							
								
								
									
										29
									
								
								tests/services/authFlow/FinishState.test.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								tests/services/authFlow/FinishState.test.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | ||||
| import FinishState from 'services/authFlow/FinishState'; | ||||
|  | ||||
| import { bootstrap, expectNavigate } from './helpers'; | ||||
|  | ||||
| describe('FinishState', () => { | ||||
|     let state; | ||||
|     let context; | ||||
|     let mock; | ||||
|  | ||||
|     beforeEach(() => { | ||||
|         state = new FinishState(); | ||||
|  | ||||
|         const data = bootstrap(); | ||||
|         context = data.context; | ||||
|         mock = data.mock; | ||||
|     }); | ||||
|  | ||||
|     afterEach(() => { | ||||
|         mock.verify(); | ||||
|     }); | ||||
|  | ||||
|     describe('#enter', () => { | ||||
|         it('should navigate to /oauth/finish', () => { | ||||
|             expectNavigate(mock, '/oauth/finish'); | ||||
|  | ||||
|             state.enter(context); | ||||
|         }); | ||||
|     }); | ||||
| }); | ||||
							
								
								
									
										97
									
								
								tests/services/authFlow/LoginState.test.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										97
									
								
								tests/services/authFlow/LoginState.test.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,97 @@ | ||||
| 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'; | ||||
|  | ||||
| describe('LoginState', () => { | ||||
|     let state; | ||||
|     let context; | ||||
|     let mock; | ||||
|  | ||||
|     beforeEach(() => { | ||||
|         state = new LoginState(); | ||||
|  | ||||
|         const data = bootstrap(); | ||||
|         context = data.context; | ||||
|         mock = data.mock; | ||||
|     }); | ||||
|  | ||||
|     afterEach(() => { | ||||
|         mock.verify(); | ||||
|     }); | ||||
|  | ||||
|     describe('#enter', () => { | ||||
|         it('should navigate to /login', () => { | ||||
|             context.getState.returns({ | ||||
|                 user: {isGuest: true} | ||||
|             }); | ||||
|  | ||||
|             expectNavigate(mock, '/login'); | ||||
|  | ||||
|             state.enter(context); | ||||
|         }); | ||||
|  | ||||
|         const testTransitionToPassword = (user) => { | ||||
|             context.getState.returns({ | ||||
|                 user: user | ||||
|             }); | ||||
|  | ||||
|             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'}); | ||||
|         }); | ||||
|     }); | ||||
|  | ||||
|     describe('#resolve', () => { | ||||
|         it('should call login with email or username', () => { | ||||
|             const payload = {}; | ||||
|  | ||||
|             expectRun( | ||||
|                 mock, | ||||
|                 'login', | ||||
|                 sinon.match.same(payload) | ||||
|             ).returns({then() {}}); | ||||
|  | ||||
|             state.resolve(context, payload); | ||||
|         }); | ||||
|  | ||||
|         it('should transition to password state on successfull login (first phase)', () => { | ||||
|             const promise = Promise.resolve(); | ||||
|  | ||||
|             mock.expects('run').returns(promise); | ||||
|             expectState(mock, PasswordState); | ||||
|  | ||||
|             state.resolve(context); | ||||
|  | ||||
|             return promise; | ||||
|         }); | ||||
|  | ||||
|         it('should NOT transition to password state on fail', () => { | ||||
|             const promise = Promise.reject(); | ||||
|  | ||||
|             mock.expects('run').returns(promise); | ||||
|             mock.expects('setState').never(); | ||||
|  | ||||
|             state.resolve(context); | ||||
|  | ||||
|             return promise.catch(mock.verify.bind(mock)); | ||||
|         }); | ||||
|     }); | ||||
|  | ||||
|     describe('#reject', () => { | ||||
|         it('should transition to forgot password state', () => { | ||||
|             expectState(mock, ForgotPasswordState); | ||||
|  | ||||
|             state.reject(context); | ||||
|         }); | ||||
|     }); | ||||
| }); | ||||
							
								
								
									
										67
									
								
								tests/services/authFlow/OAuthState.test.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								tests/services/authFlow/OAuthState.test.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,67 @@ | ||||
| import OAuthState from 'services/authFlow/OAuthState'; | ||||
| import CompleteState from 'services/authFlow/CompleteState'; | ||||
|  | ||||
| import { bootstrap, expectState, expectRun } from './helpers'; | ||||
|  | ||||
| describe('OAuthState', () => { | ||||
|     let state; | ||||
|     let context; | ||||
|     let mock; | ||||
|  | ||||
|     beforeEach(() => { | ||||
|         state = new OAuthState(); | ||||
|  | ||||
|         const data = bootstrap(); | ||||
|         context = data.context; | ||||
|         mock = data.mock; | ||||
|     }); | ||||
|  | ||||
|     afterEach(() => { | ||||
|         mock.verify(); | ||||
|     }); | ||||
|  | ||||
|     describe('#enter', () => { | ||||
|         it('should run oAuthValidate', () => { | ||||
|             const query = { | ||||
|                 client_id: 'client_id', | ||||
|                 redirect_uri: 'redirect_uri', | ||||
|                 response_type: 'response_type', | ||||
|                 scope: 'scope', | ||||
|                 state: 'state' | ||||
|             }; | ||||
|  | ||||
|             context.getState.returns({ | ||||
|                 routing: {location: {query}} | ||||
|             }); | ||||
|  | ||||
|             expectRun( | ||||
|                 mock, | ||||
|                 'oAuthValidate', | ||||
|                 sinon.match({ | ||||
|                     clientId: query.client_id, | ||||
|                     redirectUrl: query.redirect_uri, | ||||
|                     responseType: query.response_type, | ||||
|                     scope: query.scope, | ||||
|                     state: query.state | ||||
|                 }) | ||||
|             ).returns({then() {}}); | ||||
|  | ||||
|             state.enter(context); | ||||
|         }); | ||||
|  | ||||
|         it('should transition to complete state on success', () => { | ||||
|             const promise = Promise.resolve(); | ||||
|  | ||||
|             context.getState.returns({ | ||||
|                 routing: {location: {query: {}}} | ||||
|             }); | ||||
|  | ||||
|             mock.expects('run').returns(promise); | ||||
|             expectState(mock, CompleteState); | ||||
|  | ||||
|             state.enter(context); | ||||
|  | ||||
|             return promise; | ||||
|         }); | ||||
|     }); | ||||
| }); | ||||
							
								
								
									
										119
									
								
								tests/services/authFlow/PasswordState.test.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										119
									
								
								tests/services/authFlow/PasswordState.test.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,119 @@ | ||||
| import PasswordState from 'services/authFlow/PasswordState'; | ||||
| import CompleteState from 'services/authFlow/CompleteState'; | ||||
| import LoginState from 'services/authFlow/LoginState'; | ||||
| import ForgotPasswordState from 'services/authFlow/ForgotPasswordState'; | ||||
|  | ||||
| import { bootstrap, expectState, expectNavigate, expectRun } from './helpers'; | ||||
|  | ||||
| describe('PasswordState', () => { | ||||
|     let state; | ||||
|     let context; | ||||
|     let mock; | ||||
|  | ||||
|     beforeEach(() => { | ||||
|         state = new PasswordState(); | ||||
|  | ||||
|         const data = bootstrap(); | ||||
|         context = data.context; | ||||
|         mock = data.mock; | ||||
|     }); | ||||
|  | ||||
|     afterEach(() => { | ||||
|         mock.verify(); | ||||
|     }); | ||||
|  | ||||
|     describe('#enter', () => { | ||||
|         it('should navigate to /password', () => { | ||||
|             context.getState.returns({ | ||||
|                 user: {isGuest: true} | ||||
|             }); | ||||
|  | ||||
|             expectNavigate(mock, '/password'); | ||||
|  | ||||
|             state.enter(context); | ||||
|         }); | ||||
|  | ||||
|         it('should transition to complete if not guest', () => { | ||||
|             context.getState.returns({ | ||||
|                 user: {isGuest: false} | ||||
|             }); | ||||
|  | ||||
|             expectState(mock, CompleteState); | ||||
|  | ||||
|             state.enter(context); | ||||
|         }); | ||||
|     }); | ||||
|  | ||||
|     describe('#resolve', () => { | ||||
|         (() => { | ||||
|             const expectedLogin = 'login'; | ||||
|             const expectedPassword = 'password'; | ||||
|  | ||||
|             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 | ||||
|                         }) | ||||
|                     ).returns({then() {}}); | ||||
|  | ||||
|                     state.resolve(context, {password: expectedPassword}); | ||||
|                 }); | ||||
|             }; | ||||
|  | ||||
|             testWith({ | ||||
|                 email: expectedLogin | ||||
|             }); | ||||
|  | ||||
|             testWith({ | ||||
|                 username: expectedLogin | ||||
|             }); | ||||
|  | ||||
|             testWith({ | ||||
|                 email: expectedLogin, | ||||
|                 username: expectedLogin | ||||
|             }); | ||||
|         }); | ||||
|  | ||||
|         it('should transition to complete state on successfull login', () => { | ||||
|             const promise = Promise.resolve(); | ||||
|             const expectedLogin = 'login'; | ||||
|             const expectedPassword = 'password'; | ||||
|  | ||||
|             context.getState.returns({ | ||||
|                 user: { | ||||
|                     email: expectedLogin | ||||
|                 } | ||||
|             }); | ||||
|  | ||||
|             mock.expects('run').returns(promise); | ||||
|             expectState(mock, CompleteState); | ||||
|  | ||||
|             state.resolve(context, {password: expectedPassword}); | ||||
|  | ||||
|             return promise; | ||||
|         }); | ||||
|     }); | ||||
|  | ||||
|     describe('#reject', () => { | ||||
|         it('should transition to forgot password state', () => { | ||||
|             expectState(mock, ForgotPasswordState); | ||||
|  | ||||
|             state.reject(context); | ||||
|         }); | ||||
|     }); | ||||
|  | ||||
|     describe('#goBack', () => { | ||||
|         it('should transition to forgot password state', () => { | ||||
|             expectRun(mock, 'logout'); | ||||
|             expectState(mock, LoginState); | ||||
|  | ||||
|             state.goBack(context); | ||||
|         }); | ||||
|     }); | ||||
| }); | ||||
							
								
								
									
										56
									
								
								tests/services/authFlow/PermissionsState.test.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								tests/services/authFlow/PermissionsState.test.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,56 @@ | ||||
| import PermissionsState from 'services/authFlow/PermissionsState'; | ||||
| import CompleteState from 'services/authFlow/CompleteState'; | ||||
|  | ||||
| import { bootstrap, expectNavigate } from './helpers'; | ||||
|  | ||||
| describe('PermissionsState', () => { | ||||
|     let state; | ||||
|     let context; | ||||
|     let mock; | ||||
|  | ||||
|     beforeEach(() => { | ||||
|         state = new PermissionsState(); | ||||
|  | ||||
|         const data = bootstrap(); | ||||
|         context = data.context; | ||||
|         mock = data.mock; | ||||
|     }); | ||||
|  | ||||
|     afterEach(() => { | ||||
|         mock.verify(); | ||||
|     }); | ||||
|  | ||||
|     describe('#enter', () => { | ||||
|         it('should navigate to /oauth/permissions', () => { | ||||
|             expectNavigate(mock, '/oauth/permissions'); | ||||
|  | ||||
|             state.enter(context); | ||||
|         }); | ||||
|     }); | ||||
|  | ||||
|     describe('#resolve', () => { | ||||
|         it('should transition to complete state with acceptance', () => { | ||||
|             mock.expects('setState').once().withExactArgs( | ||||
|                 sinon.match.instanceOf(CompleteState) | ||||
|                     .and( | ||||
|                         sinon.match.has('isPermissionsAccepted', true) | ||||
|                     ) | ||||
|             ); | ||||
|  | ||||
|             state.resolve(context); | ||||
|         }); | ||||
|     }); | ||||
|  | ||||
|     describe('#reject', () => { | ||||
|         it('should transition to complete state without acceptance', () => { | ||||
|             mock.expects('setState').once().withExactArgs( | ||||
|                 sinon.match.instanceOf(CompleteState) | ||||
|                     .and( | ||||
|                         sinon.match.has('isPermissionsAccepted', false) | ||||
|                     ) | ||||
|             ); | ||||
|  | ||||
|             state.reject(context); | ||||
|         }); | ||||
|     }); | ||||
| }); | ||||
							
								
								
									
										81
									
								
								tests/services/authFlow/RegisterState.test.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								tests/services/authFlow/RegisterState.test.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,81 @@ | ||||
| import RegisterState from 'services/authFlow/RegisterState'; | ||||
| import CompleteState from 'services/authFlow/CompleteState'; | ||||
|  | ||||
| import { bootstrap, expectState, expectNavigate, expectRun } from './helpers'; | ||||
|  | ||||
| describe('RegisterState', () => { | ||||
|     let state; | ||||
|     let context; | ||||
|     let mock; | ||||
|  | ||||
|     beforeEach(() => { | ||||
|         state = new RegisterState(); | ||||
|  | ||||
|         const data = bootstrap(); | ||||
|         context = data.context; | ||||
|         mock = data.mock; | ||||
|     }); | ||||
|  | ||||
|     afterEach(() => { | ||||
|         mock.verify(); | ||||
|     }); | ||||
|  | ||||
|     describe('#enter', () => { | ||||
|         it('should navigate to /register', () => { | ||||
|             context.getState.returns({ | ||||
|                 user: {isGuest: true} | ||||
|             }); | ||||
|  | ||||
|             expectNavigate(mock, '/register'); | ||||
|  | ||||
|             state.enter(context); | ||||
|         }); | ||||
|  | ||||
|         it('should transition to complete if not guest', () => { | ||||
|             context.getState.returns({ | ||||
|                 user: {isGuest: false} | ||||
|             }); | ||||
|  | ||||
|             expectState(mock, CompleteState); | ||||
|  | ||||
|             state.enter(context); | ||||
|         }); | ||||
|     }); | ||||
|  | ||||
|     describe('#resolve', () => { | ||||
|         it('should register on resolve', () => { | ||||
|             const payload = {}; | ||||
|  | ||||
|             expectRun( | ||||
|                 mock, | ||||
|                 'register', | ||||
|                 sinon.match.same(payload) | ||||
|             ).returns({then() {}}); | ||||
|  | ||||
|             state.resolve(context, payload); | ||||
|         }); | ||||
|  | ||||
|         it('should transition to complete after register', () => { | ||||
|             const payload = {}; | ||||
|             const promise = Promise.resolve(); | ||||
|  | ||||
|             mock.expects('run').returns(promise); | ||||
|             expectState(mock, CompleteState); | ||||
|  | ||||
|             state.resolve(context, payload); | ||||
|  | ||||
|             return promise; | ||||
|         }); | ||||
|  | ||||
|         it('should NOT transition to complete if register fails', () => { | ||||
|             const promise = Promise.reject(); | ||||
|  | ||||
|             mock.expects('run').returns(promise); | ||||
|             mock.expects('setState').never(); | ||||
|  | ||||
|             state.resolve(context); | ||||
|  | ||||
|             return promise.catch(mock.verify.bind(mock)); | ||||
|         }); | ||||
|     }); | ||||
| }); | ||||
							
								
								
									
										29
									
								
								tests/services/authFlow/helpers.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								tests/services/authFlow/helpers.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | ||||
| export function bootstrap() { | ||||
|     const context = { | ||||
|         getState: sinon.stub(), | ||||
|         run() {}, | ||||
|         setState() {}, | ||||
|         navigate() {} | ||||
|     }; | ||||
|  | ||||
|     const mock = sinon.mock(context); | ||||
|     mock.expects('run').never(); | ||||
|     mock.expects('navigate').never(); | ||||
|     mock.expects('setState').never(); | ||||
|  | ||||
|     return {context, mock}; | ||||
| } | ||||
|  | ||||
| export function expectState(mock, state) { | ||||
|     return mock.expects('setState').once().withExactArgs( | ||||
|         sinon.match.instanceOf(state) | ||||
|     ); | ||||
| } | ||||
|  | ||||
| export function expectNavigate(mock, route) { | ||||
|     return mock.expects('navigate').once().withExactArgs(route); | ||||
| } | ||||
|  | ||||
| export function expectRun(mock, ...args) { | ||||
|     return mock.expects('run').once().withExactArgs(...args); | ||||
| } | ||||
		Reference in New Issue
	
	Block a user