mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-13 17:05:43 +01:00
merge and add single group view
This commit is contained in:
@@ -1,12 +1,24 @@
|
|||||||
{
|
{
|
||||||
"group": {
|
"group": {
|
||||||
"name": "Name",
|
"name": "Name",
|
||||||
"description": "Description"
|
"description": "Description",
|
||||||
|
"creationDate": "Creation Date",
|
||||||
|
"lastModified": "Last Modified",
|
||||||
|
"type": "Type",
|
||||||
|
"members": "Members"
|
||||||
},
|
},
|
||||||
"groups": {
|
"groups": {
|
||||||
"title": "Groups",
|
"title": "Groups",
|
||||||
"subtitle": "Create, read, update and delete groups"
|
"subtitle": "Create, read, update and delete groups"
|
||||||
},
|
},
|
||||||
|
"single-group": {
|
||||||
|
"error-title": "Error",
|
||||||
|
"error-subtitle": "Unknown group error",
|
||||||
|
"navigation-label": "Navigation",
|
||||||
|
"actions-label": "Actions",
|
||||||
|
"information-label": "Information",
|
||||||
|
"back-label": "Back"
|
||||||
|
},
|
||||||
"add-group": {
|
"add-group": {
|
||||||
"title": "Create Group",
|
"title": "Create Group",
|
||||||
"subtitle": "Create a new group"
|
"subtitle": "Create a new group"
|
||||||
|
|||||||
@@ -14,7 +14,8 @@ import AddUser from "../users/containers/AddUser";
|
|||||||
import SingleUser from "../users/containers/SingleUser";
|
import SingleUser from "../users/containers/SingleUser";
|
||||||
|
|
||||||
import Groups from "../groups/containers/Groups";
|
import Groups from "../groups/containers/Groups";
|
||||||
import AddGroup from "../groups/containers/AddGroup"
|
import SingleGroup from "../groups/containers/SingleGroup";
|
||||||
|
import AddGroup from "../groups/containers/AddGroup";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
authenticated?: boolean
|
authenticated?: boolean
|
||||||
@@ -62,6 +63,11 @@ class Main extends React.Component<Props> {
|
|||||||
component={Groups}
|
component={Groups}
|
||||||
authenticated={authenticated}
|
authenticated={authenticated}
|
||||||
/>
|
/>
|
||||||
|
<ProtectedRoute
|
||||||
|
authenticated={authenticated}
|
||||||
|
path="/group/:name"
|
||||||
|
component={SingleGroup}
|
||||||
|
/>
|
||||||
<ProtectedRoute
|
<ProtectedRoute
|
||||||
authenticated={authenticated}
|
authenticated={authenticated}
|
||||||
path="/groups/add"
|
path="/groups/add"
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import type { Group } from "../../types/Group";
|
import type { Group } from "../../types/Group";
|
||||||
import { translate } from "react-i18next";
|
import { translate } from "react-i18next";
|
||||||
|
import GroupMember from "./GroupMember";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
group: Group,
|
group: Group,
|
||||||
@@ -9,6 +10,7 @@ type Props = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
class Details extends React.Component<Props> {
|
class Details extends React.Component<Props> {
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { group, t } = this.props;
|
const { group, t } = this.props;
|
||||||
return (
|
return (
|
||||||
@@ -22,6 +24,28 @@ class Details extends React.Component<Props> {
|
|||||||
<td>{t("group.description")}</td>
|
<td>{t("group.description")}</td>
|
||||||
<td>{group.description}</td>
|
<td>{group.description}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>{t("group.creationDate")}</td>
|
||||||
|
<td>{group.creationDate}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>{t("group.lastModified")}</td>
|
||||||
|
<td>{group.lastModified}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>{t("group.type")}</td>
|
||||||
|
<td>{group.type}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>{t("group.members")}</td>
|
||||||
|
<td>
|
||||||
|
<table><tbody>
|
||||||
|
{group.members.map((member, index) => {
|
||||||
|
return <GroupMember key={index} member={member} />;
|
||||||
|
})}
|
||||||
|
</tbody></table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
);
|
);
|
||||||
|
|||||||
26
scm-ui/src/groups/components/table/GroupMember.js
Normal file
26
scm-ui/src/groups/components/table/GroupMember.js
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
// @flow
|
||||||
|
import React from "react";
|
||||||
|
import { Link } from "react-router-dom";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
member: string
|
||||||
|
};
|
||||||
|
|
||||||
|
export default class GroupMember extends React.Component<Props> {
|
||||||
|
renderLink(to: string, label: string) {
|
||||||
|
return <Link to={to}>{label}</Link>;
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { member } = this.props;
|
||||||
|
const to = `/user/${member}`;
|
||||||
|
return (
|
||||||
|
<tr className="is-hidden-mobile">
|
||||||
|
<td>
|
||||||
|
{this.renderLink(to, member)}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -18,7 +18,7 @@ export default class GroupRow extends React.Component<Props> {
|
|||||||
return (
|
return (
|
||||||
<tr>
|
<tr>
|
||||||
<td className="is-hidden-mobile">{this.renderLink(to, group.name)}</td>
|
<td className="is-hidden-mobile">{this.renderLink(to, group.name)}</td>
|
||||||
<td>{this.renderLink(to, group.description)}</td>
|
<td>{group.description}</td>
|
||||||
</tr>
|
</tr>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
123
scm-ui/src/groups/containers/SingleGroup.js
Normal file
123
scm-ui/src/groups/containers/SingleGroup.js
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
//@flow
|
||||||
|
import React from "react";
|
||||||
|
import { connect } from "react-redux";
|
||||||
|
import { Page } from "../../components/layout";
|
||||||
|
import { Route } from "react-router";
|
||||||
|
import { Details } from "./../components/table";
|
||||||
|
import type { Group } from "../types/Group";
|
||||||
|
import type { History } from "history";
|
||||||
|
import {
|
||||||
|
fetchGroup,
|
||||||
|
getGroupByName,
|
||||||
|
isFetchGroupPending,
|
||||||
|
getFetchGroupFailure,
|
||||||
|
} from "../modules/groups";
|
||||||
|
import Loading from "../../components/Loading";
|
||||||
|
|
||||||
|
import { Navigation, Section, NavLink } from "../../components/navigation";
|
||||||
|
import ErrorPage from "../../components/ErrorPage";
|
||||||
|
import { translate } from "react-i18next";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
name: string,
|
||||||
|
group: Group,
|
||||||
|
loading: boolean,
|
||||||
|
error: Error,
|
||||||
|
|
||||||
|
// dispatcher functions
|
||||||
|
fetchGroup: string => void,
|
||||||
|
|
||||||
|
// context objects
|
||||||
|
t: string => string,
|
||||||
|
match: any,
|
||||||
|
history: History
|
||||||
|
};
|
||||||
|
|
||||||
|
class SingleGroup extends React.Component<Props> {
|
||||||
|
componentDidMount() {
|
||||||
|
this.props.fetchGroup(this.props.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
stripEndingSlash = (url: string) => {
|
||||||
|
if (url.endsWith("/")) {
|
||||||
|
return url.substring(0, url.length - 2);
|
||||||
|
}
|
||||||
|
return url;
|
||||||
|
};
|
||||||
|
|
||||||
|
matchedUrl = () => {
|
||||||
|
return this.stripEndingSlash(this.props.match.url);
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { t, loading, error, group } = this.props;
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
return (
|
||||||
|
<ErrorPage
|
||||||
|
title={t("single-group.error-title")}
|
||||||
|
subtitle={t("single-group.error-subtitle")}
|
||||||
|
error={error}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!group || loading) {
|
||||||
|
return <Loading />;
|
||||||
|
}
|
||||||
|
|
||||||
|
const url = this.matchedUrl();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Page title={group.name}>
|
||||||
|
<div className="columns">
|
||||||
|
<div className="column is-three-quarters">
|
||||||
|
<Route path={url} exact component={() => <Details group={group} />} />
|
||||||
|
</div>
|
||||||
|
<div className="column">
|
||||||
|
<Navigation>
|
||||||
|
<Section label={t("single-group.navigation-label")}>
|
||||||
|
<NavLink
|
||||||
|
to={`${url}`}
|
||||||
|
label={t("single-group.information-label")}
|
||||||
|
/>
|
||||||
|
</Section>
|
||||||
|
<Section label={t("single-group.actions-label")}>
|
||||||
|
<NavLink to="/groups" label={t("single-group.back-label")} />
|
||||||
|
</Section>
|
||||||
|
</Navigation>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Page>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapStateToProps = (state, ownProps) => {
|
||||||
|
const name = ownProps.match.params.name;
|
||||||
|
const group = getGroupByName(state, name);
|
||||||
|
const loading =
|
||||||
|
isFetchGroupPending(state, name);
|
||||||
|
const error =
|
||||||
|
getFetchGroupFailure(state, name);
|
||||||
|
|
||||||
|
return {
|
||||||
|
name,
|
||||||
|
group,
|
||||||
|
loading,
|
||||||
|
error
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const mapDispatchToProps = dispatch => {
|
||||||
|
return {
|
||||||
|
fetchGroup: (name: string) => {
|
||||||
|
dispatch(fetchGroup(name));
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export default connect(
|
||||||
|
mapStateToProps,
|
||||||
|
mapDispatchToProps
|
||||||
|
)(translate("groups")(SingleGroup));
|
||||||
@@ -37,7 +37,6 @@ const GROUPS_URL = "groups";
|
|||||||
const CONTENT_TYPE_GROUP = "application/vnd.scmm-group+json;v=2";
|
const CONTENT_TYPE_GROUP = "application/vnd.scmm-group+json;v=2";
|
||||||
|
|
||||||
// fetch groups
|
// fetch groups
|
||||||
|
|
||||||
export function fetchGroups() {
|
export function fetchGroups() {
|
||||||
return fetchGroupsByLink(GROUPS_URL);
|
return fetchGroupsByLink(GROUPS_URL);
|
||||||
}
|
}
|
||||||
@@ -86,6 +85,54 @@ export function fetchGroupsFailure(url: string, error: Error): Action {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//fetch group
|
||||||
|
export function fetchGroup(name: string) {
|
||||||
|
const groupUrl = GROUPS_URL + "/" + name;
|
||||||
|
return function(dispatch: any) {
|
||||||
|
dispatch(fetchGroupPending(name));
|
||||||
|
return apiClient
|
||||||
|
.get(groupUrl)
|
||||||
|
.then(response => {
|
||||||
|
return response.json();
|
||||||
|
})
|
||||||
|
.then(data => {
|
||||||
|
dispatch(fetchGroupSuccess(data));
|
||||||
|
})
|
||||||
|
.catch(cause => {
|
||||||
|
const error = new Error(`could not fetch group: ${cause.message}`);
|
||||||
|
dispatch(fetchGroupFailure(name, error));
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function fetchGroupPending(name: string): Action {
|
||||||
|
return {
|
||||||
|
type: FETCH_GROUP_PENDING,
|
||||||
|
payload: name,
|
||||||
|
itemId: name
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function fetchGroupSuccess(group: any): Action {
|
||||||
|
return {
|
||||||
|
type: FETCH_GROUP_SUCCESS,
|
||||||
|
payload: group,
|
||||||
|
itemId: group.name
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function fetchGroupFailure(name: string, error: Error): Action {
|
||||||
|
return {
|
||||||
|
type: FETCH_GROUP_FAILURE,
|
||||||
|
payload: {
|
||||||
|
name,
|
||||||
|
error
|
||||||
|
},
|
||||||
|
itemId: name
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
//create group
|
||||||
export function createGroup(group: Group) {
|
export function createGroup(group: Group) {
|
||||||
return function(dispatch: Dispatch) {
|
return function(dispatch: Dispatch) {
|
||||||
dispatch(createGroupPending());
|
dispatch(createGroupPending());
|
||||||
@@ -121,6 +168,7 @@ export function createGroupFailure(error: Error) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//reducer
|
//reducer
|
||||||
function extractGroupsByNames(
|
function extractGroupsByNames(
|
||||||
groups: Groups[],
|
groups: Groups[],
|
||||||
@@ -179,7 +227,8 @@ function byNamesReducer(state: any = {}, action: any = {}) {
|
|||||||
return {
|
return {
|
||||||
...byNames
|
...byNames
|
||||||
};
|
};
|
||||||
|
case FETCH_GROUP_SUCCESS:
|
||||||
|
return reducerByName(state, action.payload.name, action.payload);
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
@@ -254,3 +303,11 @@ export function getGroupByName(state: Object, name: string) {
|
|||||||
return state.groups.byNames[name];
|
return state.groups.byNames[name];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isFetchGroupPending(state: Object, name: string) {
|
||||||
|
return isPending(state, FETCH_GROUP, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getFetchGroupFailure(state: Object, name: string) {
|
||||||
|
return getFailure(state, FETCH_GROUP, name);
|
||||||
|
}
|
||||||
|
|||||||
@@ -15,6 +15,15 @@ import reducer, {
|
|||||||
getFetchGroupsFailure,
|
getFetchGroupsFailure,
|
||||||
isFetchGroupsPending,
|
isFetchGroupsPending,
|
||||||
selectListAsCollection,
|
selectListAsCollection,
|
||||||
|
fetchGroup,
|
||||||
|
FETCH_GROUP_PENDING,
|
||||||
|
FETCH_GROUP_SUCCESS,
|
||||||
|
FETCH_GROUP_FAILURE,
|
||||||
|
fetchGroupSuccess,
|
||||||
|
getFetchGroupFailure,
|
||||||
|
FETCH_GROUP,
|
||||||
|
isFetchGroupPending,
|
||||||
|
getGroupByName,
|
||||||
createGroup,
|
createGroup,
|
||||||
CREATE_GROUP_SUCCESS,
|
CREATE_GROUP_SUCCESS,
|
||||||
CREATE_GROUP_PENDING,
|
CREATE_GROUP_PENDING,
|
||||||
@@ -27,22 +36,22 @@ const GROUPS_URL = "/scm/api/rest/v2/groups";
|
|||||||
|
|
||||||
const error = new Error("You have an error!");
|
const error = new Error("You have an error!");
|
||||||
|
|
||||||
const groupZaphod = {
|
const humanGroup = {
|
||||||
creationDate: "2018-07-31T08:39:07.860Z",
|
creationDate: "2018-07-31T08:39:07.860Z",
|
||||||
description: "This is a group",
|
description: "This is a group",
|
||||||
name: "zaphodGroup",
|
name: "humanGroup",
|
||||||
type: "xml",
|
type: "xml",
|
||||||
properties: {},
|
properties: {},
|
||||||
members: ["userZaphod"],
|
members: ["userZaphod"],
|
||||||
_links: {
|
_links: {
|
||||||
self: {
|
self: {
|
||||||
href: "http://localhost:3000/scm/api/rest/v2/groups/zaphodGroup"
|
href: "http://localhost:3000/scm/api/rest/v2/groups/humanGroup"
|
||||||
},
|
},
|
||||||
delete: {
|
delete: {
|
||||||
href: "http://localhost:3000/scm/api/rest/v2/groups/zaphodGroup"
|
href: "http://localhost:3000/scm/api/rest/v2/groups/humanGroup"
|
||||||
},
|
},
|
||||||
update: {
|
update: {
|
||||||
href: "http://localhost:3000/scm/api/rest/v2/groups/zaphodGroup"
|
href:"http://localhost:3000/scm/api/rest/v2/groups/humanGroup"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_embedded: {
|
_embedded: {
|
||||||
@@ -59,22 +68,22 @@ const groupZaphod = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const groupFord = {
|
const emptyGroup = {
|
||||||
creationDate: "2018-07-31T08:39:07.860Z",
|
creationDate: "2018-07-31T08:39:07.860Z",
|
||||||
description: "This is a group",
|
description: "This is a group",
|
||||||
name: "fordGroup",
|
name: "emptyGroup",
|
||||||
type: "xml",
|
type: "xml",
|
||||||
properties: {},
|
properties: {},
|
||||||
members: [],
|
members: [],
|
||||||
_links: {
|
_links: {
|
||||||
self: {
|
self: {
|
||||||
href: "http://localhost:3000/scm/api/rest/v2/groups/fordGroup"
|
href: "http://localhost:3000/scm/api/rest/v2/groups/emptyGroup"
|
||||||
},
|
},
|
||||||
delete: {
|
delete: {
|
||||||
href: "http://localhost:3000/scm/api/rest/v2/groups/fordGroup"
|
href: "http://localhost:3000/scm/api/rest/v2/groups/emptyGroup"
|
||||||
},
|
},
|
||||||
update: {
|
update: {
|
||||||
href: "http://localhost:3000/scm/api/rest/v2/groups/fordGroup"
|
href:"http://localhost:3000/scm/api/rest/v2/groups/emptyGroup"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_embedded: {
|
_embedded: {
|
||||||
@@ -100,7 +109,7 @@ const responseBody = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
_embedded: {
|
_embedded: {
|
||||||
groups: [groupZaphod, groupFord]
|
groups: [humanGroup, emptyGroup]
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -148,13 +157,40 @@ describe("groups fetch()", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should sucessfully fetch single group", () => {
|
||||||
|
fetchMock.getOnce(GROUPS_URL + "/humandGroup", humanGroup);
|
||||||
|
|
||||||
|
const store = mockStore({});
|
||||||
|
return store.dispatch(fetchGroup("humandGroup")).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 on HTTP 500", () => {
|
||||||
|
fetchMock.getOnce(GROUPS_URL + "/humandGroup", {
|
||||||
|
status: 500
|
||||||
|
});
|
||||||
|
|
||||||
|
const store = mockStore({});
|
||||||
|
return store.dispatch(fetchGroup("humandGroup")).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 successfully create group", () => {
|
it("should successfully create group", () => {
|
||||||
fetchMock.postOnce(GROUPS_URL, {
|
fetchMock.postOnce(GROUPS_URL, {
|
||||||
status: 201
|
status: 201
|
||||||
});
|
});
|
||||||
|
|
||||||
const store = mockStore({});
|
const store = mockStore({});
|
||||||
return store.dispatch(createGroup(groupZaphod)).then(() => {
|
return store.dispatch(createGroup(humanGroup)).then(() => {
|
||||||
const actions = store.getActions();
|
const actions = store.getActions();
|
||||||
expect(actions[0].type).toEqual(CREATE_GROUP_PENDING);
|
expect(actions[0].type).toEqual(CREATE_GROUP_PENDING);
|
||||||
expect(actions[1].type).toEqual(CREATE_GROUP_SUCCESS);
|
expect(actions[1].type).toEqual(CREATE_GROUP_SUCCESS);
|
||||||
@@ -167,7 +203,7 @@ describe("groups fetch()", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const store = mockStore({});
|
const store = mockStore({});
|
||||||
return store.dispatch(createGroup(groupZaphod)).then(() => {
|
return store.dispatch(createGroup(humanGroup)).then(() => {
|
||||||
const actions = store.getActions();
|
const actions = store.getActions();
|
||||||
expect(actions[0].type).toEqual(CREATE_GROUP_PENDING);
|
expect(actions[0].type).toEqual(CREATE_GROUP_PENDING);
|
||||||
expect(actions[1].type).toEqual(CREATE_GROUP_FAILURE);
|
expect(actions[1].type).toEqual(CREATE_GROUP_FAILURE);
|
||||||
@@ -178,11 +214,13 @@ describe("groups fetch()", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe("groups reducer", () => {
|
describe("groups reducer", () => {
|
||||||
it("should update state correctly according to FETCH_USERS_SUCCESS action", () => {
|
|
||||||
|
it("should update state correctly according to FETCH_GROUPS_SUCCESS action", () => {
|
||||||
|
|
||||||
const newState = reducer({}, fetchGroupsSuccess(responseBody));
|
const newState = reducer({}, fetchGroupsSuccess(responseBody));
|
||||||
|
|
||||||
expect(newState.list).toEqual({
|
expect(newState.list).toEqual({
|
||||||
entries: ["zaphodGroup", "fordGroup"],
|
entries: ["humanGroup", "emptyGroup"],
|
||||||
entry: {
|
entry: {
|
||||||
groupCreatePermission: true,
|
groupCreatePermission: true,
|
||||||
page: 0,
|
page: 0,
|
||||||
@@ -192,8 +230,8 @@ describe("groups reducer", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
expect(newState.byNames).toEqual({
|
expect(newState.byNames).toEqual({
|
||||||
zaphodGroup: groupZaphod,
|
humanGroup: humanGroup,
|
||||||
fordGroup: groupFord
|
emptyGroup: emptyGroup
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(newState.list.entry.groupCreatePermission).toBeTruthy();
|
expect(newState.list.entry.groupCreatePermission).toBeTruthy();
|
||||||
@@ -205,26 +243,46 @@ describe("groups reducer", () => {
|
|||||||
expect(newState.list.entry.groupCreatePermission).toBeTruthy();
|
expect(newState.list.entry.groupCreatePermission).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should not replace whole byNames map when fetching users", () => {
|
it("should not replace whole byNames map when fetching groups", () => {
|
||||||
const oldState = {
|
const oldState = {
|
||||||
byNames: {
|
byNames: {
|
||||||
fordGroup: groupFord
|
emptyGroup: emptyGroup
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const newState = reducer(oldState, fetchGroupsSuccess(responseBody));
|
const newState = reducer(oldState, fetchGroupsSuccess(responseBody));
|
||||||
expect(newState.byNames["zaphodGroup"]).toBeDefined();
|
expect(newState.byNames["humanGroup"]).toBeDefined();
|
||||||
expect(newState.byNames["fordGroup"]).toBeDefined();
|
expect(newState.byNames["emptyGroup"]).toBeDefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should set userCreatePermission to true if create link is present", () => {
|
it("should set groupCreatePermission to true if create link is present", () => {
|
||||||
const newState = reducer({}, fetchGroupsSuccess(responseBody));
|
const newState = reducer({}, fetchGroupsSuccess(responseBody));
|
||||||
|
|
||||||
expect(newState.list.entry.groupCreatePermission).toBeTruthy();
|
expect(newState.list.entry.groupCreatePermission).toBeTruthy();
|
||||||
expect(newState.list.entries).toEqual(["zaphodGroup", "fordGroup"]);
|
expect(newState.list.entries).toEqual(["humanGroup", "emptyGroup"]);
|
||||||
expect(newState.byNames["fordGroup"]).toBeTruthy();
|
expect(newState.byNames["emptyGroup"]).toBeTruthy();
|
||||||
expect(newState.byNames["zaphodGroup"]).toBeTruthy();
|
expect(newState.byNames["humanGroup"]).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it("should update state according to FETCH_GROUP_SUCCESS action", () => {
|
||||||
|
const newState = reducer({}, fetchGroupSuccess(emptyGroup));
|
||||||
|
expect(newState.byNames["emptyGroup"]).toBe(emptyGroup);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should affect groups state nor the state of other groups", () => {
|
||||||
|
const newState = reducer(
|
||||||
|
{
|
||||||
|
list: {
|
||||||
|
entries: ["humanGroup"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
fetchGroupSuccess(emptyGroup)
|
||||||
|
);
|
||||||
|
expect(newState.byNames["emptyGroup"]).toBe(emptyGroup);
|
||||||
|
expect(newState.list.entries).toEqual(["humanGroup"]);
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("selector tests", () => {
|
describe("selector tests", () => {
|
||||||
@@ -311,10 +369,47 @@ describe("selector tests", () => {
|
|||||||
expect(getFetchGroupsFailure(state)).toEqual(error);
|
expect(getFetchGroupsFailure(state)).toEqual(error);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should return undefined when fetch users did not fail", () => {
|
it("should return undefined when fetch groups did not fail", () => {
|
||||||
expect(getFetchGroupsFailure({})).toBe(undefined);
|
expect(getFetchGroupsFailure({})).toBe(undefined);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should return group emptyGroup", () => {
|
||||||
|
const state = {
|
||||||
|
groups: {
|
||||||
|
byNames: {
|
||||||
|
emptyGroup: emptyGroup
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
expect(getGroupByName(state, "emptyGroup")).toEqual(emptyGroup);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return true, when fetch group humandGroup is pending", () => {
|
||||||
|
const state = {
|
||||||
|
pending: {
|
||||||
|
[FETCH_GROUP + "/humandGroup"]: true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
expect(isFetchGroupPending(state, "humandGroup")).toEqual(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return false, when fetch group humandGroup is not pending", () => {
|
||||||
|
expect(isFetchGroupPending({}, "humandGroup")).toEqual(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return error when fetch group humandGroup did fail", () => {
|
||||||
|
const state = {
|
||||||
|
failure: {
|
||||||
|
[FETCH_GROUP + "/humandGroup"]: error
|
||||||
|
}
|
||||||
|
};
|
||||||
|
expect(getFetchGroupFailure(state, "humandGroup")).toEqual(error);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return undefined when fetch group humandGroup did not fail", () => {
|
||||||
|
expect(getFetchGroupFailure({}, "humandGroup")).toBe(undefined);
|
||||||
|
});
|
||||||
|
|
||||||
it("should return true if create group is pending", () => {
|
it("should return true if create group is pending", () => {
|
||||||
expect(isCreateGroupPending({pending: {
|
expect(isCreateGroupPending({pending: {
|
||||||
[CREATE_GROUP]: true
|
[CREATE_GROUP]: true
|
||||||
@@ -336,4 +431,5 @@ describe("selector tests", () => {
|
|||||||
it("should return undefined if creating group did not fail", () => {
|
it("should return undefined if creating group did not fail", () => {
|
||||||
expect(getCreateGroupFailure({})).toBeUndefined()
|
expect(getCreateGroupFailure({})).toBeUndefined()
|
||||||
})
|
})
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ export type Group = {
|
|||||||
description: string,
|
description: string,
|
||||||
lastModified: string,
|
lastModified: string,
|
||||||
type: string,
|
type: string,
|
||||||
properties: [],
|
|
||||||
members: string[],
|
members: string[],
|
||||||
_links: Links,
|
_links: Links,
|
||||||
_embedded: {
|
_embedded: {
|
||||||
|
|||||||
Reference in New Issue
Block a user