foreman-tasks 1.1.0 → 1.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/foreman_tasks/api/tasks_controller.rb +12 -5
  3. data/app/lib/foreman_tasks/concerns/polling_action_extensions.rb +12 -0
  4. data/app/models/setting/foreman_tasks.rb +6 -1
  5. data/app/services/ui_notifications/tasks/task_bulk_cancel.rb +36 -0
  6. data/app/services/ui_notifications/tasks/task_bulk_resume.rb +38 -0
  7. data/db/seeds.d/30-notification_blueprints.rb +14 -0
  8. data/foreman-tasks.gemspec +1 -0
  9. data/gemfile.d/foreman-tasks.rb +1 -0
  10. data/lib/foreman_tasks/engine.rb +1 -0
  11. data/lib/foreman_tasks/version.rb +1 -1
  12. data/script/travis_run_js_tests.sh +2 -2
  13. data/test/lib/concerns/polling_action_extensions_test.rb +34 -0
  14. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/__snapshots__/TaskInfo.test.js.snap +1 -3
  15. data/webpack/ForemanTasks/Components/TasksDashboard/TasksDashboardConstants.js +5 -0
  16. data/webpack/ForemanTasks/Components/TasksDashboard/TasksDashboardHelper.js +3 -2
  17. data/webpack/ForemanTasks/Components/TasksTable/Components/SelectAllAlert.js +43 -0
  18. data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/SelectAllAlert.test.js +29 -0
  19. data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/__snapshots__/SelectAllAlert.test.js.snap +75 -0
  20. data/webpack/ForemanTasks/Components/TasksTable/SubTasksPage.js +2 -1
  21. data/webpack/ForemanTasks/Components/TasksTable/TasksBulkActions.js +164 -0
  22. data/webpack/ForemanTasks/Components/TasksTable/TasksTable.js +24 -10
  23. data/webpack/ForemanTasks/Components/TasksTable/TasksTableActionHelpers.js +52 -0
  24. data/webpack/ForemanTasks/Components/TasksTable/TasksTableActions.js +66 -128
  25. data/webpack/ForemanTasks/Components/TasksTable/TasksTableConstants.js +11 -1
  26. data/webpack/ForemanTasks/Components/TasksTable/TasksTableHelpers.js +4 -3
  27. data/webpack/ForemanTasks/Components/TasksTable/TasksTablePage.js +64 -12
  28. data/webpack/ForemanTasks/Components/TasksTable/TasksTableReducer.js +21 -2
  29. data/webpack/ForemanTasks/Components/TasksTable/TasksTableSelectors.js +6 -0
  30. data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksBulkActions.test.js +112 -0
  31. data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksTable.fixtures.js +5 -3
  32. data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksTableActionHelpers.test.js +46 -0
  33. data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksTableActions.test.js +19 -41
  34. data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksTableHelpers.test.js +17 -1
  35. data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksTablePage.test.js +9 -1
  36. data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksTableReducer.test.js +22 -1
  37. data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/SubTasksPage.test.js.snap +5 -3
  38. data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksBulkActions.test.js.snap +229 -0
  39. data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksIndexPage.test.js.snap +5 -3
  40. data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksTableActions.test.js.snap +39 -124
  41. data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksTablePage.test.js.snap +40 -16
  42. data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksTableReducer.test.js.snap +34 -0
  43. data/webpack/ForemanTasks/Components/TasksTable/formatters/__test__/selectionHeaderCellFormatter.test.js +1 -1
  44. data/webpack/ForemanTasks/Components/TasksTable/formatters/selectionHeaderCellFormatter.js +2 -2
  45. data/webpack/ForemanTasks/Components/TasksTable/index.js +8 -2
  46. data/webpack/ForemanTasks/Components/common/ToastTypesConstants.js +11 -0
  47. metadata +31 -2
@@ -1,12 +1,22 @@
1
1
  import { getControllerSearchProps } from 'foremanReact/constants';
2
2
 
3
3
  export const TASKS_TABLE_ID = 'TASKS_TABLE';
4
+
4
5
  export const SELECT_ROWS = 'SELECT_ROWS';
