foreman-tasks 12.0.0 → 12.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 (166) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby_tests.yml +1 -0
  3. data/app/assets/javascripts/foreman-tasks/locale/de/foreman_tasks.js +58 -22
  4. data/app/assets/javascripts/foreman-tasks/locale/en/foreman_tasks.js +56 -20
  5. data/app/assets/javascripts/foreman-tasks/locale/es/foreman_tasks.js +59 -23
  6. data/app/assets/javascripts/foreman-tasks/locale/fr/foreman_tasks.js +61 -25
  7. data/app/assets/javascripts/foreman-tasks/locale/ja/foreman_tasks.js +61 -25
  8. data/app/assets/javascripts/foreman-tasks/locale/ka/foreman_tasks.js +60 -24
  9. data/app/assets/javascripts/foreman-tasks/locale/ko/foreman_tasks.js +61 -25
  10. data/app/assets/javascripts/foreman-tasks/locale/pt_BR/foreman_tasks.js +59 -23
  11. data/app/assets/javascripts/foreman-tasks/locale/ru/foreman_tasks.js +58 -22
  12. data/app/assets/javascripts/foreman-tasks/locale/zh_CN/foreman_tasks.js +61 -25
  13. data/app/assets/javascripts/foreman-tasks/locale/zh_TW/foreman_tasks.js +57 -21
  14. data/app/controllers/foreman_tasks/api/tasks_controller.rb +4 -19
  15. data/app/controllers/foreman_tasks/tasks_controller.rb +4 -5
  16. data/app/models/foreman_tasks/task.rb +1 -1
  17. data/app/views/foreman_tasks/api/tasks/dependency_summary.json.rabl +1 -3
  18. data/app/views/foreman_tasks/api/tasks/show.json.rabl +4 -1
  19. data/config/routes.rb +3 -3
  20. data/foreman-tasks.gemspec +3 -1
  21. data/lib/foreman_tasks/engine.rb +1 -1
  22. data/lib/foreman_tasks/tasks/export_tasks.rake +1 -1
  23. data/lib/foreman_tasks/version.rb +1 -1
  24. data/locale/de/LC_MESSAGES/foreman_tasks.mo +0 -0
  25. data/locale/de/foreman_tasks.po +59 -23
  26. data/locale/en/LC_MESSAGES/foreman_tasks.mo +0 -0
  27. data/locale/en/foreman_tasks.po +56 -20
  28. data/locale/es/LC_MESSAGES/foreman_tasks.mo +0 -0
  29. data/locale/es/foreman_tasks.po +59 -23
  30. data/locale/foreman_tasks.pot +173 -100
  31. data/locale/fr/LC_MESSAGES/foreman_tasks.mo +0 -0
  32. data/locale/fr/foreman_tasks.po +61 -25
  33. data/locale/ja/LC_MESSAGES/foreman_tasks.mo +0 -0
  34. data/locale/ja/foreman_tasks.po +61 -25
  35. data/locale/ka/LC_MESSAGES/foreman_tasks.mo +0 -0
  36. data/locale/ka/foreman_tasks.po +60 -24
  37. data/locale/ko/LC_MESSAGES/foreman_tasks.mo +0 -0
  38. data/locale/ko/foreman_tasks.po +61 -25
  39. data/locale/pt_BR/LC_MESSAGES/foreman_tasks.mo +0 -0
  40. data/locale/pt_BR/foreman_tasks.po +59 -23
  41. data/locale/ru/LC_MESSAGES/foreman_tasks.mo +0 -0
  42. data/locale/ru/foreman_tasks.po +58 -22
  43. data/locale/zh_CN/LC_MESSAGES/foreman_tasks.mo +0 -0
  44. data/locale/zh_CN/foreman_tasks.po +61 -25
  45. data/locale/zh_TW/LC_MESSAGES/foreman_tasks.mo +0 -0
  46. data/locale/zh_TW/foreman_tasks.po +57 -21
  47. data/test/controllers/api/tasks_controller_test.rb +29 -3
  48. data/test/controllers/tasks_controller_test.rb +46 -2
  49. data/webpack/ForemanTasks/Components/TaskActions/TaskAction.test.js +8 -0
  50. data/webpack/ForemanTasks/Components/TaskActions/TaskActionHelpers.js +8 -2
  51. data/webpack/ForemanTasks/Components/TaskActions/TaskActionHelpers.test.js +25 -33
  52. data/webpack/ForemanTasks/Components/TaskActions/index.js +24 -3
  53. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/__snapshots__/TaskInfo.test.js.snap +6 -6
  54. data/webpack/ForemanTasks/Components/TaskDetails/__tests__/TaskDetailsActions.test.js +9 -0
  55. data/webpack/ForemanTasks/Components/TaskDetails/__tests__/__snapshots__/TaskDetailsActions.test.js.snap +16 -11
  56. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksTimeRow/TasksTimeRow.js +2 -3
  57. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksTimeRow/__snapshots__/TasksTimeRow.test.js.snap +4 -8
  58. data/webpack/ForemanTasks/Components/TasksDashboard/TasksDashboard.js +2 -4
  59. data/webpack/ForemanTasks/Components/TasksDashboard/TasksDashboard.scss +0 -3
  60. data/webpack/ForemanTasks/Components/TasksDashboard/__tests__/__snapshots__/TasksDashboard.test.js.snap +2 -5
  61. data/webpack/ForemanTasks/Components/{common/ActionButtons/ActionButton.js → TasksTable/Components/CellActionButton.js} +36 -21
  62. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/index.test.js +32 -29
  63. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/createBulkTaskModal.js +14 -18
  64. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/createTaskModal.js +13 -15
  65. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/index.js +7 -7
  66. data/webpack/ForemanTasks/Components/TasksTable/TasksBulkActions.js +16 -23
  67. data/webpack/ForemanTasks/Components/TasksTable/TasksColumns.js +56 -0
  68. data/webpack/ForemanTasks/Components/TasksTable/TasksIndexPage.js +277 -3
  69. data/webpack/ForemanTasks/Components/TasksTable/TasksModals.js +96 -0
  70. data/webpack/ForemanTasks/Components/TasksTable/TasksTableConstants.js +10 -18
  71. data/webpack/ForemanTasks/Components/TasksTable/TasksTableHelpers.js +3 -3
  72. data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksBulkActions.test.js +130 -63
  73. data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksIndexPage.test.js +315 -8
  74. data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksTable.fixtures.js +214 -41
  75. data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksTableHelpers.test.js +20 -12
  76. data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksBulkActions.test.js.snap +18 -35
  77. data/webpack/ForemanTasks/ForemanTasksReducers.js +0 -4
  78. data/webpack/Routes/routes.js +22 -0
  79. data/webpack/Routes/routes.test.js +95 -0
  80. data/webpack/global_index.js +10 -0
  81. data/webpack/index.js +0 -18
  82. data/webpack/test_setup.js +1 -0
  83. metadata +15 -89
  84. data/app/controllers/foreman_tasks/react_controller.rb +0 -17
  85. data/app/views/foreman_tasks/layouts/react.html.erb +0 -13
  86. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/ConfirmModalSelectors.js +0 -30
  87. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/ConfirmModalSelectors.test.js +0 -66
  88. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/__snapshots__/ConfirmModalSelectors.test.js.snap +0 -33
  89. data/webpack/ForemanTasks/Components/TasksTable/Components/SelectAllAlert.js +0 -49
  90. data/webpack/ForemanTasks/Components/TasksTable/Components/TableSelectionCell.js +0 -32
  91. data/webpack/ForemanTasks/Components/TasksTable/Components/TableSelectionHeaderCell.js +0 -38
  92. data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/SelectAllAlert.test.js +0 -29
  93. data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/TableSelectionCell.test.js +0 -15
  94. data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/TableSelectionHeaderCell.test.js +0 -15
  95. data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/__snapshots__/SelectAllAlert.test.js.snap +0 -81
  96. data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/__snapshots__/TableSelectionCell.test.js.snap +0 -14
  97. data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/__snapshots__/TableSelectionHeaderCell.test.js.snap +0 -15
  98. data/webpack/ForemanTasks/Components/TasksTable/SubTasksPage.js +0 -40
  99. data/webpack/ForemanTasks/Components/TasksTable/TasksTable.js +0 -163
  100. data/webpack/ForemanTasks/Components/TasksTable/TasksTableActions.js +0 -108
  101. data/webpack/ForemanTasks/Components/TasksTable/TasksTablePage.js +0 -234
  102. data/webpack/ForemanTasks/Components/TasksTable/TasksTablePage.scss +0 -20
  103. data/webpack/ForemanTasks/Components/TasksTable/TasksTableReducer.js +0 -68
  104. data/webpack/ForemanTasks/Components/TasksTable/TasksTableSchema.js +0 -85
  105. data/webpack/ForemanTasks/Components/TasksTable/TasksTableSelectors.js +0 -63
  106. data/webpack/ForemanTasks/Components/TasksTable/__tests__/SubTasksPage.test.js +0 -20
  107. data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksTable.test.js +0 -9
  108. data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksTableActions.test.js +0 -65
  109. data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksTablePage.test.js +0 -35
  110. data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksTableReducer.test.js +0 -87
  111. data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/SubTasksPage.test.js.snap +0 -48
  112. data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksIndexPage.test.js.snap +0 -39
  113. data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksTable.test.js.snap +0 -52
  114. data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksTableActions.test.js.snap +0 -40
  115. data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksTablePage.test.js.snap +0 -368
  116. data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksTableReducer.test.js.snap +0 -116
  117. data/webpack/ForemanTasks/Components/TasksTable/formatters/__test__/__snapshots__/actionCellFormatter.test.js.snap +0 -15
  118. data/webpack/ForemanTasks/Components/TasksTable/formatters/__test__/__snapshots__/actionNameCellFormatter.test.js.snap +0 -10
  119. data/webpack/ForemanTasks/Components/TasksTable/formatters/__test__/__snapshots__/dateCellFormmatter.test.js.snap +0 -9
  120. data/webpack/ForemanTasks/Components/TasksTable/formatters/__test__/__snapshots__/durationCellFormmatter.test.js.snap +0 -18
  121. data/webpack/ForemanTasks/Components/TasksTable/formatters/__test__/__snapshots__/selectionCellFormatter.test.js.snap +0 -12
  122. data/webpack/ForemanTasks/Components/TasksTable/formatters/__test__/__snapshots__/selectionHeaderCellFormatter.test.js.snap +0 -11
  123. data/webpack/ForemanTasks/Components/TasksTable/formatters/__test__/actionCellFormatter.test.js +0 -11
  124. data/webpack/ForemanTasks/Components/TasksTable/formatters/__test__/actionNameCellFormatter.test.js +0 -8
  125. data/webpack/ForemanTasks/Components/TasksTable/formatters/__test__/dateCellFormmatter.test.js +0 -7
  126. data/webpack/ForemanTasks/Components/TasksTable/formatters/__test__/durationCellFormmatter.test.js +0 -12
  127. data/webpack/ForemanTasks/Components/TasksTable/formatters/__test__/selectionCellFormatter.test.js +0 -12
  128. data/webpack/ForemanTasks/Components/TasksTable/formatters/__test__/selectionHeaderCellFormatter.test.js +0 -12
  129. data/webpack/ForemanTasks/Components/TasksTable/formatters/actionCellFormatter.js +0 -19
  130. data/webpack/ForemanTasks/Components/TasksTable/formatters/actionNameCellFormatter.js +0 -9
  131. data/webpack/ForemanTasks/Components/TasksTable/formatters/dateCellFormmatter.js +0 -7
  132. data/webpack/ForemanTasks/Components/TasksTable/formatters/durationCellFormmatter.js +0 -7
  133. data/webpack/ForemanTasks/Components/TasksTable/formatters/index.js +0 -7
  134. data/webpack/ForemanTasks/Components/TasksTable/formatters/selectionCellFormatter.js +0 -17
  135. data/webpack/ForemanTasks/Components/TasksTable/formatters/selectionHeaderCellFormatter.js +0 -11
  136. data/webpack/ForemanTasks/Components/TasksTable/index.js +0 -42
  137. data/webpack/ForemanTasks/Components/common/ActionButtons/ActionButton.test.js +0 -101
  138. data/webpack/ForemanTasks/Components/common/ActionButtons/__snapshots__/ActionButton.test.js.snap +0 -95
  139. data/webpack/ForemanTasks/ForemanTasks.js +0 -11
  140. data/webpack/ForemanTasks/ForemanTasks.test.js +0 -10
  141. data/webpack/ForemanTasks/Routes/ForemanTasksRouter.js +0 -14
  142. data/webpack/ForemanTasks/Routes/ForemanTasksRouter.test.js +0 -26
  143. data/webpack/ForemanTasks/Routes/ForemanTasksRoutes.js +0 -23
  144. data/webpack/ForemanTasks/Routes/ForemanTasksRoutes.test.js +0 -16
  145. data/webpack/ForemanTasks/Routes/__snapshots__/ForemanTasksRouter.test.js.snap +0 -16
  146. data/webpack/ForemanTasks/Routes/__snapshots__/ForemanTasksRoutes.test.js.snap +0 -37
  147. data/webpack/ForemanTasks/__snapshots__/ForemanTasks.test.js.snap +0 -7
  148. data/webpack/ForemanTasks/index.js +0 -1
  149. data/webpack/__mocks__/foremanReact/common/I18n.js +0 -7
  150. data/webpack/__mocks__/foremanReact/common/helpers.js +0 -6
  151. data/webpack/__mocks__/foremanReact/common/urlHelpers.js +0 -1
  152. data/webpack/__mocks__/foremanReact/components/Layout/LayoutActions.js +0 -2
  153. data/webpack/__mocks__/foremanReact/components/Pagination/index.js +0 -2
  154. data/webpack/__mocks__/foremanReact/components/ToastsList/index.js +0 -8
  155. data/webpack/__mocks__/foremanReact/components/common/ActionButtons/ActionButtons.js +0 -3
  156. data/webpack/__mocks__/foremanReact/components/common/MessageBox.js +0 -4
  157. data/webpack/__mocks__/foremanReact/components/common/dates/LongDateTime.js +0 -5
  158. data/webpack/__mocks__/foremanReact/components/common/dates/RelativeDateTime.js +0 -3
  159. data/webpack/__mocks__/foremanReact/components/common/table/actionsHelpers/actionTypeCreator.js +0 -7
  160. data/webpack/__mocks__/foremanReact/components/common/table.js +0 -5
  161. data/webpack/__mocks__/foremanReact/constants.js +0 -24
  162. data/webpack/__mocks__/foremanReact/redux/API/APISelectors.js +0 -10
  163. data/webpack/__mocks__/foremanReact/redux/API/index.js +0 -10
  164. data/webpack/__mocks__/foremanReact/redux/middlewares/IntervalMiddleware.js +0 -5
  165. data/webpack/__mocks__/foremanReact/routes/common/PageLayout/PageLayout.js +0 -10
  166. data/webpack/__mocks__/foremanReact/routes/common/PageLayout/components/ExportButton/ExportButton.js +0 -5
