foreman-tasks 13.0.0 → 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.
Files changed (29) hide show
  1. checksums.yaml +4 -4
  2. data/app/services/foreman_tasks/troubleshooting_help_generator.rb +1 -1
  3. data/lib/foreman_tasks/version.rb +1 -1
  4. data/webpack/ForemanTasks/Components/TaskDetails/Components/Task.js +8 -70
  5. data/webpack/ForemanTasks/Components/TaskDetails/Components/TaskButtons.js +115 -104
  6. data/webpack/ForemanTasks/Components/TaskDetails/Components/TaskButtons.scss +45 -0
  7. data/webpack/ForemanTasks/Components/TaskDetails/Components/TaskHelper.js +54 -0
  8. data/webpack/ForemanTasks/Components/TaskDetails/Components/TaskInfo.js +236 -131
  9. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/Task.test.js +27 -33
  10. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/TaskButtons.test.js +83 -67
  11. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/TaskHelper.test.js +118 -1
  12. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/TaskInfo.test.js +190 -20
  13. data/webpack/ForemanTasks/Components/TaskDetails/ExecutionDetails.js +65 -0
  14. data/webpack/ForemanTasks/Components/TaskDetails/TaskDetails.js +48 -51
  15. data/webpack/ForemanTasks/Components/TaskDetails/TaskDetails.scss +0 -39
  16. data/webpack/ForemanTasks/Components/TaskDetails/TaskDetailsSelectors.js +0 -5
  17. data/webpack/ForemanTasks/Components/TaskDetails/__tests__/ExecutionDetails.test.js +194 -0
  18. data/webpack/ForemanTasks/Components/TaskDetails/__tests__/TaskDetails.fixtures.js +99 -0
  19. data/webpack/ForemanTasks/Components/TaskDetails/__tests__/TaskDetails.test.js +129 -8
  20. data/webpack/ForemanTasks/Routes/ShowTaskDetails/TaskDetailsHeader.js +174 -0
  21. data/webpack/ForemanTasks/Routes/ShowTaskDetails/TaskDetailsHeader.scss +5 -0
  22. data/webpack/ForemanTasks/Routes/ShowTaskDetails/TaskDetailsPage.js +10 -33
  23. data/webpack/ForemanTasks/Routes/ShowTaskDetails/__tests__/TaskDetailsHeader.test.js +142 -0
  24. data/webpack/ForemanTasks/Routes/ShowTaskDetails/__tests__/TaskDetailsPage.test.js +100 -88
  25. data/webpack/ForemanTasks/{Components/TaskDetails → Routes/ShowTaskDetails}/index.js +7 -8
  26. data/webpack/Routes/routes.js +1 -1
  27. data/webpack/Routes/routes.test.js +1 -1
  28. data/webpack/index.js +0 -5
  29. metadata +8 -2
@@ -0,0 +1,65 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import RunningSteps from './Components/RunningSteps';
4
+ import Errors from './Components/Errors';
5
+
6
+ const ExecutionDetails = ({
7
+ state,
8
+ runningSteps,
9
+ cancelStep,
10
+ id,
11
+ taskReload,
12
+ taskReloadStart,
13
+ executionPlan,
14
+ failedSteps,
15
+ result,
16
+ }) => {
17
+ const showingRunningSteps =
18
+ state === 'running' ||
19
+ state === 'pending' ||
20
+ state === 'paused' ||
21
+ runningSteps.length > 0;
22
+
23
+ return (
24
+ <div
25
+ id="execution-details-panel"
26
+ data-ouia-component-id="execution-details-panel"
27
+ >
28
+ {showingRunningSteps ? (
29
+ <RunningSteps
30
+ executionPlan={executionPlan}
31
+ result={result}
32
+ runningSteps={runningSteps}
33
+ id={id}
34
+ cancelStep={cancelStep}
35
+ taskReload={taskReload}
36
+ taskReloadStart={taskReloadStart}
37
+ />
38
+ ) : (
39
+ <Errors executionPlan={executionPlan} failedSteps={failedSteps} />
40
+ )}
41
+ </div>
42
+ );
43
+ };
44
+
45
+ ExecutionDetails.propTypes = {
46
+ state: PropTypes.string,
47
+ result: PropTypes.string,
48
+ runningSteps: PropTypes.array,
49
+ cancelStep: PropTypes.func.isRequired,
50
+ id: PropTypes.string.isRequired,
51
+ taskReload: PropTypes.bool.isRequired,
52
+ taskReloadStart: PropTypes.func.isRequired,
53
+ executionPlan: PropTypes.shape({}),
54
+ failedSteps: PropTypes.array,
55
+ };
56
+
57
+ ExecutionDetails.defaultProps = {
58
+ state: '',
59
+ result: undefined,
60
+ runningSteps: [],
61
+ executionPlan: {},
62
+ failedSteps: [],
63
+ };
64
+
65
+ export default ExecutionDetails;
@@ -6,17 +6,22 @@ import { STATUS } from 'foremanReact/constants';
6
6
  import { usePermissions } from 'foremanReact/common/hooks/Permissions/permissionHooks';
