@truedat/dq 4.47.4 → 4.47.7

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.
Files changed (23) hide show
  1. package/CHANGELOG.md +16 -1
  2. package/package.json +5 -5
  3. package/src/api/queries.js +5 -0
  4. package/src/components/ConditionSummary.js +63 -21
  5. package/src/components/NewRuleImplementation.js +21 -46
  6. package/src/components/RuleImplementationResults.js +5 -3
  7. package/src/components/__test_samples__/newRuleImplementationHelper.js +1239 -0
  8. package/src/components/__tests__/NewRuleImplementation.spec.js +273 -6
  9. package/src/components/ruleImplementationForm/FiltersField.js +31 -11
  10. package/src/components/ruleImplementationForm/FiltersFormGroup.js +1 -1
  11. package/src/components/ruleImplementationForm/FiltersGrid.js +18 -6
  12. package/src/components/ruleImplementationForm/FiltersGroup.js +3 -3
  13. package/src/components/ruleImplementationForm/InformationForm.js +2 -0
  14. package/src/components/ruleImplementationForm/RuleImplementationForm.js +1 -1
  15. package/src/components/ruleImplementationForm/RuleImplementationRawForm.js +30 -1
  16. package/src/components/ruleImplementationForm/__tests__/RuleImplementationRawForm.spec.js +24 -24
  17. package/src/components/ruleImplementationForm/__tests__/__snapshots__/FiltersFormGroup.spec.js.snap +7 -1
  18. package/src/components/ruleImplementationForm/__tests__/__snapshots__/FiltersGroup.spec.js.snap +8 -1
  19. package/src/components/ruleImplementationForm/__tests__/__snapshots__/RuleImplementationRawForm.spec.js.snap +67 -0
  20. package/src/components/ruleImplementationForm/__tests__/__snapshots__/ValueConditions.spec.js.snap +7 -1
  21. package/src/messages/en.js +2 -1
  22. package/src/messages/es.js +2 -1
  23. package/src/selectors/getRuleImplementationOperators.js +1 -0
@@ -1,20 +1,29 @@
1
+ import _ from "lodash/fp";
1
2
  import React from "react";
2
- import { waitFor } from "@testing-library/react";
3
+ import { waitFor, within } from "@testing-library/react";
3
4
  import { render } from "@truedat/test/render";
4
5
  import { multipleTemplatesMock } from "@truedat/test/mocks";
5
- import { NewRuleImplementation } from "../NewRuleImplementation";
6
+ import userEvent from "@testing-library/user-event";
7
+ import defaultMessages from "@truedat/test/messages";
8
+ import NewRuleImplementation, {
9
+ NewRuleImplementation as NewRuleImplementationComponent,
10
+ } from "../NewRuleImplementation";
6
11
  import { newRuleImplementationProps } from "../__test_samples__/NewRuleImplementationProps";
12
+ import {
13
+ ruleImplementationLoaderGlobalState,
14
+ ruleImplementationLoaderActions,
15
+ } from "../__test_samples__/newRuleImplementationHelper";
7
16
 
