foreman-tasks 12.2.4 → 13.1.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/app/controllers/foreman_tasks/tasks_controller.rb +0 -5
- data/app/services/foreman_tasks/troubleshooting_help_generator.rb +1 -1
- data/config/routes.rb +3 -2
- data/lib/foreman_tasks/engine.rb +2 -2
- data/lib/foreman_tasks/version.rb +1 -1
- data/test/controllers/tasks_controller_test.rb +0 -9
- data/test/foreman_tasks_test_helper.rb +2 -2
- data/test/integration/tasks_test.rb +17 -0
- data/test/test_plugin_helper.rb +8 -0
- data/webpack/ForemanTasks/Components/TaskDetails/Components/Task.js +8 -70
- data/webpack/ForemanTasks/Components/TaskDetails/Components/TaskButtons.js +115 -104
- data/webpack/ForemanTasks/Components/TaskDetails/Components/TaskButtons.scss +45 -0
- data/webpack/ForemanTasks/Components/TaskDetails/Components/TaskHelper.js +54 -0
- data/webpack/ForemanTasks/Components/TaskDetails/Components/TaskInfo.js +237 -177
- data/webpack/ForemanTasks/Components/TaskDetails/Components/TaskSkeleton.js +1 -6
- data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/Task.test.js +27 -35
- data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/TaskButtons.test.js +83 -69
- data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/TaskHelper.test.js +118 -1
- data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/TaskInfo.test.js +190 -20
- data/webpack/ForemanTasks/Components/TaskDetails/ExecutionDetails.js +65 -0
- data/webpack/ForemanTasks/Components/TaskDetails/TaskDetails.js +76 -65
- data/webpack/ForemanTasks/Components/TaskDetails/TaskDetails.scss +1 -44
- data/webpack/ForemanTasks/Components/TaskDetails/TaskDetailsConstants.js +2 -1
- data/webpack/ForemanTasks/Components/TaskDetails/TaskDetailsSelectors.js +20 -10
- data/webpack/ForemanTasks/Components/TaskDetails/__tests__/ExecutionDetails.test.js +194 -0
- data/webpack/ForemanTasks/Components/TaskDetails/__tests__/TaskDetails.fixtures.js +100 -1
- data/webpack/ForemanTasks/Components/TaskDetails/__tests__/TaskDetails.test.js +226 -18
- data/webpack/ForemanTasks/Components/TaskDetails/__tests__/TaskDetailsSelectors.test.js +81 -0
- data/webpack/ForemanTasks/Components/common/taskResultIcon.js +53 -0
- data/webpack/ForemanTasks/Routes/ShowTaskDetails/TaskDetailsHeader.js +174 -0
- data/webpack/ForemanTasks/Routes/ShowTaskDetails/TaskDetailsHeader.scss +5 -0
- data/webpack/ForemanTasks/Routes/ShowTaskDetails/TaskDetailsPage.js +51 -0
- data/webpack/ForemanTasks/Routes/ShowTaskDetails/__tests__/TaskDetailsHeader.test.js +142 -0
- data/webpack/ForemanTasks/Routes/ShowTaskDetails/__tests__/TaskDetailsPage.test.js +277 -0
- data/webpack/ForemanTasks/{Components/TaskDetails → Routes/ShowTaskDetails}/index.js +13 -12
- data/webpack/Routes/routes.js +6 -0
- data/webpack/Routes/routes.test.js +16 -5
- data/webpack/index.js +0 -5
- metadata +16 -3
- data/app/views/foreman_tasks/tasks/show.html.erb +0 -18
|
@@ -1,76 +1,40 @@
|
|
|
1
|
-
import React from 'react';
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
3
|
import {
|
|
4
|
+
ClipboardCopy,
|
|
5
|
+
ExpandableSection,
|
|
6
|
+
ExpandableSectionToggle,
|
|
7
|
+
Flex,
|
|
8
|
+
FlexItem,
|
|
4
9
|
Grid,
|
|
5
10
|
GridItem,
|
|
6
11
|
Progress,
|
|
7
12
|
ProgressVariant,
|
|
8
|
-
|
|
13
|
+
Split,
|
|
14
|
+
SplitItem,
|
|
15
|
+
Text,
|
|
16
|
+
TextVariants,
|
|
9
17
|
} from '@patternfly/react-core';
|
|
10
|
-
import
|
|
11
|
-
|
|
12
|
-
ExclamationCircleIcon,
|
|
13
|
-
ExclamationTriangleIcon,
|
|
14
|
-
QuestionCircleIcon,
|
|
15
|
-
} from '@patternfly/react-icons';
|
|
16
|
-
import { translate as __ } from 'foremanReact/common/I18n';
|
|
18
|
+
import capitalize from 'lodash/capitalize';
|
|
19
|
+
import { translate as __, sprintf } from 'foremanReact/common/I18n';
|
|
17
20
|
import RelativeDateTime from 'foremanReact/components/common/dates/RelativeDateTime';
|
|
18
21
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
) {
|
|
26
|
-
return false;
|
|
27
|
-
}
|
|
28
|
-
const a = new Date(startAt);
|
|
29
|
-
const b = new Date(startedAt);
|
|
30
|
-
if (Number.isNaN(a.getTime()) || Number.isNaN(b.getTime())) {
|
|
31
|
-
return false;
|
|
32
|
-
}
|
|
33
|
-
a.setMilliseconds(0);
|
|
34
|
-
b.setMilliseconds(0);
|
|
35
|
-
return a.getTime() !== b.getTime();
|
|
36
|
-
};
|
|
22
|
+
import { taskResultIconEl } from '../../common/taskResultIcon';
|
|
23
|
+
import {
|
|
24
|
+
formatTaskDuration,
|
|
25
|
+
isDelayed,
|
|
26
|
+
parseUsernameLinkHref,
|
|
27
|
+
} from './TaskHelper';
|
|
37
28
|
|
|
38
|
-
const
|
|
39
|
-
if (
|
|
40
|
-
return (
|
|
41
|
-
<Icon>
|
|
42
|
-
<QuestionCircleIcon />
|
|
43
|
-
</Icon>
|
|
44
|
-
);
|
|
45
|
-
switch (result) {
|
|
46
|
-
case 'success':
|
|
47
|
-
return (
|
|
48
|
-
<Icon status="success">
|
|
49
|
-
<CheckCircleIcon />
|
|
50
|
-
</Icon>
|
|
51
|
-
);
|
|
52
|
-
case 'error':
|
|
53
|
-
return (
|
|
54
|
-
<Icon status="danger">
|
|
55
|
-
<ExclamationCircleIcon />
|
|
56
|
-
</Icon>
|
|
57
|
-
);
|
|
58
|
-
case 'warning':
|
|
59
|
-
return (
|
|
60
|
-
<Icon status="warning">
|
|
61
|
-
<ExclamationTriangleIcon />
|
|
62
|
-
</Icon>
|
|
63
|
-
);
|
|
64
|
-
default:
|
|
65
|
-
return (
|
|
66
|
-
<Icon>
|
|
67
|
-
<QuestionCircleIcon />
|
|
68
|
-
</Icon>
|
|
69
|
-
);
|
|
29
|
+
const formatResultLabel = result => {
|
|
30
|
+
if (!result || typeof result !== 'string') {
|
|
31
|
+
return __('N/A');
|
|
70
32
|
}
|
|
33
|
+
|
|
34
|
+
return capitalize(result);
|
|
71
35
|
};
|
|
72
36
|
|
|
73
|
-
const
|
|
37
|
+
const progressVariant = result => {
|
|
74
38
|
switch (result) {
|
|
75
39
|
case 'error':
|
|
76
40
|
return ProgressVariant.danger;
|
|
@@ -83,140 +47,234 @@ const progressVariantForResult = result => {
|
|
|
83
47
|
}
|
|
84
48
|
};
|
|
85
49
|
|
|
50
|
+
const MetadataField = ({ title, value, className, labelOuiaId, span }) => (
|
|
51
|
+
<GridItem
|
|
52
|
+
{...(span ? { span } : { xl: 2, lg: 4, md: 6, sm: 12 })}
|
|
53
|
+
className={className}
|
|
54
|
+
>
|
|
55
|
+
<Flex
|
|
56
|
+
direction={{ default: 'column' }}
|
|
57
|
+
spaceItems={{ default: 'spaceItemsXs' }}
|
|
58
|
+
>
|
|
59
|
+
<FlexItem>
|
|
60
|
+
<Text ouiaId={labelOuiaId} component={TextVariants.small}>
|
|
61
|
+
{title}
|
|
62
|
+
</Text>
|
|
63
|
+
</FlexItem>
|
|
64
|
+
<FlexItem>{value}</FlexItem>
|
|
65
|
+
</Flex>
|
|
66
|
+
</GridItem>
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
MetadataField.propTypes = {
|
|
70
|
+
title: PropTypes.node.isRequired,
|
|
71
|
+
value: PropTypes.node.isRequired,
|
|
72
|
+
className: PropTypes.string,
|
|
73
|
+
labelOuiaId: PropTypes.string.isRequired,
|
|
74
|
+
span: PropTypes.number,
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
MetadataField.defaultProps = {
|
|
78
|
+
className: undefined,
|
|
79
|
+
span: undefined,
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
const copyableText = text =>
|
|
83
|
+
text ? (
|
|
84
|
+
<ClipboardCopy
|
|
85
|
+
variant="inline-compact"
|
|
86
|
+
hoverTip={__('Copy')}
|
|
87
|
+
clickTip={__('Copied')}
|
|
88
|
+
>
|
|
89
|
+
{text}
|
|
90
|
+
</ClipboardCopy>
|
|
91
|
+
) : (
|
|
92
|
+
__('N/A')
|
|
93
|
+
);
|
|
94
|
+
|
|
86
95
|
const TaskInfo = props => {
|
|
87
96
|
const {
|
|
88
97
|
action,
|
|
89
98
|
endedAt,
|
|
99
|
+
externalId,
|
|
100
|
+
id,
|
|
101
|
+
label,
|
|
90
102
|
result,
|
|
91
103
|
startAt,
|
|
92
|
-
startBefore,
|
|
93
104
|
startedAt,
|
|
105
|
+
startBefore,
|
|
94
106
|
state,
|
|
95
107
|
help,
|
|
96
|
-
output,
|
|
97
|
-
errors,
|
|
98
108
|
progress,
|
|
99
109
|
username,
|
|
100
110
|
usernamePath,
|
|
101
111
|
} = props;
|
|
102
112
|
|
|
103
|
-
const
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
{
|
|
117
|
-
title: 'Result',
|
|
118
|
-
value: (
|
|
119
|
-
<span>
|
|
120
|
-
{resultIconEl(state, result)} {result}
|
|
121
|
-
</span>
|
|
122
|
-
),
|
|
123
|
-
},
|
|
124
|
-
{
|
|
125
|
-
title: 'Started at',
|
|
126
|
-
value: <RelativeDateTime defaultValue={__('N/A')} date={startedAt} />,
|
|
127
|
-
},
|
|
128
|
-
],
|
|
129
|
-
[
|
|
130
|
-
{
|
|
131
|
-
title: 'Triggered by',
|
|
132
|
-
value: (usernamePath || '').includes('href') ? (
|
|
133
|
-
<a href={usernamePath.split('"')[1]}>{username}</a>
|
|
134
|
-
) : (
|
|
135
|
-
username || ''
|
|
136
|
-
),
|
|
137
|
-
},
|
|
138
|
-
{
|
|
139
|
-
title: 'Ended at',
|
|
140
|
-
value: <RelativeDateTime defaultValue={__('N/A')} date={endedAt} />,
|
|
141
|
-
},
|
|
142
|
-
],
|
|
143
|
-
[
|
|
144
|
-
{
|
|
145
|
-
title: 'Execution type',
|
|
146
|
-
value: __(isDelayed(props) ? 'Delayed' : 'Immediate'),
|
|
147
|
-
},
|
|
148
|
-
{
|
|
149
|
-
title: 'Start before',
|
|
150
|
-
value: startBefore ? (
|
|
151
|
-
<RelativeDateTime defaultValue={__('N/A')} date={startBefore} />
|
|
152
|
-
) : (
|
|
153
|
-
'-'
|
|
154
|
-
),
|
|
155
|
-
},
|
|
156
|
-
],
|
|
157
|
-
];
|
|
113
|
+
const [isExpanded, setIsExpanded] = useState(false);
|
|
114
|
+
const baseId = id || 'task-info';
|
|
115
|
+
const contentId = `${baseId}-more-details-content`;
|
|
116
|
+
const toggleId = `${baseId}-more-details-toggle`;
|
|
117
|
+
|
|
118
|
+
const usernameHref = parseUsernameLinkHref(usernamePath)?.startsWith('/')
|
|
119
|
+
? parseUsernameLinkHref(usernamePath)
|
|
120
|
+
: null;
|
|
121
|
+
const triggeredBy = usernameHref ? (
|
|
122
|
+
<a href={usernameHref}>{username}</a>
|
|
123
|
+
) : (
|
|
124
|
+
username || ''
|
|
125
|
+
);
|
|
158
126
|
|
|
159
|
-
const progVariant =
|
|
127
|
+
const progVariant = progressVariant(result);
|
|
160
128
|
|
|
161
129
|
return (
|
|
162
|
-
<Grid>
|
|
163
|
-
<
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
</span>
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
130
|
+
<Grid className="task-details-overview" hasGutter>
|
|
131
|
+
<MetadataField
|
|
132
|
+
labelOuiaId="task-info-metadata-result-label"
|
|
133
|
+
title={__('Result')}
|
|
134
|
+
value={
|
|
135
|
+
<>
|
|
136
|
+
{taskResultIconEl(state, result)}
|
|
137
|
+
<span> {formatResultLabel(result)}</span>
|
|
138
|
+
</>
|
|
139
|
+
}
|
|
140
|
+
/>
|
|
141
|
+
<MetadataField
|
|
142
|
+
labelOuiaId="task-info-metadata-state-label"
|
|
143
|
+
title={__('State')}
|
|
144
|
+
value={capitalize(state) || __('N/A')}
|
|
145
|
+
/>
|
|
146
|
+
<MetadataField
|
|
147
|
+
labelOuiaId="task-info-metadata-started-at-label"
|
|
148
|
+
title={__('Started at')}
|
|
149
|
+
value={<RelativeDateTime defaultValue={__('N/A')} date={startedAt} />}
|
|
150
|
+
/>
|
|
151
|
+
<MetadataField
|
|
152
|
+
labelOuiaId="task-info-metadata-duration-label"
|
|
153
|
+
title={__('Duration')}
|
|
154
|
+
value={formatTaskDuration(startedAt, endedAt, state)}
|
|
155
|
+
/>
|
|
156
|
+
<MetadataField
|
|
157
|
+
labelOuiaId="task-info-metadata-triggered-by-label"
|
|
158
|
+
title={__('Triggered by')}
|
|
159
|
+
value={triggeredBy}
|
|
160
|
+
/>
|
|
161
|
+
<MetadataField
|
|
162
|
+
labelOuiaId="task-info-metadata-id-label"
|
|
163
|
+
title={__('Id')}
|
|
164
|
+
value={copyableText(id)}
|
|
165
|
+
/>
|
|
166
|
+
|
|
167
|
+
<GridItem span={12}>
|
|
168
|
+
<ExpandableSectionToggle
|
|
169
|
+
toggleId={toggleId}
|
|
170
|
+
contentId={contentId}
|
|
171
|
+
isExpanded={isExpanded}
|
|
172
|
+
onToggle={setIsExpanded}
|
|
173
|
+
>
|
|
174
|
+
{isExpanded ? __('Show less details') : __('Show more details')}
|
|
175
|
+
</ExpandableSectionToggle>
|
|
193
176
|
</GridItem>
|
|
177
|
+
|
|
194
178
|
<GridItem span={12}>
|
|
195
|
-
<
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
179
|
+
<ExpandableSection
|
|
180
|
+
isExpanded={isExpanded}
|
|
181
|
+
isDetached
|
|
182
|
+
toggleId={toggleId}
|
|
183
|
+
contentId={contentId}
|
|
184
|
+
>
|
|
185
|
+
<Grid hasGutter>
|
|
186
|
+
<MetadataField
|
|
187
|
+
labelOuiaId="task-info-metadata-execution-type-label"
|
|
188
|
+
title={__('Execution type')}
|
|
189
|
+
value={__(isDelayed(props) ? 'Delayed' : 'Immediate')}
|
|
190
|
+
/>
|
|
191
|
+
<MetadataField
|
|
192
|
+
labelOuiaId="task-info-metadata-label-field-label"
|
|
193
|
+
title={__('Label')}
|
|
194
|
+
value={label || action || __('N/A')}
|
|
195
|
+
className="details-name"
|
|
196
|
+
/>
|
|
197
|
+
<MetadataField
|
|
198
|
+
labelOuiaId="task-info-metadata-start-at-label"
|
|
199
|
+
title={__('Start at')}
|
|
200
|
+
value={
|
|
201
|
+
<Flex direction={{ default: 'column' }}>
|
|
202
|
+
<FlexItem>
|
|
203
|
+
<RelativeDateTime defaultValue={__('N/A')} date={startAt} />
|
|
204
|
+
</FlexItem>
|
|
205
|
+
{startBefore && (
|
|
206
|
+
<FlexItem>
|
|
207
|
+
<span>({__('before')} </span>
|
|
208
|
+
<RelativeDateTime
|
|
209
|
+
defaultValue={__('N/A')}
|
|
210
|
+
date={startBefore}
|
|
211
|
+
/>
|
|
212
|
+
<span>)</span>
|
|
213
|
+
</FlexItem>
|
|
214
|
+
)}
|
|
215
|
+
</Flex>
|
|
216
|
+
}
|
|
217
|
+
/>
|
|
218
|
+
<MetadataField
|
|
219
|
+
labelOuiaId="task-info-metadata-ended-at-label"
|
|
220
|
+
title={__('Ended at')}
|
|
221
|
+
value={
|
|
222
|
+
<RelativeDateTime defaultValue={__('N/A')} date={endedAt} />
|
|
223
|
+
}
|
|
224
|
+
/>
|
|
225
|
+
<MetadataField
|
|
226
|
+
labelOuiaId="task-info-metadata-external-id-label"
|
|
227
|
+
title={__('External Id')}
|
|
228
|
+
value={copyableText(externalId)}
|
|
229
|
+
/>
|
|
230
|
+
{help && (
|
|
231
|
+
<MetadataField
|
|
232
|
+
labelOuiaId="task-info-metadata-help-text-label"
|
|
233
|
+
title={__('Troubleshooting')}
|
|
234
|
+
span={12}
|
|
235
|
+
value={<p dangerouslySetInnerHTML={{ __html: help }} />}
|
|
236
|
+
/>
|
|
237
|
+
)}
|
|
238
|
+
</Grid>
|
|
239
|
+
</ExpandableSection>
|
|
202
240
|
</GridItem>
|
|
203
|
-
|
|
204
|
-
{
|
|
205
|
-
<GridItem span={12}>
|
|
206
|
-
<b>{__('Troubleshooting')}</b>
|
|
207
|
-
<p dangerouslySetInnerHTML={{ __html: help }} />
|
|
208
|
-
</GridItem>
|
|
209
|
-
)}
|
|
210
|
-
{output && output.length > 0 && (
|
|
211
|
-
<GridItem span={12}>
|
|
212
|
-
<b>{__('Output:')}</b>
|
|
213
|
-
<pre>{output}</pre>
|
|
214
|
-
</GridItem>
|
|
215
|
-
)}
|
|
216
|
-
{errors && errors.length > 0 && (
|
|
241
|
+
|
|
242
|
+
{state !== 'stopped' && (
|
|
217
243
|
<GridItem span={12}>
|
|
218
|
-
<
|
|
219
|
-
|
|
244
|
+
<Flex
|
|
245
|
+
direction={{ default: 'column' }}
|
|
246
|
+
spaceItems={{ default: 'spaceItemsXs' }}
|
|
247
|
+
>
|
|
248
|
+
<FlexItem>
|
|
249
|
+
<Split hasGutter>
|
|
250
|
+
<SplitItem isFilled>
|
|
251
|
+
<Text
|
|
252
|
+
component={TextVariants.p}
|
|
253
|
+
ouiaId="task-info-running-state-summary"
|
|
254
|
+
>
|
|
255
|
+
{capitalize(state)}
|
|
256
|
+
</Text>
|
|
257
|
+
</SplitItem>
|
|
258
|
+
<SplitItem>
|
|
259
|
+
<Text
|
|
260
|
+
component={TextVariants.p}
|
|
261
|
+
ouiaId="task-info-running-progress-complete-text"
|
|
262
|
+
>
|
|
263
|
+
{sprintf(__('%s%% Complete'), progress)}
|
|
264
|
+
</Text>
|
|
265
|
+
</SplitItem>
|
|
266
|
+
</Split>
|
|
267
|
+
</FlexItem>
|
|
268
|
+
<FlexItem>
|
|
269
|
+
<Progress
|
|
270
|
+
value={progress}
|
|
271
|
+
max={100}
|
|
272
|
+
aria-label={sprintf(__('%s%% Complete'), progress)}
|
|
273
|
+
measureLocation="outside"
|
|
274
|
+
{...(progVariant ? { variant: progVariant } : {})}
|
|
275
|
+
/>
|
|
276
|
+
</FlexItem>
|
|
277
|
+
</Flex>
|
|
220
278
|
</GridItem>
|
|
221
279
|
)}
|
|
222
280
|
</Grid>
|
|
@@ -226,33 +284,35 @@ const TaskInfo = props => {
|
|
|
226
284
|
TaskInfo.propTypes = {
|
|
227
285
|
action: PropTypes.string,
|
|
228
286
|
endedAt: PropTypes.string,
|
|
287
|
+
externalId: PropTypes.string,
|
|
288
|
+
id: PropTypes.string,
|
|
289
|
+
label: PropTypes.string,
|
|
229
290
|
result: PropTypes.string,
|
|
230
291
|
startAt: PropTypes.string,
|
|
231
292
|
startBefore: PropTypes.string,
|
|
232
293
|
startedAt: PropTypes.string,
|
|
233
294
|
state: PropTypes.string,
|
|
234
295
|
help: PropTypes.string,
|
|
235
|
-
errors: PropTypes.array,
|
|
236
296
|
progress: PropTypes.number,
|
|
237
297
|
username: PropTypes.string,
|
|
238
298
|
usernamePath: PropTypes.string,
|
|
239
|
-
output: PropTypes.oneOfType([PropTypes.string, PropTypes.shape({})]),
|
|
240
299
|
};
|
|
241
300
|
|
|
242
301
|
TaskInfo.defaultProps = {
|
|
243
302
|
action: '',
|
|
244
303
|
endedAt: '',
|
|
304
|
+
externalId: '',
|
|
305
|
+
id: '',
|
|
306
|
+
label: '',
|
|
245
307
|
result: 'error',
|
|
246
308
|
startAt: '',
|
|
247
309
|
startBefore: '',
|
|
248
310
|
startedAt: '',
|
|
249
311
|
state: '',
|
|
250
312
|
help: '',
|
|
251
|
-
errors: [],
|
|
252
313
|
progress: 0,
|
|
253
314
|
username: '',
|
|
254
315
|
usernamePath: '',
|
|
255
|
-
output: '',
|
|
256
316
|
};
|
|
257
317
|
|
|
258
318
|
export default TaskInfo;
|
|
@@ -27,12 +27,7 @@ export const TaskSkeleton = () => {
|
|
|
27
27
|
</React.Fragment>
|
|
28
28
|
))}
|
|
29
29
|
<GridItem span={12} className="pf-v5-u-pb-lg" />
|
|
30
|
-
<GridItem span={
|
|
31
|
-
<div className="progress-description">
|
|
32
|
-
<Skeleton />
|
|
33
|
-
</div>
|
|
34
|
-
</GridItem>
|
|
35
|
-
<GridItem span={6} className="progress-label-top-right">
|
|
30
|
+
<GridItem span={12}>
|
|
36
31
|
<Skeleton />
|
|
37
32
|
</GridItem>
|
|
38
33
|
<GridItem span={12}>
|
|
@@ -1,46 +1,38 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { render, screen } from '@testing-library/react';
|
|
3
|
+
import userEvent from '@testing-library/user-event';
|
|
3
4
|
import '@testing-library/jest-dom';
|
|
4
|
-
import { STATUS } from 'foremanReact/constants';
|
|
5
5
|
|
|
6
6
|
import Task from '../Task';
|
|
7
7
|
|
|
8
|
+
jest.mock('foremanReact/components/common/dates/RelativeDateTime', () => {
|
|
9
|
+
const RelativeDateTime = ({ date, defaultValue }) => (
|
|
10
|
+
<span>{date || defaultValue}</span>
|
|
11
|
+
);
|
|
12
|
+
|
|
13
|
+
return RelativeDateTime;
|
|
14
|
+
});
|
|
15
|
+
|
|
8
16
|
describe('Task', () => {
|
|
9
|
-
it('renders task
|
|
10
|
-
render(
|
|
11
|
-
<Task
|
|
12
|
-
id="test"
|
|
13
|
-
taskReloadStart={jest.fn()}
|
|
14
|
-
taskProgressToggle={jest.fn()}
|
|
15
|
-
/>
|
|
16
|
-
);
|
|
17
|
-
expect(
|
|
18
|
-
screen.getByRole('button', { name: /start auto-reloading/i })
|
|
19
|
-
).toBeInTheDocument();
|
|
20
|
-
});
|
|
17
|
+
it('renders task overview metadata via TaskInfo', async () => {
|
|
18
|
+
render(<Task id="test" action="Refresh hosts" />);
|
|
21
19
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
dynflowEnableConsole
|
|
29
|
-
parentTask="parent-id"
|
|
30
|
-
taskReload
|
|
31
|
-
canEdit
|
|
32
|
-
status={STATUS.RESOLVED}
|
|
33
|
-
taskProgressToggle={jest.fn()}
|
|
34
|
-
taskReloadStart={jest.fn()}
|
|
35
|
-
/>
|
|
36
|
-
);
|
|
37
|
-
expect(screen.getByRole('link', { name: /parent task/i })).toHaveAttribute(
|
|
38
|
-
'href',
|
|
39
|
-
'/foreman_tasks/tasks/parent-id'
|
|
40
|
-
);
|
|
41
|
-
expect(screen.getByRole('link', { name: /sub tasks/i })).toHaveAttribute(
|
|
42
|
-
'href',
|
|
43
|
-
'/foreman_tasks/tasks/test/sub_tasks'
|
|
20
|
+
expect(screen.getByText('Result')).toBeInTheDocument();
|
|
21
|
+
expect(screen.getByText('State')).toBeInTheDocument();
|
|
22
|
+
expect(screen.getByText('test')).toBeInTheDocument();
|
|
23
|
+
|
|
24
|
+
await userEvent.click(
|
|
25
|
+
screen.getByRole('button', { name: /show more details/i })
|
|
44
26
|
);
|
|
27
|
+
|
|
28
|
+
expect(screen.getByText('Refresh hosts')).toBeInTheDocument();
|
|
29
|
+
expect(screen.getByText('Label')).toBeInTheDocument();
|
|
30
|
+
expect(screen.getByText('Execution type')).toBeInTheDocument();
|
|
31
|
+
expect(
|
|
32
|
+
screen.queryByRole('button', { name: /cancel/i })
|
|
33
|
+
).not.toBeInTheDocument();
|
|
34
|
+
expect(
|
|
35
|
+
screen.queryByRole('button', { name: /^task actions$/i })
|
|
36
|
+
).not.toBeInTheDocument();
|
|
45
37
|
});
|
|
46
38
|
});
|