foreman_remote_execution 16.0.5 → 16.2.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 (54) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/foreman_remote_execution/locale/de/foreman_remote_execution.js +54 -30
  3. data/app/assets/javascripts/foreman_remote_execution/locale/en_GB/foreman_remote_execution.js +52 -28
  4. data/app/assets/javascripts/foreman_remote_execution/locale/es/foreman_remote_execution.js +55 -31
  5. data/app/assets/javascripts/foreman_remote_execution/locale/fr/foreman_remote_execution.js +61 -37
  6. data/app/assets/javascripts/foreman_remote_execution/locale/ja/foreman_remote_execution.js +62 -38
  7. data/app/assets/javascripts/foreman_remote_execution/locale/ka/foreman_remote_execution.js +53 -29
  8. data/app/assets/javascripts/foreman_remote_execution/locale/ko/foreman_remote_execution.js +61 -37
  9. data/app/assets/javascripts/foreman_remote_execution/locale/pt_BR/foreman_remote_execution.js +55 -31
  10. data/app/assets/javascripts/foreman_remote_execution/locale/ru/foreman_remote_execution.js +52 -28
  11. data/app/assets/javascripts/foreman_remote_execution/locale/zh_CN/foreman_remote_execution.js +61 -37
  12. data/app/assets/javascripts/foreman_remote_execution/locale/zh_TW/foreman_remote_execution.js +52 -28
  13. data/app/controllers/api/v2/job_invocations_controller.rb +33 -6
  14. data/app/helpers/remote_execution_helper.rb +1 -1
  15. data/app/views/api/v2/job_templates/main.json.rabl +1 -1
  16. data/config/routes.rb +3 -2
  17. data/lib/foreman_remote_execution/plugin.rb +1 -7
  18. data/lib/foreman_remote_execution/version.rb +1 -1
  19. data/locale/de/LC_MESSAGES/foreman_remote_execution.mo +0 -0
  20. data/locale/de/foreman_remote_execution.po +54 -30
  21. data/locale/en_GB/LC_MESSAGES/foreman_remote_execution.mo +0 -0
  22. data/locale/en_GB/foreman_remote_execution.po +52 -28
  23. data/locale/es/LC_MESSAGES/foreman_remote_execution.mo +0 -0
  24. data/locale/es/foreman_remote_execution.po +55 -31
  25. data/locale/foreman_remote_execution.pot +193 -156
  26. data/locale/fr/LC_MESSAGES/foreman_remote_execution.mo +0 -0
  27. data/locale/fr/foreman_remote_execution.po +61 -37
  28. data/locale/ja/LC_MESSAGES/foreman_remote_execution.mo +0 -0
  29. data/locale/ja/foreman_remote_execution.po +62 -38
  30. data/locale/ka/LC_MESSAGES/foreman_remote_execution.mo +0 -0
  31. data/locale/ka/foreman_remote_execution.po +53 -29
  32. data/locale/ko/LC_MESSAGES/foreman_remote_execution.mo +0 -0
  33. data/locale/ko/foreman_remote_execution.po +61 -37
  34. data/locale/pt_BR/LC_MESSAGES/foreman_remote_execution.mo +0 -0
  35. data/locale/pt_BR/foreman_remote_execution.po +55 -31
  36. data/locale/ru/LC_MESSAGES/foreman_remote_execution.mo +0 -0
  37. data/locale/ru/foreman_remote_execution.po +52 -28
  38. data/locale/zh_CN/LC_MESSAGES/foreman_remote_execution.mo +0 -0
  39. data/locale/zh_CN/foreman_remote_execution.po +61 -37
  40. data/locale/zh_TW/LC_MESSAGES/foreman_remote_execution.mo +0 -0
  41. data/locale/zh_TW/foreman_remote_execution.po +52 -28
  42. data/webpack/JobInvocationDetail/CheckboxesActions.js +176 -46
  43. data/webpack/JobInvocationDetail/JobInvocationConstants.js +2 -3
  44. data/webpack/JobInvocationDetail/JobInvocationHostTable.js +14 -1
  45. data/webpack/JobInvocationDetail/JobInvocationToolbarButtons.js +3 -1
  46. data/webpack/JobInvocationDetail/TemplateInvocation.js +63 -50
  47. data/webpack/JobInvocationDetail/TemplateInvocationPage.js +1 -0
  48. data/webpack/JobInvocationDetail/__tests__/MainInformation.test.js +2 -4
  49. data/webpack/JobInvocationDetail/__tests__/TableToolbarActions.test.js +28 -26
  50. data/webpack/JobInvocationDetail/__tests__/TemplateInvocation.test.js +4 -0
  51. data/webpack/JobInvocationDetail/index.js +12 -13
  52. data/webpack/Routes/routes.js +1 -1
  53. data/webpack/react_app/components/HostKebab/KebabItems.js +2 -3
  54. metadata +2 -2
