diff --git a/scm-ui/src/groups/containers/EditGroup.js b/scm-ui/src/groups/containers/EditGroup.js index e21731a323..3150060f5b 100644 --- a/scm-ui/src/groups/containers/EditGroup.js +++ b/scm-ui/src/groups/containers/EditGroup.js @@ -2,7 +2,7 @@ import React from "react"; import { connect } from "react-redux"; import GroupForm from "../components/GroupForm"; -import { modifyGroup, fetchGroup } from "../modules/groups"; +import { modifyGroup } from "../modules/groups"; import type { History } from "history"; import { withRouter } from "react-router-dom"; import type { Group } from "@scm-manager/ui-types"; @@ -12,7 +12,6 @@ import { ErrorNotification } from "@scm-manager/ui-components"; type Props = { group: Group, modifyGroup: (group: Group, callback?: () => void) => void, - fetchGroup: (name: string) => void, history: History, loading?: boolean, error: Error @@ -20,7 +19,6 @@ type Props = { class EditGroup extends React.Component { groupModified = (group: Group) => () => { - this.props.fetchGroup(group.name); this.props.history.push(`/group/${group.name}`); }; @@ -58,9 +56,6 @@ const mapDispatchToProps = dispatch => { return { modifyGroup: (group: Group, callback?: () => void) => { dispatch(modifyGroup(group, callback)); - }, - fetchGroup: (name: string) => { - dispatch(fetchGroup(name)); } }; }; diff --git a/scm-ui/src/groups/containers/SingleGroup.js b/scm-ui/src/groups/containers/SingleGroup.js index d681859808..1dd4aa569f 100644 --- a/scm-ui/src/groups/containers/SingleGroup.js +++ b/scm-ui/src/groups/containers/SingleGroup.js @@ -16,7 +16,7 @@ import type { Group } from "@scm-manager/ui-types"; import type { History } from "history"; import { deleteGroup, - fetchGroup, + fetchGroupByName, getGroupByName, isFetchGroupPending, getFetchGroupFailure, @@ -37,7 +37,7 @@ type Props = { // dispatcher functions deleteGroup: (group: Group, callback?: () => void) => void, - fetchGroup: (string, string) => void, + fetchGroupByName: (string, string) => void, // context objects t: string => string, @@ -47,7 +47,7 @@ type Props = { class SingleGroup extends React.Component { componentDidMount() { - this.props.fetchGroup(this.props.groupLink, this.props.name); + this.props.fetchGroupByName(this.props.groupLink, this.props.name); } stripEndingSlash = (url: string) => { @@ -147,8 +147,8 @@ const mapStateToProps = (state, ownProps) => { const mapDispatchToProps = dispatch => { return { - fetchGroup: (link: string, name: string) => { - dispatch(fetchGroup(link, name)); + fetchGroupByName: (link: string, name: string) => { + dispatch(fetchGroupByName(link, name)); }, deleteGroup: (group: Group, callback?: () => void) => { dispatch(deleteGroup(group, callback)); diff --git a/scm-ui/src/groups/modules/groups.js b/scm-ui/src/groups/modules/groups.js index 74e7214052..5e661345b8 100644 --- a/scm-ui/src/groups/modules/groups.js +++ b/scm-ui/src/groups/modules/groups.js @@ -84,12 +84,20 @@ export function fetchGroupsFailure(url: string, error: Error): Action { } //fetch group -export function fetchGroup(link: string, name: string) { +export function fetchGroupByLink(group: Group) { + return fetchGroup(group._links.self.href, group.name); +} + +export function fetchGroupByName(link: string, name: string) { const groupUrl = link.endsWith("/") ? link + name : link + "/" + name; + return fetchGroup(groupUrl, name); +} + +function fetchGroup(link: string, name: string) { return function(dispatch: any) { dispatch(fetchGroupPending(name)); return apiClient - .get(groupUrl) + .get(link) .then(response => { return response.json(); }) @@ -189,6 +197,9 @@ export function modifyGroup(group: Group, callback?: () => void) { callback(); } }) + .then(() => { + dispatch(fetchGroupByLink(group)); + }) .catch(cause => { dispatch( modifyGroupFailure( @@ -361,8 +372,6 @@ function byNamesReducer(state: any = {}, action: any = {}) { }; case FETCH_GROUP_SUCCESS: return reducerByName(state, action.payload.name, action.payload); - case MODIFY_GROUP_SUCCESS: - return reducerByName(state, action.payload.name, action.payload); case DELETE_GROUP_SUCCESS: const newGroupByNames = deleteGroupInGroupsByNames( state, diff --git a/scm-ui/src/groups/modules/groups.test.js b/scm-ui/src/groups/modules/groups.test.js index 63ab375cd3..57d41975a1 100644 --- a/scm-ui/src/groups/modules/groups.test.js +++ b/scm-ui/src/groups/modules/groups.test.js @@ -15,7 +15,8 @@ import reducer, { getFetchGroupsFailure, isFetchGroupsPending, selectListAsCollection, - fetchGroup, + fetchGroupByLink, + fetchGroupByName, FETCH_GROUP_PENDING, FETCH_GROUP_SUCCESS, FETCH_GROUP_FAILURE, @@ -46,6 +47,7 @@ import reducer, { getCreateGroupLink } from "./groups"; const GROUPS_URL = "/api/v2/groups"; +const URL_HUMAN_GROUP = "http://localhost:8081/api/v2/groups/humanGroup"; const URL = "/groups"; const error = new Error("You have an error!"); @@ -59,13 +61,13 @@ const humanGroup = { members: ["userZaphod"], _links: { self: { - href: "http://localhost:8081/api/v2/groups/humanGroup" + href: URL_HUMAN_GROUP }, delete: { - href: "http://localhost:8081/api/v2/groups/humanGroup" + href: URL_HUMAN_GROUP }, update: { - href: "http://localhost:8081/api/v2/groups/humanGroup" + href: URL_HUMAN_GROUP } }, _embedded: { @@ -171,11 +173,37 @@ describe("groups fetch()", () => { }); }); - it("should sucessfully fetch single group", () => { + it("should sucessfully fetch single group by name", () => { fetchMock.getOnce(GROUPS_URL + "/humanGroup", humanGroup); const store = mockStore({}); - return store.dispatch(fetchGroup(URL, "humanGroup")).then(() => { + return store.dispatch(fetchGroupByName(URL, "humanGroup")).then(() => { + const actions = store.getActions(); + expect(actions[0].type).toEqual(FETCH_GROUP_PENDING); + expect(actions[1].type).toEqual(FETCH_GROUP_SUCCESS); + expect(actions[1].payload).toBeDefined(); + }); + }); + + it("should fail fetching single group by name on HTTP 500", () => { + fetchMock.getOnce(GROUPS_URL + "/humanGroup", { + status: 500 + }); + + const store = mockStore({}); + return store.dispatch(fetchGroupByName(URL, "humanGroup")).then(() => { + const actions = store.getActions(); + expect(actions[0].type).toEqual(FETCH_GROUP_PENDING); + expect(actions[1].type).toEqual(FETCH_GROUP_FAILURE); + expect(actions[1].payload).toBeDefined(); + }); + }); + + it("should sucessfully fetch single group", () => { + fetchMock.getOnce(URL_HUMAN_GROUP, humanGroup); + + const store = mockStore({}); + return store.dispatch(fetchGroupByLink(humanGroup)).then(() => { const actions = store.getActions(); expect(actions[0].type).toEqual(FETCH_GROUP_PENDING); expect(actions[1].type).toEqual(FETCH_GROUP_SUCCESS); @@ -184,12 +212,12 @@ describe("groups fetch()", () => { }); it("should fail fetching single group on HTTP 500", () => { - fetchMock.getOnce(GROUPS_URL + "/humanGroup", { + fetchMock.getOnce(URL_HUMAN_GROUP, { status: 500 }); const store = mockStore({}); - return store.dispatch(fetchGroup(URL, "humanGroup")).then(() => { + return store.dispatch(fetchGroupByLink(humanGroup)).then(() => { const actions = store.getActions(); expect(actions[0].type).toEqual(FETCH_GROUP_PENDING); expect(actions[1].type).toEqual(FETCH_GROUP_FAILURE); @@ -244,9 +272,10 @@ describe("groups fetch()", () => { }); it("should successfully modify group", () => { - fetchMock.putOnce("http://localhost:8081/api/v2/groups/humanGroup", { + fetchMock.putOnce(URL_HUMAN_GROUP, { status: 204 }); + fetchMock.getOnce(URL_HUMAN_GROUP, humanGroup); const store = mockStore({}); @@ -254,14 +283,16 @@ describe("groups fetch()", () => { const actions = store.getActions(); expect(actions[0].type).toEqual(MODIFY_GROUP_PENDING); expect(actions[1].type).toEqual(MODIFY_GROUP_SUCCESS); + expect(actions[2].type).toEqual(FETCH_GROUP_PENDING); expect(actions[1].payload).toEqual(humanGroup); }); }); it("should call the callback after modifying group", () => { - fetchMock.putOnce("http://localhost:8081/api/v2/groups/humanGroup", { + fetchMock.putOnce(URL_HUMAN_GROUP, { status: 204 }); + fetchMock.getOnce(URL_HUMAN_GROUP, humanGroup); let called = false; const callback = () => { @@ -273,12 +304,13 @@ describe("groups fetch()", () => { const actions = store.getActions(); expect(actions[0].type).toEqual(MODIFY_GROUP_PENDING); expect(actions[1].type).toEqual(MODIFY_GROUP_SUCCESS); + expect(actions[2].type).toEqual(FETCH_GROUP_PENDING); expect(called).toBe(true); }); }); it("should fail modifying group on HTTP 500", () => { - fetchMock.putOnce("http://localhost:8081/api/v2/groups/humanGroup", { + fetchMock.putOnce(URL_HUMAN_GROUP, { status: 500 }); @@ -293,7 +325,7 @@ describe("groups fetch()", () => { }); it("should delete successfully group humanGroup", () => { - fetchMock.deleteOnce("http://localhost:8081/api/v2/groups/humanGroup", { + fetchMock.deleteOnce(URL_HUMAN_GROUP, { status: 204 }); @@ -308,7 +340,7 @@ describe("groups fetch()", () => { }); it("should call the callback, after successful delete", () => { - fetchMock.deleteOnce("http://localhost:8081/api/v2/groups/humanGroup", { + fetchMock.deleteOnce(URL_HUMAN_GROUP, { status: 204 }); @@ -324,7 +356,7 @@ describe("groups fetch()", () => { }); it("should fail to delete group humanGroup", () => { - fetchMock.deleteOnce("http://localhost:8081/api/v2/groups/humanGroup", { + fetchMock.deleteOnce(URL_HUMAN_GROUP, { status: 500 }); diff --git a/scm-ui/src/repos/containers/RepositoryRoot.js b/scm-ui/src/repos/containers/RepositoryRoot.js index e3043b1041..d0c4947af9 100644 --- a/scm-ui/src/repos/containers/RepositoryRoot.js +++ b/scm-ui/src/repos/containers/RepositoryRoot.js @@ -1,19 +1,32 @@ //@flow import React from "react"; -import {deleteRepo, fetchRepo, getFetchRepoFailure, getRepository, isFetchRepoPending} from "../modules/repos"; +import { + deleteRepo, + fetchRepoByName, + getFetchRepoFailure, + getRepository, + isFetchRepoPending +} from "../modules/repos"; -import {connect} from "react-redux"; -import {Route, Switch} from "react-router-dom"; -import type {Repository} from "@scm-manager/ui-types"; +import { connect } from "react-redux"; +import { Route, Switch } from "react-router-dom"; +import type { Repository } from "@scm-manager/ui-types"; -import {ErrorPage, Loading, Navigation, NavLink, Page, Section} from "@scm-manager/ui-components"; -import {translate} from "react-i18next"; +import { + ErrorPage, + Loading, + Navigation, + NavLink, + Page, + Section +} from "@scm-manager/ui-components"; +import { translate } from "react-i18next"; import RepositoryDetails from "../components/RepositoryDetails"; import DeleteNavAction from "../components/DeleteNavAction"; import Edit from "../containers/Edit"; import Permissions from "../permissions/containers/Permissions"; -import type {History} from "history"; +import type { History } from "history"; import EditNavLink from "../components/EditNavLink"; import BranchRoot from "./ChangesetsRoot"; @@ -32,7 +45,7 @@ type Props = { repoLink: string, // dispatch functions - fetchRepo: (link: string, namespace: string, name: string) => void, + fetchRepoByName: (link: string, namespace: string, name: string) => void, deleteRepo: (repository: Repository, () => void) => void, // context props @@ -43,9 +56,9 @@ type Props = { class RepositoryRoot extends React.Component { componentDidMount() { - const { fetchRepo, namespace, name, repoLink } = this.props; + const { fetchRepoByName, namespace, name, repoLink } = this.props; - fetchRepo(repoLink, namespace, name); + fetchRepoByName(repoLink, namespace, name); } stripEndingSlash = (url: string) => { @@ -209,8 +222,8 @@ const mapStateToProps = (state, ownProps) => { const mapDispatchToProps = dispatch => { return { - fetchRepo: (link: string, namespace: string, name: string) => { - dispatch(fetchRepo(link, namespace, name)); + fetchRepoByName: (link: string, namespace: string, name: string) => { + dispatch(fetchRepoByName(link, namespace, name)); }, deleteRepo: (repository: Repository, callback: () => void) => { dispatch(deleteRepo(repository, callback)); diff --git a/scm-ui/src/repos/modules/repos.js b/scm-ui/src/repos/modules/repos.js index b5016bbb43..74550bd881 100644 --- a/scm-ui/src/repos/modules/repos.js +++ b/scm-ui/src/repos/modules/repos.js @@ -99,13 +99,20 @@ export function fetchReposFailure(err: Error): Action { } // fetch repo +export function fetchRepoByLink(repo: Repository) { + return fetchRepo(repo._links.self.href, repo.namespace, repo.name); +} -export function fetchRepo(link: string, namespace: string, name: string) { +export function fetchRepoByName(link: string, namespace: string, name: string) { const repoUrl = link.endsWith("/") ? link : link + "/"; + return fetchRepo(`${repoUrl}${namespace}/${name}`, namespace, name); +} + +function fetchRepo(link: string, namespace: string, name: string) { return function(dispatch: any) { dispatch(fetchRepoPending(namespace, name)); return apiClient - .get(`${repoUrl}${namespace}/${name}`) + .get(link) .then(response => response.json()) .then(repository => { dispatch(fetchRepoSuccess(repository)); @@ -213,6 +220,9 @@ export function modifyRepo(repository: Repository, callback?: () => void) { callback(); } }) + .then(() => { + dispatch(fetchRepoByLink(repository)); + }) .catch(cause => { const error = new Error(`failed to modify repo: ${cause.message}`); dispatch(modifyRepoFailure(repository, error)); @@ -347,8 +357,6 @@ export default function reducer( switch (action.type) { case FETCH_REPOS_SUCCESS: return normalizeByNamespaceAndName(action.payload); - case MODIFY_REPO_SUCCESS: - return reducerByNames(state, action.payload); case FETCH_REPO_SUCCESS: return reducerByNames(state, action.payload); default: diff --git a/scm-ui/src/repos/modules/repos.test.js b/scm-ui/src/repos/modules/repos.test.js index 5b5c2d3abd..e8d9873e99 100644 --- a/scm-ui/src/repos/modules/repos.test.js +++ b/scm-ui/src/repos/modules/repos.test.js @@ -15,7 +15,8 @@ import reducer, { fetchReposByLink, fetchReposByPage, FETCH_REPO, - fetchRepo, + fetchRepoByLink, + fetchRepoByName, FETCH_REPO_PENDING, FETCH_REPO_SUCCESS, FETCH_REPO_FAILURE, @@ -45,7 +46,6 @@ import reducer, { MODIFY_REPO, isModifyRepoPending, getModifyRepoFailure, - modifyRepoSuccess, getPermissionsLink } from "./repos"; import type { Repository, RepositoryCollection } from "@scm-manager/ui-types"; @@ -323,7 +323,7 @@ describe("repos fetch", () => { }); }); - it("should successfully fetch repo slarti/fjords", () => { + it("should successfully fetch repo slarti/fjords by name", () => { fetchMock.getOnce(REPOS_URL + "/slarti/fjords", slartiFjords); const expectedActions = [ @@ -343,18 +343,66 @@ describe("repos fetch", () => { ]; const store = mockStore({}); - return store.dispatch(fetchRepo(URL, "slarti", "fjords")).then(() => { + return store.dispatch(fetchRepoByName(URL, "slarti", "fjords")).then(() => { expect(store.getActions()).toEqual(expectedActions); }); }); - it("should dispatch FETCH_REPO_FAILURE, it the request for slarti/fjords fails", () => { + it("should dispatch FETCH_REPO_FAILURE, if the request for slarti/fjords by name fails", () => { fetchMock.getOnce(REPOS_URL + "/slarti/fjords", { status: 500 }); const store = mockStore({}); - return store.dispatch(fetchRepo(URL, "slarti", "fjords")).then(() => { + return store.dispatch(fetchRepoByName(URL, "slarti", "fjords")).then(() => { + const actions = store.getActions(); + expect(actions[0].type).toEqual(FETCH_REPO_PENDING); + expect(actions[1].type).toEqual(FETCH_REPO_FAILURE); + expect(actions[1].payload.namespace).toBe("slarti"); + expect(actions[1].payload.name).toBe("fjords"); + expect(actions[1].payload.error).toBeDefined(); + expect(actions[1].itemId).toBe("slarti/fjords"); + }); + }); + + it("should successfully fetch repo slarti/fjords", () => { + fetchMock.getOnce( + "http://localhost:8081/api/v2/repositories/slarti/fjords", + slartiFjords + ); + + const expectedActions = [ + { + type: FETCH_REPO_PENDING, + payload: { + namespace: "slarti", + name: "fjords" + }, + itemId: "slarti/fjords" + }, + { + type: FETCH_REPO_SUCCESS, + payload: slartiFjords, + itemId: "slarti/fjords" + } + ]; + + const store = mockStore({}); + return store.dispatch(fetchRepoByLink(slartiFjords)).then(() => { + expect(store.getActions()).toEqual(expectedActions); + }); + }); + + it("should dispatch FETCH_REPO_FAILURE, it the request for slarti/fjords fails", () => { + fetchMock.getOnce( + "http://localhost:8081/api/v2/repositories/slarti/fjords", + { + status: 500 + } + ); + + const store = mockStore({}); + return store.dispatch(fetchRepoByLink(slartiFjords)).then(() => { const actions = store.getActions(); expect(actions[0].type).toEqual(FETCH_REPO_PENDING); expect(actions[1].type).toEqual(FETCH_REPO_FAILURE); @@ -485,6 +533,12 @@ describe("repos fetch", () => { fetchMock.putOnce(slartiFjords._links.update.href, { status: 204 }); + fetchMock.getOnce( + "http://localhost:8081/api/v2/repositories/slarti/fjords", + { + status: 500 + } + ); let editedFjords = { ...slartiFjords }; editedFjords.description = "coast of africa"; @@ -495,6 +549,7 @@ describe("repos fetch", () => { const actions = store.getActions(); expect(actions[0].type).toEqual(MODIFY_REPO_PENDING); expect(actions[1].type).toEqual(MODIFY_REPO_SUCCESS); + expect(actions[2].type).toEqual(FETCH_REPO_PENDING); }); }); @@ -502,6 +557,12 @@ describe("repos fetch", () => { fetchMock.putOnce(slartiFjords._links.update.href, { status: 204 }); + fetchMock.getOnce( + "http://localhost:8081/api/v2/repositories/slarti/fjords", + { + status: 500 + } + ); let editedFjords = { ...slartiFjords }; editedFjords.description = "coast of africa"; @@ -517,6 +578,7 @@ describe("repos fetch", () => { const actions = store.getActions(); expect(actions[0].type).toEqual(MODIFY_REPO_PENDING); expect(actions[1].type).toEqual(MODIFY_REPO_SUCCESS); + expect(actions[2].type).toEqual(FETCH_REPO_PENDING); expect(called).toBe(true); }); }); @@ -574,18 +636,6 @@ describe("repos reducer", () => { const newState = reducer({}, fetchRepoSuccess(slartiFjords)); expect(newState.byNames["slarti/fjords"]).toBe(slartiFjords); }); - - it("should update reposByNames", () => { - const oldState = { - byNames: { - "slarti/fjords": slartiFjords - } - }; - let slartiFjordsEdited = { ...slartiFjords }; - slartiFjordsEdited.description = "I bless the rains down in Africa"; - const newState = reducer(oldState, modifyRepoSuccess(slartiFjordsEdited)); - expect(newState.byNames["slarti/fjords"]).toEqual(slartiFjordsEdited); - }); }); describe("repos selectors", () => { diff --git a/scm-ui/src/users/containers/SingleUser.js b/scm-ui/src/users/containers/SingleUser.js index f581874742..ed5d6df0c3 100644 --- a/scm-ui/src/users/containers/SingleUser.js +++ b/scm-ui/src/users/containers/SingleUser.js @@ -15,7 +15,7 @@ import EditUser from "./EditUser"; import type { User } from "@scm-manager/ui-types"; import type { History } from "history"; import { - fetchUser, + fetchUserByName, deleteUser, getUserByName, isFetchUserPending, @@ -37,7 +37,7 @@ type Props = { // dispatcher functions deleteUser: (user: User, callback?: () => void) => void, - fetchUser: (string, string) => void, + fetchUserByName: (string, string) => void, // context objects t: string => string, @@ -47,7 +47,7 @@ type Props = { class SingleUser extends React.Component { componentDidMount() { - this.props.fetchUser(this.props.usersLink, this.props.name); + this.props.fetchUserByName(this.props.usersLink, this.props.name); } userDeleted = () => { @@ -138,8 +138,8 @@ const mapStateToProps = (state, ownProps) => { const mapDispatchToProps = dispatch => { return { - fetchUser: (link: string, name: string) => { - dispatch(fetchUser(link, name)); + fetchUserByName: (link: string, name: string) => { + dispatch(fetchUserByName(link, name)); }, deleteUser: (user: User, callback?: () => void) => { dispatch(deleteUser(user, callback)); diff --git a/scm-ui/src/users/modules/users.js b/scm-ui/src/users/modules/users.js index 80d8107b3e..5061303720 100644 --- a/scm-ui/src/users/modules/users.js +++ b/scm-ui/src/users/modules/users.js @@ -87,12 +87,20 @@ export function fetchUsersFailure(url: string, error: Error): Action { } //fetch user -export function fetchUser(link: string, name: string) { +export function fetchUserByName(link: string, name: string) { const userUrl = link.endsWith("/") ? link + name : link + "/" + name; + return fetchUser(userUrl, name); +} + +export function fetchUserByLink(user: User) { + return fetchUser(user._links.self.href, user.name); +} + +function fetchUser(link: string, name: string) { return function(dispatch: any) { dispatch(fetchUserPending(name)); return apiClient - .get(userUrl) + .get(link) .then(response => { return response.json(); }) @@ -195,6 +203,9 @@ export function modifyUser(user: User, callback?: () => void) { callback(); } }) + .then(() => { + dispatch(fetchUserByLink(user)); + }) .catch(err => { dispatch(modifyUserFailure(user, err)); }); @@ -365,9 +376,6 @@ function byNamesReducer(state: any = {}, action: any = {}) { case FETCH_USER_SUCCESS: return reducerByName(state, action.payload.name, action.payload); - case MODIFY_USER_SUCCESS: - return reducerByName(state, action.payload.name, action.payload); - case DELETE_USER_SUCCESS: const newUserByNames = deleteUserInUsersByNames( state, diff --git a/scm-ui/src/users/modules/users.test.js b/scm-ui/src/users/modules/users.test.js index 03da4658c2..ac4d1c97a9 100644 --- a/scm-ui/src/users/modules/users.test.js +++ b/scm-ui/src/users/modules/users.test.js @@ -20,7 +20,8 @@ import reducer, { FETCH_USERS_FAILURE, FETCH_USERS_PENDING, FETCH_USERS_SUCCESS, - fetchUser, + fetchUserByLink, + fetchUserByName, fetchUserSuccess, getFetchUserFailure, fetchUsers, @@ -33,7 +34,6 @@ import reducer, { MODIFY_USER_PENDING, MODIFY_USER_SUCCESS, modifyUser, - modifyUserSuccess, getUsersFromState, FETCH_USERS, getFetchUsersFailure, @@ -124,6 +124,7 @@ const response = { const URL = "users"; const USERS_URL = "/api/v2/users"; +const USER_ZAPHOD_URL = "http://localhost:8081/api/v2/users/zaphod"; const error = new Error("KAPUTT"); @@ -166,11 +167,37 @@ describe("users fetch()", () => { }); }); - it("should sucessfully fetch single user", () => { + it("should sucessfully fetch single user by name", () => { fetchMock.getOnce(USERS_URL + "/zaphod", userZaphod); const store = mockStore({}); - return store.dispatch(fetchUser(URL, "zaphod")).then(() => { + return store.dispatch(fetchUserByName(URL, "zaphod")).then(() => { + const actions = store.getActions(); + expect(actions[0].type).toEqual(FETCH_USER_PENDING); + expect(actions[1].type).toEqual(FETCH_USER_SUCCESS); + expect(actions[1].payload).toBeDefined(); + }); + }); + + it("should fail fetching single user by name on HTTP 500", () => { + fetchMock.getOnce(USERS_URL + "/zaphod", { + status: 500 + }); + + const store = mockStore({}); + return store.dispatch(fetchUserByName(URL, "zaphod")).then(() => { + const actions = store.getActions(); + expect(actions[0].type).toEqual(FETCH_USER_PENDING); + expect(actions[1].type).toEqual(FETCH_USER_FAILURE); + expect(actions[1].payload).toBeDefined(); + }); + }); + + it("should sucessfully fetch single user", () => { + fetchMock.getOnce(USER_ZAPHOD_URL, userZaphod); + + const store = mockStore({}); + return store.dispatch(fetchUserByLink(userZaphod)).then(() => { const actions = store.getActions(); expect(actions[0].type).toEqual(FETCH_USER_PENDING); expect(actions[1].type).toEqual(FETCH_USER_SUCCESS); @@ -179,12 +206,12 @@ describe("users fetch()", () => { }); it("should fail fetching single user on HTTP 500", () => { - fetchMock.getOnce(USERS_URL + "/zaphod", { + fetchMock.getOnce(USER_ZAPHOD_URL, { status: 500 }); const store = mockStore({}); - return store.dispatch(fetchUser(URL, "zaphod")).then(() => { + return store.dispatch(fetchUserByLink(userZaphod)).then(() => { const actions = store.getActions(); expect(actions[0].type).toEqual(FETCH_USER_PENDING); expect(actions[1].type).toEqual(FETCH_USER_FAILURE); @@ -242,23 +269,26 @@ describe("users fetch()", () => { }); it("successfully update user", () => { - fetchMock.putOnce("http://localhost:8081/api/v2/users/zaphod", { + fetchMock.putOnce(USER_ZAPHOD_URL, { status: 204 }); + fetchMock.getOnce(USER_ZAPHOD_URL, userZaphod); const store = mockStore({}); return store.dispatch(modifyUser(userZaphod)).then(() => { const actions = store.getActions(); - expect(actions.length).toBe(2); + expect(actions.length).toBe(3); expect(actions[0].type).toEqual(MODIFY_USER_PENDING); expect(actions[1].type).toEqual(MODIFY_USER_SUCCESS); + expect(actions[2].type).toEqual(FETCH_USER_PENDING); }); }); it("should call callback, after successful modified user", () => { - fetchMock.putOnce("http://localhost:8081/api/v2/users/zaphod", { + fetchMock.putOnce(USER_ZAPHOD_URL, { status: 204 }); + fetchMock.getOnce(USER_ZAPHOD_URL, userZaphod); let called = false; const callMe = () => { @@ -415,20 +445,6 @@ describe("users reducer", () => { expect(newState.byNames["ford"]).toBe(userFord); expect(newState.list.entries).toEqual(["zaphod"]); }); - - it("should update state according to MODIFY_USER_SUCCESS action", () => { - const newState = reducer( - { - byNames: { - ford: { - name: "ford" - } - } - }, - modifyUserSuccess(userFord) - ); - expect(newState.byNames["ford"]).toBe(userFord); - }); }); describe("selector tests", () => {