foreman_remote_execution 17.2.0 → 18.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.
Files changed (26) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/api/v2/foreign_input_sets_controller.rb +4 -0
  3. data/app/controllers/job_invocations_controller.rb +16 -1
  4. data/config/routes.rb +2 -1
  5. data/db/seeds.d/60-ssh_proxy_feature.rb +2 -2
  6. data/db/seeds.d/90-bookmarks.rb +1 -1
  7. data/db/seeds.d/95-mail_notifications.rb +1 -1
  8. data/lib/foreman_remote_execution/plugin.rb +2 -2
  9. data/lib/foreman_remote_execution/version.rb +1 -1
  10. data/test/functional/job_invocations_controller_test.rb +84 -0
  11. data/webpack/JobInvocationDetail/JobInvocationConstants.js +10 -2
  12. data/webpack/JobInvocationDetail/JobInvocationHostTable.js +8 -1
  13. data/webpack/JobInvocationDetail/JobInvocationToolbarButtons.js +6 -78
  14. data/webpack/JobInvocationDetail/__tests__/JobInvocationHostTablePolling.test.js +113 -7
  15. data/webpack/JobInvocationDetail/__tests__/MainInformation.test.js +4 -39
  16. data/webpack/JobInvocationDetail/__tests__/areAllHostsTerminal.test.js +40 -0
  17. data/webpack/JobInvocationDetail/__tests__/fixtures.js +0 -8
  18. data/webpack/JobWizard/Footer.js +16 -13
  19. data/webpack/JobWizard/__tests__/Footer.test.js +64 -0
  20. data/webpack/JobWizard/__tests__/integration.test.js +98 -53
  21. data/webpack/JobWizard/steps/AdvancedFields/__tests__/AdvancedFields.test.js +191 -212
  22. data/webpack/react_app/components/TargetingHosts/__tests__/HostItem.test.js +73 -3
  23. data/webpack/react_app/components/jobInvocations/AggregateStatus/index.test.js +69 -36
  24. metadata +5 -5
  25. data/webpack/JobWizard/__tests__/__snapshots__/integration.test.js.snap +0 -51
  26. data/webpack/react_app/components/TargetingHosts/__tests__/__snapshots__/HostItem.test.js.snap +0 -31
@@ -1,43 +1,76 @@
1
1
  import React from 'react';
2
- import { shallow } from '@theforeman/test';
2
+ import { render, screen } from '@testing-library/react';
3
+ import userEvent from '@testing-library/user-event';
4
+ import '@testing-library/jest-dom';
3
5
  import AggregateStatus from './index';
4
6
 
5
- jest.unmock('./index.js');
7
+ const defaultStatuses = {
8
+ success: 19,
9
+ failed: 20,
10
+ pending: 3,
11
+ cancelled: 31,
12
+ };
13
+
14
+ const renderAggregateStatus = ({
15
+ statuses = defaultStatuses,
16
+ chartFilter = jest.fn(),
17
+ } = {}) => {
18
+ const view = render(
19
+ <AggregateStatus statuses={statuses} chartFilter={chartFilter} />
20
+ );
21
+
22
+ return { chartFilter, ...view };
23
+ };
6
24
 
