Skip to content

Commit 7cd6256

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 f123df3 commit 7cd6256

File tree

6 files changed

+205
-115
lines changed

6 files changed

+205
-115
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: 109 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,114 @@
1-
import { testComponentSnapshotsWithFixtures } from '@theforeman/test';
2-
1+
import React from 'react';
2+
import { screen } from '@testing-library/react';
3+
import { rtlHelpers } from 'foremanReact/common/rtlTestHelpers';
34
import PageHeader from '../PageHeader';
5+
import { useAdvisorEngineConfig } from '../../../../common/Hooks/ConfigHooks';
6+
7+
// Mock the config hook
8+
jest.mock('../../../../common/Hooks/ConfigHooks', () => ({
9+
useAdvisorEngineConfig: jest.fn(),
10+
}));
11+
12+
const { renderWithStore } = rtlHelpers;
413

5-
const fixtures = {
6-
'render without Props': {},
7-
/** fixtures, props for the component */
8-
};
14+
// Mock child components to isolate PageHeader testing
15+
// This prevents child component complexity from affecting our tests
16+
jest.mock('../components/SettingsWarning', () => () => (
17+
<div data-testid="settings-warning">SettingsWarning</div>
18+
));
19+
jest.mock('../PageTitle', () => () => (
20+
<div data-testid="page-title">PageTitle</div>
21+
));
22+
jest.mock('../../InventorySettings', () => () => (
23+
<div data-testid="inventory-settings">InventorySettings</div>
24+
));
25+
jest.mock('../components/PageDescription', () => () => (
26+
<div data-testid="page-description">PageDescription</div>
27+
));
28+
jest.mock('../../InventoryFilter', () => () => (
29+
<div data-testid="inventory-filter">InventoryFilter</div>
30+
));
31+
jest.mock('../components/ToolbarButtons', () => () => (
32+
<div data-testid="toolbar-buttons">ToolbarButtons</div>
33+
));
934

1035
describe('PageHeader', () => {
11-
describe('rendering', () =>
12-
testComponentSnapshotsWithFixtures(PageHeader, fixtures));
36+
describe('component behavior', () => {
37+
test('renders all components when not in IoP mode', () => {
38+
useAdvisorEngineConfig.mockReturnValue(false);
39+
40+
renderWithStore(<PageHeader />);
41+
42+
// All components should be present when not in IoP mode
43+
expect(screen.getByTestId('settings-warning')).toBeTruthy();
44+
expect(screen.getByTestId('page-title')).toBeTruthy();
45+
expect(screen.getByTestId('inventory-settings')).toBeTruthy();
46+
expect(screen.getByTestId('page-description')).toBeTruthy();
47+
expect(screen.getByTestId('inventory-filter')).toBeTruthy();
48+
expect(screen.getByTestId('toolbar-buttons')).toBeTruthy();
49+
});
50+
51+
test('hides inventory settings and description when in IoP mode', () => {
52+
useAdvisorEngineConfig.mockReturnValue(true);
53+
54+
renderWithStore(<PageHeader />);
55+
56+
// Core components should still be present
57+
expect(screen.getByTestId('settings-warning')).toBeTruthy();
58+
expect(screen.getByTestId('page-title')).toBeTruthy();
59+
expect(screen.getByTestId('inventory-filter')).toBeTruthy();
60+
expect(screen.getByTestId('toolbar-buttons')).toBeTruthy();
61+
62+
// These components should be hidden in IoP mode
63+
expect(screen.queryByTestId('inventory-settings')).toBeNull();
64+
expect(screen.queryByTestId('page-description')).toBeNull();
65+
});
66+
67+
test('renders with correct CSS class', () => {
68+
useAdvisorEngineConfig.mockReturnValue(false);
69+
70+
const { container } = renderWithStore(<PageHeader />);
71+
72+
expect(container.querySelector('.inventory-upload-header')).toBeTruthy();
73+
});
74+
75+
test('renders grid layout with correct structure', () => {
76+
useAdvisorEngineConfig.mockReturnValue(false);
77+
78+
const { container } = renderWithStore(<PageHeader />);
79+
80+
const gridRow = container.querySelector('.row');
81+
expect(gridRow).toBeTruthy();
82+
83+
const filterColumn = container.querySelector('.col-xs-4');
84+
expect(filterColumn).toBeTruthy();
85+
86+
const toolbarColumn = container.querySelector('.col-xs-7');
87+
expect(toolbarColumn).toBeTruthy();
88+
});
89+
90+
test('renders description section only when not in IoP mode', () => {
91+
useAdvisorEngineConfig.mockReturnValue(false);
92+
93+
const { container } = renderWithStore(<PageHeader />);
94+
95+
// Description section should be present when not in IoP mode
96+
const descriptionSection = container.querySelector(
97+
'.inventory-upload-header-description'
98+
);
99+
expect(descriptionSection).toBeTruthy();
100+
});
101+
102+
test('does not render description section when in IoP mode', () => {
103+
useAdvisorEngineConfig.mockReturnValue(true);
104+
105+
const { container } = renderWithStore(<PageHeader />);
106+
107+
// Description section should not be present in IoP mode
108+
const descriptionSection = container.querySelector(
109+
'.inventory-upload-header-description'
110+
);
111+
expect(descriptionSection).toBeNull();
112+
});
113+
});
13114
});

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

