foreman_webhooks 5.1.0 → 6.0.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.
- checksums.yaml +4 -4
- data/lib/foreman_webhooks/engine.rb +1 -1
- data/lib/foreman_webhooks/version.rb +1 -1
- data/webpack/ForemanWebhooks/Routes/Webhooks/Components/WebhookForm/Components/WebhookFormTabs.js +4 -6
- data/webpack/ForemanWebhooks/Routes/Webhooks/WebhooksIndexPage/Components/WebhookTestModal.js +1 -2
- metadata +1 -4
- data/webpack/ForemanWebhooks/Routes/Webhooks/Components/WebhookForm/Components/FieldConstructor.js +0 -312
- data/webpack/ForemanWebhooks/Routes/Webhooks/Components/WebhookForm/Components/__tests__/FieldConstructor.test.js +0 -216
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 0b5922c7ae2630c642e151ea99d59e8fce67ca342a93bd595a3c80d8837db0c7
|
|
4
|
+
data.tar.gz: c7d0bc6894477642639612f3d7b68974ea90dff25fabb91c3d684316fcd12230
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3f8c365cbf5d75887f69a3ffe3c9949e4fdfff3ca3129f12432747dda722ddf017892f700eb712353a2d805e07a53ff1f82f278afe8db3ac92ef6bec802bb76a
|
|
7
|
+
data.tar.gz: 34717dcb661c339a41377fbaa2c40603d0821bc5a0949f80abfd828497c49c9778543cd87d4505207d2e1b92cc9f684e7adca9c90eca4d854d6267dcce28a964
|
|
@@ -14,7 +14,7 @@ module ForemanWebhooks
|
|
|
14
14
|
initializer 'foreman_webhooks.register_plugin', before: :finisher_hook do |app|
|
|
15
15
|
app.reloader.to_prepare do
|
|
16
16
|
Foreman::Plugin.register :foreman_webhooks do
|
|
17
|
-
requires_foreman '>=
|
|
17
|
+
requires_foreman '>= 5.0'
|
|
18
18
|
register_gettext
|
|
19
19
|
|
|
20
20
|
apipie_documented_controllers ["#{ForemanWebhooks::Engine.root}/app/controllers/api/v2/*.rb"]
|
data/webpack/ForemanWebhooks/Routes/Webhooks/Components/WebhookForm/Components/WebhookFormTabs.js
CHANGED
|
@@ -2,10 +2,10 @@ import React from 'react';
|
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
3
|
import { Tabs, Tab, TabTitleText } from '@patternfly/react-core';
|
|
4
4
|
|
|
5
|
+
import FieldConstructor from 'foremanReact/components/common/FieldConstructor/FieldConstructor';
|
|
5
6
|
import { sprintf, translate as __ } from 'foremanReact/common/I18n';
|
|
6
7
|
|
|
7
8
|
import './WebhookFormTabs.css';
|
|
8
|
-
import FieldConstructor from './FieldConstructor';
|
|
9
9
|
|
|
10
10
|
const WebhookFormTabs = ({
|
|
11
11
|
inputValues,
|
|
@@ -48,7 +48,7 @@ const WebhookFormTabs = ({
|
|
|
48
48
|
type="select"
|
|
49
49
|
label={__('Subscribe to')}
|
|
50
50
|
required
|
|
51
|
-
allowClear
|
|
51
|
+
allowClear
|
|
52
52
|
options={availableEvents}
|
|
53
53
|
isLoading={isEventsLoading}
|
|
54
54
|
placeholder={__('Start typing to search...')}
|
|
@@ -93,7 +93,7 @@ const WebhookFormTabs = ({
|
|
|
93
93
|
type="select"
|
|
94
94
|
label={__('Template')}
|
|
95
95
|
required
|
|
96
|
-
allowClear
|
|
96
|
+
allowClear
|
|
97
97
|
options={webhookTemplates}
|
|
98
98
|
isLoading={isTemplatesLoading}
|
|
99
99
|
placeholder={__('Start typing to search...')}
|
|
@@ -105,7 +105,7 @@ const WebhookFormTabs = ({
|
|
|
105
105
|
type="select"
|
|
106
106
|
label={__('HTTP Method')}
|
|
107
107
|
required
|
|
108
|
-
allowClear
|
|
108
|
+
allowClear
|
|
109
109
|
options={httpMethods}
|
|
110
110
|
placeholder={__('Start typing to search...')}
|
|
111
111
|
/>
|
|
@@ -173,7 +173,6 @@ const WebhookFormTabs = ({
|
|
|
173
173
|
placeholder={__(
|
|
174
174
|
"Optional CAs in PEM format concatenated to verify the receiver's SSL certificate"
|
|
175
175
|
)}
|
|
176
|
-
inputSizeClass="col-md-8"
|
|
177
176
|
rows={8}
|
|
178
177
|
setValue={updateFieldValue}
|
|
179
178
|
/>
|
|
@@ -200,7 +199,6 @@ const WebhookFormTabs = ({
|
|
|
200
199
|
label={__('HTTP Headers')}
|
|
201
200
|
labelHelp={__('Optional. Must be a JSON object (ERB allowed)')}
|
|
202
201
|
placeholder='{ "X-Shellhook-Arg-1": "value", "X-Shellhook-Arg-2": "<%= @object.id %>" }'
|
|
203
|
-
inputSizeClass="col-md-8"
|
|
204
202
|
rows={8}
|
|
205
203
|
setValue={updateFieldValue}
|
|
206
204
|
/>
|
data/webpack/ForemanWebhooks/Routes/Webhooks/WebhooksIndexPage/Components/WebhookTestModal.js
CHANGED
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
ModalVariant,
|
|
13
13
|
} from '@patternfly/react-core';
|
|
14
14
|
|
|
15
|
+
import FieldConstructor from 'foremanReact/components/common/FieldConstructor/FieldConstructor';
|
|
15
16
|
import { APIActions } from 'foremanReact/redux/API';
|
|
16
17
|
import {
|
|
17
18
|
WEBHOOK_TEST_MODAL_ID,
|
|
@@ -19,7 +20,6 @@ import {
|
|
|
19
20
|
} from '../../constants';
|
|
20
21
|
|
|
21
22
|
import './WebhookModal.scss';
|
|
22
|
-
import FieldConstructor from '../../Components/WebhookForm/Components/FieldConstructor';
|
|
23
23
|
|
|
24
24
|
const WebhookTestModal = ({ toTest, modalState }) => {
|
|
25
25
|
const dispatch = useDispatch();
|
|
@@ -80,7 +80,6 @@ const WebhookTestModal = ({ toTest, modalState }) => {
|
|
|
80
80
|
label={__('Payload')}
|
|
81
81
|
labelHelp={__('Will be sent as is')}
|
|
82
82
|
placeholder="{ id: 1, name: test }"
|
|
83
|
-
inputSizeClass="col-md-8"
|
|
84
83
|
rows={8}
|
|
85
84
|
value={value.payload}
|
|
86
85
|
setValue={(key, val) => {
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: foreman_webhooks
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version:
|
|
4
|
+
version: 6.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Timo Goebel
|
|
@@ -138,10 +138,8 @@ files:
|
|
|
138
138
|
- test/test_plugin_helper.rb
|
|
139
139
|
- test/unit/foreman_webhooks/webhook_service_test.rb
|
|
140
140
|
- webpack/ForemanWebhooks/Routes/ForemanWebhooksRoutes.js
|
|
141
|
-
- webpack/ForemanWebhooks/Routes/Webhooks/Components/WebhookForm/Components/FieldConstructor.js
|
|
142
141
|
- webpack/ForemanWebhooks/Routes/Webhooks/Components/WebhookForm/Components/WebhookFormTabs.css
|
|
143
142
|
- webpack/ForemanWebhooks/Routes/Webhooks/Components/WebhookForm/Components/WebhookFormTabs.js
|
|
144
|
-
- webpack/ForemanWebhooks/Routes/Webhooks/Components/WebhookForm/Components/__tests__/FieldConstructor.test.js
|
|
145
143
|
- webpack/ForemanWebhooks/Routes/Webhooks/Components/WebhookForm/WebhookForm.js
|
|
146
144
|
- webpack/ForemanWebhooks/Routes/Webhooks/Components/WebhookForm/WebhookFormSelectors.js
|
|
147
145
|
- webpack/ForemanWebhooks/Routes/Webhooks/Components/WebhookForm/__tests__/WebhookForm.test.js
|
|
@@ -214,7 +212,6 @@ test_files:
|
|
|
214
212
|
- test/models/webhook_test.rb
|
|
215
213
|
- test/test_plugin_helper.rb
|
|
216
214
|
- test/unit/foreman_webhooks/webhook_service_test.rb
|
|
217
|
-
- webpack/ForemanWebhooks/Routes/Webhooks/Components/WebhookForm/Components/__tests__/FieldConstructor.test.js
|
|
218
215
|
- webpack/ForemanWebhooks/Routes/Webhooks/Components/WebhookForm/__tests__/WebhookForm.test.js
|
|
219
216
|
- webpack/ForemanWebhooks/Routes/Webhooks/Components/WebhookTable/Components/Formatters/__tests__/actionCellFormatter.test.js
|
|
220
217
|
- webpack/ForemanWebhooks/Routes/Webhooks/Components/WebhookTable/Components/Formatters/__tests__/enabledCellFormatter.test.js
|
data/webpack/ForemanWebhooks/Routes/Webhooks/Components/WebhookForm/Components/FieldConstructor.js
DELETED
|
@@ -1,312 +0,0 @@
|
|
|
1
|
-
/* eslint-disable max-lines */
|
|
2
|
-
import React, { useEffect, useState } from 'react';
|
|
3
|
-
import PropTypes from 'prop-types';
|
|
4
|
-
import AutocompleteInput from 'foremanReact/components/common/AutocompleteInput/AutocompleteInput';
|
|
5
|
-
import { translate as __ } from 'foremanReact/common/I18n';
|
|
6
|
-
import {
|
|
7
|
-
ExclamationCircleIcon,
|
|
8
|
-
HelpIcon,
|
|
9
|
-
PencilAltIcon,
|
|
10
|
-
} from '@patternfly/react-icons';
|
|
11
|
-
import {
|
|
12
|
-
TextInput,
|
|
13
|
-
Checkbox,
|
|
14
|
-
Button,
|
|
15
|
-
FormHelperText,
|
|
16
|
-
HelperText,
|
|
17
|
-
HelperTextItem,
|
|
18
|
-
Icon,
|
|
19
|
-
TextArea,
|
|
20
|
-
FormGroup,
|
|
21
|
-
Popover,
|
|
22
|
-
Grid,
|
|
23
|
-
GridItem,
|
|
24
|
-
} from '@patternfly/react-core';
|
|
25
|
-
|
|
26
|
-
const FormField = ({
|
|
27
|
-
name,
|
|
28
|
-
type,
|
|
29
|
-
required,
|
|
30
|
-
options,
|
|
31
|
-
validated,
|
|
32
|
-
value,
|
|
33
|
-
disabled,
|
|
34
|
-
setValue,
|
|
35
|
-
placeholder,
|
|
36
|
-
errMsg,
|
|
37
|
-
fieldId,
|
|
38
|
-
setIsPasswordDisabled,
|
|
39
|
-
...props
|
|
40
|
-
}) => {
|
|
41
|
-
const [fieldValidated, setFieldValidated] = useState('default');
|
|
42
|
-
const [firstLoad, setFirstLoad] = useState(true);
|
|
43
|
-
|
|
44
|
-
const requiredValidate = () => {
|
|
45
|
-
if (firstLoad || !required) return;
|
|
46
|
-
if (!value || value === '' || validated === 'error')
|
|
47
|
-
setFieldValidated('error');
|
|
48
|
-
else setFieldValidated('success');
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
const localHandler = (_event, newValue) => {
|
|
52
|
-
setValue(name, newValue);
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
useEffect(() => {
|
|
56
|
-
setFirstLoad(false);
|
|
57
|
-
}, []);
|
|
58
|
-
|
|
59
|
-
useEffect(() => {
|
|
60
|
-
requiredValidate();
|
|
61
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
62
|
-
}, [value]);
|
|
63
|
-
|
|
64
|
-
if (type === 'checkbox') {
|
|
65
|
-
return (
|
|
66
|
-
<>
|
|
67
|
-
<Checkbox
|
|
68
|
-
ouiaId={name}
|
|
69
|
-
id={fieldId ?? `id-${name}`}
|
|
70
|
-
isChecked={value || false}
|
|
71
|
-
onChange={(_, newValue) => {
|
|
72
|
-
setValue(name, newValue);
|
|
73
|
-
}}
|
|
74
|
-
isDisabled={disabled}
|
|
75
|
-
isRequired={required}
|
|
76
|
-
type={type}
|
|
77
|
-
validated={fieldValidated}
|
|
78
|
-
/>
|
|
79
|
-
<ValidationComponent localValidated={fieldValidated} errMsg={errMsg} />
|
|
80
|
-
</>
|
|
81
|
-
);
|
|
82
|
-
} else if (type === 'textarea') {
|
|
83
|
-
return (
|
|
84
|
-
<>
|
|
85
|
-
<TextArea
|
|
86
|
-
rows={6}
|
|
87
|
-
name={name}
|
|
88
|
-
id={fieldId ?? `id-${name}`}
|
|
89
|
-
value={value ?? ''}
|
|
90
|
-
onChange={(_, newValue) => setValue(name, newValue)}
|
|
91
|
-
isRequired={required}
|
|
92
|
-
isDisabled={disabled}
|
|
93
|
-
type={type}
|
|
94
|
-
validated={fieldValidated}
|
|
95
|
-
placeholder={placeholder}
|
|
96
|
-
/>
|
|
97
|
-
<ValidationComponent localValidated={fieldValidated} errMsg={errMsg} />
|
|
98
|
-
</>
|
|
99
|
-
);
|
|
100
|
-
} else if (options.length !== 0) {
|
|
101
|
-
return (
|
|
102
|
-
<>
|
|
103
|
-
<AutocompleteInput
|
|
104
|
-
options={options}
|
|
105
|
-
selected={value ?? ''}
|
|
106
|
-
onSelect={newValue => setValue(name, newValue)}
|
|
107
|
-
onChange={() => requiredValidate()}
|
|
108
|
-
name={name}
|
|
109
|
-
placeholder={placeholder}
|
|
110
|
-
validationStatus={fieldValidated}
|
|
111
|
-
validationMsg={errMsg}
|
|
112
|
-
fieldId={fieldId}
|
|
113
|
-
/>
|
|
114
|
-
</>
|
|
115
|
-
);
|
|
116
|
-
}
|
|
117
|
-
return (
|
|
118
|
-
<>
|
|
119
|
-
{name === 'password' && disabled && setIsPasswordDisabled ? (
|
|
120
|
-
<Grid hasGutter={false}>
|
|
121
|
-
<GridItem span={11}>
|
|
122
|
-
<TextInput
|
|
123
|
-
name={name}
|
|
124
|
-
value={value ?? ''}
|
|
125
|
-
id={fieldId ?? `id-${name}`}
|
|
126
|
-
onChange={localHandler}
|
|
127
|
-
isDisabled={disabled}
|
|
128
|
-
isRequired={required}
|
|
129
|
-
type={type}
|
|
130
|
-
validated={fieldValidated}
|
|
131
|
-
placeholder={placeholder}
|
|
132
|
-
onBlur={requiredValidate}
|
|
133
|
-
autoComplete="off"
|
|
134
|
-
/>
|
|
135
|
-
</GridItem>
|
|
136
|
-
<GridItem span={1}>
|
|
137
|
-
<Button
|
|
138
|
-
ouiaId={`reset-${name}`}
|
|
139
|
-
onClick={() => setIsPasswordDisabled(!disabled)}
|
|
140
|
-
variant="control"
|
|
141
|
-
icon={<PencilAltIcon />}
|
|
142
|
-
/>
|
|
143
|
-
</GridItem>
|
|
144
|
-
</Grid>
|
|
145
|
-
) : (
|
|
146
|
-
<TextInput
|
|
147
|
-
name={name}
|
|
148
|
-
value={value ?? ''}
|
|
149
|
-
id={fieldId ?? `id-${name}`}
|
|
150
|
-
onChange={localHandler}
|
|
151
|
-
isRequired={required}
|
|
152
|
-
type={type}
|
|
153
|
-
validated={fieldValidated}
|
|
154
|
-
onBlur={requiredValidate}
|
|
155
|
-
autoComplete={type === 'password' ? 'new-password' : null}
|
|
156
|
-
/>
|
|
157
|
-
)}
|
|
158
|
-
|
|
159
|
-
<ValidationComponent localValidated={fieldValidated} errMsg={errMsg} />
|
|
160
|
-
</>
|
|
161
|
-
);
|
|
162
|
-
};
|
|
163
|
-
|
|
164
|
-
const ValidationComponent = ({ localValidated, errMsg }) => (
|
|
165
|
-
<>
|
|
166
|
-
{localValidated === 'error' && (
|
|
167
|
-
<FormHelperText>
|
|
168
|
-
<HelperText>
|
|
169
|
-
<HelperTextItem
|
|
170
|
-
icon={
|
|
171
|
-
<Icon>
|
|
172
|
-
<ExclamationCircleIcon />
|
|
173
|
-
</Icon>
|
|
174
|
-
}
|
|
175
|
-
variant={localValidated}
|
|
176
|
-
>
|
|
177
|
-
{errMsg ?? __('Field is required')}
|
|
178
|
-
</HelperTextItem>
|
|
179
|
-
</HelperText>
|
|
180
|
-
</FormHelperText>
|
|
181
|
-
)}
|
|
182
|
-
</>
|
|
183
|
-
);
|
|
184
|
-
|
|
185
|
-
const FieldConstructor = ({
|
|
186
|
-
label,
|
|
187
|
-
value,
|
|
188
|
-
required,
|
|
189
|
-
labelHelp,
|
|
190
|
-
fieldId,
|
|
191
|
-
name,
|
|
192
|
-
...props
|
|
193
|
-
}) => (
|
|
194
|
-
<FormGroup
|
|
195
|
-
isInline
|
|
196
|
-
fieldId={fieldId ?? `id-${name}`}
|
|
197
|
-
label={label}
|
|
198
|
-
isRequired={required}
|
|
199
|
-
labelIcon={
|
|
200
|
-
labelHelp ? (
|
|
201
|
-
<Popover
|
|
202
|
-
bodyContent={
|
|
203
|
-
typeof labelHelp === 'string' ? (
|
|
204
|
-
<div dangerouslySetInnerHTML={{ __html: labelHelp }} />
|
|
205
|
-
) : (
|
|
206
|
-
labelHelp
|
|
207
|
-
)
|
|
208
|
-
}
|
|
209
|
-
>
|
|
210
|
-
<Button
|
|
211
|
-
ouiaId={`label-${label}`}
|
|
212
|
-
type="button"
|
|
213
|
-
variant="plain"
|
|
214
|
-
onClick={e => e.preventDefault()}
|
|
215
|
-
>
|
|
216
|
-
<Icon>
|
|
217
|
-
<HelpIcon />
|
|
218
|
-
</Icon>
|
|
219
|
-
</Button>
|
|
220
|
-
</Popover>
|
|
221
|
-
) : (
|
|
222
|
-
''
|
|
223
|
-
)
|
|
224
|
-
}
|
|
225
|
-
>
|
|
226
|
-
<FormField
|
|
227
|
-
value={value}
|
|
228
|
-
required={required}
|
|
229
|
-
name={name}
|
|
230
|
-
{...props}
|
|
231
|
-
fieldId={fieldId}
|
|
232
|
-
/>
|
|
233
|
-
</FormGroup>
|
|
234
|
-
);
|
|
235
|
-
|
|
236
|
-
FieldConstructor.propTypes = {
|
|
237
|
-
label: PropTypes.string.isRequired,
|
|
238
|
-
required: PropTypes.bool,
|
|
239
|
-
labelHelp: PropTypes.oneOfType([
|
|
240
|
-
PropTypes.string,
|
|
241
|
-
PropTypes.object,
|
|
242
|
-
PropTypes.node,
|
|
243
|
-
]),
|
|
244
|
-
setValue: PropTypes.func.isRequired,
|
|
245
|
-
name: PropTypes.string.isRequired,
|
|
246
|
-
disabled: PropTypes.bool,
|
|
247
|
-
value: PropTypes.oneOfType([
|
|
248
|
-
PropTypes.string,
|
|
249
|
-
PropTypes.object,
|
|
250
|
-
PropTypes.bool,
|
|
251
|
-
PropTypes.number,
|
|
252
|
-
]),
|
|
253
|
-
fieldId: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
|
254
|
-
};
|
|
255
|
-
|
|
256
|
-
FieldConstructor.defaultProps = {
|
|
257
|
-
labelHelp: undefined,
|
|
258
|
-
required: false,
|
|
259
|
-
disabled: false,
|
|
260
|
-
value: '',
|
|
261
|
-
fieldId: undefined,
|
|
262
|
-
};
|
|
263
|
-
|
|
264
|
-
FormField.propTypes = {
|
|
265
|
-
disabled: PropTypes.bool,
|
|
266
|
-
setValue: PropTypes.func.isRequired,
|
|
267
|
-
name: PropTypes.string.isRequired,
|
|
268
|
-
type: PropTypes.string.isRequired,
|
|
269
|
-
label: PropTypes.string,
|
|
270
|
-
required: PropTypes.bool,
|
|
271
|
-
allowClear: PropTypes.bool,
|
|
272
|
-
options: PropTypes.arrayOf(
|
|
273
|
-
PropTypes.shape({
|
|
274
|
-
value: PropTypes.oneOfType([PropTypes.string, PropTypes.number])
|
|
275
|
-
.isRequired,
|
|
276
|
-
label: PropTypes.string.isRequired,
|
|
277
|
-
})
|
|
278
|
-
),
|
|
279
|
-
validated: PropTypes.string,
|
|
280
|
-
placeholder: PropTypes.string,
|
|
281
|
-
errMsg: PropTypes.string,
|
|
282
|
-
value: PropTypes.oneOfType([
|
|
283
|
-
PropTypes.bool,
|
|
284
|
-
PropTypes.string,
|
|
285
|
-
PropTypes.number,
|
|
286
|
-
]),
|
|
287
|
-
fieldId: PropTypes.string,
|
|
288
|
-
};
|
|
289
|
-
|
|
290
|
-
FormField.defaultProps = {
|
|
291
|
-
label: '',
|
|
292
|
-
errMsg: null,
|
|
293
|
-
placeholder: '',
|
|
294
|
-
validated: 'default',
|
|
295
|
-
required: false,
|
|
296
|
-
allowClear: false,
|
|
297
|
-
options: [],
|
|
298
|
-
disabled: false,
|
|
299
|
-
value: '',
|
|
300
|
-
fieldId: undefined,
|
|
301
|
-
};
|
|
302
|
-
|
|
303
|
-
ValidationComponent.propTypes = {
|
|
304
|
-
localValidated: PropTypes.string.isRequired,
|
|
305
|
-
errMsg: PropTypes.string,
|
|
306
|
-
};
|
|
307
|
-
|
|
308
|
-
ValidationComponent.defaultProps = {
|
|
309
|
-
errMsg: null,
|
|
310
|
-
};
|
|
311
|
-
|
|
312
|
-
export default FieldConstructor;
|
|
@@ -1,216 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { render, screen, fireEvent } from '@testing-library/react';
|
|
3
|
-
import userEvent from '@testing-library/user-event';
|
|
4
|
-
import '@testing-library/jest-dom';
|
|
5
|
-
import FieldConstructor from '../FieldConstructor';
|
|
6
|
-
|
|
7
|
-
const defaultProps = {
|
|
8
|
-
name: 'test-field',
|
|
9
|
-
setValue: jest.fn(),
|
|
10
|
-
label: 'Test Field',
|
|
11
|
-
value: '',
|
|
12
|
-
type: 'text',
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
describe('FieldConstructor RTL Tests', () => {
|
|
16
|
-
beforeEach(() => {
|
|
17
|
-
jest.clearAllMocks();
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
describe('Text Input Fields', () => {
|
|
21
|
-
test('renders text input field', () => {
|
|
22
|
-
render(<FieldConstructor {...defaultProps} type="text" />);
|
|
23
|
-
|
|
24
|
-
expect(screen.getByText('Test Field')).toBeInTheDocument();
|
|
25
|
-
expect(document.getElementById('id-test-field')).toHaveAttribute(
|
|
26
|
-
'type',
|
|
27
|
-
'text'
|
|
28
|
-
);
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
test('renders password input field', () => {
|
|
32
|
-
render(<FieldConstructor {...defaultProps} type="password" />);
|
|
33
|
-
|
|
34
|
-
expect(screen.getByText('Test Field')).toBeInTheDocument();
|
|
35
|
-
expect(document.getElementById('id-test-field')).toHaveAttribute(
|
|
36
|
-
'type',
|
|
37
|
-
'password'
|
|
38
|
-
);
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
test('calls setValue when text input changes', () => {
|
|
42
|
-
render(<FieldConstructor {...defaultProps} type="text" />);
|
|
43
|
-
|
|
44
|
-
const input = document.getElementById('id-test-field');
|
|
45
|
-
fireEvent.change(input, { target: { value: 'test value' } });
|
|
46
|
-
|
|
47
|
-
expect(defaultProps.setValue).toHaveBeenCalledWith(
|
|
48
|
-
'test-field',
|
|
49
|
-
'test value'
|
|
50
|
-
);
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
test('renders with initial value', () => {
|
|
54
|
-
render(
|
|
55
|
-
<FieldConstructor {...defaultProps} type="text" value="initial value" />
|
|
56
|
-
);
|
|
57
|
-
|
|
58
|
-
expect(document.getElementById('id-test-field')).toHaveValue(
|
|
59
|
-
'initial value'
|
|
60
|
-
);
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
test('renders as enabled when loading', () => {
|
|
64
|
-
render(<FieldConstructor {...defaultProps} type="text" isLoading />);
|
|
65
|
-
|
|
66
|
-
expect(document.getElementById('id-test-field')).toBeEnabled();
|
|
67
|
-
});
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
describe('Textarea Fields', () => {
|
|
71
|
-
test('renders textarea field', () => {
|
|
72
|
-
render(<FieldConstructor {...defaultProps} type="textarea" />);
|
|
73
|
-
|
|
74
|
-
expect(screen.getByText('Test Field')).toBeInTheDocument();
|
|
75
|
-
expect(document.getElementById('id-test-field').tagName).toBe('TEXTAREA');
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
test('calls setValue when textarea changes', () => {
|
|
79
|
-
render(<FieldConstructor {...defaultProps} type="textarea" />);
|
|
80
|
-
|
|
81
|
-
const textarea = document.getElementById('id-test-field');
|
|
82
|
-
fireEvent.change(textarea, { target: { value: 'textarea content' } });
|
|
83
|
-
|
|
84
|
-
expect(defaultProps.setValue).toHaveBeenCalledWith(
|
|
85
|
-
'test-field',
|
|
86
|
-
'textarea content'
|
|
87
|
-
);
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
test('renders with specified rows', () => {
|
|
91
|
-
render(<FieldConstructor {...defaultProps} type="textarea" rows={5} />);
|
|
92
|
-
|
|
93
|
-
expect(document.getElementsByTagName('textarea')).toHaveLength(1);
|
|
94
|
-
});
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
describe('Checkbox Fields', () => {
|
|
98
|
-
test('renders checkbox field', () => {
|
|
99
|
-
render(<FieldConstructor {...defaultProps} type="checkbox" />);
|
|
100
|
-
|
|
101
|
-
expect(screen.getByText('Test Field')).toBeInTheDocument();
|
|
102
|
-
expect(document.getElementById('id-test-field')).toHaveAttribute(
|
|
103
|
-
'type',
|
|
104
|
-
'checkbox'
|
|
105
|
-
);
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
test('renders unchecked checkbox', () => {
|
|
109
|
-
render(
|
|
110
|
-
<FieldConstructor {...defaultProps} type="checkbox" value={false} />
|
|
111
|
-
);
|
|
112
|
-
|
|
113
|
-
expect(document.getElementById('id-test-field')).not.toBeChecked();
|
|
114
|
-
});
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
describe('Autocomplete render test', () => {
|
|
118
|
-
test('renders autocomplete', () => {
|
|
119
|
-
const props = {
|
|
120
|
-
...defaultProps,
|
|
121
|
-
onChange: defaultProps.setValue,
|
|
122
|
-
options: [
|
|
123
|
-
{ value: 'host_created.event.foreman', label: 'Host Created' },
|
|
124
|
-
{ value: 'host_updated.event.foreman', label: 'Host Updated' },
|
|
125
|
-
],
|
|
126
|
-
};
|
|
127
|
-
render(<FieldConstructor {...props} type="select" />);
|
|
128
|
-
|
|
129
|
-
expect(screen.getByRole('combobox')).toBeInTheDocument();
|
|
130
|
-
});
|
|
131
|
-
});
|
|
132
|
-
|
|
133
|
-
describe('Label Help', () => {
|
|
134
|
-
test('renders help icon when labelHelp is provided', () => {
|
|
135
|
-
render(
|
|
136
|
-
<FieldConstructor {...defaultProps} labelHelp="This is help text" />
|
|
137
|
-
);
|
|
138
|
-
|
|
139
|
-
expect(screen.getByRole('button')).toBeInTheDocument();
|
|
140
|
-
});
|
|
141
|
-
|
|
142
|
-
test('does not render help icon when labelHelp is not provided', () => {
|
|
143
|
-
render(<FieldConstructor {...defaultProps} />);
|
|
144
|
-
|
|
145
|
-
expect(screen.queryByRole('button')).not.toBeInTheDocument();
|
|
146
|
-
});
|
|
147
|
-
|
|
148
|
-
test('renders help icon with JSX content', async () => {
|
|
149
|
-
const helpContent = <div>JSX help content</div>;
|
|
150
|
-
render(<FieldConstructor {...defaultProps} labelHelp={helpContent} />);
|
|
151
|
-
|
|
152
|
-
const button = screen.getByRole('button');
|
|
153
|
-
expect(button).toBeInTheDocument();
|
|
154
|
-
|
|
155
|
-
userEvent.click(button);
|
|
156
|
-
|
|
157
|
-
expect(await screen.findByText('JSX help content')).toBeInTheDocument();
|
|
158
|
-
});
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
describe('Validation', () => {
|
|
162
|
-
test('renders error message when validated is error', async () => {
|
|
163
|
-
render(
|
|
164
|
-
<>
|
|
165
|
-
<FieldConstructor {...defaultProps} required type="text" />
|
|
166
|
-
<button>Dummy</button>
|
|
167
|
-
</>
|
|
168
|
-
);
|
|
169
|
-
|
|
170
|
-
const input = document.getElementById('id-test-field');
|
|
171
|
-
await userEvent.click(input);
|
|
172
|
-
expect(input).toHaveFocus();
|
|
173
|
-
|
|
174
|
-
await userEvent.tab();
|
|
175
|
-
expect(input).not.toHaveFocus();
|
|
176
|
-
|
|
177
|
-
expect(screen.getByText('Field is required')).toBeInTheDocument();
|
|
178
|
-
});
|
|
179
|
-
|
|
180
|
-
test('does not render error message when validated is not error', () => {
|
|
181
|
-
render(
|
|
182
|
-
<FieldConstructor {...defaultProps} type="text" validated="success" />
|
|
183
|
-
);
|
|
184
|
-
|
|
185
|
-
expect(screen.queryByText('Field is required')).not.toBeInTheDocument();
|
|
186
|
-
});
|
|
187
|
-
});
|
|
188
|
-
|
|
189
|
-
describe('Edge Cases', () => {
|
|
190
|
-
test('handles undefined value', () => {
|
|
191
|
-
render(
|
|
192
|
-
<FieldConstructor {...defaultProps} type="text" value={undefined} />
|
|
193
|
-
);
|
|
194
|
-
|
|
195
|
-
expect(document.getElementById('id-test-field')).toHaveValue('');
|
|
196
|
-
});
|
|
197
|
-
|
|
198
|
-
test('handles null value', () => {
|
|
199
|
-
render(<FieldConstructor {...defaultProps} type="text" value={null} />);
|
|
200
|
-
|
|
201
|
-
expect(document.getElementById('id-test-field')).toHaveValue('');
|
|
202
|
-
});
|
|
203
|
-
|
|
204
|
-
test('handles numeric value', () => {
|
|
205
|
-
render(<FieldConstructor {...defaultProps} type="text" value={123} />);
|
|
206
|
-
|
|
207
|
-
expect(document.getElementById('id-test-field')).toHaveValue('123');
|
|
208
|
-
});
|
|
209
|
-
|
|
210
|
-
test('handles boolean value for checkbox', () => {
|
|
211
|
-
render(<FieldConstructor {...defaultProps} type="checkbox" value />);
|
|
212
|
-
|
|
213
|
-
expect(document.getElementById('id-test-field')).toBeChecked();
|
|
214
|
-
});
|
|
215
|
-
});
|
|
216
|
-
});
|