add reducer, selector and actions for getting one changeset

This commit is contained in:
Maren Süwer
2018-09-20 12:03:49 +02:00
parent 33fc15b99c
commit a1838c1ec8
2 changed files with 420 additions and 25 deletions

View File

@@ -16,51 +16,47 @@ 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}`;
//added for detailed view of changesets
//********added for detailed view of changesets
export const FETCH_CHANGESET = "scm/repos/FETCH_CHANGESET";
export const FETCH_CHANGESET_PENDING = `${FETCH_CHANGESET}_${PENDING_SUFFIX}`;
export const FETCH_CHANGESET_SUCCESS = `${FETCH_CHANGESET}_${SUCCESS_SUFFIX}`;
export const FETCH_CHANGESET_FAILURE = `${FETCH_CHANGESET}_${FAILURE_SUFFIX}`;
// end of detailed view add
//********end of detailed view add
// actions
const REPO_URL = "repositories";
//TODO: Content type
//added for detailed view of changesets
//********added for detailed view of changesets
function fetchChangesetIfNeeded(
export function fetchChangesetIfNeeded(
state: Object,
namespace: string,
repoName: string,
id: string
) {
return function(dispatch) {
return function(dispatch: any) {
if (shouldFetchChangeset(state, namespace, repoName, id)) {
dispatch(fetchChangeset(url));
return dispatch(fetchChangeset(namespace, repoName, id));
}
};
}
export function shouldFetchChangeset(
state: Object,
export function fetchChangeset(
namespace: string,
repoName: string,
id: string
) {
// decide if changeset should be fetched here
return true;
}
function fetchChangeset(namespace: string, repoName: string, id: string) {
return function(dispatch) {
return function(dispatch: any) {
dispatch(fetchChangesetPending(namespace, repoName, id));
return apiClient
.get(url)
.get(REPO_URL + `/${namespace}/${repoName}/changesets/${id}`)
.then(response => response.json())
.then(json => dispatch(fetchChangesetSuccess(namespace, repoName, id)))
.then(data =>
dispatch(fetchChangesetSuccess(data, namespace, repoName, id))
)
.catch(err => {
dispatch(fetchChangesetFailure(namespace, repoName, id, err));
});
@@ -79,25 +75,26 @@ export function fetchChangesetPending(
repoName,
id
},
itemId: createItemId(namespace, repoName) + "/" + id
itemId: createItemId(namespace, repoName, id)
};
}
export function fetchChangesetSuccess(
changeset: any,
namespace: string,
repoName: string,
id: string
): Action {
return {
type: FETCH_CHANGESET_SUCCESS,
payload: { namespace, repoName, id },
itemId: createItemId(namespace, repoName) + "/" + id
payload: { changeset, namespace, repoName, id },
itemId: createItemId(namespace, repoName, id)
};
}
function fetchChangesetFailure(
namespace: string,
name: string,
repoName: string,
id: string,
error: Error
): Action {
@@ -105,15 +102,14 @@ function fetchChangesetFailure(
type: FETCH_CHANGESET_FAILURE,
payload: {
namespace,
name,
repoName,
id,
error
},
itemId: createItemId(namespace, repoName) + "/" + id
itemId: createItemId(namespace, repoName, id)
};
}
// end of detailed view add
//********end of detailed view add
export function fetchChangesetsWithOptions(
namespace: string,
@@ -234,6 +230,26 @@ function byKeyReducer(
action: Action = { type: "UNKNOWN" }
): Object {
switch (action.type) {
//********added for detailed view of changesets
case FETCH_CHANGESET_SUCCESS:
const _key = createItemId(
action.payload.namespace,
action.payload.repoName
);
let _oldChangesets = { [_key]: {} };
if (state[_key] !== undefined) {
_oldChangesets[_key] = state[_key];
}
return {
...state,
[_key]: {
byId: addChangesetToChangesets(
action.payload.changeset,
_oldChangesets[_key].byId
)
}
};
//********end of added for detailed view of changesets
case FETCH_CHANGESETS_SUCCESS:
const key = action.itemId;
let oldChangesets = { [key]: {} };
@@ -256,6 +272,18 @@ function listReducer(
action: Action = { type: "UNKNOWN" }
): Object {
switch (action.type) {
//********added for detailed view of changesets
case FETCH_CHANGESET_SUCCESS:
const changesetId = action.payload.changeset.id;
const stateEntries = state.entries;
stateEntries.push(changesetId);
return {
entries: stateEntries,
entry: {
...state.entry
}
};
//********end of added for detailed view of changesets
case FETCH_CHANGESETS_SUCCESS:
const changesets = action.payload._embedded.changesets;
const changesetIds = changesets.map(c => c.id);
@@ -291,6 +319,21 @@ function extractChangesetsByIds(data: any, oldChangesetsByIds: any) {
return changesetsByIds;
}
//********added for detailed view of changesets
function addChangesetToChangesets(data: any, oldChangesetsByIds: any) {
const changeset = data;
const changesetsByIds = {};
changesetsByIds[changeset.id] = changeset;
for (let id in oldChangesetsByIds) {
changesetsByIds[id] = oldChangesetsByIds[id];
}
return changesetsByIds;
}
//********end of added for detailed view of changesets
//selectors
export function getChangesets(
@@ -306,6 +349,53 @@ export function getChangesets(
return Object.values(state.changesets.byKey[key].byId);
}
//********added for detailed view of changesets
export function getChangeset(
state: Object,
namespace: string,
name: string,
id: string,
branch?: string
) {
const key = createItemId(namespace, name, branch);
const changesets = state.changesets.byKey[key].byId;
if (changesets != null && changesets[id]) {
return changesets[id];
}
return null;
}
export function shouldFetchChangeset(
state: Object,
namespace: string,
repoName: string,
id: string
) {
if (getChangeset(state, namespace, repoName, id)) {
return false;
}
return true;
}
export function isFetchChangesetPending(
state: Object,
namespace: string,
name: string,
id: string
) {
return isPending(state, FETCH_CHANGESET, createItemId(namespace, name, id));
}
export function getFetchChangesetFailure(
state: Object,
namespace: string,
name: string,
id: string
) {
return getFailure(state, FETCH_CHANGESET, createItemId(namespace, name, id));
}
//********end of added for detailed view of changesets
export function isFetchChangesetsPending(
state: Object,
namespace: string,

View File

@@ -8,6 +8,10 @@ import {
FETCH_CHANGESETS_FAILURE,
FETCH_CHANGESETS_PENDING,
FETCH_CHANGESETS_SUCCESS,
FETCH_CHANGESET,
FETCH_CHANGESET_FAILURE,
FETCH_CHANGESET_PENDING,
FETCH_CHANGESET_SUCCESS,
fetchChangesets,
fetchChangesetsByBranchAndPage,
fetchChangesetsByNamespaceNameAndBranch,
@@ -15,7 +19,14 @@ import {
fetchChangesetsSuccess,
getChangesets,
getFetchChangesetsFailure,
isFetchChangesetsPending
isFetchChangesetsPending,
fetchChangeset,
getChangeset,
fetchChangesetIfNeeded,
shouldFetchChangeset,
isFetchChangesetPending,
getFetchChangesetFailure,
fetchChangesetSuccess
} from "./changesets";
import reducer from "./changesets";
@@ -33,6 +44,139 @@ describe("changesets", () => {
fetchMock.restore();
});
//********added for detailed view of changesets
const changesetId = "aba876c0625d90a6aff1494f3d161aaa7008b958";
it("should fetch changeset", () => {
fetchMock.getOnce(DEFAULT_BRANCH_URL + "/" + changesetId, "{}");
const expectedActions = [
{
type: FETCH_CHANGESET_PENDING,
payload: {
id: changesetId,
namespace: "foo",
repoName: "bar"
},
itemId: "foo/bar/" + changesetId
},
{
type: FETCH_CHANGESET_SUCCESS,
payload: {
changeset: {},
id: changesetId,
namespace: "foo",
repoName: "bar"
},
itemId: "foo/bar/" + changesetId
}
];
const store = mockStore({});
return store
.dispatch(fetchChangeset("foo", "bar", changesetId))
.then(() => {
expect(store.getActions()).toEqual(expectedActions);
});
});
it("should fail fetching changeset on error", () => {
fetchMock.getOnce(DEFAULT_BRANCH_URL + "/" + changesetId, 500);
const expectedActions = [
{
type: FETCH_CHANGESET_PENDING,
payload: {
id: changesetId,
namespace: "foo",
repoName: "bar"
},
itemId: "foo/bar/" + changesetId
}
];
const store = mockStore({});
return store
.dispatch(fetchChangeset("foo", "bar", changesetId))
.then(() => {
expect(store.getActions()[0]).toEqual(expectedActions[0]);
expect(store.getActions()[1].type).toEqual(FETCH_CHANGESET_FAILURE);
expect(store.getActions()[1].payload).toBeDefined();
});
});
it("should fetch changeset if needed", () => {
fetchMock.getOnce(DEFAULT_BRANCH_URL + "/" + "id3", "{}");
const state = {
changesets: {
byKey: {
"foo/bar": {
byId: {
id1: { id: "id1" },
id2: { id: "id2" }
}
}
}
}
};
const expectedActions = [
{
type: FETCH_CHANGESET_PENDING,
payload: {
id: "id3",
namespace: "foo",
repoName: "bar"
},
itemId: "foo/bar/" + "id3"
},
{
type: FETCH_CHANGESET_SUCCESS,
payload: {
changeset: {},
id: "id3",
namespace: "foo",
repoName: "bar"
},
itemId: "foo/bar/" + "id3"
}
];
const store = mockStore({});
return store
.dispatch(fetchChangesetIfNeeded(state, "foo", "bar", "id3"))
.then(() => {
expect(store.getActions()).toEqual(expectedActions);
});
});
it("should not fetch changeset if not needed", () => {
fetchMock.getOnce(DEFAULT_BRANCH_URL + "/" + "id1", 500);
const state = {
changesets: {
byKey: {
"foo/bar": {
byId: {
id1: { id: "id1" },
id2: { id: "id2" }
}
}
}
}
};
const expectedActions = [];
const store = mockStore({});
return expect(
store.dispatch(fetchChangesetIfNeeded(state, "foo", "bar", "id1"))
).toEqual(undefined);
});
//********end of added for detailed view of changesets
it("should fetch changesets for default branch", () => {
fetchMock.getOnce(DEFAULT_BRANCH_URL, "{}");
@@ -248,11 +392,172 @@ describe("changesets", () => {
expect(newState.byKey["foo/bar"].byId["changeset2"]).toBeDefined();
expect(newState.byKey["foo/bar"].byId["changeset1"]).toBeDefined();
});
//********added for detailed view of changesets
const responseBodySingleChangeset = {
id: "id3",
author: {
mail: "z@phod.com",
name: "zaphod"
},
date: "2018-09-13T08:46:22Z",
description: "added testChangeset",
_links: {},
_embedded: {
tags: [],
branches: []
}
};
it("should add changeset to state", () => {
const newState = reducer(
{
byKey: {
"foo/bar": {
byId: {
["id2"]: {
id: "id2",
author: { mail: "mail@author.com", name: "author" }
}
}
}
},
list: {
entry: {
page: 1,
pageTotal: 10,
_links: {}
},
entries: ["id2"]
}
},
fetchChangesetSuccess(responseBodySingleChangeset, "foo", "bar", "id3")
);
expect(newState).toBeDefined();
expect(newState.byKey["foo/bar"].byId["id3"].description).toEqual(
"added testChangeset"
);
expect(newState.byKey["foo/bar"].byId["id3"].author.mail).toEqual(
"z@phod.com"
);
expect(newState.byKey["foo/bar"].byId["id2"]).toBeDefined();
expect(newState.byKey["foo/bar"].byId["id3"]).toBeDefined();
expect(newState.list).toEqual({
entry: {
page: 1,
pageTotal: 10,
_links: {}
},
entries: ["id2", "id3"]
});
});
//********end of added for detailed view of changesets
});
describe("changeset selectors", () => {
const error = new Error("Something went wrong");
//********added for detailed view of changesets
it("should return changeset", () => {
const state = {
changesets: {
byKey: {
"foo/bar": {
byId: {
id1: { id: "id1" },
id2: { id: "id2" }
}
}
}
}
};
const result = getChangeset(state, "foo", "bar", "id1");
expect(result).toEqual({ id: "id1" });
});
it("should return null if changeset does not exist", () => {
const state = {
changesets: {
byKey: {
"foo/bar": {
byId: {
id1: { id: "id1" },
id2: { id: "id2" }
}
}
}
}
};
const result = getChangeset(state, "foo", "bar", "id3");
expect(result).toEqual(null);
});
it("should return true if changeset does not exist", () => {
const state = {
changesets: {
byKey: {
"foo/bar": {
byId: {
id1: { id: "id1" },
id2: { id: "id2" }
}
}
}
}
};
const result = shouldFetchChangeset(state, "foo", "bar", "id3");
expect(result).toEqual(true);
});
it("should return false if changeset exists", () => {
const state = {
changesets: {
byKey: {
"foo/bar": {
byId: {
id1: { id: "id1" },
id2: { id: "id2" }
}
}
}
}
};
const result = shouldFetchChangeset(state, "foo", "bar", "id2");
expect(result).toEqual(false);
});
it("should return true, when fetching changeset is pending", () => {
const state = {
pending: {
[FETCH_CHANGESET + "/foo/bar/id1"]: true
}
};
expect(isFetchChangesetPending(state, "foo", "bar", "id1")).toBeTruthy();
});
it("should return false, when fetching changeset is not pending", () => {
expect(isFetchChangesetPending({}, "foo", "bar", "id1")).toEqual(false);
});
it("should return error if fetching changeset failed", () => {
const state = {
failure: {
[FETCH_CHANGESET + "/foo/bar/id1"]: error
}
};
expect(getFetchChangesetFailure(state, "foo", "bar", "id1")).toEqual(
error
);
});
it("should return false if fetching changeset did not fail", () => {
expect(getFetchChangesetFailure({}, "foo", "bar", "id1")).toBeUndefined();
});
//********end of added for detailed view of changesets
it("should get all changesets for a given namespace and name", () => {
const state = {
changesets: {