Skip to content

Commit 296fbbd

Browse files
committed
Conditionally hide UI components and enable inventory sync in IOP mode
- Enable inventory synchronization in local advisor engine environments - Hide cloud-specific UI elements when use_iop_mode is true - Conditionally display settings based on iop mode This allows inventory sync to run in IOP mode while hiding cloud-specific UI components that are not relevant in local advisor engine environments.
1 parent aa9f29f commit 296fbbd

File tree

7 files changed

+290
-54
lines changed

7 files changed

+290
-54
lines changed

lib/inventory_sync/async/inventory_hosts_sync.rb

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@ class InventoryHostsSync < QueryInventoryJob
88
set_callback :step, :around, :create_missing_hosts
99

1010
def plan(organizations)
11-
# Do not run for local advisor, since we use sub-man id to identify hosts.
12-
return if ForemanRhCloud.with_iop_smart_proxy?
1311
# by default the tasks will be executed concurrently
1412
super(organizations)
1513
plan_self_host_sync

webpack/ForemanInventoryUpload/Components/PageHeader/PageHeader.js

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,26 +6,33 @@ import InventoryFilter from '../InventoryFilter';
66
import ToolbarButtons from './components/ToolbarButtons';
77
import SettingsWarning from './components/SettingsWarning';
88
import PageTitle from './PageTitle';
9+
import { useAdvisorEngineConfig } from '../../../common/Hooks/ConfigHooks';
910
import './PageHeader.scss';
1011

11-
const PageHeader = () => (
12-
<div className="inventory-upload-header">
13-
<SettingsWarning />
14-
<PageTitle />
15-
<div className="inventory-upload-header-description">
16-
<InventorySettings />
17-
<PageDescription />
12+
const PageHeader = () => {
13+
const useIopMode = useAdvisorEngineConfig();
14+
15+
return (
16+
<div className="inventory-upload-header">
17+
<SettingsWarning />
18+
<PageTitle />
19+
{!useIopMode && (
20+
<div className="inventory-upload-header-description">
21+
<InventorySettings />
22+
<PageDescription />
23+
</div>
24+
)}
25+
<Grid.Row>
26+
<Grid.Col xs={4}>
27+
<InventoryFilter />
28+
</Grid.Col>
29+
<Grid.Col xs={7} xsOffset={1}>
30+
<ToolbarButtons />
31+
</Grid.Col>
32+
</Grid.Row>
1833
</div>
19-
<Grid.Row>
20-
<Grid.Col xs={4}>
21-
<InventoryFilter />
22-
</Grid.Col>
23-
<Grid.Col xs={7} xsOffset={1}>
24-
<ToolbarButtons />
25-
</Grid.Col>
26-
</Grid.Row>
27-
</div>
28-
);
34+
);
35+
};
2936

3037
PageHeader.propTypes = {};
3138

Lines changed: 154 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,49 @@
1+
import React from 'react';
2+
import { render, screen } from '@testing-library/react';
3+
import { Provider } from 'react-redux';
4+
import configureMockStore from 'redux-mock-store';
5+
import thunk from 'redux-thunk';
16
import { testComponentSnapshotsWithFixtures } from '@theforeman/test';
2-
7+
import { useAPI } from 'foremanReact/common/hooks/API/APIHooks';
8+
import {
9+
setupAdvisorEngineTest,
10+
createBaseStoreWithAdvisorConfig,
11+
} from '../../../../__mocks__/testHelpers/advisorEngineTestHelper';
312
import PageHeader from '../PageHeader';
413

