create permissions store and write selectors

This commit is contained in:
Maren Süwer
2018-08-23 10:16:54 +02:00
parent b84472b11c
commit f81cc096aa
5 changed files with 178 additions and 30 deletions

View File

@@ -11,6 +11,7 @@ import groups from "./groups/modules/groups";
import auth from "./modules/auth";
import pending from "./modules/pending";
import failure from "./modules/failure";
import permissions from "./permissions/modules/permissions";
import type { BrowserHistory } from "history/createBrowserHistory";
@@ -25,6 +26,7 @@ function createReduxStore(history: BrowserHistory) {
users,
repos,
repositoryTypes,
permissions,
groups,
auth
});

View File

@@ -1,13 +1,46 @@
//@flow
import React from "react";
import type { History } from "history";
import connect from "react-redux/es/connect/connect";
import { translate } from "react-i18next";
import { fetchPermissions } from "../modules/permissions";
type Props = {};
type Props = {
namespace: string,
name: string,
//dispatch functions
fetchPermissions: (namespace: string, name: string) => void
};
class Permissions extends React.Component<Props> {
componentDidMount() {
const { fetchPermissions, namespace, name } = this.props;
fetchPermissions(namespace, name);
}
render() {
return <div>Permissions will be shown here!</div>;
}
}
export default Permissions;
const mapStateToProps = (state, ownProps) => {
// const { namespace, name } = ownProps.match.params;
return {
//namespace,
//name
};
};
const mapDispatchToProps = dispatch => {
return {
fetchPermissions: (namespace: string, name: string) => {
dispatch(fetchPermissions(namespace, name));
}
};
};
export default connect(
mapStateToProps,
mapDispatchToProps
)(translate("repos")(Permissions));

View File

