fleet/frontend/redux/nodes/auth/reducer.tests.js
Zachary Wasserman 60428e01c4 Fix required password reset flow (#833)
Permissions errors were preventing users from completing this flow

- Add separate endpoint for performing required password reset
- Rewrite frontend reset to use this endpoint

Fixes #792
2017-01-09 21:42:50 -07:00

221 lines
5.9 KiB
JavaScript

import configureStore from 'redux-mock-store';
import expect from 'expect';
import { find } from 'lodash';
import thunk from 'redux-thunk';
import authMiddleware from '../../middlewares/auth';
import kolide from '../../../kolide';
import local from '../../../utilities/local';
import {
loginRequest,
LOGIN_REQUEST,
LOGIN_SUCCESS,
loginUser,
logoutUser,
LOGOUT_REQUEST,
LOGOUT_SUCCESS,
performRequiredPasswordResetRequest,
performRequiredPasswordResetSuccess,
performRequiredPasswordResetFailure,
} from './actions';
import reducer, { initialState } from './reducer';
import {
validLoginRequest,
validLogoutRequest,
validUser,
} from '../../../test/mocks';
describe('Auth - reducer', () => {
it('sets the initial state', () => {
const state = reducer(undefined, { type: 'FOO' });
expect(state).toEqual(initialState);
});
it('changes loading to true for the userLogin action', () => {
const state = reducer(initialState, loginRequest);
expect(state).toEqual({
...initialState,
loading: true,
});
});
context('loginUser action', () => {
const formData = {
username: 'username',
password: 'p@ssw0rd',
};
const middlewares = [thunk, authMiddleware];
const mockStore = configureStore(middlewares);
const store = mockStore({});
it('calls the api login endpoint', (done) => {
const expectedBearerToken = 'expected-bearer-token';
const loginRequestMock = validLoginRequest(expectedBearerToken);
store.dispatch(loginUser(formData))
.then(() => {
const loginSuccessAction = find(store.getActions(), { type: 'LOGIN_SUCCESS' });
expect(loginSuccessAction.payload.token).toEqual(expectedBearerToken);
expect(loginRequestMock.isDone()).toEqual(true);
done();
})
.catch(done);
});
it('returns the authenticated user', (done) => {
validLoginRequest();
store.dispatch(loginUser(formData))
.then((user) => {
expect(user).toEqual(validUser);
done();
})
.catch(done);
});
it('sets the users auth token in local storage', (done) => {
const expectedBearerToken = 'expected-bearer-token';
validLoginRequest(expectedBearerToken);
store.dispatch(loginUser(formData))
.then(() => {
expect(local.getItem('auth_token')).toEqual(expectedBearerToken);
done();
})
.catch(done);
});
it('sets the api client bearerToken', (done) => {
const expectedBearerToken = 'expected-bearer-token';
validLoginRequest(expectedBearerToken);
store.dispatch(loginUser(formData))
.then(() => {
expect(kolide.bearerToken).toEqual(expectedBearerToken);
done();
})
.catch(done);
});
it('dispatches LOGIN_REQUEST and LOGIN_SUCCESS actions', (done) => {
validLoginRequest();
store.dispatch(loginUser(formData))
.then(() => {
const actionTypes = store.getActions().map(a => a.type);
expect(actionTypes).toInclude(LOGIN_REQUEST, LOGIN_SUCCESS);
done();
})
.catch(done);
});
});
context('logoutUser action', () => {
const bearerToken = 'ABC123';
const middlewares = [thunk, authMiddleware];
const mockStore = configureStore(middlewares);
const store = mockStore({});
beforeEach(() => {
local.setItem('auth_token', bearerToken);
kolide.setBearerToken(bearerToken);
});
it('calls the api logout endpoint', (done) => {
const logoutRequestMock = validLogoutRequest(bearerToken);
store.dispatch(logoutUser())
.then(() => {
expect(logoutRequestMock.isDone()).toEqual(true);
done();
})
.catch(done);
});
it('removes the users auth token from local storage', (done) => {
validLogoutRequest(bearerToken);
store.dispatch(logoutUser())
.then(() => {
expect(local.getItem('auth_token')).toNotExist();
done();
})
.catch(done);
});
it('clears the api client bearerToken', (done) => {
validLogoutRequest(bearerToken);
store.dispatch(logoutUser())
.then(() => {
expect(kolide.bearerToken).toNotExist();
done();
})
.catch(done);
});
it('dispatches LOGOUT_REQUEST and LOGOUT_SUCCESS actions', (done) => {
validLogoutRequest(bearerToken);
store.dispatch(logoutUser())
.then(() => {
const actionTypes = store.getActions().map(a => a.type);
expect(actionTypes).toInclude(LOGOUT_REQUEST, LOGOUT_SUCCESS);
done();
})
.catch(done);
});
});
context('perform required password reset', () => {
const user = { id: 1, email: '[email protected]', force_password_reset: true };
it('updates state when request is dispatched', () => {
const initState = {
...initialState,
user,
};
const newState = reducer(initState, performRequiredPasswordResetRequest);
expect(newState).toEqual({
...initState,
loading: true,
});
});
it('updates state when request is successful', () => {
const initState = {
...initialState,
user,
loading: true,
};
const newUser = { ...user, force_password_reset: false };
const newState = reducer(initState, performRequiredPasswordResetSuccess(newUser));
expect(newState).toEqual({
...initState,
loading: false,
user: newUser,
});
});
it('updates state when request fails', () => {
const initState = {
...initialState,
loading: true,
};
const errors = { base: 'Unable to reset password' };
const newState = reducer(initState, performRequiredPasswordResetFailure(errors));
expect(newState).toEqual({
...initState,
errors,
loading: false,
});
});
});
});