@truedat/bg 7.10.3 → 7.11.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 +3 -3
- package/src/concepts/api.js +2 -0
- package/src/concepts/components/ConceptLinksUploadButton.js +0 -4
- package/src/concepts/components/ConceptRoutes.js +28 -46
- package/src/concepts/components/ConceptSuggestions.js +71 -0
- package/src/concepts/components/__tests__/ConceptRoutes.spec.js +201 -0
- package/src/concepts/components/__tests__/ConceptSuggestions.spec.js +74 -0
- package/src/concepts/components/__tests__/__snapshots__/ConceptRoutes.spec.js.snap +165 -0
- package/src/concepts/hooks/useConcepts.js +7 -0
- package/src/concepts/relations/api.js +9 -1
- package/src/concepts/relations/components/ConceptLinksApprovalResults.js +91 -0
- package/src/concepts/relations/components/ConceptLinksApprovals.js +225 -0
- package/src/concepts/relations/components/ConceptLinksApprovalsLabelResults.js +42 -0
- package/src/concepts/relations/components/ConceptLinksApprovalsRow.js +43 -0
- package/src/concepts/relations/components/ConceptLinksApprovalsTable.js +104 -0
- package/src/concepts/relations/components/ConceptSelector.js +117 -75
- package/src/concepts/relations/components/__tests__/ConceptLinksApprovalResults.spec.js +123 -0
- package/src/concepts/relations/components/__tests__/ConceptLinksApprovals.spec.js +77 -0
- package/src/concepts/relations/components/__tests__/ConceptLinksApprovalsLabelResults.spec.js +47 -0
- package/src/concepts/relations/components/__tests__/ConceptLinksApprovalsRow.spec.js +68 -0
- package/src/concepts/relations/components/__tests__/ConceptLinksApprovalsTable.spec.js +107 -0
- package/src/concepts/relations/components/__tests__/ConceptSelector.spec.js +90 -1
- package/src/concepts/relations/components/__tests__/__snapshots__/ConceptLinksApprovalResults.spec.js.snap +217 -0
- package/src/concepts/relations/components/__tests__/__snapshots__/ConceptLinksApprovals.spec.js.snap +559 -0
- package/src/concepts/relations/components/__tests__/__snapshots__/ConceptLinksApprovalsLabelResults.spec.js.snap +34 -0
- package/src/concepts/relations/components/__tests__/__snapshots__/ConceptLinksApprovalsRow.spec.js.snap +47 -0
- package/src/concepts/relations/components/__tests__/__snapshots__/ConceptLinksApprovalsTable.spec.js.snap +132 -0
- package/src/concepts/relations/components/__tests__/__snapshots__/ConceptSelector.spec.js.snap +99 -0
- package/src/concepts/relations/hooks/useLinks.js +25 -0
- package/src/concepts/relations/sagas/linkConcept.js +1 -0
- package/src/concepts/relations/selectors/getLinksSearchColumns.js +106 -0
- package/src/concepts/relations/selectors/index.js +2 -0
- package/src/concepts/relations/styles/ConceptLinksApprovals.less +15 -0
|
@@ -1,14 +1,7 @@
|
|
|
1
1
|
import _ from "lodash/fp";
|
|
2
2
|
import PropTypes from "prop-types";
|
|
3
3
|
import { connect } from "react-redux";
|
|
4
|
-
import {
|
|
5
|
-
Button,
|
|
6
|
-
Table,
|
|
7
|
-
Message,
|
|
8
|
-
Label,
|
|
9
|
-
Icon,
|
|
10
|
-
Segment,
|
|
11
|
-
} from "semantic-ui-react";
|
|
4
|
+
import { Button, Table, Message, Label, Segment } from "semantic-ui-react";
|
|
12
5
|
import { FormattedMessage, useIntl } from "react-intl";
|
|
13
6
|
import SearchWidget from "@truedat/core/search/SearchWidget";
|
|
14
7
|
import {
|
|
@@ -44,6 +37,7 @@ const ConceptSelectorRow = ({
|
|
|
44
37
|
onClick,
|
|
45
38
|
disabled,
|
|
46
39
|
positive,
|
|
40
|
+
extraColumns = [],
|
|
47
41
|
}) => {
|
|
48
42
|
const { name, status, domain } = concept;
|
|
49
43
|
return (
|
|
@@ -65,6 +59,12 @@ const ConceptSelectorRow = ({
|
|
|
65
59
|
</Label>
|
|
66
60
|
}
|
|
67
61
|
/>
|
|
62
|
+
{extraColumns.map((column, key) => (
|
|
63
|
+
<Table.Cell
|
|
64
|
+
key={key}
|
|
65
|
+
content={column.fieldDecorator(column.fieldSelector(concept))}
|
|
66
|
+
/>
|
|
67
|
+
))}
|
|
68
68
|
</Table.Row>
|
|
69
69
|
);
|
|
70
70
|
};
|
|
@@ -77,20 +77,14 @@ ConceptSelectorRow.propTypes = {
|
|
|
77
77
|
positive: PropTypes.bool,
|
|
78
78
|
};
|
|
79
79
|
|
|
80
|
-
export
|
|
80
|
+
export const ConceptSelectorTable = ({
|
|
81
81
|
businessConceptId,
|
|
82
|
-
|
|
82
|
+
concepts,
|
|
83
83
|
selectedConcept,
|
|
84
|
-
|
|
84
|
+
handleConceptSelected,
|
|
85
85
|
links,
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
const { trigger: triggerDownload, isMutating: downloading } =
|
|
89
|
-
useConceptLinksDownload();
|
|
90
|
-
const { formatMessage } = useIntl();
|
|
91
|
-
const concepts = searchData?.data;
|
|
92
|
-
const conceptsActions = _.propOr({}, "_actions")(searchData);
|
|
93
|
-
|
|
86
|
+
extraColumns = [],
|
|
87
|
+
}) => {
|
|
94
88
|
const selectedConceptIsFiltered = !_.reduce(
|
|
95
89
|
(acc, c) => (selectedConcept && c.id == selectedConcept.id) || acc,
|
|
96
90
|
false
|
|
@@ -104,7 +98,85 @@ export function ConceptSelectorContent({
|
|
|
104
98
|
)(concept)
|
|
105
99
|
: false;
|
|
106
100
|
};
|
|
107
|
-
|
|
101
|
+
|
|
102
|
+
return !_.isEmpty(concepts) || selectedConcept ? (
|
|
103
|
+
<Table selectable size="small">
|
|
104
|
+
<Table.Header>
|
|
105
|
+
<Table.Row>
|
|
106
|
+
<Table.HeaderCell
|
|
107
|
+
content={<FormattedMessage id="concepts.props.name" />}
|
|
108
|
+
/>
|
|
109
|
+
<Table.HeaderCell
|
|
110
|
+
content={<FormattedMessage id="concepts.props.domain" />}
|
|
111
|
+
/>
|
|
112
|
+
<Table.HeaderCell
|
|
113
|
+
content={<FormattedMessage id="concepts.props.status" />}
|
|
114
|
+
/>
|
|
115
|
+
{extraColumns.map((column, key) => (
|
|
116
|
+
<Table.HeaderCell
|
|
117
|
+
key={key}
|
|
118
|
+
content={
|
|
119
|
+
<FormattedMessage id={`concepts.props.${column.name}`} />
|
|
120
|
+
}
|
|
121
|
+
/>
|
|
122
|
+
))}
|
|
123
|
+
</Table.Row>
|
|
124
|
+
</Table.Header>
|
|
125
|
+
<Table.Body>
|
|
126
|
+
{concepts.map((s, i) => (
|
|
127
|
+
<ConceptSelectorRow
|
|
128
|
+
disabled={
|
|
129
|
+
businessConceptId == s.business_concept_id || isDisabled(s)
|
|
130
|
+
}
|
|
131
|
+
key={i}
|
|
132
|
+
concept={s}
|
|
133
|
+
active={selectedConcept && selectedConcept.id == s.id}
|
|
134
|
+
onClick={handleConceptSelected}
|
|
135
|
+
positive={isPositive(
|
|
136
|
+
links,
|
|
137
|
+
s.business_concept_id,
|
|
138
|
+
businessConceptId
|
|
139
|
+
)}
|
|
140
|
+
extraColumns={extraColumns}
|
|
141
|
+
/>
|
|
142
|
+
))}
|
|
143
|
+
{selectedConcept && selectedConceptIsFiltered && (
|
|
144
|
+
<ConceptSelectorRow
|
|
145
|
+
concept={selectedConcept}
|
|
146
|
+
extraColumns={extraColumns}
|
|
147
|
+
active
|
|
148
|
+
/>
|
|
149
|
+
)}
|
|
150
|
+
</Table.Body>
|
|
151
|
+
</Table>
|
|
152
|
+
) : (
|
|
153
|
+
<Message header={<FormattedMessage id="concepts.search.results.empty" />} />
|
|
154
|
+
);
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
ConceptSelectorTable.propTypes = {
|
|
158
|
+
businessConceptId: PropTypes.number,
|
|
159
|
+
concepts: PropTypes.array,
|
|
160
|
+
selectedConcept: PropTypes.object,
|
|
161
|
+
handleConceptSelected: PropTypes.func,
|
|
162
|
+
links: PropTypes.array,
|
|
163
|
+
extraColumns: PropTypes.array,
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
export function ConceptSelectorContent({
|
|
167
|
+
businessConceptId,
|
|
168
|
+
handleConceptSelected,
|
|
169
|
+
selectedConcept,
|
|
170
|
+
showTitle = true,
|
|
171
|
+
links,
|
|
172
|
+
}) {
|
|
173
|
+
const { formatMessage } = useIntl();
|
|
174
|
+
const { searchData, filterParams: searchParams } = useSearchContext();
|
|
175
|
+
const { trigger: triggerDownload, isMutating: downloading } =
|
|
176
|
+
useConceptLinksDownload();
|
|
177
|
+
const concepts = searchData?.data;
|
|
178
|
+
const conceptsActions = _.propOr({}, "_actions")(searchData);
|
|
179
|
+
|
|
108
180
|
return (
|
|
109
181
|
<>
|
|
110
182
|
{showTitle && (
|
|
@@ -113,64 +185,34 @@ export function ConceptSelectorContent({
|
|
|
113
185
|
</label>
|
|
114
186
|
)}
|
|
115
187
|
<Segment>
|
|
116
|
-
{conceptsActions?.downloadLinks && (
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
188
|
+
{conceptsActions?.downloadLinks && (
|
|
189
|
+
<>
|
|
190
|
+
<Button
|
|
191
|
+
icon="download"
|
|
192
|
+
floated="right"
|
|
193
|
+
secondary
|
|
194
|
+
loading={downloading}
|
|
195
|
+
onClick={() => triggerDownload(searchParams)}
|
|
196
|
+
data-tooltip={formatMessage({
|
|
197
|
+
id: "concepts.actions.downloadLinks.tooltip",
|
|
198
|
+
})}
|
|
199
|
+
/>
|
|
128
200
|
<ConceptLinksUploadButton />
|
|
129
|
-
|
|
201
|
+
</>
|
|
130
202
|
)}
|
|
131
203
|
<SearchWidget />
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
/>
|
|
145
|
-
</Table.Row>
|
|
146
|
-
</Table.Header>
|
|
147
|
-
<Table.Body>
|
|
148
|
-
{concepts.map((s, i) => (
|
|
149
|
-
<ConceptSelectorRow
|
|
150
|
-
disabled={
|
|
151
|
-
businessConceptId == s.business_concept_id || isDisabled(s)
|
|
152
|
-
}
|
|
153
|
-
key={i}
|
|
154
|
-
concept={s}
|
|
155
|
-
active={selectedConcept && selectedConcept.id == s.id}
|
|
156
|
-
onClick={handleConceptSelected}
|
|
157
|
-
positive={isPositive(
|
|
158
|
-
links,
|
|
159
|
-
s.business_concept_id,
|
|
160
|
-
businessConceptId
|
|
161
|
-
)}
|
|
162
|
-
/>
|
|
163
|
-
))}
|
|
164
|
-
{selectedConcept && selectedConceptIsFiltered && (
|
|
165
|
-
<ConceptSelectorRow concept={selectedConcept} active />
|
|
166
|
-
)}
|
|
167
|
-
</Table.Body>
|
|
168
|
-
</Table>
|
|
169
|
-
) : (
|
|
170
|
-
<Message
|
|
171
|
-
header={<FormattedMessage id="concepts.search.results.empty" />}
|
|
172
|
-
/>
|
|
173
|
-
)}
|
|
204
|
+
<ConceptSelectorTable
|
|
205
|
+
concepts={concepts}
|
|
206
|
+
showTitle={showTitle}
|
|
207
|
+
downloading={downloading}
|
|
208
|
+
selectedConcept={selectedConcept}
|
|
209
|
+
handleConceptSelected={handleConceptSelected}
|
|
210
|
+
links={links}
|
|
211
|
+
businessConceptId={businessConceptId}
|
|
212
|
+
triggerDownload={triggerDownload}
|
|
213
|
+
downloadLinks={conceptsActions?.downloadLinks}
|
|
214
|
+
searchParams={searchParams}
|
|
215
|
+
/>
|
|
174
216
|
<ConceptsPagination size="small" />
|
|
175
217
|
</Segment>
|
|
176
218
|
</>
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { render, waitForLoad } from "@truedat/test/render";
|
|
2
|
+
import LinksApprovalResults from "../ConceptLinksApprovalResults";
|
|
3
|
+
import { useLocation } from "react-router";
|
|
4
|
+
|
|
5
|
+
jest.mock("react-router", () => {
|
|
6
|
+
const actual = jest.requireActual("react-router");
|
|
7
|
+
return {
|
|
8
|
+
...actual,
|
|
9
|
+
useLocation: jest.fn(),
|
|
10
|
+
};
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
const mockFormatMessage = jest.fn(({ id }) => id);
|
|
14
|
+
jest.mock("react-intl", () => ({
|
|
15
|
+
...jest.requireActual("react-intl"),
|
|
16
|
+
useIntl: () => ({
|
|
17
|
+
formatMessage: mockFormatMessage,
|
|
18
|
+
}),
|
|
19
|
+
}));
|
|
20
|
+
|
|
21
|
+
describe("<LinksApprovalResults />", () => {
|
|
22
|
+
beforeEach(() => {
|
|
23
|
+
jest.clearAllMocks();
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it("renders approval results with relations and errors", async () => {
|
|
27
|
+
useLocation.mockReturnValue({
|
|
28
|
+
state: {
|
|
29
|
+
status: "approved",
|
|
30
|
+
relations: [
|
|
31
|
+
{
|
|
32
|
+
id: 1,
|
|
33
|
+
source_id: 10,
|
|
34
|
+
source_name: "Source 1",
|
|
35
|
+
target_id: 20,
|
|
36
|
+
target_name: "Target 1",
|
|
37
|
+
},
|
|
38
|
+
],
|
|
39
|
+
errors: {
|
|
40
|
+
permissions: {
|
|
41
|
+
message: "forbidden",
|
|
42
|
+
reason: "permissions",
|
|
43
|
+
relations: [
|
|
44
|
+
{
|
|
45
|
+
id: 2,
|
|
46
|
+
source_id: 11,
|
|
47
|
+
source_name: "Source 2",
|
|
48
|
+
target_id: 21,
|
|
49
|
+
target_name: "Target 2",
|
|
50
|
+
},
|
|
51
|
+
],
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
const rendered = render(<LinksApprovalResults />);
|
|
58
|
+
await waitForLoad(rendered);
|
|
59
|
+
|
|
60
|
+
expect(rendered.container).toMatchSnapshot();
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it("renders rejection results", async () => {
|
|
64
|
+
useLocation.mockReturnValue({
|
|
65
|
+
state: {
|
|
66
|
+
status: "rejected",
|
|
67
|
+
relations: [
|
|
68
|
+
{
|
|
69
|
+
id: 3,
|
|
70
|
+
source_id: 12,
|
|
71
|
+
source_name: "Source 3",
|
|
72
|
+
target_id: 22,
|
|
73
|
+
target_name: "Target 3",
|
|
74
|
+
},
|
|
75
|
+
],
|
|
76
|
+
errors: {},
|
|
77
|
+
},
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
const rendered = render(<LinksApprovalResults />);
|
|
81
|
+
await waitForLoad(rendered);
|
|
82
|
+
|
|
83
|
+
expect(rendered.container).toMatchSnapshot();
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it("renders with no errors", async () => {
|
|
87
|
+
useLocation.mockReturnValue({
|
|
88
|
+
state: {
|
|
89
|
+
status: "approved",
|
|
90
|
+
relations: [
|
|
91
|
+
{
|
|
92
|
+
id: 4,
|
|
93
|
+
source_id: 13,
|
|
94
|
+
source_name: "Source 4",
|
|
95
|
+
target_id: 23,
|
|
96
|
+
target_name: "Target 4",
|
|
97
|
+
},
|
|
98
|
+
],
|
|
99
|
+
errors: {},
|
|
100
|
+
},
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
const rendered = render(<LinksApprovalResults />);
|
|
104
|
+
await waitForLoad(rendered);
|
|
105
|
+
|
|
106
|
+
expect(rendered.container).toMatchSnapshot();
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
it("renders with empty relations and errors", async () => {
|
|
110
|
+
useLocation.mockReturnValue({
|
|
111
|
+
state: {
|
|
112
|
+
status: "approved",
|
|
113
|
+
relations: [],
|
|
114
|
+
errors: {},
|
|
115
|
+
},
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
const rendered = render(<LinksApprovalResults />);
|
|
119
|
+
await waitForLoad(rendered);
|
|
120
|
+
|
|
121
|
+
expect(rendered.container).toMatchSnapshot();
|
|
122
|
+
});
|
|
123
|
+
});
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { render, waitForLoad } from "@truedat/test/render";
|
|
2
|
+
import { useSearchContext } from "@truedat/core/search/SearchContext";
|
|
3
|
+
import { ConceptLinksApprovals } from "../ConceptLinksApprovals";
|
|
4
|
+
|
|
5
|
+
jest.mock("@truedat/core/search/SearchContext", () => {
|
|
6
|
+
const originalModule = jest.requireActual(
|
|
7
|
+
"@truedat/core/search/SearchContext"
|
|
8
|
+
);
|
|
9
|
+
|
|
10
|
+
return {
|
|
11
|
+
__esModule: true,
|
|
12
|
+
...originalModule,
|
|
13
|
+
useSearchContext: jest.fn(),
|
|
14
|
+
};
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
describe("<ConceptLinksApprovals />", () => {
|
|
18
|
+
it("matches the latest snapshot", async () => {
|
|
19
|
+
useSearchContext.mockReturnValue({
|
|
20
|
+
searchData: {
|
|
21
|
+
data: [
|
|
22
|
+
{
|
|
23
|
+
domain_ids: [2],
|
|
24
|
+
id: 1,
|
|
25
|
+
origin: null,
|
|
26
|
+
source_domain_ids: [2],
|
|
27
|
+
source_id: 11,
|
|
28
|
+
source_name: "Busines 11",
|
|
29
|
+
source_type: "business_concept",
|
|
30
|
+
status: "pending",
|
|
31
|
+
target_domain_ids: [2],
|
|
32
|
+
target_id: 21,
|
|
33
|
+
target_name: "Structure 21",
|
|
34
|
+
target_type: "data_structure",
|
|
35
|
+
updated_at: "2025-08-11T07:07:13.336631Z",
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
domain_ids: [2, 1],
|
|
39
|
+
id: 2,
|
|
40
|
+
origin: null,
|
|
41
|
+
source_domain_ids: [2],
|
|
42
|
+
source_id: 21,
|
|
43
|
+
source_name: "Busines 21",
|
|
44
|
+
source_type: "business_concept",
|
|
45
|
+
status: "pending",
|
|
46
|
+
target_domain_ids: [1],
|
|
47
|
+
target_id: 22,
|
|
48
|
+
target_name: "Structure 22",
|
|
49
|
+
target_type: "data_structure",
|
|
50
|
+
updated_at: "2025-08-11T07:07:13.336631Z",
|
|
51
|
+
},
|
|
52
|
+
],
|
|
53
|
+
scroll_id: null,
|
|
54
|
+
},
|
|
55
|
+
searchMust: { status: ["pending"] },
|
|
56
|
+
setOnSearchChange: jest.fn(),
|
|
57
|
+
});
|
|
58
|
+
const rendered = render(<ConceptLinksApprovals />);
|
|
59
|
+
|
|
60
|
+
await waitForLoad(rendered);
|
|
61
|
+
|
|
62
|
+
expect(rendered.container).toMatchSnapshot();
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it("matches the latest snapshot for empty results", async () => {
|
|
66
|
+
useSearchContext.mockReturnValue({
|
|
67
|
+
searchData: [],
|
|
68
|
+
searchMust: { status: ["pending"] },
|
|
69
|
+
setOnSearchChange: jest.fn(),
|
|
70
|
+
});
|
|
71
|
+
const rendered = render(<ConceptLinksApprovals />);
|
|
72
|
+
|
|
73
|
+
await waitForLoad(rendered);
|
|
74
|
+
|
|
75
|
+
expect(rendered.container).toMatchSnapshot();
|
|
76
|
+
});
|
|
77
|
+
});
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { render, waitForLoad } from "@truedat/test/render";
|
|
2
|
+
import { useSearchContext } from "@truedat/core/search/SearchContext";
|
|
3
|
+
import { ConceptLinksApprovalsLabelResults } from "../ConceptLinksApprovalsLabelResults";
|
|
4
|
+
|
|
5
|
+
jest.mock("@truedat/core/search/SearchContext", () => {
|
|
6
|
+
const originalModule = jest.requireActual(
|
|
7
|
+
"@truedat/core/search/SearchContext"
|
|
8
|
+
);
|
|
9
|
+
|
|
10
|
+
return {
|
|
11
|
+
__esModule: true,
|
|
12
|
+
...originalModule,
|
|
13
|
+
useSearchContext: jest.fn(),
|
|
14
|
+
};
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
describe("ConceptLinksApprovalsLabelResults", () => {
|
|
18
|
+
it("matches the latest snapshot", async () => {
|
|
19
|
+
useSearchContext.mockReturnValue({
|
|
20
|
+
count: 1,
|
|
21
|
+
loading: false,
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
const props = {
|
|
25
|
+
selectedCount: 1,
|
|
26
|
+
approveView: true,
|
|
27
|
+
};
|
|
28
|
+
const rendered = render(<ConceptLinksApprovalsLabelResults {...props} />);
|
|
29
|
+
await waitForLoad(rendered);
|
|
30
|
+
rendered.debug();
|
|
31
|
+
expect(rendered.container).toMatchSnapshot();
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it("should not render results count when is loading", async () => {
|
|
35
|
+
useSearchContext.mockReturnValue({
|
|
36
|
+
count: 1,
|
|
37
|
+
loading: true,
|
|
38
|
+
});
|
|
39
|
+
const props = {
|
|
40
|
+
selectedCount: 1,
|
|
41
|
+
approveView: true,
|
|
42
|
+
};
|
|
43
|
+
const rendered = render(<ConceptLinksApprovalsLabelResults {...props} />);
|
|
44
|
+
await waitForLoad(rendered);
|
|
45
|
+
expect(rendered.container).toMatchSnapshot();
|
|
46
|
+
});
|
|
47
|
+
});
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { render, waitForLoad } from "@truedat/test/render";
|
|
2
|
+
import { ConceptLinksApprovalsRow } from "../ConceptLinksApprovalsRow";
|
|
3
|
+
|
|
4
|
+
describe("ConceptLinksApprovalsRow", () => {
|
|
5
|
+
const defaultProps = {
|
|
6
|
+
checked: false,
|
|
7
|
+
columns: [
|
|
8
|
+
{
|
|
9
|
+
key: "name",
|
|
10
|
+
textAlign: "left",
|
|
11
|
+
},
|
|
12
|
+
],
|
|
13
|
+
onCheckboxChange: jest.fn(),
|
|
14
|
+
link: {
|
|
15
|
+
id: "123",
|
|
16
|
+
name: "Test Link",
|
|
17
|
+
},
|
|
18
|
+
approveView: false,
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
it("renders null when columns are empty", async () => {
|
|
22
|
+
const rendered = render(
|
|
23
|
+
<ConceptLinksApprovalsRow {...defaultProps} columns={[]} />
|
|
24
|
+
);
|
|
25
|
+
await waitForLoad(rendered);
|
|
26
|
+
expect(rendered.container).toMatchSnapshot();
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it("renders null when link is empty", async () => {
|
|
30
|
+
const rendered = render(
|
|
31
|
+
<ConceptLinksApprovalsRow {...defaultProps} link={{}} />
|
|
32
|
+
);
|
|
33
|
+
await waitForLoad(rendered);
|
|
34
|
+
expect(rendered.container).toMatchSnapshot();
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it("renders row with checkbox when approveView is true", async () => {
|
|
38
|
+
const rendered = render(
|
|
39
|
+
<ConceptLinksApprovalsRow {...defaultProps} approveView={true} />
|
|
40
|
+
);
|
|
41
|
+
await waitForLoad(rendered);
|
|
42
|
+
expect(rendered.container).toMatchSnapshot();
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it("renders row without checkbox when approveView is false", async () => {
|
|
46
|
+
const rendered = render(
|
|
47
|
+
<ConceptLinksApprovalsRow {...defaultProps} approveView={false} />
|
|
48
|
+
);
|
|
49
|
+
await waitForLoad(rendered);
|
|
50
|
+
expect(rendered.container).toMatchSnapshot();
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it("calls onCheckboxChange when checkbox is clicked", async () => {
|
|
54
|
+
const onCheckboxChange = jest.fn();
|
|
55
|
+
const rendered = render(
|
|
56
|
+
<ConceptLinksApprovalsRow
|
|
57
|
+
{...defaultProps}
|
|
58
|
+
approveView={true}
|
|
59
|
+
onCheckboxChange={onCheckboxChange}
|
|
60
|
+
/>
|
|
61
|
+
);
|
|
62
|
+
await waitForLoad(rendered);
|
|
63
|
+
|
|
64
|
+
const checkbox = rendered.container.querySelector("input[type='checkbox']");
|
|
65
|
+
checkbox.click();
|
|
66
|
+
expect(onCheckboxChange).toHaveBeenCalled();
|
|
67
|
+
});
|
|
68
|
+
});
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { render, waitForLoad } from "@truedat/test/render";
|
|
2
|
+
import { useSearchContext } from "@truedat/core/search/SearchContext";
|
|
3
|
+
import { ConceptLinksApprovalsTable } from "../ConceptLinksApprovalsTable";
|
|
4
|
+
|
|
5
|
+
jest.mock("@truedat/core/search/SearchContext", () => {
|
|
6
|
+
const originalModule = jest.requireActual(
|
|
7
|
+
"@truedat/core/search/SearchContext"
|
|
8
|
+
);
|
|
9
|
+
|
|
10
|
+
return {
|
|
11
|
+
__esModule: true,
|
|
12
|
+
...originalModule,
|
|
13
|
+
useSearchContext: jest.fn(),
|
|
14
|
+
};
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
describe("ConceptLinksApprovalsTable", () => {
|
|
18
|
+
const mockColumns = [
|
|
19
|
+
{ name: "source_name", width: 4 },
|
|
20
|
+
{ name: "target_name", width: 4 },
|
|
21
|
+
{ name: "tag_type", width: 2 },
|
|
22
|
+
{ name: "status", width: 2 },
|
|
23
|
+
{ name: "updated_at", width: 2 },
|
|
24
|
+
];
|
|
25
|
+
|
|
26
|
+
beforeEach(() => {
|
|
27
|
+
useSearchContext.mockReturnValue({
|
|
28
|
+
searchData: {
|
|
29
|
+
data: [
|
|
30
|
+
{
|
|
31
|
+
id: 1,
|
|
32
|
+
source_name: "Concept 1",
|
|
33
|
+
target_name: "Structure 1",
|
|
34
|
+
tag_type: "relates_to",
|
|
35
|
+
status: "pending",
|
|
36
|
+
updated_at: "2023-01-01",
|
|
37
|
+
},
|
|
38
|
+
],
|
|
39
|
+
},
|
|
40
|
+
loading: false,
|
|
41
|
+
sortColumn: null,
|
|
42
|
+
sortDirection: null,
|
|
43
|
+
handleSortSelection: jest.fn(),
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it("matches the latest snapshot with data", async () => {
|
|
48
|
+
const props = {
|
|
49
|
+
columns: mockColumns,
|
|
50
|
+
approveView: true,
|
|
51
|
+
checkedAll: false,
|
|
52
|
+
addAll: jest.fn(),
|
|
53
|
+
checkRow: jest.fn(),
|
|
54
|
+
isRowChecked: jest.fn(),
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const rendered = render(<ConceptLinksApprovalsTable {...props} />);
|
|
58
|
+
await waitForLoad(rendered);
|
|
59
|
+
expect(rendered.container).toMatchSnapshot();
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it("matches the latest snapshot with empty data", async () => {
|
|
63
|
+
useSearchContext.mockReturnValue({
|
|
64
|
+
searchData: { data: [] },
|
|
65
|
+
loading: false,
|
|
66
|
+
sortColumn: null,
|
|
67
|
+
sortDirection: null,
|
|
68
|
+
handleSortSelection: jest.fn(),
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
const props = {
|
|
72
|
+
columns: mockColumns,
|
|
73
|
+
approveView: true,
|
|
74
|
+
checkedAll: false,
|
|
75
|
+
addAll: jest.fn(),
|
|
76
|
+
checkRow: jest.fn(),
|
|
77
|
+
isRowChecked: jest.fn(),
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
const rendered = render(<ConceptLinksApprovalsTable {...props} />);
|
|
81
|
+
await waitForLoad(rendered);
|
|
82
|
+
expect(rendered.container).toMatchSnapshot();
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it("matches the latest snapshot while loading", async () => {
|
|
86
|
+
useSearchContext.mockReturnValue({
|
|
87
|
+
searchData: { data: [] },
|
|
88
|
+
loading: true,
|
|
89
|
+
sortColumn: null,
|
|
90
|
+
sortDirection: null,
|
|
91
|
+
handleSortSelection: jest.fn(),
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
const props = {
|
|
95
|
+
columns: mockColumns,
|
|
96
|
+
approveView: true,
|
|
97
|
+
checkedAll: false,
|
|
98
|
+
addAll: jest.fn(),
|
|
99
|
+
checkRow: jest.fn(),
|
|
100
|
+
isRowChecked: jest.fn(),
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
const rendered = render(<ConceptLinksApprovalsTable {...props} />);
|
|
104
|
+
await waitForLoad(rendered);
|
|
105
|
+
expect(rendered.container).toMatchSnapshot();
|
|
106
|
+
});
|
|
107
|
+
});
|