7
7
  import { ResourceLoadFailedEmptyState } from 'foremanReact/components/common/EmptyState';
8
8
  import Task from './Components/Task';
9
- import RunningSteps from './Components/RunningSteps';
10
- import Errors from './Components/Errors';
11
9
  import Locks from './Components/Locks';
12
10
  import Raw from './Components/Raw';
11
+ import ExecutionDetails from './ExecutionDetails';
13
12
  import Dependencies from './Components/Dependencies';
14
13
  import { TASKS_PATH, VIEW_FOREMAN_TASKS } from './TaskDetailsConstants';
15
- import { getTaskID } from './TasksDetailsHelper';
16
14
  import { TaskSkeleton } from './Components/TaskSkeleton';
17
15
 
18
16
  import './TaskDetails.scss';
19
17
 
18
+ export const TASK_DETAILS_TAB_KEYS = Object.freeze({
19
+ EXECUTION: 'execution',
20
+ DEPENDENCIES: 'dependencies',
21
+ LOCKS: 'locks',
22
+ RAW: 'raw',
23
+ });
24
+
20
25
  const TaskDetails = ({
21
26
  executionPlan,
22
27
  failedSteps,
@@ -31,11 +36,11 @@ const TaskDetails = ({
31
36
  apiStatus,
32
37
  apiErrorMessage,
33
38
  apiErrorCode,
39
+ id,
34
40
  ...props
35
41
  }) => {
36
- const id = getTaskID();
37
- const { taskReload, isLoading, result } = props;
38
- const [activeTabKey, setActiveTabKey] = useState(1);
42
+ const { taskReload, isLoading } = props;
43
+ const [activeTab, setActiveTab] = useState(TASK_DETAILS_TAB_KEYS.EXECUTION);
39
44
  const hasViewPermission = usePermissions([VIEW_FOREMAN_TASKS]);
40
45
 
41
46
  useEffect(() => {
@@ -76,7 +81,7 @@ const TaskDetails = ({
76
81
  const cancellable = executionPlan ? executionPlan.cancellable : false;
77
82
  const lockRecords = locks.concat(links);
78
83
 
79
- const taskComponentProps = {
84
+ const taskProps = {
80
85
  ...props,
81
86
  cancellable,
82
87
  resumable,
@@ -87,49 +92,49 @@ const TaskDetails = ({
87
92
 
88
93
  return (
89
94
  <div className="task-details-react">
95
+ <section className="task-details-overview-section">
96
+ {isLoading ? <TaskSkeleton /> : <Task {...taskProps} />}
97
+ </section>
90
98
  <Tabs
99
+ aria-label={__('Task details')}
91
100
  id="task-details-tabs"
92
101
  ouiaId="task-details-tabs"
93
- activeKey={activeTabKey}
94
- onSelect={(_event, tabKey) => setActiveTabKey(tabKey)}
102
+ activeKey={activeTab}
95
103
  mountOnEnter
104
+ onSelect={(_e, tabKey) => setActiveTab(tabKey)}
96
105
  >
97
106
  <Tab
98
- eventKey={1}
99
- title={<TabTitleText>{__('Task')}</TabTitleText>}
100
- aria-label={__('Task')}
101
- ouiaId="task-details-tab-task"
102
- >
103
- {isLoading ? <TaskSkeleton /> : <Task {...taskComponentProps} />}
104
- </Tab>
105
- <Tab
106
- eventKey={2}
107
- title={<TabTitleText>{__('Running Steps')}</TabTitleText>}
108
107
  isDisabled={isLoading}
109
- aria-label={__('Running Steps')}
110
- ouiaId="task-details-tab-running-steps"
108
+ eventKey={TASK_DETAILS_TAB_KEYS.EXECUTION}
109
+ title={<TabTitleText>{__('Execution details')}</TabTitleText>}
110
+ aria-label={__('Execution details')}
111
+ ouiaId="task-details-tab-execution-details"
111
112
  >
112
- <RunningSteps
113
- executionPlan={executionPlan}
114
- result={result}
115
- runningSteps={runningSteps}
116
- id={id}
117
- cancelStep={cancelStep}
118
- taskReload={taskReload}
119
- taskReloadStart={taskReloadStart}
120
- />
113
+ {!isLoading && (
114
+ <ExecutionDetails
115
+ state={props.state}
116
+ result={props.result}
117
+ runningSteps={runningSteps}
118
+ cancelStep={cancelStep}
119
+ id={id}
120
+ taskReload={taskReload}
121
+ taskReloadStart={taskReloadStart}
122
+ executionPlan={executionPlan}
123
+ failedSteps={failedSteps}
124
+ />
125
+ )}
121
126
  </Tab>
122
127
  <Tab
123
- eventKey={3}
124
- title={<TabTitleText>{__('Errors')}</TabTitleText>}
128
+ eventKey={TASK_DETAILS_TAB_KEYS.DEPENDENCIES}
125
129
  isDisabled={isLoading}
126
- aria-label={__('Errors')}
127
- ouiaId="task-details-tab-errors"
130
+ title={<TabTitleText>{__('Dependencies')}</TabTitleText>}
131
+ aria-label={__('Dependencies')}
132
+ ouiaId="task-details-tab-dependencies"
128
133
  >
129
- <Errors executionPlan={executionPlan} failedSteps={failedSteps} />
134
+ <Dependencies dependsOn={dependsOn} blocks={blocks} />
130
135
  </Tab>
131
136
  <Tab
132
- eventKey={4}
137
+ eventKey={TASK_DETAILS_TAB_KEYS.LOCKS}
133
138
  title={<TabTitleText>{__('Locks')}</TabTitleText>}
134
139
  isDisabled={isLoading}
135
140
  aria-label={__('Locks')}
@@ -138,16 +143,7 @@ const TaskDetails = ({
138
143
  <Locks locks={lockRecords} />
139
144
  </Tab>
140
145
  <Tab
141
- eventKey={5}
142
- title={<TabTitleText>{__('Dependencies')}</TabTitleText>}
143
- isDisabled={isLoading}
144
- aria-label={__('Dependencies')}
145
- ouiaId="task-details-tab-dependencies"
146
- >
147
- <Dependencies dependsOn={dependsOn} blocks={blocks} />
148
- </Tab>
149
- <Tab
150
- eventKey={6}
146
+ eventKey={TASK_DETAILS_TAB_KEYS.RAW}
151
147
  title={<TabTitleText>{__('Raw')}</TabTitleText>}
152
148
  isDisabled={isLoading}
153
149
  aria-label={__('Raw')}
@@ -169,7 +165,9 @@ const TaskDetails = ({
169
165
  };
170
166
 
171
167
  TaskDetails.propTypes = {
168
+ id: PropTypes.string.isRequired,
172
169
  label: PropTypes.string,
170
+ result: PropTypes.string,
173
171
  runningSteps: PropTypes.array,
174
172
  cancelStep: PropTypes.func.isRequired,
175
173
  taskReload: PropTypes.bool.isRequired,
@@ -181,10 +179,10 @@ TaskDetails.propTypes = {
181
179
  links: PropTypes.array,
182
180
  dependsOn: PropTypes.array,
183
181
  blocks: PropTypes.array,
182
+ executionPlan: PropTypes.shape({}),
183
+ failedSteps: PropTypes.array,
184
184
  ...Task.propTypes,
185
- ...Errors.propTypes,
186
185
  ...Locks.propTypes,
187
- ...Dependencies.propTypes,
188
186
  ...Raw.propTypes,
189
187
  };
190
188
  TaskDetails.defaultProps = {
@@ -194,11 +192,10 @@ TaskDetails.defaultProps = {
194
192
  links: [],
195
193
  dependsOn: [],
196
194
  blocks: [],
195
+ failedSteps: [],
196
+ executionPlan: {},
197
197
  ...Task.defaultProps,
198
- ...RunningSteps.defaultProps,
199
- ...Errors.defaultProps,
200
198
  ...Locks.defaultProps,
201
- ...Dependencies.defaultProps,
202
199
  ...Raw.defaultProps,
203
200
  };
204
201
 
@@ -6,45 +6,6 @@
6
6
  .container {
7
7
  margin: 0;
8
8
  }
9
- .spin {
10
- -webkit-animation: spin 1s infinite linear;
11
- -moz-animation: spin 1s infinite linear;
12
- -o-animation: spin 1s infinite linear;
13
- animation: spin 1s infinite linear;
14
- -webkit-transform-origin: 50% 50%;
15
- transform-origin: 50% 50%;
16
- -ms-transform-origin: 50% 50%; /* IE 9 */
17
- }
18
-
19
- @-moz-keyframes spin {
20
- from {
21
- -moz-transform: rotate(0deg);
22
- }
23
- to {
24
- -moz-transform: rotate(360deg);
25
- }
26
- }
27
-
28
- @-webkit-keyframes spin {
29
- from {
30
- -webkit-transform: rotate(0deg);
31
- }
32
- to {
33
- -webkit-transform: rotate(360deg);
34
- }
35
- }
36
-
37
- @keyframes spin {
38
- from {
39
- transform: rotate(0deg);
40
- }
41
- to {
42
- transform: rotate(360deg);
43
- }
44
- }
45
- .dynflow-button > span {
46
- pointer-events: auto;
47
- }
48
9
 
49
10
  pre {
50
11
  white-space: pre-wrap;
@@ -39,11 +39,6 @@ export const selectResumable = state =>
39
39
  export const selectCancellable = state =>
40
40
  selectTaskDetailsResponse(state).cancellable || false;
41
41
 
42
- export const selectErrors = state => {
43
- const { humanized } = selectTaskDetailsResponse(state);
44
- return humanized ? humanized.errors : [];
45
- };
46
-
47
42
  export const selectProgress = state =>
48
43
  selectTaskDetailsResponse(state).progress
49
44
  ? Math.trunc(selectTaskDetailsResponse(state).progress * 100)
@@ -0,0 +1,194 @@
1
+ import React from 'react';
2
+ import { render, screen } from '@testing-library/react';
3
+ import '@testing-library/jest-dom';
4
+
5
+ import ExecutionDetails from '../ExecutionDetails';
6
+ import {
7
+ fixtureFailedExecutionDetail,
8
+ fixtureRunningExecutionDetail,
9
+ } from './TaskDetails.fixtures';
10
+
11
+ const rtlBaseProps = {
12
+ cancelStep: jest.fn(),
13
+ taskReloadStart: jest.fn(),
14
+ id: 'a15dd820-32f1-4ced-9ab7-c0fab8234c47',
15
+ taskReload: false,
16
+ };
17
+
18
+ describe('ExecutionDetails', () => {
19
+ it('renders execution details panel with OUIA id', () => {
20
+ render(
21
+ <ExecutionDetails
22
+ {...rtlBaseProps}
23
+ state="stopped"
24
+ runningSteps={[]}
25
+ executionPlan={{ state: 'stopped', cancellable: false }}
26
+ failedSteps={[]}
27
+ />
28
+ );
29
+
30
+ expect(
31
+ document.querySelector('[data-ouia-component-id="execution-details-panel"]')
32
+ ).toBeInTheDocument();
33
+ expect(document.getElementById('execution-details-panel')).toBeInTheDocument();
34
+ });
35
+
36
+ it('shows Errors pane when stopped with no running steps', () => {
37
+ render(
38
+ <ExecutionDetails
39
+ {...rtlBaseProps}
40
+ state="stopped"
41
+ runningSteps={[]}
42
+ executionPlan={{ state: 'stopped', cancellable: false }}
43
+ failedSteps={[]}
44
+ />
45
+ );
46
+
47
+ expect(screen.getByRole('heading', { name: /^no errors found$/i })).toBeInTheDocument();
48
+ expect(
49
+ screen.getByText(/the task finished with no errors or warnings/i)
50
+ ).toBeInTheDocument();
51
+ });
52
+
53
+ it('shows RunningSteps when stopped but runningSteps list is non-empty', () => {
54
+ render(
55
+ <ExecutionDetails
56
+ {...rtlBaseProps}
57
+ state="stopped"
58
+ runningSteps={[
59
+ {
60
+ cancellable: false,
61
+ id: 1,
62
+ action_class: 'Actions::Stale',
63
+ state: 'paused',
64
+ input: '{}',
65
+ output: '{}',
66
+ },
67
+ ]}
68
+ executionPlan={{ state: 'stopped', cancellable: false }}
69
+ failedSteps={[]}
70
+ />
71
+ );
72
+
73
+ expect(
74
+ screen.getByRole('heading', { name: 'Warning alert: Running step 1' })
75
+ ).toBeInTheDocument();
76
+ });
77
+
78
+ it('forwards executionPlan and result to RunningSteps when state is pending without steps', () => {
79
+ render(
80
+ <ExecutionDetails
81
+ {...rtlBaseProps}
82
+ state="pending"
83
+ runningSteps={[]}
84
+ executionPlan={{ state: 'planned', cancellable: false }}
85
+ result="pending"
86
+ failedSteps={[]}
87
+ />
88
+ );
89
+
90
+ expect(
91
+ screen.getByRole('heading', { level: 2, name: /planned task/i })
92
+ ).toBeInTheDocument();
93
+ });
94
+
95
+ it('shows temporarily suspended messaging when pending, plan running, result pending', () => {
96
+ render(
97
+ <ExecutionDetails
98
+ {...rtlBaseProps}
99
+ state="pending"
100
+ runningSteps={[]}
101
+ executionPlan={{ state: 'running', cancellable: false }}
102
+ result="pending"
103
+ failedSteps={[]}
104
+ />
105
+ );
106
+
107
+ expect(
108
+ screen.getByRole('heading', {
109
+ level: 4,
110
+ name: /temporarily suspended step/i,
111
+ })
112
+ ).toBeInTheDocument();
113
+ });
114
+
115
+ it('routes failed steps through Errors pane when stopped', () => {
116
+ render(
117
+ <ExecutionDetails
118
+ {...rtlBaseProps}
119
+ {...fixtureFailedExecutionDetail}
120
+ executionPlan={fixtureFailedExecutionDetail.executionPlan}
121
+ failedSteps={fixtureFailedExecutionDetail.failedSteps}
122
+ />
123
+ );
124
+
125
+ expect(
126
+ screen.getByRole('tab', {
127
+ name: /action actions::katello::eventqueue::monitor is already active/i,
128
+ })
129
+ ).toBeInTheDocument();
130
+ expect(
131
+ screen.getByLabelText(/failed task errors/i)
132
+ ).toBeInTheDocument();
133
+ expect(screen.getByText('Exception:')).toBeInTheDocument();
134
+ });
135
+
136
+ it('renders RunningSteps with cancel when task is running', () => {
137
+ const cancelStep = jest.fn();
138
+
139
+ render(
140
+ <ExecutionDetails
141
+ {...rtlBaseProps}
142
+ cancelStep={cancelStep}
143
+ {...fixtureRunningExecutionDetail}
144
+ runningSteps={[
145
+ {
146
+ ...fixtureRunningExecutionDetail.runningSteps[0],
147
+ cancellable: true,
148
+ },
149
+ ]}
150
+ />
151
+ );
152
+
153
+ expect(screen.getByRole('button', { name: /cancel/i })).toBeInTheDocument();
154
+ });
155
+
156
+ it('shows RunningSteps when state is paused without running steps', () => {
157
+ render(
158
+ <ExecutionDetails
159
+ {...rtlBaseProps}
160
+ state="paused"
161
+ runningSteps={[]}
162
+ executionPlan={{ state: 'paused', cancellable: false }}
163
+ failedSteps={[]}
164
+ />
165
+ );
166
+
167
+ expect(screen.getByText(/no running steps/i)).toBeInTheDocument();
168
+ expect(
169
+ screen.queryByRole('heading', { name: /^no errors found$/i })
170
+ ).not.toBeInTheDocument();
171
+ });
172
+
173
+ it('shows RunningSteps when state is paused with running steps', () => {
174
+ render(
175
+ <ExecutionDetails
176
+ {...rtlBaseProps}
177
+ state="paused"
178
+ runningSteps={[
179
+ {
180
+ ...fixtureRunningExecutionDetail.runningSteps[0],
181
+ state: 'paused',
182
+ },
183
+ ]}
184
+ executionPlan={{ state: 'paused', cancellable: false }}
185
+ failedSteps={[]}
186
+ />
187
+ );
188
+
189
+ expect(
190
+ screen.getByRole('heading', { name: 'Warning alert: Running step 1' })
191
+ ).toBeInTheDocument();
192
+ expect(screen.getByText('paused')).toBeInTheDocument();
193
+ });
194
+ });
@@ -1,4 +1,5 @@
1
1
  export const minProps = {
2
+ id: 'a15dd820-32f1-4ced-9ab7-c0fab8234c47',
2
3
  cancelStep: jest.fn(),
3
4
  taskReload: false,
4
5
  taskReloadStop: jest.fn(),
@@ -6,3 +7,101 @@ export const minProps = {
6
7
  taskProgressToggle: jest.fn(),
7
8
  apiStatus: 'RESOLVED',
8
9
  };
10
+
11
+ /** Props for snapshots that exercise the Execution details tab alongside the overview. */
12
+ export const taskDetailsWithExecutionTabDefaults = {
13
+ ...minProps,
14
+ locks: [
15
+ {
16
+ exclusive: false,
17
+ resource_type: 'User',
18
+ resource_id: 4,
19
+ link: null,
20
+ },
21
+ ],
22
+ links: [],
23
+ executionPlan: { state: 'stopped', cancellable: false },
24
+ failedSteps: [],
25
+ runningSteps: [],
26
+ dependsOn: [],
27
+ blocks: [],
28
+ action: 'Refresh foo',
29
+ state: 'stopped',
30
+ result: 'success',
31
+ progress: 100,
32
+ startAt: '',
33
+ startedAt: '',
34
+ endedAt: '',
35
+ startBefore: '',
36
+ };
37
+
38
+ const SAMPLE_FAILED_STEP = {
39
+ error: {
40
+ exception_class: 'RuntimeError',
41
+ message:
42
+ 'Action Actions::Katello::EventQueue::Monitor is already active',
43
+ backtrace: [
44
+ "/home/example/gems/dynflow-1.2.3/lib/dynflow/action/singleton.rb:15:in `rescue in singleton_lock!'",
45
+ ],
46
+ },
47
+ action_class: 'Actions::Katello::EventQueue::Monitor',
48
+ state: 'error',
49
+ input:
50
+ '{"locale"=>"en",\n "current_request_id"=>nil,\n "current_user_id"=>4}\n',
51
+ output: '{}\n',
52
+ };
53
+
54
+ const SAMPLE_RUNNING_STEP = {
55
+ cancellable: false,
56
+ id: 1,
57
+ action_class: 'Actions::DynflowExample',
58
+ state: 'running',
59
+ input: '{}',
60
+ output: '{}',
61
+ };
62
+
63
+ const SAMPLE_DEPENDS_ON = [
64
+ {
65
+ id: '123',
66
+ action: 'Actions::FooBar',
67
+ humanized: 'Foo Bar Action',
68
+ state: 'stopped',
69
+ result: 'success',
70
+ },
71
+ ];
72
+
73
+ export const fixtureFailedExecutionDetail = {
74
+ ...taskDetailsWithExecutionTabDefaults,
75
+ result: 'error',
76
+ state: 'stopped',
77
+ failedSteps: [SAMPLE_FAILED_STEP],
78
+ };
79
+
80
+ export const fixtureRunningExecutionDetail = {
81
+ ...taskDetailsWithExecutionTabDefaults,
82
+ state: 'running',
83
+ runningSteps: [SAMPLE_RUNNING_STEP],
84
+ };
85
+
86
+ export const fixtureWithOverviewMessages = {
87
+ ...taskDetailsWithExecutionTabDefaults,
88
+ help: '<strong>See logs</strong> for more.',
89
+ output: {
90
+ messages: ['partial output'],
91
+ result: 'error',
92
+ },
93
+ };
94
+
95
+ export const fixtureWithDependencies = {
96
+ ...taskDetailsWithExecutionTabDefaults,
97
+ dependsOn: SAMPLE_DEPENDS_ON,
98
+ blocks: [
99
+ {
100
+ id: '789',
101
+ action: 'Actions::Test',
102
+ humanized: 'Test Action',
103
+ state: 'paused',
104
+ result: 'warning',
105
+ },
106
+ ],
107
+ };