@@ -1,16 +1,20 @@
1
+ import '@testing-library/jest-dom/extend-expect';
2
+ import { fireEvent, render, screen, waitFor } from '@testing-library/react';
3
+ import axios from 'axios';
4
+ import { foremanUrl } from 'foremanReact/common/helpers';
5
+ import { useAPI } from 'foremanReact/common/hooks/API/APIHooks';
1
6
  import React from 'react';
2
7
  import { Provider } from 'react-redux';
3
8
  import configureStore from 'redux-mock-store';
4
- import { render, screen, fireEvent, waitFor } from '@testing-library/react';
5
- import '@testing-library/jest-dom/extend-expect';
6
- import { useAPI } from 'foremanReact/common/hooks/API/APIHooks';
9
+
7
10
  import { CheckboxesActions } from '../CheckboxesActions';
8
11
  import * as selectors from '../JobInvocationSelectors';
9
12
  import { PopupAlert } from '../OpenAllInvocationsModal';
10
13
 
14
+ jest.mock('axios');
11
15
  jest.mock('foremanReact/common/hooks/API/APIHooks');
12
-
13
16
  jest.mock('../JobInvocationSelectors');
17
+
14
18
  jest.mock('../JobInvocationConstants', () => ({
15
19
  ...jest.requireActual('../JobInvocationConstants'),
16
20
  templateInvocationPageUrl: jest.fn(
@@ -18,18 +22,15 @@ jest.mock('../JobInvocationConstants', () => ({
18
22
  ),
19
23
  DIRECT_OPEN_HOST_LIMIT: 3,
20
24
  }));
25
+
21
26
  selectors.selectItems.mockImplementation(() => ({
22
27
  targeting: { search_query: 'name~*' },
23
28
  }));
24
- selectors.selectHasPermission.mockImplementation(() => () => () => true);
29
+ selectors.selectHasPermission.mockImplementation(() => () => true);
30
+ selectors.selectTaskCancelable.mockImplementation(() => true);
31
+
25
32
  const mockStore = configureStore([]);
26
- const store = mockStore({
27
- templateInvocation: {
28
- permissions: {
29
- execute_jobs: true,
30
- },
31
- },
32
- });
33
+ const store = mockStore({});
33
34
 
34
35
  describe('TableToolbarActions', () => {
35
36
  const jobID = '42';
@@ -38,6 +39,7 @@ describe('TableToolbarActions', () => {
38
39
  beforeEach(() => {
39
40
  openSpy = jest.spyOn(window, 'open').mockImplementation(jest.fn());
40
41
  useAPI.mockClear();
42
+ axios.post.mockResolvedValue({ data: {} });
41
43
  useAPI.mockReturnValue({
42
44
  response: null,
43
45
  status: 'initial',
@@ -68,7 +70,7 @@ describe('TableToolbarActions', () => {
68
70
  expect(openSpy).toHaveBeenCalledTimes(selectedIds.length);
69
71
  });
70
72
 
71
- test('shows modal when results length is greater than 3', () => {
73
+ test('shows modal when results length is greater than 3', async () => {
72
74
  const selectedIds = [1, 2, 3, 4];
73
75
  render(
74
76
  <Provider store={store}>
@@ -83,13 +85,13 @@ describe('TableToolbarActions', () => {
83
85
  screen.getByLabelText(/open all template invocations in new tab/i)
84
86
  );
85
87
  expect(
86
- screen.getByRole('heading', {
87
- name: /open all %s invocations in new tabs \+ selected/i,
88
+ await screen.findByRole('heading', {
89
+ name: /open all.*invocations in new tabs \+ selected/i,
88
90
  })
89
91
  ).toBeInTheDocument();
90
92
  });
91
93
 
92
- test('shows alert when popups are blocked', () => {
94
+ test('shows alert when popups are blocked', async () => {
93
95
  openSpy.mockReturnValue(null);
94
96
  const selectedIds = [1, 2];
95
97
  render(
@@ -105,7 +107,7 @@ describe('TableToolbarActions', () => {
105
107
  screen.getByLabelText(/open all template invocations in new tab/i)
106
108
  );
107
109
  expect(
108
- screen.getByText(/Popups are blocked by your browser/)
110
+ await screen.findByText(/Popups are blocked by your browser/)
109
111
  ).toBeInTheDocument();
110
112
  });
111
113
  });
@@ -123,23 +125,23 @@ describe('TableToolbarActions', () => {
123
125
  </Provider>
124
126
  );
125
127
  fireEvent.click(screen.getByLabelText(/actions dropdown toggle/i));
126
- fireEvent.click(screen.getByText(/open all failed runs/i));
128
+ fireEvent.click(await screen.findByText(/open all failed runs/i));
127
129
  await waitFor(() => {
128
130
  expect(openSpy).toHaveBeenCalledTimes(failedHosts.length);
129
131
  });
130
132
  });
131
133
 
132
- test('shows modal when results length is greater than 3', () => {
134
+ test('shows modal when results length is greater than 3', async () => {
133
135
  render(
134
136
  <Provider store={store}>
135
137
  <CheckboxesActions selectedIds={[]} failedCount={4} jobID={jobID} />
136
138
  </Provider>
137
139
  );
138
140
  fireEvent.click(screen.getByLabelText(/actions dropdown toggle/i));
139
- fireEvent.click(screen.getByText(/open all failed runs/i));
141
+ fireEvent.click(await screen.findByText(/open all failed runs/i));
140
142
  expect(
141
- screen.getByRole('heading', {
142
- name: /open all %s invocations in new tabs \+ failed/i,
143
+ await screen.findByRole('heading', {
144
+ name: /open all.*invocations in new tabs \+ failed/i,
143
145
  })
144
146
  ).toBeInTheDocument();
145
147
  });
@@ -152,7 +154,7 @@ describe('TableToolbarActions', () => {
152
154
  );
153
155
  expect(useAPI).toHaveBeenCalledWith(
154
156
  'get',
155
- `foreman/api/job_invocations/${jobID}/hosts`,
157
+ foremanUrl(`/api/job_invocations/${jobID}/hosts`),
156
158
  expect.objectContaining({
157
159
  skip: true,
158
160
  })
@@ -193,9 +195,9 @@ describe('TableToolbarActions', () => {
193
195
  );
194
196
  const rerunLink = screen.getByRole('link', { name: /rerun/i });
195
197
  expect(rerunLink).toBeEnabled();
196
- const expectedSearchParams = new URLSearchParams();
197
- selectedIds.forEach(id => expectedSearchParams.append('host_ids[]', id));
198
- const expectedHref = `foreman/job_invocations/42/rerun?search=(name~*) AND ((id ^ (101, 102, 103)))`;
198
+ const expectedHref = foremanUrl(
199
+ `/job_invocations/42/rerun?search=(job_invocation.id = 42) AND ((id ^ (101, 102, 103)))`
200
+ );
199
201
  expect(rerunLink).toHaveAttribute('href', expectedHref);
200
202
  });
201
203
  });
@@ -32,6 +32,7 @@ describe('TemplateInvocation', () => {
32
32
  hostID="1"
33
33
  jobID="1"
34
34
  isInTableView={false}
35
+ isExpanded
35
36
  hostName="example-host"
36
37
  hostProxy={{ name: 'example-proxy', href: '#' }}
37
38
  />
@@ -54,6 +55,7 @@ describe('TemplateInvocation', () => {
54
55
  hostID="1"
55
56
  jobID="1"
56
57
  isInTableView={false}
58
+ isExpanded
57
59
  hostName="example-host"
58
60
  hostProxy={{ name: 'example-proxy', href: '#' }}
59
61
  />
@@ -108,6 +110,7 @@ describe('TemplateInvocation', () => {
108
110
  hostID="1"
109
111
  jobID="1"
110
112
  isInTableView={false}
113
+ isExpanded
111
114
  hostName="example-host"
112
115
  hostProxy={{ name: 'example-proxy', href: '#' }}
113
116
  />
@@ -133,6 +136,7 @@ describe('TemplateInvocation', () => {
133
136
  hostID="1"
134
137
  jobID="1"
135
138
  isInTableView={false}
139
+ isExpanded
136
140
  hostName="example-host"
137
141
  />
138
142
  </Provider>
@@ -5,32 +5,31 @@ import {
5
5
  PageSectionVariants,
6
6
  Skeleton,
7
7
  } from '@patternfly/react-core';
8
- import { useAPI } from 'foremanReact/common/hooks/API/APIHooks';
8
+ import React, { useEffect, useState } from 'react';
9
9
  import { translate as __, documentLocale } from 'foremanReact/common/I18n';
10
- import { stopInterval } from 'foremanReact/redux/middlewares/IntervalMiddleware';
10
+ import { useDispatch, useSelector } from 'react-redux';
11
11
  import PageLayout from 'foremanReact/routes/common/PageLayout/PageLayout';
12
- import SkeletonLoader from 'foremanReact/components/common/SkeletonLoader';
13
12
  import PropTypes from 'prop-types';
14
- import React, { useEffect, useState } from 'react';
15
- import { useDispatch, useSelector } from 'react-redux';
13
+ import SkeletonLoader from 'foremanReact/components/common/SkeletonLoader';
14
+ import { stopInterval } from 'foremanReact/redux/middlewares/IntervalMiddleware';
15
+ import { useAPI } from 'foremanReact/common/hooks/API/APIHooks';
16
16
 
17
17
  import { JobAdditionInfo } from './JobAdditionInfo';
18
+ import JobInvocationHostTable from './JobInvocationHostTable';
19
+ import JobInvocationOverview from './JobInvocationOverview';
20
+ import JobInvocationSystemStatusChart from './JobInvocationSystemStatusChart';
21
+ import JobInvocationToolbarButtons from './JobInvocationToolbarButtons';
18
22
  import { getJobInvocation, getTask } from './JobInvocationActions';
23
+ import './JobInvocationDetail.scss';
19
24
  import {
20
25
  CURRENT_PERMISSIONS,
21
- currentPermissionsUrl,
22
26
  DATE_OPTIONS,
23
27
  JOB_INVOCATION_KEY,
24
28
  STATUS,
25
29
  STATUS_UPPERCASE,
30
+ currentPermissionsUrl,
26
31
  } from './JobInvocationConstants';
27
- import JobInvocationHostTable from './JobInvocationHostTable';
28
- import JobInvocationOverview from './JobInvocationOverview';
29
32
  import { selectItems } from './JobInvocationSelectors';
30
- import JobInvocationSystemStatusChart from './JobInvocationSystemStatusChart';
31
- import JobInvocationToolbarButtons from './JobInvocationToolbarButtons';
32
-
33
- import './JobInvocationDetail.scss';
34
33
 
35
34
  const JobInvocationDetailPage = ({
36
35
  match: {
@@ -184,9 +183,9 @@ const JobInvocationDetailPage = ({
184
183
  id={id}
185
184
  targeting={targeting}
186
185
  failedCount={failed}
187
- finished={finished}
188
186
  autoRefresh={autoRefresh}
189
187
  initialFilter={selectedFilter}
188
+ statusLabel={statusLabel}
190
189
  onFilterUpdate={handleFilterChange}
191
190
  />
192
191
  </SkeletonLoader>
@@ -16,7 +16,7 @@ const ForemanREXRoutes = [
16
16
  render: props => <JobWizardPageRerun {...props} />,
17
17
  },
18
18
  {
19
- path: '/experimental/job_invocations_detail/:id',
19
+ path: '/job_invocations/:id',
20
20
  exact: true,
21
21
  render: props => <JobInvocationDetailPage {...props} />,
22
22
  },
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import { useSelector } from 'react-redux';
3
- import { DropdownItem } from '@patternfly/react-core/deprecated';
3
+ import { DropdownItem } from '@patternfly/react-core';
4
4
  import { CodeIcon } from '@patternfly/react-icons';
5
5
  import { selectAPIResponse } from 'foremanReact/redux/API/APISelectors';
6
6
  import { translate as __ } from 'foremanReact/common/I18n';
@@ -16,9 +16,8 @@ const HostKebabItems = () => {
16
16
  <DropdownItem
17
17
  ouiaId="web-console-dropdown-item"
18
18
  icon={<CodeIcon />}
19
- href={consoleUrl}
19
+ to={consoleUrl}
20
20
  target="_blank"
21
- rel="noreferrer"
22
21
  >
23
22
  {__('Web Console')}
24
23
  </DropdownItem>
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: foreman_remote_execution
3
3
  version: !ruby/object:Gem::Version
4
- version: 16.0.5
4
+ version: 16.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Foreman Remote Execution team
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-07-28 00:00:00.000000000 Z
10
+ date: 2025-08-29 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: deface