import { Action as ReduxAction } from 'redux'; import sinon from 'sinon'; import expect from 'app/test/unexpected'; import request from 'app/services/request'; import { setLoadingState, oAuthValidate, oAuthComplete, setClient, setOAuthRequest, setScopes, setOAuthCode, requirePermissionsAccept, login, setLogin, } from 'app/components/auth/actions'; import { OAuthValidateResponse } from 'app/services/api/oauth'; import { OAuthState } from './reducer'; const oauthData: OAuthState = { params: { clientId: '', redirectUrl: '', responseType: '', scope: '', state: '', }, prompt: 'none', }; describe('components/auth/actions', () => { const dispatch = sinon.stub().named('store.dispatch'); const getState = sinon.stub().named('store.getState'); function callThunk, F extends (...args: A) => any>(fn: F, ...args: A): Promise { const thunk = fn(...args); return thunk(dispatch, getState); } function expectDispatchCalls(calls: Array>) { expect(dispatch, 'to have calls satisfying', [[setLoadingState(true)], ...calls, [setLoadingState(false)]]); } beforeEach(() => { dispatch.reset(); getState.reset(); getState.returns({}); sinon.stub(request, 'get').named('request.get'); sinon.stub(request, 'post').named('request.post'); }); afterEach(() => { (request.get as any).restore(); (request.post as any).restore(); }); describe('#oAuthValidate()', () => { let resp: OAuthValidateResponse; beforeEach(() => { resp = { client: { id: '123', name: '', description: '', }, session: { scopes: ['account_info'], }, }; (request.get as any).returns(Promise.resolve(resp)); }); 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', () => callThunk(oAuthValidate, oauthData).then(() => { expectDispatchCalls([ [setClient(resp.client)], [ setOAuthRequest({ params: { clientId: '', redirectUrl: '', responseType: '', state: '', scope: '', }, prompt: ['none'], loginHint: undefined, }), ], [setScopes(resp.session.scopes)], ]); })); }); describe('#oAuthComplete()', () => { beforeEach(() => { getState.returns({ auth: { oauth: oauthData, }, }); }); it('should post to api/oauth2/complete', () => { (request.post as any).returns( Promise.resolve({ redirectUri: '', }), ); return callThunk(oAuthComplete).then(() => { expect(request.post, 'to have a call satisfying', [ '/api/oauth2/v1/complete?client_id=&redirect_uri=&response_type=&scope=&state=', {}, ]); }); }); it('should dispatch setOAuthCode for static_page redirect', () => { const resp = { success: true, redirectUri: 'static_page?code=123&state=', }; (request.post as any).returns(Promise.resolve(resp)); return callThunk(oAuthComplete).then(() => { expectDispatchCalls([ [ setOAuthCode({ success: true, code: '123', displayCode: false, }), ], ]); }); }); it('should resolve to with success false and redirectUri for access_denied', async () => { const resp = { statusCode: 401, error: 'access_denied', redirectUri: 'redirectUri', }; (request.post as any).returns(Promise.reject(resp)); const data = await callThunk(oAuthComplete); expect(data, 'to equal', { success: false, redirectUri: 'redirectUri', }); }); it('should dispatch requirePermissionsAccept if accept_required', () => { const resp = { statusCode: 401, error: 'accept_required', }; (request.post as any).returns(Promise.reject(resp)); return callThunk(oAuthComplete).catch((error) => { expect(error.acceptRequired, 'to be true'); expectDispatchCalls([[requirePermissionsAccept()]]); }); }); }); describe('#login()', () => { describe('when correct login was entered', () => { beforeEach(() => { (request.post as any).returns( Promise.reject({ errors: { password: 'error.password_required', }, }), ); }); it('should set login', () => callThunk(login, { login: 'foo' }).then(() => { expectDispatchCalls([[setLogin('foo')]]); })); }); }); });