@@ -1,45 +1,218 @@
1
1
  import { STATUS } from 'foremanReact/constants';
2
2
 
3
- export const minProps = {
4
- getTableItems: jest.fn(),
5
- getBreadcrumbs: jest.fn(),
6
- itemCount: 2,
7
- selectPage: jest.fn(),
8
- selectAllRows: jest.fn(),
9
- unselectAllRows: jest.fn(),
10
- selectRow: jest.fn(),
11
- unselectRow: jest.fn(),
12
- reloadPage: jest.fn(),
13
- selectedRows: [],
14
- perPage: 10,
15
- history: { location: { search: '' } },
16
- results: ['a', 'b'],
17
- sort: {
18
- by: 'q',
19
- order: 'w',
20
- },
21
- openClickedModal: jest.fn(),
22
- openModalAction: jest.fn(),
23
- openModal: jest.fn(),
24
- };
25
-
26
- export default {
27
- 'render with minimal Props': {
28
- ...minProps,
29
- },
30
- 'render with no results': {
31
- ...minProps,
32
- results: [],
33
- status: STATUS.RESOLVED,
34
- },
35
- 'render with error Props': {
36
- ...minProps,
37
- results: ['a'],
38
- status: STATUS.ERROR,
39
- },
40
- 'render with loading Props': {
41
- ...minProps,
42
- results: ['a'],
43
- status: STATUS.PENDING,
3
+ export const tasksSuccessResponse = {
4
+ status: STATUS.RESOLVED,
5
+ response: {
6
+ total: 1236,
7
+ subtotal: 1236,
8
+ page: 1,
9
+ per_page: 5,
10
+ search: null,
11
+ can_create: true,
12
+ can_edit: true,
13
+ sort: {
14
+ by: 'started_at',
15
+ order: 'DESC',
16
+ },
17
+ results: [
18
+ {
19
+ id: '0cf9deae-e5d9-44b6-a09a-abe59ac842b6',
20
+ label: 'Actions::RemoteExecution::RunHostsJob',
21
+ pending: false,
22
+ action: '»»Run hosts job««:',
23
+ username: 'admin',
24
+ started_at: null,
25
+ ended_at: '2025-01-28 12:00:10 +0000',
26
+ duration: '0',
27
+ state: 'stopped',
28
+ result: 'error',
29
+ progress: 1,
30
+ input: {},
31
+ output: {},
32
+ humanized: {
33
+ action: '»»Run hosts job««:',
34
+ input: '',
35
+ output: null,
36
+ errors: [
37
+ 'undefined method `template_inputs_with_foreign\' for #<JobTemplate id: 192, name: "Demo template", template: "<%= input(\\"command\\") %>\\n<%= input(\\"search\\") %>", snippet: false, template_kind_id: nil, created_at: "2024-12-10 16:29:15.574825000 +0000", updated_at: "2025-01-24 18:07:07.794425000 +0000", locked: false, default: false, vendor: nil, type: "JobTemplate", os_family: nil, description: "", job_category: "Commands", provider_type: "script", description_format: "Run %{command}", execution_timeout_interval: nil, cloned_from_id: nil, ansible_callback_enabled: false>\nDid you mean? template_inputs',
38
+ ],
39
+ },
40
+ cli_example: null,
41
+ start_at: '2025-01-28 12:00:10 +0000',
42
+ can_edit: true,
43
+ can_delete: true,
44
+ available_actions: {
45
+ cancellable: true,
46
+ resumable: false,
47
+ },
48
+ },
49
+ {
50
+ id: '0ff5124e-0851-430a-a831-7e50971a80dc',
51
+ label: 'StoredValuesCleanupJob',
52
+ pending: false,
53
+ action: 'StoredValuesCleanupJob',
54
+ username: 'admin',
55
+ started_at: null,
56
+ ended_at: '2025-11-17 10:51:21 +0000',
57
+ duration: '0',
58
+ state: 'stopped',
59
+ result: 'cancelled',
60
+ progress: 1,
61
+ input: null,
62
+ output: null,
63
+ humanized: {
64
+ action: 'StoredValuesCleanupJob',
65
+ input: null,
66
+ output: null,
67
+ errors: null,
68
+ },
69
+ cli_example: null,
70
+ start_at: '2025-11-17 22:50:45 +0000',
71
+ can_edit: true,
72
+ can_delete: true,
73
+ available_actions: {
74
+ cancellable: false,
75
+ resumable: false,
76
+ },
77
+ },
78
+ {
79
+ id: '4aa47ed6-dbfc-4262-8637-6b204e80a06d',
80
+ label: 'Actions::RemoteExecution::RunHostsJob',
81
+ pending: false,
82
+ action: '»»Run hosts job««: Run echo',
83
+ username: 'admin',
84
+ started_at: null,
85
+ ended_at: '2025-07-21 17:14:01 +0100',
86
+ duration: '0',
87
+ state: 'stopped',
88
+ result: 'cancelled',
89
+ progress: 1,
90
+ input: {
91
+ job_invocation: {
92
+ id: 62,
93
+ name: 'Commands',
94
+ description: 'Run echo',
95
+ },
96
+ current_request_id: '2503edc5-51e5-447d-bdd2-512468535eba',
97
+ current_timezone: 'Europe/London',
98
+ current_organization_id: null,
99
+ current_location_id: null,
100
+ current_user_id: 4,
101
+ },
102
+ output: {},
103
+ humanized: {
104
+ action: '»»Run hosts job««:',
105
+ input: 'Run echo',
106
+ output: null,
107
+ errors: [],
108
+ },
109
+ cli_example: null,
110
+ start_at: '2026-07-21 12:56:00 +0100',
111
+ can_edit: true,
112
+ can_delete: true,
113
+ available_actions: {
114
+ cancellable: false,
115
+ resumable: true,
116
+ },
117
+ },
118
+ {
119
+ id: '53bed58a-2cda-4047-bcf6-71141ca06ba5',
120
+ label: 'Actions::RemoteExecution::RunHostsJob',
121
+ pending: false,
122
+ action: '»»Run hosts job««: Run ls',
123
+ username: 'admin',
124
+ started_at: null,
125
+ ended_at: '2025-11-26 17:35:36 +0000',
126
+ duration: '0',
127
+ state: 'stopped',
128
+ result: 'cancelled',
129
+ progress: 1,
130
+ input: {
131
+ job_invocation: {
132
+ id: 70,
133
+ name: 'Commands',
134
+ description: 'Run ls',
135
+ },
136
+ current_request_id: '8cfe5ca7-c48b-4dfb-a1c4-29505300c4b9',
137
+ current_timezone: 'Europe/London',
138
+ current_organization_id: 1,
139
+ current_location_id: 2,
140
+ current_user_id: 4,
141
+ },
142
+ output: {},
143
+ humanized: {
144
+ action: '»»Run hosts job««:',
145
+ input: 'Run ls',
146
+ output: null,
147
+ errors: [],
148
+ },
149
+ cli_example: null,
150
+ start_at: '2026-09-25 15:17:00 +0100',
151
+ can_edit: true,
152
+ can_delete: true,
153
+ available_actions: {
154
+ cancellable: false,
155
+ resumable: false,
156
+ },
157
+ },
158
+ {
159
+ id: '58276bf0-67c3-4452-b5f3-6fd90c4997b3',
160
+ label: 'jobLabel1',
161
+ pending: false,
162
+ action: 'jobLabel1',
163
+ username: 'admin',
164
+ started_at: null,
165
+ ended_at: '2026-03-05 14:30:55 +0000',
166
+ duration: '0',
167
+ state: 'stopped',
168
+ result: 'pending',
169
+ progress: 1,
170
+ input: null,
171
+ output: null,
172
+ humanized: {
173
+ action: 'jobLabel1',
174
+ input: null,
175
+ output: null,
176
+ errors: null,
177
+ },
178
+ cli_example: null,
179
+ start_at: '2026-03-05 22:40:34 +0000',
180
+ can_edit: true,
181
+ can_delete: true,
182
+ available_actions: {
183
+ cancellable: false,
184
+ resumable: false,
185
+ },
186
+ },
187
+ {
188
+ id: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890',
189
+ label: 'Actions::RemoteExecution::RunHostsJob',
190
+ pending: false,
191
+ action: 'Running job',
192
+ username: 'admin',
193
+ started_at: '2026-03-10 10:00:00 +0000',
194
+ ended_at: '2026-03-10 10:00:00 +0000',
195
+ duration: '0',
196
+ state: 'running',
197
+ result: 'pending',
198
+ progress: 0.5,
199
+ input: null,
200
+ output: null,
201
+ humanized: {
202
+ action: 'Running job',
203
+ input: null,
204
+ output: null,
205
+ errors: null,
206
+ },
207
+ cli_example: null,
208
+ start_at: '2026-03-10 10:00:00 +0000',
209
+ can_edit: true,
210
+ can_delete: true,
211
+ available_actions: {
212
+ cancellable: false,
213
+ resumable: false,
214
+ },
215
+ },
216
+ ],
44
217
  },
45
218
  };
@@ -5,8 +5,8 @@ describe('updateURlQuery', () => {
5
5
  const history = {
6
6
  push: jest.fn(),
7
7
  location: {
8
- pathname:
9
- '/foreman_tasks/tasks/?state=stopped&result=error&page=1&per_page=20',
8
+ pathname: '/foreman_tasks/tasks/',
9
+ search: '?state=stopped&result=error&page=1&per_page=20',
10
10
  },
11
11
  };
12
12
  const query = { time_mode: 'recent', per_page: 35 };
@@ -28,17 +28,25 @@ describe('updateURlQuery', () => {
28
28
  });
29
29
 
30
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?search=%28state%3Dstopped%29'
36
- );
31
+ const originalLocation = window.location;
32
+
33
+ beforeEach(() => {
34
+ delete window.location;
35
+ });
36
+
37
+ afterEach(() => {
38
+ window.location = originalLocation;
37
39
  });
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'
40
+
41
+ it('should return correct url for subtasks', () => {
42
+ window.location = new URL(
43
+ 'https://test.example.com/foreman_tasks/tasks/some-id/sub_tasks'
42
44
  );
45
+ expect(getCSVurl()).toEqual('/foreman_tasks/tasks/some-id/sub_tasks.csv');
46
+ });
47
+
48
+ it('should append .csv to current pathname', () => {
49
+ window.location = new URL('https://test.example.com/foreman_tasks/tasks');
50
+ expect(getCSVurl()).toMatch(/^\/foreman_tasks\/tasks\.csv/);
43
51
  });
44
52
  });
@@ -1,6 +1,6 @@
1
1
  // Jest Snapshot v1, https://goo.gl/fbAQLP
2
2
 
3
- exports[`TasksTable bulk actions handles bulkCancelById requests 1`] = `
3
+ exports[`TasksBulkActions Test reloadPage callback handles bulkCancelById requests 1`] = `
4
4
  Array [
5
5
  Array [
6
6
  Object {
@@ -23,16 +23,11 @@ Array [
23
23
  "type": "TOASTS_ADD",
24
24
  },
25
25
  ],
26
- Array [
27
- "TASKS_TABLE",
28
- ],
29
- Array [
30
- [Function],
31
- ],
32
26
  ]
33
27
  `;
34
28
 
35
- exports[`TasksTable bulk actions handles bulkCancelById requests that are not cancellable 1`] = `
29
+
30
+ exports[`TasksBulkActions handles bulkCancelById requests that are not cancellable 1`] = `
36
31
  Array [
37
32
  Array [
38
33
  Object {
@@ -48,7 +43,7 @@ Array [
48
43
  ]
49
44
  `;
50
45
 
51
- exports[`TasksTable bulk actions handles bulkCancelById requests with canEdit false 1`] = `
46
+ exports[`TasksBulkActions handles bulkCancelById requests with canEdit false 1`] = `
52
47
  Array [
53
48
  Array [
54
49
  Object {
@@ -64,7 +59,7 @@ Array [
64
59
  ]
65
60
  `;
66
61
 
67
- exports[`TasksTable bulk actions handles bulkCancelBySearch requests 1`] = `
62
+ exports[`TasksBulkActions handles bulkCancelBySearch requests 1`] = `
68
63
  Array [
69
64
  Array [
70
65
  Object {
@@ -85,7 +80,7 @@ Array [
85
80
  ]
86
81
  `;
87
82
 
88
- exports[`TasksTable bulk actions handles bulkForceCancelById requests 1`] = `
83
+ exports[`TasksBulkActions Test reloadPage callback handles bulkForceCancelById requests 1`] = `
89
84
  Array [
90
85
  Array [
91
86
  Object {
@@ -119,16 +114,11 @@ Array [
119
114
  "type": "TOASTS_ADD",
120
115
  },
121
116
  ],
122
- Array [
123
- "TASKS_TABLE",
124
- ],
125
- Array [
126
- [Function],
127
- ],
128
117
  ]
129
118
  `;
130
119
 
131
- exports[`TasksTable bulk actions handles bulkForceCancelById requests that are stopped 1`] = `
120
+
121
+ exports[`TasksBulkActions handles bulkForceCancelById requests that are stopped 1`] = `
132
122
  Array [
133
123
  Array [
134
124
  Object {
@@ -144,7 +134,7 @@ Array [
144
134
  ]
145
135
  `;
146
136
 
147
- exports[`TasksTable bulk actions handles bulkForceCancelById requests that fail 1`] = `
137
+ exports[`TasksBulkActions handles bulkForceCancelById requests that fail 1`] = `
148
138
  Array [
149
139
  Array [
150
140
  Object {
@@ -171,7 +161,7 @@ Array [
171
161
  ]
172
162
  `;
173
163
 
174
- exports[`TasksTable bulk actions handles bulkForceCancelById requests with canEdit false 1`] = `
164
+ exports[`TasksBulkActions handles bulkForceCancelById requests with canEdit false 1`] = `
175
165
  Array [
176
166
  Array [
177
167
  Object {
@@ -187,7 +177,7 @@ Array [
187
177
  ]
188
178
  `;
189
179
 
190
- exports[`TasksTable bulk actions handles bulkForceCancelBySearch requests 1`] = `
180
+ exports[`TasksBulkActions handles bulkForceCancelBySearch requests 1`] = `
191
181
  Array [
192
182
  Array [
193
183
  Object {
@@ -208,7 +198,7 @@ Array [
208
198
  ]
209
199
  `;
210
200
 
211
- exports[`TasksTable bulk actions handles bulkResumeById requests that are not resumable 1`] = `
201
+ exports[`TasksBulkActions handles bulkResumeById requests that are not resumable 1`] = `
212
202
  Array [
213
203
  Array [
214
204
  Object {
@@ -224,7 +214,7 @@ Array [
224
214
  ]
225
215
  `;
226
216
 
227
- exports[`TasksTable bulk actions handles bulkResumeById requests that fail 1`] = `
217
+ exports[`TasksBulkActions handles bulkResumeById requests that fail 1`] = `
228
218
  Array [
229
219
  Array [
230
220
  Object {
@@ -251,7 +241,7 @@ Array [
251
241
  ]
252
242
  `;
253
243
 
254
- exports[`TasksTable bulk actions handles bulkResumeById requests with canEdit false 1`] = `
244
+ exports[`TasksBulkActions handles bulkResumeById requests with canEdit false 1`] = `
255
245
  Array [
256
246
  Array [
257
247
  Object {
@@ -267,7 +257,7 @@ Array [
267
257
  ]
268
258
  `;
269
259
 
270
- exports[`TasksTable bulk actions handles bulkResumeBySearch requests 1`] = `
260
+ exports[`TasksBulkActions handles bulkResumeBySearch requests 1`] = `
271
261
  Array [
272
262
  Array [
273
263
  Object {
@@ -288,7 +278,7 @@ Array [
288
278
  ]
289
279
  `;
290
280
 
291
- exports[`TasksTable bulk actions handles resumable bulkResumeById requests 1`] = `
281
+ exports[`TasksBulkActions Test reloadPage callback handles resumable bulkResumeById requests 1`] = `
292
282
  Array [
293
283
  Array [
294
284
  Object {
@@ -322,16 +312,9 @@ Array [
322
312
  "type": "TOASTS_ADD",
323
313
  },
324
314
  ],
325
- Array [
326
- "TASKS_TABLE",
327
- ],
328
- Array [
329
- [Function],
330
- ],
331
315
  ]
332
316
  `;
333
-
334
- exports[`TasksTable bulk actions handles skipped bulkCancelById requests 1`] = `
317
+ exports[`TasksBulkActions handles skipped bulkCancelById requests 1`] = `
335
318
  Array [
336
319
  Array [
337
320
  Object {
@@ -357,7 +340,7 @@ Array [
357
340
  ]
358
341
  `;
359
342
 
360
- exports[`TasksTable bulk actions handles skipped bulkResumeById requests 1`] = `
343
+ exports[`TasksBulkActions handles skipped bulkResumeById requests 1`] = `
361
344
  Array [
362
345
  Array [
363
346
  Object {
@@ -1,13 +1,9 @@
1
1
  import { combineReducers } from 'redux';
2
2
  import { reducers as tasksDashboardReducers } from './Components/TasksDashboard';
3
- import { reducers as tasksTableReducers } from './Components/TasksTable';
4
- import { reducers as confirmModalReducers } from './Components/TasksTable/Components/ConfirmModal';
5
3
 
6
4
  const reducers = {
7
5
  foremanTasks: combineReducers({
8
6
  ...tasksDashboardReducers,
9
- ...tasksTableReducers,
10
- ...confirmModalReducers,
11
7
  }),
12
8
  };
13
9
 
@@ -0,0 +1,22 @@
1
+ import React from 'react';
2
+ import TasksTableIndexPage from '../ForemanTasks/Components/TasksTable/TasksIndexPage';
3
+ import ShowTask from '../ForemanTasks/Routes/ShowTask/ShowTask';
4
+
5
+ const ForemanTasksRoutes = [
6
+ {
7
+ path: '/foreman_tasks/tasks',
8
+ exact: true,
9
+ render: props => <TasksTableIndexPage {...props} />,
10
+ },
11
+ {
12
+ path: '/foreman_tasks/tasks/:id/sub_tasks',
13
+ exact: true,
14
+ render: props => <TasksTableIndexPage {...props} />,
15
+ },
16
+ {
17
+ path: '/foreman_tasks/ex_tasks/:id',
18
+ render: props => <ShowTask {...props} />,
19
+ },
20
+ ];
21
+
22
+ export default ForemanTasksRoutes;
@@ -0,0 +1,95 @@
1
+ import React from 'react';
2
+ import { render, screen } from '@testing-library/react';
3
+ import '@testing-library/jest-dom';
4
+
5
+ import ForemanTasksRoutes from './routes';
6
+
7
+ jest.mock(
8
+ '../ForemanTasks/Components/TasksTable/TasksIndexPage',
9
+ () =>
10
+ function TasksTableIndexPageStub() {
11
+ return <div data-testid="tasks-table-index-stub" />;
12
+ }
13
+ );
14
+
15
+ jest.mock(
16
+ '../ForemanTasks/Routes/ShowTask/ShowTask',
17
+ () =>
18
+ function ShowTaskStub() {
19
+ return <div data-testid="show-task-stub" />;
20
+ }
21
+ );
22
+
23
+ const routerProps = {
24
+ history: { push: jest.fn(), replace: jest.fn(), go: jest.fn() },
25
+ location: {
26
+ pathname: '/foreman_tasks/tasks',
27
+ search: '',
28
+ hash: '',
29
+ state: undefined,
30
+ },
31
+ match: {
32
+ params: {},
33
+ path: '/foreman_tasks/tasks',
34
+ url: '/foreman_tasks/tasks',
35
+ isExact: true,
36
+ },
37
+ };
38
+
39
+ describe('ForemanTasks routes', () => {
40
+ it('defines the foreman_tasks React paths', () => {
41
+ expect(
42
+ ForemanTasksRoutes.map(({ path, exact }) => ({ path, exact }))
43
+ ).toEqual([
44
+ { path: '/foreman_tasks/tasks', exact: true },
45
+ { path: '/foreman_tasks/tasks/:id/sub_tasks', exact: true },
46
+ { path: '/foreman_tasks/ex_tasks/:id', exact: undefined },
47
+ ]);
48
+ });
49
+
50
+ it('each route render returns a mountable page', () => {
51
+ const propsByIndex = [
52
+ {
53
+ ...routerProps,
54
+ match: {
55
+ ...routerProps.match,
56
+ params: {},
57
+ path: '/foreman_tasks/tasks',
58
+ url: '/foreman_tasks/tasks',
59
+ },
60
+ },
61
+ {
62
+ ...routerProps,
63
+ match: {
64
+ ...routerProps.match,
65
+ params: { id: '7' },
66
+ path: '/foreman_tasks/tasks/:id/sub_tasks',
67
+ url: '/foreman_tasks/tasks/7/sub_tasks',
68
+ },
69
+ },
70
+ {
71
+ ...routerProps,
72
+ match: {
73
+ ...routerProps.match,
74
+ params: { id: '42' },
75
+ path: '/foreman_tasks/ex_tasks/:id',
76
+ url: '/foreman_tasks/ex_tasks/42',
77
+ },
78
+ },
79
+ ];
80
+
81
+ ForemanTasksRoutes.forEach((route, index) => {
82
+ const { unmount } = render(route.render(propsByIndex[index]));
83
+
84
+ if (index === 2) {
85
+ expect(screen.getByTestId('show-task-stub')).toBeInTheDocument();
86
+ } else {
87
+ expect(
88
+ screen.getByTestId('tasks-table-index-stub')
89
+ ).toBeInTheDocument();
90
+ }
91
+
92
+ unmount();
93
+ });
94
+ });
95
+ });
@@ -0,0 +1,10 @@
1
+ import { registerRoutes } from 'foremanReact/routes/RoutingService';
2
+ import { registerReducer } from 'foremanReact/common/MountingService';
3
+ import routes from './Routes/routes';
4
+ import reducers from './ForemanTasks/ForemanTasksReducers';
5
+
6
+ Object.entries(reducers).forEach(([key, reducer]) =>
7
+ registerReducer(key, reducer)
8
+ );
9
+
10
+ registerRoutes('foreman_tasks', routes);
data/webpack/index.js CHANGED
@@ -2,23 +2,9 @@
2
2
  /* eslint-disable import/no-extraneous-dependencies */
3
3
  /* eslint-disable import/extensions */
4
4
  import componentRegistry from 'foremanReact/components/componentRegistry';
5
- import { registerReducer } from 'foremanReact/common/MountingService';
6
- import reducers from './ForemanTasks/ForemanTasksReducers';
7
- import ForemanTasks from './ForemanTasks';
8
5
  import TasksDashboard from './ForemanTasks/Components/TasksDashboard';
9
6
  import TaskDetails from './ForemanTasks/Components/TaskDetails';
10
- import TasksTable from './ForemanTasks/Components/TasksTable';
11
7
 
12
- // register reducers
13
- Object.entries(reducers).forEach(([key, reducer]) =>
14
- registerReducer(key, reducer)
15
- );
16
-
17
- // register components
18
- componentRegistry.register({
19
- name: 'ForemanTasks',
20
- type: ForemanTasks,
21
- });
22
8
  componentRegistry.register({
23
9
  name: 'TasksDashboard',
24
10
  type: TasksDashboard,
@@ -27,7 +13,3 @@ componentRegistry.register({
27
13
  name: 'TaskDetails',
28
14
  type: TaskDetails,
29
15
  });
30
- componentRegistry.register({
31
- name: 'TasksTable',
32
- type: TasksTable,
33
- });
@@ -0,0 +1 @@
1
+ import 'foremanJSTestSetup';