Lines changed: 0 additions & 36 deletions
This file was deleted.

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
);
Lines changed: 69 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,60 +1,78 @@
11
import React from 'react';
2-
import { Provider } from 'react-redux';
3-
import configureMockStore from 'redux-mock-store';
4-
import thunk from 'redux-thunk';
5-
import { screen, render } from '@testing-library/react';
2+
import { screen } from '@testing-library/react';
3+
import { rtlHelpers } from 'foremanReact/common/rtlTestHelpers';
64
import ToolbarButtons from '../ToolbarButtons';
5+
import { useAdvisorEngineConfig } from '../../../../../../common/Hooks/ConfigHooks';
6+
import { selectSubscriptionConnectionEnabled } from '../../../../InventorySettings/InventorySettingsSelectors';
77

8-
const middlewares = [thunk];
9-
const mockStore = configureMockStore(middlewares);
10-
11-
const renderOptions = {
12-
API: {
13-
INVENTORY_SETTINGS: {
14-
response: { subscriptionConnectionEnabled: true },
15-
},
16-
},
17-
ForemanRhCloud: {
18-
inventoryUpload: {
19-
accountsList: {
20-
CloudConnectorStatus: {},
21-
},
22-
},
23-
},
24-
};
8+
// Mock the config hook
9+
jest.mock('../../../../../../common/Hooks/ConfigHooks', () => ({
10+
useAdvisorEngineConfig: jest.fn(),
11+
}));
12+
13+
// Mock the selector
14+
jest.mock('../../../../InventorySettings/InventorySettingsSelectors', () => ({
15+
selectSubscriptionConnectionEnabled: jest.fn(),
16+
}));
17+
18+
// Mock child components to isolate ToolbarButtons testing
19+
jest.mock(
20+
'../../SyncButton',
21+
() =>
22+
function MockSyncButton() {
23+
return <div data-testid="sync-button">Sync all inventory status</div>;
24+
}
25+
);
26+
jest.mock(
27+
'../../CloudConnectorButton',
28+
() =>
29+
function MockCloudConnectorButton() {
30+
return (
31+
<div data-testid="cloud-connector-button">
32+
Configure cloud connector
33+
</div>
34+
);
35+
}
36+
);
37+
38+
const { renderWithStore } = rtlHelpers;
2539

2640
describe('ToolbarButtons', () => {
27-
test('when subscription connection is enabled', () => {
28-
const store = mockStore(renderOptions);
29-
30-
render(
31-
<Provider store={store}>
32-
<ToolbarButtons />
33-
</Provider>
34-
);
35-
expect(screen.queryAllByText('Configure cloud connector')).toHaveLength(1);
36-
expect(screen.queryAllByText('Sync all inventory status')).toHaveLength(1);
41+
test('renders both buttons when subscription connection is enabled and not in IOP mode', () => {
42+
useAdvisorEngineConfig.mockReturnValue(false);
43+
selectSubscriptionConnectionEnabled.mockReturnValue(true);
44+
45+
renderWithStore(<ToolbarButtons />);
46+
47+
expect(screen.getByTestId('cloud-connector-button')).toBeTruthy();
48+
expect(screen.getByTestId('sync-button')).toBeTruthy();
3749
});
3850

39-
test('when subscription connection is not enabled', () => {
40-
const localSetting = {
41-
API: {
42-
INVENTORY_SETTINGS: {
43-
response: { subscriptionConnectionEnabled: false },
44-
},
45-
},
46-
};
47-
const store = mockStore({
48-
...renderOptions,
49-
...localSetting,
50-
});
51-
52-
render(
53-
<Provider store={store}>
54-
<ToolbarButtons />
55-
</Provider>
56-
);
57-
expect(screen.queryAllByText('Configure cloud connector')).toHaveLength(0);
58-
expect(screen.queryAllByText('Sync all inventory status')).toHaveLength(0);
51+
test('renders only sync button when in IOP mode', () => {
52+
useAdvisorEngineConfig.mockReturnValue(true);
53+
selectSubscriptionConnectionEnabled.mockReturnValue(true);
54+
55+
renderWithStore(<ToolbarButtons />);
56+
57+
expect(screen.queryByTestId('cloud-connector-button')).toBeNull();
58+
expect(screen.getByTestId('sync-button')).toBeTruthy();
59+
});
60+
61+
test('renders nothing when subscription connection is not enabled', () => {
62+
useAdvisorEngineConfig.mockReturnValue(false);
63+
selectSubscriptionConnectionEnabled.mockReturnValue(false);
64+
65+
const { container } = renderWithStore(<ToolbarButtons />);
66+
67+
expect(container.firstChild).toBeNull();
68+
});
69+
70+
test('renders toolbar buttons container with correct className when enabled', () => {
71+
useAdvisorEngineConfig.mockReturnValue(false);
72+
selectSubscriptionConnectionEnabled.mockReturnValue(true);
73+
74+
const { container } = renderWithStore(<ToolbarButtons />);
75+
76+
expect(container.querySelector('.inventory_toolbar_buttons')).toBeTruthy();
5977
});
6078
});

0 commit comments

Comments
 (0)