@truedat/dd 5.19.0 → 5.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +5 -5
- package/src/api/queries.js +19 -1
- package/src/components/Grant.js +9 -27
- package/src/components/GrantRemoval.js +26 -34
- package/src/components/GrantRemovalDirectButton.js +89 -0
- package/src/components/GrantRemovalWorkflow.js +107 -0
- package/src/components/GrantRemovalWorkflowDropdown.js +144 -0
- package/src/components/GrantRequest.js +2 -1
- package/src/components/GrantRequestCancel.js +5 -2
- package/src/components/GrantRequestHeader.js +13 -7
- package/src/components/GrantRequestRow.js +8 -1
- package/src/components/GrantRequests.js +8 -3
- package/src/components/GrantRequestsTable.js +1 -1
- package/src/components/StructureGrantDropdown.js +7 -40
- package/src/components/StructureGrantSummaryButton.js +2 -2
- package/src/components/StructureGrants.js +21 -17
- package/src/components/__tests__/Grant.spec.js +11 -7
- package/src/components/__tests__/GrantRemoval.spec.js +19 -54
- package/src/components/__tests__/GrantRemovalDirectButton.spec.js +66 -0
- package/src/components/__tests__/GrantRemovalWorkflow.spec.js +157 -0
- package/src/components/__tests__/GrantRequest.spec.js +2 -0
- package/src/components/__tests__/GrantRequestHeader.spec.js +2 -5
- package/src/components/__tests__/StructureGrantDropdown.spec.js +1 -16
- package/src/components/__tests__/StructureGrantSummaryButton.spec.js +3 -2
- package/src/components/__tests__/StructureGrants.spec.js +5 -1
- package/src/components/__tests__/__snapshots__/Grant.spec.js.snap +5 -4
- package/src/components/__tests__/__snapshots__/GrantRequest.spec.js.snap +3 -3
- package/src/components/__tests__/__snapshots__/GrantRequestHeader.spec.js.snap +4 -4
- package/src/components/__tests__/__snapshots__/GrantRequestsSearchResults.spec.js.snap +1 -1
- package/src/components/__tests__/__snapshots__/StructureGrantDropdown.spec.js.snap +0 -52
- package/src/components/__tests__/__snapshots__/StructureGrantListButton.spec.js.snap +0 -14
- package/src/components/__tests__/__snapshots__/StructureGrantSummaryButton.spec.js.snap +0 -14
- package/src/components/__tests__/__snapshots__/StructureGrants.spec.js.snap +4 -5
- package/src/hooks/useGrantRequest.js +10 -1
- package/src/messages/en.js +23 -8
- package/src/messages/es.js +26 -9
- package/src/reducers/structure.js +1 -0
- package/src/sagas/__tests__/createGrantRequestStatus.spec.js +1 -1
- package/src/sagas/createGrantRequestStatus.js +24 -8
- package/src/selectors/getGrantRequestsColumns.js +32 -5
- package/src/selectors/getGrantRequestsSearchColumns.js +20 -14
- package/src/selectors/utils/decorators.js +68 -0
- package/src/components/__tests__/__snapshots__/GrantRemoval.spec.js.snap +0 -9
|
@@ -8,11 +8,11 @@ import { linkTo } from "@truedat/core/routes";
|
|
|
8
8
|
import { Date } from "@truedat/core/components";
|
|
9
9
|
|
|
10
10
|
import GrantChangeRequest from "./GrantChangeRequest";
|
|
11
|
-
import GrantRemoval from "./GrantRemoval";
|
|
12
11
|
import GrantRequestCancel from "./GrantRequestCancel";
|
|
13
12
|
import StructureGrantRequestAddCart from "./StructureGrantRequestAddCart";
|
|
14
13
|
|
|
15
14
|
const isNilOrEmpty = (value) => _.isEmpty(value) || _.isNil(value);
|
|
15
|
+
|
|
16
16
|
export const StructureGrantDropdown = ({
|
|
17
17
|
grantRequest,
|
|
18
18
|
grantRequestStatus,
|
|
@@ -54,38 +54,10 @@ export const StructureGrantDropdown = ({
|
|
|
54
54
|
}
|
|
55
55
|
icon="info"
|
|
56
56
|
text={formatMessage({
|
|
57
|
-
id: `grant.actions.
|
|
57
|
+
id: `grant.actions.viewRequest.confirmation.header`,
|
|
58
58
|
})}
|
|
59
59
|
/>
|
|
60
60
|
),
|
|
61
|
-
requestRemoval: (
|
|
62
|
-
<GrantRemoval
|
|
63
|
-
grant={grant}
|
|
64
|
-
previousStructureQuery={previousStructureQuery}
|
|
65
|
-
key="requestRemoval"
|
|
66
|
-
>
|
|
67
|
-
<Dropdown.Item
|
|
68
|
-
icon="delete"
|
|
69
|
-
text={formatMessage({
|
|
70
|
-
id: `grant.actions.request_removal.confirmation.header`,
|
|
71
|
-
})}
|
|
72
|
-
/>
|
|
73
|
-
</GrantRemoval>
|
|
74
|
-
),
|
|
75
|
-
cancelRemoval: (
|
|
76
|
-
<GrantRemoval
|
|
77
|
-
grant={grant}
|
|
78
|
-
previousStructureQuery={previousStructureQuery}
|
|
79
|
-
key="cancelRemoval"
|
|
80
|
-
>
|
|
81
|
-
<Dropdown.Item
|
|
82
|
-
icon="delete"
|
|
83
|
-
text={formatMessage({
|
|
84
|
-
id: `grant.actions.cancel_removal.confirmation.header`,
|
|
85
|
-
})}
|
|
86
|
-
/>
|
|
87
|
-
</GrantRemoval>
|
|
88
|
-
),
|
|
89
61
|
requestChange: (
|
|
90
62
|
<GrantChangeRequest
|
|
91
63
|
structure={structure}
|
|
@@ -133,14 +105,9 @@ export const StructureGrantDropdown = ({
|
|
|
133
105
|
? "structure.grant.modification.attended"
|
|
134
106
|
: "structure.grant.access.attended",
|
|
135
107
|
},
|
|
136
|
-
pendingRemovalGrant: {
|
|
137
|
-
color: "red",
|
|
138
|
-
options: [actions["cancelRemoval"]],
|
|
139
|
-
header: "structure.grant.has_grant_pending_removal",
|
|
140
|
-
},
|
|
141
108
|
activeGrant: {
|
|
142
109
|
color: "green",
|
|
143
|
-
options: [actions["requestChange"]
|
|
110
|
+
options: [actions["requestChange"]],
|
|
144
111
|
header: "structure.grant.has_grant",
|
|
145
112
|
},
|
|
146
113
|
};
|
|
@@ -149,8 +116,6 @@ export const StructureGrantDropdown = ({
|
|
|
149
116
|
? "pendingRequest"
|
|
150
117
|
: hasProcessingGrantRequest
|
|
151
118
|
? "processingRequest"
|
|
152
|
-
: grant?.pending_removal
|
|
153
|
-
? "pendingRemovalGrant"
|
|
154
119
|
: "activeGrant";
|
|
155
120
|
|
|
156
121
|
const stateProps = dropdownStates[currentState];
|
|
@@ -173,7 +138,9 @@ export const StructureGrantDropdown = ({
|
|
|
173
138
|
|
|
174
139
|
const popupContent = (
|
|
175
140
|
<>
|
|
176
|
-
|
|
141
|
+
{stateProps?.header ? (
|
|
142
|
+
<Header as="h6">{formatMessage({ id: stateProps.header })}</Header>
|
|
143
|
+
) : null}
|
|
177
144
|
{grantRequest ? grantRequestDetails : grantDetails}
|
|
178
145
|
</>
|
|
179
146
|
);
|
|
@@ -181,7 +148,7 @@ export const StructureGrantDropdown = ({
|
|
|
181
148
|
const optionsWithCart =
|
|
182
149
|
authorized && !requested
|
|
183
150
|
? [actions["addToCart"], ...stateProps.options]
|
|
184
|
-
: stateProps
|
|
151
|
+
: stateProps?.options;
|
|
185
152
|
|
|
186
153
|
const trigger = (
|
|
187
154
|
<Dropdown
|
|
@@ -4,7 +4,7 @@ import PropTypes from "prop-types";
|
|
|
4
4
|
import { useQuery } from "@apollo/client";
|
|
5
5
|
import { connect } from "react-redux";
|
|
6
6
|
import { Loading } from "@truedat/core/components";
|
|
7
|
-
import {
|
|
7
|
+
import { LATEST_GRANT_REQUEST_BY_DS_QUERY } from "../api/queries";
|
|
8
8
|
import StructureGrantRequestButton from "./StructureGrantRequestButton";
|
|
9
9
|
import StructureGrantDropdown from "./StructureGrantDropdown";
|
|
10
10
|
|
|
@@ -17,7 +17,7 @@ export const StructureGrantSummaryButton = ({
|
|
|
17
17
|
}) => {
|
|
18
18
|
const { grant, id } = structure;
|
|
19
19
|
|
|
20
|
-
const { loading, error, data } = useQuery(
|
|
20
|
+
const { loading, error, data } = useQuery(LATEST_GRANT_REQUEST_BY_DS_QUERY, {
|
|
21
21
|
fetchPolicy: "cache-and-network",
|
|
22
22
|
variables: { id },
|
|
23
23
|
});
|
|
@@ -2,35 +2,25 @@ import _ from "lodash/fp";
|
|
|
2
2
|
import React from "react";
|
|
3
3
|
import PropTypes from "prop-types";
|
|
4
4
|
import { useIntl } from "react-intl";
|
|
5
|
-
import { Table
|
|
5
|
+
import { Table } from "semantic-ui-react";
|
|
6
6
|
import { connect } from "react-redux";
|
|
7
|
+
import { useHistory } from "react-router-dom";
|
|
7
8
|
import { columnDecorator } from "@truedat/core/services";
|
|
9
|
+
import { linkTo } from "@truedat/core/routes";
|
|
8
10
|
import { getGrantsColumns } from "../selectors";
|
|
9
11
|
import GrantRemoval from "./GrantRemoval";
|
|
10
12
|
|
|
11
|
-
export const RemovalButton = ({ grant }) => (
|
|
12
|
-
<GrantRemoval grant={grant}>
|
|
13
|
-
{grant.pending_removal ? (
|
|
14
|
-
<Button size="mini" color="olive" icon="undo" />
|
|
15
|
-
) : (
|
|
16
|
-
<Button size="mini" color="red" icon="delete" />
|
|
17
|
-
)}
|
|
18
|
-
</GrantRemoval>
|
|
19
|
-
);
|
|
20
|
-
|
|
21
|
-
RemovalButton.propTypes = {
|
|
22
|
-
grant: PropTypes.object,
|
|
23
|
-
};
|
|
24
|
-
|
|
25
13
|
const matchesStructure = ({ id }) => _.pathEq("data_structure.id", id);
|
|
26
14
|
|
|
27
15
|
export const StructureGrants = ({
|
|
28
16
|
columns,
|
|
29
17
|
grants,
|
|
18
|
+
grantsActions,
|
|
30
19
|
structure,
|
|
31
20
|
userPermissions,
|
|
32
21
|
}) => {
|
|
33
22
|
const { formatMessage } = useIntl();
|
|
23
|
+
const history = useHistory();
|
|
34
24
|
const canUpdateRemoval =
|
|
35
25
|
userPermissions?.update_grant_removal &&
|
|
36
26
|
_.any(matchesStructure(structure))(grants);
|
|
@@ -54,19 +44,31 @@ export const StructureGrants = ({
|
|
|
54
44
|
</Table.Header>
|
|
55
45
|
<Table.Body>
|
|
56
46
|
{grants.map((grant, i) => (
|
|
57
|
-
|
|
47
|
+
// Move style to file after task to create "CSS entrypoint" is done
|
|
48
|
+
<Table.Row key={i} style={{ cursor: "pointer" }}>
|
|
58
49
|
{columns.map((column, key) => (
|
|
59
50
|
<Table.Cell
|
|
60
51
|
key={key}
|
|
61
52
|
textAlign={column.textAlign}
|
|
62
53
|
content={columnDecorator(column)(grant)}
|
|
54
|
+
onClick={(ev) => {
|
|
55
|
+
/* Only do history.push if the table cell but not
|
|
56
|
+
* some possibly contained anchor (or an element
|
|
57
|
+
* inside an anchor, such as an icon) is clicked
|
|
58
|
+
*/
|
|
59
|
+
!ev.target.closest("a") && history.push(linkTo.GRANT(grant));
|
|
60
|
+
}}
|
|
63
61
|
/>
|
|
64
62
|
))}
|
|
65
63
|
{canUpdateRemoval ? (
|
|
66
64
|
<Table.Cell
|
|
67
65
|
content={
|
|
68
66
|
matchesStructure(structure)(grant) ? (
|
|
69
|
-
<
|
|
67
|
+
<GrantRemoval
|
|
68
|
+
grant={grant}
|
|
69
|
+
actions={grantsActions}
|
|
70
|
+
userPermissions={userPermissions}
|
|
71
|
+
/>
|
|
70
72
|
) : null
|
|
71
73
|
}
|
|
72
74
|
/>
|
|
@@ -80,6 +82,7 @@ export const StructureGrants = ({
|
|
|
80
82
|
|
|
81
83
|
StructureGrants.propTypes = {
|
|
82
84
|
grants: PropTypes.array,
|
|
85
|
+
grantsActions: PropTypes.object,
|
|
83
86
|
columns: PropTypes.array,
|
|
84
87
|
structure: PropTypes.object,
|
|
85
88
|
userPermissions: PropTypes.object,
|
|
@@ -90,6 +93,7 @@ const mapStateToProps = (state) => ({
|
|
|
90
93
|
structure: state.structure,
|
|
91
94
|
columns: getGrantsColumns(state),
|
|
92
95
|
userPermissions: state.userPermissions,
|
|
96
|
+
grantsActions: state?.structure?._actions?._grants,
|
|
93
97
|
});
|
|
94
98
|
|
|
95
99
|
export default connect(mapStateToProps)(StructureGrants);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import userEvent from "@testing-library/user-event";
|
|
3
3
|
import { render } from "@truedat/test/render";
|
|
4
|
+
import { waitFor } from "@testing-library/react";
|
|
4
5
|
import { Grant } from "../Grant";
|
|
5
6
|
import en from "../../messages/en";
|
|
6
7
|
|
|
@@ -45,7 +46,7 @@ describe("<Grant />", () => {
|
|
|
45
46
|
},
|
|
46
47
|
};
|
|
47
48
|
const actions = {
|
|
48
|
-
|
|
49
|
+
manage_grant_removal: {},
|
|
49
50
|
};
|
|
50
51
|
|
|
51
52
|
const defaultProps = {
|
|
@@ -71,25 +72,28 @@ describe("<Grant />", () => {
|
|
|
71
72
|
expect(container).toMatchSnapshot();
|
|
72
73
|
});
|
|
73
74
|
|
|
74
|
-
it("matches the latest snapshot with
|
|
75
|
+
it("matches the latest snapshot with manage_grant_removal action", async () => {
|
|
75
76
|
const props = {
|
|
76
77
|
...defaultProps,
|
|
78
|
+
grant: { ...grant, pending_removal: true },
|
|
77
79
|
actions: {
|
|
78
|
-
|
|
80
|
+
manage_grant_removal: {},
|
|
79
81
|
},
|
|
80
82
|
};
|
|
81
|
-
const { container } = render(<Grant {...props} />, renderOpts);
|
|
83
|
+
const { container, queryByText } = render(<Grant {...props} />, renderOpts);
|
|
84
|
+
await waitFor(() => expect(queryByText(/lazy/i)).not.toBeInTheDocument());
|
|
82
85
|
expect(container).toMatchSnapshot();
|
|
83
86
|
});
|
|
84
87
|
|
|
85
|
-
it("matches the latest snapshot with update action", () => {
|
|
88
|
+
it("matches the latest snapshot with update action", async () => {
|
|
86
89
|
const props = {
|
|
87
90
|
...defaultProps,
|
|
88
91
|
actions: {
|
|
89
92
|
update: {},
|
|
90
93
|
},
|
|
91
94
|
};
|
|
92
|
-
const { container } = render(<Grant {...props} />, renderOpts);
|
|
95
|
+
const { container, queryByText } = render(<Grant {...props} />, renderOpts);
|
|
96
|
+
await waitFor(() => expect(queryByText(/lazy/i)).not.toBeInTheDocument());
|
|
93
97
|
expect(container).toMatchSnapshot();
|
|
94
98
|
});
|
|
95
99
|
|
|
@@ -102,7 +106,7 @@ describe("<Grant />", () => {
|
|
|
102
106
|
userEvent.click(await findByText("yes"));
|
|
103
107
|
|
|
104
108
|
expect(defaultProps.onStatusChange).toHaveBeenLastCalledWith({
|
|
105
|
-
action: "
|
|
109
|
+
action: "mark_pending_removal",
|
|
106
110
|
data_structure_id: 2,
|
|
107
111
|
id: 1,
|
|
108
112
|
});
|
|
@@ -1,68 +1,33 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import userEvent from "@testing-library/user-event";
|
|
3
2
|
import { render } from "@truedat/test/render";
|
|
4
|
-
import { requestGrantRemoval } from "../../routines";
|
|
5
3
|
import GrantRemoval from "../GrantRemoval";
|
|
6
4
|
|
|
7
5
|
describe("<GrantRemoval />", () => {
|
|
8
6
|
const grant = {
|
|
9
|
-
id:
|
|
10
|
-
detail: { foo: "bar" },
|
|
11
|
-
data_structure: { id: 2 },
|
|
12
|
-
data_structure_version: { id: 3 },
|
|
7
|
+
id: 17,
|
|
13
8
|
};
|
|
14
|
-
it("matches the latest snapshot", () => {
|
|
15
|
-
const { container } = render(
|
|
16
|
-
<GrantRemoval grant={grant}>
|
|
17
|
-
<p>child</p>
|
|
18
|
-
</GrantRemoval>
|
|
19
|
-
);
|
|
20
|
-
expect(container).toMatchSnapshot();
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
it("on click calls requestGrantRemoval routine if onConfirm si undefined", async () => {
|
|
24
|
-
const dispatch = jest.fn();
|
|
25
|
-
const { findByText } = render(
|
|
26
|
-
<GrantRemoval grant={grant}>
|
|
27
|
-
<p>child</p>
|
|
28
|
-
</GrantRemoval>,
|
|
29
|
-
{ dispatch }
|
|
30
|
-
);
|
|
31
|
-
|
|
32
|
-
userEvent.click(await findByText("child"));
|
|
33
|
-
expect(await findByText("Request grant removal")).toBeInTheDocument();
|
|
34
9
|
|
|
35
|
-
|
|
10
|
+
const actions_with_request_cancel = {
|
|
11
|
+
manage_grant_removal: {},
|
|
12
|
+
};
|
|
36
13
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
});
|
|
14
|
+
it("Mounts grant removal/reactivation button if user has permissions, remove", () => {
|
|
15
|
+
const { queryByText } = render(
|
|
16
|
+
<GrantRemoval
|
|
17
|
+
grant={{ ...grant, pending_removal: false }}
|
|
18
|
+
actions={actions_with_request_cancel}
|
|
19
|
+
/>
|
|
20
|
+
);
|
|
21
|
+
expect(queryByText(/Remove/)).toBeInTheDocument();
|
|
46
22
|
});
|
|
47
23
|
|
|
48
|
-
it("
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
24
|
+
it("Mounts grant removal/reactivation button if user has permissions, reactivate", () => {
|
|
25
|
+
const { queryByText } = render(
|
|
26
|
+
<GrantRemoval
|
|
27
|
+
grant={{ ...grant, pending_removal: true }}
|
|
28
|
+
actions={actions_with_request_cancel}
|
|
29
|
+
/>
|
|
54
30
|
);
|
|
55
|
-
|
|
56
|
-
userEvent.click(await findByText("child"));
|
|
57
|
-
expect(await findByText("Request grant removal")).toBeInTheDocument();
|
|
58
|
-
|
|
59
|
-
userEvent.click(await findByText("Yes"));
|
|
60
|
-
|
|
61
|
-
expect(onConfirm).toHaveBeenLastCalledWith({
|
|
62
|
-
action: "request_removal",
|
|
63
|
-
data_structure_id: 2,
|
|
64
|
-
id: 1,
|
|
65
|
-
version: 3,
|
|
66
|
-
});
|
|
31
|
+
expect(queryByText(/Reactivate/)).toBeInTheDocument();
|
|
67
32
|
});
|
|
68
33
|
});
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import userEvent from "@testing-library/user-event";
|
|
3
|
+
import { render } from "@truedat/test/render";
|
|
4
|
+
|
|
5
|
+
import GrantRemovalDirectButton from "../GrantRemovalDirectButton";
|
|
6
|
+
|
|
7
|
+
describe("<GrantRemovalDirectButton />", () => {
|
|
8
|
+
const grant = {
|
|
9
|
+
id: 1,
|
|
10
|
+
detail: { foo: "bar" },
|
|
11
|
+
data_structure: { id: 2 },
|
|
12
|
+
data_structure_version: { id: 3 },
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
it("on click calls requestGrantRemoval routine if onConfirm is undefined", async () => {
|
|
16
|
+
const requestGrantRemoval = jest.fn();
|
|
17
|
+
const { findByText } = render(
|
|
18
|
+
<GrantRemovalDirectButton
|
|
19
|
+
grant={grant}
|
|
20
|
+
operation="markPendingRemoval"
|
|
21
|
+
actions={{ manage_grant_removal: {} }}
|
|
22
|
+
requestGrantRemoval={requestGrantRemoval}
|
|
23
|
+
previousStructureQuery={{}}
|
|
24
|
+
/>
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
userEvent.click(await findByText("Remove"));
|
|
28
|
+
expect(await findByText("Request grant removal")).toBeInTheDocument();
|
|
29
|
+
|
|
30
|
+
userEvent.click(await findByText("Yes"));
|
|
31
|
+
|
|
32
|
+
expect(requestGrantRemoval).toHaveBeenCalledWith({
|
|
33
|
+
action: "mark_pending_removal",
|
|
34
|
+
data_structure_id: 2,
|
|
35
|
+
id: 1,
|
|
36
|
+
version: 3,
|
|
37
|
+
previousStructureQuery: {},
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it("on click calls onConfirm prop", async () => {
|
|
42
|
+
const onConfirm = jest.fn();
|
|
43
|
+
const { findByText } = render(
|
|
44
|
+
<GrantRemovalDirectButton
|
|
45
|
+
grant={grant}
|
|
46
|
+
operation="markPendingRemoval"
|
|
47
|
+
actions={{ manage_grant_removal: {} }}
|
|
48
|
+
onConfirm={onConfirm}
|
|
49
|
+
previousStructureQuery={{}}
|
|
50
|
+
/>
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
userEvent.click(await findByText("Remove"));
|
|
54
|
+
expect(await findByText("Request grant removal")).toBeInTheDocument();
|
|
55
|
+
|
|
56
|
+
userEvent.click(await findByText("Yes"));
|
|
57
|
+
|
|
58
|
+
expect(onConfirm).toHaveBeenLastCalledWith({
|
|
59
|
+
action: "mark_pending_removal",
|
|
60
|
+
data_structure_id: 2,
|
|
61
|
+
id: 1,
|
|
62
|
+
version: 3,
|
|
63
|
+
previousStructureQuery: {},
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
});
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { render } from "@truedat/test/render";
|
|
3
|
+
import { LATEST_GRANT_REQUEST_BY_GRANT_QUERY } from "@truedat/dd/api/queries";
|
|
4
|
+
import GrantRemovalWorkflow from "../GrantRemovalWorkflow";
|
|
5
|
+
|
|
6
|
+
describe("<GrantRemovalWorkflow />", () => {
|
|
7
|
+
const latestGrantRequestByGrantMock = (variables, grantRequestStatus) => {
|
|
8
|
+
const latestGrantRequest = !grantRequestStatus
|
|
9
|
+
? null
|
|
10
|
+
: {
|
|
11
|
+
__typename: "GrantRequest",
|
|
12
|
+
id: 17,
|
|
13
|
+
group: {
|
|
14
|
+
__typename: "GrantRequestGroup",
|
|
15
|
+
grant: null,
|
|
16
|
+
},
|
|
17
|
+
requestType: "GRANT_REMOVAL",
|
|
18
|
+
status: {
|
|
19
|
+
__typename: "GrantRequestStatus",
|
|
20
|
+
status: grantRequestStatus,
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
return {
|
|
25
|
+
request: {
|
|
26
|
+
query: LATEST_GRANT_REQUEST_BY_GRANT_QUERY,
|
|
27
|
+
variables,
|
|
28
|
+
},
|
|
29
|
+
result: {
|
|
30
|
+
data: {
|
|
31
|
+
latestGrantRequest,
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const grant = {
|
|
38
|
+
id: 17,
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const latestRequestVars = { id: grant.id, requestType: "GRANT_REMOVAL" };
|
|
42
|
+
|
|
43
|
+
it("Shows workflow button at start state", async () => {
|
|
44
|
+
const renderOpts = {
|
|
45
|
+
mocks: [latestGrantRequestByGrantMock(latestRequestVars, null)],
|
|
46
|
+
};
|
|
47
|
+
const { findByRole } = render(
|
|
48
|
+
<GrantRemovalWorkflow
|
|
49
|
+
grant={{ ...grant, pending_removal: false }}
|
|
50
|
+
actions={{}}
|
|
51
|
+
/>,
|
|
52
|
+
renderOpts
|
|
53
|
+
);
|
|
54
|
+
expect(await findByRole("button")).toHaveClass("orange");
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it("Shows workflow button at pending state", async () => {
|
|
58
|
+
const renderOpts = {
|
|
59
|
+
mocks: [latestGrantRequestByGrantMock(latestRequestVars, "pending")],
|
|
60
|
+
};
|
|
61
|
+
const { findByRole, queryByText } = render(
|
|
62
|
+
<GrantRemovalWorkflow
|
|
63
|
+
grant={{ ...grant, pending_removal: false }}
|
|
64
|
+
actions={{}}
|
|
65
|
+
/>,
|
|
66
|
+
renderOpts
|
|
67
|
+
);
|
|
68
|
+
const button = await findByRole("button");
|
|
69
|
+
expect(button).toHaveClass("yellow");
|
|
70
|
+
const cancelRequestOption = queryByText(/Cancel request/);
|
|
71
|
+
expect(cancelRequestOption).toBeInTheDocument();
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it("Shows workflow button at rejected state", async () => {
|
|
75
|
+
const renderOpts = {
|
|
76
|
+
mocks: [latestGrantRequestByGrantMock(latestRequestVars, "rejected")],
|
|
77
|
+
};
|
|
78
|
+
const { findByRole } = render(
|
|
79
|
+
<GrantRemovalWorkflow
|
|
80
|
+
grant={{ ...grant, pending_removal: false }}
|
|
81
|
+
actions={{}}
|
|
82
|
+
/>,
|
|
83
|
+
renderOpts
|
|
84
|
+
);
|
|
85
|
+
expect(await findByRole("button")).toHaveClass("red");
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it("Shows workflow button at approved state", async () => {
|
|
89
|
+
const renderOpts = {
|
|
90
|
+
mocks: [latestGrantRequestByGrantMock(latestRequestVars, "approved")],
|
|
91
|
+
};
|
|
92
|
+
const { findByRole } = render(
|
|
93
|
+
<GrantRemovalWorkflow
|
|
94
|
+
grant={{ ...grant, pending_removal: true }}
|
|
95
|
+
actions={{}}
|
|
96
|
+
/>,
|
|
97
|
+
renderOpts
|
|
98
|
+
);
|
|
99
|
+
expect(await findByRole("button")).toHaveClass("brown");
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
it("Workflow bypass: request approved, initially pending_removal true but someone with permissions set pending_removal to false", async () => {
|
|
103
|
+
const renderOpts = {
|
|
104
|
+
mocks: [latestGrantRequestByGrantMock(latestRequestVars, "approved")],
|
|
105
|
+
};
|
|
106
|
+
const { findByRole } = render(
|
|
107
|
+
<GrantRemovalWorkflow
|
|
108
|
+
grant={{ ...grant, pending_removal: false }}
|
|
109
|
+
actions={{}}
|
|
110
|
+
/>,
|
|
111
|
+
renderOpts
|
|
112
|
+
);
|
|
113
|
+
expect(await findByRole("button")).toHaveClass("grey");
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
it("Workflow bypass: request pending, initially pending_removal to false but someone with permissions set pending_removal to true", async () => {
|
|
117
|
+
const renderOpts = {
|
|
118
|
+
mocks: [latestGrantRequestByGrantMock(latestRequestVars, "pending")],
|
|
119
|
+
};
|
|
120
|
+
const { findByRole } = render(
|
|
121
|
+
<GrantRemovalWorkflow
|
|
122
|
+
grant={{ ...grant, pending_removal: true }}
|
|
123
|
+
actions={{}}
|
|
124
|
+
/>,
|
|
125
|
+
renderOpts
|
|
126
|
+
);
|
|
127
|
+
expect(await findByRole("button")).toHaveClass("grey");
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
it("Workflow bypass: request rejected, initially pending_removal to false but someone with permissions set pending_removal to true", async () => {
|
|
131
|
+
const renderOpts = {
|
|
132
|
+
mocks: [latestGrantRequestByGrantMock(latestRequestVars, "rejected")],
|
|
133
|
+
};
|
|
134
|
+
const { findByRole } = render(
|
|
135
|
+
<GrantRemovalWorkflow
|
|
136
|
+
grant={{ ...grant, pending_removal: true }}
|
|
137
|
+
actions={{}}
|
|
138
|
+
/>,
|
|
139
|
+
renderOpts
|
|
140
|
+
);
|
|
141
|
+
expect(await findByRole("button")).toHaveClass("grey");
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
it("Workflow bypass: request processing, initially pending_removal to false but someone with permissions set pending_removal to true", async () => {
|
|
145
|
+
const renderOpts = {
|
|
146
|
+
mocks: [latestGrantRequestByGrantMock(latestRequestVars, "processing")],
|
|
147
|
+
};
|
|
148
|
+
const { findByRole } = render(
|
|
149
|
+
<GrantRemovalWorkflow
|
|
150
|
+
grant={{ ...grant, pending_removal: true }}
|
|
151
|
+
actions={{}}
|
|
152
|
+
/>,
|
|
153
|
+
renderOpts
|
|
154
|
+
);
|
|
155
|
+
expect(await findByRole("button")).toHaveClass("grey");
|
|
156
|
+
});
|
|
157
|
+
});
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React, { Suspense } from "react";
|
|
2
2
|
import { render } from "@truedat/test/render";
|
|
3
3
|
import { GrantRequest } from "../GrantRequest";
|
|
4
|
+
import en from "../../messages/en";
|
|
4
5
|
|
|
5
6
|
describe("<GrantRequest />", () => {
|
|
6
7
|
const grantRequest = {
|
|
@@ -67,6 +68,7 @@ describe("<GrantRequest />", () => {
|
|
|
67
68
|
"grantRequest.summary.emptyApprovals": "empty",
|
|
68
69
|
"grantRequestApproval.header": "approval header",
|
|
69
70
|
"grantRequests.header": "grant requests",
|
|
71
|
+
"request.grantAccess": "Structure access",
|
|
70
72
|
"ruleImplementation.summary.field": "field",
|
|
71
73
|
"ruleImplementation.summary.operator": "operator",
|
|
72
74
|
"ruleImplementation.summary.values": "values",
|
|
@@ -1,15 +1,12 @@
|
|
|
1
1
|
import React, { Suspense } from "react";
|
|
2
2
|
import { render } from "@truedat/test/render";
|
|
3
3
|
import { GrantRequestHeader } from "../GrantRequestHeader";
|
|
4
|
+
import en from "../../messages/en";
|
|
4
5
|
|
|
5
6
|
describe("<GrantRequestHeader />", () => {
|
|
6
7
|
const renderOpts = {
|
|
7
8
|
messages: {
|
|
8
|
-
en
|
|
9
|
-
"grantRequest.header": "header",
|
|
10
|
-
"grantRequest.actions.approve": "approve",
|
|
11
|
-
"grantRequest.actions.reject": "reject",
|
|
12
|
-
},
|
|
9
|
+
en,
|
|
13
10
|
},
|
|
14
11
|
};
|
|
15
12
|
|
|
@@ -98,21 +98,6 @@ describe("<StructureGrantDropdown />", () => {
|
|
|
98
98
|
expect(container).toMatchSnapshot();
|
|
99
99
|
});
|
|
100
100
|
|
|
101
|
-
it("matches the latest snapshot for pendingRemovalGrant state", () => {
|
|
102
|
-
const grantRequest = null;
|
|
103
|
-
const props = {
|
|
104
|
-
...propsBuilder({ pending_removal: true }),
|
|
105
|
-
grantRequest,
|
|
106
|
-
grantRequestStatus: null,
|
|
107
|
-
};
|
|
108
|
-
const { container } = render(
|
|
109
|
-
<StructureGrantDropdown {...props} />,
|
|
110
|
-
renderOpts
|
|
111
|
-
);
|
|
112
|
-
|
|
113
|
-
expect(container).toMatchSnapshot();
|
|
114
|
-
});
|
|
115
|
-
|
|
116
101
|
it("matches the latest snapshot for activeGrant state", () => {
|
|
117
102
|
const grantRequest = null;
|
|
118
103
|
const props = {
|
|
@@ -177,7 +162,7 @@ describe("<StructureGrantDropdown />", () => {
|
|
|
177
162
|
);
|
|
178
163
|
|
|
179
164
|
userEvent.click(
|
|
180
|
-
await findByText(en["grant.actions.
|
|
165
|
+
await findByText(en["grant.actions.viewRequest.confirmation.header"])
|
|
181
166
|
);
|
|
182
167
|
|
|
183
168
|
expect(mockHistory.push).toHaveBeenCalledWith("/grantRequests/8");
|
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { waitFor } from "@testing-library/react";
|
|
3
3
|
import { render } from "@truedat/test/render";
|
|
4
|
-
import {
|
|
4
|
+
import { LATEST_GRANT_REQUEST_BY_DS_QUERY } from "../../api/queries";
|
|
5
5
|
import StructureGrantSummaryButton from "../StructureGrantSummaryButton";
|
|
6
6
|
import en from "../../messages/en";
|
|
7
7
|
|
|
8
8
|
const latestGrantMockBuilder = (status) => ({
|
|
9
|
-
request: { query:
|
|
9
|
+
request: { query: LATEST_GRANT_REQUEST_BY_DS_QUERY },
|
|
10
10
|
result: {
|
|
11
11
|
data: {
|
|
12
12
|
latestGrantRequest: status
|
|
13
13
|
? {
|
|
14
14
|
id: 1,
|
|
15
|
+
requestType: "ACCESS",
|
|
15
16
|
group: {
|
|
16
17
|
grant: {
|
|
17
18
|
id: 1,
|