foreman-tasks 1.0.1 → 2.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (169) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +12 -12
  3. data/.rubocop_todo.yml +34 -116
  4. data/README.md +2 -0
  5. data/app/controllers/foreman_tasks/api/recurring_logics_controller.rb +20 -1
  6. data/app/controllers/foreman_tasks/api/tasks_controller.rb +65 -10
  7. data/app/controllers/foreman_tasks/concerns/hosts_controller_extension.rb +1 -1
  8. data/app/controllers/foreman_tasks/recurring_logics_controller.rb +19 -0
  9. data/app/controllers/foreman_tasks/tasks_controller.rb +9 -14
  10. data/app/helpers/foreman_tasks/foreman_tasks_helper.rb +1 -3
  11. data/app/lib/actions/helpers/humanizer.rb +1 -3
  12. data/app/lib/actions/proxy_action.rb +33 -12
  13. data/app/lib/foreman_tasks/concerns/polling_action_extensions.rb +12 -0
  14. data/app/models/foreman_tasks/concerns/action_triggering.rb +1 -1
  15. data/app/models/foreman_tasks/recurring_logic.rb +1 -0
  16. data/app/models/foreman_tasks/remote_task.rb +1 -0
  17. data/app/models/foreman_tasks/task.rb +8 -0
  18. data/app/models/foreman_tasks/task/dynflow_task.rb +2 -1
  19. data/app/models/foreman_tasks/task/search.rb +11 -1
  20. data/app/models/setting/foreman_tasks.rb +7 -2
  21. data/app/services/foreman_tasks/troubleshooting_help_generator.rb +0 -4
  22. data/app/services/ui_notifications/tasks/task_bulk_cancel.rb +36 -0
  23. data/app/services/ui_notifications/tasks/task_bulk_resume.rb +38 -0
  24. data/app/services/ui_notifications/tasks/task_bulk_stop.rb +36 -0
  25. data/app/views/foreman_tasks/api/recurring_logics/base.json.rabl +2 -1
  26. data/app/views/foreman_tasks/api/tasks/details.json.rabl +1 -1
  27. data/app/views/foreman_tasks/api/tasks/show.json.rabl +1 -1
  28. data/app/views/foreman_tasks/recurring_logics/index.html.erb +30 -0
  29. data/app/views/foreman_tasks/tasks/show.html.erb +3 -0
  30. data/config/routes.rb +8 -0
  31. data/db/migrate/20200517215015_rename_bookmarks_controller.rb +35 -0
  32. data/db/migrate/20200519093217_drop_dynflow_allow_dangerous_actions_setting.foreman_tasks.rb +5 -0
  33. data/db/migrate/20200611090846_add_task_lock_index_on_resource_type_and_task_id.rb +9 -0
  34. data/db/seeds.d/30-notification_blueprints.rb +21 -0
  35. data/foreman-tasks.gemspec +5 -6
  36. data/gemfile.d/foreman-tasks.rb +1 -0
  37. data/lib/foreman_tasks/dynflow/console_authorizer.rb +2 -2
  38. data/lib/foreman_tasks/engine.rb +17 -19
  39. data/lib/foreman_tasks/tasks/cleanup.rake +1 -1
  40. data/lib/foreman_tasks/tasks/export_tasks.rake +2 -2
  41. data/lib/foreman_tasks/test_extensions.rb +1 -1
  42. data/lib/foreman_tasks/version.rb +1 -1
  43. data/locale/action_names.rb +2 -2
  44. data/locale/en/LC_MESSAGES/foreman_tasks.mo +0 -0
  45. data/locale/en/foreman_tasks.po +270 -54
  46. data/locale/foreman_tasks.pot +630 -292
  47. data/locale/fr/LC_MESSAGES/foreman_tasks.mo +0 -0
  48. data/locale/fr/foreman_tasks.po +817 -0
  49. data/locale/ja/LC_MESSAGES/foreman_tasks.mo +0 -0
  50. data/locale/ja/foreman_tasks.po +817 -0
  51. data/locale/zh_CN/LC_MESSAGES/foreman_tasks.mo +0 -0
  52. data/locale/zh_CN/foreman_tasks.po +816 -0
  53. data/package.json +1 -2
  54. data/script/rails +2 -2
  55. data/script/travis_run_js_tests.sh +2 -2
  56. data/test/factories/task_factory.rb +34 -2
  57. data/test/foreman_tasks_test_helper.rb +4 -0
  58. data/test/lib/concerns/polling_action_extensions_test.rb +34 -0
  59. data/test/unit/actions/action_with_sub_plans_test.rb +1 -1
  60. data/test/unit/task_test.rb +160 -74
  61. data/webpack/ForemanTasks/Components/TaskActions/TaskAction.test.js +60 -0
  62. data/webpack/ForemanTasks/Components/TaskActions/TaskActionHelpers.js +67 -0
  63. data/webpack/ForemanTasks/Components/TaskActions/TaskActionHelpers.test.js +46 -0
  64. data/webpack/ForemanTasks/Components/TaskActions/TaskActionsConstants.js +16 -0
  65. data/webpack/ForemanTasks/Components/TaskActions/UnlockModals.js +60 -0
  66. data/webpack/ForemanTasks/Components/TaskActions/UnlockModals.test.js +14 -0
  67. data/webpack/ForemanTasks/Components/TaskActions/__snapshots__/TaskAction.test.js.snap +233 -0
  68. data/webpack/ForemanTasks/Components/TaskActions/__snapshots__/UnlockModals.test.js.snap +25 -0
  69. data/webpack/ForemanTasks/Components/TaskActions/index.js +115 -0
  70. data/webpack/ForemanTasks/Components/TaskDetails/Components/RunningSteps.js +17 -3
  71. data/webpack/ForemanTasks/Components/TaskDetails/Components/Task.js +132 -165
  72. data/webpack/ForemanTasks/Components/TaskDetails/Components/TaskInfo.js +3 -12
  73. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/RunningSteps.test.js +8 -1
  74. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/Task.test.js +68 -3
  75. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/TaskInfo.test.js +0 -1
  76. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/__snapshots__/RunningSteps.test.js.snap +1 -1
  77. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/__snapshots__/Task.test.js.snap +108 -75
  78. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/__snapshots__/TaskInfo.test.js.snap +3 -9
  79. data/webpack/ForemanTasks/Components/TaskDetails/TaskDetails.js +35 -5
  80. data/webpack/ForemanTasks/Components/TaskDetails/TaskDetailsActions.js +34 -14
  81. data/webpack/ForemanTasks/Components/TaskDetails/TaskDetailsConstants.js +3 -4
  82. data/webpack/ForemanTasks/Components/TaskDetails/TaskDetailsReducer.js +0 -6
  83. data/webpack/ForemanTasks/Components/TaskDetails/TaskDetailsSelectors.js +4 -10
  84. data/webpack/ForemanTasks/Components/TaskDetails/TasksDetailsHelper.js +6 -1
  85. data/webpack/ForemanTasks/Components/TaskDetails/__tests__/TaskDetails.fixtures.js +8 -0
  86. data/webpack/ForemanTasks/Components/TaskDetails/__tests__/TaskDetails.test.js +7 -1
  87. data/webpack/ForemanTasks/Components/TaskDetails/__tests__/TaskDetailsActions.test.js +18 -2
  88. data/webpack/ForemanTasks/Components/TaskDetails/__tests__/__snapshots__/TaskDetails.test.js.snap +30 -13
  89. data/webpack/ForemanTasks/Components/TaskDetails/__tests__/__snapshots__/TaskDetailsActions.test.js.snap +91 -0
  90. data/webpack/ForemanTasks/Components/TaskDetails/__tests__/integration.test.js +13 -4
  91. data/webpack/ForemanTasks/Components/TaskDetails/index.js +6 -8
  92. data/webpack/ForemanTasks/Components/TasksDashboard/TasksDashboardActions.js +1 -1
  93. data/webpack/ForemanTasks/Components/TasksDashboard/TasksDashboardConstants.js +5 -0
  94. data/webpack/ForemanTasks/Components/TasksDashboard/TasksDashboardHelper.js +3 -2
  95. data/webpack/ForemanTasks/Components/TasksDashboard/__tests__/TasksDashboardActions.test.js +2 -2
  96. data/webpack/ForemanTasks/Components/TasksTable/Components/ActionSelectButton.js +14 -1
  97. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/ConfirmModal.js +83 -0
  98. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/ConfirmModalActions.js +106 -0
  99. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/ConfirmModalReducer.js +38 -0
  100. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/ConfirmModalSelectors.js +45 -0
  101. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/ConfirmModal.test.js +36 -0
  102. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/ConfirmModalActions.test.js +205 -0
  103. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/ConfirmModalReducer.test.js +27 -0
  104. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/ConfirmModalSelectors.test.js +54 -0
  105. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/__snapshots__/ConfirmModal.test.js.snap +41 -0
  106. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/__snapshots__/ConfirmModalReducer.test.js.snap +19 -0
  107. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/__snapshots__/ConfirmModalSelectors.test.js.snap +30 -0
  108. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/index.js +29 -0
  109. data/webpack/ForemanTasks/Components/TasksTable/Components/SelectAllAlert.js +43 -0
  110. data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/ActionSelectButton.test.js +1 -0
  111. data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/SelectAllAlert.test.js +29 -0
  112. data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/__snapshots__/ActionSelectButton.test.js.snap +11 -0
  113. data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/__snapshots__/SelectAllAlert.test.js.snap +75 -0
  114. data/webpack/ForemanTasks/Components/TasksTable/SubTasksPage.js +4 -1
  115. data/webpack/ForemanTasks/Components/TasksTable/TasksBulkActions.js +247 -0
  116. data/webpack/ForemanTasks/Components/TasksTable/TasksTable.js +37 -19
  117. data/webpack/ForemanTasks/Components/TasksTable/TasksTableActions.js +56 -92
  118. data/webpack/ForemanTasks/Components/TasksTable/TasksTableConstants.js +19 -11
  119. data/webpack/ForemanTasks/Components/TasksTable/TasksTableHelpers.js +4 -3
  120. data/webpack/ForemanTasks/Components/TasksTable/TasksTablePage.js +64 -73
  121. data/webpack/ForemanTasks/Components/TasksTable/TasksTableReducer.js +21 -2
  122. data/webpack/ForemanTasks/Components/TasksTable/TasksTableSchema.js +2 -2
  123. data/webpack/ForemanTasks/Components/TasksTable/TasksTableSelectors.js +13 -4
  124. data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksBulkActions.test.js +147 -0
  125. data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksTable.fixtures.js +3 -10
  126. data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksTableActions.test.js +46 -74
  127. data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksTableHelpers.test.js +17 -1
  128. data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksTablePage.test.js +9 -1
  129. data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksTableReducer.test.js +22 -1
  130. data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/SubTasksPage.test.js.snap +4 -12
  131. data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksBulkActions.test.js.snap +336 -0
  132. data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksIndexPage.test.js.snap +3 -12
  133. data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksTableActions.test.js.snap +22 -158
  134. data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksTablePage.test.js.snap +56 -132
  135. data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksTableReducer.test.js.snap +34 -0
  136. data/webpack/ForemanTasks/Components/TasksTable/formatters/__test__/selectionHeaderCellFormatter.test.js +1 -1
  137. data/webpack/ForemanTasks/Components/TasksTable/formatters/selectionHeaderCellFormatter.js +2 -2
  138. data/webpack/ForemanTasks/Components/TasksTable/index.js +10 -4
  139. data/webpack/ForemanTasks/Components/common/ActionButtons/ActionButton.js +47 -19
  140. data/webpack/ForemanTasks/Components/common/ActionButtons/ActionButton.test.js +61 -14
  141. data/webpack/ForemanTasks/Components/common/ActionButtons/__snapshots__/ActionButton.test.js.snap +80 -21
  142. data/webpack/ForemanTasks/Components/common/ClickConfirmation/ClickConfirmation.scss +9 -0
  143. data/webpack/ForemanTasks/Components/common/ClickConfirmation/ClickConfirmation.test.js +44 -0
  144. data/webpack/ForemanTasks/Components/common/ClickConfirmation/__snapshots__/ClickConfirmation.test.js.snap +52 -0
  145. data/webpack/ForemanTasks/Components/common/ClickConfirmation/index.js +59 -66
  146. data/webpack/ForemanTasks/Components/common/ToastsHelpers/ToastTypesConstants.js +11 -0
  147. data/webpack/ForemanTasks/Components/common/ToastsHelpers/index.js +15 -0
  148. data/webpack/ForemanTasks/ForemanTasksReducers.js +2 -0
  149. data/webpack/ForemanTasks/Routes/ForemanTasksRoutes.test.js +2 -1
  150. data/webpack/__mocks__/foremanReact/components/ForemanModal/ForemanModalHooks.js +2 -2
  151. data/webpack/__mocks__/foremanReact/components/ForemanModal/index.js +17 -3
  152. data/webpack/__mocks__/foremanReact/components/common/ActionButtons/ActionButtons.js +3 -0
  153. data/webpack/__mocks__/foremanReact/{API.js → redux/API.js} +1 -1
  154. metadata +76 -27
  155. data/webpack/ForemanTasks/Components/TasksTable/Components/CancelConfirm.js +0 -53
  156. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmationModals.js +0 -56
  157. data/webpack/ForemanTasks/Components/TasksTable/Components/ResumeConfirm.js +0 -52
  158. data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/CancelConfirm.test.js +0 -26
  159. data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/ConfirmationModals.test.js +0 -24
  160. data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/ResumeConfirm.test.js +0 -26
  161. data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/__snapshots__/CancelConfirm.test.js.snap +0 -65
  162. data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/__snapshots__/ConfirmationModals.test.js.snap +0 -30
  163. data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/__snapshots__/ResumeConfirm.test.js.snap +0 -63
  164. data/webpack/ForemanTasks/Components/common/ActionButtons/CancelButton.js +0 -23
  165. data/webpack/ForemanTasks/Components/common/ActionButtons/CancelButton.test.js +0 -26
  166. data/webpack/ForemanTasks/Components/common/ActionButtons/ResumeButton.js +0 -23
  167. data/webpack/ForemanTasks/Components/common/ActionButtons/ResumeButton.test.js +0 -27
  168. data/webpack/ForemanTasks/Components/common/ActionButtons/__snapshots__/CancelButton.test.js.snap +0 -15
  169. data/webpack/ForemanTasks/Components/common/ActionButtons/__snapshots__/ResumeButton.test.js.snap +0 -15