5
6
  export const UNSELECT_ROWS = 'UNSELECT_ROWS';
6
7
  export const UNSELECT_ALL_ROWS = 'UNSELECT_ALL_ROWS';
8
+ export const SELECT_ALL_ROWS = 'SELECT_ALL_ROWS';
9
+ export const OPEN_SELECT_ALL = 'OPEN_SELECT_ALL';
10
+
7
11
  export const TASKS_RESUME_REQUEST = 'TASKS_RESUME_REQUEST';
8
12
  export const TASKS_RESUME_SUCCESS = 'TASKS_RESUME_SUCCESS';
9
13
  export const TASKS_RESUME_FAILURE = 'TASKS_RESUME_FAILURE';
14
+ export const TASKS_CANCEL_REQUEST = 'TASKS_CANCEL_REQUEST';
15
+ export const TASKS_CANCEL_SUCCESS = 'TASKS_CANCEL_SUCCESS';
16
+ export const TASKS_CANCEL_FAILURE = 'TASKS_CANCEL_FAILURE';
17
+
18
+ export const BULK_CANCEL_PATH = 'bulk_cancel';
19
+ export const BULK_RESUME_PATH = 'bulk_resume';
10
20
 
11
21
  export const CANCEL_CONFIRM_MODAL_ID = 'cancelConfirmModal';
12
22
  export const RESUME_CONFIRM_MODAL_ID = 'resumeConfirmModal';
@@ -16,5 +26,5 @@ export const UPDATE_CLICKED = 'UPDATE_CLICKED';
16
26
 
17
27
  export const TASKS_SEARCH_PROPS = {
18
28
  ...getControllerSearchProps('tasks'),
19
- controller: 'foreman_tasks/tasks'
29
+ controller: 'foreman_tasks/tasks',
20
30
  };
@@ -22,9 +22,10 @@ export const resolveSearchQuery = (search, history) => {
22
22
  updateURlQuery(uriQuery, history);
23
23
  };
24
24
 
