@truedat/dd 8.12.2 → 8.12.4
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 +3 -3
- package/src/api/__tests__/queries.spec.js +55 -0
- package/src/api/queries.js +31 -0
- package/src/components/Grant.js +106 -16
- package/src/components/GrantRequest.js +2 -2
- package/src/components/GrantRequestBulkApprovalPopup.js +0 -1
- package/src/components/GrantsDownloadButton.js +9 -1
- package/src/components/GrantsTable.js +4 -1
- package/src/components/StructureFields.js +7 -4
- package/src/components/StructureGrantCartUserSelector.js +29 -4
- package/src/components/StructureGrantDropdown.js +7 -1
- package/src/components/StructureGrants.js +4 -1
- package/src/components/StructuresUpdateOption.js +2 -2
- package/src/components/SystemStructures.js +3 -3
- package/src/components/__tests__/CatalogViewConfigForm.spec.js +2 -0
- package/src/components/__tests__/EditDomainForm.spec.js +3 -1
- package/src/components/__tests__/Grant.spec.js +171 -0
- package/src/components/__tests__/GrantApprovalRuleForm.spec.js +2 -0
- package/src/components/__tests__/GrantApprovalRuleNew.spec.js +8 -0
- package/src/components/__tests__/GrantApprovalRules.spec.js +4 -0
- package/src/components/__tests__/GrantRequest.spec.js +4 -4
- package/src/components/__tests__/GrantRequestBulkActions.spec.js +1 -4
- package/src/components/__tests__/GrantRequestsSearchResults.spec.js +2 -0
- package/src/components/__tests__/GrantsDownloadButton.spec.js +58 -2
- package/src/components/__tests__/GrantsTable.spec.js +22 -2
- package/src/components/__tests__/LineageDefs.spec.js +6 -1
- package/src/components/__tests__/LineageForm.spec.js +1 -0
- package/src/components/__tests__/LineageGraphToolbar.spec.js +19 -17
- package/src/components/__tests__/LineageInspectorPanel.spec.js +17 -9
- package/src/components/__tests__/ProfileGroup.spec.js +7 -1
- package/src/components/__tests__/ReferenceDatasetForm.spec.js +2 -0
- package/src/components/__tests__/ReferenceDatasetRoutes.spec.js +9 -0
- package/src/components/__tests__/StructureGrantCartCheckout.spec.js +39 -1
- package/src/components/__tests__/StructureGrantCartInformation.spec.js +5 -2
- package/src/components/__tests__/StructureGrantCartUserSelector.spec.js +128 -0
- package/src/components/__tests__/StructureGrantDropdown.spec.js +92 -0
- package/src/components/__tests__/StructureGrantListButton.spec.js +70 -0
- package/src/components/__tests__/StructureGrantSummaryButton.spec.js +36 -1
- package/src/components/__tests__/StructureGrants.spec.js +12 -0
- package/src/components/__tests__/StructureRelationRow.spec.js +72 -4
- package/src/components/__tests__/StructureRelations.spec.js +18 -0
- package/src/components/__tests__/StructureRoles.spec.js +9 -0
- package/src/components/__tests__/StructureRow.spec.js +13 -4
- package/src/components/__tests__/StructureSelector.spec.js +2 -0
- package/src/components/__tests__/StructureTag.spec.js +2 -0
- package/src/components/__tests__/StructureTagForm.spec.js +2 -0
- package/src/components/__tests__/StructureType.spec.js +3 -1
- package/src/components/__tests__/StructureTypeForm.spec.js +3 -1
- package/src/components/__tests__/StructureView.spec.js +17 -1
- package/src/components/__tests__/StructuresGrantRequestView.spec.js +2 -0
- package/src/components/__tests__/StructuresView.spec.js +2 -1
- package/src/components/__tests__/Tag.spec.js +4 -1
- package/src/components/__tests__/Tags.spec.js +7 -1
- package/src/components/__tests__/__snapshots__/GrantsTable.spec.js.snap +34 -2
- package/src/components/__tests__/__snapshots__/LineageDefs.spec.js.snap +32 -30
- package/src/components/__tests__/__snapshots__/StructureFields.spec.js.snap +1 -16
- package/src/components/__tests__/__snapshots__/StructureRelationRow.spec.js.snap +23 -19
- package/src/components/__tests__/__snapshots__/StructureRow.spec.js.snap +28 -24
- package/src/components/__tests__/__snapshots__/StructuresUpdateOption.spec.js.snap +7 -3
- package/src/messages/en.js +2 -2
- package/src/messages/es.js +2 -2
- package/src/reducers/__tests__/grantRequestsCart.spec.js +17 -0
- package/src/reducers/__tests__/structureRelations.spec.js +28 -0
- package/src/reducers/grantRequestsCart.js +3 -0
- package/src/selectors/__tests__/__snapshots__/getGrantsColumns.spec.js.snap +1 -9
- package/src/selectors/__tests__/getGrantRequestsSearchColumns.spec.js +11 -4
- package/src/selectors/__tests__/getGrantsColumns.spec.js +295 -0
- package/src/selectors/getBusinessConceptsLinksToStructuresColumnsSelector.js +3 -5
- package/src/selectors/getGrantRequestsSearchColumns.js +3 -5
- package/src/selectors/getGrantsColumns.js +85 -11
- package/src/selectors/getLinkedImplementationsToStructuresColumns.js +3 -7
- package/src/selectors/getStructureFieldColumns.js +7 -6
- package/src/selectors/getStructureProperties.js +2 -5
- package/src/selectors/getStructuresUploadEventColumns.js +2 -7
- package/src/selectors/structureColumnsSelector.js +13 -16
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import userEvent from "@testing-library/user-event";
|
|
2
2
|
import { render, waitForLoad } from "@truedat/test/render";
|
|
3
3
|
import { singleTemplateMock, domainsMock } from "@truedat/test/mocks";
|
|
4
|
+
import { DOMAINS_QUERY, FUNCTIONS_QUERY } from "@truedat/core/api/queries";
|
|
4
5
|
import { StructureGrantCartCheckout } from "../StructureGrantCartCheckout";
|
|
5
6
|
|
|
6
7
|
jest.mock("@truedat/core/webContext", () => ({
|
|
@@ -23,6 +24,10 @@ jest.mock("@truedat/auth/hooks/useUsers", () => ({
|
|
|
23
24
|
useGrantRequestableUsers: jest.fn(),
|
|
24
25
|
}));
|
|
25
26
|
|
|
27
|
+
jest.mock("@truedat/auth/hooks/useRoles", () => ({
|
|
28
|
+
useRoles: () => ({ data: undefined }),
|
|
29
|
+
}));
|
|
30
|
+
|
|
26
31
|
jest.mock("react-redux", () => {
|
|
27
32
|
const actual = jest.requireActual("react-redux");
|
|
28
33
|
return {
|
|
@@ -177,6 +182,17 @@ const grantRequestsCartSingleDomain = {
|
|
|
177
182
|
};
|
|
178
183
|
|
|
179
184
|
describe("StructureGrantCartCheckout", () => {
|
|
185
|
+
const domainQueryErrorMock = {
|
|
186
|
+
request: {
|
|
187
|
+
query: DOMAINS_QUERY,
|
|
188
|
+
variables: { action: "createForeignGrantRequest" },
|
|
189
|
+
},
|
|
190
|
+
error: new Error("Domains are not used by this checkout test"),
|
|
191
|
+
};
|
|
192
|
+
const functionsQueryErrorMock = {
|
|
193
|
+
request: { query: FUNCTIONS_QUERY },
|
|
194
|
+
error: new Error("Functions are not used by this checkout test"),
|
|
195
|
+
};
|
|
180
196
|
const mockTrigger = jest.fn().mockResolvedValue({});
|
|
181
197
|
const mockDispatch = jest.fn();
|
|
182
198
|
const mockInitGroupTemplates = jest.fn();
|
|
@@ -208,7 +224,11 @@ describe("StructureGrantCartCheckout", () => {
|
|
|
208
224
|
|
|
209
225
|
const variables = { scope: "gr" };
|
|
210
226
|
const renderOpts = {
|
|
211
|
-
mocks: [
|
|
227
|
+
mocks: [
|
|
228
|
+
singleTemplateMock(variables),
|
|
229
|
+
functionsQueryErrorMock,
|
|
230
|
+
domainQueryErrorMock,
|
|
231
|
+
],
|
|
212
232
|
};
|
|
213
233
|
|
|
214
234
|
it("matches snapshot when modification grant (single flow)", async () => {
|
|
@@ -272,6 +292,8 @@ describe("StructureGrantCartCheckout", () => {
|
|
|
272
292
|
mocks: [
|
|
273
293
|
singleTemplateMock({ scope: "gr" }),
|
|
274
294
|
domainsMock({ action: "createForeignGrantRequest" }),
|
|
295
|
+
functionsQueryErrorMock,
|
|
296
|
+
domainQueryErrorMock,
|
|
275
297
|
],
|
|
276
298
|
};
|
|
277
299
|
const rendered = render(
|
|
@@ -297,6 +319,8 @@ describe("StructureGrantCartCheckout", () => {
|
|
|
297
319
|
mocks: [
|
|
298
320
|
singleTemplateMock({ scope: "gr" }),
|
|
299
321
|
domainsMock({ action: "createForeignGrantRequest" }),
|
|
322
|
+
functionsQueryErrorMock,
|
|
323
|
+
domainQueryErrorMock,
|
|
300
324
|
],
|
|
301
325
|
};
|
|
302
326
|
const rendered = render(
|
|
@@ -324,6 +348,8 @@ describe("StructureGrantCartCheckout", () => {
|
|
|
324
348
|
mocks: [
|
|
325
349
|
singleTemplateMock({ scope: "gr" }),
|
|
326
350
|
domainsMock({ action: "createForeignGrantRequest" }),
|
|
351
|
+
functionsQueryErrorMock,
|
|
352
|
+
domainQueryErrorMock,
|
|
327
353
|
],
|
|
328
354
|
};
|
|
329
355
|
const rendered = render(
|
|
@@ -348,6 +374,8 @@ describe("StructureGrantCartCheckout", () => {
|
|
|
348
374
|
mocks: [
|
|
349
375
|
singleTemplateMock({ scope: "gr" }),
|
|
350
376
|
domainsMock({ action: "createForeignGrantRequest" }),
|
|
377
|
+
functionsQueryErrorMock,
|
|
378
|
+
domainQueryErrorMock,
|
|
351
379
|
],
|
|
352
380
|
};
|
|
353
381
|
const rendered = render(
|
|
@@ -373,6 +401,8 @@ describe("StructureGrantCartCheckout", () => {
|
|
|
373
401
|
mocks: [
|
|
374
402
|
singleTemplateMock({ scope: "gr" }),
|
|
375
403
|
domainsMock({ action: "createForeignGrantRequest" }),
|
|
404
|
+
functionsQueryErrorMock,
|
|
405
|
+
domainQueryErrorMock,
|
|
376
406
|
],
|
|
377
407
|
};
|
|
378
408
|
const rendered = render(
|
|
@@ -408,6 +438,8 @@ describe("StructureGrantCartCheckout", () => {
|
|
|
408
438
|
mocks: [
|
|
409
439
|
singleTemplateMock({ scope: "gr" }),
|
|
410
440
|
domainsMock({ action: "createForeignGrantRequest" }),
|
|
441
|
+
functionsQueryErrorMock,
|
|
442
|
+
domainQueryErrorMock,
|
|
411
443
|
],
|
|
412
444
|
};
|
|
413
445
|
const rendered = render(
|
|
@@ -456,6 +488,8 @@ describe("StructureGrantCartCheckout", () => {
|
|
|
456
488
|
mocks: [
|
|
457
489
|
singleTemplateMock({ scope: "gr" }),
|
|
458
490
|
domainsMock({ action: "createForeignGrantRequest" }),
|
|
491
|
+
functionsQueryErrorMock,
|
|
492
|
+
domainQueryErrorMock,
|
|
459
493
|
],
|
|
460
494
|
};
|
|
461
495
|
|
|
@@ -544,6 +578,8 @@ describe("StructureGrantCartCheckout", () => {
|
|
|
544
578
|
mocks: [
|
|
545
579
|
singleTemplateMock({ scope: "gr" }),
|
|
546
580
|
domainsMock({ action: "createForeignGrantRequest" }),
|
|
581
|
+
functionsQueryErrorMock,
|
|
582
|
+
domainQueryErrorMock,
|
|
547
583
|
],
|
|
548
584
|
};
|
|
549
585
|
const rendered = render(
|
|
@@ -598,6 +634,8 @@ describe("StructureGrantCartCheckout", () => {
|
|
|
598
634
|
mocks: [
|
|
599
635
|
singleTemplateMock({ scope: "gr" }),
|
|
600
636
|
domainsMock({ action: "createForeignGrantRequest" }),
|
|
637
|
+
functionsQueryErrorMock,
|
|
638
|
+
domainQueryErrorMock,
|
|
601
639
|
],
|
|
602
640
|
};
|
|
603
641
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { render, waitForLoad } from "@truedat/test/render";
|
|
2
|
-
import { singleTemplateMock } from "@truedat/test/mocks";
|
|
2
|
+
import { singleTemplateMock, domainsMock } from "@truedat/test/mocks";
|
|
3
3
|
import { StructureGrantCartInformation } from "../StructureGrantCartInformation";
|
|
4
4
|
|
|
5
5
|
jest.mock("@truedat/auth/hooks/useRoles", () => {
|
|
@@ -38,7 +38,10 @@ describe("<StructureGrantCartInformation />", () => {
|
|
|
38
38
|
};
|
|
39
39
|
|
|
40
40
|
const renderOpts = {
|
|
41
|
-
mocks: [
|
|
41
|
+
mocks: [
|
|
42
|
+
singleTemplateMock(variables),
|
|
43
|
+
domainsMock({ action: "createForeignGrantRequest" }, []),
|
|
44
|
+
],
|
|
42
45
|
};
|
|
43
46
|
|
|
44
47
|
it("matches the latest snapshot", async () => {
|
|
@@ -4,6 +4,10 @@ import { render, waitForLoad } from "@truedat/test/render";
|
|
|
4
4
|
import { useGrantRequestableUsers } from "@truedat/auth/hooks/useUsers";
|
|
5
5
|
import StructureGrantCartUserSelector from "../StructureGrantCartUserSelector";
|
|
6
6
|
|
|
7
|
+
jest.mock("@truedat/auth/hooks/useRoles", () => ({
|
|
8
|
+
useRoles: () => ({ data: undefined }),
|
|
9
|
+
}));
|
|
10
|
+
|
|
7
11
|
jest.mock("@truedat/auth/hooks/useUsers", () => ({
|
|
8
12
|
useGrantRequestableUsers: jest.fn(() => ({
|
|
9
13
|
users: [
|
|
@@ -179,4 +183,128 @@ describe("<StructureGrantCartUserSelector />", () => {
|
|
|
179
183
|
);
|
|
180
184
|
expect(payloads.some((payload) => payload?.id === "group:10")).toBe(false);
|
|
181
185
|
});
|
|
186
|
+
|
|
187
|
+
it("preselects user group when modificationGrant has user_group_id", async () => {
|
|
188
|
+
const dispatch = jest.fn();
|
|
189
|
+
useGrantRequestableUsers.mockImplementation(() => ({
|
|
190
|
+
users: [{ id: 1, full_name: "foo user" }],
|
|
191
|
+
groups: [{ id: 10, name: "foo", alias: "bar" }],
|
|
192
|
+
trigger: jest.fn(),
|
|
193
|
+
}));
|
|
194
|
+
|
|
195
|
+
const rendered = render(<StructureGrantCartUserSelector />, {
|
|
196
|
+
state: {
|
|
197
|
+
grantRequestsCart: {
|
|
198
|
+
modificationGrant: {
|
|
199
|
+
user_group_id: 10,
|
|
200
|
+
user_group: { id: 10, name: "foo", alias: "bar" },
|
|
201
|
+
user_id: null,
|
|
202
|
+
},
|
|
203
|
+
},
|
|
204
|
+
},
|
|
205
|
+
dispatch,
|
|
206
|
+
});
|
|
207
|
+
await waitForLoad(rendered);
|
|
208
|
+
|
|
209
|
+
await waitFor(() => {
|
|
210
|
+
const payloads = dispatch.mock.calls.map(
|
|
211
|
+
([action]) => action?.payload ?? action,
|
|
212
|
+
);
|
|
213
|
+
expect(payloads.some((payload) => payload?.user_group_id === 10)).toBe(
|
|
214
|
+
true,
|
|
215
|
+
);
|
|
216
|
+
});
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
it("shows group alias in the modification header", async () => {
|
|
220
|
+
const rendered = render(<StructureGrantCartUserSelector />, {
|
|
221
|
+
state: {
|
|
222
|
+
grantRequestsCart: {
|
|
223
|
+
modificationGrant: {
|
|
224
|
+
user_group_id: 10,
|
|
225
|
+
user_group: { id: 10, alias: "bar", name: "foo" },
|
|
226
|
+
user_id: null,
|
|
227
|
+
},
|
|
228
|
+
},
|
|
229
|
+
},
|
|
230
|
+
messages: {
|
|
231
|
+
en: {
|
|
232
|
+
"grantRequestCart.user.label": "Request for:",
|
|
233
|
+
},
|
|
234
|
+
},
|
|
235
|
+
});
|
|
236
|
+
await waitForLoad(rendered);
|
|
237
|
+
|
|
238
|
+
expect(rendered.getByText(/bar/i)).toBeInTheDocument();
|
|
239
|
+
expect(rendered.queryByText(/undefined/i)).not.toBeInTheDocument();
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
it("shows group name in the modification header when alias is empty", async () => {
|
|
243
|
+
const rendered = render(<StructureGrantCartUserSelector />, {
|
|
244
|
+
state: {
|
|
245
|
+
grantRequestsCart: {
|
|
246
|
+
modificationGrant: {
|
|
247
|
+
user_group_id: 10,
|
|
248
|
+
user_group: { id: 10, alias: "", name: "foo" },
|
|
249
|
+
user_id: null,
|
|
250
|
+
},
|
|
251
|
+
},
|
|
252
|
+
},
|
|
253
|
+
messages: {
|
|
254
|
+
en: {
|
|
255
|
+
"grantRequestCart.user.label": "Request for:",
|
|
256
|
+
},
|
|
257
|
+
},
|
|
258
|
+
});
|
|
259
|
+
await waitForLoad(rendered);
|
|
260
|
+
|
|
261
|
+
expect(rendered.getByText(/foo/i)).toBeInTheDocument();
|
|
262
|
+
expect(rendered.queryByText(/bar/i)).not.toBeInTheDocument();
|
|
263
|
+
expect(rendered.queryByText(/undefined/i)).not.toBeInTheDocument();
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
it("shows deleted group in the modification header when the group is missing", async () => {
|
|
267
|
+
const rendered = render(<StructureGrantCartUserSelector />, {
|
|
268
|
+
state: {
|
|
269
|
+
grantRequestsCart: {
|
|
270
|
+
modificationGrant: {
|
|
271
|
+
user_group_id: 10,
|
|
272
|
+
user_group: null,
|
|
273
|
+
user_id: null,
|
|
274
|
+
},
|
|
275
|
+
},
|
|
276
|
+
},
|
|
277
|
+
messages: {
|
|
278
|
+
en: {
|
|
279
|
+
"grantRequestCart.user.label": "Request for:",
|
|
280
|
+
"deleted.group": "Deleted group",
|
|
281
|
+
},
|
|
282
|
+
},
|
|
283
|
+
});
|
|
284
|
+
await waitForLoad(rendered);
|
|
285
|
+
|
|
286
|
+
expect(rendered.getByText(/deleted group/i)).toBeInTheDocument();
|
|
287
|
+
expect(rendered.queryByText(/undefined/i)).not.toBeInTheDocument();
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
it("shows user full name in the modification header for a personal grant", async () => {
|
|
291
|
+
const rendered = render(<StructureGrantCartUserSelector />, {
|
|
292
|
+
state: {
|
|
293
|
+
grantRequestsCart: {
|
|
294
|
+
modificationGrant: {
|
|
295
|
+
user: { full_name: "foo user" },
|
|
296
|
+
},
|
|
297
|
+
},
|
|
298
|
+
},
|
|
299
|
+
messages: {
|
|
300
|
+
en: {
|
|
301
|
+
"grantRequestCart.user.label": "Request for:",
|
|
302
|
+
},
|
|
303
|
+
},
|
|
304
|
+
});
|
|
305
|
+
await waitForLoad(rendered);
|
|
306
|
+
|
|
307
|
+
expect(rendered.getByText(/foo user/i)).toBeInTheDocument();
|
|
308
|
+
expect(rendered.queryByText(/undefined/i)).not.toBeInTheDocument();
|
|
309
|
+
});
|
|
182
310
|
});
|
|
@@ -276,4 +276,96 @@ describe("<StructureGrantDropdown />", () => {
|
|
|
276
276
|
rendered.getByText(/grant.actions.viewrequest.confirmation.header/i),
|
|
277
277
|
).toBeInTheDocument();
|
|
278
278
|
});
|
|
279
|
+
|
|
280
|
+
it("shows users icon and change action for active group grant", async () => {
|
|
281
|
+
const user = userEvent.setup({ delay: null });
|
|
282
|
+
const grant = {
|
|
283
|
+
pending_removal: false,
|
|
284
|
+
user_group_id: 10,
|
|
285
|
+
user_group: { id: 10, name: "foo", alias: "bar" },
|
|
286
|
+
};
|
|
287
|
+
const props = {
|
|
288
|
+
...propsBuilder(grant),
|
|
289
|
+
grantRequest: null,
|
|
290
|
+
grantRequestStatus: null,
|
|
291
|
+
};
|
|
292
|
+
const rendered = render(<StructureGrantDropdown {...props} />);
|
|
293
|
+
await waitForLoad(rendered);
|
|
294
|
+
|
|
295
|
+
expect(
|
|
296
|
+
rendered.container.querySelector(".button.group-actions .users.icon"),
|
|
297
|
+
).not.toBeInTheDocument();
|
|
298
|
+
|
|
299
|
+
fireEvent.mouseOver(await rendered.findByRole("listbox"));
|
|
300
|
+
expect(
|
|
301
|
+
await rendered.findByText(/structure.grant.has_grant/i),
|
|
302
|
+
).toBeInTheDocument();
|
|
303
|
+
expect(
|
|
304
|
+
rendered.baseElement.querySelector(".users.icon"),
|
|
305
|
+
).toBeInTheDocument();
|
|
306
|
+
|
|
307
|
+
await user.click(await rendered.findByRole("listbox"));
|
|
308
|
+
expect(
|
|
309
|
+
rendered.getByText(/structure.grant.request_grant_change/i),
|
|
310
|
+
).toBeInTheDocument();
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
it("shows users icon in popup for pending group grant request", async () => {
|
|
314
|
+
const grantRequest = {
|
|
315
|
+
group: {
|
|
316
|
+
user_group_id: 10,
|
|
317
|
+
_embedded: {
|
|
318
|
+
user_group: { id: 10, name: "foo" },
|
|
319
|
+
},
|
|
320
|
+
},
|
|
321
|
+
};
|
|
322
|
+
const props = {
|
|
323
|
+
...propsBuilder(null),
|
|
324
|
+
grantRequest,
|
|
325
|
+
grantRequestStatus: "pending",
|
|
326
|
+
};
|
|
327
|
+
const rendered = render(<StructureGrantDropdown {...props} />, {
|
|
328
|
+
state: { authentication: { user_name: "foo" } },
|
|
329
|
+
});
|
|
330
|
+
await waitForLoad(rendered);
|
|
331
|
+
|
|
332
|
+
expect(
|
|
333
|
+
rendered.container.querySelector(".button.group-actions .users.icon"),
|
|
334
|
+
).not.toBeInTheDocument();
|
|
335
|
+
|
|
336
|
+
fireEvent.mouseOver(await rendered.findByRole("listbox"));
|
|
337
|
+
expect(
|
|
338
|
+
await rendered.findByText(/structure.grant.requested_access/i),
|
|
339
|
+
).toBeInTheDocument();
|
|
340
|
+
expect(
|
|
341
|
+
rendered.baseElement.querySelector(".users.icon"),
|
|
342
|
+
).toBeInTheDocument();
|
|
343
|
+
});
|
|
344
|
+
|
|
345
|
+
it("shows users icon in popup for active group grant", async () => {
|
|
346
|
+
const grant = {
|
|
347
|
+
pending_removal: false,
|
|
348
|
+
user_group_id: 10,
|
|
349
|
+
user_group: { id: 10, name: "foo", alias: "bar" },
|
|
350
|
+
};
|
|
351
|
+
const props = {
|
|
352
|
+
...propsBuilder(grant),
|
|
353
|
+
grantRequest: null,
|
|
354
|
+
grantRequestStatus: null,
|
|
355
|
+
};
|
|
356
|
+
const rendered = render(<StructureGrantDropdown {...props} />);
|
|
357
|
+
await waitForLoad(rendered);
|
|
358
|
+
|
|
359
|
+
expect(
|
|
360
|
+
rendered.container.querySelector(".button.group-actions .users.icon"),
|
|
361
|
+
).not.toBeInTheDocument();
|
|
362
|
+
|
|
363
|
+
fireEvent.mouseOver(await rendered.findByRole("listbox"));
|
|
364
|
+
expect(
|
|
365
|
+
await rendered.findByText(/structure.grant.has_grant/i),
|
|
366
|
+
).toBeInTheDocument();
|
|
367
|
+
expect(
|
|
368
|
+
rendered.baseElement.querySelector(".users.icon"),
|
|
369
|
+
).toBeInTheDocument();
|
|
370
|
+
});
|
|
279
371
|
});
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import userEvent from "@testing-library/user-event";
|
|
2
|
+
import { fireEvent } from "@testing-library/react";
|
|
2
3
|
import { render, waitForLoad } from "@truedat/test/render";
|
|
3
4
|
import SearchContextWrapper from "@truedat/core/components/common/SearchContextWrapper";
|
|
4
5
|
import StructureGrantListButton from "../StructureGrantListButton";
|
|
@@ -117,4 +118,73 @@ describe("<StructureGrantListButton />", () => {
|
|
|
117
118
|
onSuccess();
|
|
118
119
|
expect(refreshSearch).toHaveBeenCalled();
|
|
119
120
|
});
|
|
121
|
+
|
|
122
|
+
it("shows users icon in popup for group grant in my_grants", async () => {
|
|
123
|
+
const groupStructure = {
|
|
124
|
+
...structure,
|
|
125
|
+
my_grants: [
|
|
126
|
+
{
|
|
127
|
+
id: 2,
|
|
128
|
+
user_group_id: 10,
|
|
129
|
+
user_group: { id: 10, name: "foo" },
|
|
130
|
+
},
|
|
131
|
+
],
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
const rendered = render(
|
|
135
|
+
<SearchContextWrapper props={searchProps}>
|
|
136
|
+
<StructureGrantListButton structure={groupStructure} />
|
|
137
|
+
</SearchContextWrapper>,
|
|
138
|
+
renderOpts,
|
|
139
|
+
);
|
|
140
|
+
await waitForLoad(rendered);
|
|
141
|
+
|
|
142
|
+
expect(
|
|
143
|
+
rendered.container.querySelector(".button.group-actions .users.icon"),
|
|
144
|
+
).not.toBeInTheDocument();
|
|
145
|
+
|
|
146
|
+
fireEvent.mouseOver(await rendered.findByRole("listbox"));
|
|
147
|
+
expect(
|
|
148
|
+
await rendered.findByText(/structure.grant.has_grant/i),
|
|
149
|
+
).toBeInTheDocument();
|
|
150
|
+
expect(
|
|
151
|
+
rendered.baseElement.querySelector(".users.icon"),
|
|
152
|
+
).toBeInTheDocument();
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
it("shows users icon in popup for pending group grant request in my_grant_request", async () => {
|
|
156
|
+
const pendingGroupStructure = {
|
|
157
|
+
...structure,
|
|
158
|
+
my_grant_request: {
|
|
159
|
+
status: "pending",
|
|
160
|
+
_embedded: { group: { user_group_id: 10 } },
|
|
161
|
+
},
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
const rendered = render(
|
|
165
|
+
<SearchContextWrapper props={searchProps}>
|
|
166
|
+
<StructureGrantListButton structure={pendingGroupStructure} />
|
|
167
|
+
</SearchContextWrapper>,
|
|
168
|
+
{
|
|
169
|
+
...renderOpts,
|
|
170
|
+
state: {
|
|
171
|
+
...renderOpts.state,
|
|
172
|
+
authentication: { user_name: "foo" },
|
|
173
|
+
},
|
|
174
|
+
},
|
|
175
|
+
);
|
|
176
|
+
await waitForLoad(rendered);
|
|
177
|
+
|
|
178
|
+
expect(
|
|
179
|
+
rendered.container.querySelector(".button.group-actions .users.icon"),
|
|
180
|
+
).not.toBeInTheDocument();
|
|
181
|
+
|
|
182
|
+
fireEvent.mouseOver(await rendered.findByRole("listbox"));
|
|
183
|
+
expect(
|
|
184
|
+
await rendered.findByText(/structure.grant.requested_access/i),
|
|
185
|
+
).toBeInTheDocument();
|
|
186
|
+
expect(
|
|
187
|
+
rendered.baseElement.querySelector(".users.icon"),
|
|
188
|
+
).toBeInTheDocument();
|
|
189
|
+
});
|
|
120
190
|
});
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
import { waitFor } from "@testing-library/react";
|
|
2
2
|
import userEvent from "@testing-library/user-event";
|
|
3
3
|
import { render, waitForLoad } from "@truedat/test/render";
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
buildDSVQuery,
|
|
6
|
+
DATA_STRUCTURE_VERSION_GRANTS_QUERY,
|
|
7
|
+
LEGACY_DATA_STRUCTURE_VERSION_QUERY,
|
|
8
|
+
LATEST_GRANT_REQUEST_BY_DS_QUERY,
|
|
9
|
+
} from "../../api/queries";
|
|
5
10
|
import StructureGrantSummaryButton from "../StructureGrantSummaryButton";
|
|
6
11
|
import { createGrantRequestStatus } from "../../routines";
|
|
7
12
|
import en from "../../messages/en";
|
|
@@ -209,4 +214,34 @@ describe("<StructureGrantSummaryButton />", () => {
|
|
|
209
214
|
).toHaveLength(0);
|
|
210
215
|
});
|
|
211
216
|
});
|
|
217
|
+
|
|
218
|
+
it("requests user group fields in data structure version grants query", () => {
|
|
219
|
+
const query = DATA_STRUCTURE_VERSION_GRANTS_QUERY.loc.source.body;
|
|
220
|
+
expect(query).toMatch(/user_group_id|userGroupId/);
|
|
221
|
+
expect(query).toMatch(/user_group|userGroup/);
|
|
222
|
+
expect(query).toMatch(/source_group_name|sourceGroupName/);
|
|
223
|
+
expect(query).toMatch(/\balias\b/);
|
|
224
|
+
expect(query).toMatch(/\bname\b/);
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
it("requests user group fields in legacy data structure version query grant", () => {
|
|
228
|
+
const query = LEGACY_DATA_STRUCTURE_VERSION_QUERY.loc.source.body;
|
|
229
|
+
expect(query).toMatch(/user_group_id|userGroupId/);
|
|
230
|
+
expect(query).toMatch(/user_group|userGroup/);
|
|
231
|
+
expect(query).toMatch(/source_group_name|sourceGroupName/);
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
it("requests user group fields in data structure version query grant", () => {
|
|
235
|
+
const query = buildDSVQuery(false).loc.source.body;
|
|
236
|
+
expect(query).toMatch(/user_group_id|userGroupId/);
|
|
237
|
+
expect(query).toMatch(/user_group|userGroup/);
|
|
238
|
+
expect(query).toMatch(/source_group_name|sourceGroupName/);
|
|
239
|
+
});
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
describe("data structure version grants query current user group member", () => {
|
|
243
|
+
it("requests current user group member in data structure version grants query", () => {
|
|
244
|
+
const query = DATA_STRUCTURE_VERSION_GRANTS_QUERY.loc.source.body;
|
|
245
|
+
expect(query).toMatch(/current_user_group_member|currentUserGroupMember/);
|
|
246
|
+
});
|
|
212
247
|
});
|
|
@@ -93,4 +93,16 @@ describe("<StructureGrants />", () => {
|
|
|
93
93
|
const { container } = render(<StructureGrants {...props} />);
|
|
94
94
|
expect(container).toMatchSnapshot();
|
|
95
95
|
});
|
|
96
|
+
|
|
97
|
+
it("shows User / Group header for the user column", () => {
|
|
98
|
+
const rendered = render(<StructureGrants {...props} />, {
|
|
99
|
+
messages: {
|
|
100
|
+
en: {
|
|
101
|
+
"grant.header.user": "User",
|
|
102
|
+
"grants.props.user_or_group": "User / Group",
|
|
103
|
+
},
|
|
104
|
+
},
|
|
105
|
+
});
|
|
106
|
+
expect(rendered.getByText(/user \/ group/i)).toBeInTheDocument();
|
|
107
|
+
});
|
|
96
108
|
});
|
|
@@ -3,6 +3,16 @@ import { waitFor } from "@testing-library/react";
|
|
|
3
3
|
import { render, waitForLoad } from "@truedat/test/render";
|
|
4
4
|
import _ from "lodash/fp";
|
|
5
5
|
import { StructureRelationRow } from "../StructureRelationRow";
|
|
6
|
+
import { linksDecorator } from "../../selectors/getStructureFieldColumns";
|
|
7
|
+
|
|
8
|
+
const renderRow = (props) =>
|
|
9
|
+
render(
|
|
10
|
+
<table>
|
|
11
|
+
<tbody>
|
|
12
|
+
<StructureRelationRow {...props} />
|
|
13
|
+
</tbody>
|
|
14
|
+
</table>,
|
|
15
|
+
);
|
|
6
16
|
|
|
7
17
|
describe("<StructureRelationRow />", () => {
|
|
8
18
|
const structure = { id: 1, name: "Structure 1", type: "Some Type 1" };
|
|
@@ -35,7 +45,7 @@ describe("<StructureRelationRow />", () => {
|
|
|
35
45
|
|
|
36
46
|
it("matches the latest snapshot", async () => {
|
|
37
47
|
const props = { relation, columns };
|
|
38
|
-
const rendered =
|
|
48
|
+
const rendered = renderRow(props);
|
|
39
49
|
await waitForLoad(rendered);
|
|
40
50
|
expect(rendered.container).toMatchSnapshot();
|
|
41
51
|
});
|
|
@@ -43,7 +53,7 @@ describe("<StructureRelationRow />", () => {
|
|
|
43
53
|
it("clicking the row will pass the relation to onClick()", async () => {
|
|
44
54
|
const onClick = jest.fn();
|
|
45
55
|
const props = { relation, columns, onClick };
|
|
46
|
-
const rendered =
|
|
56
|
+
const rendered = renderRow(props);
|
|
47
57
|
await waitForLoad(rendered);
|
|
48
58
|
const user = userEvent.setup({ delay: null });
|
|
49
59
|
|
|
@@ -58,7 +68,7 @@ describe("<StructureRelationRow />", () => {
|
|
|
58
68
|
const value = _.path("structure.name")(relation);
|
|
59
69
|
const onClick = jest.fn();
|
|
60
70
|
const props = { relation, columns: [_.head(columns)], onClick };
|
|
61
|
-
const rendered =
|
|
71
|
+
const rendered = renderRow(props);
|
|
62
72
|
await waitForLoad(rendered);
|
|
63
73
|
|
|
64
74
|
expect(rendered.container.querySelector("td")).toHaveTextContent(value);
|
|
@@ -71,11 +81,69 @@ describe("<StructureRelationRow />", () => {
|
|
|
71
81
|
_.set("fieldDecorator", fieldDecorator),
|
|
72
82
|
)(columns);
|
|
73
83
|
const props = { relation, columns: [column] };
|
|
74
|
-
const rendered =
|
|
84
|
+
const rendered = renderRow(props);
|
|
75
85
|
await waitForLoad(rendered);
|
|
76
86
|
|
|
77
87
|
expect(rendered.container.querySelector("td")).toHaveTextContent(
|
|
78
88
|
"used_by_decorated",
|
|
79
89
|
);
|
|
80
90
|
});
|
|
91
|
+
|
|
92
|
+
it("row prints concept links", async () => {
|
|
93
|
+
const relation = {
|
|
94
|
+
id: 1,
|
|
95
|
+
relation_type,
|
|
96
|
+
structure,
|
|
97
|
+
links: [
|
|
98
|
+
{ name: "foo concept", resource_id: "1" },
|
|
99
|
+
{ name: "bar concept", resource_id: "2" },
|
|
100
|
+
],
|
|
101
|
+
};
|
|
102
|
+
const props = {
|
|
103
|
+
relation,
|
|
104
|
+
columns: [{ name: "links", fieldDecorator: linksDecorator }],
|
|
105
|
+
};
|
|
106
|
+
const rendered = render(<StructureRelationRow {...props} />);
|
|
107
|
+
await waitForLoad(rendered);
|
|
108
|
+
|
|
109
|
+
expect(rendered.getByText(/foo concept/i)).toBeInTheDocument();
|
|
110
|
+
expect(rendered.getByText(/bar concept/i)).toBeInTheDocument();
|
|
111
|
+
expect(rendered.getAllByRole("link")).toHaveLength(2);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it("row skips empty or invalid concept links", async () => {
|
|
115
|
+
const relation = {
|
|
116
|
+
id: 1,
|
|
117
|
+
relation_type,
|
|
118
|
+
structure,
|
|
119
|
+
links: [null, {}, { name: "foo concept", resource_id: "1" }],
|
|
120
|
+
};
|
|
121
|
+
const props = {
|
|
122
|
+
relation,
|
|
123
|
+
columns: [{ name: "links", fieldDecorator: linksDecorator }],
|
|
124
|
+
};
|
|
125
|
+
const rendered = render(<StructureRelationRow {...props} />);
|
|
126
|
+
await waitForLoad(rendered);
|
|
127
|
+
|
|
128
|
+
expect(rendered.getByText(/foo concept/i)).toBeInTheDocument();
|
|
129
|
+
expect(rendered.getAllByRole("link")).toHaveLength(1);
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it("row prints nothing when concept links are missing", async () => {
|
|
133
|
+
const relation = {
|
|
134
|
+
id: 1,
|
|
135
|
+
relation_type,
|
|
136
|
+
structure,
|
|
137
|
+
links: [],
|
|
138
|
+
};
|
|
139
|
+
const props = {
|
|
140
|
+
relation,
|
|
141
|
+
columns: [{ name: "links", fieldDecorator: linksDecorator }],
|
|
142
|
+
};
|
|
143
|
+
const rendered = render(<StructureRelationRow {...props} />);
|
|
144
|
+
await waitForLoad(rendered);
|
|
145
|
+
|
|
146
|
+
expect(rendered.queryByRole("link")).not.toBeInTheDocument();
|
|
147
|
+
expect(rendered.container.querySelector("td")).toBeEmptyDOMElement();
|
|
148
|
+
});
|
|
81
149
|
});
|
|
@@ -64,4 +64,22 @@ describe("<StructureRelations />", () => {
|
|
|
64
64
|
relations.length,
|
|
65
65
|
);
|
|
66
66
|
});
|
|
67
|
+
|
|
68
|
+
it("renders concept links column header", async () => {
|
|
69
|
+
const relations = [
|
|
70
|
+
{
|
|
71
|
+
id: 1,
|
|
72
|
+
relation_type,
|
|
73
|
+
structure: { id: 1, name: "foo structure", type: "foo" },
|
|
74
|
+
links: [{ name: "foo concept", resource_id: "1" }],
|
|
75
|
+
},
|
|
76
|
+
];
|
|
77
|
+
const columnsWithLinks = [...columns, { name: "links" }];
|
|
78
|
+
const rendered = render(
|
|
79
|
+
<StructureRelations relations={relations} columns={columnsWithLinks} />,
|
|
80
|
+
);
|
|
81
|
+
await waitForLoad(rendered);
|
|
82
|
+
|
|
83
|
+
expect(rendered.getByText(/structure.relation.links/i)).toBeInTheDocument();
|
|
84
|
+
});
|
|
67
85
|
});
|
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
import { render, waitForLoad } from "@truedat/test/render";
|
|
2
2
|
import StructureRoles from "../StructureRoles";
|
|
3
3
|
|
|
4
|
+
jest.mock("@truedat/core/hooks/useAclEntries", () => ({
|
|
5
|
+
...jest.requireActual("@truedat/core/hooks/useAclEntries"),
|
|
6
|
+
useAclEntries: () => ({
|
|
7
|
+
data: { aclEntries: [], actions: { canCreate: false } },
|
|
8
|
+
loading: false,
|
|
9
|
+
mutate: jest.fn(),
|
|
10
|
+
}),
|
|
11
|
+
}));
|
|
12
|
+
|
|
4
13
|
jest.mock("react-router", () => ({
|
|
5
14
|
...jest.requireActual("react-router"),
|
|
6
15
|
useParams: jest.fn().mockReturnValue({ id: "1" }),
|