7
25
  describe('AggregateStatus', () => {
8
- describe('has no data', () => {
9
- it('renders cards with no data', () => {
10
- const chartNumbers = shallow(
11
- <AggregateStatus statuses={{}} chartFilter={_x => {}} />
12
- );
13
- const success = chartNumbers.find('#success_count').text();
14
- const failed = chartNumbers.find('#failed_count').text();
15
- const pending = chartNumbers.find('#pending_count').text();
16
- const cancelled = chartNumbers.find('#cancelled_count').text();
17
- expect(success).toBe('');
18
- expect(failed).toBe('');
19
- expect(cancelled).toBe('');
20
- expect(pending).toBe('');
21
- });
22
-
23
- it('renders cards with props passed', () => {
24
- const statuses = {
25
- success: 19,
26
- failed: 20,
27
- cancelled: 31,
28
- pending: 3,
29
- };
30
- const chartNumbers = shallow(
31
- <AggregateStatus statuses={statuses} chartFilter={_x => {}} />
32
- );
33
- const success = chartNumbers.find('#success_count').text();
34
- const failed = chartNumbers.find('#failed_count').text();
35
- const pending = chartNumbers.find('#pending_count').text();
36
- const cancelled = chartNumbers.find('#cancelled_count').text();
37
- expect(success).toBe(statuses.success.toString());
38
- expect(failed).toBe(statuses.failed.toString());
39
- expect(cancelled).toBe(statuses.cancelled.toString());
40
- expect(pending).toBe(statuses.pending.toString());
41
- });
26
+ it('renders status notifications without counts when statuses are empty', () => {
27
+ const { container } = renderAggregateStatus({ statuses: {} });
28
+
29
+ expect(container.textContent.trim()).toBe('');
30
+ });
31
+
32
+ it('renders status counts from props', () => {
33
+ renderAggregateStatus();
34
+
35
+ expect(screen.getByText('19')).toBeInTheDocument();
36
+ expect(screen.getByText('20')).toBeInTheDocument();
37
+ expect(screen.getByText('3')).toBeInTheDocument();
38
+ expect(screen.getByText('31')).toBeInTheDocument();
39
+ });
40
+
41
+ it('calls chartFilter with success when the success count is clicked', async () => {
42
+ const { chartFilter } = renderAggregateStatus();
43
+
44
+ await userEvent.click(screen.getByText('19'));
45
+
46
+ expect(chartFilter).toHaveBeenCalledTimes(1);
47
+ expect(chartFilter).toHaveBeenCalledWith('success');
48
+ });
49
+
50
+ it('calls chartFilter with failed when the failed count is clicked', async () => {
51
+ const { chartFilter } = renderAggregateStatus();
52
+
53
+ await userEvent.click(screen.getByText('20'));
54
+
55
+ expect(chartFilter).toHaveBeenCalledTimes(1);
56
+ expect(chartFilter).toHaveBeenCalledWith('failed');
57
+ });
58
+
59
+ it('calls chartFilter with pending when the pending count is clicked', async () => {
60
+ const { chartFilter } = renderAggregateStatus();
61
+
62
+ await userEvent.click(screen.getByText('3'));
63
+
64
+ expect(chartFilter).toHaveBeenCalledTimes(1);
65
+ expect(chartFilter).toHaveBeenCalledWith('pending');
66
+ });
67
+
68
+ it('calls chartFilter with cancelled when the cancelled count is clicked', async () => {
69
+ const { chartFilter } = renderAggregateStatus();
70
+
71
+ await userEvent.click(screen.getByText('31'));
72
+
73
+ expect(chartFilter).toHaveBeenCalledTimes(1);
74
+ expect(chartFilter).toHaveBeenCalledWith('cancelled');
42
75
  });
43
76
  });
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: 17.2.0
4
+ version: 18.0.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-08-24 00:00:00.000000000 Z
10
+ date: 2026-09-15 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: deface
@@ -405,6 +405,7 @@ files:
405
405
  - webpack/JobInvocationDetail/__tests__/TableToolbarActions.test.js
406
406
  - webpack/JobInvocationDetail/__tests__/TemplateInvocation.test.js
407
407
  - webpack/JobInvocationDetail/__tests__/TemplateInvocationPolling.test.js
408
+ - webpack/JobInvocationDetail/__tests__/areAllHostsTerminal.test.js
408
409
  - webpack/JobInvocationDetail/__tests__/fixtures.js
409
410
  - webpack/JobInvocationDetail/__tests__/foremanTestHelpers.js
410
411
  - webpack/JobInvocationDetail/index.js
@@ -417,8 +418,8 @@ files:
417
418
  - webpack/JobWizard/JobWizardSelectors.js
418
419
  - webpack/JobWizard/PermissionDenied.js
419
420
  - webpack/JobWizard/StartsErrorAlert.js
421
+ - webpack/JobWizard/__tests__/Footer.test.js
420
422
  - webpack/JobWizard/__tests__/JobWizardPageRerun.test.js
421
- - webpack/JobWizard/__tests__/__snapshots__/integration.test.js.snap
422
423
  - webpack/JobWizard/__tests__/fixtures.js
423
424
  - webpack/JobWizard/__tests__/integration.test.js
424
425
  - webpack/JobWizard/__tests__/validation.test.js
@@ -525,7 +526,6 @@ files:
525
526
  - webpack/react_app/components/TargetingHosts/__tests__/TargetingHosts.test.js
526
527
  - webpack/react_app/components/TargetingHosts/__tests__/TargetingHostsPage.test.js
527
528
  - webpack/react_app/components/TargetingHosts/__tests__/TargetingHostsSelectors.test.js
528
- - webpack/react_app/components/TargetingHosts/__tests__/__snapshots__/HostItem.test.js.snap
529
529
  - webpack/react_app/components/TargetingHosts/__tests__/__snapshots__/HostStatus.test.js.snap
530
530
  - webpack/react_app/components/TargetingHosts/__tests__/__snapshots__/TargetingHosts.test.js.snap
531
531
  - webpack/react_app/components/TargetingHosts/__tests__/__snapshots__/TargetingHostsPage.test.js.snap
@@ -567,7 +567,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
567
567
  - !ruby/object:Gem::Version
568
568
  version: '0'
569
569
  requirements: []
570
- rubygems_version: 4.0.16
570
+ rubygems_version: 4.0.20
571
571
  specification_version: 4
572
572
  summary: A plugin bringing remote execution to the Foreman, completing the config
573
573
  management functionality with remote management functionality.
@@ -1,51 +0,0 @@
1
- // Jest Snapshot v1, https://goo.gl/fbAQLP
2
-
3
- exports[`Job wizard fill should select template: initial 1`] = `
4
- Array [
5
- Object {
6
- "key": "JOB_CATEGORIES",
7
- "type": "get",
8
- "url": "/ui_job_wizard/categories",
9
- },
10
- Object {
11
- "key": "HOST_IDS",
12
- "params": Object {
13
- "search": "id = 105 or id = 37",
14
- },
15
- "type": "get",
16
- "url": "/api/hosts",
17
- },
18
- Object {
19
- "key": "JOB_TEMPLATES",
20
- "type": "get",
21
- "url": URI {
22
- "_deferred_build": true,
23
- "_parts": Object {
24
- "duplicateQueryParameters": false,
25
- "escapeQuerySpace": true,
26
- "fragment": null,
27
- "hostname": null,
28
- "password": null,
29
- "path": "foreman/api/v2/job_templates",
30
- "port": null,
31
- "preventInvalidHostname": false,
32
- "protocol": null,
33
- "query": "search=job_category%3D%22Ansible+Commands%22&per_page=all",
34
- "urn": null,
35
- "username": null,
36
- },
37
- "_string": "",
38
- },
39
- },
40
- ]
41
- `;
42
-
43
- exports[`Job wizard fill should select template: select template 1`] = `
44
- Array [
45
- Object {
46
- "key": "JOB_TEMPLATE",
47
- "type": "get",
48
- "url": "/ui_job_wizard/template/178",
49
- },
50
- ]
51
- `;
@@ -1,31 +0,0 @@
1
- // Jest Snapshot v1, https://goo.gl/fbAQLP
2
-
3
- exports[`HostItem renders 1`] = `
4
- <tr
5
- id="targeting-host-Host1"
6
- >
7
- <td
8
- className="host_name"
9
- >
10
- <a
11
- href="/host1"
12
- >
13
- Host1
14
- </a>
15
- </td>
16
- <td
17
- className="host_status"
18
- >
19
- <HostStatus
20
- status="success"
21
- />
22
- </td>
23
- <td
24
- className="host_actions"
25
- >
26
- <ActionButtons
27
- buttons={Array []}
28
- />
29
- </td>
30
- </tr>
31
- `;