@truedat/dd 8.9.1 → 8.10.1

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.
@@ -26,65 +26,69 @@ export const GrantRequestsTable = ({
26
26
 
27
27
  const grantRequests = _.propOr([], "data")(searchData);
28
28
 
29
+ const showEmpty = _.isEmpty(grantRequests) && !loading;
30
+
29
31
  return (
30
- <>
31
- {!_.isEmpty(grantRequests) ? (
32
- <Table sortable selectable>
33
- <Table.Header>
34
- <Table.Row>
35
- {approveView ? (
36
- <Table.HeaderCell textAlign="center">
37
- <Checkbox
38
- id="selectGrantRequest"
39
- onChange={addAll}
40
- checked={checkedAll}
41
- />
42
- </Table.HeaderCell>
43
- ) : null}
44
- {columns.map((column, key) => (
45
- <Table.HeaderCell
46
- key={key}
47
- width={column.width}
48
- content={formatMessage({
49
- id: `grantRequest.header.${column.name}`,
50
- defaultMessage: column.name,
51
- })}
52
- sorted={
53
- _.path("sort.name")(column) === sortColumn
54
- ? sortDirection
55
- : null
56
- }
57
- className={_.path("sort.name")(column) ? "" : "disabled"}
58
- onClick={() =>
59
- handleSortSelection(_.path("sort.name")(column))
60
- }
61
- />
62
- ))}
63
- </Table.Row>
64
- </Table.Header>
65
- <Table.Body>
66
- {grantRequests.map((gr, key) => (
67
- <GrantRequestRow
68
- key={key}
69
- checked={isRowChecked && isRowChecked(gr)}
70
- grantRequest={gr}
71
- columns={columns}
72
- approveView={approveView}
73
- onCheckboxChange={() => checkRow && checkRow(gr)}
32
+ <Table sortable={!showEmpty} selectable={!showEmpty}>
33
+ <Table.Header>
34
+ <Table.Row>
35
+ {approveView ? (
36
+ <Table.HeaderCell textAlign="center">
37
+ <Checkbox
38
+ id="selectGrantRequest"
39
+ onChange={addAll}
40
+ checked={checkedAll}
74
41
  />
75
- ))}
76
- </Table.Body>
77
- </Table>
78
- ) : null}
79
- {_.isEmpty(grantRequests) && !loading ? (
80
- <Header as="h4">
81
- <Icon name="search" />
82
- <Header.Content>
83
- {formatMessage({ id: "grantRequests.empty" })}
84
- </Header.Content>
85
- </Header>
86
- ) : null}
87
- </>
42
+ </Table.HeaderCell>
43
+ ) : null}
44
+ {columns.map((column, key) => (
45
+ <Table.HeaderCell
46
+ key={key}
47
+ width={column.width}
48
+ content={formatMessage({
49
+ id: `grantRequest.header.${column.name}`,
50
+ defaultMessage: column.name,
51
+ })}
52
+ sorted={
53
+ _.path("sort.name")(column) === sortColumn
54
+ ? sortDirection
55
+ : null
56
+ }
57
+ className={_.path("sort.name")(column) ? "" : "disabled"}
58
+ onClick={() => handleSortSelection(_.path("sort.name")(column))}
59
+ />
60
+ ))}
61
+ </Table.Row>
62
+ </Table.Header>
63
+ <Table.Body>
64
+ {showEmpty ? (
65
+ <Table.Row>
66
+ <Table.Cell
67
+ colSpan={columns.length + (approveView ? 1 : 0)}
68
+ textAlign="center"
69
+ >
70
+ <Header as="h4">
71
+ <Icon name="search" />
72
+ <Header.Content>
73
+ {formatMessage({ id: "grantRequests.empty" })}
74
+ </Header.Content>
75
+ </Header>
76
+ </Table.Cell>
77
+ </Table.Row>
78
+ ) : (
79
+ grantRequests.map((gr, key) => (
80
+ <GrantRequestRow
81
+ key={key}
82
+ checked={isRowChecked && isRowChecked(gr)}
83
+ grantRequest={gr}
84
+ columns={columns}
85
+ approveView={approveView}
86
+ onCheckboxChange={() => checkRow && checkRow(gr)}
87
+ />
88
+ ))
89
+ )}
90
+ </Table.Body>
91
+ </Table>
88
92
  );
89
93
  };
90
94
 
@@ -40,6 +40,7 @@ describe("<GrantRequestBulkActions />", () => {
40
40
  loading: false,
41
41
  toggleHiddenFilterValue: jest.fn(),
42
42
  resetFilters: jest.fn(),
43
+ setHiddenFilters: jest.fn(),
43
44
  searchMust: { foo: "bar" },
44
45
  cleanQuery: jest.fn(),
45
46
  };
@@ -52,6 +53,7 @@ describe("<GrantRequestBulkActions />", () => {
52
53
  loading: false,
53
54
  toggleHiddenFilterValue: jest.fn(),
54
55
  resetFilters: jest.fn(),
56
+ setHiddenFilters: jest.fn(),
55
57
  searchMust: { foo: "bar" },
56
58
  cleanQuery: jest.fn(),
57
59
  };
@@ -88,6 +90,8 @@ describe("<GrantRequestBulkActions />", () => {
88
90
  renderOpts,
89
91
  );
90
92
  await waitForLoad(rendered);
93
+ const user = userEvent.setup({ delay: null });
94
+ await user.click(rendered.getByRole("option", { name: /role1/i }));
91
95
  expect(
92
96
  rendered.getByRole("button", { name: /approve_request/i }),
93
97
  ).toBeEnabled();
@@ -5,11 +5,11 @@ import { linkTo } from "@truedat/core/routes";
5
5
 
6
6
  import GrantRequestRow from "../GrantRequestRow";
7
7
 
8
- const mockHistory = jest.fn();
8
+ const mockNavigate = jest.fn();
9
9
 
10
10
  jest.mock("react-router", () => ({
11
11
  ...jest.requireActual("react-router"),
12
- useNavigate: () => mockHistory,
12
+ useNavigate: () => mockNavigate,
13
13
  }));
14
14
 
15
15
  const columns = [
@@ -33,6 +33,10 @@ describe("<GrantRequestRow />", () => {
33
33
  const onCheckboxChange = jest.fn();
34
34
  const onClick = jest.fn();
35
35
 
36
+ beforeEach(() => {
37
+ mockNavigate.mockClear();
38
+ });
39
+
36
40
  const props = {
37
41
  active: true,
38
42
  checked: true,
@@ -90,7 +94,7 @@ describe("<GrantRequestRow />", () => {
90
94
  });
91
95
  });
92
96
 
93
- it("navigates to grant request", async () => {
97
+ it("navigates to grant request in the same window", async () => {
94
98
  const rendered = render(
95
99
  <table>
96
100
  <tbody>
@@ -105,6 +109,6 @@ describe("<GrantRequestRow />", () => {
105
109
  });
106
110
 
107
111
  await user.click(rendered.queryByText(/blah/i));
108
- expect(mockHistory).toHaveBeenCalledWith(linkTo.GRANT_REQUEST({ id: 1 }));
112
+ expect(mockNavigate).toHaveBeenCalledWith(linkTo.GRANT_REQUEST({ id: 1 }));
109
113
  });
110
114
  });
@@ -0,0 +1,198 @@
1
+ import { render, waitForLoad } from "@truedat/test/render";
2
+ import { screen } from "@testing-library/react";
3
+ import SearchContext from "@truedat/core/search/SearchContext";
4
+ import { GrantRequestsDownloadButton } from "../GrantRequestsDownloadButton";
5
+
6
+ jest.mock("@truedat/dd/hooks/useGrantRequest", () => ({
7
+ useGrantRequestsDownload: jest.fn(() => ({
8
+ trigger: jest.fn(),
9
+ isMutating: false,
10
+ })),
11
+ }));
12
+
13
+ describe("<GrantRequestsDownloadButton />", () => {
14
+ const renderOpts = {
15
+ messages: {
16
+ en: {
17
+ "grantRequest.actions.download.tooltip": "Descargar / Download",
18
+ "grantRequest.actions.download.popup":
19
+ "Search or apply a filter to download grant requests",
20
+ "grantRequests.props.current_status": "Status",
21
+ "grantRequests.props.user_full_name": "User",
22
+ "grantRequests.props.created_by_full_name": "Created by",
23
+ "grantRequests.props.structure_external_id": "Structure",
24
+ "grantRequests.props.domains": "Domains",
25
+ "grantRequests.props.system_name": "System",
26
+ "grantRequests.props.structure_path": "Path",
27
+ "grantRequests.props.request_type": "Request type",
28
+ },
29
+ },
30
+ };
31
+
32
+ const buildSearchContext = (filterParams = {}) => ({
33
+ searchData: {
34
+ data: [
35
+ {
36
+ id: 1,
37
+ current_status: "pending",
38
+ user: { full_name: "Jane Doe" },
39
+ created_by: { full_name: "Admin" },
40
+ data_structure_version: {
41
+ name: "country",
42
+ path: ["postgres", "public"],
43
+ domain: { name: "demo", id: 5 },
44
+ system: { name: "PostgreSQL", id: 7 },
45
+ external_id: "postgres/postgres/public/country",
46
+ data_structure_id: 241939,
47
+ },
48
+ },
49
+ ],
50
+ },
51
+ loading: false,
52
+ filterParams,
53
+ });
54
+
55
+ it("matches the latest snapshot", async () => {
56
+ const props = {
57
+ hasFilterApplied: true,
58
+ searchBy: "approve",
59
+ setDownloading: jest.fn(),
60
+ };
61
+
62
+ const rendered = render(
63
+ <SearchContext value={buildSearchContext({ status: ["pending"] })}>
64
+ <GrantRequestsDownloadButton {...props} />
65
+ </SearchContext>,
66
+ renderOpts,
67
+ );
68
+
69
+ await waitForLoad(rendered);
70
+ expect(rendered.container).toMatchSnapshot();
71
+ });
72
+
73
+ it("is enabled if there are results and a filter applied", async () => {
74
+ const props = {
75
+ hasFilterApplied: true,
76
+ searchBy: "all",
77
+ setDownloading: jest.fn(),
78
+ };
79
+
80
+ render(
81
+ <SearchContext value={buildSearchContext({ status: ["pending"] })}>
82
+ <GrantRequestsDownloadButton {...props} />
83
+ </SearchContext>,
84
+ renderOpts,
85
+ );
86
+
87
+ const button = await screen.findByRole("button");
88
+ expect(button).toBeEnabled();
89
+ });
90
+
91
+ it("is disabled when there are no results", async () => {
92
+ const props = {
93
+ hasFilterApplied: true,
94
+ searchBy: "all",
95
+ setDownloading: jest.fn(),
96
+ };
97
+
98
+ render(
99
+ <SearchContext
100
+ value={{
101
+ searchData: { data: [] },
102
+ loading: false,
103
+ filterParams: { status: ["pending"] },
104
+ }}
105
+ >
106
+ <GrantRequestsDownloadButton {...props} />
107
+ </SearchContext>,
108
+ renderOpts,
109
+ );
110
+
111
+ const button = await screen.getByRole("button");
112
+ expect(button).toBeDisabled();
113
+ });
114
+
115
+ it("is disabled when no filter is applied", async () => {
116
+ const props = {
117
+ hasFilterApplied: false,
118
+ searchBy: "all",
119
+ setDownloading: jest.fn(),
120
+ };
121
+
122
+ render(
123
+ <SearchContext value={buildSearchContext({})}>
124
+ <GrantRequestsDownloadButton {...props} />
125
+ </SearchContext>,
126
+ renderOpts,
127
+ );
128
+
129
+ const button = await screen.getByRole("button");
130
+ expect(button).toBeDisabled();
131
+ });
132
+
133
+ it("calls triggerDownload with search_by 'approve' from approve view", async () => {
134
+ const triggerMock = jest.fn();
135
+ const grantRequestHook = require("@truedat/dd/hooks/useGrantRequest");
136
+ grantRequestHook.useGrantRequestsDownload.mockReturnValue({
137
+ trigger: triggerMock,
138
+ isMutating: false,
139
+ });
140
+
141
+ const props = {
142
+ hasFilterApplied: true,
143
+ searchBy: "approve",
144
+ setDownloading: jest.fn(),
145
+ };
146
+
147
+ render(
148
+ <SearchContext value={buildSearchContext({ status: ["pending"] })}>
149
+ <GrantRequestsDownloadButton {...props} />
150
+ </SearchContext>,
151
+ renderOpts,
152
+ );
153
+
154
+ const button = await screen.findByRole("button");
155
+ button.click();
156
+
157
+ expect(triggerMock).toHaveBeenCalledWith(
158
+ expect.objectContaining({
159
+ search_by: "approve",
160
+ header_labels: expect.any(Object),
161
+ lang: "en",
162
+ status: ["pending"],
163
+ }),
164
+ );
165
+ });
166
+
167
+ it("calls triggerDownload with search_by 'all' from search view", async () => {
168
+ const triggerMock = jest.fn();
169
+ const grantRequestHook = require("@truedat/dd/hooks/useGrantRequest");
170
+ grantRequestHook.useGrantRequestsDownload.mockReturnValue({
171
+ trigger: triggerMock,
172
+ isMutating: false,
173
+ });
174
+
175
+ const props = {
176
+ hasFilterApplied: true,
177
+ searchBy: "all",
178
+ setDownloading: jest.fn(),
179
+ };
180
+
181
+ render(
182
+ <SearchContext value={buildSearchContext({ query: "foo" })}>
183
+ <GrantRequestsDownloadButton {...props} />
184
+ </SearchContext>,
185
+ renderOpts,
186
+ );
187
+
188
+ const button = await screen.findByRole("button");
189
+ button.click();
190
+
191
+ expect(triggerMock).toHaveBeenCalledWith(
192
+ expect.objectContaining({
193
+ search_by: "all",
194
+ query: "foo",
195
+ }),
196
+ );
197
+ });
198
+ });
@@ -4,7 +4,7 @@ exports[`<GrantRequestBulkActions /> matches the latest snapshot 1`] = `
4
4
  <div>
5
5
  <div
6
6
  aria-expanded="false"
7
- class="ui selection dropdown grant-requests-bulk-role-selector"
7
+ class="ui selection dropdown grant-requests-bulk-role-selector "
8
8
  role="listbox"
9
9
  tabindex="0"
10
10
  >
@@ -23,6 +23,20 @@ exports[`<GrantRequestBulkActions /> matches the latest snapshot 1`] = `
23
23
  <div
24
24
  class="menu transition"
25
25
  >
26
+ <div
27
+ aria-checked="false"
28
+ aria-disabled="true"
29
+ aria-selected="false"
30
+ class="disabled item header"
31
+ role="option"
32
+ style="pointer-events: all;"
33
+ >
34
+ <span
35
+ class="text"
36
+ >
37
+ select
38
+ </span>
39
+ </div>
26
40
  <div
27
41
  aria-checked="true"
28
42
  aria-selected="true"
@@ -52,12 +66,12 @@ exports[`<GrantRequestBulkActions /> matches the latest snapshot 1`] = `
52
66
  </div>
53
67
  </div>
54
68
  <button
55
- class="ui primary button button icon group-actions"
69
+ class="ui primary button button icon group-actions grant-requests-approval-button"
56
70
  >
57
71
  approve_request
58
72
  </button>
59
73
  <button
60
- class="ui secondary button button icon group-actions"
74
+ class="ui secondary button button icon group-actions grant-requests-approval-button"
61
75
  >
62
76
  reject
63
77
  </button>
@@ -3,7 +3,7 @@
3
3
  exports[`<GrantRequestBulkApprovalPopup /> matches the latest snapshot 1`] = `
4
4
  <div>
5
5
  <button
6
- class="ui primary button button icon group-actions"
6
+ class="ui primary button button icon group-actions grant-requests-approval-button"
7
7
  >
8
8
  button content
9
9
  </button>
@@ -0,0 +1,16 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`<GrantRequestsDownloadButton /> matches the latest snapshot 1`] = `
4
+ <div>
5
+ <button
6
+ class="ui icon secondary button"
7
+ data-position="top right"
8
+ data-tooltip="Descargar / Download"
9
+ >
10
+ <i
11
+ aria-hidden="true"
12
+ class="download icon"
13
+ />
14
+ </button>
15
+ </div>
16
+ `;
@@ -8,7 +8,12 @@ exports[`<GrantRequestsLabelResults /> When is loading 1`] = `
8
8
  <div
9
9
  class="ui label"
10
10
  >
11
- searching
11
+ results
12
+ </div>
13
+ <div
14
+ class="ui label"
15
+ >
16
+ selected
12
17
  </div>
13
18
  </div>
14
19
  ,