Skip to content

Commit 2cc7ef5

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 2cc7ef5

File tree

6 files changed

+266
-41
lines changed

6 files changed

+266
-41
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: 172 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,184 @@
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-
37
import PageHeader from '../PageHeader';
48

9+
// Mock child components to isolate PageHeader testing
10+
// This prevents child component complexity from affecting our tests
11+
jest.mock('../components/SettingsWarning', () => () => (
12+
<div data-testid="settings-warning">SettingsWarning</div>
13+
));
14+
jest.mock('../PageTitle', () => () => (
15+
<div data-testid="page-title">PageTitle</div>
16+
));
17+
jest.mock('../../InventorySettings', () => () => (
18+
<div data-testid="inventory-settings">InventorySettings</div>
19+
));
20+
jest.mock('../components/PageDescription', () => () => (
21+
<div data-testid="page-description">PageDescription</div>
22+
));
23+
jest.mock('../../InventoryFilter', () => () => (
24+
<div data-testid="inventory-filter">InventoryFilter</div>
25+
));
26+
jest.mock('../components/ToolbarButtons', () => () => (
27+
<div data-testid="toolbar-buttons">ToolbarButtons</div>
28+
));
29+
30+
// Mock the hook since useAPI is mocked in tests and doesn't read from Redux
31+
jest.mock('../../../../common/Hooks/ConfigHooks', () => ({
32+
useAdvisorEngineConfig: jest.fn(() => false),
33+
}));
34+
35+
const {
36+
useAdvisorEngineConfig,
37+
} = require('../../../../common/Hooks/ConfigHooks');
38+
39+
const middlewares = [thunk];
40+
const mockStore = configureMockStore(middlewares);
41+
42+
const baseStoreState = {
43+
API: {
44+
INVENTORY_SETTINGS: {
45+
response: { subscriptionConnectionEnabled: true },
46+
},
47+
},
48+
ForemanRhCloud: {
49+
inventoryUpload: {
50+
accountsList: {
51+
CloudConnectorStatus: {},
52+
},
53+
syncStatus: {},
54+
inventoryFilter: {
55+
filterTerm: '',
56+
},
57+
},
58+
},
59+
};
60+
561
const fixtures = {
662
'render without Props': {},
763
/** fixtures, props for the component */
864
};
965

1066
describe('PageHeader', () => {
67+
beforeEach(() => {
68+
useAdvisorEngineConfig.mockReturnValue(false);
69+
});
70+
71+
afterEach(() => {
72+
jest.clearAllMocks();
73+
});
74+
1175
describe('rendering', () =>
1276
testComponentSnapshotsWithFixtures(PageHeader, fixtures));
77+
78+
describe('component behavior', () => {
79+
test('renders all components when not in IoP mode', () => {
80+
const store = mockStore(baseStoreState);
81+
82+
render(
83+
<Provider store={store}>
84+
<PageHeader />
85+
</Provider>
86+
);
87+
88+
// All components should be present when not in IoP mode
89+
expect(screen.getByTestId('settings-warning')).toBeTruthy();
90+
expect(screen.getByTestId('page-title')).toBeTruthy();
91+
expect(screen.getByTestId('inventory-settings')).toBeTruthy();
92+
expect(screen.getByTestId('page-description')).toBeTruthy();
93+
expect(screen.getByTestId('inventory-filter')).toBeTruthy();
94+
expect(screen.getByTestId('toolbar-buttons')).toBeTruthy();
95+
});
96+
97+
test('hides inventory settings and description when in IoP mode', () => {
98+
useAdvisorEngineConfig.mockReturnValue(true);
99+
const store = mockStore(baseStoreState);
100+
101+
render(
102+
<Provider store={store}>
103+
<PageHeader />
104+
</Provider>
105+
);
106+
107+
// Core components should still be present
108+
expect(screen.getByTestId('settings-warning')).toBeTruthy();
109+
expect(screen.getByTestId('page-title')).toBeTruthy();
110+
expect(screen.getByTestId('inventory-filter')).toBeTruthy();
111+
expect(screen.getByTestId('toolbar-buttons')).toBeTruthy();
112+
113+
// These components should be hidden in IoP mode
114+
expect(screen.queryByTestId('inventory-settings')).toBeNull();
115+
expect(screen.queryByTestId('page-description')).toBeNull();
116+
});
117+
118+
test('renders with correct CSS class', () => {
119+
const store = mockStore(baseStoreState);
120+
121+
const { container } = render(
122+
<Provider store={store}>
123+
<PageHeader />
124+
</Provider>
125+
);
126+
127+
expect(container.querySelector('.inventory-upload-header')).toBeTruthy();
128+
});
129+
130+
test('renders grid layout with correct structure', () => {
131+
const store = mockStore(baseStoreState);
132+
133+
const { container } = render(
134+
<Provider store={store}>
135+
<PageHeader />
136+
</Provider>
137+
);
138+
139+
// Check for grid row
140+
const gridRow = container.querySelector('.row');
141+
expect(gridRow).toBeTruthy();
142+
143+
// Check for grid columns with correct classes
144+
const filterColumn = container.querySelector('.col-xs-4');
145+
expect(filterColumn).toBeTruthy();
146+
147+
const toolbarColumn = container.querySelector('.col-xs-7');
148+
expect(toolbarColumn).toBeTruthy();
149+
});
150+
151+
test('renders description section only when not in IoP mode', () => {
152+
const store = mockStore(baseStoreState);
153+
154+
const { container } = render(
155+
<Provider store={store}>
156+
<PageHeader />
157+
</Provider>
158+
);
159+
160+
// Description section should be present when not in IoP mode
161+
const descriptionSection = container.querySelector(
162+
'.inventory-upload-header-description'
163+
);
164+
expect(descriptionSection).toBeTruthy();
165+
});
166+
167+
test('does not render description section when in IoP mode', () => {
168+
useAdvisorEngineConfig.mockReturnValue(true);
169+
const store = mockStore(baseStoreState);
170+
171+
const { container } = render(
172+
<Provider store={store}>
173+
<PageHeader />
174+
</Provider>
175+
);
176+
177+
// Description section should not be present in IoP mode
178+
const descriptionSection = container.querySelector(
179+
'.inventory-upload-header-description'
180+
);
181+
expect(descriptionSection).toBeNull();
182+
});
183+
});
13184
});

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)