foreman_remote_execution 16.6.4 → 16.7.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.
- checksums.yaml +4 -4
- data/app/controllers/api/v2/job_invocations_controller.rb +22 -13
- data/app/views/api/v2/job_invocations/main.json.rabl +15 -11
- data/lib/foreman_remote_execution/version.rb +1 -1
- data/package.json +3 -3
- data/test/functional/api/v2/job_invocations_controller_test.rb +68 -3
- data/test/integration/job_wizard_category_js_test.rb +234 -0
- data/webpack/JobInvocationDetail/CheckboxesActions.js +4 -10
- data/webpack/JobInvocationDetail/JobInvocationActions.js +2 -1
- data/webpack/JobInvocationDetail/JobInvocationConstants.js +4 -4
- data/webpack/JobInvocationDetail/JobInvocationDetail.scss +5 -0
- data/webpack/JobInvocationDetail/JobInvocationEmptyState.js +52 -0
- data/webpack/JobInvocationDetail/JobInvocationSelectors.js +0 -15
- data/webpack/JobInvocationDetail/JobInvocationToolbarButtons.js +201 -150
- data/webpack/JobInvocationDetail/__tests__/JobInvocationDetailEmptyState.test.js +53 -0
- data/webpack/JobInvocationDetail/__tests__/MainInformation.test.js +109 -11
- data/webpack/JobInvocationDetail/__tests__/TableToolbarActions.test.js +3 -1
- data/webpack/JobInvocationDetail/__tests__/foremanTestHelpers.js +30 -0
- data/webpack/JobInvocationDetail/index.js +42 -9
- data/webpack/__mocks__/foremanReact/Root/Context/ForemanContext/index.js +15 -0
- data/webpack/__mocks__/foremanReact/common/hooks/Permissions/permissionHooks.js +1 -0
- data/webpack/__mocks__/foremanReact/redux/API/APISelectors.js +5 -0
- metadata +7 -2
|
@@ -1,9 +1,13 @@
|
|
|
1
|
+
/* eslint-disable max-lines */
|
|
1
2
|
import React from 'react';
|
|
2
3
|
import configureMockStore from 'redux-mock-store';
|
|
3
4
|
import { fireEvent, render, screen, act } from '@testing-library/react';
|
|
4
5
|
import '@testing-library/jest-dom/extend-expect';
|
|
6
|
+
import { createMemoryHistory } from 'history';
|
|
7
|
+
import { Router } from 'react-router-dom';
|
|
5
8
|
import { Provider } from 'react-redux';
|
|
6
9
|
import thunk from 'redux-thunk';
|
|
10
|
+
import { STATUS } from 'foremanReact/constants';
|
|
7
11
|
import { foremanUrl } from 'foremanReact/common/helpers';
|
|
8
12
|
import * as api from 'foremanReact/redux/API';
|
|
9
13
|
import JobInvocationDetailPage from '../index';
|
|
@@ -11,7 +15,6 @@ import {
|
|
|
11
15
|
jobInvocationData,
|
|
12
16
|
jobInvocationDataScheduled,
|
|
13
17
|
jobInvocationDataRecurring,
|
|
14
|
-
mockPermissionsData,
|
|
15
18
|
mockReportTemplatesResponse,
|
|
16
19
|
mockReportTemplateInputsResponse,
|
|
17
20
|
} from './fixtures';
|
|
@@ -26,8 +29,10 @@ import {
|
|
|
26
29
|
CHANGE_ENABLED_RECURRING_LOGIC,
|
|
27
30
|
GET_REPORT_TEMPLATES,
|
|
28
31
|
GET_REPORT_TEMPLATE_INPUTS,
|
|
32
|
+
GET_TASK,
|
|
29
33
|
JOB_INVOCATION_KEY,
|
|
30
34
|
} from '../JobInvocationConstants';
|
|
35
|
+
import { createForemanContextWrapper } from './foremanTestHelpers';
|
|
31
36
|
|
|
32
37
|
jest.spyOn(api, 'get');
|
|
33
38
|
|
|
@@ -35,8 +40,11 @@ jest.spyOn(api, 'get');
|
|
|
35
40
|
const originalToLocaleString = Date.prototype.toLocaleString;
|
|
36
41
|
beforeAll(() => {
|
|
37
42
|
// eslint-disable-next-line no-extend-native
|
|
38
|
-
Date.prototype.toLocaleString = function (locale, options) {
|
|
39
|
-
return originalToLocaleString.call(this, locale, {
|
|
43
|
+
Date.prototype.toLocaleString = function toLocaleStringUTC(locale, options) {
|
|
44
|
+
return originalToLocaleString.call(this, locale, {
|
|
45
|
+
...options,
|
|
46
|
+
timeZone: 'UTC',
|
|
47
|
+
});
|
|
40
48
|
};
|
|
41
49
|
});
|
|
42
50
|
afterAll(() => {
|
|
@@ -44,12 +52,6 @@ afterAll(() => {
|
|
|
44
52
|
Date.prototype.toLocaleString = originalToLocaleString;
|
|
45
53
|
});
|
|
46
54
|
|
|
47
|
-
jest.mock('foremanReact/common/hooks/API/APIHooks', () => ({
|
|
48
|
-
useAPI: jest.fn(() => ({
|
|
49
|
-
response: mockPermissionsData,
|
|
50
|
-
})),
|
|
51
|
-
}));
|
|
52
|
-
|
|
53
55
|
jest.mock('foremanReact/routes/common/PageLayout/PageLayout', () =>
|
|
54
56
|
jest.fn(props => (
|
|
55
57
|
<div>
|
|
@@ -63,6 +65,7 @@ jest.mock('foremanReact/routes/common/PageLayout/PageLayout', () =>
|
|
|
63
65
|
const initialState = {
|
|
64
66
|
JOB_INVOCATION_KEY: {
|
|
65
67
|
response: jobInvocationData,
|
|
68
|
+
status: STATUS.RESOLVED,
|
|
66
69
|
},
|
|
67
70
|
GET_REPORT_TEMPLATES: mockReportTemplatesResponse,
|
|
68
71
|
extendable: {},
|
|
@@ -71,6 +74,7 @@ const initialState = {
|
|
|
71
74
|
const initialStateScheduled = {
|
|
72
75
|
JOB_INVOCATION_KEY: {
|
|
73
76
|
response: jobInvocationDataScheduled,
|
|
77
|
+
status: STATUS.RESOLVED,
|
|
74
78
|
},
|
|
75
79
|
extendable: {},
|
|
76
80
|
};
|
|
@@ -91,6 +95,15 @@ api.get.mockImplementation(({ handleSuccess, ...action }) => {
|
|
|
91
95
|
return { type: 'get', ...action };
|
|
92
96
|
});
|
|
93
97
|
|
|
98
|
+
const initialStateRecurring = {
|
|
99
|
+
JOB_INVOCATION_KEY: {
|
|
100
|
+
response: jobInvocationDataRecurring,
|
|
101
|
+
status: STATUS.RESOLVED,
|
|
102
|
+
},
|
|
103
|
+
GET_REPORT_TEMPLATES: mockReportTemplatesResponse,
|
|
104
|
+
extendable: {},
|
|
105
|
+
};
|
|
106
|
+
|
|
94
107
|
jest.mock('../JobInvocationHostTable.js', () => () => (
|
|
95
108
|
<div data-testid="mock-table">Mock Table</div>
|
|
96
109
|
));
|
|
@@ -198,6 +211,29 @@ describe('JobInvocationDetailPage', () => {
|
|
|
198
211
|
).toEqual(`/legacy/job_invocations/${jobId}`);
|
|
199
212
|
});
|
|
200
213
|
|
|
214
|
+
it('keeps toolbar buttons mounted while job invocation data is refreshing', async () => {
|
|
215
|
+
const jobId = jobInvocationData.id;
|
|
216
|
+
const store = mockStore({
|
|
217
|
+
...initialState,
|
|
218
|
+
JOB_INVOCATION_KEY: {
|
|
219
|
+
response: jobInvocationData,
|
|
220
|
+
status: STATUS.PENDING,
|
|
221
|
+
},
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
render(
|
|
225
|
+
<Provider store={store}>
|
|
226
|
+
<JobInvocationDetailPage
|
|
227
|
+
match={{ params: { id: `${jobId}` } }}
|
|
228
|
+
{...props}
|
|
229
|
+
/>
|
|
230
|
+
</Provider>
|
|
231
|
+
);
|
|
232
|
+
|
|
233
|
+
expect(screen.getByText('Create report')).toBeInTheDocument();
|
|
234
|
+
expect(screen.getByText('Rerun all')).toBeInTheDocument();
|
|
235
|
+
});
|
|
236
|
+
|
|
201
237
|
it('shows scheduled date', async () => {
|
|
202
238
|
const store = mockStore(initialStateScheduled);
|
|
203
239
|
render(
|
|
@@ -217,8 +253,9 @@ describe('JobInvocationDetailPage', () => {
|
|
|
217
253
|
it('should dispatch global actions', async () => {
|
|
218
254
|
// recurring in the future
|
|
219
255
|
const jobId = jobInvocationDataRecurring.id;
|
|
256
|
+
const taskId = jobInvocationDataRecurring.task.id;
|
|
220
257
|
const recurrenceId = jobInvocationDataRecurring.recurrence.id;
|
|
221
|
-
const store = mockStore(
|
|
258
|
+
const store = mockStore(initialStateRecurring);
|
|
222
259
|
render(
|
|
223
260
|
<Provider store={store}>
|
|
224
261
|
<JobInvocationDetailPage
|
|
@@ -232,7 +269,11 @@ describe('JobInvocationDetailPage', () => {
|
|
|
232
269
|
{ key: GET_REPORT_TEMPLATES, url: '/api/report_templates' },
|
|
233
270
|
{
|
|
234
271
|
key: JOB_INVOCATION_KEY,
|
|
235
|
-
url: `/api/job_invocations/${jobId}
|
|
272
|
+
url: `/api/job_invocations/${jobId}`,
|
|
273
|
+
},
|
|
274
|
+
{
|
|
275
|
+
key: GET_TASK,
|
|
276
|
+
url: `/foreman_tasks/api/tasks/${taskId}`,
|
|
236
277
|
},
|
|
237
278
|
{
|
|
238
279
|
key: GET_REPORT_TEMPLATE_INPUTS,
|
|
@@ -281,4 +322,61 @@ describe('JobInvocationDetailPage', () => {
|
|
|
281
322
|
}
|
|
282
323
|
});
|
|
283
324
|
});
|
|
325
|
+
|
|
326
|
+
it('renders empty state when the job invocation fails to load', () => {
|
|
327
|
+
const jobId = '99';
|
|
328
|
+
const errorMessage = 'Record not found';
|
|
329
|
+
const history = createMemoryHistory();
|
|
330
|
+
const ForemanContextWrapper = createForemanContextWrapper();
|
|
331
|
+
const store = mockStore({
|
|
332
|
+
JOB_INVOCATION_KEY: {
|
|
333
|
+
status: STATUS.ERROR,
|
|
334
|
+
response: {
|
|
335
|
+
message: errorMessage,
|
|
336
|
+
response: { status: 404 },
|
|
337
|
+
},
|
|
338
|
+
},
|
|
339
|
+
extendable: {},
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
render(
|
|
343
|
+
<Router history={history}>
|
|
344
|
+
<ForemanContextWrapper>
|
|
345
|
+
<Provider store={store}>
|
|
346
|
+
<JobInvocationDetailPage
|
|
347
|
+
match={{ params: { id: jobId } }}
|
|
348
|
+
history={history}
|
|
349
|
+
/>
|
|
350
|
+
</Provider>
|
|
351
|
+
</ForemanContextWrapper>
|
|
352
|
+
</Router>
|
|
353
|
+
);
|
|
354
|
+
|
|
355
|
+
expect(
|
|
356
|
+
screen.getByRole('heading', {
|
|
357
|
+
name: 'Unable to load job invocation',
|
|
358
|
+
level: 5,
|
|
359
|
+
})
|
|
360
|
+
).toBeInTheDocument();
|
|
361
|
+
expect(
|
|
362
|
+
screen.getByText(
|
|
363
|
+
(_, element) =>
|
|
364
|
+
element?.tagName === 'P' &&
|
|
365
|
+
element.textContent?.includes(
|
|
366
|
+
`The job invocation with id ${jobId} could not be found. It may have been deleted or may not be available in your current organization or location scope.`
|
|
367
|
+
)
|
|
368
|
+
)
|
|
369
|
+
).toBeInTheDocument();
|
|
370
|
+
expect(
|
|
371
|
+
screen.getByText(`Server returned: ${errorMessage}`)
|
|
372
|
+
).toBeInTheDocument();
|
|
373
|
+
expect(
|
|
374
|
+
screen.getByRole('button', { name: 'Go to job invocations' })
|
|
375
|
+
).toBeInTheDocument();
|
|
376
|
+
expect(
|
|
377
|
+
screen.getByRole('button', { name: 'Create a new job invocation' })
|
|
378
|
+
).toBeInTheDocument();
|
|
379
|
+
expect(screen.queryByText('Description')).not.toBeInTheDocument();
|
|
380
|
+
expect(screen.queryByTestId('mock-table')).not.toBeInTheDocument();
|
|
381
|
+
});
|
|
284
382
|
});
|
|
@@ -2,6 +2,7 @@ import '@testing-library/jest-dom/extend-expect';
|
|
|
2
2
|
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
|
|
3
3
|
import axios from 'axios';
|
|
4
4
|
import { foremanUrl } from 'foremanReact/common/helpers';
|
|
5
|
+
import { usePermissions } from 'foremanReact/common/hooks/Permissions/permissionHooks';
|
|
5
6
|
import { useAPI } from 'foremanReact/common/hooks/API/APIHooks';
|
|
6
7
|
import React from 'react';
|
|
7
8
|
import { Provider } from 'react-redux';
|
|
@@ -13,6 +14,7 @@ import { PopupAlert } from '../OpenAllInvocationsModal';
|
|
|
13
14
|
|
|
14
15
|
jest.mock('axios');
|
|
15
16
|
jest.mock('foremanReact/common/hooks/API/APIHooks');
|
|
17
|
+
jest.mock('foremanReact/common/hooks/Permissions/permissionHooks');
|
|
16
18
|
jest.mock('../JobInvocationSelectors');
|
|
17
19
|
|
|
18
20
|
jest.mock('../JobInvocationConstants', () => ({
|
|
@@ -26,8 +28,8 @@ jest.mock('../JobInvocationConstants', () => ({
|
|
|
26
28
|
selectors.selectItems.mockImplementation(() => ({
|
|
27
29
|
targeting: { search_query: 'name~*' },
|
|
28
30
|
}));
|
|
29
|
-
selectors.selectHasPermission.mockImplementation(() => () => true);
|
|
30
31
|
selectors.selectTaskCancelable.mockImplementation(() => true);
|
|
32
|
+
usePermissions.mockReturnValue(true);
|
|
31
33
|
|
|
32
34
|
const mockStore = configureStore([]);
|
|
33
35
|
const store = mockStore({});
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
import { getForemanContext } from 'foremanReact/Root/Context/ForemanContext';
|
|
4
|
+
|
|
5
|
+
export const createForemanContextWrapper = (
|
|
6
|
+
permissions = ['view_job_invocations', 'create_job_invocations']
|
|
7
|
+
) => {
|
|
8
|
+
const foremanContextValue = {
|
|
9
|
+
context: {
|
|
10
|
+
metadata: {
|
|
11
|
+
permissions: new Set(permissions),
|
|
12
|
+
UISettings: { perPage: 20 },
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
setContext: jest.fn(),
|
|
16
|
+
};
|
|
17
|
+
const ForemanContext = getForemanContext(foremanContextValue);
|
|
18
|
+
|
|
19
|
+
const ForemanContextWrapper = ({ children }) => (
|
|
20
|
+
<ForemanContext.Provider value={foremanContextValue}>
|
|
21
|
+
{children}
|
|
22
|
+
</ForemanContext.Provider>
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
ForemanContextWrapper.propTypes = {
|
|
26
|
+
children: PropTypes.node.isRequired,
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
return ForemanContextWrapper;
|
|
30
|
+
};
|
|
@@ -5,29 +5,33 @@ import {
|
|
|
5
5
|
PageSectionVariants,
|
|
6
6
|
Skeleton,
|
|
7
7
|
} from '@patternfly/react-core';
|
|
8
|
-
import React, { useEffect, useState } from 'react';
|
|
8
|
+
import React, { useEffect, useMemo, useState } from 'react';
|
|
9
9
|
import { translate as __, documentLocale } from 'foremanReact/common/I18n';
|
|
10
10
|
import { useDispatch, useSelector } from 'react-redux';
|
|
11
11
|
import PageLayout from 'foremanReact/routes/common/PageLayout/PageLayout';
|
|
12
12
|
import PropTypes from 'prop-types';
|
|
13
13
|
import SkeletonLoader from 'foremanReact/components/common/SkeletonLoader';
|
|
14
14
|
import { stopInterval } from 'foremanReact/redux/middlewares/IntervalMiddleware';
|
|
15
|
-
import {
|
|
15
|
+
import { STATUS as API_STATUS } from 'foremanReact/constants';
|
|
16
|
+
import {
|
|
17
|
+
selectAPIErrorMessage,
|
|
18
|
+
selectAPIHttpStatus,
|
|
19
|
+
selectAPIStatus,
|
|
20
|
+
} from 'foremanReact/redux/API/APISelectors';
|
|
16
21
|
|
|
17
22
|
import { JobAdditionInfo } from './JobAdditionInfo';
|
|
18
23
|
import JobInvocationHostTable from './JobInvocationHostTable';
|
|
19
24
|
import JobInvocationOverview from './JobInvocationOverview';
|
|
20
25
|
import JobInvocationSystemStatusChart from './JobInvocationSystemStatusChart';
|
|
26
|
+
import JobInvocationEmptyState from './JobInvocationEmptyState';
|
|
21
27
|
import JobInvocationToolbarButtons from './JobInvocationToolbarButtons';
|
|
22
28
|
import { getJobInvocation, getTask } from './JobInvocationActions';
|
|
23
29
|
import './JobInvocationDetail.scss';
|
|
24
30
|
import {
|
|
25
|
-
CURRENT_PERMISSIONS,
|
|
26
31
|
DATE_OPTIONS,
|
|
27
32
|
JOB_INVOCATION_KEY,
|
|
28
33
|
STATUS,
|
|
29
34
|
STATUS_UPPERCASE,
|
|
30
|
-
currentPermissionsUrl,
|
|
31
35
|
} from './JobInvocationConstants';
|
|
32
36
|
import { selectItems } from './JobInvocationSelectors';
|
|
33
37
|
|
|
@@ -51,9 +55,15 @@ const JobInvocationDetailPage = ({
|
|
|
51
55
|
statusLabel === STATUS.SUCCEEDED ||
|
|
52
56
|
statusLabel === STATUS.CANCELLED;
|
|
53
57
|
const autoRefresh = task?.state === STATUS.PENDING || false;
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
58
|
+
const jobInvocationApiStatus = useSelector(state =>
|
|
59
|
+
selectAPIStatus(state, JOB_INVOCATION_KEY)
|
|
60
|
+
);
|
|
61
|
+
const jobInvocationErrorMessage = useSelector(state =>
|
|
62
|
+
selectAPIErrorMessage(state, JOB_INVOCATION_KEY)
|
|
63
|
+
);
|
|
64
|
+
const jobInvocationHttpStatus = useSelector(state =>
|
|
65
|
+
selectAPIHttpStatus(state, JOB_INVOCATION_KEY)
|
|
66
|
+
);
|
|
57
67
|
const [selectedFilter, setSelectedFilter] = useState('');
|
|
58
68
|
|
|
59
69
|
const handleFilterChange = newFilter => {
|
|
@@ -72,7 +82,7 @@ const JobInvocationDetailPage = ({
|
|
|
72
82
|
}
|
|
73
83
|
|
|
74
84
|
useEffect(() => {
|
|
75
|
-
dispatch(getJobInvocation(`/api/job_invocations/${id}
|
|
85
|
+
dispatch(getJobInvocation(`/api/job_invocations/${id}`));
|
|
76
86
|
if (finished && !autoRefresh) {
|
|
77
87
|
dispatch(stopInterval(JOB_INVOCATION_KEY));
|
|
78
88
|
}
|
|
@@ -88,6 +98,25 @@ const JobInvocationDetailPage = ({
|
|
|
88
98
|
}
|
|
89
99
|
}, [dispatch, taskId]);
|
|
90
100
|
|
|
101
|
+
const apiFailed = jobInvocationApiStatus === API_STATUS.ERROR;
|
|
102
|
+
|
|
103
|
+
const backendErrorMessage = useMemo(() => {
|
|
104
|
+
if (jobInvocationApiStatus === API_STATUS.ERROR) {
|
|
105
|
+
return jobInvocationErrorMessage || null;
|
|
106
|
+
}
|
|
107
|
+
return null;
|
|
108
|
+
}, [jobInvocationApiStatus, jobInvocationErrorMessage]);
|
|
109
|
+
|
|
110
|
+
if (apiFailed) {
|
|
111
|
+
return (
|
|
112
|
+
<JobInvocationEmptyState
|
|
113
|
+
jobInvocationId={id}
|
|
114
|
+
httpStatus={jobInvocationHttpStatus}
|
|
115
|
+
errorMessage={backendErrorMessage}
|
|
116
|
+
/>
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
|
|
91
120
|
const pageStatus =
|
|
92
121
|
items.id === undefined
|
|
93
122
|
? STATUS_UPPERCASE.PENDING
|
|
@@ -123,7 +152,11 @@ const JobInvocationDetailPage = ({
|
|
|
123
152
|
<PageLayout
|
|
124
153
|
header={description}
|
|
125
154
|
breadcrumbOptions={breadcrumbOptions}
|
|
126
|
-
toolbarButtons={
|
|
155
|
+
toolbarButtons={
|
|
156
|
+
items.id !== undefined && (
|
|
157
|
+
<JobInvocationToolbarButtons jobId={id} data={items} />
|
|
158
|
+
)
|
|
159
|
+
}
|
|
127
160
|
searchable={false}
|
|
128
161
|
>
|
|
129
162
|
<Flex className="job-invocation-detail-flex">
|
|
@@ -1,6 +1,21 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
const getForemanContext = contextData => {
|
|
4
|
+
window.tfm_forced_singletons = window.tfm_forced_singletons || {};
|
|
5
|
+
|
|
6
|
+
if (!window.tfm_forced_singletons.Context) {
|
|
7
|
+
window.tfm_forced_singletons.Context = React.createContext(contextData);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
return window.tfm_forced_singletons.Context;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export { getForemanContext };
|
|
1
14
|
export const useForemanOrganization = () => ({ id: 1 });
|
|
2
15
|
export const useForemanLocation = () => ({ id: 2 });
|
|
3
16
|
export const useForemanVersion = () => '3.7';
|
|
4
17
|
export const useForemanHostsPageUrl = () => '/hosts';
|
|
5
18
|
export const useForemanHostDetailsPageUrl = () => '/hosts/';
|
|
6
19
|
export const useForemanSettings = () => ({ perPage: 20 });
|
|
20
|
+
export const useForemanPermissions = () =>
|
|
21
|
+
new Set(['view_job_invocations', 'create_job_invocations']);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const usePermissions = jest.fn(() => true);
|
|
@@ -19,3 +19,8 @@ export const selectAPIErrorMessage = (state, key) => {
|
|
|
19
19
|
const error = selectAPIError(state, key);
|
|
20
20
|
return error && error.message;
|
|
21
21
|
};
|
|
22
|
+
|
|
23
|
+
export const selectAPIHttpStatus = (state, key) => {
|
|
24
|
+
const error = selectAPIError(state, key);
|
|
25
|
+
return error?.response?.status;
|
|
26
|
+
};
|
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.
|
|
4
|
+
version: 16.7.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Foreman Remote Execution team
|
|
8
8
|
bindir: bin
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date: 2026-
|
|
10
|
+
date: 2026-07-13 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
13
|
name: deface
|
|
@@ -354,6 +354,7 @@ files:
|
|
|
354
354
|
- test/graphql/queries/job_invocation_query_test.rb
|
|
355
355
|
- test/graphql/queries/job_invocations_query_test.rb
|
|
356
356
|
- test/helpers/remote_execution_helper_test.rb
|
|
357
|
+
- test/integration/job_wizard_category_js_test.rb
|
|
357
358
|
- test/support/remote_execution_helper.rb
|
|
358
359
|
- test/test_plugin_helper.rb
|
|
359
360
|
- test/unit/actions/run_host_job_test.rb
|
|
@@ -381,6 +382,7 @@ files:
|
|
|
381
382
|
- webpack/JobInvocationDetail/JobInvocationActions.js
|
|
382
383
|
- webpack/JobInvocationDetail/JobInvocationConstants.js
|
|
383
384
|
- webpack/JobInvocationDetail/JobInvocationDetail.scss
|
|
385
|
+
- webpack/JobInvocationDetail/JobInvocationEmptyState.js
|
|
384
386
|
- webpack/JobInvocationDetail/JobInvocationHostTable.js
|
|
385
387
|
- webpack/JobInvocationDetail/JobInvocationOverview.js
|
|
386
388
|
- webpack/JobInvocationDetail/JobInvocationSelectors.js
|
|
@@ -394,11 +396,13 @@ files:
|
|
|
394
396
|
- webpack/JobInvocationDetail/TemplateInvocationComponents/TemplateActionButtons.js
|
|
395
397
|
- webpack/JobInvocationDetail/TemplateInvocationComponents/index.scss
|
|
396
398
|
- webpack/JobInvocationDetail/TemplateInvocationPage.js
|
|
399
|
+
- webpack/JobInvocationDetail/__tests__/JobInvocationDetailEmptyState.test.js
|
|
397
400
|
- webpack/JobInvocationDetail/__tests__/MainInformation.test.js
|
|
398
401
|
- webpack/JobInvocationDetail/__tests__/OutputCodeBlock.test.js
|
|
399
402
|
- webpack/JobInvocationDetail/__tests__/TableToolbarActions.test.js
|
|
400
403
|
- webpack/JobInvocationDetail/__tests__/TemplateInvocation.test.js
|
|
401
404
|
- webpack/JobInvocationDetail/__tests__/fixtures.js
|
|
405
|
+
- webpack/JobInvocationDetail/__tests__/foremanTestHelpers.js
|
|
402
406
|
- webpack/JobInvocationDetail/index.js
|
|
403
407
|
- webpack/JobWizard/Footer.js
|
|
404
408
|
- webpack/JobWizard/JobWizard.js
|
|
@@ -468,6 +472,7 @@ files:
|
|
|
468
472
|
- webpack/__mocks__/foremanReact/common/globalIdHelpers.js
|
|
469
473
|
- webpack/__mocks__/foremanReact/common/helpers.js
|
|
470
474
|
- webpack/__mocks__/foremanReact/common/hooks/API/APIHooks.js
|
|
475
|
+
- webpack/__mocks__/foremanReact/common/hooks/Permissions/permissionHooks.js
|
|
471
476
|
- webpack/__mocks__/foremanReact/components/AutoComplete/AutoCompleteActions.js
|
|
472
477
|
- webpack/__mocks__/foremanReact/components/AutoComplete/AutoCompleteConstants.js
|
|
473
478
|
- webpack/__mocks__/foremanReact/components/BreadcrumbBar/index.js
|