8
17
  describe("<NewRuleImplementation />", () => {
9
18
  const createRuleImplementation = jest.fn();
10
19
  const updateRuleImplementation = jest.fn();
11
- const sources = [{ id: 1, external_id: "foo", config: { alias: ["foo"] } }];
20
+
12
21
  const ruleImplementationProps = { id: 1, name: "nn", executable: true };
22
+
13
23
  const props = {
14
24
  ruleImplementationProps,
15
25
  createRuleImplementation,
16
26
  updateRuleImplementation,
17
- sources,
18
27
  };
19
28
  const renderOpts = {
20
29
  mocks: [
@@ -32,11 +41,11 @@ describe("<NewRuleImplementation />", () => {
32
41
  <NewRuleImplementation {...props} />,
33
42
  renderOpts
34
43
  );
44
+
35
45
  await waitFor(() => expect(queryByText(/lazy/i)).not.toBeInTheDocument());
36
46
  await waitFor(() =>
37
47
  expect(queryByText(/loading/i)).not.toBeInTheDocument()
38
48
  );
39
-
40
49
  expect(container).toMatchSnapshot();
41
50
  });
42
51
 
@@ -47,7 +56,7 @@ describe("<NewRuleImplementation />", () => {
47
56
  applyTemplate: applyTemplate,
48
57
  };
49
58
  const { container, queryByText } = render(
50
- <NewRuleImplementation {...props} />,
59
+ <NewRuleImplementationComponent {...props} />,
51
60
  renderOpts
52
61
  );
53
62
  await waitFor(() => expect(queryByText(/lazy/i)).not.toBeInTheDocument());
@@ -57,3 +66,261 @@ describe("<NewRuleImplementation />", () => {
57
66
  expect(container).toMatchSnapshot();
58
67
  });
59
68
  });
69
+
70
+ describe("<NewRuleImplementation> NewRuleImplementation doSubmit", () => {
71
+ const dispatch = jest.fn();
72
+
73
+ const renderOptsImplementationEdit = {
74
+ mocks: [
75
+ multipleTemplatesMock({
76
+ scope: "ri",
77
+ domainIds: [2],
78
+ }),
79
+ ],
80
+ messages: {
81
+ en: {
82
+ ...defaultMessages.en,
83
+ // This is in td-web
84
+ "filtersGrid.field.modifier.cast_as_date": "Cast as date",
85
+ },
86
+ },
87
+ state: ruleImplementationLoaderGlobalState,
88
+ fallback: "lazy",
89
+ dispatch,
90
+ };
91
+
92
+ const props = {
93
+ ...ruleImplementationLoaderActions,
94
+ edition: true,
95
+ };
96
+
97
+ const expectedRuleImplementationBase = {
98
+ dataset: [
99
+ {
100
+ alias: { index: 4, text: null },
101
+ clauses: [],
102
+ structure: { id: 11127104 },
103
+ },
104
+ ],
105
+ df_content: {},
106
+ df_name: "template1",
107
+ domain_id: 2,
108
+ executable: true,
109
+ goal: 90,
110
+ id: 1329 + 1,
111
+ implementation_key: "oracle_prueba",
112
+ implementation_type: "default",
113
+ minimum: 80,
114
+ populations: [],
115
+ result_type: "percentage",
116
+ rule_id: undefined,
117
+ segments: [],
118
+ status: undefined,
119
+ };
120
+
121
+ it("doSubmit: is empty operator", async () => {
122
+ const expectedRuleImplementation = {
123
+ ...expectedRuleImplementationBase,
124
+ validations: [
125
+ {
126
+ modifier: null,
127
+ operator: { name: "empty" },
128
+ population: [],
129
+ structure: { id: 11127109, parent_index: 4 },
130
+ value: [],
131
+ value_modifier: [],
132
+ },
133
+ ],
134
+ };
135
+
136
+ const { queryByText, getByRole, findByRole, findByTestId } = render(
137
+ <NewRuleImplementation {...props} />,
138
+ renderOptsImplementationEdit
139
+ );
140
+
141
+ // Information Form
142
+
143
+ await waitFor(() => {
144
+ expect(queryByText(/Template/)).toBeTruthy();
145
+ });
146
+
147
+ userEvent.click(await findByRole("option", { name: "template1" }));
148
+
149
+ await waitFor(() => {
150
+ expect(getByRole("button", { name: "Next" })).toBeEnabled();
151
+ });
152
+ userEvent.click(await getByRole("button", { name: "Next" }));
153
+
154
+ // Dataset Form
155
+
156
+ await waitFor(() => {
157
+ expect(getByRole("button", { name: "Next" })).toBeEnabled();
158
+ });
159
+ userEvent.click(await getByRole("button", { name: "Next" }));
160
+
161
+ // Population Form
162
+
163
+ await waitFor(() => {
164
+ expect(getByRole("button", { name: "Next" })).toBeEnabled();
165
+ });
166
+ userEvent.click(await getByRole("button", { name: "Next" }));
167
+
168
+ // Validations Form
169
+
170
+ userEvent.click(await findByRole("button", { name: "add-condition-row" }));
171
+
172
+ const row = await findByTestId("row-0");
173
+
174
+ const field = row.querySelector('div[label="Field"]');
175
+ const operator = row.querySelector('div[label="Operator"]');
176
+
177
+ userEvent.click(field);
178
+ const fieldOptions = await within(field).findByRole("listbox");
179
+ const emailFieldOption = within(fieldOptions).getByText("EMAIL");
180
+ userEvent.click(emailFieldOption);
181
+ const selectedField = fieldOptions.querySelector(".selected>span");
182
+ expect(within(selectedField).queryByText(/EMAIL/)).toBeInTheDocument();
183
+
184
+ userEvent.click(operator);
185
+ const operatorOptions = await within(operator).findByRole("listbox");
186
+ const emptyOperatorOption = within(operatorOptions).getByText("is empty");
187
+ userEvent.click(emptyOperatorOption);
188
+ const selectedOperator = operatorOptions.querySelector(".selected>span");
189
+ expect(
190
+ within(selectedOperator).queryByText(/is empty/)
191
+ ).toBeInTheDocument();
192
+
193
+ await waitFor(() => {
194
+ expect(getByRole("button", { name: "Save" })).toBeEnabled();
195
+ });
196
+
197
+ userEvent.click(await getByRole("button", { name: "Save" }));
198
+
199
+ expect(dispatch).toHaveBeenCalledWith({
200
+ ...ruleImplementationLoaderActions.updateRuleImplementation(),
201
+ payload: { rule_implementation: expectedRuleImplementation },
202
+ });
203
+ });
204
+
205
+ it("doSubmit: unique across fields operator", async () => {
206
+ const expectedRuleImplementation = {
207
+ ...expectedRuleImplementationBase,
208
+ validations: [
209
+ {
210
+ modifier: null,
211
+ operator: { name: "unique", value_type: "field_list" },
212
+ population: [],
213
+ structure: { id: 11127109, parent_index: 4 },
214
+ value: [
215
+ {
216
+ fields: [
217
+ {
218
+ id: 11127109,
219
+ name: "EMAIL",
220
+ parent_index: 4,
221
+ path: undefined,
222
+ },
223
+ {
224
+ id: 11127116,
225
+ name: "PHONE_NUMBER",
226
+ parent_index: 4,
227
+ path: undefined,
228
+ },
229
+ ],
230
+ },
231
+ ],
232
+ value_modifier: [],
233
+ },
234
+ ],
235
+ };
236
+
237
+ const { queryByText, getByRole, findByRole, findByTestId } = render(
238
+ <NewRuleImplementation {...props} />,
239
+ renderOptsImplementationEdit
240
+ );
241
+
242
+ // Information Form
243
+
244
+ await waitFor(() => {
245
+ expect(queryByText(/Template/)).toBeTruthy();
246
+ });
247
+
248
+ userEvent.click(await findByRole("option", { name: "template1" }));
249
+
250
+ await waitFor(() => {
251
+ expect(getByRole("button", { name: "Next" })).toBeEnabled();
252
+ });
253
+ userEvent.click(await getByRole("button", { name: "Next" }));
254
+
255
+ // Dataset Form
256
+
257
+ await waitFor(() => {
258
+ expect(getByRole("button", { name: "Next" })).toBeEnabled();
259
+ });
260
+ userEvent.click(await getByRole("button", { name: "Next" }));
261
+
262
+ // Population Form
263
+
264
+ await waitFor(() => {
265
+ expect(getByRole("button", { name: "Next" })).toBeEnabled();
266
+ });
267
+ userEvent.click(await getByRole("button", { name: "Next" }));
268
+
269
+ // Validations Form
270
+
271
+ userEvent.click(await findByRole("button", { name: "add-condition-row" }));
272
+
273
+ const row = await findByTestId("row-0");
274
+
275
+ const field = row.querySelector('div[label="Field"]');
276
+ const operator = row.querySelector('div[label="Operator"]');
277
+
278
+ userEvent.click(field);
279
+ const fieldOptions = await within(field).findByRole("listbox");
280
+ const emailFieldOption = within(fieldOptions).getByText("EMAIL");
281
+ userEvent.click(emailFieldOption);
282
+ const selectedField = fieldOptions.querySelector(".selected>span");
283
+ expect(within(selectedField).queryByText(/EMAIL/)).toBeInTheDocument();
284
+
285
+ userEvent.click(operator);
286
+ const operatorOptions = await within(operator).findByRole("listbox");
287
+ const uniqueAcrossFieldsOperatorOption = within(operatorOptions).getByText(
288
+ "unique across fields"
289
+ );
290
+ userEvent.click(uniqueAcrossFieldsOperatorOption);
291
+ const selectedOperator = operatorOptions.querySelector(".selected>span");
292
+ expect(
293
+ within(selectedOperator).queryByText(/unique across fields/)
294
+ ).toBeInTheDocument();
295
+
296
+ const updatedRow = await findByTestId("row-0");
297
+ const value = updatedRow.querySelector('div[label="Value"]');
298
+ userEvent.click(value);
299
+ const valueOptions = await within(value).findByRole("listbox");
300
+ const valueEmailFieldOption = within(valueOptions).getByText("EMAIL");
301
+ const valuePhoneNumberFieldOption =
302
+ within(valueOptions).getByText("PHONE_NUMBER");
303
+
304
+ userEvent.click(valueEmailFieldOption);
305
+ userEvent.click(valuePhoneNumberFieldOption);
306
+ const selectedFieldValues = updatedRow.querySelectorAll(".label");
307
+
308
+ const selectedFieldTexts = [...selectedFieldValues].map(
309
+ (selectedFieldValue) => selectedFieldValue.text
310
+ );
311
+
312
+ expect(_.difference(selectedFieldTexts, ["EMAIL", "PHONE_NUMBER"])).toEqual(
313
+ []
314
+ );
315
+
316
+ await waitFor(() => {
317
+ expect(getByRole("button", { name: "Save" })).toBeEnabled();
318
+ });
319
+ userEvent.click(await getByRole("button", { name: "Save" }));
320
+
321
+ expect(dispatch).toHaveBeenCalledWith({
322
+ ...ruleImplementationLoaderActions.updateRuleImplementation(),
323
+ payload: { rule_implementation: expectedRuleImplementation },
324
+ });
325
+ });
326
+ });
@@ -48,6 +48,19 @@ export const FiltersField = ({
48
48
  const { value_type, value_type_filter, fixed_values } = operator;
49
49
 
50
50
  const modifierDef = _.find({ name: modifier?.name })(typeCastModifiers);
51
+ const pickFromValue = _.pick(["data_structure_id", "name", "parent_index"]);
52
+
53
+ const getVal = (value) =>
54
+ _.isNil(_.prop("parent_index")(value))
55
+ ? _.prop("id")(value)
56
+ : `${_.prop("id")(value)}/${_.prop("parent_index")(value)}`;
57
+
58
+ const getValue = (valueOrValues, operator) =>
59
+ operator?.value_type === "field_list"
60
+ ? (valueOrValues?.fields || []).map((v) => {
61
+ return getVal(v);
62
+ })
63
+ : getVal(valueOrValues);
51
64
 
52
65
  switch (value_type) {
53
66
  case "string":
@@ -89,6 +102,7 @@ export const FiltersField = ({
89
102
  case "timestamp":
90
103
  return <DateTimeField label={label} value={value} onChange={onChange} />;
91
104
  case "field":
105
+ case "field_list":
92
106
  const structureFields = getStructureFields(parentStructures);
93
107
  return value_type_filter == "any" ? (
94
108
  <StructureSelectorInputField
@@ -111,24 +125,30 @@ export const FiltersField = ({
111
125
  ) : (
112
126
  <>
113
127
  <StructureFieldsDropdown
128
+ multiple={value_type === "field_list"}
114
129
  label={label}
115
130
  inline={false}
116
131
  parentStructures={parentStructures}
117
132
  structureFields={structureFields}
118
133
  typeCastModifiers={typeCastModifiers}
119
- filters={{ field_type: [fieldType] }}
120
- onSelectField={(value, modifier) =>
134
+ filters={
135
+ value_type === "field_list" ? null : { field_type: [fieldType] }
136
+ }
137
+ onSelectField={(value, modifier) => {
121
138
  onChange(
122
139
  null,
123
- _.pick(["data_structure_id", "name", "parent_index"])(value),
140
+ pickFromValue(value),
124
141
  modifier ? { name: modifier.name } : null
125
- )
126
- }
127
- value={
128
- _.isNil(_.prop("parent_index")(value))
129
- ? _.prop("id")(value)
130
- : `${_.prop("id")(value)}/${_.prop("parent_index")(value)}`
131
- }
142
+ );
143
+ }}
144
+ onSelectFields={(values) => {
145
+ onChange(
146
+ null,
147
+ values.map((value) => pickFromValue(value)),
148
+ null
149
+ );
150
+ }}
151
+ value={getValue(value, operator)}
132
152
  />
133
153
  {modifier && (
134
154
  <FieldModifier
@@ -158,7 +178,7 @@ FiltersField.propTypes = {
158
178
  parentStructures: PropTypes.array,
159
179
  operator: PropTypes.object,
160
180
  fieldType: PropTypes.string,
161
- value: PropTypes.string,
181
+ value: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
162
182
  name: PropTypes.string,
163
183
  onChange: PropTypes.func,
164
184
  modifier: PropTypes.object,
@@ -162,7 +162,7 @@ FiltersFormGroup.propTypes = {
162
162
  parentStructures: PropTypes.array,
163
163
  siblings: PropTypes.array,
164
164
  scope: PropTypes.string,
165
- operators: PropTypes.array,
165
+ operators: PropTypes.object,
166
166
  };
167
167
 
168
168
  export default FiltersFormGroup;
@@ -56,13 +56,21 @@ export const FiltersGrid = ({
56
56
  });
57
57
  };
58
58
 
59
+ const composeFieldValue = (value) => ({
60
+ id: value.data_structure_id || value.id,
61
+ name: value.name,
62
+ path: value.path,
63
+ parent_index: value.parent_index,
64
+ });
65
+
59
66
  const composeValue = (value_type, value) => {
60
67
  if (value_type == "field") {
68
+ return composeFieldValue(value);
69
+ } else if (value_type === "field_list") {
61
70
  return {
62
- id: value.data_structure_id || value.id,
63
- name: value.name,
64
- path: value.path,
65
- parent_index: value.parent_index,
71
+ fields: _.map((v) => {
72
+ return composeFieldValue(v);
73
+ })(value),
66
74
  };
67
75
  } else {
68
76
  return { raw: value };
@@ -151,7 +159,11 @@ export const FiltersGrid = ({
151
159
  scope={scope}
152
160
  />
153
161
  </Grid>
154
- <Button onClick={onRowAddition} icon="plus circle" />
162
+ <Button
163
+ aria-label="add-condition-row"
164
+ onClick={onRowAddition}
165
+ icon="plus circle"
166
+ />
155
167
  </>
156
168
  );
157
169
  };
@@ -161,7 +173,7 @@ FiltersGrid.propTypes = {
161
173
  setRowValue: PropTypes.func,
162
174
  scope: PropTypes.string,
163
175
  structures: PropTypes.array,
164
- typeOperators: PropTypes.array,
176
+ typeOperators: PropTypes.object,
165
177
  };
166
178
 
167
179
  export default FiltersGrid;
@@ -50,7 +50,7 @@ const Filter = ({
50
50
  _.filter((v) => !_.isNil(v?.id))(row?.value || []);
51
51
  return (
52
52
  <>
53
- <Grid.Row>
53
+ <Grid.Row data-testid={`row-${index}`}>
54
54
  <Grid.Column width={14}>
55
55
  <FiltersFormGroup
56
56
  clause={clause}
@@ -126,7 +126,7 @@ const Filter = ({
126
126
  Filter.propTypes = {
127
127
  activeConditionIndex: PropTypes.number,
128
128
  allOperators: PropTypes.array,
129
- operators: PropTypes.array,
129
+ operators: PropTypes.object,
130
130
  clause: PropTypes.object,
131
131
  composeValue: PropTypes.func,
132
132
  onConditionChange: PropTypes.func,
@@ -182,7 +182,7 @@ export const FiltersGroup = ({
182
182
  FiltersGroup.propTypes = {
183
183
  activeConditionIndex: PropTypes.number,
184
184
  allOperators: PropTypes.array,
185
- operators: PropTypes.array,
185
+ operators: PropTypes.object,
186
186
  composeValue: PropTypes.func,
187
187
  onConditionChange: PropTypes.func,
188
188
  onOperatorChange: PropTypes.func,
@@ -25,6 +25,7 @@ export const InformationForm = ({
25
25
 
26
26
  const handleContentChange = ({ content, valid }) => {
27
27
  onChange("dfContent", content);
28
+
28
29
  setIsValid(_.isEmpty(valid));
29
30
  };
30
31
  const domainId = ruleImplementation?.domain_id || rule?.domain_id;
@@ -64,6 +65,7 @@ export const InformationForm = ({
64
65
  autoComplete="off"
65
66
  />
66
67
  </Form.Field>
68
+
67
69
  {_.isEmpty(rule) && !ruleImplementation?.rule_id ? (
68
70
  <Form.Field>
69
71
  <DomainDropdownSelector
@@ -350,7 +350,7 @@ RuleImplementationForm.propTypes = {
350
350
  addSegments: PropTypes.func,
351
351
  authManageSegments: PropTypes.bool,
352
352
  isAdmin: PropTypes.bool,
353
- isSubmitting: PropTypes.bool.isRequired,
353
+ isSubmitting: PropTypes.bool,
354
354
  onChange: PropTypes.func,
355
355
  onSubmit: PropTypes.func.isRequired,
356
356
  operators: PropTypes.object,
@@ -4,6 +4,8 @@ import PropTypes from "prop-types";
4
4
  import { connect } from "react-redux";
5
5
  import { useHistory } from "react-router-dom";
6
6
  import { FormattedMessage, useIntl } from "react-intl";
7
+ import { gql, useQuery } from "@apollo/client";
8
+ import { Loading } from "@truedat/core/components";
7
9
  import { Button, Form, Icon, Popup } from "semantic-ui-react";
8
10
  import { accentInsensitivePathOrder } from "@truedat/core/services/sort";
9
11
  import LimitsForm from "./LimitsForm";
@@ -80,6 +82,7 @@ export const RuleImplementationRawForm = ({
80
82
  setImplementationRawContent({
81
83
  ...rawContent,
82
84
  source_id: value,
85
+ source: _.find({ id: value })(sources),
83
86
  database: "",
84
87
  });
85
88
  };
@@ -334,6 +337,32 @@ RuleImplementationRawForm.propTypes = {
334
337
  sourcesLoading: PropTypes.bool,
335
338
  };
336
339
 
340
+ export const SOURCES_WITH_CONFIG = gql`
341
+ query SOURCES_WITH_CONFIG($jobTypes: String) {
342
+ sources(jobTypes: $jobTypes) {
343
+ id
344
+ externalId
345
+ config
346
+ }
347
+ }
348
+ `;
349
+
350
+ export const RuleImplementationRawFormLoader = (props) => {
351
+ const { data, error, loading } = useQuery(SOURCES_WITH_CONFIG, {
352
+ variables: { jobTypes: "quality" },
353
+ });
354
+ if (error) return null;
355
+ if (loading) return <Loading />;
356
+ const sources = data?.sources || [];
357
+ return (
358
+ <RuleImplementationRawForm
359
+ sources={sources}
360
+ sourcesLoading={loading}
361
+ {...props}
362
+ />
363
+ );
364
+ };
365
+
337
366
  const mapStateToProps = ({
338
367
  implementationActions,
339
368
  rule,
@@ -344,4 +373,4 @@ const mapStateToProps = ({
344
373
  rule,
345
374
  });
346
375
 
347
- export default connect(mapStateToProps)(RuleImplementationRawForm);
376
+ export default connect(mapStateToProps)(RuleImplementationRawFormLoader);
@@ -4,7 +4,7 @@ import { waitFor } from "@testing-library/react";
4
4
  import userEvent from "@testing-library/user-event";
5
5
  import { render } from "@truedat/test/render";
6
6
  import { multipleTemplatesMock } from "@truedat/test/mocks";
7
- import RuleImplementationRawForm from "../RuleImplementationRawForm";
7
+ import { RuleImplementationRawForm } from "../RuleImplementationRawForm";
8
8
 
9
9
  jest.setTimeout(30000);
10
10
 
@@ -13,6 +13,7 @@ const renderOpts = {
13
13
  state: {
14
14
  rule: { domain_id: 1 },
15
15
  ruleImplementationCreating: false,
16
+ domains: [{ id: 1, name: "domain1" }],
16
17
  },
17
18
  fallback: "lazy",
18
19
  };
@@ -35,6 +36,7 @@ const props = {
35
36
  minimum: "1",
36
37
  result_type: "percentage",
37
38
  },
39
+ sourcesLoading: false,
38
40
  sources: [
39
41
  {
40
42
  id: "1",
@@ -56,8 +58,11 @@ const props = {
56
58
 
57
59
  describe("<RuleImplementationRawForm />", () => {
58
60
  it("matches the latest snapshot", async () => {
61
+ const updatedProps = _.flow(_.set("ruleImplementation.domain_id", 1))(
62
+ props
63
+ );
59
64
  const { container, queryByText } = render(
60
- <RuleImplementationRawForm {...props} />,
65
+ <RuleImplementationRawForm {...updatedProps} />,
61
66
  renderOpts
62
67
  );
63
68
  await waitFor(() => expect(queryByText(/lazy/i)).not.toBeInTheDocument(), {
@@ -141,6 +146,7 @@ describe("<RuleImplementationRawForm />", () => {
141
146
 
142
147
  it("submit button enabled if there is valid content in form with database", async () => {
143
148
  const updatedProps = _.flow(
149
+ _.set("ruleImplementation.domain_id", 1),
144
150
  _.set("ruleImplementation.dfName", "template1"),
145
151
  _.set("ruleImplementation.dfContent", { field1: "foo" })
146
152
  )(props);
@@ -156,13 +162,11 @@ describe("<RuleImplementationRawForm />", () => {
156
162
  rule: { id: 5, name: "regla" },
157
163
  };
158
164
 
159
- const { queryByRole } = render(
165
+ const { findByRole } = render(
160
166
  <RuleImplementationRawForm {...customProps} />,
161
167
  renderOpts
162
168
  );
163
- await waitFor(() =>
164
- expect(queryByRole("button", { name: /save/i })).toBeEnabled()
165
- );
169
+ expect(await findByRole("button", { name: /save/i })).toBeEnabled();
166
170
  });
167
171
 
168
172
  it("submit button disabled if databases are available and not selected", async () => {
@@ -176,14 +180,10 @@ describe("<RuleImplementationRawForm />", () => {
176
180
  },
177
181
  };
178
182
 
179
- const { queryByText, getByRole } = render(
183
+ const { getByRole } = render(
180
184
  <RuleImplementationRawForm {...customProps} />,
181
185
  renderOpts
182
186
  );
183
- await waitFor(() => expect(queryByText(/lazy/i)).not.toBeInTheDocument());
184
- await waitFor(() =>
185
- expect(queryByText(/loading/i)).not.toBeInTheDocument()
186
- );
187
187
  expect(getByRole("button", { name: "Save" })).toBeDisabled();
188
188
  });
189
189
 
@@ -221,6 +221,15 @@ describe("<RuleImplementationRawForm />", () => {
221
221
  population: "",
222
222
  source_id: "2",
223
223
  validations: "",
224
+ source: {
225
+ id: "2",
226
+ config: {
227
+ alias: "source2",
228
+ job_types: ["quality"],
229
+ databases: ["db1", "db2"],
230
+ },
231
+ externalId: "ext_id_2",
232
+ },
224
233
  });
225
234
  });
226
235
 
@@ -239,17 +248,12 @@ describe("<RuleImplementationRawForm />", () => {
239
248
  validations: "a.city='MADRID'",
240
249
  },
241
250
  };
242
- const { queryByRole, queryByText } = render(
251
+ const { findByRole } = render(
243
252
  <RuleImplementationRawForm {...customProps} />,
244
253
  renderOpts
245
254
  );
246
- await waitFor(() => expect(queryByText(/lazy/i)).not.toBeInTheDocument());
247
- await waitFor(() =>
248
- expect(queryByText(/loading/i)).not.toBeInTheDocument()
249
- );
250
- await waitFor(() =>
251
- expect(queryByRole("button", { name: /save/i })).toBeEnabled()
252
- );
255
+
256
+ expect(await findByRole("button", { name: /save/i })).toBeEnabled();
253
257
  });
254
258
 
255
259
  it("submit button disabled if there is invalid content in form", async () => {
@@ -266,14 +270,10 @@ describe("<RuleImplementationRawForm />", () => {
266
270
  validations: "a.city='MADRID'",
267
271
  },
268
272
  };
269
- const { queryByRole, queryByText } = render(
273
+ const { queryByRole } = render(
270
274
  <RuleImplementationRawForm {...customProps} />,
271
275
  renderOpts
272
276
  );
273
- await waitFor(() => expect(queryByText(/lazy/i)).not.toBeInTheDocument());
274
- await waitFor(() =>
275
- expect(queryByText(/loading/i)).not.toBeInTheDocument()
276
- );
277
277
  expect(queryByRole("button", { name: /save/i })).toBeDisabled();
278
278
  });
279
279