foreman-tasks 11.0.6 → 11.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/lib/foreman_tasks/version.rb +1 -1
- data/webpack/ForemanTasks/Components/TaskDetails/Components/Task.js +38 -15
- data/webpack/ForemanTasks/Components/TaskDetails/Components/TaskButtons.js +59 -36
- data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/TaskButtons.test.js +196 -71
- data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/__snapshots__/Task.test.js.snap +102 -140
- data/webpack/ForemanTasks/Components/TaskDetails/__tests__/__snapshots__/TaskDetails.test.js.snap +2 -16
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/OtherInfo.js +5 -3
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/OtherInfo.test.js +58 -9
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/StoppedTasksCard.scss +0 -30
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/StoppedTasksCard.test.js +190 -9
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/StoppedTasksCardTable.js +70 -35
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksLabelsRow/TasksLabelsRow.js +9 -14
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksLabelsRow/TasksLabelsRow.scss +3 -23
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksLabelsRow/TasksLabelsRow.test.js +33 -26
- data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/ConfirmModalSelectors.js +0 -16
- data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/GenericConfirmModal.js +70 -0
- data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/ConfirmModalSelectors.test.js +25 -14
- data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/__snapshots__/ConfirmModalSelectors.test.js.snap +8 -7
- data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/index.test.js +409 -0
- data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/createBulkTaskModal.js +67 -0
- data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/createTaskModal.js +51 -0
- data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/index.js +73 -23
- data/webpack/ForemanTasks/Components/TasksTable/TasksTable.js +5 -2
- data/webpack/ForemanTasks/Components/TasksTable/TasksTableConstants.js +1 -1
- data/webpack/ForemanTasks/Components/TasksTable/TasksTablePage.js +67 -11
- data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksTablePage.test.js.snap +86 -6
- data/webpack/ForemanTasks/Components/common/ClickConfirmation/ClickConfirmation.test.js +225 -39
- data/webpack/ForemanTasks/Components/common/ClickConfirmation/index.js +136 -37
- metadata +6 -24
- data/webpack/ForemanTasks/Components/TaskActions/UnlockModals.js +0 -60
- data/webpack/ForemanTasks/Components/TaskActions/UnlockModals.test.js +0 -14
- data/webpack/ForemanTasks/Components/TaskActions/__snapshots__/UnlockModals.test.js.snap +0 -25
- data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/__snapshots__/TaskButtons.test.js.snap +0 -212
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/StoppedTasksCardTable.test.js +0 -54
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/__snapshots__/OtherInfo.test.js.snap +0 -30
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/__snapshots__/StoppedTasksCard.test.js.snap +0 -107
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/__snapshots__/StoppedTasksCardTable.test.js.snap +0 -960
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksLabelsRow/__snapshots__/TasksLabelsRow.test.js.snap +0 -47
- data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/ConfirmModal.js +0 -83
- data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/ConfirmModalActions.js +0 -106
- data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/ConfirmModalReducer.js +0 -38
- data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/ConfirmModal.test.js +0 -36
- data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/ConfirmModalActions.test.js +0 -205
- data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/ConfirmModalReducer.test.js +0 -27
- data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/__snapshots__/ConfirmModal.test.js.snap +0 -41
- data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/__snapshots__/ConfirmModalReducer.test.js.snap +0 -19
- data/webpack/ForemanTasks/Components/common/ClickConfirmation/ClickConfirmation.scss +0 -9
- data/webpack/ForemanTasks/Components/common/ClickConfirmation/__snapshots__/ClickConfirmation.test.js.snap +0 -52
- data/webpack/__mocks__/foremanReact/components/ForemanModal/ForemanModalActions.js +0 -2
- data/webpack/__mocks__/foremanReact/components/ForemanModal/ForemanModalHooks.js +0 -10
- data/webpack/__mocks__/foremanReact/components/ForemanModal/index.js +0 -18
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6323c04ba353b2c7db536b30690adf3e03648858e9883ba31276a217acedaaa5
|
|
4
|
+
data.tar.gz: 521d94f6dfc0d3fba10057376aeafa6b71dc5605b19dd9ed07d08e7505b982c2
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ef93f73cb3325aa63c06b392ec9abb20825d27a71388667a29eddc242365407d3be292cabcba7bb6340329140f14d28eee4bb2c66219cf109e11f8f5af0c7a2a
|
|
7
|
+
data.tar.gz: 4a30e8776e8938bc75f1a3b88093d7d6707324abd41942c0e9e92efc39c2c85da6d322e7424b71b389f2c4e617fd4d4bdfa1aea587aa4bc72d918bf9c0a02148
|
|
@@ -1,7 +1,10 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
3
|
import TaskInfo from './TaskInfo';
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
ForceUnlockConfirmationModal,
|
|
6
|
+
UnlockConfirmationModal,
|
|
7
|
+
} from '../../common/ClickConfirmation';
|
|
5
8
|
import { TaskButtons } from './TaskButtons';
|
|
6
9
|
|
|
7
10
|
const Task = props => {
|
|
@@ -25,28 +28,48 @@ const Task = props => {
|
|
|
25
28
|
}
|
|
26
29
|
unlockTaskRequest(id, action);
|
|
27
30
|
};
|
|
31
|
+
const [unlockModalOpen, setUnlockModalOpen] = useState(false);
|
|
32
|
+
const [forceUnlockModalOpen, setForceUnlockModalOpen] = useState(false);
|
|
33
|
+
|
|
28
34
|
return (
|
|
29
35
|
<React.Fragment>
|
|
30
|
-
<
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
36
|
+
<UnlockConfirmationModal
|
|
37
|
+
onClick={unlock}
|
|
38
|
+
isOpen={unlockModalOpen}
|
|
39
|
+
setModalClosed={() => setUnlockModalOpen(false)}
|
|
40
|
+
/>
|
|
41
|
+
<ForceUnlockConfirmationModal
|
|
42
|
+
onClick={forceUnlock}
|
|
43
|
+
isOpen={forceUnlockModalOpen}
|
|
44
|
+
setModalClosed={() => setForceUnlockModalOpen(false)}
|
|
45
|
+
/>
|
|
46
|
+
<TaskButtons
|
|
47
|
+
taskReloadStart={taskReloadStart}
|
|
48
|
+
setUnlockModalOpen={setUnlockModalOpen}
|
|
49
|
+
setForceUnlockModalOpen={setForceUnlockModalOpen}
|
|
50
|
+
{...props}
|
|
51
|
+
/>
|
|
52
|
+
<TaskInfo {...props} />
|
|
38
53
|
</React.Fragment>
|
|
39
54
|
);
|
|
40
55
|
};
|
|
41
56
|
|
|
42
57
|
Task.propTypes = {
|
|
43
|
-
|
|
44
|
-
|
|
58
|
+
taskReload: PropTypes.bool,
|
|
59
|
+
id: PropTypes.string,
|
|
60
|
+
forceCancelTaskRequest: PropTypes.func,
|
|
61
|
+
unlockTaskRequest: PropTypes.func,
|
|
62
|
+
action: PropTypes.string,
|
|
63
|
+
taskReloadStart: PropTypes.func,
|
|
45
64
|
};
|
|
46
65
|
|
|
47
66
|
Task.defaultProps = {
|
|
48
|
-
|
|
49
|
-
|
|
67
|
+
taskReload: false,
|
|
68
|
+
id: '',
|
|
69
|
+
forceCancelTaskRequest: () => null,
|
|
70
|
+
unlockTaskRequest: () => null,
|
|
71
|
+
action: '',
|
|
72
|
+
taskReloadStart: () => null,
|
|
50
73
|
};
|
|
51
74
|
|
|
52
75
|
export default Task;
|
|
@@ -1,12 +1,8 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { Button, Icon } from '@patternfly/react-core';
|
|
4
|
+
import { SyncAltIcon } from '@patternfly/react-icons';
|
|
5
5
|
import { translate as __ } from 'foremanReact/common/I18n';
|
|
6
|
-
import {
|
|
7
|
-
UNLOCK_MODAL,
|
|
8
|
-
FORCE_UNLOCK_MODAL,
|
|
9
|
-
} from '../../TaskActions/TaskActionsConstants';
|
|
10
6
|
|
|
11
7
|
export const TaskButtons = ({
|
|
12
8
|
canEdit,
|
|
@@ -24,13 +20,9 @@ export const TaskButtons = ({
|
|
|
24
20
|
parentTask,
|
|
25
21
|
cancelTaskRequest,
|
|
26
22
|
resumeTaskRequest,
|
|
23
|
+
setUnlockModalOpen,
|
|
24
|
+
setForceUnlockModalOpen,
|
|
27
25
|
}) => {
|
|
28
|
-
const unlockModalActions = useForemanModal({
|
|
29
|
-
id: UNLOCK_MODAL,
|
|
30
|
-
});
|
|
31
|
-
const forceUnlockModalActions = useForemanModal({
|
|
32
|
-
id: FORCE_UNLOCK_MODAL,
|
|
33
|
-
});
|
|
34
26
|
const editActionsTitle = canEdit
|
|
35
27
|
? undefined
|
|
36
28
|
: __('You do not have permission');
|
|
@@ -39,35 +31,42 @@ export const TaskButtons = ({
|
|
|
39
31
|
: `dynflow_enable_console ${__('Setting is off')}`;
|
|
40
32
|
|
|
41
33
|
return (
|
|
42
|
-
|
|
34
|
+
<>
|
|
43
35
|
<Button
|
|
36
|
+
variant="secondary"
|
|
37
|
+
ouiaId="task-buttons-reload-button"
|
|
44
38
|
className="reload-button"
|
|
45
|
-
|
|
39
|
+
size="sm"
|
|
46
40
|
onClick={taskProgressToggle}
|
|
47
41
|
>
|
|
48
|
-
<
|
|
49
|
-
|
|
50
|
-
|
|
42
|
+
<Icon className={taskReload ? 'spin' : ''}>
|
|
43
|
+
<SyncAltIcon />
|
|
44
|
+
</Icon>
|
|
51
45
|
{taskReload ? __('Stop auto-reloading') : __('Start auto-reloading')}
|
|
52
46
|
</Button>
|
|
53
47
|
<Button
|
|
48
|
+
variant="secondary"
|
|
49
|
+
ouiaId="task-buttons-dynflow-button"
|
|
54
50
|
className="dynflow-button"
|
|
55
|
-
|
|
51
|
+
size="sm"
|
|
52
|
+
component="a"
|
|
56
53
|
href={`/foreman_tasks/dynflow/${externalId}`}
|
|
57
|
-
|
|
58
|
-
rel="noopener noreferrer"
|
|
54
|
+
isDisabled={!dynflowEnableConsole}
|
|
59
55
|
target="_blank"
|
|
56
|
+
rel="noopener noreferrer"
|
|
60
57
|
>
|
|
61
58
|
<span title={dynflowTitle} data-original-title={dynflowTitle}>
|
|
62
59
|
{__('Dynflow console')}
|
|
63
60
|
</span>
|
|
64
61
|
</Button>
|
|
65
62
|
<Button
|
|
63
|
+
variant="secondary"
|
|
64
|
+
ouiaId="task-buttons-resume-button"
|
|
66
65
|
className="resume-button"
|
|
67
|
-
|
|
66
|
+
size="sm"
|
|
68
67
|
title={editActionsTitle}
|
|
69
68
|
data-original-title={editActionsTitle}
|
|
70
|
-
|
|
69
|
+
isDisabled={!canEdit || !resumable}
|
|
71
70
|
onClick={() => {
|
|
72
71
|
if (!taskReload) {
|
|
73
72
|
taskReloadStart(id);
|
|
@@ -78,11 +77,13 @@ export const TaskButtons = ({
|
|
|
78
77
|
{__('Resume')}
|
|
79
78
|
</Button>
|
|
80
79
|
<Button
|
|
80
|
+
variant="secondary"
|
|
81
|
+
ouiaId="task-buttons-cancel-button"
|
|
81
82
|
className="cancel-button"
|
|
82
|
-
|
|
83
|
+
size="sm"
|
|
83
84
|
title={editActionsTitle}
|
|
84
85
|
data-original-title={editActionsTitle}
|
|
85
|
-
|
|
86
|
+
isDisabled={!canEdit || !cancellable}
|
|
86
87
|
onClick={() => {
|
|
87
88
|
if (!taskReload) {
|
|
88
89
|
taskReloadStart(id);
|
|
@@ -94,47 +95,59 @@ export const TaskButtons = ({
|
|
|
94
95
|
</Button>
|
|
95
96
|
{parentTask && (
|
|
96
97
|
<Button
|
|
98
|
+
variant="secondary"
|
|
99
|
+
ouiaId="task-buttons-parent-button"
|
|
97
100
|
className="parent-button"
|
|
98
|
-
|
|
101
|
+
size="sm"
|
|
99
102
|
href={`/foreman_tasks/tasks/${parentTask}`}
|
|
103
|
+
component="a"
|
|
100
104
|
>
|
|
101
105
|
{__('Parent task')}
|
|
102
106
|
</Button>
|
|
103
107
|
)}
|
|
104
108
|
{hasSubTasks && (
|
|
105
109
|
<Button
|
|
110
|
+
variant="secondary"
|
|
111
|
+
ouiaId="task-buttons-subtask-button"
|
|
106
112
|
className="subtask-button"
|
|
107
|
-
|
|
113
|
+
size="sm"
|
|
108
114
|
href={`/foreman_tasks/tasks/${id}/sub_tasks`}
|
|
115
|
+
component="a"
|
|
109
116
|
>
|
|
110
117
|
{__('Sub tasks')}
|
|
111
118
|
</Button>
|
|
112
119
|
)}
|
|
113
120
|
<Button
|
|
121
|
+
variant="secondary"
|
|
122
|
+
ouiaId="task-buttons-unlock-button"
|
|
114
123
|
className="unlock-button"
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
onClick={
|
|
124
|
+
size="sm"
|
|
125
|
+
isDisabled={!canEdit || state !== 'paused'}
|
|
126
|
+
onClick={() => {
|
|
127
|
+
setUnlockModalOpen(true);
|
|
128
|
+
}}
|
|
118
129
|
title={editActionsTitle}
|
|
119
130
|
data-original-title={editActionsTitle}
|
|
120
131
|
>
|
|
121
132
|
{__('Unlock')}
|
|
122
133
|
</Button>
|
|
123
134
|
<Button
|
|
135
|
+
variant="secondary"
|
|
136
|
+
ouiaId="task-buttons-force-unlock-button"
|
|
124
137
|
className="force-unlock-button"
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
onClick={
|
|
138
|
+
size="sm"
|
|
139
|
+
isDisabled={!canEdit || state === 'stopped'}
|
|
140
|
+
onClick={() => setForceUnlockModalOpen(true)}
|
|
128
141
|
title={editActionsTitle}
|
|
129
142
|
data-original-title={editActionsTitle}
|
|
130
143
|
>
|
|
131
144
|
{__('Force Unlock')}
|
|
132
145
|
</Button>
|
|
133
|
-
|
|
146
|
+
</>
|
|
134
147
|
);
|
|
135
148
|
};
|
|
136
149
|
|
|
137
|
-
|
|
150
|
+
export const TaskButtonspropTypes = {
|
|
138
151
|
canEdit: PropTypes.bool,
|
|
139
152
|
dynflowEnableConsole: PropTypes.bool,
|
|
140
153
|
taskReloadStart: PropTypes.func.isRequired,
|
|
@@ -151,8 +164,7 @@ TaskButtons.propTypes = {
|
|
|
151
164
|
cancelTaskRequest: PropTypes.func,
|
|
152
165
|
resumeTaskRequest: PropTypes.func,
|
|
153
166
|
};
|
|
154
|
-
|
|
155
|
-
TaskButtons.defaultProps = {
|
|
167
|
+
export const TaskButtonsdefaultProps = {
|
|
156
168
|
canEdit: false,
|
|
157
169
|
dynflowEnableConsole: false,
|
|
158
170
|
taskReload: false,
|
|
@@ -166,3 +178,14 @@ TaskButtons.defaultProps = {
|
|
|
166
178
|
cancelTaskRequest: () => null,
|
|
167
179
|
resumeTaskRequest: () => null,
|
|
168
180
|
};
|
|
181
|
+
|
|
182
|
+
TaskButtons.propTypes = {
|
|
183
|
+
...TaskButtonspropTypes,
|
|
184
|
+
setUnlockModalOpen: PropTypes.func,
|
|
185
|
+
setForceUnlockModalOpen: PropTypes.func,
|
|
186
|
+
};
|
|
187
|
+
TaskButtons.defaultProps = {
|
|
188
|
+
setUnlockModalOpen: () => null,
|
|
189
|
+
setForceUnlockModalOpen: () => null,
|
|
190
|
+
...TaskButtonsdefaultProps,
|
|
191
|
+
};
|
|
@@ -1,45 +1,159 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
mount,
|
|
5
|
-
shallow,
|
|
6
|
-
} from '@theforeman/test';
|
|
7
|
-
import { useForemanModal } from 'foremanReact/components/ForemanModal/ForemanModalHooks';
|
|
2
|
+
import { render, screen, fireEvent } from '@testing-library/react';
|
|
3
|
+
import '@testing-library/jest-dom';
|
|
8
4
|
import { STATUS } from 'foremanReact/constants';
|
|
9
5
|
import { TaskButtons } from '../TaskButtons';
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
id: 'test',
|
|
23
|
-
state: 'paused',
|
|
24
|
-
hasSubTasks: true,
|
|
25
|
-
dynflowEnableConsole: true,
|
|
26
|
-
parentTask: 'parent-id',
|
|
27
|
-
taskReload: true,
|
|
28
|
-
canEdit: true,
|
|
29
|
-
status: STATUS.RESOLVED,
|
|
30
|
-
taskReloadStart: jest.fn(),
|
|
31
|
-
taskProgressToggle: jest.fn(),
|
|
32
|
-
},
|
|
6
|
+
|
|
7
|
+
const setUnlockModalOpen = jest.fn();
|
|
8
|
+
const setForceUnlockModalOpen = jest.fn();
|
|
9
|
+
|
|
10
|
+
const defaultProps = {
|
|
11
|
+
id: 'test',
|
|
12
|
+
taskReloadStart: jest.fn(),
|
|
13
|
+
taskProgressToggle: jest.fn(),
|
|
14
|
+
cancelTaskRequest: jest.fn(),
|
|
15
|
+
resumeTaskRequest: jest.fn(),
|
|
16
|
+
setUnlockModalOpen,
|
|
17
|
+
setForceUnlockModalOpen,
|
|
33
18
|
};
|
|
34
19
|
|
|
35
|
-
describe('
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
20
|
+
describe('TaskButtons', () => {
|
|
21
|
+
beforeEach(() => {
|
|
22
|
+
jest.clearAllMocks();
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
describe('rendering', () => {
|
|
26
|
+
it('renders reload button with correct text when taskReload is false', () => {
|
|
27
|
+
render(<TaskButtons {...defaultProps} taskReload={false} />);
|
|
28
|
+
expect(
|
|
29
|
+
screen.getByRole('button', { name: /start auto-reloading/i })
|
|
30
|
+
).toBeInTheDocument();
|
|
31
|
+
expect(
|
|
32
|
+
screen.queryByRole('button', { name: /stop auto-reloading/i })
|
|
33
|
+
).not.toBeInTheDocument();
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it('renders reload button with correct text when taskReload is true', () => {
|
|
37
|
+
render(<TaskButtons {...defaultProps} taskReload />);
|
|
38
|
+
expect(
|
|
39
|
+
screen.getByRole('button', { name: /stop auto-reloading/i })
|
|
40
|
+
).toBeInTheDocument();
|
|
41
|
+
expect(
|
|
42
|
+
screen.queryByRole('button', { name: /start auto-reloading/i })
|
|
43
|
+
).not.toBeInTheDocument();
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it('renders dynflow console link with correct href when externalId is provided', () => {
|
|
47
|
+
render(<TaskButtons {...defaultProps} externalId="external-123" />);
|
|
48
|
+
const dynflowLink = screen.getByRole('link', {
|
|
49
|
+
name: /dynflow console/i,
|
|
50
|
+
});
|
|
51
|
+
expect(dynflowLink).toHaveAttribute(
|
|
52
|
+
'href',
|
|
53
|
+
'/foreman_tasks/dynflow/external-123'
|
|
54
|
+
);
|
|
55
|
+
expect(dynflowLink).toHaveAttribute('target', '_blank');
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it('disables dynflow console link when dynflowEnableConsole is false', () => {
|
|
59
|
+
render(<TaskButtons {...defaultProps} dynflowEnableConsole={false} />);
|
|
60
|
+
const dynflowLink = screen.getByRole('link', {
|
|
61
|
+
name: /dynflow console/i,
|
|
62
|
+
});
|
|
63
|
+
expect(dynflowLink).not.toBeDisabled();
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it('enables dynflow console link when dynflowEnableConsole is true', () => {
|
|
67
|
+
render(
|
|
68
|
+
<TaskButtons
|
|
69
|
+
{...defaultProps}
|
|
70
|
+
dynflowEnableConsole
|
|
71
|
+
externalId="external-123"
|
|
72
|
+
/>
|
|
73
|
+
);
|
|
74
|
+
const dynflowLink = screen.getByRole('link', {
|
|
75
|
+
name: /dynflow console/i,
|
|
76
|
+
});
|
|
77
|
+
expect(dynflowLink).not.toBeDisabled();
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it('disables resume and cancel buttons when canEdit is false', () => {
|
|
81
|
+
render(<TaskButtons {...defaultProps} canEdit={false} />);
|
|
82
|
+
expect(screen.getByRole('button', { name: /resume/i })).toBeDisabled();
|
|
83
|
+
expect(screen.getByRole('button', { name: /cancel/i })).toBeDisabled();
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it('disables resume button when resumable is false', () => {
|
|
87
|
+
render(<TaskButtons {...defaultProps} canEdit resumable={false} />);
|
|
88
|
+
expect(screen.getByRole('button', { name: /resume/i })).toBeDisabled();
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it('disables cancel button when cancellable is false', () => {
|
|
92
|
+
render(<TaskButtons {...defaultProps} canEdit cancellable={false} />);
|
|
93
|
+
expect(screen.getByRole('button', { name: /cancel/i })).toBeDisabled();
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
it('disables unlock button when state is not paused', () => {
|
|
97
|
+
render(<TaskButtons {...defaultProps} canEdit state="running" />);
|
|
98
|
+
expect(screen.getByRole('button', { name: /^unlock$/i })).toBeDisabled();
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
it('enables unlock button when state is paused and canEdit is true', () => {
|
|
102
|
+
render(<TaskButtons {...defaultProps} canEdit state="paused" />);
|
|
103
|
+
expect(
|
|
104
|
+
screen.getByRole('button', { name: /^unlock$/i })
|
|
105
|
+
).not.toBeDisabled();
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
it('disables force unlock button when state is stopped', () => {
|
|
109
|
+
render(<TaskButtons {...defaultProps} canEdit state="stopped" />);
|
|
110
|
+
expect(
|
|
111
|
+
screen.getByRole('button', { name: /force unlock/i })
|
|
112
|
+
).toBeDisabled();
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
it('enables force unlock button when state is not stopped and canEdit is true', () => {
|
|
116
|
+
render(<TaskButtons {...defaultProps} canEdit state="running" />);
|
|
117
|
+
expect(
|
|
118
|
+
screen.getByRole('button', { name: /force unlock/i })
|
|
119
|
+
).not.toBeDisabled();
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
it('renders parent task button when parentTask is provided', () => {
|
|
123
|
+
render(<TaskButtons {...defaultProps} parentTask="parent-123" />);
|
|
124
|
+
const parentButton = screen.getByRole('link', { name: /parent task/i });
|
|
125
|
+
expect(parentButton).toBeInTheDocument();
|
|
126
|
+
expect(parentButton).toHaveAttribute(
|
|
127
|
+
'href',
|
|
128
|
+
'/foreman_tasks/tasks/parent-123'
|
|
129
|
+
);
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it('does not render parent task button when parentTask is not provided', () => {
|
|
133
|
+
render(<TaskButtons {...defaultProps} />);
|
|
134
|
+
expect(
|
|
135
|
+
screen.queryByRole('link', { name: /parent task/i })
|
|
136
|
+
).not.toBeInTheDocument();
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
it('renders sub tasks button when hasSubTasks is true', () => {
|
|
140
|
+
render(<TaskButtons {...defaultProps} hasSubTasks id="task-123" />);
|
|
141
|
+
const subTasksButton = screen.getByRole('link', { name: /sub tasks/i });
|
|
142
|
+
expect(subTasksButton).toBeInTheDocument();
|
|
143
|
+
expect(subTasksButton).toHaveAttribute(
|
|
144
|
+
'href',
|
|
145
|
+
'/foreman_tasks/tasks/task-123/sub_tasks'
|
|
146
|
+
);
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
it('does not render sub tasks button when hasSubTasks is false', () => {
|
|
150
|
+
render(<TaskButtons {...defaultProps} hasSubTasks={false} />);
|
|
151
|
+
expect(
|
|
152
|
+
screen.queryByRole('link', { name: /sub tasks/i })
|
|
153
|
+
).not.toBeInTheDocument();
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
describe('user interactions', () => {
|
|
43
157
|
const cancelTaskRequest = jest.fn();
|
|
44
158
|
const resumeTaskRequest = jest.fn();
|
|
45
159
|
const taskProgressToggle = jest.fn();
|
|
@@ -47,6 +161,7 @@ describe('Task', () => {
|
|
|
47
161
|
const id = 'some-id';
|
|
48
162
|
const action = 'some-action';
|
|
49
163
|
const props = {
|
|
164
|
+
...defaultProps,
|
|
50
165
|
taskReload: false,
|
|
51
166
|
id,
|
|
52
167
|
action,
|
|
@@ -55,41 +170,51 @@ describe('Task', () => {
|
|
|
55
170
|
taskProgressToggle,
|
|
56
171
|
taskReloadStart,
|
|
57
172
|
status: STATUS.RESOLVED,
|
|
173
|
+
canEdit: true,
|
|
174
|
+
resumable: true,
|
|
175
|
+
cancellable: true,
|
|
176
|
+
state: 'paused',
|
|
58
177
|
};
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
expect(taskProgressToggle).
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
resumeButton.
|
|
72
|
-
|
|
73
|
-
expect(
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
178
|
+
|
|
179
|
+
it('calls taskProgressToggle when reload button is clicked', () => {
|
|
180
|
+
render(<TaskButtons {...props} />);
|
|
181
|
+
const reloadButton = screen.getByRole('button', {
|
|
182
|
+
name: /start auto-reloading/i,
|
|
183
|
+
});
|
|
184
|
+
fireEvent.click(reloadButton);
|
|
185
|
+
expect(taskProgressToggle).toHaveBeenCalled();
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
it('calls taskReloadStart and resumeTaskRequest when resume button is clicked', () => {
|
|
189
|
+
render(<TaskButtons {...props} />);
|
|
190
|
+
const resumeButton = screen.getByRole('button', { name: /resume/i });
|
|
191
|
+
fireEvent.click(resumeButton);
|
|
192
|
+
expect(taskReloadStart).toHaveBeenCalledWith(id);
|
|
193
|
+
expect(resumeTaskRequest).toHaveBeenCalledWith(id, action);
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
it('calls taskReloadStart and cancelTaskRequest when cancel button is clicked', () => {
|
|
197
|
+
render(<TaskButtons {...props} />);
|
|
198
|
+
const cancelButton = screen.getByRole('button', { name: /cancel/i });
|
|
199
|
+
fireEvent.click(cancelButton);
|
|
200
|
+
expect(taskReloadStart).toHaveBeenCalledWith(id);
|
|
201
|
+
expect(cancelTaskRequest).toHaveBeenCalledWith(id, action);
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
it('calls setUnlockModalOpen when unlock button is clicked', () => {
|
|
205
|
+
render(<TaskButtons {...props} />);
|
|
206
|
+
const unlockButton = screen.getByRole('button', { name: /^unlock$/i });
|
|
207
|
+
fireEvent.click(unlockButton);
|
|
208
|
+
expect(setUnlockModalOpen).toHaveBeenCalledWith(true);
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
it('calls setForceUnlockModalOpen when force unlock button is clicked', () => {
|
|
212
|
+
render(<TaskButtons {...props} />);
|
|
213
|
+
const forceUnlockButton = screen.getByRole('button', {
|
|
214
|
+
name: /force unlock/i,
|
|
215
|
+
});
|
|
216
|
+
fireEvent.click(forceUnlockButton);
|
|
217
|
+
expect(setForceUnlockModalOpen).toHaveBeenCalledWith(true);
|
|
93
218
|
});
|
|
94
219
|
});
|
|
95
220
|
});
|