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.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/lib/foreman_tasks/version.rb +1 -1
  3. data/webpack/ForemanTasks/Components/TaskDetails/Components/Task.js +38 -15
  4. data/webpack/ForemanTasks/Components/TaskDetails/Components/TaskButtons.js +59 -36
  5. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/TaskButtons.test.js +196 -71
  6. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/__snapshots__/Task.test.js.snap +102 -140
  7. data/webpack/ForemanTasks/Components/TaskDetails/__tests__/__snapshots__/TaskDetails.test.js.snap +2 -16
  8. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/OtherInfo.js +5 -3
  9. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/OtherInfo.test.js +58 -9
  10. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/StoppedTasksCard.scss +0 -30
  11. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/StoppedTasksCard.test.js +190 -9
  12. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/StoppedTasksCardTable.js +70 -35
  13. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksLabelsRow/TasksLabelsRow.js +9 -14
  14. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksLabelsRow/TasksLabelsRow.scss +3 -23
  15. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksLabelsRow/TasksLabelsRow.test.js +33 -26
  16. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/ConfirmModalSelectors.js +0 -16
  17. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/GenericConfirmModal.js +70 -0
  18. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/ConfirmModalSelectors.test.js +25 -14
  19. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/__snapshots__/ConfirmModalSelectors.test.js.snap +8 -7
  20. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/index.test.js +409 -0
  21. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/createBulkTaskModal.js +67 -0
  22. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/createTaskModal.js +51 -0
  23. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/index.js +73 -23
  24. data/webpack/ForemanTasks/Components/TasksTable/TasksTable.js +5 -2
  25. data/webpack/ForemanTasks/Components/TasksTable/TasksTableConstants.js +1 -1
  26. data/webpack/ForemanTasks/Components/TasksTable/TasksTablePage.js +67 -11
  27. data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksTablePage.test.js.snap +86 -6
  28. data/webpack/ForemanTasks/Components/common/ClickConfirmation/ClickConfirmation.test.js +225 -39
  29. data/webpack/ForemanTasks/Components/common/ClickConfirmation/index.js +136 -37
  30. metadata +6 -24
  31. data/webpack/ForemanTasks/Components/TaskActions/UnlockModals.js +0 -60
  32. data/webpack/ForemanTasks/Components/TaskActions/UnlockModals.test.js +0 -14
  33. data/webpack/ForemanTasks/Components/TaskActions/__snapshots__/UnlockModals.test.js.snap +0 -25
  34. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/__snapshots__/TaskButtons.test.js.snap +0 -212
  35. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/StoppedTasksCardTable.test.js +0 -54
  36. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/__snapshots__/OtherInfo.test.js.snap +0 -30
  37. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/__snapshots__/StoppedTasksCard.test.js.snap +0 -107
  38. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/__snapshots__/StoppedTasksCardTable.test.js.snap +0 -960
  39. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksLabelsRow/__snapshots__/TasksLabelsRow.test.js.snap +0 -47
  40. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/ConfirmModal.js +0 -83
  41. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/ConfirmModalActions.js +0 -106
  42. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/ConfirmModalReducer.js +0 -38
  43. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/ConfirmModal.test.js +0 -36
  44. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/ConfirmModalActions.test.js +0 -205
  45. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/ConfirmModalReducer.test.js +0 -27
  46. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/__snapshots__/ConfirmModal.test.js.snap +0 -41
  47. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/__snapshots__/ConfirmModalReducer.test.js.snap +0 -19
  48. data/webpack/ForemanTasks/Components/common/ClickConfirmation/ClickConfirmation.scss +0 -9
  49. data/webpack/ForemanTasks/Components/common/ClickConfirmation/__snapshots__/ClickConfirmation.test.js.snap +0 -52
  50. data/webpack/__mocks__/foremanReact/components/ForemanModal/ForemanModalActions.js +0 -2
  51. data/webpack/__mocks__/foremanReact/components/ForemanModal/ForemanModalHooks.js +0 -10
  52. 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: 5ab9cdf16d7b982c8bd76f4660f35f02aea1e3033b09edc41597503370feb6e9
4
- data.tar.gz: 33058b753f95df98812dedb93b8dfc8a4ae072aabfd867d9408efe2cc4dc6cde
3
+ metadata.gz: 6323c04ba353b2c7db536b30690adf3e03648858e9883ba31276a217acedaaa5
4
+ data.tar.gz: 521d94f6dfc0d3fba10057376aeafa6b71dc5605b19dd9ed07d08e7505b982c2
5
5
  SHA512:
6
- metadata.gz: ef63b94b770d70900b2605dd64c7c57f29b1d28512399518acccf3934be0170bcfd2327117e73189722eb36b112bae70caa0a9c4c92427a846e711b098f09ec1
7
- data.tar.gz: f6ceb952e127b1f4999e1b2108f9d12c258153dfab8b48bf9430ba1794391cc12ad68e3df4f32d12cc7dcb0daec3c9a2836e6511ce2e79b63c99df275f411343
6
+ metadata.gz: ef93f73cb3325aa63c06b392ec9abb20825d27a71388667a29eddc242365407d3be292cabcba7bb6340329140f14d28eee4bb2c66219cf109e11f8f5af0c7a2a
7
+ data.tar.gz: 4a30e8776e8938bc75f1a3b88093d7d6707324abd41942c0e9e92efc39c2c85da6d322e7424b71b389f2c4e617fd4d4bdfa1aea587aa4bc72d918bf9c0a02148
@@ -1,3 +1,3 @@
1
1
  module ForemanTasks
