foreman-tasks 11.0.6 → 11.0.7
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 +37 -9
- data/webpack/ForemanTasks/Components/TaskDetails/Components/TaskButtons.js +19 -16
- data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/TaskButtons.test.js +197 -71
- data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/__snapshots__/Task.test.js.snap +24 -40
- data/webpack/ForemanTasks/Components/TaskDetails/__tests__/__snapshots__/TaskDetails.test.js.snap +2 -16
- 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 -19
- 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/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
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
import { useSelector } from 'react-redux';
|
|
4
|
+
import { sprintf } from 'foremanReact/common/I18n';
|
|
5
|
+
import { selectClicked } from './ConfirmModalSelectors';
|
|
6
|
+
import { GenericConfirmModal } from './GenericConfirmModal';
|
|
7
|
+
|
|
8
|
+
export const createTaskModal = ({
|
|
9
|
+
actionCreator,
|
|
10
|
+
title,
|
|
11
|
+
messageTemplate,
|
|
12
|
+
confirmButtonVariant = 'primary',
|
|
13
|
+
ouiaIdPrefix,
|
|
14
|
+
}) => {
|
|
15
|
+
const TaskModal = ({ isModalOpen, setIsModalOpen, url, parentTaskID }) => {
|
|
16
|
+
const { taskId, taskName } = useSelector(selectClicked);
|
|
17
|
+
|
|
18
|
+
const handleConfirm = () =>
|
|
19
|
+
actionCreator({
|
|
20
|
+
taskId,
|
|
21
|
+
taskName,
|
|
22
|
+
url,
|
|
23
|
+
parentTaskID,
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
return (
|
|
27
|
+
<GenericConfirmModal
|
|
28
|
+
isModalOpen={isModalOpen}
|
|
29
|
+
setIsModalOpen={setIsModalOpen}
|
|
30
|
+
title={title}
|
|
31
|
+
message={sprintf(messageTemplate, { taskName })}
|
|
32
|
+
onConfirm={handleConfirm}
|
|
33
|
+
confirmButtonVariant={confirmButtonVariant}
|
|
34
|
+
ouiaIdPrefix={ouiaIdPrefix}
|
|
35
|
+
/>
|
|
36
|
+
);
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
TaskModal.propTypes = {
|
|
40
|
+
isModalOpen: PropTypes.bool.isRequired,
|
|
41
|
+
setIsModalOpen: PropTypes.func.isRequired,
|
|
42
|
+
url: PropTypes.string.isRequired,
|
|
43
|
+
parentTaskID: PropTypes.string,
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
TaskModal.defaultProps = {
|
|
47
|
+
parentTaskID: null,
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
return TaskModal;
|
|
51
|
+
};
|
|
@@ -1,29 +1,79 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import reducer from './ConfirmModalReducer';
|
|
5
|
-
import tasksActions from './ConfirmModalActions';
|
|
1
|
+
import { translate as __ } from 'foremanReact/common/I18n';
|
|
2
|
+
import { createTaskModal } from './createTaskModal';
|
|
3
|
+
import { createBulkTaskModal } from './createBulkTaskModal';
|
|
6
4
|
import {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
5
|
+
cancelTask,
|
|
6
|
+
forceCancelTask,
|
|
7
|
+
resumeTask,
|
|
8
|
+
} from '../../TasksTableActions';
|
|
9
|
+
import {
|
|
10
|
+
bulkCancelBySearch,
|
|
11
|
+
bulkCancelById,
|
|
12
|
+
bulkForceCancelBySearch,
|
|
13
|
+
bulkForceCancelById,
|
|
14
|
+
bulkResumeBySearch,
|
|
15
|
+
bulkResumeById,
|
|
16
|
+
} from '../../TasksBulkActions';
|
|
17
|
+
|
|
18
|
+
export const CancelModal = createTaskModal({
|
|
19
|
+
actionCreator: cancelTask,
|
|
20
|
+
title: __('Cancel Task'),
|
|
21
|
+
messageTemplate: __(
|
|
22
|
+
'This will cancel task "%(taskName)s", putting it in the stopped state. Are you sure?'
|
|
23
|
+
),
|
|
24
|
+
confirmButtonVariant: 'primary',
|
|
25
|
+
ouiaIdPrefix: 'cancel',
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
export const CancelSelectedModal = createBulkTaskModal({
|
|
29
|
+
bulkActionBySearch: bulkCancelBySearch,
|
|
30
|
+
bulkActionById: bulkCancelById,
|
|
31
|
+
title: __('Cancel Selected Tasks'),
|
|
32
|
+
messageTemplate: __(
|
|
33
|
+
'This will cancel %(number)s task(s), putting them in the stopped state. Are you sure?'
|
|
34
|
+
),
|
|
35
|
+
confirmButtonVariant: 'primary',
|
|
36
|
+
ouiaIdPrefix: 'cancel-selected',
|
|
37
|
+
});
|
|
14
38
|
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
39
|
+
export const ForceUnlockModal = createTaskModal({
|
|
40
|
+
actionCreator: forceCancelTask,
|
|
41
|
+
title: __('Force Unlock Task'),
|
|
42
|
+
messageTemplate: __(
|
|
43
|
+
'This will force unlock task "%(taskName)s". This may cause harm and should be used with caution. Are you sure?'
|
|
44
|
+
),
|
|
45
|
+
confirmButtonVariant: 'danger',
|
|
46
|
+
ouiaIdPrefix: 'force-unlock',
|
|
22
47
|
});
|
|
23
48
|
|
|
24
|
-
const
|
|
25
|
-
|
|
49
|
+
export const ForceUnlockSelectedModal = createBulkTaskModal({
|
|
50
|
+
bulkActionBySearch: bulkForceCancelBySearch,
|
|
51
|
+
bulkActionById: bulkForceCancelById,
|
|
52
|
+
title: __('Force Unlock Selected Tasks'),
|
|
53
|
+
messageTemplate: __(
|
|
54
|
+
'This will force unlock %(number)s task(s). This may cause harm and should be used with caution. Are you sure?'
|
|
55
|
+
),
|
|
56
|
+
confirmButtonVariant: 'danger',
|
|
57
|
+
ouiaIdPrefix: 'force-unlock-selected',
|
|
58
|
+
});
|
|
26
59
|
|
|
27
|
-
export const
|
|
60
|
+
export const ResumeModal = createTaskModal({
|
|
61
|
+
actionCreator: resumeTask,
|
|
62
|
+
title: __('Resume Task'),
|
|
63
|
+
messageTemplate: __(
|
|
64
|
+
'This will resume task "%(taskName)s", putting it in the running state. Are you sure?'
|
|
65
|
+
),
|
|
66
|
+
confirmButtonVariant: 'primary',
|
|
67
|
+
ouiaIdPrefix: 'resume',
|
|
68
|
+
});
|
|
28
69
|
|
|
29
|
-
export
|
|
70
|
+
export const ResumeSelectedModal = createBulkTaskModal({
|
|
71
|
+
bulkActionBySearch: bulkResumeBySearch,
|
|
72
|
+
bulkActionById: bulkResumeById,
|
|
73
|
+
title: __('Resume Selected Tasks'),
|
|
74
|
+
messageTemplate: __(
|
|
75
|
+
'This will resume %(number)s task(s), putting them in the running state. Are you sure?'
|
|
76
|
+
),
|
|
77
|
+
confirmButtonVariant: 'primary',
|
|
78
|
+
ouiaIdPrefix: 'resume-selected',
|
|
79
|
+
});
|
|
@@ -8,8 +8,11 @@ import Pagination from 'foremanReact/components/Pagination';
|
|
|
8
8
|
import { getURIQuery } from 'foremanReact/common/helpers';
|
|
9
9
|
import createTasksTableSchema from './TasksTableSchema';
|
|
10
10
|
import { updateURlQuery } from './TasksTableHelpers';
|
|
11
|
-
import {
|
|
12
|
-
|
|
11
|
+
import {
|
|
12
|
+
RESUME_MODAL,
|
|
13
|
+
CANCEL_MODAL,
|
|
14
|
+
FORCE_UNLOCK_MODAL,
|
|
15
|
+
} from './TasksTableConstants';
|
|
13
16
|
|
|
14
17
|
const TasksTable = ({
|
|
15
18
|
getTableItems,
|
|
@@ -16,7 +16,7 @@ export const CANCEL_MODAL = 'cancelConfirmModal';
|
|
|
16
16
|
export const RESUME_MODAL = 'resumeConfirmModal';
|
|
17
17
|
export const CANCEL_SELECTED_MODAL = 'cancelSelectedConfirmModal';
|
|
18
18
|
export const RESUME_SELECTED_MODAL = 'resumeSelectedConfirmModal';
|
|
19
|
-
export const
|
|
19
|
+
export const FORCE_UNLOCK_MODAL = 'forceUnlockConfirmModal';
|
|
20
20
|
export const FORCE_UNLOCK_SELECTED_MODAL = 'forceUnlockSelectedConfirmModal';
|
|
21
21
|
|
|
22
22
|
export const UPDATE_CLICKED = 'UPDATE_CLICKED';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React from 'react';
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
3
|
import URI from 'urijs';
|
|
4
4
|
import { getURIsearch } from 'foremanReact/common/urlHelpers';
|
|
@@ -8,17 +8,25 @@ import { translate as __ } from 'foremanReact/common/I18n';
|
|
|
8
8
|
import { getURIQuery } from 'foremanReact/common/helpers';
|
|
9
9
|
import ExportButton from 'foremanReact/routes/common/PageLayout/components/ExportButton/ExportButton';
|
|
10
10
|
import { STATUS } from 'foremanReact/constants';
|
|
11
|
-
import { useForemanModal } from 'foremanReact/components/ForemanModal/ForemanModalHooks';
|
|
12
11
|
import TasksDashboard from '../TasksDashboard';
|
|
13
12
|
import TasksTable from './TasksTable';
|
|
14
13
|
import { getCSVurl, updateURlQuery } from './TasksTableHelpers';
|
|
15
|
-
import
|
|
14
|
+
import {
|
|
15
|
+
CancelModal,
|
|
16
|
+
ResumeModal,
|
|
17
|
+
CancelSelectedModal,
|
|
18
|
+
ResumeSelectedModal,
|
|
19
|
+
ForceUnlockModal,
|
|
20
|
+
ForceUnlockSelectedModal,
|
|
21
|
+
} from './Components/ConfirmModal';
|
|
16
22
|
import {
|
|
17
23
|
TASKS_SEARCH_PROPS,
|
|
18
24
|
CANCEL_SELECTED_MODAL,
|
|
19
25
|
RESUME_SELECTED_MODAL,
|
|
20
26
|
FORCE_UNLOCK_SELECTED_MODAL,
|
|
21
|
-
|
|
27
|
+
CANCEL_MODAL,
|
|
28
|
+
RESUME_MODAL,
|
|
29
|
+
FORCE_UNLOCK_MODAL,
|
|
22
30
|
} from './TasksTableConstants';
|
|
23
31
|
import { ActionSelectButton } from './Components/ActionSelectButton';
|
|
24
32
|
import './TasksTablePage.scss';
|
|
@@ -48,21 +56,69 @@ const TasksTablePage = ({
|
|
|
48
56
|
updateURlQuery(newUriQuery, history);
|
|
49
57
|
}
|
|
50
58
|
};
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
59
|
+
const [modalStates, setModalStates] = useState({
|
|
60
|
+
[CANCEL_MODAL]: false,
|
|
61
|
+
[RESUME_MODAL]: false,
|
|
62
|
+
[CANCEL_SELECTED_MODAL]: false,
|
|
63
|
+
[RESUME_SELECTED_MODAL]: false,
|
|
64
|
+
[FORCE_UNLOCK_MODAL]: false,
|
|
65
|
+
[FORCE_UNLOCK_SELECTED_MODAL]: false,
|
|
54
66
|
});
|
|
55
67
|
|
|
56
|
-
const openModal = id =>
|
|
68
|
+
const openModal = id => {
|
|
69
|
+
setModalStates(prev => ({
|
|
70
|
+
...prev,
|
|
71
|
+
[id]: true,
|
|
72
|
+
}));
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const closeModal = id => {
|
|
76
|
+
setModalStates(prev => ({
|
|
77
|
+
...prev,
|
|
78
|
+
[id]: false,
|
|
79
|
+
}));
|
|
80
|
+
};
|
|
57
81
|
|
|
58
82
|
return (
|
|
59
83
|
<div className="tasks-table-wrapper">
|
|
60
|
-
<
|
|
61
|
-
|
|
84
|
+
<CancelModal
|
|
85
|
+
isModalOpen={modalStates[CANCEL_MODAL]}
|
|
86
|
+
setIsModalOpen={() => closeModal(CANCEL_MODAL)}
|
|
87
|
+
url={url}
|
|
88
|
+
parentTaskID={props.parentTaskID}
|
|
89
|
+
/>
|
|
90
|
+
<ResumeModal
|
|
91
|
+
isModalOpen={modalStates[RESUME_MODAL]}
|
|
92
|
+
setIsModalOpen={() => closeModal(RESUME_MODAL)}
|
|
93
|
+
url={url}
|
|
94
|
+
parentTaskID={props.parentTaskID}
|
|
95
|
+
/>
|
|
96
|
+
<CancelSelectedModal
|
|
97
|
+
isModalOpen={modalStates[CANCEL_SELECTED_MODAL]}
|
|
98
|
+
setIsModalOpen={() => closeModal(CANCEL_SELECTED_MODAL)}
|
|
62
99
|
url={url}
|
|
100
|
+
uriQuery={uriQuery}
|
|
63
101
|
parentTaskID={props.parentTaskID}
|
|
102
|
+
/>
|
|
103
|
+
<ResumeSelectedModal
|
|
104
|
+
isModalOpen={modalStates[RESUME_SELECTED_MODAL]}
|
|
105
|
+
setIsModalOpen={() => closeModal(RESUME_SELECTED_MODAL)}
|
|
106
|
+
url={url}
|
|
64
107
|
uriQuery={uriQuery}
|
|
65
|
-
|
|
108
|
+
parentTaskID={props.parentTaskID}
|
|
109
|
+
/>
|
|
110
|
+
<ForceUnlockModal
|
|
111
|
+
isModalOpen={modalStates[FORCE_UNLOCK_MODAL]}
|
|
112
|
+
setIsModalOpen={() => closeModal(FORCE_UNLOCK_MODAL)}
|
|
113
|
+
url={url}
|
|
114
|
+
parentTaskID={props.parentTaskID}
|
|
115
|
+
/>
|
|
116
|
+
<ForceUnlockSelectedModal
|
|
117
|
+
isModalOpen={modalStates[FORCE_UNLOCK_SELECTED_MODAL]}
|
|
118
|
+
setIsModalOpen={() => closeModal(FORCE_UNLOCK_SELECTED_MODAL)}
|
|
119
|
+
url={url}
|
|
120
|
+
uriQuery={uriQuery}
|
|
121
|
+
parentTaskID={props.parentTaskID}
|
|
66
122
|
/>
|
|
67
123
|
<PageLayout
|
|
68
124
|
searchable
|
data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksTablePage.test.js.snap
CHANGED
|
@@ -4,10 +4,50 @@ exports[`TasksTablePage rendering render with Breadcrubs and edit permissions 1`
|
|
|
4
4
|
<div
|
|
5
5
|
className="tasks-table-wrapper"
|
|
6
6
|
>
|
|
7
|
-
<
|
|
8
|
-
|
|
7
|
+
<TaskModal
|
|
8
|
+
isModalOpen={false}
|
|
9
9
|
parentTaskID={null}
|
|
10
|
-
|
|
10
|
+
setIsModalOpen={[Function]}
|
|
11
|
+
url="/foreman_tasks/tasks?action=\\"some-name\\""
|
|
12
|
+
/>
|
|
13
|
+
<TaskModal
|
|
14
|
+
isModalOpen={false}
|
|
15
|
+
parentTaskID={null}
|
|
16
|
+
setIsModalOpen={[Function]}
|
|
17
|
+
url="/foreman_tasks/tasks?action=\\"some-name\\""
|
|
18
|
+
/>
|
|
19
|
+
<BulkTaskModal
|
|
20
|
+
isModalOpen={false}
|
|
21
|
+
parentTaskID={null}
|
|
22
|
+
setIsModalOpen={[Function]}
|
|
23
|
+
uriQuery={
|
|
24
|
+
Object {
|
|
25
|
+
"state": "stopped",
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
url="/foreman_tasks/tasks?action=\\"some-name\\""
|
|
29
|
+
/>
|
|
30
|
+
<BulkTaskModal
|
|
31
|
+
isModalOpen={false}
|
|
32
|
+
parentTaskID={null}
|
|
33
|
+
setIsModalOpen={[Function]}
|
|
34
|
+
uriQuery={
|
|
35
|
+
Object {
|
|
36
|
+
"state": "stopped",
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
url="/foreman_tasks/tasks?action=\\"some-name\\""
|
|
40
|
+
/>
|
|
41
|
+
<TaskModal
|
|
42
|
+
isModalOpen={false}
|
|
43
|
+
parentTaskID={null}
|
|
44
|
+
setIsModalOpen={[Function]}
|
|
45
|
+
url="/foreman_tasks/tasks?action=\\"some-name\\""
|
|
46
|
+
/>
|
|
47
|
+
<BulkTaskModal
|
|
48
|
+
isModalOpen={false}
|
|
49
|
+
parentTaskID={null}
|
|
50
|
+
setIsModalOpen={[Function]}
|
|
11
51
|
uriQuery={
|
|
12
52
|
Object {
|
|
13
53
|
"state": "stopped",
|
|
@@ -156,10 +196,50 @@ exports[`TasksTablePage rendering render with minimal props 1`] = `
|
|
|
156
196
|
<div
|
|
157
197
|
className="tasks-table-wrapper"
|
|
158
198
|
>
|
|
159
|
-
<
|
|
160
|
-
|
|
199
|
+
<TaskModal
|
|
200
|
+
isModalOpen={false}
|
|
201
|
+
parentTaskID={null}
|
|
202
|
+
setIsModalOpen={[Function]}
|
|
203
|
+
url="/foreman_tasks/tasks?action=\\"some-name\\""
|
|
204
|
+
/>
|
|
205
|
+
<TaskModal
|
|
206
|
+
isModalOpen={false}
|
|
207
|
+
parentTaskID={null}
|
|
208
|
+
setIsModalOpen={[Function]}
|
|
209
|
+
url="/foreman_tasks/tasks?action=\\"some-name\\""
|
|
210
|
+
/>
|
|
211
|
+
<BulkTaskModal
|
|
212
|
+
isModalOpen={false}
|
|
213
|
+
parentTaskID={null}
|
|
214
|
+
setIsModalOpen={[Function]}
|
|
215
|
+
uriQuery={
|
|
216
|
+
Object {
|
|
217
|
+
"state": "stopped",
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
url="/foreman_tasks/tasks?action=\\"some-name\\""
|
|
221
|
+
/>
|
|
222
|
+
<BulkTaskModal
|
|
223
|
+
isModalOpen={false}
|
|
224
|
+
parentTaskID={null}
|
|
225
|
+
setIsModalOpen={[Function]}
|
|
226
|
+
uriQuery={
|
|
227
|
+
Object {
|
|
228
|
+
"state": "stopped",
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
url="/foreman_tasks/tasks?action=\\"some-name\\""
|
|
232
|
+
/>
|
|
233
|
+
<TaskModal
|
|
234
|
+
isModalOpen={false}
|
|
235
|
+
parentTaskID={null}
|
|
236
|
+
setIsModalOpen={[Function]}
|
|
237
|
+
url="/foreman_tasks/tasks?action=\\"some-name\\""
|
|
238
|
+
/>
|
|
239
|
+
<BulkTaskModal
|
|
240
|
+
isModalOpen={false}
|
|
161
241
|
parentTaskID={null}
|
|
162
|
-
|
|
242
|
+
setIsModalOpen={[Function]}
|
|
163
243
|
uriQuery={
|
|
164
244
|
Object {
|
|
165
245
|
"state": "stopped",
|
|
@@ -1,44 +1,230 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
confirmType: 'danger',
|
|
10
|
-
body: 'some-body',
|
|
11
|
-
confirmationMessage: 'some-message',
|
|
12
|
-
id: 'some-id',
|
|
13
|
-
confirmAction: 'some-confirm',
|
|
14
|
-
onClick: jest.fn(),
|
|
15
|
-
},
|
|
16
|
-
};
|
|
2
|
+
import { render, screen, fireEvent } from '@testing-library/react';
|
|
3
|
+
import '@testing-library/jest-dom';
|
|
4
|
+
import {
|
|
5
|
+
ClickConfirmation,
|
|
6
|
+
UnlockConfirmationModal,
|
|
7
|
+
ForceUnlockConfirmationModal,
|
|
8
|
+
} from './';
|
|
17
9
|
|
|
18
10
|
describe('ClickConfirmation', () => {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
11
|
+
const defaultProps = {
|
|
12
|
+
title: 'Test Modal',
|
|
13
|
+
body: 'This is a test modal body',
|
|
14
|
+
confirmationMessage: 'I understand the consequences',
|
|
15
|
+
confirmAction: 'Confirm',
|
|
16
|
+
onClick: jest.fn(),
|
|
17
|
+
id: 'test-modal',
|
|
18
|
+
isOpen: true,
|
|
19
|
+
setModalClosed: jest.fn(),
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
beforeEach(() => {
|
|
23
|
+
jest.clearAllMocks();
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
describe('Basic Rendering', () => {
|
|
27
|
+
it('renders modal with correct title and content when open', () => {
|
|
28
|
+
render(<ClickConfirmation {...defaultProps} />);
|
|
29
|
+
|
|
30
|
+
expect(screen.getByText('Test Modal')).toBeInTheDocument();
|
|
31
|
+
expect(screen.getByText('This is a test modal body')).toBeInTheDocument();
|
|
32
|
+
expect(
|
|
33
|
+
screen.getByText('I understand the consequences')
|
|
34
|
+
).toBeInTheDocument();
|
|
35
|
+
expect(screen.getByText('Confirm')).toBeInTheDocument();
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('does not render modal when isOpen is false', () => {
|
|
39
|
+
render(<ClickConfirmation {...defaultProps} isOpen={false} />);
|
|
40
|
+
|
|
41
|
+
expect(screen.queryByText('Test Modal')).not.toBeInTheDocument();
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it('renders with warning variant by default', () => {
|
|
45
|
+
render(<ClickConfirmation {...defaultProps} />);
|
|
46
|
+
|
|
47
|
+
const modal = screen.getByRole('dialog');
|
|
48
|
+
expect(modal).toBeInTheDocument();
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('renders with danger variant when specified', () => {
|
|
52
|
+
render(<ClickConfirmation {...defaultProps} confirmType="danger" />);
|
|
53
|
+
|
|
54
|
+
const confirmButton = screen.getByRole('button', { name: 'Confirm' });
|
|
55
|
+
expect(confirmButton).toHaveClass('pf-m-danger');
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
describe('Checkbox Interaction', () => {
|
|
60
|
+
it('starts with checkbox unchecked and confirm button disabled', () => {
|
|
61
|
+
render(<ClickConfirmation {...defaultProps} />);
|
|
62
|
+
|
|
63
|
+
const checkbox = screen.getByRole('checkbox');
|
|
64
|
+
const confirmButton = screen.getByRole('button', { name: 'Confirm' });
|
|
65
|
+
|
|
66
|
+
expect(checkbox).not.toBeChecked();
|
|
67
|
+
expect(confirmButton).toBeDisabled();
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it('enables confirm button when checkbox is checked', () => {
|
|
71
|
+
render(<ClickConfirmation {...defaultProps} />);
|
|
72
|
+
|
|
73
|
+
const checkbox = screen.getByRole('checkbox');
|
|
74
|
+
const confirmButton = screen.getByRole('button', { name: 'Confirm' });
|
|
75
|
+
|
|
76
|
+
fireEvent.click(checkbox);
|
|
77
|
+
|
|
78
|
+
expect(checkbox).toBeChecked();
|
|
79
|
+
expect(confirmButton).toBeEnabled();
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it('disables confirm button when checkbox is unchecked', () => {
|
|
83
|
+
render(<ClickConfirmation {...defaultProps} />);
|
|
84
|
+
|
|
85
|
+
const checkbox = screen.getByRole('checkbox');
|
|
86
|
+
const confirmButton = screen.getByRole('button', { name: 'Confirm' });
|
|
87
|
+
|
|
88
|
+
// Check the checkbox first
|
|
89
|
+
fireEvent.click(checkbox);
|
|
90
|
+
expect(confirmButton).toBeEnabled();
|
|
91
|
+
|
|
92
|
+
// Uncheck the checkbox
|
|
93
|
+
fireEvent.click(checkbox);
|
|
94
|
+
expect(checkbox).not.toBeChecked();
|
|
95
|
+
expect(confirmButton).toBeDisabled();
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
describe('Button Actions', () => {
|
|
100
|
+
it('calls onClick and setModalClosed when confirm button is clicked', () => {
|
|
101
|
+
const onClick = jest.fn();
|
|
102
|
+
const setModalClosed = jest.fn();
|
|
103
|
+
|
|
104
|
+
render(
|
|
105
|
+
<ClickConfirmation
|
|
106
|
+
{...defaultProps}
|
|
107
|
+
onClick={onClick}
|
|
108
|
+
setModalClosed={setModalClosed}
|
|
109
|
+
/>
|
|
110
|
+
);
|
|
111
|
+
|
|
112
|
+
const checkbox = screen.getByRole('checkbox');
|
|
113
|
+
const confirmButton = screen.getByRole('button', { name: 'Confirm' });
|
|
114
|
+
|
|
115
|
+
// Enable the button by checking the checkbox
|
|
116
|
+
fireEvent.click(checkbox);
|
|
117
|
+
|
|
118
|
+
// Click the confirm button
|
|
119
|
+
fireEvent.click(confirmButton);
|
|
120
|
+
|
|
121
|
+
expect(onClick).toHaveBeenCalledTimes(1);
|
|
122
|
+
expect(setModalClosed).toHaveBeenCalledTimes(1);
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
it('calls setModalClosed when cancel button is clicked', () => {
|
|
126
|
+
const setModalClosed = jest.fn();
|
|
127
|
+
|
|
128
|
+
render(
|
|
129
|
+
<ClickConfirmation {...defaultProps} setModalClosed={setModalClosed} />
|
|
130
|
+
);
|
|
131
|
+
|
|
132
|
+
const cancelButton = screen.getByRole('button', { name: 'Cancel' });
|
|
133
|
+
fireEvent.click(cancelButton);
|
|
134
|
+
|
|
135
|
+
expect(setModalClosed).toHaveBeenCalledTimes(1);
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
it('does not call onClick when confirm button is clicked while disabled', () => {
|
|
139
|
+
const onClick = jest.fn();
|
|
140
|
+
|
|
141
|
+
render(<ClickConfirmation {...defaultProps} onClick={onClick} />);
|
|
142
|
+
|
|
143
|
+
const confirmButton = screen.getByRole('button', { name: 'Confirm' });
|
|
144
|
+
|
|
145
|
+
// Try to click the disabled button
|
|
146
|
+
fireEvent.click(confirmButton);
|
|
147
|
+
|
|
148
|
+
expect(onClick).not.toHaveBeenCalled();
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
describe('UnlockModal', () => {
|
|
154
|
+
const defaultProps = {
|
|
155
|
+
onClick: jest.fn(),
|
|
156
|
+
id: 'unlock-modal',
|
|
157
|
+
isOpen: true,
|
|
158
|
+
setModalClosed: jest.fn(),
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
beforeEach(() => {
|
|
162
|
+
jest.clearAllMocks();
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
it('renders with correct unlock-specific content and warning variant', () => {
|
|
166
|
+
render(<UnlockConfirmationModal {...defaultProps} />);
|
|
167
|
+
|
|
168
|
+
expect(
|
|
169
|
+
screen.getByRole('heading', { name: 'Warning alert: Unlock' })
|
|
170
|
+
).toBeInTheDocument();
|
|
171
|
+
expect(
|
|
172
|
+
screen.getByText(
|
|
173
|
+
/This will unlock the resources that the task is running against/
|
|
174
|
+
)
|
|
175
|
+
).toBeInTheDocument();
|
|
176
|
+
expect(
|
|
177
|
+
screen.getByText(
|
|
178
|
+
'I understand that this may cause harm and have working database backups of all backend services.'
|
|
179
|
+
)
|
|
180
|
+
).toBeInTheDocument();
|
|
181
|
+
|
|
182
|
+
const confirmButton = screen.getByRole('button', { name: 'Unlock' });
|
|
183
|
+
expect(confirmButton).toBeInTheDocument();
|
|
184
|
+
expect(confirmButton).toHaveClass('pf-m-primary');
|
|
185
|
+
});
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
describe('ForceUnlockModal', () => {
|
|
189
|
+
const defaultProps = {
|
|
190
|
+
onClick: jest.fn(),
|
|
191
|
+
id: 'force-unlock-modal',
|
|
192
|
+
selectedRowsLen: 3,
|
|
193
|
+
isOpen: true,
|
|
194
|
+
setModalClosed: jest.fn(),
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
beforeEach(() => {
|
|
198
|
+
jest.clearAllMocks();
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
it('renders with correct force unlock-specific content and danger variant', () => {
|
|
202
|
+
render(<ForceUnlockConfirmationModal {...defaultProps} />);
|
|
203
|
+
|
|
204
|
+
expect(
|
|
205
|
+
screen.getByRole('heading', { name: 'Danger alert: Force Unlock' })
|
|
206
|
+
).toBeInTheDocument();
|
|
207
|
+
expect(
|
|
208
|
+
screen.getByText(/Resources for 3 task\(s\) will be unlocked/)
|
|
209
|
+
).toBeInTheDocument();
|
|
210
|
+
expect(
|
|
211
|
+
screen.getByText(
|
|
212
|
+
'I understand that this may cause harm and have working database backups of all backend services.'
|
|
213
|
+
)
|
|
214
|
+
).toBeInTheDocument();
|
|
215
|
+
|
|
216
|
+
const confirmButton = screen.getByRole('button', { name: 'Force Unlock' });
|
|
217
|
+
expect(confirmButton).toBeInTheDocument();
|
|
218
|
+
expect(confirmButton).toHaveClass('pf-m-danger');
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
it('displays correct number of tasks in body', () => {
|
|
222
|
+
render(
|
|
223
|
+
<ForceUnlockConfirmationModal {...defaultProps} selectedRowsLen={5} />
|
|
224
|
+
);
|
|
225
|
+
|
|
226
|
+
expect(
|
|
227
|
+
screen.getByText(/Resources for 5 task\(s\) will be unlocked/)
|
|
228
|
+
).toBeInTheDocument();
|
|
43
229
|
});
|
|
44
230
|
});
|