14+
// Mock useAPI to return values based on the key
15+
jest.mock('foremanReact/common/hooks/API/APIHooks');
16+
17+
const mockUseAPI = useAPI;
18+
19+
// Mock child components to isolate PageHeader testing
20+
// This prevents child component complexity from affecting our tests
21+
jest.mock('../components/SettingsWarning', () => () => (
22+
<div data-testid="settings-warning">SettingsWarning</div>
23+
));
24+
jest.mock('../PageTitle', () => () => (
25+
<div data-testid="page-title">PageTitle</div>
26+
));
27+
jest.mock('../../InventorySettings', () => () => (
28+
<div data-testid="inventory-settings">InventorySettings</div>
29+
));
30+
jest.mock('../components/PageDescription', () => () => (
31+
<div data-testid="page-description">PageDescription</div>
32+
));
33+
jest.mock('../../InventoryFilter', () => () => (
34+
<div data-testid="inventory-filter">InventoryFilter</div>
35+
));
36+
jest.mock('../components/ToolbarButtons', () => () => (
37+
<div data-testid="toolbar-buttons">ToolbarButtons</div>
38+
));
39+
40+
const middlewares = [thunk];
41+
const mockStore = configureMockStore(middlewares);
42+
43+
// Create store states using helper
44+
const baseStoreState = createBaseStoreWithAdvisorConfig(false);
45+
const iopModeStoreState = createBaseStoreWithAdvisorConfig(true);
46+
547
const fixtures = {
648
'render without Props': {},
749
/** fixtures, props for the component */
@@ -10,4 +52,115 @@ const fixtures = {
1052
describe('PageHeader', () => {
1153
describe('rendering', () =>
1254
testComponentSnapshotsWithFixtures(PageHeader, fixtures));
55+
56+
describe('component behavior', () => {
57+
test('renders all components when not in IoP mode', () => {
58+
setupAdvisorEngineTest(mockUseAPI, false);
59+
const store = mockStore(baseStoreState);
60+
61+
render(
62+
<Provider store={store}>
63+
<PageHeader />
64+
</Provider>
65+
);
66+
67+
// All components should be present when not in IoP mode
68+
expect(screen.getByTestId('settings-warning')).toBeTruthy();
69+
expect(screen.getByTestId('page-title')).toBeTruthy();
70+
expect(screen.getByTestId('inventory-settings')).toBeTruthy();
71+
expect(screen.getByTestId('page-description')).toBeTruthy();
72+
expect(screen.getByTestId('inventory-filter')).toBeTruthy();
73+
expect(screen.getByTestId('toolbar-buttons')).toBeTruthy();
74+
});
75+
76+
test('hides inventory settings and description when in IoP mode', () => {
77+
setupAdvisorEngineTest(mockUseAPI, true);
78+
const store = mockStore(iopModeStoreState);
79+
80+
render(
81+
<Provider store={store}>
82+
<PageHeader />
83+
</Provider>
84+
);
85+
86+
// Core components should still be present
87+
expect(screen.getByTestId('settings-warning')).toBeTruthy();
88+
expect(screen.getByTestId('page-title')).toBeTruthy();
89+
expect(screen.getByTestId('inventory-filter')).toBeTruthy();
90+
expect(screen.getByTestId('toolbar-buttons')).toBeTruthy();
91+
92+
// These components should be hidden in IoP mode
93+
expect(screen.queryByTestId('inventory-settings')).toBeNull();
94+
expect(screen.queryByTestId('page-description')).toBeNull();
95+
});
96+
97+
test('renders with correct CSS class', () => {
98+
setupAdvisorEngineTest(mockUseAPI, false);
99+
const store = mockStore(baseStoreState);
100+
101+
const { container } = render(
102+
<Provider store={store}>
103+
<PageHeader />
104+
</Provider>
105+
);
106+
107+
expect(container.querySelector('.inventory-upload-header')).toBeTruthy();
108+
});
109+
110+
test('renders grid layout with correct structure', () => {
111+
setupAdvisorEngineTest(mockUseAPI, false);
112+
const store = mockStore(baseStoreState);
113+
114+
const { container } = render(
115+
<Provider store={store}>
116+
<PageHeader />
117+
</Provider>
118+
);
119+
120+
// Check for grid row
121+
const gridRow = container.querySelector('.row');
122+
expect(gridRow).toBeTruthy();
123+
124+
// Check for grid columns with correct classes
125+
const filterColumn = container.querySelector('.col-xs-4');
126+
expect(filterColumn).toBeTruthy();
127+
128+
const toolbarColumn = container.querySelector('.col-xs-7');
129+
expect(toolbarColumn).toBeTruthy();
130+
});
131+
132+
test('renders description section only when not in IoP mode', () => {
133+
setupAdvisorEngineTest(mockUseAPI, false);
134+
const store = mockStore(baseStoreState);
135+
136+
const { container } = render(
137+
<Provider store={store}>
138+
<PageHeader />
139+
</Provider>
140+
);
141+
142+
// Description section should be present when not in IoP mode
143+
const descriptionSection = container.querySelector(
144+
'.inventory-upload-header-description'
145+
);
146+
expect(descriptionSection).toBeTruthy();
147+
});
148+
149+
test('does not render description section when in IoP mode', () => {
150+
setupAdvisorEngineTest(mockUseAPI, true);
151+
const store = mockStore(iopModeStoreState);
152+
153+
const { container } = render(
154+
<Provider store={store}>
155+
<PageHeader />
156+
</Provider>
157+
);
158+
159+
// Description section should not be present in IoP mode
160+
const descriptionSection = container.querySelector(
161+
'.inventory-upload-header-description'
162+
);
163+
expect(descriptionSection).toBeNull();
164+
});
165+
});
13166
});

webpack/ForemanInventoryUpload/Components/PageHeader/__tests__/__snapshots__/PageHeader.test.js.snap

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@ exports[`PageHeader rendering render without Props 1`] = `
44
<div
55
className="inventory-upload-header"
66
>
7-
<ConnectedSettingsWarning />
8-
<PageTitle />
7+
<Component />
8+
<Component />
99
<div
1010
className="inventory-upload-header-description"
1111
>
12-
<ConnectedInventorySettings />
13-
<PageDescription />
12+
<Component />
13+
<Component />
1414
</div>
1515
<Row
1616
bsClass="row"
@@ -21,15 +21,15 @@ exports[`PageHeader rendering render without Props 1`] = `
2121
componentClass="div"
2222
xs={4}
2323
>
24-
<Connect(InventoryFilter) />
24+
<Component />
2525
</Col>
2626
<Col
2727
bsClass="col"
2828
componentClass="div"
2929
xs={7}
3030
xsOffset={1}
3131
>
32-
<ToolbarButtons />
32+
<Component />
3333
</Col>
3434
</Row>
3535
</div>

webpack/ForemanInventoryUpload/Components/PageHeader/components/ToolbarButtons/ToolbarButtons.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,21 @@ import SyncButton from '../SyncButton';
44
import CloudConnectorButton from '../CloudConnectorButton';
55
import './toolbarButtons.scss';
66
import { selectSubscriptionConnectionEnabled } from '../../../InventorySettings/InventorySettingsSelectors';
7+
import { useAdvisorEngineConfig } from '../../../../../common/Hooks/ConfigHooks';
78

89
const ToolbarButtons = () => {
910
const subscriptionConnectionEnabled = useSelector(
1011
selectSubscriptionConnectionEnabled
1112
);
13+
const useIopMode = useAdvisorEngineConfig();
1214

1315
if (!subscriptionConnectionEnabled) {
1416
return null;
1517
}
1618

1719
return (
1820
<div className="inventory_toolbar_buttons">
19-
<CloudConnectorButton />
21+
{!useIopMode && <CloudConnectorButton />}
2022
<SyncButton />
2123
</div>
2224
);

0 commit comments

Comments
 (0)