@truedat/dq 4.58.3 → 4.58.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/CHANGELOG.md +7 -1
- package/package.json +5 -5
- package/src/components/ImplementationsRoutes.js +26 -2
- package/src/components/NewBasicRuleImplementation.js +139 -0
- package/src/components/NewRuleImplementation.js +1 -4
- package/src/components/RuleImplementationActions.js +17 -1
- package/src/components/RuleImplementationsActions.js +1 -0
- package/src/components/RuleImplementationsOptions.js +38 -15
- package/src/components/__tests__/NewBasicRuleImplementation.spec.js +166 -0
- package/src/components/__tests__/__snapshots__/NewBasicRuleImplementation.spec.js.snap +314 -0
- package/src/components/__tests__/__snapshots__/RuleImplementationsActions.spec.js.snap +1 -0
- package/src/components/ruleImplementationForm/RuleImplementationBasicForm.js +203 -0
- package/src/components/ruleImplementationForm/__tests__/RuleImplementationBasicForm.spec.js +136 -0
- package/src/components/ruleImplementationForm/__tests__/__snapshots__/RuleImplementationBasicForm.spec.js.snap +273 -0
- package/src/messages/en.js +2 -0
- package/src/messages/es.js +3 -1
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
|
+
|
|
3
|
+
exports[`<NewBasicRuleImplementation /> matches the latest snapshot 1`] = `
|
|
4
|
+
<div>
|
|
5
|
+
<div
|
|
6
|
+
class="ui divided grid full-height"
|
|
7
|
+
style=""
|
|
8
|
+
>
|
|
9
|
+
<div
|
|
10
|
+
class="eleven wide column"
|
|
11
|
+
>
|
|
12
|
+
<div
|
|
13
|
+
class="row"
|
|
14
|
+
>
|
|
15
|
+
<h2
|
|
16
|
+
class="ui header"
|
|
17
|
+
>
|
|
18
|
+
<div
|
|
19
|
+
class="content"
|
|
20
|
+
>
|
|
21
|
+
New Implementation
|
|
22
|
+
</div>
|
|
23
|
+
</h2>
|
|
24
|
+
<div
|
|
25
|
+
class="ui hidden divider"
|
|
26
|
+
/>
|
|
27
|
+
</div>
|
|
28
|
+
<div
|
|
29
|
+
class="stretched row"
|
|
30
|
+
>
|
|
31
|
+
<form
|
|
32
|
+
class="ui form rule"
|
|
33
|
+
>
|
|
34
|
+
<div
|
|
35
|
+
class="field"
|
|
36
|
+
>
|
|
37
|
+
<label>
|
|
38
|
+
Implementation Key
|
|
39
|
+
<i
|
|
40
|
+
aria-hidden="true"
|
|
41
|
+
class="question circle outline icon rule-form-popup"
|
|
42
|
+
/>
|
|
43
|
+
</label>
|
|
44
|
+
<div
|
|
45
|
+
class="required field"
|
|
46
|
+
>
|
|
47
|
+
<div
|
|
48
|
+
class="ui input"
|
|
49
|
+
>
|
|
50
|
+
<input
|
|
51
|
+
autocomplete="off"
|
|
52
|
+
name="implementation_key"
|
|
53
|
+
placeholder="Rule Implementation Key"
|
|
54
|
+
required=""
|
|
55
|
+
type="text"
|
|
56
|
+
value=""
|
|
57
|
+
/>
|
|
58
|
+
</div>
|
|
59
|
+
</div>
|
|
60
|
+
</div>
|
|
61
|
+
<div
|
|
62
|
+
class="field"
|
|
63
|
+
/>
|
|
64
|
+
<div
|
|
65
|
+
class="ui segment"
|
|
66
|
+
>
|
|
67
|
+
<div
|
|
68
|
+
class="field"
|
|
69
|
+
>
|
|
70
|
+
<label
|
|
71
|
+
class="rule-form-label"
|
|
72
|
+
>
|
|
73
|
+
Result Type
|
|
74
|
+
<span>
|
|
75
|
+
*
|
|
76
|
+
</span>
|
|
77
|
+
<i
|
|
78
|
+
aria-hidden="true"
|
|
79
|
+
class="question circle outline icon rule-form-popup"
|
|
80
|
+
/>
|
|
81
|
+
</label>
|
|
82
|
+
<div
|
|
83
|
+
class="inline fields"
|
|
84
|
+
>
|
|
85
|
+
<div
|
|
86
|
+
class="field"
|
|
87
|
+
>
|
|
88
|
+
<div
|
|
89
|
+
class="ui checked radio checkbox"
|
|
90
|
+
>
|
|
91
|
+
<input
|
|
92
|
+
checked=""
|
|
93
|
+
class="hidden"
|
|
94
|
+
name="result_type"
|
|
95
|
+
readonly=""
|
|
96
|
+
tabindex="0"
|
|
97
|
+
type="radio"
|
|
98
|
+
value="percentage"
|
|
99
|
+
/>
|
|
100
|
+
<label>
|
|
101
|
+
Percentage
|
|
102
|
+
</label>
|
|
103
|
+
</div>
|
|
104
|
+
</div>
|
|
105
|
+
<div
|
|
106
|
+
class="field"
|
|
107
|
+
>
|
|
108
|
+
<div
|
|
109
|
+
class="ui radio checkbox"
|
|
110
|
+
>
|
|
111
|
+
<input
|
|
112
|
+
class="hidden"
|
|
113
|
+
name="result_type"
|
|
114
|
+
readonly=""
|
|
115
|
+
tabindex="0"
|
|
116
|
+
type="radio"
|
|
117
|
+
value="deviation"
|
|
118
|
+
/>
|
|
119
|
+
<label>
|
|
120
|
+
Deviation
|
|
121
|
+
</label>
|
|
122
|
+
</div>
|
|
123
|
+
</div>
|
|
124
|
+
<div
|
|
125
|
+
class="field"
|
|
126
|
+
>
|
|
127
|
+
<div
|
|
128
|
+
class="ui radio checkbox"
|
|
129
|
+
>
|
|
130
|
+
<input
|
|
131
|
+
class="hidden"
|
|
132
|
+
name="result_type"
|
|
133
|
+
readonly=""
|
|
134
|
+
tabindex="0"
|
|
135
|
+
type="radio"
|
|
136
|
+
value="errors_number"
|
|
137
|
+
/>
|
|
138
|
+
<label>
|
|
139
|
+
Error count
|
|
140
|
+
</label>
|
|
141
|
+
</div>
|
|
142
|
+
</div>
|
|
143
|
+
</div>
|
|
144
|
+
</div>
|
|
145
|
+
<div
|
|
146
|
+
class="field"
|
|
147
|
+
>
|
|
148
|
+
<label
|
|
149
|
+
class="rule-form-label"
|
|
150
|
+
>
|
|
151
|
+
Threshold
|
|
152
|
+
<span>
|
|
153
|
+
*
|
|
154
|
+
</span>
|
|
155
|
+
<i
|
|
156
|
+
aria-hidden="true"
|
|
157
|
+
class="question circle outline icon rule-form-popup"
|
|
158
|
+
/>
|
|
159
|
+
<div
|
|
160
|
+
class="ui left pointing label"
|
|
161
|
+
>
|
|
162
|
+
Required field is empty
|
|
163
|
+
</div>
|
|
164
|
+
</label>
|
|
165
|
+
<div
|
|
166
|
+
class="field"
|
|
167
|
+
>
|
|
168
|
+
<div
|
|
169
|
+
class="ui input"
|
|
170
|
+
>
|
|
171
|
+
<input
|
|
172
|
+
autocomplete="off"
|
|
173
|
+
name="minimum"
|
|
174
|
+
placeholder="Threshold value"
|
|
175
|
+
type="text"
|
|
176
|
+
value=""
|
|
177
|
+
/>
|
|
178
|
+
</div>
|
|
179
|
+
</div>
|
|
180
|
+
</div>
|
|
181
|
+
<div
|
|
182
|
+
class="field"
|
|
183
|
+
>
|
|
184
|
+
<label
|
|
185
|
+
class="rule-form-label"
|
|
186
|
+
>
|
|
187
|
+
Goal
|
|
188
|
+
<span>
|
|
189
|
+
*
|
|
190
|
+
</span>
|
|
191
|
+
<i
|
|
192
|
+
aria-hidden="true"
|
|
193
|
+
class="question circle outline icon rule-form-popup"
|
|
194
|
+
/>
|
|
195
|
+
<div
|
|
196
|
+
class="ui left pointing label"
|
|
197
|
+
>
|
|
198
|
+
Required field is empty
|
|
199
|
+
</div>
|
|
200
|
+
</label>
|
|
201
|
+
<div
|
|
202
|
+
class="field"
|
|
203
|
+
>
|
|
204
|
+
<div
|
|
205
|
+
class="ui input"
|
|
206
|
+
>
|
|
207
|
+
<input
|
|
208
|
+
autocomplete="off"
|
|
209
|
+
name="goal"
|
|
210
|
+
placeholder="Goal value"
|
|
211
|
+
type="text"
|
|
212
|
+
value=""
|
|
213
|
+
/>
|
|
214
|
+
</div>
|
|
215
|
+
</div>
|
|
216
|
+
</div>
|
|
217
|
+
</div>
|
|
218
|
+
<div
|
|
219
|
+
class="required field"
|
|
220
|
+
>
|
|
221
|
+
<label>
|
|
222
|
+
Template
|
|
223
|
+
<div
|
|
224
|
+
class="ui left pointing label"
|
|
225
|
+
>
|
|
226
|
+
Empty required field
|
|
227
|
+
</div>
|
|
228
|
+
</label>
|
|
229
|
+
<div
|
|
230
|
+
class="field"
|
|
231
|
+
>
|
|
232
|
+
<div
|
|
233
|
+
aria-busy="false"
|
|
234
|
+
aria-expanded="false"
|
|
235
|
+
class="ui search selection dropdown"
|
|
236
|
+
name="template"
|
|
237
|
+
role="combobox"
|
|
238
|
+
>
|
|
239
|
+
<input
|
|
240
|
+
aria-autocomplete="list"
|
|
241
|
+
autocomplete="off"
|
|
242
|
+
class="search"
|
|
243
|
+
tabindex="0"
|
|
244
|
+
type="text"
|
|
245
|
+
value=""
|
|
246
|
+
/>
|
|
247
|
+
<div
|
|
248
|
+
aria-atomic="true"
|
|
249
|
+
aria-live="polite"
|
|
250
|
+
class="divider default text"
|
|
251
|
+
role="alert"
|
|
252
|
+
>
|
|
253
|
+
Select a template...
|
|
254
|
+
</div>
|
|
255
|
+
<i
|
|
256
|
+
aria-hidden="true"
|
|
257
|
+
class="dropdown icon"
|
|
258
|
+
/>
|
|
259
|
+
<div
|
|
260
|
+
class="menu transition"
|
|
261
|
+
role="listbox"
|
|
262
|
+
>
|
|
263
|
+
<div
|
|
264
|
+
aria-checked="false"
|
|
265
|
+
aria-selected="true"
|
|
266
|
+
class="selected item"
|
|
267
|
+
role="option"
|
|
268
|
+
style="pointer-events: all;"
|
|
269
|
+
>
|
|
270
|
+
<span
|
|
271
|
+
class="text"
|
|
272
|
+
>
|
|
273
|
+
template1
|
|
274
|
+
</span>
|
|
275
|
+
</div>
|
|
276
|
+
<div
|
|
277
|
+
aria-checked="false"
|
|
278
|
+
aria-selected="false"
|
|
279
|
+
class="item"
|
|
280
|
+
role="option"
|
|
281
|
+
style="pointer-events: all;"
|
|
282
|
+
>
|
|
283
|
+
<span
|
|
284
|
+
class="text"
|
|
285
|
+
>
|
|
286
|
+
template2
|
|
287
|
+
</span>
|
|
288
|
+
</div>
|
|
289
|
+
</div>
|
|
290
|
+
</div>
|
|
291
|
+
</div>
|
|
292
|
+
</div>
|
|
293
|
+
<button
|
|
294
|
+
class="ui primary disabled right floated button"
|
|
295
|
+
disabled=""
|
|
296
|
+
tabindex="-1"
|
|
297
|
+
type="submit"
|
|
298
|
+
>
|
|
299
|
+
Save
|
|
300
|
+
</button>
|
|
301
|
+
<button
|
|
302
|
+
class="ui secondary right floated button"
|
|
303
|
+
>
|
|
304
|
+
Cancel
|
|
305
|
+
</button>
|
|
306
|
+
</form>
|
|
307
|
+
</div>
|
|
308
|
+
</div>
|
|
309
|
+
<div
|
|
310
|
+
class="five wide column"
|
|
311
|
+
/>
|
|
312
|
+
</div>
|
|
313
|
+
</div>
|
|
314
|
+
`;
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import _ from "lodash/fp";
|
|
2
|
+
import React, { useState, useEffect } from "react";
|
|
3
|
+
import PropTypes from "prop-types";
|
|
4
|
+
import { connect } from "react-redux";
|
|
5
|
+
import { useHistory } from "react-router-dom";
|
|
6
|
+
import { useIntl } from "react-intl";
|
|
7
|
+
import { useQuery } from "@apollo/client";
|
|
8
|
+
import { Button, Form, Icon, Popup } from "semantic-ui-react";
|
|
9
|
+
import { DomainSelector } from "@truedat/core/components";
|
|
10
|
+
import { DOMAIN_QUERY } from "@truedat/core/api/queries";
|
|
11
|
+
import LimitsForm from "./LimitsForm";
|
|
12
|
+
import { areLimitsValid } from "./limitsValidation";
|
|
13
|
+
|
|
14
|
+
const SelectableDynamicForm = React.lazy(() =>
|
|
15
|
+
import("@truedat/df/components/SelectableDynamicForm")
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
const DomainActionsLoader = ({ id, actions, onLoad }) => {
|
|
19
|
+
useQuery(DOMAIN_QUERY, {
|
|
20
|
+
fetchPolicy: "cache-and-network",
|
|
21
|
+
variables: { id, actions },
|
|
22
|
+
onCompleted: onLoad,
|
|
23
|
+
});
|
|
24
|
+
return null;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
DomainActionsLoader.propTypes = {
|
|
28
|
+
id: PropTypes.number,
|
|
29
|
+
actions: PropTypes.array,
|
|
30
|
+
onLoad: PropTypes.func,
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const Help = ({ message }) => {
|
|
34
|
+
const { formatMessage } = useIntl();
|
|
35
|
+
return (
|
|
36
|
+
<Popup
|
|
37
|
+
trigger={
|
|
38
|
+
<Icon className="rule-form-popup" name="question circle outline" />
|
|
39
|
+
}
|
|
40
|
+
content={formatMessage({ id: message })}
|
|
41
|
+
on="click"
|
|
42
|
+
hideOnScroll
|
|
43
|
+
/>
|
|
44
|
+
);
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
Help.propTypes = {
|
|
48
|
+
message: PropTypes.string,
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export const RuleImplementationBasicForm = ({
|
|
52
|
+
implementationKey,
|
|
53
|
+
isSubmitting,
|
|
54
|
+
onChange,
|
|
55
|
+
onSubmit,
|
|
56
|
+
rule,
|
|
57
|
+
ruleImplementation,
|
|
58
|
+
setImplementationKey,
|
|
59
|
+
}) => {
|
|
60
|
+
const { formatMessage } = useIntl();
|
|
61
|
+
const history = useHistory();
|
|
62
|
+
|
|
63
|
+
const domainActions = ["publishImplementation"];
|
|
64
|
+
|
|
65
|
+
const [isContentValid, setIsContentValid] = useState();
|
|
66
|
+
|
|
67
|
+
const [domains, setDomains] = useState();
|
|
68
|
+
const [canPublish, setCanPublish] = useState(false);
|
|
69
|
+
|
|
70
|
+
useEffect(() => {
|
|
71
|
+
const currentDomainActions = _.flow(
|
|
72
|
+
_.find((domain) => domain.id === String(ruleImplementation.domain_id)),
|
|
73
|
+
_.pathOr([], "actions")
|
|
74
|
+
)(domains);
|
|
75
|
+
|
|
76
|
+
_.flow(
|
|
77
|
+
_.any((action) => action == "publishImplementation"),
|
|
78
|
+
setCanPublish
|
|
79
|
+
)(currentDomainActions);
|
|
80
|
+
|
|
81
|
+
return () => {
|
|
82
|
+
setCanPublish(false);
|
|
83
|
+
};
|
|
84
|
+
}, [domains, ruleImplementation.domain_id]);
|
|
85
|
+
|
|
86
|
+
const handleContentChange = ({ content, valid }) => {
|
|
87
|
+
onChange("dfContent", content);
|
|
88
|
+
setIsContentValid(_.isEmpty(valid));
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
const doSubmit = (params) => {
|
|
92
|
+
if (isValidForm()) {
|
|
93
|
+
onSubmit(params);
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
const isValidForm = () =>
|
|
98
|
+
ruleImplementation?.dfName &&
|
|
99
|
+
!_.isEmpty(ruleImplementation?.dfName) &&
|
|
100
|
+
isContentValid &&
|
|
101
|
+
(!_.isEmpty(rule) || _.prop("domain_id")(ruleImplementation)) &&
|
|
102
|
+
areLimitsValid(ruleImplementation);
|
|
103
|
+
|
|
104
|
+
const doCancel = () => history.goBack();
|
|
105
|
+
|
|
106
|
+
const domainId = ruleImplementation?.domain_id || rule?.domain_id;
|
|
107
|
+
|
|
108
|
+
return (
|
|
109
|
+
<Form className="rule">
|
|
110
|
+
<Form.Field>
|
|
111
|
+
<label>
|
|
112
|
+
{formatMessage({ id: "ruleImplementation.props.name" })}
|
|
113
|
+
<Help message="datasetForm.implementation_key.tooltip" />
|
|
114
|
+
</label>
|
|
115
|
+
<Form.Input
|
|
116
|
+
autoComplete="off"
|
|
117
|
+
name="implementation_key"
|
|
118
|
+
onChange={(_e, { value }) => setImplementationKey(value)}
|
|
119
|
+
placeholder={formatMessage({
|
|
120
|
+
id: "ruleImplementation.props.name.placeholder",
|
|
121
|
+
})}
|
|
122
|
+
required
|
|
123
|
+
value={implementationKey}
|
|
124
|
+
/>
|
|
125
|
+
</Form.Field>
|
|
126
|
+
{_.isEmpty(rule) && !ruleImplementation?.rule_id ? (
|
|
127
|
+
<Form.Field>
|
|
128
|
+
<DomainSelector
|
|
129
|
+
action={
|
|
130
|
+
ruleImplementation.rule_id
|
|
131
|
+
? "manageBasicImplementations"
|
|
132
|
+
: "manageBasicRulelessImplementations"
|
|
133
|
+
}
|
|
134
|
+
value={domainId}
|
|
135
|
+
domainActions={domainActions}
|
|
136
|
+
onLoad={(data) => setDomains(data.domains)}
|
|
137
|
+
onChange={(_e, { value }) => onChange("domain_id", value)}
|
|
138
|
+
labels
|
|
139
|
+
/>
|
|
140
|
+
</Form.Field>
|
|
141
|
+
) : (
|
|
142
|
+
<DomainActionsLoader
|
|
143
|
+
id={domainId}
|
|
144
|
+
actions={domainActions}
|
|
145
|
+
onLoad={(data) => setDomains([data.domain])}
|
|
146
|
+
/>
|
|
147
|
+
)}
|
|
148
|
+
<LimitsForm onChange={onChange} ruleImplementation={ruleImplementation} />
|
|
149
|
+
<SelectableDynamicForm
|
|
150
|
+
scope="ri"
|
|
151
|
+
domainIds={_.isNil(domainId) ? null : [domainId]}
|
|
152
|
+
required
|
|
153
|
+
content={ruleImplementation?.dfContent}
|
|
154
|
+
name={ruleImplementation?.dfName}
|
|
155
|
+
onChange={handleContentChange}
|
|
156
|
+
onNameChange={(dfName) => onChange("dfName", dfName)}
|
|
157
|
+
/>
|
|
158
|
+
{canPublish ? (
|
|
159
|
+
<Button
|
|
160
|
+
floated="right"
|
|
161
|
+
disabled={!isValidForm()}
|
|
162
|
+
type="submit"
|
|
163
|
+
primary
|
|
164
|
+
loading={isSubmitting}
|
|
165
|
+
onClick={() => doSubmit({ status: "published" })}
|
|
166
|
+
content={formatMessage({ id: "actions.publish" })}
|
|
167
|
+
/>
|
|
168
|
+
) : null}
|
|
169
|
+
<Button
|
|
170
|
+
floated="right"
|
|
171
|
+
disabled={!isValidForm()}
|
|
172
|
+
type="submit"
|
|
173
|
+
primary
|
|
174
|
+
loading={isSubmitting}
|
|
175
|
+
onClick={() => doSubmit({ status: "draft" })}
|
|
176
|
+
content={formatMessage({ id: "actions.save" })}
|
|
177
|
+
/>
|
|
178
|
+
<Button
|
|
179
|
+
content={formatMessage({ id: "actions.cancel" })}
|
|
180
|
+
floated="right"
|
|
181
|
+
onClick={() => doCancel()}
|
|
182
|
+
secondary
|
|
183
|
+
/>
|
|
184
|
+
</Form>
|
|
185
|
+
);
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
RuleImplementationBasicForm.propTypes = {
|
|
189
|
+
implementationKey: PropTypes.string,
|
|
190
|
+
isSubmitting: PropTypes.bool,
|
|
191
|
+
onChange: PropTypes.func,
|
|
192
|
+
onSubmit: PropTypes.func.isRequired,
|
|
193
|
+
rule: PropTypes.object,
|
|
194
|
+
ruleImplementation: PropTypes.object,
|
|
195
|
+
setImplementationKey: PropTypes.func,
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
const mapStateToProps = ({ rule, ruleImplementationCreating }) => ({
|
|
199
|
+
isSubmitting: ruleImplementationCreating,
|
|
200
|
+
rule,
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
export default connect(mapStateToProps)(RuleImplementationBasicForm);
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import _ from "lodash/fp";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import { waitFor } from "@testing-library/react";
|
|
4
|
+
import userEvent from "@testing-library/user-event";
|
|
5
|
+
import { render } from "@truedat/test/render";
|
|
6
|
+
import { DOMAIN_QUERY, DOMAINS_QUERY } from "@truedat/core/api/queries";
|
|
7
|
+
import { multipleTemplatesMock } from "@truedat/test/mocks";
|
|
8
|
+
import { RuleImplementationBasicForm } from "../RuleImplementationBasicForm";
|
|
9
|
+
|
|
10
|
+
jest.setTimeout(30000);
|
|
11
|
+
|
|
12
|
+
const domains = [
|
|
13
|
+
{ id: 1, name: "domain1", actions: ["publishImplementation"] },
|
|
14
|
+
];
|
|
15
|
+
const domainsMock = {
|
|
16
|
+
request: { query: DOMAINS_QUERY },
|
|
17
|
+
result: { data: { domains: domains } },
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const domainMock = {
|
|
21
|
+
request: { query: DOMAIN_QUERY },
|
|
22
|
+
result: { data: { domain: domains } },
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const renderOpts = {
|
|
26
|
+
mocks: [
|
|
27
|
+
multipleTemplatesMock({ scope: "ri", domainIds: [1] }),
|
|
28
|
+
domainMock,
|
|
29
|
+
domainsMock,
|
|
30
|
+
],
|
|
31
|
+
state: {
|
|
32
|
+
rule: { domain_id: 1 },
|
|
33
|
+
ruleImplementationCreating: false,
|
|
34
|
+
},
|
|
35
|
+
fallback: "lazy",
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const props = {
|
|
39
|
+
onChange: jest.fn(),
|
|
40
|
+
onSubmit: jest.fn(),
|
|
41
|
+
implementationKey: "",
|
|
42
|
+
isSubmitting: false,
|
|
43
|
+
ruleImplementation: {
|
|
44
|
+
id: 1,
|
|
45
|
+
goal: "10",
|
|
46
|
+
minimum: "1",
|
|
47
|
+
result_type: "percentage",
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
describe("<RuleImplementationBasicForm />", () => {
|
|
52
|
+
it("matches the latest snapshot", async () => {
|
|
53
|
+
const updatedProps = _.flow(_.set("ruleImplementation.domain_id", 1))(
|
|
54
|
+
props
|
|
55
|
+
);
|
|
56
|
+
const { container, queryByText } = render(
|
|
57
|
+
<RuleImplementationBasicForm {...updatedProps} />,
|
|
58
|
+
renderOpts
|
|
59
|
+
);
|
|
60
|
+
await waitFor(() => expect(queryByText(/lazy/i)).not.toBeInTheDocument(), {
|
|
61
|
+
timeout: 10000,
|
|
62
|
+
});
|
|
63
|
+
await waitFor(() =>
|
|
64
|
+
expect(queryByText(/loading/i)).not.toBeInTheDocument()
|
|
65
|
+
);
|
|
66
|
+
expect(container).toMatchSnapshot();
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it("Implementation_key field is editable with status published", () => {
|
|
70
|
+
const updatedProps = _.flow(
|
|
71
|
+
_.set("ruleImplementation.domain_id", 1),
|
|
72
|
+
_.set("ruleImplementation.status", "published"),
|
|
73
|
+
_.set("ruleImplementation.implementation_key", "implementation_test")
|
|
74
|
+
)(props);
|
|
75
|
+
const { queryByPlaceholderText } = render(
|
|
76
|
+
<RuleImplementationBasicForm {...updatedProps} />,
|
|
77
|
+
renderOpts
|
|
78
|
+
);
|
|
79
|
+
expect(
|
|
80
|
+
queryByPlaceholderText("Rule Implementation Key")
|
|
81
|
+
).not.toBeDisabled();
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it("submit button enabled if there is valid content in form without rule", async () => {
|
|
85
|
+
const updatedProps = _.flow(
|
|
86
|
+
_.set("ruleImplementation.domain_id", 1),
|
|
87
|
+
_.set("ruleImplementation.dfName", "template1"),
|
|
88
|
+
_.set("ruleImplementation.dfContent", { field1: "foo" })
|
|
89
|
+
)(props);
|
|
90
|
+
const customProps = {
|
|
91
|
+
...updatedProps,
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
const { getByRole } = render(
|
|
95
|
+
<RuleImplementationBasicForm {...customProps} />,
|
|
96
|
+
renderOpts
|
|
97
|
+
);
|
|
98
|
+
await waitFor(() => {
|
|
99
|
+
expect(getByRole("button", { name: "Save" })).toBeEnabled();
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it("submit button enabled if there is valid content in form with rule", async () => {
|
|
104
|
+
const updatedProps = _.flow(
|
|
105
|
+
_.set("ruleImplementation.domain_id", 1),
|
|
106
|
+
_.set("ruleImplementation.dfName", "template1"),
|
|
107
|
+
_.set("ruleImplementation.dfContent", { field1: "foo" })
|
|
108
|
+
)(props);
|
|
109
|
+
const customProps = {
|
|
110
|
+
...updatedProps,
|
|
111
|
+
rule: { id: 5, name: "regla" },
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
const { findByRole } = render(
|
|
115
|
+
<RuleImplementationBasicForm {...customProps} />,
|
|
116
|
+
renderOpts
|
|
117
|
+
);
|
|
118
|
+
expect(await findByRole("button", { name: /save/i })).toBeEnabled();
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
it("submit button disabled if there is invalid content in form", async () => {
|
|
122
|
+
const updatedProps = _.flow(
|
|
123
|
+
_.set("ruleImplementation.domain_id", 1),
|
|
124
|
+
_.set("ruleImplementation.dfName", "template1"),
|
|
125
|
+
_.set("ruleImplementation.dfContent", {})
|
|
126
|
+
)(props);
|
|
127
|
+
const customProps = {
|
|
128
|
+
...updatedProps,
|
|
129
|
+
};
|
|
130
|
+
const { queryByRole } = render(
|
|
131
|
+
<RuleImplementationBasicForm {...customProps} />,
|
|
132
|
+
renderOpts
|
|
133
|
+
);
|
|
134
|
+
expect(queryByRole("button", { name: /save/i })).toBeDisabled();
|
|
135
|
+
});
|
|
136
|
+
});
|