2018-07-09 11:38:13 +02:00
|
|
|
import reducer, {
|
2018-07-13 10:57:11 +02:00
|
|
|
fetchMeSuccess,
|
2018-07-12 11:33:41 +02:00
|
|
|
logout,
|
2018-07-13 10:57:11 +02:00
|
|
|
logoutSuccess,
|
|
|
|
|
loginSuccess,
|
|
|
|
|
fetchMeRequest,
|
|
|
|
|
loginRequest,
|
|
|
|
|
logoutRequest,
|
|
|
|
|
fetchMeFailure,
|
|
|
|
|
fetchMeUnauthenticated,
|
|
|
|
|
loginFailure,
|
|
|
|
|
logoutFailure,
|
2018-07-09 11:38:13 +02:00
|
|
|
LOGIN_REQUEST,
|
2018-07-13 10:57:11 +02:00
|
|
|
FETCH_ME_REQUEST,
|
|
|
|
|
LOGIN_SUCCESS,
|
|
|
|
|
login,
|
|
|
|
|
LOGIN_FAILURE,
|
|
|
|
|
LOGOUT_FAILURE,
|
|
|
|
|
FETCH_ME_SUCCESS,
|
|
|
|
|
fetchMe,
|
|
|
|
|
FETCH_ME_FAILURE,
|
|
|
|
|
FETCH_ME_UNAUTHORIZED,
|
|
|
|
|
isAuthenticated
|
2018-07-12 11:33:41 +02:00
|
|
|
} from "./auth";
|
2018-07-09 11:38:13 +02:00
|
|
|
|
2018-07-11 22:01:36 +02:00
|
|
|
import configureMockStore from "redux-mock-store";
|
|
|
|
|
import thunk from "redux-thunk";
|
|
|
|
|
import fetchMock from "fetch-mock";
|
2018-07-13 10:57:11 +02:00
|
|
|
import { LOGOUT_REQUEST, LOGOUT_SUCCESS } from "./auth";
|
|
|
|
|
|
|
|
|
|
describe("auth reducer", () => {
|
|
|
|
|
it("should initialize in loading state ", () => {
|
|
|
|
|
const state = reducer();
|
|
|
|
|
expect(state.me.loading).toBeTruthy();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it("should set me and login on successful fetch of me", () => {
|
|
|
|
|
const state = reducer(undefined, fetchMeSuccess({ username: "tricia" }));
|
|
|
|
|
expect(state.me.loading).toBeFalsy();
|
|
|
|
|
expect(state.me.entry.username).toBe("tricia");
|
|
|
|
|
expect(state.login.authenticated).toBeTruthy();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it("should set authenticated to false", () => {
|
|
|
|
|
const initialState = {
|
|
|
|
|
login: {
|
|
|
|
|
authenticated: true
|
|
|
|
|
},
|
|
|
|
|
me: {
|
|
|
|
|
username: "tricia"
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
const state = reducer(initialState, fetchMeUnauthenticated());
|
|
|
|
|
expect(state.me.username).toBeUndefined();
|
|
|
|
|
expect(state.login.authenticated).toBeFalsy();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it("should reset the state after logout", () => {
|
|
|
|
|
const initialState = {
|
|
|
|
|
login: {
|
|
|
|
|
authenticated: true
|
|
|
|
|
},
|
|
|
|
|
me: {
|
|
|
|
|
username: "tricia"
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
const state = reducer(initialState, logoutSuccess());
|
|
|
|
|
expect(state.me.loading).toBeTruthy();
|
|
|
|
|
expect(state.me.entry).toBeFalsy();
|
|
|
|
|
expect(state.login).toBeUndefined();
|
|
|
|
|
});
|
2018-07-09 11:38:13 +02:00
|
|
|
|
2018-07-13 10:57:11 +02:00
|
|
|
it("should set state authenticated after login", () => {
|
|
|
|
|
const state = reducer(undefined, loginSuccess());
|
|
|
|
|
expect(state.login.authenticated).toBeTruthy();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it("should set me to loading", () => {
|
|
|
|
|
const state = reducer({ me: { loading: false } }, fetchMeRequest());
|
|
|
|
|
expect(state.me.loading).toBeTruthy();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it("should set login to loading", () => {
|
|
|
|
|
const state = reducer({ login: { loading: false } }, loginRequest());
|
|
|
|
|
expect(state.login.loading).toBeTruthy();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it("should set logout to loading", () => {
|
|
|
|
|
const state = reducer({ logout: { loading: false } }, logoutRequest());
|
|
|
|
|
expect(state.logout.loading).toBeTruthy();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it("should set me to error", () => {
|
|
|
|
|
const error = new Error("failed");
|
|
|
|
|
const state = reducer(undefined, fetchMeFailure(error));
|
|
|
|
|
expect(state.me.error).toBe(error);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it("should set login to error", () => {
|
|
|
|
|
const error = new Error("failed");
|
|
|
|
|
const state = reducer(undefined, loginFailure(error));
|
|
|
|
|
expect(state.login.error).toBe(error);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it("should set logout to error", () => {
|
|
|
|
|
const error = new Error("failed");
|
|
|
|
|
const state = reducer(undefined, logoutFailure(error));
|
|
|
|
|
expect(state.logout.error).toBe(error);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe("auth actions", () => {
|
2018-07-11 22:01:36 +02:00
|
|
|
const mockStore = configureMockStore([thunk]);
|
2018-07-09 11:38:13 +02:00
|
|
|
|
2018-07-11 22:01:36 +02:00
|
|
|
afterEach(() => {
|
|
|
|
|
fetchMock.reset();
|
|
|
|
|
fetchMock.restore();
|
|
|
|
|
});
|
|
|
|
|
|
2018-07-13 10:57:11 +02:00
|
|
|
it("should dispatch login success and dispatch fetch me", () => {
|
2018-07-11 22:01:36 +02:00
|
|
|
fetchMock.postOnce("/scm/api/rest/v2/auth/access_token", {
|
|
|
|
|
body: {
|
|
|
|
|
cookie: true,
|
|
|
|
|
grant_type: "password",
|
|
|
|
|
username: "tricia",
|
|
|
|
|
password: "secret123"
|
|
|
|
|
},
|
|
|
|
|
headers: { "content-type": "application/json" }
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
fetchMock.getOnce("/scm/api/rest/v2/me", {
|
|
|
|
|
body: {
|
|
|
|
|
username: "tricia"
|
|
|
|
|
},
|
|
|
|
|
headers: { "content-type": "application/json" }
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const expectedActions = [
|
|
|
|
|
{ type: LOGIN_REQUEST },
|
2018-07-13 10:57:11 +02:00
|
|
|
{ type: FETCH_ME_REQUEST },
|
|
|
|
|
{ type: LOGIN_SUCCESS }
|
2018-07-11 22:01:36 +02:00
|
|
|
];
|
2018-07-09 11:38:13 +02:00
|
|
|
|
2018-07-11 22:01:36 +02:00
|
|
|
const store = mockStore({});
|
|
|
|
|
|
|
|
|
|
return store.dispatch(login("tricia", "secret123")).then(() => {
|
|
|
|
|
expect(store.getActions()).toEqual(expectedActions);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
2018-07-13 10:57:11 +02:00
|
|
|
it("should dispatch login failure", () => {
|
2018-07-11 22:01:36 +02:00
|
|
|
fetchMock.postOnce("/scm/api/rest/v2/auth/access_token", {
|
|
|
|
|
status: 400
|
|
|
|
|
});
|
|
|
|
|
|
2018-07-13 10:57:11 +02:00
|
|
|
const expectedActions = [{ type: LOGIN_REQUEST }, { type: LOGIN_FAILURE }];
|
2018-07-11 22:01:36 +02:00
|
|
|
|
|
|
|
|
const store = mockStore({});
|
|
|
|
|
return store.dispatch(login("tricia", "secret123")).then(() => {
|
|
|
|
|
const actions = store.getActions();
|
|
|
|
|
expect(actions[0].type).toEqual(LOGIN_REQUEST);
|
2018-07-13 10:57:11 +02:00
|
|
|
expect(actions[1].type).toEqual(LOGIN_FAILURE);
|
2018-07-11 22:01:36 +02:00
|
|
|
expect(actions[1].payload).toBeDefined();
|
|
|
|
|
});
|
|
|
|
|
});
|
2018-07-12 11:33:41 +02:00
|
|
|
|
2018-07-13 10:57:11 +02:00
|
|
|
it("should dispatch fetch me success", () => {
|
|
|
|
|
fetchMock.getOnce("/scm/api/rest/v2/me", {
|
|
|
|
|
body: { username: "sorbot" },
|
|
|
|
|
headers: { "content-type": "application/json" }
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const expectedActions = [
|
|
|
|
|
{ type: FETCH_ME_REQUEST },
|
|
|
|
|
{ type: FETCH_ME_SUCCESS, payload: { username: "sorbot" } }
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
const store = mockStore({});
|
|
|
|
|
|
|
|
|
|
return store.dispatch(fetchMe()).then(() => {
|
|
|
|
|
expect(store.getActions()).toEqual(expectedActions);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it("should dispatch fetch me failure", () => {
|
|
|
|
|
fetchMock.getOnce("/scm/api/rest/v2/me", {
|
|
|
|
|
status: 500
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const store = mockStore({});
|
|
|
|
|
return store.dispatch(fetchMe()).then(() => {
|
|
|
|
|
const actions = store.getActions();
|
|
|
|
|
expect(actions[0].type).toEqual(FETCH_ME_REQUEST);
|
|
|
|
|
expect(actions[1].type).toEqual(FETCH_ME_FAILURE);
|
|
|
|
|
expect(actions[1].payload).toBeDefined();
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it("should dispatch fetch me unauthorized", () => {
|
|
|
|
|
fetchMock.getOnce("/scm/api/rest/v2/me", {
|
|
|
|
|
status: 401
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const expectedActions = [
|
|
|
|
|
{ type: FETCH_ME_REQUEST },
|
|
|
|
|
{ type: FETCH_ME_UNAUTHORIZED }
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
const store = mockStore({});
|
|
|
|
|
|
|
|
|
|
return store.dispatch(fetchMe()).then(() => {
|
|
|
|
|
// return of async actions
|
|
|
|
|
expect(store.getActions()).toEqual(expectedActions);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it("should dispatch logout success", () => {
|
2018-07-12 11:33:41 +02:00
|
|
|
fetchMock.deleteOnce("/scm/api/rest/v2/auth/access_token", {
|
|
|
|
|
status: 204
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
fetchMock.getOnce("/scm/api/rest/v2/me", {
|
|
|
|
|
status: 401
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const expectedActions = [
|
|
|
|
|
{ type: LOGOUT_REQUEST },
|
2018-07-13 10:57:11 +02:00
|
|
|
{ type: LOGOUT_SUCCESS },
|
|
|
|
|
{ type: FETCH_ME_REQUEST }
|
2018-07-12 11:33:41 +02:00
|
|
|
];
|
|
|
|
|
|
|
|
|
|
const store = mockStore({});
|
|
|
|
|
|
|
|
|
|
return store.dispatch(logout()).then(() => {
|
|
|
|
|
expect(store.getActions()).toEqual(expectedActions);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
2018-07-13 10:57:11 +02:00
|
|
|
it("should dispatch logout failure", () => {
|
2018-07-12 11:33:41 +02:00
|
|
|
fetchMock.deleteOnce("/scm/api/rest/v2/auth/access_token", {
|
|
|
|
|
status: 500
|
|
|
|
|
});
|
|
|
|
|
|
2018-07-13 10:57:11 +02:00
|
|
|
const expectedActions = [
|
|
|
|
|
{ type: LOGOUT_REQUEST },
|
|
|
|
|
{ type: LOGOUT_FAILURE }
|
|
|
|
|
];
|
2018-07-12 11:33:41 +02:00
|
|
|
|
|
|
|
|
const store = mockStore({});
|
|
|
|
|
return store.dispatch(logout()).then(() => {
|
|
|
|
|
const actions = store.getActions();
|
|
|
|
|
expect(actions[0].type).toEqual(LOGOUT_REQUEST);
|
2018-07-13 10:57:11 +02:00
|
|
|
expect(actions[1].type).toEqual(LOGOUT_FAILURE);
|
2018-07-12 11:33:41 +02:00
|
|
|
expect(actions[1].payload).toBeDefined();
|
|
|
|
|
});
|
|
|
|
|
});
|
2018-07-09 11:38:13 +02:00
|
|
|
});
|
|
|
|
|
|
2018-07-13 10:57:11 +02:00
|
|
|
describe("auth selectors", () => {
|
|
|
|
|
it("should be false", () => {
|
|
|
|
|
expect(isAuthenticated({})).toBeFalsy();
|
|
|
|
|
expect(isAuthenticated({ auth: {} })).toBeFalsy();
|
|
|
|
|
expect(isAuthenticated({ auth: { login: {} } })).toBeFalsy();
|
|
|
|
|
expect(
|
|
|
|
|
isAuthenticated({ auth: { login: { authenticated: false } } })
|
|
|
|
|
).toBeFalsy();
|
2018-07-12 11:33:41 +02:00
|
|
|
});
|
|
|
|
|
|
2018-07-13 10:57:11 +02:00
|
|
|
it("shuld be true", () => {
|
|
|
|
|
expect(
|
|
|
|
|
isAuthenticated({ auth: { login: { authenticated: true } } })
|
|
|
|
|
).toBeTruthy();
|
2018-07-12 11:33:41 +02:00
|
|
|
});
|
2018-07-09 11:38:13 +02:00
|
|
|
});
|