2
- VERSION = '11.0.6'.freeze
2
+ VERSION = '11.1.0'.freeze
3
3
  end
@@ -1,7 +1,10 @@
1
- import React from 'react';
2
- import { Grid, Row } from 'patternfly-react';
1
+ import React, { useState } from 'react';
2
+ import PropTypes from 'prop-types';
3
3
  import TaskInfo from './TaskInfo';
4
- import { ForceUnlockModal, UnlockModal } from '../../TaskActions/UnlockModals';
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
- <UnlockModal onClick={unlock} />
31
- <ForceUnlockModal onClick={forceUnlock} />
32
- <Grid>
33
- <Row>
34
- <TaskButtons taskReloadStart={taskReloadStart} {...props} />
35
- </Row>
36
- <TaskInfo {...props} />
37
- </Grid>
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
- ...TaskInfo.PropTypes,
44
- ...TaskButtons.PropTypes,
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
- ...TaskInfo.defaultProps,
49
- ...TaskButtons.defaultProps,
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 { Col, Button } from 'patternfly-react';
4
- import { useForemanModal } from 'foremanReact/components/ForemanModal/ForemanModalHooks';
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
- <Col xs={12}>
34
+ <>
43
35
  <Button
36
+ variant="secondary"
37
+ ouiaId="task-buttons-reload-button"
44
38
  className="reload-button"
45
- bsSize="small"
39
+ size="sm"
46
40
  onClick={taskProgressToggle}
47
41
  >
48
- <span
49
- className={`glyphicon glyphicon-refresh ${taskReload ? 'spin' : ''}`}
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
- bsSize="small"
51
+ size="sm"
52
+ component="a"
56
53
  href={`/foreman_tasks/dynflow/${externalId}`}
57
- disabled={!dynflowEnableConsole}
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
- bsSize="small"
66
+ size="sm"
68
67
  title={editActionsTitle}
69
68
  data-original-title={editActionsTitle}
70
- disabled={!canEdit || !resumable}
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
- bsSize="small"
83
+ size="sm"
83
84
  title={editActionsTitle}
84
85
  data-original-title={editActionsTitle}
85
- disabled={!canEdit || !cancellable}
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
- bsSize="small"
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
- bsSize="small"
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
- bsSize="small"
116
- disabled={!canEdit || state !== 'paused'}
117
- onClick={unlockModalActions.setModalOpen}
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
- bsSize="small"
126
- disabled={!canEdit || state === 'stopped'}
127
- onClick={forceUnlockModalActions.setModalOpen}
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
- </Col>
146
+ </>
134
147
  );
135
148
  };
136
149
 
137
- TaskButtons.propTypes = {
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
- testComponentSnapshotsWithFixtures,
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
- import {
11
- UNLOCK_MODAL,
12
- FORCE_UNLOCK_MODAL,
13
- } from '../../../TaskActions/TaskActionsConstants';
14
-
15
- const fixtures = {
16
- 'render with minimal Props': {
17
- id: 'test',
18
- taskReloadStart: jest.fn(),
19
- taskProgressToggle: jest.fn(),
20
- },
21
- 'render with some Props': {
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('Task', () => {
36
- describe('rendering', () =>
37
- testComponentSnapshotsWithFixtures(TaskButtons, fixtures));
38
- describe('click test', () => {
39
- const setModalOpen = jest.fn();
40
- useForemanModal.mockImplementation(id => ({
41
- setModalOpen: () => setModalOpen(id),
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
- afterEach(() => {
60
- jest.clearAllMocks();
61
- });
62
- it('reload', () => {
63
- const component = mount(<TaskButtons {...props} />);
64
- const reloadButton = component.find('.reload-button').at(0);
65
- reloadButton.simulate('click');
66
- expect(taskProgressToggle).toBeCalled();
67
- });
68
- it('resume', () => {
69
- const component = shallow(<TaskButtons {...props} />);
70
- const resumeButton = component.find('.resume-button').at(0);
71
- resumeButton.props().onClick();
72
- expect(taskReloadStart).toBeCalled();
73
- expect(resumeTaskRequest).toBeCalledWith(id, action);
74
- });
75
- it('cancel', () => {
76
- const component = shallow(<TaskButtons {...props} />);
77
- const cancelButton = component.find('.cancel-button').at(0);
78
- cancelButton.props().onClick();
79
- expect(taskReloadStart).toBeCalled();
80
- expect(cancelTaskRequest).toBeCalledWith(id, action);
81
- });
82
- it('unlock', () => {
83
- const component = shallow(<TaskButtons {...props} />);
84
- const unlockButton = component.find('.unlock-button').at(0);
85
- unlockButton.props().onClick();
86
- expect(setModalOpen).toBeCalledWith({ id: UNLOCK_MODAL });
87
- });
88
- it('focrce unlock', () => {
89
- const component = shallow(<TaskButtons {...props} />);
90
- const forceUnlockButton = component.find('.force-unlock-button').at(0);
91
- forceUnlockButton.props().onClick();
92
- expect(setModalOpen).toBeCalledWith({ id: FORCE_UNLOCK_MODAL });
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
  });