@@ -67,7 +67,7 @@ const createTasksTableSchema = (
67
67
  sortableColumn('started_at', __('Started at'), 3, sortController, [
68
68
  dateCellFormmatter,
69
69
  ]),
70
- sortableColumn('duration', __('Duration'), 3, sortController, [
70
+ sortableColumn('duration', __('Duration'), 2, sortController, [
71
71
  durationCellFormmatter,
72
72
  ]),
73
73
  column(
@@ -76,7 +76,7 @@ const createTasksTableSchema = (
76
76
  headFormat,
77
77
  [actionCellFormatter(taskActions)],
78
78
  {
79
- className: 'col-md-1',
79
+ className: 'col-md-2',
80
80
  }
81
81
  ),
82
82
  ];
@@ -24,9 +24,6 @@ export const selectActionName = state =>
24
24
  export const selectSelectedRows = state =>
25
25
  selectTasksTableQuery(state).selectedRows || [];
26
26
 
27
- export const selectClicked = state =>
28
- selectTasksTableQuery(state).clicked || {};
29
-
30
27
  export const selectResults = createSelector(
31
28
  selectTasksTableContent,
32
29
  ({ results }) =>
@@ -38,7 +35,10 @@ export const selectResults = createSelector(
38
35
  username: result.username || '',
39
36
  state: result.state + (result.frozen ? ` ${__('Disabled')}` : ''),
40
37
  duration: getDuration(result.started_at, result.ended_at),
41
- availableActions: result.available_actions,
38
+ availableActions: {
39
+ ...result.available_actions,
40
+ stoppable: result.state !== 'stopped',
41
+ },
42
42
  }))
43
43
  );
44
44
 
@@ -48,3 +48,12 @@ 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;
57
+
58
+ export const selectModalID = state =>
59
+ selectTasksTableQuery(state).modalID || '';
@@ -0,0 +1,147 @@
1
+ import { testActionSnapshotWithFixtures } from '@theforeman/test';
2
+ import { API } from 'foremanReact/redux/API';
3
+ import {
4
+ bulkCancelById,
5
+ bulkCancelBySearch,
6
+ bulkResumeById,
7
+ bulkResumeBySearch,
8
+ bulkForceCancelById,
9
+ bulkForceCancelBySearch,
10
+ } from '../TasksBulkActions';
11
+
12
+ jest.mock('foremanReact/components/common/table', () => ({
13
+ getTableItemsAction: jest.fn(controller => controller),
14
+ }));
15
+
16
+ jest.mock('foremanReact/redux/API');
17
+
18
+ const task = {
19
+ id: 'some-id',
20
+ name: 'some-name',
21
+ };
22
+
23
+ const fixtures = {
24
+ 'handles bulkResumeById requests that fail': () => {
25
+ const selected = [{ ...task, isResumable: true }];
26
+
27
+ API.post.mockImplementation(() =>
28
+ Promise.reject(new Error('Network Error'))
29
+ );
30
+ return bulkResumeById({ selected, url: 'some-url' });
31
+ },
32
+ 'handles resumable bulkResumeById requests': () => {
33
+ const selected = [{ ...task, isResumable: true }];
34
+
35
+ API.post.mockImplementation(() => ({
36
+ data: {
37
+ resumed: [{ action: 'I am resumed' }],
38
+ failed: [{ action: 'I am failed' }],
39
+ },
40
+ }));
41
+ return bulkResumeById({ selected, url: 'some-url' });
42
+ },
43
+ 'handles bulkCancelById requests': () => {
44
+ const selected = [{ ...task, isCancellable: true }];
45
+
46
+ API.post.mockImplementation(() => ({
47
+ data: {
48
+ cancelled: [{ action: 'I am cancelled' }],
49
+ },
50
+ }));
51
+ return bulkCancelById({ selected, url: 'some-url' });
52
+ },
53
+ 'handles skipped bulkResumeById requests': () => {
54
+ const selected = [{ ...task, isResumable: true }];
55
+
56
+ API.post.mockImplementation(() => ({
57
+ data: {
58
+ skipped: [{ action: 'I am skipped' }],
59
+ },
60
+ }));
61
+ return bulkResumeById({ selected, url: 'some-url' });
62
+ },
63
+ 'handles skipped bulkCancelById requests': () => {
64
+ const selected = [{ ...task, isCancellable: true }];
65
+
66
+ API.post.mockImplementation(() => ({
67
+ data: {
68
+ skipped: [{ action: 'I am skipped' }],
69
+ },
70
+ }));
71
+ return bulkCancelById({ selected, url: 'some-url' });
72
+ },
73
+
74
+ 'handles bulkForceCancelById requests': () => {
75
+ const selected = [{ ...task, isCancellable: true }];
76
+
77
+ API.post.mockImplementation(() => ({
78
+ data: {
79
+ stopped_length: 2,
80
+ skipped_length: 4,
81
+ },
82
+ }));
83
+ return bulkForceCancelById({ selected, url: 'some-url' });
84
+ },
85
+
86
+ 'handles bulkForceCancelById requests that fail': () => {
87
+ const selected = [{ ...task, isResumable: true }];
88
+
89
+ API.post.mockImplementation(() =>
90
+ Promise.reject(new Error('Network Error'))
91
+ );
92
+ return bulkForceCancelById({ selected, url: 'some-url' });
93
+ },
94
+
95
+ 'handles bulkCancelById requests that are not cancellable': () => {
96
+ const selected = [{ ...task, isCancellable: false }];
97
+ return bulkCancelById({ selected, url: 'some-url' });
98
+ },
99
+ 'handles bulkResumeById requests that are not resumable': () => {
100
+ const selected = [{ ...task, isResumable: false, isCancellable: false }];
101
+ return bulkResumeById({ selected, url: 'some-url' });
102
+ },
103
+
104
+ 'handles bulkForceCancelById requests that are stopped': () => {
105
+ const selected = [{ ...task, isResumable: false, state: 'stopped' }];
106
+ return bulkForceCancelById({ selected, url: 'some-url' });
107
+ },
108
+
109
+ 'handles bulkCancelBySearch requests': () => {
110
+ API.post.mockImplementation(() => ({
111
+ data: {
112
+ cancelled: [{ action: 'I am cancelled' }],
113
+ skipped: [{ action: 'I am skipped' }],
114
+ },
115
+ }));
116
+ return bulkCancelBySearch({
117
+ query: { search: {} },
118
+ url: 'some-url',
119
+ parentTaskID: 'parent',
120
+ });
121
+ },
122
+
123
+ 'handles bulkResumeBySearch requests': () => {
124
+ API.post.mockImplementation(() => ({
125
+ data: {
126
+ cancelled: [{ action: 'I am cancelled' }],
127
+ skipped: [{ action: 'I am skipped' }],
128
+ failed: [{ action: 'I am failed' }],
129
+ },
130
+ }));
131
+ return bulkResumeBySearch({
132
+ query: { search: {} },
133
+ url: 'some-url',
134
+ parentTaskID: 'parent',
135
+ });
136
+ },
137
+ 'handles bulkForceCancelBySearch requests': () =>
138
+ bulkForceCancelBySearch({
139
+ query: { search: {} },
140
+ url: 'some-url',
141
+ parentTaskID: 'parent',
142
+ }),
143
+ };
144
+
145
+ describe('TasksTable bulk actions', () => {
146
+ testActionSnapshotWithFixtures(fixtures);
147
+ });
@@ -4,9 +4,7 @@ export const minProps = {
4
4
  getTableItems: jest.fn(),
5
5
  getBreadcrumbs: jest.fn(),
6
6
  itemCount: 2,
7
- cancelTask: jest.fn(),
8
- resumeTask: jest.fn(),
9
- actionSelected: jest.fn(),
7
+ selectPage: jest.fn(),
10
8
  selectAllRows: jest.fn(),
11
9
  unselectAllRows: jest.fn(),
12
10
  selectRow: jest.fn(),
@@ -17,19 +15,14 @@ export const minProps = {
17
15
  perPage: 10,
18
16
  },
19
17
  history: { location: { search: '' } },
20
- status: STATUS.RESOLVED,
21
18
  results: ['a', 'b'],
22
19
  sort: {
23
20
  by: 'q',
24
21
  order: 'w',
25
22
  },
26
23
  openClickedModal: jest.fn(),
27
- modalProps: {
28
- cancelSelectedModal: {},
29
- resumeSelectedModal: {},
30
- cancelModal: {},
31
- resumeModal: {},
32
- },
24
+ openModalAction: jest.fn(),
25
+ openModal: jest.fn(),
33
26
  };
34
27
 
35
28
  export default {
@@ -1,93 +1,65 @@
1
- import { testActionSnapshotWithFixtures } from '@theforeman/test';
2
- import API from 'foremanReact/API';
3
- import { TASKS_TABLE_ID, CANCEL, RESUME } from '../TasksTableConstants';
1
+ import {
2
+ testActionSnapshotWithFixtures,
3
+ IntegrationTestHelper,
4
+ } from '@theforeman/test';
5
+ import { TASKS_TABLE_ID } from '../TasksTableConstants';
4
6
  import {
5
7
  getTableItems,
6
8
  cancelTask,
7
- cancelTaskRequest,
8
9
  resumeTask,
9
- resumeTaskRequest,
10
- actionSelected,
10
+ forceCancelTask,
11
+ selectPage,
12
+ openClickedModal,
13
+ openModalAction,
11
14
  } from '../TasksTableActions';
12
15
 
13
16
  jest.mock('foremanReact/components/common/table', () => ({
14
17
  getTableItemsAction: jest.fn(controller => controller),
15
18
  }));
16
19
 
17
- jest.mock('foremanReact/API');
18
-
19
- API.post.mockImplementation(() => ({ data: 'some-data' }));
20
+ const taskInfo = {
21
+ taskId: 'some-id',
22
+ taskName: 'some-name',
23
+ };
20
24
 
21
25
  const fixtures = {
22
- 'should cancelTask': () => cancelTask('some-id', 'some-name', 'some-url'),
23
- 'should cancelTaskRequest and succeed': () =>
24
- cancelTaskRequest('some-id', 'some-name', 'some-url'),
25
- 'should cancelTaskRequest and fail': () => {
26
- API.post.mockImplementation(() =>
27
- Promise.reject(new Error('Network Error'))
28
- );
29
- return cancelTaskRequest('some-id', 'some-name');
30
- },
31
-
32
- 'should resumeTask': () => resumeTask('some-id', 'some-name', 'some-url'),
33
- 'should resumeTaskRequest and succeed': () => {
34
- API.post.mockImplementation(() => ({ data: 'some-data' }));
35
- return resumeTaskRequest('some-id', 'some-name', 'some-url');
36
- },
37
- 'should resumeTaskRequest and fail': () => {
38
- API.post.mockImplementation(() =>
39
- Promise.reject(new Error('Network Error'))
40
- );
41
- return resumeTaskRequest('some-id', 'some-name', 'some-url');
42
- },
43
- 'should actionSelected CANCEL not cancelleble': () => {
44
- const selected = [
45
- {
46
- id: '',
47
- name: '',
48
- isResumeble: false,
49
- isCancelleble: false,
50
- },
51
- ];
52
- return actionSelected(CANCEL, selected, 'some-url');
53
- },
54
- 'should actionSelected CANCEL cancelleble': () => {
55
- const selected = [
56
- {
57
- id: '',
58
- name: '',
59
- isResumeble: false,
60
- isCancelleble: true,
61
- },
62
- ];
63
- return actionSelected(CANCEL, selected, 'some-url');
64
- },
65
- 'should actionSelected RESUME not resumable': () => {
66
- const selected = [
67
- {
68
- id: '',
69
- name: '',
70
- isResumeble: false,
71
- isCancelleble: false,
72
- },
73
- ];
74
- return actionSelected(RESUME, selected, 'some-url');
75
- },
76
- 'should actionSelected RESUME resumable': () => {
77
- const selected = [
78
- {
79
- id: '',
80
- name: '',
81
- isResumeble: true,
82
- isCancelleble: false,
83
- },
84
- ];
85
- return actionSelected(RESUME, selected, 'some-url');
86
- },
26
+ 'should selectPage and succeed': () => selectPage([{ id: 'some-id' }]),
27
+ 'handles openClickedModal': () =>
28
+ openClickedModal({ ...taskInfo, setModalOpen: jest.fn() }),
29
+ 'handles openModalAction': () => openModalAction('some-modal-id', jest.fn()),
87
30
  };
88
31
  describe('TasksTable actions', () => {
89
32
  it('getTableItems should reuse common/table/getTableItemsAction', () => {
90
33
  expect(getTableItems('')).toEqual(TASKS_TABLE_ID);
91
34
  });
35
+
36
+ it('should resumeTask', async () => {
37
+ const dispatch = jest.fn();
38
+ resumeTask({ ...taskInfo, url: 'some-url' })(dispatch);
39
+ await IntegrationTestHelper.flushAllPromises();
40
+ expect(dispatch.mock.calls).toHaveLength(3);
41
+ });
42
+ it('should cancelTask', async () => {
43
+ const dispatch = jest.fn();
44
+ cancelTask({ ...taskInfo, url: 'some-url' })(dispatch);
45
+ await IntegrationTestHelper.flushAllPromises();
46
+ expect(dispatch.mock.calls).toHaveLength(3);
47
+ });
48
+ it('should forceCancelTask', async () => {
49
+ const dispatch = jest.fn();
50
+ forceCancelTask({ ...taskInfo, url: 'some-url' })(dispatch);
51
+ await IntegrationTestHelper.flushAllPromises();
52
+ expect(dispatch.mock.calls).toHaveLength(3);
53
+ });
54
+ it('openClickedModal opens modal', () => {
55
+ const setModalOpen = jest.fn();
56
+ openClickedModal({ ...taskInfo, setModalOpen });
57
+ expect(setModalOpen).toHaveBeenCalled();
58
+ });
59
+ it('openModalAction opens modal', () => {
60
+ const setModalOpen = jest.fn();
61
+ openModalAction('some-modal-id', setModalOpen);
62
+ expect(setModalOpen).toHaveBeenCalled();
63
+ });
92
64
  testActionSnapshotWithFixtures(fixtures);
93
65
  });
@@ -1,4 +1,4 @@
1
- import { updateURlQuery, getDuration } from '../TasksTableHelpers';
1
+ import { updateURlQuery, getDuration, getCSVurl } from '../TasksTableHelpers';
2
2
 
3
3
  describe('updateURlQuery', () => {
4
4
  it('should use url with new query', () => {
@@ -26,3 +26,19 @@ describe('updateURlQuery', () => {
26
26
  expect(duration.tooltip).toEqual('Task was canceled');
27
27
  });
28
28
  });
29
+
30
+ describe('getCSVurl', () => {
31
+ it('should return currect url for tasks with search', () => {
32
+ const url = '/foreman_tasks/tasks';
33
+ const query = { state: 'stopped' };
34
+ expect(getCSVurl(url, query)).toEqual(
35
+ '/foreman_tasks/tasks.csv?state=stopped'
36
+ );
37
+ });
38
+ it('should return currect url for subtasks', () => {
39
+ const url = '/foreman_tasks/tasks/some-id/sub_tasks';
40
+ expect(getCSVurl(url, {})).toEqual(
41
+ '/foreman_tasks/tasks/some-id/sub_tasks.csv'
42
+ );
43
+ });
44
+ });
@@ -2,11 +2,19 @@ import { testComponentSnapshotsWithFixtures } from '@theforeman/test';
2
2
  import TasksTablePage from '../TasksTablePage';
3
3
  import { minProps } from './TasksTable.fixtures';
4
4
 
5
+ jest.mock('foremanReact/common/helpers', () => ({
6
+ getURIQuery: () => ({ state: 'stopped' }),
7
+ }));
8
+
9
+ const history = {
10
+ location: { pathname: '/foreman_tasks/tasks', search: '?action="some-name"' },
11
+ };
5
12
  const fixtures = {
6
- 'render with minimal props': minProps,
13
+ 'render with minimal props': { ...minProps, history },
7
14
 
8
15
  'render with Breadcrubs': {
9
16
  ...minProps,
17
+ history,
10
18
  getBreadcrumbs: () => ({
11
19
  breadcrumbItems: [
12
20
  { caption: 'Tasks', url: `/foreman_tasks/tasks` },
@@ -1,3 +1,4 @@
1
+ import Immutable from 'seamless-immutable';
1
2
  import { testReducerSnapshotWithFixtures } from '@theforeman/test';
2
3
  import {
3
4
  TASKS_TABLE_ID,
@@ -7,6 +8,8 @@ import {
7
8
  UNSELECT_ROWS,
8
9
  UNSELECT_ALL_ROWS,
9
10
  UPDATE_CLICKED,
11
+ SELECT_ALL_ROWS,
12
+ OPEN_SELECT_ALL,
10
13
  } from '../TasksTableConstants';
11
14
  import reducer from '../TasksTableReducer';
12
15
 
@@ -44,7 +47,7 @@ const fixtures = {
44
47
  'should handle UNSELECT_ROWS': {
45
48
  action: {
46
49
  type: UNSELECT_ROWS,
47
- payload: 4,
50
+ payload: [{ id: 4 }],
48
51
  },
49
52
  },
50
53
  'should handle UNSELECT_ALL_ROWS': {
@@ -58,6 +61,24 @@ const fixtures = {
58
61
  payload: { clicked: 'task' },
59
62
  },
60
63
  },
64
+ 'should handle SELECT_ALL_ROWS': {
65
+ action: {
66
+ type: SELECT_ALL_ROWS,
67
+ payload: { clicked: 'task' },
68
+ },
69
+ },
70
+ 'should handle OPEN_SELECT_ALL': {
71
+ action: {
72
+ type: OPEN_SELECT_ALL,
73
+ },
74
+ },
75
+ 'should handle UNSELECT_ROWS with all rows selected': {
76
+ state: Immutable({ tasksTableQuery: { allRowsSelected: true } }),
77
+ action: {
78
+ type: UNSELECT_ROWS,
79
+ payload: { id: [4], results: [{ id: 3 }, { id: 4 }, { id: 5 }] },
80
+ },
81
+ },
61
82
  };
62
83
 
63
84
  describe('TasksTableReducer reducer', () =>