@truedat/qx 8.4.9 → 8.5.2
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/components/common/expressions/Clauses.js +5 -9
- package/src/components/common/expressions/Condition.js +36 -37
- package/src/components/common/expressions/__tests__/Clauses.spec.js +87 -0
- package/src/components/common/expressions/__tests__/Condition.spec.js +220 -1
- package/src/components/common/expressions/__tests__/__snapshots__/Clauses.spec.js.snap +22 -21
- package/src/components/common/expressions/__tests__/__snapshots__/Condition.spec.js.snap +212 -214
- package/src/components/dataViews/queryableProperties/GroupBy.js +4 -2
- package/src/components/dataViews/queryableProperties/__tests__/GroupBy.spec.js +134 -28
- package/src/components/qualityControls/ControlProperties.js +32 -16
- package/src/components/qualityControls/ControlPropertiesForm.js +3 -3
- package/src/components/qualityControls/ControlPropertiesSummary.js +127 -104
- package/src/components/qualityControls/ControlPropertiesView.js +48 -74
- package/src/components/qualityControls/InformationForm.js +181 -180
- package/src/components/qualityControls/ScoreCriteria.js +0 -4
- package/src/components/qualityControls/ScoreCriteriaView.js +6 -9
- package/src/components/qualityControls/__tests__/ControlProperties.spec.js +47 -16
- package/src/components/qualityControls/__tests__/ControlPropertiesForm.spec.js +100 -0
- package/src/components/qualityControls/__tests__/ControlPropertiesSummary.spec.js +141 -0
- package/src/components/qualityControls/__tests__/ControlPropertiesView.spec.js +102 -11
- package/src/components/qualityControls/__tests__/EditQualityControl.spec.js +27 -3
- package/src/components/qualityControls/__tests__/InformationForm.spec.js +342 -0
- package/src/components/qualityControls/__tests__/NewDraftQualityControl.spec.js +26 -6
- package/src/components/qualityControls/__tests__/NewQualityControl.spec.js +66 -20
- package/src/components/qualityControls/__tests__/QualityBadge.spec.js +30 -3
- package/src/components/qualityControls/__tests__/QualityControlEditor.spec.js +282 -45
- package/src/components/qualityControls/__tests__/ScoreCriteria.spec.js +25 -3
- package/src/components/qualityControls/__tests__/ScoreCriteriaView.spec.js +19 -3
- package/src/components/qualityControls/__tests__/__fixtures__/qualityControlHelper.js +1 -1
- package/src/components/qualityControls/__tests__/__snapshots__/ControlProperties.spec.js.snap +13 -1
- package/src/components/qualityControls/__tests__/__snapshots__/ControlPropertiesView.spec.js.snap +70 -40
- package/src/components/qualityControls/__tests__/__snapshots__/EditQualityControl.spec.js.snap +118 -132
- package/src/components/qualityControls/__tests__/__snapshots__/NewDraftQualityControl.spec.js.snap +118 -132
- package/src/components/qualityControls/__tests__/__snapshots__/NewQualityControl.spec.js.snap +0 -13
- package/src/components/qualityControls/__tests__/__snapshots__/QualityBadge.spec.js.snap +15 -5
- package/src/components/qualityControls/__tests__/__snapshots__/QualityControlEditor.spec.js.snap +488 -125
- package/src/components/qualityControls/__tests__/__snapshots__/ScoreCriteria.spec.js.snap +13 -5
- package/src/components/qualityControls/__tests__/qualityByControlMode.spec.js +65 -14
- package/src/components/qualityControls/controlProperties/{Ratio.js → ResourceWithValidation.js} +19 -10
- package/src/components/qualityControls/controlProperties/__tests__/ResourceWithValidation.spec.js +192 -0
- package/src/components/qualityControls/qualityByControlMode.js +6 -30
- package/src/components/qualityControls/scoreCriterias/ErrorCount.js +0 -1
- package/src/components/qualityControls/scoreCriterias/__tests__/ErrorCount.spec.js +4 -4
- package/src/components/dataViews/queryableProperties/__tests__/__snapshots__/GroupBy.spec.js.snap +0 -604
- package/src/components/qualityControls/controlProperties/Count.js +0 -56
- package/src/components/qualityControls/controlProperties/__tests__/Count.spec.js +0 -66
- package/src/components/qualityControls/controlProperties/__tests__/Ratio.spec.js +0 -95
- package/src/components/qualityControls/controlProperties/__tests__/__snapshots__/Count.spec.js.snap +0 -67
- package/src/components/qualityControls/controlProperties/__tests__/__snapshots__/Ratio.spec.js.snap +0 -161
- package/src/components/qualityControls/scoreCriterias/Count.js +0 -88
- package/src/components/qualityControls/scoreCriterias/__tests__/Count.spec.js +0 -62
- package/src/components/qualityControls/scoreCriterias/__tests__/__snapshots__/Count.spec.js.snap +0 -58
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
import { render, waitForLoad } from "@truedat/test/render";
|
|
2
|
+
|
|
3
|
+
const mockUseFormContext = jest.fn();
|
|
4
|
+
const mockController = jest.fn();
|
|
5
|
+
const mockUseIntl = jest.fn();
|
|
6
|
+
const mockDefaultScoreCriteriaForMode = jest.fn();
|
|
7
|
+
const mockDefaultControlPropertiesForMode = jest.fn();
|
|
8
|
+
const mockSelectableDynamicForm = jest.fn();
|
|
9
|
+
|
|
10
|
+
jest.mock("react-intl", () => ({
|
|
11
|
+
...jest.requireActual("react-intl"),
|
|
12
|
+
useIntl: () => mockUseIntl(),
|
|
13
|
+
}));
|
|
14
|
+
|
|
15
|
+
jest.mock("react-hook-form", () => ({
|
|
16
|
+
useFormContext: () => mockUseFormContext(),
|
|
17
|
+
Controller: (props) => mockController(props),
|
|
18
|
+
}));
|
|
19
|
+
|
|
20
|
+
jest.mock("@truedat/core/components", () => ({
|
|
21
|
+
DomainSelector: ({ value, onChange }) => (
|
|
22
|
+
<div>
|
|
23
|
+
{`domain-selector-${value?.length || 0}`}
|
|
24
|
+
<button type="button" onClick={() => onChange?.(null, { value: [1, 2] })}>change-domain</button>
|
|
25
|
+
</div>
|
|
26
|
+
),
|
|
27
|
+
FieldLabel: ({ children, label }) => (
|
|
28
|
+
<div>
|
|
29
|
+
<span>{label}</span>
|
|
30
|
+
{children}
|
|
31
|
+
</div>
|
|
32
|
+
),
|
|
33
|
+
}));
|
|
34
|
+
|
|
35
|
+
jest.mock("semantic-ui-react", () => ({
|
|
36
|
+
Divider: () => <div>divider</div>,
|
|
37
|
+
Segment: ({ children }) => <div>{children}</div>,
|
|
38
|
+
Form: {
|
|
39
|
+
Radio: ({ label, disabled, checked, onChange }) => (
|
|
40
|
+
<div>
|
|
41
|
+
{`radio-${label}-${disabled}-${checked}`}
|
|
42
|
+
<button type="button" onClick={() => onChange?.(null, { checked: !checked })}>toggle-radio</button>
|
|
43
|
+
</div>
|
|
44
|
+
),
|
|
45
|
+
Input: ({ value, onChange }) => (
|
|
46
|
+
<div>
|
|
47
|
+
{`input-${value}`}
|
|
48
|
+
<button type="button" onClick={() => onChange?.(null, { value: "new-value" })}>change-input</button>
|
|
49
|
+
</div>
|
|
50
|
+
),
|
|
51
|
+
Field: ({ children }) => <div>{children}</div>,
|
|
52
|
+
Dropdown: ({ onChange, value }) => (
|
|
53
|
+
<button
|
|
54
|
+
type="button"
|
|
55
|
+
onClick={() => onChange(null, { value: "error_count" })}
|
|
56
|
+
>{`dropdown-${value}`}</button>
|
|
57
|
+
),
|
|
58
|
+
},
|
|
59
|
+
}));
|
|
60
|
+
|
|
61
|
+
jest.mock("../ScoreCriteria", () => ({
|
|
62
|
+
__esModule: true,
|
|
63
|
+
default: () => <div>score-criteria</div>,
|
|
64
|
+
defaultForMode: (...args) => mockDefaultScoreCriteriaForMode(...args),
|
|
65
|
+
}));
|
|
66
|
+
|
|
67
|
+
jest.mock("../ControlProperties", () => ({
|
|
68
|
+
__esModule: true,
|
|
69
|
+
defaultForMode: (...args) => mockDefaultControlPropertiesForMode(...args),
|
|
70
|
+
}));
|
|
71
|
+
|
|
72
|
+
jest.mock("@truedat/df/components/SelectableDynamicForm", () => ({
|
|
73
|
+
__esModule: true,
|
|
74
|
+
default: (props) => mockSelectableDynamicForm(props),
|
|
75
|
+
}));
|
|
76
|
+
|
|
77
|
+
describe("<InformationForm />", () => {
|
|
78
|
+
const fieldNames = [
|
|
79
|
+
"active",
|
|
80
|
+
"domain_ids",
|
|
81
|
+
"name",
|
|
82
|
+
"df_type",
|
|
83
|
+
"control_mode",
|
|
84
|
+
"score_criteria",
|
|
85
|
+
];
|
|
86
|
+
|
|
87
|
+
beforeEach(() => {
|
|
88
|
+
jest.clearAllMocks();
|
|
89
|
+
|
|
90
|
+
mockUseIntl.mockReturnValue({
|
|
91
|
+
formatMessage: ({ id }) => id,
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
mockDefaultControlPropertiesForMode.mockReturnValue({
|
|
95
|
+
from: "control-properties",
|
|
96
|
+
});
|
|
97
|
+
mockDefaultScoreCriteriaForMode.mockReturnValue({
|
|
98
|
+
from: "score-criteria",
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
const setupControllers = ({
|
|
103
|
+
values = {},
|
|
104
|
+
errors = {},
|
|
105
|
+
handlers = {},
|
|
106
|
+
} = {}) => {
|
|
107
|
+
mockController.mockImplementation(({ name, render }) =>
|
|
108
|
+
render({
|
|
109
|
+
field: {
|
|
110
|
+
onBlur: jest.fn(),
|
|
111
|
+
onChange: handlers[name] || jest.fn(),
|
|
112
|
+
value: values[name],
|
|
113
|
+
},
|
|
114
|
+
fieldState: {
|
|
115
|
+
error: errors[name],
|
|
116
|
+
},
|
|
117
|
+
})
|
|
118
|
+
);
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
const renderComponent = (props = {}) => {
|
|
122
|
+
const InformationForm = require("../InformationForm").default;
|
|
123
|
+
const setValue = jest.fn();
|
|
124
|
+
const setStepInformation = jest.fn();
|
|
125
|
+
const setValidDfContent = jest.fn();
|
|
126
|
+
const stepInformation = props.stepInformation || {};
|
|
127
|
+
|
|
128
|
+
mockUseFormContext.mockReturnValue({
|
|
129
|
+
control: {},
|
|
130
|
+
watch: () => ({
|
|
131
|
+
dynamic_content: { previous: true },
|
|
132
|
+
domain_ids: [2],
|
|
133
|
+
}),
|
|
134
|
+
setValue,
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
mockSelectableDynamicForm.mockImplementation(({ onChange, name }) => (
|
|
138
|
+
<button
|
|
139
|
+
type="button"
|
|
140
|
+
onClick={() =>
|
|
141
|
+
onChange({
|
|
142
|
+
content: { new: "content" },
|
|
143
|
+
valid: [],
|
|
144
|
+
})
|
|
145
|
+
}
|
|
146
|
+
>{`selectable-df-${name}`}</button>
|
|
147
|
+
));
|
|
148
|
+
|
|
149
|
+
const rendered = render(
|
|
150
|
+
<InformationForm
|
|
151
|
+
isModification={false}
|
|
152
|
+
setStepInformation={setStepInformation}
|
|
153
|
+
stepInformation={stepInformation}
|
|
154
|
+
setValidDfContent={setValidDfContent}
|
|
155
|
+
{...props}
|
|
156
|
+
/>
|
|
157
|
+
);
|
|
158
|
+
|
|
159
|
+
return {
|
|
160
|
+
rendered,
|
|
161
|
+
setValue,
|
|
162
|
+
setStepInformation,
|
|
163
|
+
setValidDfContent,
|
|
164
|
+
};
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
it("renders the main fields and score criteria", async () => {
|
|
168
|
+
setupControllers({
|
|
169
|
+
values: {
|
|
170
|
+
active: true,
|
|
171
|
+
domain_ids: [2],
|
|
172
|
+
name: "quality name",
|
|
173
|
+
df_type: "template_1",
|
|
174
|
+
control_mode: "percentage",
|
|
175
|
+
},
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
const { rendered } = renderComponent();
|
|
179
|
+
await waitForLoad(rendered);
|
|
180
|
+
|
|
181
|
+
expect(rendered.getByText(/radio-quality_control.form.active-false-true/i)).toBeInTheDocument();
|
|
182
|
+
expect(rendered.getByText(/domain-selector-1/i)).toBeInTheDocument();
|
|
183
|
+
expect(rendered.getByText(/input-quality name/i)).toBeInTheDocument();
|
|
184
|
+
expect(rendered.getByText(/selectable-df-template_1/i)).toBeInTheDocument();
|
|
185
|
+
expect(rendered.getByText(/score-criteria/i)).toBeInTheDocument();
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
it("updates step information when field names differ", () => {
|
|
189
|
+
setupControllers({
|
|
190
|
+
values: {
|
|
191
|
+
active: true,
|
|
192
|
+
domain_ids: [],
|
|
193
|
+
name: "",
|
|
194
|
+
df_type: "template_1",
|
|
195
|
+
control_mode: "percentage",
|
|
196
|
+
},
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
const stepInformation = { fieldNames: ["active"] };
|
|
200
|
+
const { setStepInformation } = renderComponent({ stepInformation });
|
|
201
|
+
|
|
202
|
+
expect(setStepInformation).toHaveBeenCalledWith(0, {
|
|
203
|
+
...stepInformation,
|
|
204
|
+
fieldNames,
|
|
205
|
+
});
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
it("does not update step information when field names are equal", () => {
|
|
209
|
+
setupControllers({
|
|
210
|
+
values: {
|
|
211
|
+
active: true,
|
|
212
|
+
domain_ids: [],
|
|
213
|
+
name: "",
|
|
214
|
+
df_type: "template_1",
|
|
215
|
+
control_mode: "percentage",
|
|
216
|
+
},
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
const { setStepInformation } = renderComponent({
|
|
220
|
+
stepInformation: { fieldNames },
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
expect(setStepInformation).not.toHaveBeenCalled();
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
it("sets dynamic content and valid df flag when selectable form changes", async () => {
|
|
227
|
+
setupControllers({
|
|
228
|
+
values: {
|
|
229
|
+
active: false,
|
|
230
|
+
domain_ids: [],
|
|
231
|
+
name: "a",
|
|
232
|
+
df_type: "template_2",
|
|
233
|
+
control_mode: "deviation",
|
|
234
|
+
},
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
const { rendered, setValue, setValidDfContent } = renderComponent();
|
|
238
|
+
|
|
239
|
+
rendered.getByRole("button", { name: /selectable-df-template_2/i }).click();
|
|
240
|
+
|
|
241
|
+
expect(setValue).toHaveBeenCalledWith("dynamic_content", { new: "content" }, {
|
|
242
|
+
shouldValidate: true,
|
|
243
|
+
shouldDirty: true,
|
|
244
|
+
});
|
|
245
|
+
expect(setValidDfContent).toHaveBeenCalledWith(true);
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
it("updates dependent fields when control mode changes", () => {
|
|
249
|
+
const controlModeOnChange = jest.fn();
|
|
250
|
+
setupControllers({
|
|
251
|
+
values: {
|
|
252
|
+
active: false,
|
|
253
|
+
domain_ids: [],
|
|
254
|
+
name: "a",
|
|
255
|
+
df_type: "template_3",
|
|
256
|
+
control_mode: "percentage",
|
|
257
|
+
},
|
|
258
|
+
handlers: {
|
|
259
|
+
control_mode: controlModeOnChange,
|
|
260
|
+
},
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
const { rendered, setValue } = renderComponent();
|
|
264
|
+
|
|
265
|
+
rendered.getByRole("button", { name: /dropdown-percentage/i }).click();
|
|
266
|
+
|
|
267
|
+
expect(controlModeOnChange).toHaveBeenCalledWith("error_count");
|
|
268
|
+
expect(mockDefaultControlPropertiesForMode).toHaveBeenCalledWith(
|
|
269
|
+
"error_count"
|
|
270
|
+
);
|
|
271
|
+
expect(mockDefaultScoreCriteriaForMode).toHaveBeenCalledWith("error_count");
|
|
272
|
+
expect(setValue).toHaveBeenCalledWith("control_properties", {
|
|
273
|
+
from: "control-properties",
|
|
274
|
+
});
|
|
275
|
+
expect(setValue).toHaveBeenCalledWith("score_criteria", {
|
|
276
|
+
from: "score-criteria",
|
|
277
|
+
});
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
it("active radio onChange passes checked value to field onChange", async () => {
|
|
281
|
+
const activeOnChange = jest.fn();
|
|
282
|
+
setupControllers({
|
|
283
|
+
values: {
|
|
284
|
+
active: true,
|
|
285
|
+
domain_ids: [],
|
|
286
|
+
name: "",
|
|
287
|
+
df_type: "t",
|
|
288
|
+
control_mode: "percentage",
|
|
289
|
+
},
|
|
290
|
+
handlers: { active: activeOnChange },
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
const { rendered } = renderComponent();
|
|
294
|
+
await waitForLoad(rendered);
|
|
295
|
+
|
|
296
|
+
rendered.getByRole("button", { name: /toggle-radio/i }).click();
|
|
297
|
+
|
|
298
|
+
expect(activeOnChange).toHaveBeenCalledWith(false);
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
it("domain_ids onChange passes selected value to field onChange", async () => {
|
|
302
|
+
const domainOnChange = jest.fn();
|
|
303
|
+
setupControllers({
|
|
304
|
+
values: {
|
|
305
|
+
active: false,
|
|
306
|
+
domain_ids: [1],
|
|
307
|
+
name: "",
|
|
308
|
+
df_type: "t",
|
|
309
|
+
control_mode: "percentage",
|
|
310
|
+
},
|
|
311
|
+
handlers: { domain_ids: domainOnChange },
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
const { rendered } = renderComponent();
|
|
315
|
+
await waitForLoad(rendered);
|
|
316
|
+
|
|
317
|
+
rendered.getByRole("button", { name: /change-domain/i }).click();
|
|
318
|
+
|
|
319
|
+
expect(domainOnChange).toHaveBeenCalledWith([1, 2]);
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
it("name input onChange passes value to field onChange", async () => {
|
|
323
|
+
const nameOnChange = jest.fn();
|
|
324
|
+
setupControllers({
|
|
325
|
+
values: {
|
|
326
|
+
active: false,
|
|
327
|
+
domain_ids: [],
|
|
328
|
+
name: "old",
|
|
329
|
+
df_type: "t",
|
|
330
|
+
control_mode: "percentage",
|
|
331
|
+
},
|
|
332
|
+
handlers: { name: nameOnChange },
|
|
333
|
+
});
|
|
334
|
+
|
|
335
|
+
const { rendered } = renderComponent();
|
|
336
|
+
await waitForLoad(rendered);
|
|
337
|
+
|
|
338
|
+
rendered.getByRole("button", { name: /change-input/i }).click();
|
|
339
|
+
|
|
340
|
+
expect(nameOnChange).toHaveBeenCalledWith("new-value");
|
|
341
|
+
});
|
|
342
|
+
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import userEvent from "@testing-library/user-event";
|
|
2
2
|
import { waitFor } from "@testing-library/react";
|
|
3
3
|
import { render, waitForLoad } from "@truedat/test/render";
|
|
4
|
-
import { QUALITY_CONTROLS } from "@truedat/core/routes";
|
|
4
|
+
import { QUALITY_CONTROLS, linkTo } from "@truedat/core/routes";
|
|
5
5
|
import { SOURCE_OPTIONS_QUERY } from "@truedat/cx/sources/api/queries";
|
|
6
6
|
import { REFERENCE_DATASETS_HEADERS_QUERY } from "@truedat/dd/api/queries";
|
|
7
7
|
import { DOMAINS_QUERY } from "@truedat/core/api/queries";
|
|
@@ -164,7 +164,9 @@ describe("<NewDraftQualityControl />", () => {
|
|
|
164
164
|
});
|
|
165
165
|
|
|
166
166
|
// Save button only appears on step 2 (last step)
|
|
167
|
-
expect(
|
|
167
|
+
expect(
|
|
168
|
+
rendered.queryByRole("button", { name: /save/ })
|
|
169
|
+
).not.toBeInTheDocument();
|
|
168
170
|
|
|
169
171
|
const user = userEvent.setup({ delay: null });
|
|
170
172
|
// Fill step 0 (Information) - make a change to enable save later
|
|
@@ -173,7 +175,9 @@ describe("<NewDraftQualityControl />", () => {
|
|
|
173
175
|
// Navigate to step 1
|
|
174
176
|
await user.click(rendered.getByRole("button", { name: /forward/i }));
|
|
175
177
|
await waitFor(() =>
|
|
176
|
-
expect(
|
|
178
|
+
expect(
|
|
179
|
+
rendered.getByRole("button", { name: /back/i })
|
|
180
|
+
).toBeInTheDocument()
|
|
177
181
|
);
|
|
178
182
|
|
|
179
183
|
// Navigate to step 2
|
|
@@ -195,6 +199,11 @@ describe("<NewDraftQualityControl />", () => {
|
|
|
195
199
|
await waitFor(() =>
|
|
196
200
|
expect(trigger).toHaveBeenCalledWith({ quality_control: qualityControl })
|
|
197
201
|
);
|
|
202
|
+
await waitFor(() =>
|
|
203
|
+
expect(mockNavigate).toHaveBeenCalledWith(
|
|
204
|
+
linkTo.QUALITY_CONTROL({ id: "9", version: "1" })
|
|
205
|
+
)
|
|
206
|
+
);
|
|
198
207
|
});
|
|
199
208
|
|
|
200
209
|
it("test publish submit ", async () => {
|
|
@@ -214,7 +223,9 @@ describe("<NewDraftQualityControl />", () => {
|
|
|
214
223
|
});
|
|
215
224
|
|
|
216
225
|
// Publish button only appears on step 2 (last step)
|
|
217
|
-
expect(
|
|
226
|
+
expect(
|
|
227
|
+
rendered.queryByRole("button", { name: /publish/ })
|
|
228
|
+
).not.toBeInTheDocument();
|
|
218
229
|
|
|
219
230
|
const user = userEvent.setup({ delay: null });
|
|
220
231
|
// Fill step 0 (Information) - make a change to enable publish later
|
|
@@ -223,13 +234,17 @@ describe("<NewDraftQualityControl />", () => {
|
|
|
223
234
|
// Navigate to step 1
|
|
224
235
|
await user.click(rendered.getByRole("button", { name: /forward/i }));
|
|
225
236
|
await waitFor(() =>
|
|
226
|
-
expect(
|
|
237
|
+
expect(
|
|
238
|
+
rendered.getByRole("button", { name: /back/i })
|
|
239
|
+
).toBeInTheDocument()
|
|
227
240
|
);
|
|
228
241
|
|
|
229
242
|
// Navigate to step 2
|
|
230
243
|
await user.click(rendered.getByRole("button", { name: /forward/i }));
|
|
231
244
|
await waitFor(() =>
|
|
232
|
-
expect(
|
|
245
|
+
expect(
|
|
246
|
+
rendered.getByRole("button", { name: /publish/ })
|
|
247
|
+
).toBeInTheDocument()
|
|
233
248
|
);
|
|
234
249
|
|
|
235
250
|
await waitFor(() =>
|
|
@@ -245,6 +260,11 @@ describe("<NewDraftQualityControl />", () => {
|
|
|
245
260
|
await waitFor(() =>
|
|
246
261
|
expect(trigger).toHaveBeenCalledWith({ quality_control: qualityControl })
|
|
247
262
|
);
|
|
263
|
+
await waitFor(() =>
|
|
264
|
+
expect(mockNavigate).toHaveBeenCalledWith(
|
|
265
|
+
linkTo.QUALITY_CONTROL({ id: "9", version: "1" })
|
|
266
|
+
)
|
|
267
|
+
);
|
|
248
268
|
});
|
|
249
269
|
|
|
250
270
|
it("when no quality control is fetched, do not render editor", async () => {
|
|
@@ -3,6 +3,7 @@ import { act, waitFor } from "@testing-library/react";
|
|
|
3
3
|
import { render, waitForLoad } from "@truedat/test/render";
|
|
4
4
|
import { singleTemplateMock, templateByNameMock } from "@truedat/test/mocks";
|
|
5
5
|
import { DOMAINS_QUERY } from "@truedat/core/api/queries";
|
|
6
|
+
import { QUALITY_CONTROLS, linkTo } from "@truedat/core/routes";
|
|
6
7
|
import { SOURCE_OPTIONS_QUERY } from "@truedat/cx/sources/api/queries";
|
|
7
8
|
import { REFERENCE_DATASETS_HEADERS_QUERY } from "@truedat/dd/api/queries";
|
|
8
9
|
import { useQualityControlCreate } from "@truedat/qx/hooks/useQualityControls";
|
|
@@ -18,7 +19,7 @@ jest.mock("react-router", () => ({
|
|
|
18
19
|
|
|
19
20
|
jest.mock("@truedat/qx/hooks/useQualityControls", () => ({
|
|
20
21
|
useQualityControlCreate: jest.fn(() => ({
|
|
21
|
-
trigger: jest.fn(() => new Promise(() => {
|
|
22
|
+
trigger: jest.fn(() => new Promise(() => {})),
|
|
22
23
|
isMutating: false,
|
|
23
24
|
})),
|
|
24
25
|
}));
|
|
@@ -128,7 +129,7 @@ describe("<NewQualityControl />", () => {
|
|
|
128
129
|
await user.click(rendered.getByText(/confirmation.yes/i));
|
|
129
130
|
|
|
130
131
|
await waitFor(() => expect(mockNavigate.mock.calls.length).toBe(1));
|
|
131
|
-
expect(mockNavigate.mock.calls[0][0]).toBe(
|
|
132
|
+
expect(mockNavigate.mock.calls[0][0]).toBe(QUALITY_CONTROLS);
|
|
132
133
|
});
|
|
133
134
|
|
|
134
135
|
it("test save submit ", async () => {
|
|
@@ -149,7 +150,9 @@ describe("<NewQualityControl />", () => {
|
|
|
149
150
|
});
|
|
150
151
|
|
|
151
152
|
// Save button only appears on step 2 (last step)
|
|
152
|
-
expect(
|
|
153
|
+
expect(
|
|
154
|
+
rendered.queryByRole("button", { name: /save/i })
|
|
155
|
+
).not.toBeInTheDocument();
|
|
153
156
|
|
|
154
157
|
// Fill step 0 (Information)
|
|
155
158
|
// Select a domain
|
|
@@ -186,7 +189,9 @@ describe("<NewQualityControl />", () => {
|
|
|
186
189
|
// Navigate to step 1 (Control Properties)
|
|
187
190
|
await user.click(rendered.getByRole("button", { name: /forward/i }));
|
|
188
191
|
await waitFor(() =>
|
|
189
|
-
expect(
|
|
192
|
+
expect(
|
|
193
|
+
rendered.getByRole("button", { name: /back/i })
|
|
194
|
+
).toBeInTheDocument()
|
|
190
195
|
);
|
|
191
196
|
|
|
192
197
|
// Fill step 1 - Source selector is now in step 1
|
|
@@ -209,7 +214,9 @@ describe("<NewQualityControl />", () => {
|
|
|
209
214
|
// Navigate to step 2 (Segmentation)
|
|
210
215
|
await user.click(rendered.getByRole("button", { name: /forward/i }));
|
|
211
216
|
await waitFor(() =>
|
|
212
|
-
expect(
|
|
217
|
+
expect(
|
|
218
|
+
rendered.getByRole("button", { name: /save/i })
|
|
219
|
+
).toBeInTheDocument()
|
|
213
220
|
);
|
|
214
221
|
|
|
215
222
|
await waitFor(() =>
|
|
@@ -297,6 +304,11 @@ describe("<NewQualityControl />", () => {
|
|
|
297
304
|
},
|
|
298
305
|
})
|
|
299
306
|
);
|
|
307
|
+
await waitFor(() =>
|
|
308
|
+
expect(mockNavigate).toHaveBeenCalledWith(
|
|
309
|
+
linkTo.QUALITY_CONTROL({ id: "9", version: "1" })
|
|
310
|
+
)
|
|
311
|
+
);
|
|
300
312
|
});
|
|
301
313
|
|
|
302
314
|
it("test publish submit ", async () => {
|
|
@@ -317,19 +329,34 @@ describe("<NewQualityControl />", () => {
|
|
|
317
329
|
});
|
|
318
330
|
|
|
319
331
|
// Publish button only appears on step 2 (last step)
|
|
320
|
-
expect(
|
|
332
|
+
expect(
|
|
333
|
+
rendered.queryByRole("button", { name: /publish/i })
|
|
334
|
+
).not.toBeInTheDocument();
|
|
321
335
|
|
|
322
336
|
// Fill step 0 (Information)
|
|
323
337
|
// Fill in the 'Name' field
|
|
324
338
|
await user.type(rendered.getByPlaceholderText(/name/i), "test_modified");
|
|
325
339
|
|
|
326
|
-
// Select a domain
|
|
340
|
+
// Select a domain (template loads and auto-selects when single; dynamic form appears)
|
|
327
341
|
await user.click(rendered.getByText(/domain.multiple.placeholder/i));
|
|
328
342
|
await user.click(rendered.getByText(/bardomain/i));
|
|
329
343
|
|
|
344
|
+
// Interact with dynamic form so setDfContent runs and validDfContent becomes true (required for Publish)
|
|
345
|
+
await waitFor(() =>
|
|
346
|
+
expect(rendered.getByPlaceholderText(/field1/i)).toBeInTheDocument()
|
|
347
|
+
);
|
|
348
|
+
await user.type(
|
|
349
|
+
rendered.getByPlaceholderText(/field1/i),
|
|
350
|
+
"field_template_modified"
|
|
351
|
+
);
|
|
352
|
+
await waitFor(() => {
|
|
353
|
+
const input = rendered.getByPlaceholderText(/field1/i);
|
|
354
|
+
expect(input).toHaveValue("field_template_modified");
|
|
355
|
+
});
|
|
356
|
+
|
|
330
357
|
await user.click(
|
|
331
358
|
rendered.getByRole("option", {
|
|
332
|
-
name: /quality_control.control_mode.
|
|
359
|
+
name: /quality_control.control_mode.error_count/i,
|
|
333
360
|
})
|
|
334
361
|
);
|
|
335
362
|
|
|
@@ -337,7 +364,7 @@ describe("<NewQualityControl />", () => {
|
|
|
337
364
|
await waitFor(() => {
|
|
338
365
|
expect(
|
|
339
366
|
rendered.getByPlaceholderText(
|
|
340
|
-
/quality_control.score_criteria.
|
|
367
|
+
/quality_control.score_criteria.error_count.goal/i
|
|
341
368
|
)
|
|
342
369
|
).toBeInTheDocument();
|
|
343
370
|
});
|
|
@@ -345,14 +372,14 @@ describe("<NewQualityControl />", () => {
|
|
|
345
372
|
// Fill in the 'Goal' field
|
|
346
373
|
await user.type(
|
|
347
374
|
rendered.getByPlaceholderText(
|
|
348
|
-
/quality_control.score_criteria.
|
|
375
|
+
/quality_control.score_criteria.error_count.goal/i
|
|
349
376
|
),
|
|
350
377
|
"25"
|
|
351
378
|
);
|
|
352
379
|
// Fill in the 'Threshold' field
|
|
353
380
|
await user.type(
|
|
354
381
|
rendered.getByPlaceholderText(
|
|
355
|
-
/quality_control.score_criteria.
|
|
382
|
+
/quality_control.score_criteria.error_count.maximum/i
|
|
356
383
|
),
|
|
357
384
|
"50"
|
|
358
385
|
);
|
|
@@ -360,7 +387,9 @@ describe("<NewQualityControl />", () => {
|
|
|
360
387
|
// Navigate to step 1 (Control Properties)
|
|
361
388
|
await user.click(rendered.getByRole("button", { name: /forward/i }));
|
|
362
389
|
await waitFor(() =>
|
|
363
|
-
expect(
|
|
390
|
+
expect(
|
|
391
|
+
rendered.getByRole("button", { name: /back/i })
|
|
392
|
+
).toBeInTheDocument()
|
|
364
393
|
);
|
|
365
394
|
|
|
366
395
|
// Fill step 1 - Source selector is now in step 1
|
|
@@ -377,28 +406,40 @@ describe("<NewQualityControl />", () => {
|
|
|
377
406
|
);
|
|
378
407
|
await user.click(rendered.getByRole("option", { name: /dataset1/i }));
|
|
379
408
|
|
|
409
|
+
await waitFor(() =>
|
|
410
|
+
expect(
|
|
411
|
+
rendered.getAllByRole("option", { name: /campo1/ }).length
|
|
412
|
+
).toBeGreaterThan(0)
|
|
413
|
+
);
|
|
414
|
+
await act(async () => {
|
|
415
|
+
await user.click(rendered.getAllByRole("option", { name: /campo1/ })[0]);
|
|
416
|
+
await user.click(rendered.getByRole("option", { name: "eq" }));
|
|
417
|
+
await user.click(rendered.getAllByRole("option", { name: /campo2/ })[1]);
|
|
418
|
+
});
|
|
419
|
+
|
|
380
420
|
// Navigate to step 2 (Segmentation)
|
|
381
421
|
await user.click(rendered.getByRole("button", { name: /forward/i }));
|
|
382
422
|
await waitFor(() =>
|
|
383
|
-
expect(
|
|
423
|
+
expect(
|
|
424
|
+
rendered.getByRole("button", { name: /publish/i })
|
|
425
|
+
).toBeInTheDocument()
|
|
384
426
|
);
|
|
385
427
|
|
|
386
428
|
await waitFor(() =>
|
|
387
429
|
expect(rendered.getByRole("button", { name: /publish/i })).toBeEnabled()
|
|
388
430
|
);
|
|
389
|
-
await user.click(rendered.
|
|
431
|
+
await user.click(rendered.getByRole("button", { name: /publish/i }));
|
|
390
432
|
|
|
391
433
|
await waitFor(() =>
|
|
392
434
|
expect(trigger).toHaveBeenCalledWith({
|
|
393
|
-
quality_control: {
|
|
435
|
+
quality_control: expect.objectContaining({
|
|
394
436
|
name: "test_modified",
|
|
395
437
|
active: true,
|
|
396
438
|
domain_ids: ["2"],
|
|
397
439
|
df_type: "template1",
|
|
398
440
|
source_id: 181,
|
|
399
|
-
control_mode: "
|
|
400
|
-
|
|
401
|
-
control_properties: {
|
|
441
|
+
control_mode: "error_count",
|
|
442
|
+
control_properties: expect.objectContaining({
|
|
402
443
|
errors_resource: {
|
|
403
444
|
type: "reference_dataset",
|
|
404
445
|
id: 7,
|
|
@@ -422,11 +463,16 @@ describe("<NewQualityControl />", () => {
|
|
|
422
463
|
],
|
|
423
464
|
},
|
|
424
465
|
},
|
|
425
|
-
},
|
|
466
|
+
}),
|
|
426
467
|
score_criteria: { goal: "25", maximum: "50" },
|
|
427
468
|
status: "published",
|
|
428
|
-
},
|
|
469
|
+
}),
|
|
429
470
|
})
|
|
430
471
|
);
|
|
472
|
+
await waitFor(() =>
|
|
473
|
+
expect(mockNavigate).toHaveBeenCalledWith(
|
|
474
|
+
linkTo.QUALITY_CONTROL({ id: "9", version: "1" })
|
|
475
|
+
)
|
|
476
|
+
);
|
|
431
477
|
});
|
|
432
478
|
});
|
|
@@ -109,12 +109,12 @@ describe("<QualityBadgeForSearch />", () => {
|
|
|
109
109
|
result: 200,
|
|
110
110
|
result_message: "under_threshold",
|
|
111
111
|
status: "succeeded",
|
|
112
|
-
type: "
|
|
112
|
+
type: "error_count",
|
|
113
113
|
};
|
|
114
114
|
|
|
115
115
|
const rendered = render(
|
|
116
116
|
<QualityBadgeForSearch
|
|
117
|
-
controlMode={"
|
|
117
|
+
controlMode={"error_count"}
|
|
118
118
|
criteria={scoreCriteria}
|
|
119
119
|
latestScore={latestScore}
|
|
120
120
|
/>
|
|
@@ -154,7 +154,7 @@ describe("<QualityBadgeForSearch />", () => {
|
|
|
154
154
|
};
|
|
155
155
|
const rendered = render(
|
|
156
156
|
<QualityBadgeForSearch
|
|
157
|
-
controlMode={"
|
|
157
|
+
controlMode={"error_count"}
|
|
158
158
|
criteria={scoreCriteria}
|
|
159
159
|
latestScore={latestScore}
|
|
160
160
|
/>
|
|
@@ -190,4 +190,31 @@ describe("<QualityBadgeForSearch />", () => {
|
|
|
190
190
|
|
|
191
191
|
expect(rendered.queryByText(/score.no_results/i)).toBeInTheDocument();
|
|
192
192
|
});
|
|
193
|
+
|
|
194
|
+
it("matches the latest snapshot for default count mode", async () => {
|
|
195
|
+
const scoreCriteria = {
|
|
196
|
+
goal: 30,
|
|
197
|
+
maximum: 40,
|
|
198
|
+
};
|
|
199
|
+
const latestScore = {
|
|
200
|
+
executed_at: "2025-03-25T05:34:21.438113Z",
|
|
201
|
+
count_content: {
|
|
202
|
+
count: 20,
|
|
203
|
+
},
|
|
204
|
+
result: 20,
|
|
205
|
+
result_message: "under_goal",
|
|
206
|
+
status: "succeeded",
|
|
207
|
+
type: "count",
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
const rendered = render(
|
|
211
|
+
<QualityBadgeForSearch
|
|
212
|
+
controlMode={"count"}
|
|
213
|
+
criteria={scoreCriteria}
|
|
214
|
+
latestScore={latestScore}
|
|
215
|
+
/>
|
|
216
|
+
);
|
|
217
|
+
await waitForLoad(rendered);
|
|
218
|
+
expect(rendered.container).toMatchSnapshot();
|
|
219
|
+
});
|
|
193
220
|
});
|