foreman_remote_execution 16.6.5 → 17.0.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 +16 -11
- data/app/views/job_templates/_alerts.html.erb +4 -0
- data/lib/foreman_remote_execution/plugin.rb +1 -1
- 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/webpack/JobInvocationDetail/CheckboxesActions.js +4 -10
- data/webpack/JobInvocationDetail/JobInvocationActions.js +80 -90
- data/webpack/JobInvocationDetail/JobInvocationConstants.js +7 -6
- data/webpack/JobInvocationDetail/JobInvocationEmptyState.js +52 -0
- data/webpack/JobInvocationDetail/JobInvocationHostTable.js +76 -42
- data/webpack/JobInvocationDetail/JobInvocationSelectors.js +1 -19
- data/webpack/JobInvocationDetail/JobInvocationToolbarButtons.js +202 -153
- data/webpack/JobInvocationDetail/TemplateInvocation.js +31 -25
- data/webpack/JobInvocationDetail/__tests__/JobInvocationDetailEmptyState.test.js +53 -0
- data/webpack/JobInvocationDetail/__tests__/JobInvocationHostTablePolling.test.js +336 -0
- data/webpack/JobInvocationDetail/__tests__/JobInvocationPolling.test.js +223 -0
- data/webpack/JobInvocationDetail/__tests__/MainInformation.test.js +260 -111
- data/webpack/JobInvocationDetail/__tests__/TableToolbarActions.test.js +3 -1
- data/webpack/JobInvocationDetail/__tests__/TemplateInvocationPolling.test.js +254 -0
- data/webpack/JobInvocationDetail/__tests__/fixtures.js +2 -0
- data/webpack/JobInvocationDetail/__tests__/foremanTestHelpers.js +30 -0
- data/webpack/JobInvocationDetail/index.js +50 -30
- 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
- data/webpack/test_setup.js +1 -13
- metadata +11 -3
|
@@ -1,17 +1,20 @@
|
|
|
1
|
+
/* eslint-disable max-lines */
|
|
1
2
|
import React from 'react';
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import '
|
|
5
|
-
import {
|
|
6
|
-
import
|
|
3
|
+
import { fireEvent, screen, act } from '@testing-library/react';
|
|
4
|
+
import '@testing-library/jest-dom';
|
|
5
|
+
import { createMemoryHistory } from 'history';
|
|
6
|
+
import { Router } from 'react-router-dom';
|
|
7
|
+
import { rtlHelpers } from 'foremanReact/common/testHelpers';
|
|
8
|
+
import { STATUS } from 'foremanReact/constants';
|
|
7
9
|
import { foremanUrl } from 'foremanReact/common/helpers';
|
|
10
|
+
import { usePermissions } from 'foremanReact/common/hooks/Permissions/permissionHooks';
|
|
8
11
|
import * as api from 'foremanReact/redux/API';
|
|
12
|
+
import { APIActions } from 'foremanReact/redux/API';
|
|
9
13
|
import JobInvocationDetailPage from '../index';
|
|
10
14
|
import {
|
|
11
15
|
jobInvocationData,
|
|
12
16
|
jobInvocationDataScheduled,
|
|
13
17
|
jobInvocationDataRecurring,
|
|
14
|
-
mockPermissionsData,
|
|
15
18
|
mockReportTemplatesResponse,
|
|
16
19
|
mockReportTemplateInputsResponse,
|
|
17
20
|
} from './fixtures';
|
|
@@ -20,6 +23,7 @@ import {
|
|
|
20
23
|
enableRecurringLogic,
|
|
21
24
|
cancelRecurringLogic,
|
|
22
25
|
} from '../JobInvocationActions';
|
|
26
|
+
import { createForemanContextWrapper } from './foremanTestHelpers';
|
|
23
27
|
import {
|
|
24
28
|
CANCEL_JOB,
|
|
25
29
|
CANCEL_RECURRING_LOGIC,
|
|
@@ -29,14 +33,38 @@ import {
|
|
|
29
33
|
JOB_INVOCATION_KEY,
|
|
30
34
|
} from '../JobInvocationConstants';
|
|
31
35
|
|
|
36
|
+
const { renderWithStore } = rtlHelpers;
|
|
37
|
+
|
|
38
|
+
jest.mock('foremanReact/redux/API/APISelectors', () =>
|
|
39
|
+
jest.requireActual('foremanReact/redux/API/APISelectors')
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
jest.mock('foremanReact/common/hooks/Permissions/permissionHooks');
|
|
43
|
+
jest.mock('../JobInvocationActions', () => {
|
|
44
|
+
const actual = jest.requireActual('../JobInvocationActions');
|
|
45
|
+
|
|
46
|
+
return {
|
|
47
|
+
...actual,
|
|
48
|
+
getJobInvocation: jest.fn(() => () => undefined),
|
|
49
|
+
stopJobInvocationPolling: jest.fn(),
|
|
50
|
+
};
|
|
51
|
+
});
|
|
52
|
+
|
|
32
53
|
jest.spyOn(api, 'get');
|
|
54
|
+
jest.spyOn(APIActions, 'post');
|
|
55
|
+
jest.spyOn(APIActions, 'put');
|
|
56
|
+
|
|
57
|
+
usePermissions.mockReturnValue(true);
|
|
33
58
|
|
|
34
59
|
// Mock toLocaleString to always use UTC timezone for consistent test results
|
|
35
60
|
const originalToLocaleString = Date.prototype.toLocaleString;
|
|
36
61
|
beforeAll(() => {
|
|
37
62
|
// eslint-disable-next-line no-extend-native
|
|
38
|
-
Date.prototype.toLocaleString = function (locale, options) {
|
|
39
|
-
return originalToLocaleString.call(this, locale, {
|
|
63
|
+
Date.prototype.toLocaleString = function toLocaleStringUTC(locale, options) {
|
|
64
|
+
return originalToLocaleString.call(this, locale, {
|
|
65
|
+
...options,
|
|
66
|
+
timeZone: 'UTC',
|
|
67
|
+
});
|
|
40
68
|
};
|
|
41
69
|
});
|
|
42
70
|
afterAll(() => {
|
|
@@ -44,12 +72,6 @@ afterAll(() => {
|
|
|
44
72
|
Date.prototype.toLocaleString = originalToLocaleString;
|
|
45
73
|
});
|
|
46
74
|
|
|
47
|
-
jest.mock('foremanReact/common/hooks/API/APIHooks', () => ({
|
|
48
|
-
useAPI: jest.fn(() => ({
|
|
49
|
-
response: mockPermissionsData,
|
|
50
|
-
})),
|
|
51
|
-
}));
|
|
52
|
-
|
|
53
75
|
jest.mock('foremanReact/routes/common/PageLayout/PageLayout', () =>
|
|
54
76
|
jest.fn(props => (
|
|
55
77
|
<div>
|
|
@@ -60,36 +82,50 @@ jest.mock('foremanReact/routes/common/PageLayout/PageLayout', () =>
|
|
|
60
82
|
))
|
|
61
83
|
);
|
|
62
84
|
|
|
63
|
-
const
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
};
|
|
85
|
+
const setupApiMocks = () => {
|
|
86
|
+
api.get.mockImplementation(({ handleSuccess, key, ...action }) => {
|
|
87
|
+
if (key === GET_REPORT_TEMPLATES) {
|
|
88
|
+
if (handleSuccess) {
|
|
89
|
+
handleSuccess({
|
|
90
|
+
data: mockReportTemplatesResponse,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
} else if (key === GET_REPORT_TEMPLATE_INPUTS) {
|
|
94
|
+
if (handleSuccess) {
|
|
95
|
+
handleSuccess({
|
|
96
|
+
data: mockReportTemplateInputsResponse,
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
}
|
|
70
100
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
}
|
|
75
|
-
extendable: {},
|
|
101
|
+
return { type: 'get', key, ...action };
|
|
102
|
+
});
|
|
103
|
+
APIActions.post.mockImplementation(payload => ({ type: 'post', ...payload }));
|
|
104
|
+
APIActions.put.mockImplementation(payload => ({ type: 'put', ...payload }));
|
|
76
105
|
};
|
|
77
106
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
handleSuccess &&
|
|
86
|
-
handleSuccess({
|
|
87
|
-
data: mockReportTemplateInputsResponse,
|
|
88
|
-
});
|
|
89
|
-
}
|
|
107
|
+
const createJobInvocationDetailState = ({
|
|
108
|
+
jobInvocation = jobInvocationData,
|
|
109
|
+
jobInvocationStatus = STATUS.RESOLVED,
|
|
110
|
+
jobInvocationError = null,
|
|
111
|
+
} = {}) => {
|
|
112
|
+
const jobInvocationResponse =
|
|
113
|
+
jobInvocationError || JSON.parse(JSON.stringify(jobInvocation));
|
|
90
114
|
|
|
91
|
-
return {
|
|
92
|
-
|
|
115
|
+
return {
|
|
116
|
+
API: {
|
|
117
|
+
[JOB_INVOCATION_KEY]: jobInvocationError
|
|
118
|
+
? {
|
|
119
|
+
response: jobInvocationResponse,
|
|
120
|
+
status: STATUS.ERROR,
|
|
121
|
+
}
|
|
122
|
+
: {
|
|
123
|
+
response: jobInvocationResponse,
|
|
124
|
+
status: jobInvocationStatus,
|
|
125
|
+
},
|
|
126
|
+
},
|
|
127
|
+
};
|
|
128
|
+
};
|
|
93
129
|
|
|
94
130
|
jest.mock('../JobInvocationHostTable.js', () => () => (
|
|
95
131
|
<div data-testid="mock-table">Mock Table</div>
|
|
@@ -97,21 +133,62 @@ jest.mock('../JobInvocationHostTable.js', () => () => (
|
|
|
97
133
|
|
|
98
134
|
const reportTemplateJobId = mockReportTemplatesResponse.results[0].id;
|
|
99
135
|
|
|
100
|
-
const
|
|
101
|
-
|
|
136
|
+
const defaultHistory = { push: jest.fn() };
|
|
137
|
+
|
|
138
|
+
const renderJobInvocationDetailPage = (
|
|
139
|
+
initialState,
|
|
140
|
+
{ jobId, history = defaultHistory } = {}
|
|
141
|
+
) => {
|
|
142
|
+
const id =
|
|
143
|
+
jobId ?? initialState.API?.[JOB_INVOCATION_KEY]?.response?.id ?? '1';
|
|
144
|
+
|
|
145
|
+
return renderWithStore(
|
|
146
|
+
<JobInvocationDetailPage
|
|
147
|
+
match={{ params: { id: `${id}` } }}
|
|
148
|
+
history={history}
|
|
149
|
+
/>,
|
|
150
|
+
initialState,
|
|
151
|
+
undefined
|
|
152
|
+
);
|
|
153
|
+
};
|
|
102
154
|
|
|
103
155
|
describe('JobInvocationDetailPage', () => {
|
|
156
|
+
beforeEach(() => {
|
|
157
|
+
setupApiMocks();
|
|
158
|
+
usePermissions.mockReturnValue(true);
|
|
159
|
+
|
|
160
|
+
const { getJobInvocation } = jest.requireMock('../JobInvocationActions');
|
|
161
|
+
getJobInvocation.mockImplementation(() => () => undefined);
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
afterEach(() => {
|
|
165
|
+
api.get.mockClear();
|
|
166
|
+
APIActions.post.mockClear();
|
|
167
|
+
APIActions.put.mockClear();
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
it('shows scheduled date', async () => {
|
|
171
|
+
const scheduledJobInvocation = JSON.parse(
|
|
172
|
+
JSON.stringify(jobInvocationDataScheduled)
|
|
173
|
+
);
|
|
174
|
+
|
|
175
|
+
renderJobInvocationDetailPage(
|
|
176
|
+
createJobInvocationDetailState({
|
|
177
|
+
jobInvocation: scheduledJobInvocation,
|
|
178
|
+
}),
|
|
179
|
+
{ jobId: jobInvocationDataScheduled.id }
|
|
180
|
+
);
|
|
181
|
+
|
|
182
|
+
expect(screen.getByText('Scheduled at:')).toBeInTheDocument();
|
|
183
|
+
expect(screen.getByText('Jan 1, 3000, 11:34 UTC')).toBeInTheDocument();
|
|
184
|
+
expect(screen.getByText('Not yet')).toBeInTheDocument();
|
|
185
|
+
});
|
|
186
|
+
|
|
104
187
|
it('renders main information', async () => {
|
|
105
188
|
const jobId = jobInvocationData.id;
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
<Provider store={store}>
|
|
110
|
-
<JobInvocationDetailPage
|
|
111
|
-
match={{ params: { id: `${jobId}` } }}
|
|
112
|
-
{...props}
|
|
113
|
-
/>
|
|
114
|
-
</Provider>
|
|
189
|
+
|
|
190
|
+
const { container } = renderJobInvocationDetailPage(
|
|
191
|
+
createJobInvocationDetailState()
|
|
115
192
|
);
|
|
116
193
|
|
|
117
194
|
expect(screen.getByText('Description')).toBeInTheDocument();
|
|
@@ -198,87 +275,159 @@ describe('JobInvocationDetailPage', () => {
|
|
|
198
275
|
).toEqual(`/legacy/job_invocations/${jobId}`);
|
|
199
276
|
});
|
|
200
277
|
|
|
201
|
-
it('
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
match={{ params: { id: `${jobInvocationDataScheduled.id}` } }}
|
|
207
|
-
{...props}
|
|
208
|
-
/>
|
|
209
|
-
</Provider>
|
|
278
|
+
it('keeps toolbar buttons mounted while job invocation data is refreshing', async () => {
|
|
279
|
+
renderJobInvocationDetailPage(
|
|
280
|
+
createJobInvocationDetailState({
|
|
281
|
+
jobInvocationStatus: STATUS.PENDING,
|
|
282
|
+
})
|
|
210
283
|
);
|
|
211
284
|
|
|
212
|
-
expect(screen.getByText('
|
|
213
|
-
expect(screen.getByText('
|
|
214
|
-
|
|
285
|
+
expect(screen.getByText('Create report')).toBeInTheDocument();
|
|
286
|
+
expect(screen.getByText('Rerun all')).toBeInTheDocument();
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
it('disables Create report when the job task state is running', async () => {
|
|
290
|
+
usePermissions.mockImplementation(requiredPermissions =>
|
|
291
|
+
requiredPermissions.includes('generate_report_templates')
|
|
292
|
+
);
|
|
293
|
+
|
|
294
|
+
renderJobInvocationDetailPage(
|
|
295
|
+
createJobInvocationDetailState({
|
|
296
|
+
jobInvocation: {
|
|
297
|
+
...jobInvocationData,
|
|
298
|
+
task: { ...jobInvocationData.task, state: 'running' },
|
|
299
|
+
},
|
|
300
|
+
})
|
|
301
|
+
);
|
|
302
|
+
|
|
303
|
+
const createReportButton = screen.getByRole('link', {
|
|
304
|
+
name: 'Create report',
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
expect(createReportButton).toHaveAttribute('aria-disabled', 'true');
|
|
308
|
+
expect(createReportButton).toHaveClass('pf-m-disabled');
|
|
215
309
|
});
|
|
216
310
|
|
|
217
311
|
it('should dispatch global actions', async () => {
|
|
218
|
-
// recurring in the future
|
|
219
312
|
const jobId = jobInvocationDataRecurring.id;
|
|
220
313
|
const recurrenceId = jobInvocationDataRecurring.recurrence.id;
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
/>
|
|
228
|
-
</Provider>
|
|
314
|
+
|
|
315
|
+
const { store } = renderJobInvocationDetailPage(
|
|
316
|
+
createJobInvocationDetailState({
|
|
317
|
+
jobInvocation: jobInvocationDataRecurring,
|
|
318
|
+
}),
|
|
319
|
+
{ jobId }
|
|
229
320
|
);
|
|
230
321
|
|
|
231
|
-
|
|
232
|
-
{
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
322
|
+
expect(api.get).toHaveBeenCalledWith(
|
|
323
|
+
expect.objectContaining({
|
|
324
|
+
key: GET_REPORT_TEMPLATES,
|
|
325
|
+
url: '/api/report_templates',
|
|
326
|
+
})
|
|
327
|
+
);
|
|
328
|
+
expect(api.get).toHaveBeenCalledWith(
|
|
329
|
+
expect.objectContaining({
|
|
238
330
|
key: GET_REPORT_TEMPLATE_INPUTS,
|
|
239
331
|
url: `/api/templates/${reportTemplateJobId}/template_inputs`,
|
|
240
|
-
}
|
|
241
|
-
|
|
332
|
+
})
|
|
333
|
+
);
|
|
334
|
+
|
|
335
|
+
api.get.mockClear();
|
|
336
|
+
APIActions.post.mockClear();
|
|
337
|
+
APIActions.put.mockClear();
|
|
338
|
+
|
|
339
|
+
store.dispatch(cancelJob(jobId, false));
|
|
340
|
+
store.dispatch(cancelJob(jobId, true));
|
|
341
|
+
store.dispatch(enableRecurringLogic(recurrenceId, true));
|
|
342
|
+
store.dispatch(enableRecurringLogic(recurrenceId, false));
|
|
343
|
+
store.dispatch(cancelRecurringLogic(recurrenceId));
|
|
344
|
+
|
|
345
|
+
expect(APIActions.post).toHaveBeenNthCalledWith(
|
|
346
|
+
1,
|
|
347
|
+
expect.objectContaining({
|
|
242
348
|
key: CANCEL_JOB,
|
|
243
349
|
url: `/job_invocations/${jobId}/cancel`,
|
|
244
|
-
}
|
|
245
|
-
|
|
350
|
+
})
|
|
351
|
+
);
|
|
352
|
+
expect(APIActions.post).toHaveBeenNthCalledWith(
|
|
353
|
+
2,
|
|
354
|
+
expect.objectContaining({
|
|
246
355
|
key: CANCEL_JOB,
|
|
247
356
|
url: `/job_invocations/${jobId}/cancel?force=true`,
|
|
248
|
-
}
|
|
249
|
-
|
|
357
|
+
})
|
|
358
|
+
);
|
|
359
|
+
expect(APIActions.put).toHaveBeenNthCalledWith(
|
|
360
|
+
1,
|
|
361
|
+
expect.objectContaining({
|
|
250
362
|
key: CHANGE_ENABLED_RECURRING_LOGIC,
|
|
251
363
|
url: `/foreman_tasks/api/recurring_logics/${recurrenceId}`,
|
|
252
|
-
}
|
|
253
|
-
|
|
364
|
+
})
|
|
365
|
+
);
|
|
366
|
+
expect(APIActions.put).toHaveBeenNthCalledWith(
|
|
367
|
+
2,
|
|
368
|
+
expect.objectContaining({
|
|
254
369
|
key: CHANGE_ENABLED_RECURRING_LOGIC,
|
|
255
370
|
url: `/foreman_tasks/api/recurring_logics/${recurrenceId}`,
|
|
256
|
-
}
|
|
257
|
-
|
|
371
|
+
})
|
|
372
|
+
);
|
|
373
|
+
expect(APIActions.post).toHaveBeenNthCalledWith(
|
|
374
|
+
3,
|
|
375
|
+
expect.objectContaining({
|
|
258
376
|
key: CANCEL_RECURRING_LOGIC,
|
|
259
377
|
url: `/foreman_tasks/recurring_logics/${recurrenceId}/cancel`,
|
|
260
|
-
}
|
|
261
|
-
|
|
378
|
+
})
|
|
379
|
+
);
|
|
380
|
+
});
|
|
262
381
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
382
|
+
it('renders empty state when the job invocation fails to load', () => {
|
|
383
|
+
const jobId = '99';
|
|
384
|
+
const errorMessage = 'Record not found';
|
|
385
|
+
const history = createMemoryHistory();
|
|
386
|
+
const ForemanContextWrapper = createForemanContextWrapper();
|
|
387
|
+
|
|
388
|
+
renderWithStore(
|
|
389
|
+
<Router history={history}>
|
|
390
|
+
<ForemanContextWrapper>
|
|
391
|
+
<JobInvocationDetailPage
|
|
392
|
+
match={{ params: { id: jobId } }}
|
|
393
|
+
history={history}
|
|
394
|
+
/>
|
|
395
|
+
</ForemanContextWrapper>
|
|
396
|
+
</Router>,
|
|
397
|
+
createJobInvocationDetailState({
|
|
398
|
+
jobInvocationError: {
|
|
399
|
+
message: errorMessage,
|
|
400
|
+
response: { status: 404 },
|
|
401
|
+
},
|
|
402
|
+
}),
|
|
403
|
+
undefined
|
|
404
|
+
);
|
|
405
|
+
|
|
406
|
+
expect(
|
|
407
|
+
screen.getByRole('heading', {
|
|
408
|
+
name: 'Unable to load job invocation',
|
|
409
|
+
level: 5,
|
|
410
|
+
})
|
|
411
|
+
).toBeInTheDocument();
|
|
412
|
+
expect(
|
|
413
|
+
screen.getByText(
|
|
414
|
+
(_, element) =>
|
|
415
|
+
element?.tagName === 'P' &&
|
|
416
|
+
element.textContent?.includes(
|
|
417
|
+
`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.`
|
|
418
|
+
)
|
|
419
|
+
)
|
|
420
|
+
).toBeInTheDocument();
|
|
421
|
+
expect(
|
|
422
|
+
screen.getByText(`Server returned: ${errorMessage}`)
|
|
423
|
+
).toBeInTheDocument();
|
|
424
|
+
expect(
|
|
425
|
+
screen.getByRole('button', { name: 'Go to job invocations' })
|
|
426
|
+
).toBeInTheDocument();
|
|
427
|
+
expect(
|
|
428
|
+
screen.getByRole('button', { name: 'Create a new job invocation' })
|
|
429
|
+
).toBeInTheDocument();
|
|
430
|
+
expect(screen.queryByText('Description')).not.toBeInTheDocument();
|
|
431
|
+
expect(screen.queryByTestId('mock-table')).not.toBeInTheDocument();
|
|
283
432
|
});
|
|
284
433
|
});
|
|
@@ -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({});
|