diff --git a/scm-ui/src/changesets/modules/changesets.js b/scm-ui/src/changesets/modules/changesets.js new file mode 100644 index 0000000000..639a4ff1db --- /dev/null +++ b/scm-ui/src/changesets/modules/changesets.js @@ -0,0 +1,71 @@ +// @flow + +import {FAILURE_SUFFIX, PENDING_SUFFIX, SUCCESS_SUFFIX} from "../../modules/types"; +import { apiClient } from "@scm-manager/ui-components"; + +export const FETCH_CHANGESETS = "scm/repos/FETCH_CHANGESETS"; +export const FETCH_CHANGESETS_PENDING = `${FETCH_CHANGESETS}_${PENDING_SUFFIX}`; +export const FETCH_CHANGESETS_SUCCESS = `${FETCH_CHANGESETS}_${SUCCESS_SUFFIX}`; +export const FETCH_CHANGESETS_FAILURE = `${FETCH_CHANGESETS}_${FAILURE_SUFFIX}`; + +const REPO_URL = "repositories"; + +export function fetchChangesets(namespace: string, name: string) { + return fetchChangesetsByLink(REPO_URL + "/" + namespace + "/" + name + "/changesets"); +} + +export function fetchChangesetsByLink(link: string) { + return function(dispatch: any) { + dispatch(fetchChangesetsPending()); + return apiClient.get(link).then(response => response.json()) + .then(data => { + dispatch(fetchChangesetsSuccess(data)) + }).catch(cause => { + dispatch(fetchChangesetsFailure(link, cause)) + }) + } +} + +export function fetchChangesetsPending(): Action { + return { + type: FETCH_CHANGESETS_PENDING + } +} + +export function fetchChangesetsSuccess(data: any): Action { + return { + type: FETCH_CHANGESETS_SUCCESS, + payload: data + } +} + +function fetchChangesetsFailure(url: string, error: Error): Action { + return { + type: FETCH_CHANGESETS_FAILURE, + payload: { + url, + error + } + } +} + + +export default function reducer(state: any = {}, action: any = {}) { + switch (action.type) { + case FETCH_CHANGESETS_SUCCESS: + + return {byIds: extractChangesetsByIds(action.payload)}; + default: + return state; + } +} + +function extractChangesetsByIds(data: any) { + const changesets = data._embedded.changesets; + const changesetsByIds = {}; + for (let changeset of changesets) { + changesetsByIds[changeset.id] = changeset; + } + + return changesetsByIds; +} diff --git a/scm-ui/src/changesets/modules/changesets.test.js b/scm-ui/src/changesets/modules/changesets.test.js new file mode 100644 index 0000000000..aaeb75451e --- /dev/null +++ b/scm-ui/src/changesets/modules/changesets.test.js @@ -0,0 +1,66 @@ +// @flow + + +import configureMockStore from "redux-mock-store"; +import thunk from "redux-thunk"; +import fetchMock from "fetch-mock"; +import { + FETCH_CHANGESETS_PENDING, + FETCH_CHANGESETS_SUCCESS, + fetchChangesets, + fetchChangesetsSuccess +} from "./changesets"; +import reducer from "./changesets"; + +const collection = {}; + +describe("fetching of changesets", () => { + const URL = "/api/rest/v2/repositories/foo/bar/changesets"; + const mockStore = configureMockStore([thunk]); + + afterEach(() => { + fetchMock.reset(); + fetchMock.restore(); + }); + + it("should fetch changesets", () => { + fetchMock.getOnce(URL, "{}"); + + const expectedActions = [ + { type: FETCH_CHANGESETS_PENDING }, + { + type: FETCH_CHANGESETS_SUCCESS, + payload: collection + } + ]; + + const store = mockStore({}); + return store.dispatch(fetchChangesets("foo", "bar")).then(() => { + expect(store.getActions()).toEqual(expectedActions); + }); + }) +}); + +describe("changesets reducer", () => { + const responseBody = { + _embedded: { + changesets: [ + {id: "changeset1", author: { mail: "z@phod.com", name: "zaphod"}}, + {id: "changeset2"}, + {id: "changeset3"}, + ], + _embedded: { + tags: [], + branches: [], + parents: [] + } + } + }; + it("should set state correctly", () => { + const newState = reducer({}, fetchChangesetsSuccess(responseBody)); + expect(newState.byIds["changeset1"]).toBeDefined(); + expect(newState.byIds["changeset1"].author.mail).toEqual("z@phod.com"); + expect(newState.byIds["changeset2"]).toBeDefined(); + expect(newState.byIds["changeset3"]).toBeDefined(); + }) +}); diff --git a/scm-ui/src/createReduxStore.js b/scm-ui/src/createReduxStore.js index 8411326b53..a63a6edcdb 100644 --- a/scm-ui/src/createReduxStore.js +++ b/scm-ui/src/createReduxStore.js @@ -7,6 +7,7 @@ import { routerReducer, routerMiddleware } from "react-router-redux"; import users from "./users/modules/users"; import repos from "./repos/modules/repos"; import repositoryTypes from "./repos/modules/repositoryTypes"; +import changesets from "./changesets/modules/changesets"; import groups from "./groups/modules/groups"; import auth from "./modules/auth"; import pending from "./modules/pending"; @@ -26,6 +27,7 @@ function createReduxStore(history: BrowserHistory) { users, repos, repositoryTypes, + changesets, groups, auth, config diff --git a/scm-ui/src/repos/modules/repos.test.js b/scm-ui/src/repos/modules/repos.test.js index ae85d6cb17..d537f4bdc0 100644 --- a/scm-ui/src/repos/modules/repos.test.js +++ b/scm-ui/src/repos/modules/repos.test.js @@ -405,7 +405,7 @@ describe("repos fetch", () => { }); }); - it("should disapatch failure if server returns status code 500", () => { + it("should dispatch failure if server returns status code 500", () => { fetchMock.postOnce(REPOS_URL, { status: 500 });