foreman_puppet 10.1.3 → 11.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.
- checksums.yaml +4 -4
- data/app/controllers/concerns/foreman_puppet/extensions/hosts_controller_extensions.rb +1 -1
- data/app/controllers/foreman_puppet/api/v2/hosts_bulk_actions_controller.rb +75 -1
- data/app/models/concerns/foreman_puppet/extensions/host.rb +2 -2
- data/app/models/concerns/foreman_puppet/extensions/host_common.rb +35 -0
- data/app/models/concerns/foreman_puppet/extensions/hostgroup.rb +10 -3
- data/app/models/foreman_puppet/config_group.rb +6 -0
- data/app/models/foreman_puppet/puppetclass.rb +14 -0
- data/app/services/concerns/foreman_puppet/extensions/bulk_hosts_manager.rb +18 -0
- data/config/api_routes.rb +1 -0
- data/db/seeds.d/111_puppet_proxy_feature.rb +1 -1
- data/lib/foreman_puppet/register.rb +2 -1
- data/lib/foreman_puppet/version.rb +1 -1
- data/test/controllers/foreman_puppet/api/v2/hosts_bulk_actions_controller_test.rb +93 -0
- data/test/models/foreman_puppet/host_test.rb +66 -0
- data/test/models/foreman_puppet/hostgroup_test.rb +32 -0
- data/test/services/foreman_puppet/bulk_hosts_manager_test.rb +45 -0
- data/webpack/__mocks__/foremanReact/redux/API/index.js +8 -0
- data/webpack/global_index.js +18 -1
- data/webpack/src/Extends/Hosts/ActionsBar/index.js +20 -0
- data/webpack/src/Extends/Hosts/BulkActions/BulkChangeProxyCommon/__tests__/actions.test.js +0 -7
- data/webpack/src/Extends/Hosts/BulkActions/BulkChangeProxyCommon/index.js +9 -13
- data/webpack/src/Extends/Hosts/BulkActions/BulkChangePuppetCAProxy/__tests__/index.test.js +3 -0
- data/webpack/src/Extends/Hosts/BulkActions/BulkChangePuppetCAProxy/index.js +2 -0
- data/webpack/src/Extends/Hosts/BulkActions/BulkChangePuppetEnvironment/BulkChangePuppetEnvironmentModal.js +239 -0
- data/webpack/src/Extends/Hosts/BulkActions/BulkChangePuppetEnvironment/__tests__/BulkChangePuppetEnvironmentModal.test.js +155 -0
- data/webpack/src/Extends/Hosts/BulkActions/BulkChangePuppetEnvironment/__tests__/actions.test.js +49 -0
- data/webpack/src/Extends/Hosts/BulkActions/BulkChangePuppetEnvironment/__tests__/index.test.js +66 -0
- data/webpack/src/Extends/Hosts/BulkActions/BulkChangePuppetEnvironment/actions.js +37 -0
- data/webpack/src/Extends/Hosts/BulkActions/BulkChangePuppetEnvironment/index.js +30 -0
- data/webpack/src/Extends/Hosts/BulkActions/BulkChangePuppetProxy/__tests__/index.test.js +160 -44
- data/webpack/src/Extends/Hosts/BulkActions/BulkChangePuppetProxy/index.js +2 -0
- data/webpack/src/Extends/Hosts/BulkActions/BulkRemoveProxyCommon/__tests__/actions.test.js +0 -6
- data/webpack/src/Extends/Hosts/BulkActions/BulkRemoveProxyCommon/index.js +8 -13
- data/webpack/src/Extends/Hosts/BulkActions/BulkRemovePuppetCAProxy/__tests__/index.test.js +138 -38
- data/webpack/src/Extends/Hosts/BulkActions/BulkRemovePuppetCAProxy/index.js +2 -0
- data/webpack/src/Extends/Hosts/BulkActions/BulkRemovePuppetEnvironment/BulkRemovePuppetEnvironmentModal.js +148 -0
- data/webpack/src/Extends/Hosts/BulkActions/BulkRemovePuppetEnvironment/__tests__/BulkRemovePuppetEnvironmentModal.test.js +80 -0
- data/webpack/src/Extends/Hosts/BulkActions/BulkRemovePuppetEnvironment/__tests__/index.test.js +66 -0
- data/webpack/src/Extends/Hosts/BulkActions/BulkRemovePuppetEnvironment/index.js +30 -0
- data/webpack/src/Extends/Hosts/BulkActions/BulkRemovePuppetProxy/__tests__/index.test.js +125 -33
- data/webpack/src/Extends/Hosts/BulkActions/BulkRemovePuppetProxy/index.js +2 -0
- data/webpack/src/Router/routes.fixtures.js +13 -0
- data/webpack/src/Router/routes.test.js +68 -8
- data/webpack/src/foreman_puppet_host_form.test.js +3 -1
- data/webpack/test_setup.js +1 -0
- metadata +14 -3
- data/webpack/src/Router/__snapshots__/routes.test.js.snap +0 -3
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
import { FormattedMessage } from 'react-intl';
|
|
4
|
+
import { useDispatch } from 'react-redux';
|
|
5
|
+
import { Modal, Button, TextContent, Text } from '@patternfly/react-core';
|
|
6
|
+
import { translate as __ } from 'foremanReact/common/I18n';
|
|
7
|
+
import { addToast } from 'foremanReact/components/ToastsList/slice';
|
|
8
|
+
import { useForemanOrganization } from 'foremanReact/Root/Context/ForemanContext';
|
|
9
|
+
import { bulkActionErrorToastParams } from '../toastHelpers';
|
|
10
|
+
import {
|
|
11
|
+
bulkChangePuppetEnvironment,
|
|
12
|
+
BULK_CHANGE_PUPPET_ENVIRONMENT_KEY,
|
|
13
|
+
} from '../BulkChangePuppetEnvironment/actions';
|
|
14
|
+
|
|
15
|
+
const BulkRemovePuppetEnvironmentModal = ({
|
|
16
|
+
isOpen,
|
|
17
|
+
closeModal,
|
|
18
|
+
selectAllHostsMode,
|
|
19
|
+
selectedCount,
|
|
20
|
+
fetchBulkParams,
|
|
21
|
+
onSuccess: onSuccessCallback,
|
|
22
|
+
}) => {
|
|
23
|
+
const dispatch = useDispatch();
|
|
24
|
+
const currentOrganization = useForemanOrganization();
|
|
25
|
+
|
|
26
|
+
const handleModalClose = () => {
|
|
27
|
+
closeModal();
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const handleError = response => {
|
|
31
|
+
handleModalClose();
|
|
32
|
+
dispatch(
|
|
33
|
+
addToast(
|
|
34
|
+
bulkActionErrorToastParams(
|
|
35
|
+
response,
|
|
36
|
+
__('Failed to remove Puppet Environment'),
|
|
37
|
+
BULK_CHANGE_PUPPET_ENVIRONMENT_KEY
|
|
38
|
+
)
|
|
39
|
+
)
|
|
40
|
+
);
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const handleSuccess = response => {
|
|
44
|
+
dispatch(
|
|
45
|
+
addToast({
|
|
46
|
+
type: 'success',
|
|
47
|
+
message: response.data.message,
|
|
48
|
+
})
|
|
49
|
+
);
|
|
50
|
+
try {
|
|
51
|
+
if (onSuccessCallback) onSuccessCallback();
|
|
52
|
+
} finally {
|
|
53
|
+
handleModalClose();
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const handleConfirm = () => {
|
|
58
|
+
const requestBody = {
|
|
59
|
+
included: {
|
|
60
|
+
search: fetchBulkParams(),
|
|
61
|
+
},
|
|
62
|
+
environment_id: null,
|
|
63
|
+
organization_id: currentOrganization?.id,
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
dispatch(
|
|
67
|
+
bulkChangePuppetEnvironment(requestBody, handleSuccess, handleError)
|
|
68
|
+
);
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const modalActions = [
|
|
72
|
+
<Button
|
|
73
|
+
key="remove"
|
|
74
|
+
ouiaId="bulk-remove-puppet-environment-modal-remove-button"
|
|
75
|
+
variant="primary"
|
|
76
|
+
onClick={handleConfirm}
|
|
77
|
+
>
|
|
78
|
+
{__('Remove Puppet Environment')}
|
|
79
|
+
</Button>,
|
|
80
|
+
<Button
|
|
81
|
+
key="cancel"
|
|
82
|
+
ouiaId="bulk-remove-puppet-environment-modal-cancel-button"
|
|
83
|
+
variant="link"
|
|
84
|
+
onClick={handleModalClose}
|
|
85
|
+
>
|
|
86
|
+
{__('Cancel')}
|
|
87
|
+
</Button>,
|
|
88
|
+
];
|
|
89
|
+
|
|
90
|
+
return (
|
|
91
|
+
<Modal
|
|
92
|
+
isOpen={isOpen}
|
|
93
|
+
onClose={handleModalClose}
|
|
94
|
+
onEscapePress={handleModalClose}
|
|
95
|
+
title={__('Remove Puppet Environment')}
|
|
96
|
+
width="50%"
|
|
97
|
+
position="top"
|
|
98
|
+
actions={modalActions}
|
|
99
|
+
id="bulk-remove-puppet-environment"
|
|
100
|
+
key="bulk-remove-puppet-environment"
|
|
101
|
+
ouiaId="bulk-remove-puppet-environment"
|
|
102
|
+
>
|
|
103
|
+
<TextContent>
|
|
104
|
+
<Text ouiaId="bulk-remove-puppet-environment-options">
|
|
105
|
+
{selectAllHostsMode ? (
|
|
106
|
+
<FormattedMessage
|
|
107
|
+
id="bulk-remove-puppet-environment-warning-message-all"
|
|
108
|
+
defaultMessage={__(
|
|
109
|
+
'Removing the Puppet environment will affect {boldCount} selected hosts.'
|
|
110
|
+
)}
|
|
111
|
+
values={{
|
|
112
|
+
boldCount: <strong>{__('All')}</strong>,
|
|
113
|
+
}}
|
|
114
|
+
/>
|
|
115
|
+
) : (
|
|
116
|
+
<FormattedMessage
|
|
117
|
+
id="bulk-remove-puppet-environment-warning-message"
|
|
118
|
+
defaultMessage={__(
|
|
119
|
+
'Removing the Puppet environment will affect {boldCount} selected {count, plural, one {host} other {hosts}}.'
|
|
120
|
+
)}
|
|
121
|
+
values={{
|
|
122
|
+
count: selectedCount,
|
|
123
|
+
boldCount: <strong>{selectedCount}</strong>,
|
|
124
|
+
}}
|
|
125
|
+
/>
|
|
126
|
+
)}
|
|
127
|
+
</Text>
|
|
128
|
+
</TextContent>
|
|
129
|
+
</Modal>
|
|
130
|
+
);
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
BulkRemovePuppetEnvironmentModal.propTypes = {
|
|
134
|
+
isOpen: PropTypes.bool,
|
|
135
|
+
closeModal: PropTypes.func,
|
|
136
|
+
fetchBulkParams: PropTypes.func.isRequired,
|
|
137
|
+
onSuccess: PropTypes.func,
|
|
138
|
+
selectedCount: PropTypes.number.isRequired,
|
|
139
|
+
selectAllHostsMode: PropTypes.bool.isRequired,
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
BulkRemovePuppetEnvironmentModal.defaultProps = {
|
|
143
|
+
isOpen: false,
|
|
144
|
+
closeModal: () => {},
|
|
145
|
+
onSuccess: undefined,
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
export default BulkRemovePuppetEnvironmentModal;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { render, screen, fireEvent } from '@testing-library/react';
|
|
3
|
+
import '@testing-library/jest-dom';
|
|
4
|
+
import { IntlProvider } from 'react-intl';
|
|
5
|
+
import { useDispatch } from 'react-redux';
|
|
6
|
+
|
|
7
|
+
import BulkRemovePuppetEnvironmentModal from '../BulkRemovePuppetEnvironmentModal';
|
|
8
|
+
import { bulkChangePuppetEnvironment } from '../../BulkChangePuppetEnvironment/actions';
|
|
9
|
+
|
|
10
|
+
jest.mock('react-redux', () => ({
|
|
11
|
+
...jest.requireActual('react-redux'),
|
|
12
|
+
useDispatch: jest.fn(),
|
|
13
|
+
}));
|
|
14
|
+
|
|
15
|
+
jest.mock('foremanReact/Root/Context/ForemanContext', () => ({
|
|
16
|
+
useForemanOrganization: jest.fn(() => ({ id: 23 })),
|
|
17
|
+
}));
|
|
18
|
+
|
|
19
|
+
jest.mock('../../BulkChangePuppetEnvironment/actions', () => ({
|
|
20
|
+
bulkChangePuppetEnvironment: jest.fn(() => ({
|
|
21
|
+
type: 'BULK_CHANGE_PUPPET_ENVIRONMENT',
|
|
22
|
+
})),
|
|
23
|
+
BULK_CHANGE_PUPPET_ENVIRONMENT_KEY: 'BULK_CHANGE_PUPPET_ENVIRONMENT',
|
|
24
|
+
}));
|
|
25
|
+
|
|
26
|
+
describe('BulkRemovePuppetEnvironmentModal', () => {
|
|
27
|
+
const dispatch = jest.fn();
|
|
28
|
+
|
|
29
|
+
const renderComponent = (fetchBulkParams = jest.fn()) =>
|
|
30
|
+
render(
|
|
31
|
+
<IntlProvider locale="en">
|
|
32
|
+
<BulkRemovePuppetEnvironmentModal
|
|
33
|
+
isOpen
|
|
34
|
+
closeModal={jest.fn()}
|
|
35
|
+
fetchBulkParams={fetchBulkParams}
|
|
36
|
+
selectedCount={2}
|
|
37
|
+
selectAllHostsMode={false}
|
|
38
|
+
/>
|
|
39
|
+
</IntlProvider>
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
beforeEach(() => {
|
|
43
|
+
jest.clearAllMocks();
|
|
44
|
+
useDispatch.mockReturnValue(dispatch);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('renders the removal warning', () => {
|
|
48
|
+
renderComponent();
|
|
49
|
+
|
|
50
|
+
expect(
|
|
51
|
+
screen.getAllByText('Remove Puppet Environment')[0]
|
|
52
|
+
).toBeInTheDocument();
|
|
53
|
+
expect(
|
|
54
|
+
screen.getByText(/Removing the Puppet environment will affect/)
|
|
55
|
+
).toBeInTheDocument();
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it('submits organization scope with the bulk remove request', () => {
|
|
59
|
+
const fetchBulkParams = jest.fn(
|
|
60
|
+
() => 'organization = "Default Organization"'
|
|
61
|
+
);
|
|
62
|
+
renderComponent(fetchBulkParams);
|
|
63
|
+
|
|
64
|
+
fireEvent.click(
|
|
65
|
+
screen.getByRole('button', { name: 'Remove Puppet Environment' })
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
expect(bulkChangePuppetEnvironment).toHaveBeenCalledWith(
|
|
69
|
+
{
|
|
70
|
+
included: {
|
|
71
|
+
search: 'organization = "Default Organization"',
|
|
72
|
+
},
|
|
73
|
+
environment_id: null,
|
|
74
|
+
organization_id: 23,
|
|
75
|
+
},
|
|
76
|
+
expect.any(Function),
|
|
77
|
+
expect.any(Function)
|
|
78
|
+
);
|
|
79
|
+
});
|
|
80
|
+
});
|
data/webpack/src/Extends/Hosts/BulkActions/BulkRemovePuppetEnvironment/__tests__/index.test.js
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import renderer, { act } from 'react-test-renderer';
|
|
3
|
+
|
|
4
|
+
import { useBulkModalOpen } from 'foremanReact/common/BulkModalStateHelper';
|
|
5
|
+
import { ForemanActionsBarContext } from 'foremanReact/components/HostDetails/ActionsBar';
|
|
6
|
+
|
|
7
|
+
import BulkRemovePuppetEnvironmentScene from '../index';
|
|
8
|
+
import BulkRemovePuppetEnvironmentModal from '../BulkRemovePuppetEnvironmentModal';
|
|
9
|
+
|
|
10
|
+
jest.mock('foremanReact/common/BulkModalStateHelper', () => ({
|
|
11
|
+
useBulkModalOpen: jest.fn(),
|
|
12
|
+
}));
|
|
13
|
+
|
|
14
|
+
jest.mock('../BulkRemovePuppetEnvironmentModal', () => ({
|
|
15
|
+
__esModule: true,
|
|
16
|
+
default: jest.fn(() => null),
|
|
17
|
+
}));
|
|
18
|
+
|
|
19
|
+
describe('BulkRemovePuppetEnvironmentScene', () => {
|
|
20
|
+
const fetchBulkParams = jest.fn();
|
|
21
|
+
const refreshTableData = jest.fn();
|
|
22
|
+
const contextValue = {
|
|
23
|
+
selectAllHostsMode: false,
|
|
24
|
+
selectedCount: 2,
|
|
25
|
+
selectedResults: [1, 2],
|
|
26
|
+
fetchBulkParams,
|
|
27
|
+
refreshTableData,
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
beforeEach(() => {
|
|
31
|
+
jest.clearAllMocks();
|
|
32
|
+
useBulkModalOpen.mockReturnValue({
|
|
33
|
+
isOpen: true,
|
|
34
|
+
close: jest.fn(),
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('opens with bulk modal state and passes expected props', () => {
|
|
39
|
+
let component;
|
|
40
|
+
act(() => {
|
|
41
|
+
component = renderer.create(
|
|
42
|
+
<ForemanActionsBarContext.Provider value={contextValue}>
|
|
43
|
+
<BulkRemovePuppetEnvironmentScene />
|
|
44
|
+
</ForemanActionsBarContext.Provider>
|
|
45
|
+
);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
const componentType =
|
|
49
|
+
BulkRemovePuppetEnvironmentModal.default ||
|
|
50
|
+
BulkRemovePuppetEnvironmentModal;
|
|
51
|
+
const { props } = component.root.findByType(componentType);
|
|
52
|
+
|
|
53
|
+
expect(props).toEqual(
|
|
54
|
+
expect.objectContaining({
|
|
55
|
+
fetchBulkParams,
|
|
56
|
+
selectedCount: 2,
|
|
57
|
+
selectAllHostsMode: false,
|
|
58
|
+
isOpen: true,
|
|
59
|
+
closeModal: expect.any(Function),
|
|
60
|
+
onSuccess: refreshTableData,
|
|
61
|
+
})
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
component.unmount();
|
|
65
|
+
});
|
|
66
|
+
});
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import React, { useContext } from 'react';
|
|
2
|
+
import { ForemanActionsBarContext } from 'foremanReact/components/HostDetails/ActionsBar';
|
|
3
|
+
import { useBulkModalOpen } from 'foremanReact/common/BulkModalStateHelper';
|
|
4
|
+
import BulkRemovePuppetEnvironmentModal from './BulkRemovePuppetEnvironmentModal';
|
|
5
|
+
|
|
6
|
+
const BulkRemovePuppetEnvironmentScene = () => {
|
|
7
|
+
const {
|
|
8
|
+
selectAllHostsMode,
|
|
9
|
+
selectedCount,
|
|
10
|
+
fetchBulkParams,
|
|
11
|
+
refreshTableData,
|
|
12
|
+
} = useContext(ForemanActionsBarContext);
|
|
13
|
+
const { isOpen, close: closeModal } = useBulkModalOpen(
|
|
14
|
+
'bulk-remove-puppet-environment'
|
|
15
|
+
);
|
|
16
|
+
|
|
17
|
+
return (
|
|
18
|
+
<BulkRemovePuppetEnvironmentModal
|
|
19
|
+
fetchBulkParams={fetchBulkParams}
|
|
20
|
+
selectedCount={selectedCount}
|
|
21
|
+
selectAllHostsMode={selectAllHostsMode}
|
|
22
|
+
isOpen={isOpen}
|
|
23
|
+
closeModal={closeModal}
|
|
24
|
+
onSuccess={refreshTableData}
|
|
25
|
+
/>
|
|
26
|
+
);
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export { BulkRemovePuppetEnvironmentModal };
|
|
30
|
+
export default BulkRemovePuppetEnvironmentScene;
|
|
@@ -1,61 +1,153 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import { screen, act } from '@testing-library/react';
|
|
3
|
+
import userEvent from '@testing-library/user-event';
|
|
4
|
+
import '@testing-library/jest-dom';
|
|
3
5
|
|
|
4
6
|
import { openBulkModal } from 'foremanReact/common/BulkModalStateHelper';
|
|
5
7
|
import { ForemanActionsBarContext } from 'foremanReact/components/HostDetails/ActionsBar';
|
|
8
|
+
import { rtlHelpers } from 'foremanReact/common/rtlTestHelpers';
|
|
9
|
+
import { APIActions } from 'foremanReact/redux/API';
|
|
10
|
+
import { foremanUrl } from 'foremanReact/common/helpers';
|
|
6
11
|
|
|
7
12
|
import BulkRemovePuppetProxyScene from '../index';
|
|
8
|
-
import
|
|
13
|
+
import { BULK_REMOVE_PUPPET_PROXY_KEY } from '../../BulkRemoveProxyCommon/actions';
|
|
9
14
|
|
|
10
|
-
jest.mock(
|
|
11
|
-
|
|
12
|
-
|
|
15
|
+
jest.mock(
|
|
16
|
+
'foremanReact/components/HostDetails/ActionsBar',
|
|
17
|
+
() => ({
|
|
18
|
+
ForemanActionsBarContext: jest.requireActual('react').createContext(),
|
|
19
|
+
}),
|
|
20
|
+
{ virtual: true }
|
|
21
|
+
);
|
|
13
22
|
|
|
14
|
-
jest.mock('
|
|
15
|
-
|
|
16
|
-
|
|
23
|
+
jest.mock('foremanReact/redux/API', () => ({
|
|
24
|
+
APIActions: {
|
|
25
|
+
put: jest.fn(payload => ({ type: 'MOCK_API_PUT', payload })),
|
|
26
|
+
},
|
|
17
27
|
}));
|
|
18
28
|
|
|
29
|
+
const { renderWithStoreAndI18n } = rtlHelpers;
|
|
30
|
+
|
|
19
31
|
describe('BulkRemovePuppetProxyScene', () => {
|
|
20
|
-
const fetchBulkParams = jest.fn();
|
|
32
|
+
const fetchBulkParams = jest.fn(() => 'name = host1');
|
|
33
|
+
const refreshTableData = jest.fn();
|
|
21
34
|
const contextValue = {
|
|
22
35
|
selectAllHostsMode: false,
|
|
23
36
|
selectedCount: 2,
|
|
24
37
|
selectedResults: [1, 2],
|
|
25
38
|
fetchBulkParams,
|
|
39
|
+
refreshTableData,
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const renderScene = (context = contextValue) =>
|
|
43
|
+
renderWithStoreAndI18n(
|
|
44
|
+
<ForemanActionsBarContext.Provider value={context}>
|
|
45
|
+
<BulkRemovePuppetProxyScene />
|
|
46
|
+
</ForemanActionsBarContext.Provider>
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
const openSceneModal = async () => {
|
|
50
|
+
openBulkModal('bulk-remove-puppet-proxy', true);
|
|
51
|
+
|
|
52
|
+
return screen.findByRole('dialog', { name: 'Remove Puppet Proxy' });
|
|
26
53
|
};
|
|
27
54
|
|
|
28
55
|
beforeEach(() => {
|
|
29
|
-
jest.clearAllMocks();
|
|
30
56
|
openBulkModal('bulk-remove-puppet-proxy', false);
|
|
31
57
|
});
|
|
32
58
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
59
|
+
afterEach(() => {
|
|
60
|
+
jest.clearAllMocks();
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it('does not show the modal when bulk modal state is closed', () => {
|
|
64
|
+
renderScene();
|
|
65
|
+
|
|
66
|
+
expect(
|
|
67
|
+
screen.queryByRole('dialog', { name: 'Remove Puppet Proxy' })
|
|
68
|
+
).not.toBeInTheDocument();
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it('shows the modal with a warning for the selected hosts when opened', async () => {
|
|
72
|
+
renderScene();
|
|
73
|
+
await openSceneModal();
|
|
74
|
+
|
|
75
|
+
expect(
|
|
76
|
+
screen.getByText(/Removing the Puppet proxy will affect/)
|
|
77
|
+
).toBeInTheDocument();
|
|
78
|
+
expect(screen.getByText('2', { selector: 'strong' })).toBeInTheDocument();
|
|
79
|
+
expect(screen.getByText(/selected hosts/)).toBeInTheDocument();
|
|
80
|
+
expect(
|
|
81
|
+
screen.getByRole('button', { name: 'Remove Puppet Proxy' })
|
|
82
|
+
).toBeInTheDocument();
|
|
83
|
+
expect(screen.getByRole('button', { name: 'Cancel' })).toBeInTheDocument();
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it('shows the all hosts warning when select all hosts mode is enabled', async () => {
|
|
87
|
+
renderScene({
|
|
88
|
+
...contextValue,
|
|
89
|
+
selectAllHostsMode: true,
|
|
90
|
+
});
|
|
91
|
+
await openSceneModal();
|
|
92
|
+
|
|
93
|
+
expect(
|
|
94
|
+
screen.getByText(/Removing the Puppet proxy will affect/)
|
|
95
|
+
).toBeInTheDocument();
|
|
96
|
+
expect(screen.getByText('All', { selector: 'strong' })).toBeInTheDocument();
|
|
97
|
+
expect(screen.getByText(/selected hosts/)).toBeInTheDocument();
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it('closes the modal when Cancel is clicked', async () => {
|
|
101
|
+
renderScene();
|
|
102
|
+
await openSceneModal();
|
|
103
|
+
|
|
104
|
+
await userEvent.click(screen.getByRole('button', { name: 'Cancel' }));
|
|
105
|
+
|
|
106
|
+
expect(
|
|
107
|
+
screen.queryByRole('dialog', { name: 'Remove Puppet Proxy' })
|
|
108
|
+
).not.toBeInTheDocument();
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
it('dispatches the bulk remove puppet proxy action when confirmed', async () => {
|
|
112
|
+
renderScene();
|
|
113
|
+
await openSceneModal();
|
|
114
|
+
|
|
115
|
+
await userEvent.click(
|
|
116
|
+
screen.getByRole('button', { name: 'Remove Puppet Proxy' })
|
|
39
117
|
);
|
|
40
118
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
expect.
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
119
|
+
expect(fetchBulkParams).toHaveBeenCalledTimes(1);
|
|
120
|
+
expect(APIActions.put).toHaveBeenCalledWith({
|
|
121
|
+
key: BULK_REMOVE_PUPPET_PROXY_KEY,
|
|
122
|
+
url: foremanUrl('/api/v2/hosts/bulk/remove_puppet_proxy'),
|
|
123
|
+
handleSuccess: expect.any(Function),
|
|
124
|
+
handleError: expect.any(Function),
|
|
125
|
+
params: {
|
|
126
|
+
included: {
|
|
127
|
+
search: 'name = host1',
|
|
128
|
+
},
|
|
129
|
+
ca_proxy: false,
|
|
130
|
+
},
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
it('refreshes table data after a successful bulk remove', async () => {
|
|
135
|
+
renderScene();
|
|
136
|
+
await openSceneModal();
|
|
137
|
+
|
|
138
|
+
await userEvent.click(
|
|
139
|
+
screen.getByRole('button', { name: 'Remove Puppet Proxy' })
|
|
57
140
|
);
|
|
58
141
|
|
|
59
|
-
|
|
142
|
+
const { handleSuccess } = APIActions.put.mock.calls[0][0];
|
|
143
|
+
|
|
144
|
+
act(() => {
|
|
145
|
+
handleSuccess({ data: { message: 'Puppet proxy removed' } });
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
expect(refreshTableData).toHaveBeenCalledTimes(1);
|
|
149
|
+
expect(
|
|
150
|
+
screen.queryByRole('dialog', { name: 'Remove Puppet Proxy' })
|
|
151
|
+
).not.toBeInTheDocument();
|
|
60
152
|
});
|
|
61
153
|
});
|
|
@@ -10,6 +10,7 @@ const BulkRemovePuppetProxyScene = () => {
|
|
|
10
10
|
selectedCount,
|
|
11
11
|
selectedResults,
|
|
12
12
|
fetchBulkParams,
|
|
13
|
+
refreshTableData,
|
|
13
14
|
} = useContext(ForemanActionsBarContext);
|
|
14
15
|
const { isOpen, close: closeModal } = useBulkModalOpen(
|
|
15
16
|
'bulk-remove-puppet-proxy'
|
|
@@ -24,6 +25,7 @@ const BulkRemovePuppetProxyScene = () => {
|
|
|
24
25
|
fetchBulkParams={fetchBulkParams}
|
|
25
26
|
isOpen={isOpen}
|
|
26
27
|
closeModal={closeModal}
|
|
28
|
+
onSuccess={refreshTableData}
|
|
27
29
|
handleErrorMessage={__('Failed to remove Puppet Proxy')}
|
|
28
30
|
allHostsMessage={__(
|
|
29
31
|
'Removing the Puppet proxy will affect {boldCount} selected hosts.'
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
export const ExampleRoutePage = () => (
|
|
4
|
+
<h1>Foreman Puppet example route</h1>
|
|
5
|
+
);
|
|
6
|
+
|
|
7
|
+
export const exampleRoutes = {
|
|
8
|
+
example: {
|
|
9
|
+
path: '/foreman_puppet_example',
|
|
10
|
+
exact: true,
|
|
11
|
+
component: ExampleRoutePage,
|
|
12
|
+
},
|
|
13
|
+
};
|
|
@@ -1,16 +1,76 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import { createMemoryHistory } from 'history';
|
|
3
|
+
import { Router, Route, Switch } from 'react-router-dom';
|
|
4
|
+
import { screen } from '@testing-library/react';
|
|
5
|
+
import '@testing-library/jest-dom';
|
|
3
6
|
|
|
4
|
-
import
|
|
7
|
+
import routes from './routes';
|
|
8
|
+
import ForemanPuppetRouter from './index';
|
|
9
|
+
import { exampleRoutes } from './routes.fixtures';
|
|
10
|
+
import { rtlHelpers } from 'foremanReact/common/rtlTestHelpers';
|
|
11
|
+
|
|
12
|
+
const { renderWithStore } = rtlHelpers;
|
|
13
|
+
|
|
14
|
+
const renderForemanPuppetRouterAtPath = path => {
|
|
15
|
+
const history = createMemoryHistory({ initialEntries: [path] });
|
|
16
|
+
|
|
17
|
+
return renderWithStore(
|
|
18
|
+
<Router history={history}>
|
|
19
|
+
<ForemanPuppetRouter />
|
|
20
|
+
</Router>
|
|
21
|
+
);
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const renderRoutesAtPath = (routeMap, path) => {
|
|
25
|
+
const history = createMemoryHistory({ initialEntries: [path] });
|
|
26
|
+
|
|
27
|
+
return renderWithStore(
|
|
28
|
+
<Router history={history}>
|
|
29
|
+
<Switch>
|
|
30
|
+
{Object.entries(routeMap).map(([key, props]) => (
|
|
31
|
+
<Route key={key} {...props} />
|
|
32
|
+
))}
|
|
33
|
+
</Switch>
|
|
34
|
+
</Router>
|
|
35
|
+
);
|
|
36
|
+
};
|
|
5
37
|
|
|
6
38
|
describe('ForemanPuppetRoutes', () => {
|
|
7
|
-
it('
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
39
|
+
it('exports an empty routes configuration object', () => {
|
|
40
|
+
expect(routes).toEqual({});
|
|
41
|
+
expect(routes).not.toBeNull();
|
|
42
|
+
expect(Array.isArray(routes)).toBe(false);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
describe('fixture routes', () => {
|
|
46
|
+
it('defines valid route entries', () => {
|
|
47
|
+
Object.entries(exampleRoutes).forEach(([routeKey, route]) => {
|
|
48
|
+
expect(routeKey).toBeTruthy();
|
|
49
|
+
expect(route).toEqual(
|
|
50
|
+
expect.objectContaining({
|
|
51
|
+
path: expect.any(String),
|
|
52
|
+
component: expect.any(Function),
|
|
53
|
+
})
|
|
54
|
+
);
|
|
55
|
+
});
|
|
12
56
|
});
|
|
13
57
|
|
|
14
|
-
|
|
58
|
+
it('renders a fixture route at its path', () => {
|
|
59
|
+
const { path } = exampleRoutes.example;
|
|
60
|
+
|
|
61
|
+
renderRoutesAtPath(exampleRoutes, path);
|
|
62
|
+
|
|
63
|
+
expect(
|
|
64
|
+
screen.getByRole('heading', { name: 'Foreman Puppet example route' })
|
|
65
|
+
).toBeInTheDocument();
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
describe('ForemanPuppetRouter', () => {
|
|
70
|
+
it('renders without content when no routes are configured', () => {
|
|
71
|
+
const { container } = renderForemanPuppetRouterAtPath('/');
|
|
72
|
+
|
|
73
|
+
expect(container).toBeEmptyDOMElement();
|
|
74
|
+
});
|
|
15
75
|
});
|
|
16
76
|
});
|
|
@@ -4,6 +4,8 @@ import $ from 'jquery';
|
|
|
4
4
|
|
|
5
5
|
import { checkForUnavailablePuppetclasses } from './foreman_puppet_host_form';
|
|
6
6
|
|
|
7
|
+
const WARNING_RENDER_TIMEOUT = 100;
|
|
8
|
+
|
|
7
9
|
jest.unmock('jquery');
|
|
8
10
|
jest.unmock('./foreman_puppet_host_form');
|
|
9
11
|
|
|
@@ -59,6 +61,6 @@ describe('checkForUnavailablePuppetclasses', () => {
|
|
|
59
61
|
checkForUnavailablePuppetclasses();
|
|
60
62
|
setTimeout(() => {
|
|
61
63
|
expect($('a .pficon')).toHaveLength(1);
|
|
62
|
-
},
|
|
64
|
+
}, WARNING_RENDER_TIMEOUT);
|
|
63
65
|
});
|
|
64
66
|
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import 'foremanJSTestSetup';
|