25
- export const addSearchToURL = (path, query) => {
26
- const url = new URI(path);
27
- url.addSearch({ ...query, include_permissions: true });
25
+ export const getCSVurl = (path, query) => {
26
+ let url = new URI(path);
27
+ url = url.pathname(`${url.pathname()}.csv`);
28
+ url.addSearch(query);
28
29
  return url.toString();
29
30
  };
30
31
 
@@ -10,7 +10,7 @@ import { STATUS } from 'foremanReact/constants';
10
10
  import { useForemanModal } from 'foremanReact/components/ForemanModal/ForemanModalHooks';
11
11
  import TasksDashboard from '../TasksDashboard';
12
12
  import TasksTable from './TasksTable';
13
- import { resolveSearchQuery, addSearchToURL } from './TasksTableHelpers';
13
+ import { resolveSearchQuery, getCSVurl } from './TasksTableHelpers';
14
14
  import { ConfirmationModals } from './Components/ConfirmationModals';
15
15
  import {
16
16
  TASKS_SEARCH_PROPS,
@@ -21,8 +21,17 @@ import {
21
21
  } from './TasksTableConstants';
22
22
  import { ActionSelectButton } from './Components/ActionSelectButton';
23
23
  import './TasksTablePage.scss';
24
+ import { SelectAllAlert } from './Components/SelectAllAlert';
24
25
 
25
- const TasksTablePage = ({ getBreadcrumbs, history, clicked, createHeader, ...props }) => {
26
+ const TasksTablePage = ({
27
+ getBreadcrumbs,
28
+ history,
29
+ clicked,
30
+ createHeader,
31
+ selectAllRows,
32
+ showSelectAll,
33
+ ...props
34
+ }) => {
26
35
  const url = history.location.pathname + history.location.search;
27
36
  const uriQuery = getURIQuery(url);
28
37
  const onSearch = searchQuery => {
@@ -53,15 +62,23 @@ const TasksTablePage = ({ getBreadcrumbs, history, clicked, createHeader, ...pro
53
62
  };
54
63
 
55
64
  const {
56
- bulkCancel,
57
- bulkResume,
65
+ bulkCancelById,
66
+ bulkCancelBySearch,
67
+ bulkResumeById,
68
+ bulkResumeBySearch,
58
69
  cancelTask,
59
70
  resumeTask,
60
71
  parentTaskID,
61
72
  } = props;
62
73
  const tasksActions = {
63
74
  cancelSelectedTasks: () => {
64
- bulkCancel({ selected: getSelectedTasks(), url, parentTaskID });
75
+ props.allRowsSelected
76
+ ? bulkCancelBySearch({ query: uriQuery, parentTaskID })
77
+ : bulkCancelById({
78
+ selected: getSelectedTasks(),
79
+ url,
80
+ parentTaskID,
81
+ });
65
82
  },
66
83
  cancelTask: () => {
67
84
  cancelTask({
@@ -72,7 +89,13 @@ const TasksTablePage = ({ getBreadcrumbs, history, clicked, createHeader, ...pro
72
89
  });
73
90
  },
74
91
  resumeSelectedTasks: () => {
75
- bulkResume({ selected: getSelectedTasks(), url, parentTaskID });
92
+ props.allRowsSelected
93
+ ? bulkResumeBySearch({ query: uriQuery, parentTaskID })
94
+ : bulkResumeById({
95
+ selected: getSelectedTasks(),
96
+ url,
97
+ parentTaskID,
98
+ });
76
99
  },
77
100
  resumeTask: () => {
78
101
  resumeTask({
@@ -88,7 +111,9 @@ const TasksTablePage = ({ getBreadcrumbs, history, clicked, createHeader, ...pro
88
111
  <div className="tasks-table-wrapper">
89
112
  <ConfirmationModals
90
113
  tasksActions={tasksActions}
91
- selectedRowsLen={props.selectedRows.length}
114
+ selectedRowsLen={
115
+ props.allRowsSelected ? props.itemCount : props.selectedRows.length
116
+ }
92
117
  modalProps={modalProps}
93
118
  />
94
119
  <PageLayout
@@ -102,11 +127,11 @@ const TasksTablePage = ({ getBreadcrumbs, history, clicked, createHeader, ...pro
102
127
  <React.Fragment>
103
128
  {props.status === STATUS.PENDING && <Spinner size="lg" loading />}
104
129
  <ExportButton
105
- url={addSearchToURL('/foreman_tasks/tasks.csv', uriQuery)}
130
+ url={getCSVurl(url, uriQuery)}
106
131
  title={__('Export All')}
107
132
  />
108
133
  <ActionSelectButton
109
- disabled={props.selectedRows.length < 1}
134
+ disabled={!(props.selectedRows.length || props.allRowsSelected)}
110
135
  onCancel={modalProps.cancelSelectedModal.setModalOpen}
111
136
  onResume={modalProps.resumeSelectedModal.setModalOpen}
112
137
  />
@@ -117,13 +142,30 @@ const TasksTablePage = ({ getBreadcrumbs, history, clicked, createHeader, ...pro
117
142
  <TasksDashboard history={history} parentTaskID={props.parentTaskID} />
118
143
  }
119
144
  >
120
- <TasksTable history={history} {...props} modalProps={modalProps} />
145
+ <React.Fragment>
146
+ {showSelectAll && props.itemCount >= props.pagination.perPage && (
147
+ <SelectAllAlert
148
+ itemCount={props.itemCount}
149
+ perPage={props.pagination.perPage}
150
+ selectAllRows={selectAllRows}
151
+ unselectAllRows={props.unselectAllRows}
152
+ allRowsSelected={props.allRowsSelected}
153
+ />
154
+ )}
155
+ <TasksTable history={history} {...props} modalProps={modalProps} />
156
+ </React.Fragment>
121
157
  </PageLayout>
122
158
  </div>
123
159
  );
124
160
  };
125
161
 
126
162
  TasksTablePage.propTypes = {
163
+ allRowsSelected: PropTypes.bool,
164
+ itemCount: PropTypes.number.isRequired,
165
+ pagination: PropTypes.shape({
166
+ perPage: PropTypes.number,
167
+ }),
168
+ selectAllRows: PropTypes.func.isRequired,
127
169
  results: PropTypes.array.isRequired,
128
170
  getTableItems: PropTypes.func.isRequired,
129
171
  getBreadcrumbs: PropTypes.func.isRequired,
@@ -132,8 +174,10 @@ TasksTablePage.propTypes = {
132
174
  history: PropTypes.object.isRequired,
133
175
  cancelTask: PropTypes.func.isRequired,
134
176
  resumeTask: PropTypes.func.isRequired,
135
- bulkCancel: PropTypes.func.isRequired,
136
- bulkResume: PropTypes.func.isRequired,
177
+ bulkCancelById: PropTypes.func.isRequired,
178
+ bulkCancelBySearch: PropTypes.func.isRequired,
179
+ bulkResumeById: PropTypes.func.isRequired,
180
+ bulkResumeBySearch: PropTypes.func.isRequired,
137
181
  selectedRows: PropTypes.arrayOf(PropTypes.string),
138
182
  parentTaskID: PropTypes.string,
139
183
  createHeader: PropTypes.func,
@@ -142,15 +186,23 @@ TasksTablePage.propTypes = {
142
186
  taskName: PropTypes.string,
143
187
  parentTaskID: PropTypes.string,
144
188
  }),
189
+ showSelectAll: PropTypes.bool,
190
+ unselectAllRows: PropTypes.func.isRequired,
145
191
  };
146
192
 
147
193
  TasksTablePage.defaultProps = {
194
+ pagination: {
195
+ page: 1,
196
+ perPage: 20,
197
+ },
198
+ allRowsSelected: false,
148
199
  actionName: '',
149
200
  status: STATUS.PENDING,
150
201
  selectedRows: [],
151
202
  parentTaskID: null,
152
203
  clicked: {},
153
204
  createHeader: () => __('Tasks'),
205
+ showSelectAll: false,
154
206
  };
155
207
 
156
208
  export default TasksTablePage;
@@ -9,6 +9,8 @@ import {
9
9
  UNSELECT_ROWS,
10
10
  UNSELECT_ALL_ROWS,
11
11
  UPDATE_CLICKED,
12
+ SELECT_ALL_ROWS,
13
+ OPEN_SELECT_ALL,
12
14
  } from './TasksTableConstants';
13
15
 
14
16
  const initialState = Immutable({
@@ -21,6 +23,8 @@ export const TasksTableQueryReducer = (state = initialState, action) => {
21
23
  response || {};
22
24
  const ACTION_TYPES = createTableActionTypes(TASKS_TABLE_ID);
23
25
  switch (type) {
26
+ case SELECT_ALL_ROWS:
27
+ return state.set('allRowsSelected', true);
24
28
  case ACTION_TYPES.SUCCESS:
25
29
  return Immutable.merge(state, {
26
30
  itemCount: subtotal,
@@ -33,13 +37,28 @@ export const TasksTableQueryReducer = (state = initialState, action) => {
33
37
  });
34
38
  case SELECT_ROWS:
35
39
  return state.set('selectedRows', union(payload, state.selectedRows));
40
+ case OPEN_SELECT_ALL:
41
+ return state.set('showSelectAll', true);
36
42
  case UNSELECT_ROWS:
43
+ if (state.allRowsSelected) {
44
+ // User can unselect rows if only the page rows are selected
45
+ return state
46
+ .set(
47
+ 'selectedRows',
48
+ payload.results.map(row => row.id).filter(row => row !== payload.id)
49
+ )
50
+ .set('allRowsSelected', false)
51
+ .set('showSelectAll', false);
52
+ }
37
53
  return state.set(
38
54
  'selectedRows',
39
- state.selectedRows.filter(row => row !== payload)
55
+ state.selectedRows.filter(row => row !== payload.id)
40
56
  );
41
57
  case UNSELECT_ALL_ROWS:
42
- return state.set('selectedRows', []);
58
+ return state
59
+ .set('selectedRows', [])
60
+ .set('allRowsSelected', false)
61
+ .set('showSelectAll', false);
43
62
  case UPDATE_CLICKED:
44
63
  return state.set('clicked', payload.clicked);
45
64
  default:
@@ -48,3 +48,9 @@ export const selectError = state => selectTasksTableContent(state).error;
48
48
 
49
49
  export const selectSort = state =>
50
50
  selectTasksTableQuery(state).sort || { by: 'started_at', order: 'DESC' };
51
+
52
+ export const selectAllRowsSelected = state =>
53
+ selectTasksTableQuery(state).allRowsSelected;
54
+
55
+ export const selectShowSelectAll = state =>
56
+ selectTasksTableQuery(state).showSelectAll;
@@ -0,0 +1,112 @@
1
+ import { testActionSnapshotWithFixtures } from '@theforeman/test';
2
+ import API from 'foremanReact/API';
3
+ import {
4
+ bulkCancelById,
5
+ bulkCancelBySearch,
6
+ bulkResumeById,
7
+ bulkResumeBySearch,
8
+ } from '../TasksBulkActions';
9
+
10
+ jest.mock('foremanReact/components/common/table', () => ({
11
+ getTableItemsAction: jest.fn(controller => controller),
12
+ }));
13
+
14
+ jest.mock('foremanReact/API');
15
+
16
+ const task = {
17
+ id: 'some-id',
18
+ name: 'some-name',
19
+ };
20
+
21
+ const fixtures = {
22
+ 'handles bulkResumeById requests that fail': () => {
23
+ const selected = [{ ...task, isResumable: true }];
24
+
25
+ API.post.mockImplementation(() =>
26
+ Promise.reject(new Error('Network Error'))
27
+ );
28
+ return bulkResumeById({ selected, url: 'some-url' });
29
+ },
30
+ 'handles resumable bulkResumeById requests': () => {
31
+ const selected = [{ ...task, isResumable: true }];
32
+
33
+ API.post.mockImplementation(() => ({
34
+ data: {
35
+ resumed: [{ action: 'I am resumed' }],
36
+ failed: [{ action: 'I am failed' }],
37
+ },
38
+ }));
39
+ return bulkResumeById({ selected, url: 'some-url' });
40
+ },
41
+ 'handles bulkCancelById requests': () => {
42
+ const selected = [{ ...task, isCancellable: true }];
43
+
44
+ API.post.mockImplementation(() => ({
45
+ data: {
46
+ cancelled: [{ action: 'I am cancelled' }],
47
+ },
48
+ }));
49
+ return bulkCancelById({ selected, url: 'some-url' });
50
+ },
51
+ 'handles skipped bulkResumeById requests': () => {
52
+ const selected = [{ ...task, isResumable: true }];
53
+
54
+ API.post.mockImplementation(() => ({
55
+ data: {
56
+ skipped: [{ action: 'I am skipped' }],
57
+ },
58
+ }));
59
+ return bulkResumeById({ selected, url: 'some-url' });
60
+ },
61
+ 'handles skipped bulkCancelById requests': () => {
62
+ const selected = [{ ...task, isCancellable: true }];
63
+
64
+ API.post.mockImplementation(() => ({
65
+ data: {
66
+ skipped: [{ action: 'I am skipped' }],
67
+ },
68
+ }));
69
+ return bulkCancelById({ selected, url: 'some-url' });
70
+ },
71
+ 'handles bulkCancelById requests that are not cancellable': () => {
72
+ const selected = [{ ...task, isCancellable: false }];
73
+ return bulkCancelById({ selected, url: 'some-url' });
74
+ },
75
+ 'handles bulkResumeById requests that are not resumable': () => {
76
+ const selected = [{ ...task, isResumable: false, isCancellable: false }];
77
+ return bulkResumeById({ selected, url: 'some-url' });
78
+ },
79
+
80
+ 'handles bulkCancelBySearch requests': () => {
81
+ API.post.mockImplementation(() => ({
82
+ data: {
83
+ cancelled: [{ action: 'I am cancelled' }],
84
+ skipped: [{ action: 'I am skipped' }],
85
+ },
86
+ }));
87
+ return bulkCancelBySearch({
88
+ query: { search: {} },
89
+ url: 'some-url',
90
+ parentTaskID: 'parent',
91
+ });
92
+ },
93
+
94
+ 'handles bulkResumeBySearch requests': () => {
95
+ API.post.mockImplementation(() => ({
96
+ data: {
97
+ cancelled: [{ action: 'I am cancelled' }],
98
+ skipped: [{ action: 'I am skipped' }],
99
+ failed: [{ action: 'I am failed' }],
100
+ },
101
+ }));
102
+ return bulkResumeBySearch({
103
+ query: { search: {} },
104
+ url: 'some-url',
105
+ parentTaskID: 'parent',
106
+ });
107
+ },
108
+ };
109
+
110
+ describe('TasksTable bulk actions', () => {
111
+ testActionSnapshotWithFixtures(fixtures);
112
+ });
@@ -6,8 +6,11 @@ export const minProps = {
6
6
  itemCount: 2,
7
7
  cancelTask: jest.fn(),
8
8
  resumeTask: jest.fn(),
9
- bulkCancel: jest.fn(),
10
- bulkResume: jest.fn(),
9
+ bulkResumeById: jest.fn(),
10
+ bulkCancelById: jest.fn(),
11
+ bulkResumeBySearch: jest.fn(),
12
+ bulkCancelBySearch: jest.fn(),
13
+ selectPage: jest.fn(),
11
14
  selectAllRows: jest.fn(),
12
15
  unselectAllRows: jest.fn(),
13
16
  selectRow: jest.fn(),
@@ -18,7 +21,6 @@ export const minProps = {
18
21
  perPage: 10,
19
22
  },
20
23
  history: { location: { search: '' } },
21
- status: STATUS.RESOLVED,
22
24
  results: ['a', 'b'],
23
25
  sort: {
24
26
  by: 'q',
@@ -0,0 +1,46 @@
1
+ import { convertDashboardQuery } from '../TasksTableActionHelpers';
2
+ import {
3
+ TASKS_DASHBOARD_JS_QUERY_MODES,
4
+ TASKS_DASHBOARD_AVAILABLE_TIMES,
5
+ } from '../../TasksDashboard/TasksDashboardConstants';
6
+
7
+ let realDate;
8
+
9
+ describe('convertDashboardQuery', () => {
10
+ it('convertDashboardQuery should work with full query', () => {
11
+ // Setup
12
+ const currentDate = new Date('2020-05-08T11:01:58.135Z');
13
+ realDate = Date;
14
+ global.Date = class extends Date {
15
+ constructor(date) {
16
+ if (date) {
17
+ // eslint-disable-next-line constructor-super
18
+ return super(date);
19
+ }
20
+ return currentDate;
21
+ }
22
+ };
23
+ const query = {
24
+ time_mode: TASKS_DASHBOARD_JS_QUERY_MODES.RECENT,
25
+ time_horizon: TASKS_DASHBOARD_AVAILABLE_TIMES.WEEK,
26
+ state: 'stopped',
27
+ result: 'error',
28
+ search: 'action~job',
29
+ };
30
+ expect(convertDashboardQuery(query)).toEqual(
31
+ 'state=stopped and result=error and action~job and (state_updated_at>2020-05-01T11:01:58.135Z or state_updated_at = NULL)'
32
+ );
33
+ // Cleanup
34
+ global.Date = realDate;
35
+ });
36
+ it('convertDashboardQuery should work with only search query', () => {
37
+ const query = {
38
+ search: 'action~job',
39
+ };
40
+ expect(convertDashboardQuery(query)).toEqual('action~job');
41
+ });
42
+ it('convertDashboardQuery should work with no query', () => {
43
+ const query = {};
44
+ expect(convertDashboardQuery(query)).toEqual('');
45
+ });
46
+ });
@@ -1,4 +1,7 @@
1
- import { testActionSnapshotWithFixtures } from '@theforeman/test';
1
+ import {
2
+ testActionSnapshotWithFixtures,
3
+ IntegrationTestHelper,
4
+ } from '@theforeman/test';
2
5
  import API from 'foremanReact/API';
3
6
  import { TASKS_TABLE_ID } from '../TasksTableConstants';
4
7
  import {
@@ -7,8 +10,7 @@ import {
7
10
  cancelTaskRequest,
8
11
  resumeTask,
9
12
  resumeTaskRequest,
10
- bulkCancel,
11
- bulkResume,
13
+ selectPage,
12
14
  } from '../TasksTableActions';
13
15
 
14
16
  jest.mock('foremanReact/components/common/table', () => ({
@@ -24,13 +26,7 @@ const taskInfo = {
24
26
  taskName: 'some-name',
25
27
  };
26
28
 
27
- const task = {
28
- id: 'some-id',
29
- name: 'some-name',
30
- };
31
-
32
29
  const fixtures = {
33
- 'should cancelTask': () => cancelTask({ ...taskInfo, url: 'some-url' }),
34
30
  'should cancelTaskRequest and succeed': () =>
35
31
  cancelTaskRequest('some-id', 'some-name'),
36
32
  'should cancelTaskRequest and fail': () => {
@@ -40,7 +36,6 @@ const fixtures = {
40
36
  return cancelTaskRequest('some-id', 'some-name');
41
37
  },
42
38
 
43
- 'should resumeTask': () => resumeTask({ ...taskInfo, url: 'some-url' }),
44
39
  'should resumeTaskRequest and succeed': () => {
45
40
  API.post.mockImplementation(() => ({ data: 'some-data' }));
46
41
  return resumeTaskRequest('some-id', 'some-name');
@@ -51,41 +46,24 @@ const fixtures = {
51
46
  );
52
47
  return resumeTaskRequest('some-id', 'some-name');
53
48
  },
54
- 'handles bulkResume requests that fail': () => {
55
- const selected = [{ ...task, isResumable: true, isCancellable: false }];
56
-
57
- API.post.mockImplementation(() =>
58
- Promise.reject(new Error('Network Error'))
59
- );
60
- return bulkResume({ selected, url: 'some-url' });
61
- },
62
- 'handles resumable bulkResume requests': () => {
63
- const selected = [{ ...task, isResumable: true, isCancellable: false }];
64
-
65
- API.post.mockImplementation(() => ({
66
- data: {
67
- resumed: [{ action: 'I am resumed' }],
68
- failed: [{ action: 'I am failed' }],
69
- },
70
- }));
71
- return bulkResume({ selected, url: 'some-url' });
72
- },
73
- 'handles bulkCancel requests': () => {
74
- const selected = [{ ...task, isResumable: false, isCancellable: true }];
75
- return bulkCancel({ selected, url: 'some-url' });
76
- },
77
- 'handles bulkCancel requests that are not cancellable': () => {
78
- const selected = [{ ...task, isResumable: false, isCancellable: false }];
79
- return bulkCancel({ selected, url: 'some-url' });
80
- },
81
- 'handles bulkResume requests that are not resumable': () => {
82
- const selected = [{ ...task, isResumable: false, isCancellable: false }];
83
- return bulkResume({ selected, url: 'some-url' });
84
- },
49
+ 'should selectPage and succeed': () => selectPage([{ id: 'some-id' }]),
85
50
  };
86
51
  describe('TasksTable actions', () => {
87
52
  it('getTableItems should reuse common/table/getTableItemsAction', () => {
88
53
  expect(getTableItems('')).toEqual(TASKS_TABLE_ID);
89
54
  });
55
+
56
+ it('should resumeTask', async () => {
57
+ const dispatch = jest.fn();
58
+ resumeTask({ ...taskInfo, url: 'some-url' })(dispatch);
59
+ await IntegrationTestHelper.flushAllPromises();
60
+ expect(dispatch.mock.calls).toHaveLength(3);
61
+ });
62
+ it('should cancelTask', async () => {
63
+ const dispatch = jest.fn();
64
+ cancelTask({ ...taskInfo, url: 'some-url' })(dispatch);
65
+ await IntegrationTestHelper.flushAllPromises();
66
+ expect(dispatch.mock.calls).toHaveLength(3);
67
+ });
90
68
  testActionSnapshotWithFixtures(fixtures);
91
69
  });