@@ -2,7 +2,9 @@
import { apiClient } from "../../apiclient";
import * as types from "../../modules/types";
import type { Action } from "../../types/Action";
import type { Permission, Permissions } from "../types/Permissions";
import type { Permissions } from "../types/Permissions";
import { isPending } from "../../modules/pending";
import { getFailure } from "../../modules/failure";
export const FETCH_PERMISSIONS = "scm/repos/FETCH_PERMISSIONS";
export const FETCH_PERMISSIONS_PENDING = `${FETCH_PERMISSIONS}_${
@@ -88,8 +90,32 @@ export default function reducer(
switch (action.type) {
case FETCH_PERMISSIONS_SUCCESS:
return state;
return {
...state,
[action.itemId]: action.payload
};
default:
return state;
}
}
// selectors
export function getPermissionsOfRepo(
state: Object,
namespace: string,
name: string
) {
if (state.permissions && state.permissions[namespace + "/" + name]) {
const permissions = state.permissions[namespace + "/" + name];
return permissions;
}
}
export function isFetchPermissionsPending(state: Object) {
return isPending(state, FETCH_PERMISSIONS);
}
export function getFetchPermissionsFailure(state: Object) {
return getFailure(state, FETCH_PERMISSIONS);
}

View File

@@ -5,33 +5,60 @@ import fetchMock from "fetch-mock";
import reducer, {
fetchPermissions,
fetchPermissionsSuccess,
getPermissionsOfRepo,
isFetchPermissionsPending,
getFetchPermissionsFailure,
FETCH_PERMISSIONS,
FETCH_PERMISSIONS_PENDING,
FETCH_PERMISSIONS_SUCCESS,
FETCH_PERMISSIONS_FAILURE
} from "./permissions";
import type { Permission, Permissions } from "../types/Permissions";
const s_bPermission_user_eins: Permission = {
const hitchhiker_puzzle42Permission_user_eins: Permission = {
name: "user_eins",
type: "READ",
groupPermission: true,
_links: {
self: {
href:
"http://localhost:8081/scm/api/rest/v2/repositories/s/b/permissions/user_eins"
"http://localhost:8081/scm/api/rest/v2/repositories/hitchhiker/puzzle42/permissions/user_eins"
},
delete: {
href:
"http://localhost:8081/scm/api/rest/v2/repositories/s/b/permissions/user_eins"
"http://localhost:8081/scm/api/rest/v2/repositories/hitchhiker/puzzle42/permissions/user_eins"
},
update: {
href:
"http://localhost:8081/scm/api/rest/v2/repositories/s/b/permissions/user_eins"
"http://localhost:8081/scm/api/rest/v2/repositories/hitchhiker/puzzle42/permissions/user_eins"
}
}
};
const s_bPermissions: Permissions = [s_bPermission_user_eins];
const hitchhiker_puzzle42Permission_user_zwei: Permission = {
name: "user_zwei",
type: "WRITE",
groupPermission: true,
_links: {
self: {
href:
"http://localhost:8081/scm/api/rest/v2/repositories/hitchhiker/puzzle42/permissions/user_zwei"
},
delete: {
href:
"http://localhost:8081/scm/api/rest/v2/repositories/hitchhiker/puzzle42/permissions/user_zwei"
},
update: {
href:
"http://localhost:8081/scm/api/rest/v2/repositories/hitchhiker/puzzle42/permissions/user_zwei"
}
}
};
const hitchhiker_puzzle42Permissions: Permissions = [
hitchhiker_puzzle42Permission_user_eins,
hitchhiker_puzzle42Permission_user_zwei
];
describe("permission fetch", () => {
const REPOS_URL = "/scm/api/rest/v2/repositories";
@@ -42,47 +69,54 @@ describe("permission fetch", () => {
fetchMock.restore();
});
it("should successfully fetch permissions to repo s/b", () => {
fetchMock.getOnce(REPOS_URL + "/s/b/permissions", s_bPermissions);
it("should successfully fetch permissions to repo hitchhiker/puzzle42", () => {
fetchMock.getOnce(
REPOS_URL + "/hitchhiker/puzzle42/permissions",
hitchhiker_puzzle42Permissions
);
const expectedActions = [
{
type: FETCH_PERMISSIONS_PENDING,
payload: {
namespace: "s",
name: "b"
namespace: "hitchhiker",
name: "puzzle42"
},
itemId: "s/b"
itemId: "hitchhiker/puzzle42"
},
{
type: FETCH_PERMISSIONS_SUCCESS,
payload: s_bPermissions,
itemId: "s/b"
payload: hitchhiker_puzzle42Permissions,
itemId: "hitchhiker/puzzle42"
}
];
const store = mockStore({});
return store.dispatch(fetchPermissions("s", "b")).then(() => {
expect(store.getActions()).toEqual(expectedActions);
});
return store
.dispatch(fetchPermissions("hitchhiker", "puzzle42"))
.then(() => {
expect(store.getActions()).toEqual(expectedActions);
});
});
it("should dispatch FETCH_PERMISSIONS_FAILURE, it the request fails", () => {
fetchMock.getOnce(REPOS_URL + "/s/b/permissions", {
fetchMock.getOnce(REPOS_URL + "/hitchhiker/puzzle42/permissions", {
status: 500
});
const store = mockStore({});
return store.dispatch(fetchPermissions("s", "b")).then(() => {
const actions = store.getActions();
expect(actions[0].type).toEqual(FETCH_PERMISSIONS_PENDING);
expect(actions[1].type).toEqual(FETCH_PERMISSIONS_FAILURE);
expect(actions[1].payload).toBeDefined();
});
return store
.dispatch(fetchPermissions("hitchhiker", "puzzle42"))
.then(() => {
const actions = store.getActions();
expect(actions[0].type).toEqual(FETCH_PERMISSIONS_PENDING);
expect(actions[1].type).toEqual(FETCH_PERMISSIONS_FAILURE);
expect(actions[1].payload).toBeDefined();
});
});
});
describe("repos reducer", () => {
describe("permissions reducer", () => {
it("should return empty object, if state and action is undefined", () => {
expect(reducer()).toEqual({});
});
@@ -100,7 +134,60 @@ describe("repos reducer", () => {
it("should store the permissions on FETCH_PERMISSION_SUCCESS", () => {
const newState = reducer(
{},
fetchPermissionsSuccess(s_bPermissions, "s", "b")
fetchPermissionsSuccess(
hitchhiker_puzzle42Permissions,
"hitchhiker",
"puzzle42"
)
);
expect(newState["hitchhiker/puzzle42"]).toBe(
hitchhiker_puzzle42Permissions
);
});
});
describe("permissions selectors", () => {
const error = new Error("something goes wrong");
it("should return the permissions of one repository", () => {
const state = {
permissions: {
"hitchhiker/puzzle42": hitchhiker_puzzle42Permissions
}
};
const repoPermissions = getPermissionsOfRepo(
state,
"hitchhiker",
"puzzle42"
);
expect(repoPermissions).toEqual(hitchhiker_puzzle42Permissions);
});
it("should return true, when fetch permissions is pending", () => {
const state = {
pending: {
[FETCH_PERMISSIONS]: true
}
};
expect(isFetchPermissionsPending(state)).toEqual(true);
});
it("should return false, when fetch permissions is not pending", () => {
expect(isFetchPermissionsPending({})).toEqual(false);
});
it("should return error when fetch permissions did fail", () => {
const state = {
failure: {
[FETCH_PERMISSIONS]: error
}
};
expect(getFetchPermissionsFailure(state)).toEqual(error);
});
it("should return undefined when fetch permissions did not fail", () => {
expect(getFetchPermissionsFailure({})).toBe(undefined);
});
});

View File

@@ -101,7 +101,7 @@ class RepositoryRoot extends React.Component<Props> {
/>
<Route
path={`${url}/permissions`}
component={() => <Permissions />}
component={() => <Permissions namespace={repository.namespace} name={repository.name} />}
/>
</div>
<div className="column">