diff --git a/.eslintrc b/.eslintrc index 5ebc30109..bf7886e16 100644 --- a/.eslintrc +++ b/.eslintrc @@ -14,8 +14,10 @@ "advisor", "ansible", "camelcase", + "cdn", "checkbox", "csrf", + "cve", "cves", "dropdown", "donut", @@ -23,6 +25,7 @@ "href", "ips", "ipv4", + "dropdown", "jed", "katello", "knowledgebase", @@ -31,15 +34,15 @@ "nowrap", "pid", "redhat", + "redux", "remediate", "remediations", "repo", "rhc", + "scalprum", "theforeman", "tooltip", - "unmount", - "redux", - "dropdown" + "unmount" ], "minLength": 3 } diff --git a/package.json b/package.json index 43479e9e8..f2be22cd4 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,10 @@ "peerDependencies": { "@theforeman/vendor": ">= 15.0.1" }, + "dependencies": { + "@scalprum/react-core": "^0.9.3", + "@scalprum/core": "^0.8.1" + }, "devDependencies": { "@babel/core": "^7.7.0", "@theforeman/builder": ">= 15.0.1", diff --git a/webpack/CVEsHostDetailsTab/CVEsHostDetailsTab.js b/webpack/CVEsHostDetailsTab/CVEsHostDetailsTab.js index 3241c5c9f..e719d5f7d 100644 --- a/webpack/CVEsHostDetailsTab/CVEsHostDetailsTab.js +++ b/webpack/CVEsHostDetailsTab/CVEsHostDetailsTab.js @@ -1,17 +1,37 @@ import React from 'react'; import PropTypes from 'prop-types'; -import { translate as __ } from 'foremanReact/common/I18n'; +import { ScalprumComponent, ScalprumProvider } from '@scalprum/react-core'; +import { providerOptions } from '../common/ScalprumModule/ScalprumContext'; -const CVEsHostDetailsTab = ({ hostName }) => ( -
-

- {__('CVEs tab for host:')} {hostName} -

-
-); +const CVEsHostDetailsTab = ({ systemId }) => { + const scope = 'vulnerability'; + const module = './SystemDetailTable'; + return ( +
+ +
+ ); +}; CVEsHostDetailsTab.propTypes = { - hostName: PropTypes.string.isRequired, + systemId: PropTypes.string.isRequired, +}; + +const CVEsHostDetailsTabWrapper = ({ response }) => ( + + + +); + +CVEsHostDetailsTabWrapper.propTypes = { + response: PropTypes.shape({ + subscription_facet_attributes: PropTypes.shape({ + uuid: PropTypes.string.isRequired, + }), + }).isRequired, }; -export default CVEsHostDetailsTab; +export default CVEsHostDetailsTabWrapper; diff --git a/webpack/CVEsHostDetailsTab/__tests__/CVEsHostDetailsTab.test.js b/webpack/CVEsHostDetailsTab/__tests__/CVEsHostDetailsTab.test.js index 42ebf8ee4..be22e2b08 100644 --- a/webpack/CVEsHostDetailsTab/__tests__/CVEsHostDetailsTab.test.js +++ b/webpack/CVEsHostDetailsTab/__tests__/CVEsHostDetailsTab.test.js @@ -1,18 +1,25 @@ import React from 'react'; -import { render, screen } from '@testing-library/react'; -import CVEsHostDetailsTab from '../CVEsHostDetailsTab'; +import { render } from '@testing-library/react'; +import CVEsHostDetailsTabWrapper from '../CVEsHostDetailsTab'; -describe('CVEsHostDetailsTab', () => { +jest.mock('@scalprum/react-core', () => ({ + ScalprumComponent: jest.fn(props => ( +
{JSON.stringify(props)}
+ )), + ScalprumProvider: jest.fn(({ children }) =>
{children}
), +})); + +describe('CVEsHostDetailsTabWrapper', () => { it('renders without crashing', () => { - render(); + const { container } = render( + + ); expect( - screen.getByText('CVEs tab for host: test-host.example.com') + container.querySelector( + '.rh-cloud-insights-vulnerability-host-details-component' + ) ).toBeTruthy(); }); - - it('renders the host name', () => { - const hostName = 'test-host.example.com'; - render(); - expect(screen.getByText(`CVEs tab for host: ${hostName}`)).toBeTruthy(); - }); }); diff --git a/webpack/CVEsHostDetailsTab/index.js b/webpack/CVEsHostDetailsTab/index.js index e67c6a77e..401a6f39b 100644 --- a/webpack/CVEsHostDetailsTab/index.js +++ b/webpack/CVEsHostDetailsTab/index.js @@ -1,3 +1,3 @@ -import CVEsHostDetailsTab from './CVEsHostDetailsTab'; +import CVEsHostDetailsTabWrapper from './CVEsHostDetailsTab'; -export default CVEsHostDetailsTab; +export default CVEsHostDetailsTabWrapper; diff --git a/webpack/ForemanRhCloudFills.js b/webpack/ForemanRhCloudFills.js index a64ff9217..088908504 100644 --- a/webpack/ForemanRhCloudFills.js +++ b/webpack/ForemanRhCloudFills.js @@ -5,7 +5,7 @@ import InventoryAutoUploadSwitcher from './ForemanInventoryUpload/SubscriptionsP import NewHostDetailsTab from './InsightsHostDetailsTab/NewHostDetailsTab'; import { InsightsTotalRiskChartWrapper } from './InsightsHostDetailsTab/InsightsTotalRiskChartWrapper'; import { isNotRhelHost, vulnerabilityDisabled } from './ForemanRhCloudHelpers'; -import CVEsHostDetailsTab from './CVEsHostDetailsTab/CVEsHostDetailsTab'; +import CVEsHostDetailsTabWrapper from './CVEsHostDetailsTab/CVEsHostDetailsTab'; const fills = [ { @@ -32,11 +32,12 @@ const fills = [ }, { slot: 'host-details-page-tabs', - name: 'CVEs', - component: props => , + name: 'Vulnerabilities', + component: props => , weight: 300, metadata: { hideTab: vulnerabilityDisabled, + title: __('Vulnerabilities'), }, }, ]; diff --git a/webpack/ForemanRhCloudPages.js b/webpack/ForemanRhCloudPages.js index 988442afb..2cb3512cc 100644 --- a/webpack/ForemanRhCloudPages.js +++ b/webpack/ForemanRhCloudPages.js @@ -2,7 +2,7 @@ import React from 'react'; import componentRegistry from 'foremanReact/components/componentRegistry'; import { registerRoutes as foremanRegisterRoutes } from 'foremanReact/routes/RoutingService'; import ForemanInventoryUpload from './ForemanInventoryUpload'; -import InsightsVulnerability from './InsightsVulnerability/InsightsVulnerability'; +import InsightsVulnerabilityListPage from './InsightsVulnerability/InsightsVulnerabilityListPage'; import InsightsCloudSync from './InsightsCloudSync'; import InsightsHostDetailsTab from './InsightsHostDetailsTab'; @@ -10,7 +10,10 @@ const pages = [ { name: 'ForemanInventoryUpload', type: ForemanInventoryUpload }, { name: 'InsightsCloudSync', type: InsightsCloudSync }, { name: 'InsightsHostDetailsTab', type: InsightsHostDetailsTab }, - { name: 'InsightsVulnerability', type: InsightsVulnerability }, + { + name: 'InsightsVulnerabilityListPage', + type: InsightsVulnerabilityListPage, + }, ]; export const registerPages = () => { @@ -31,7 +34,7 @@ export const routes = [ { path: '/foreman_rh_cloud/insights_vulnerability', exact: true, - render: props => , + render: props => , }, ]; diff --git a/webpack/InsightsVulnerability/InsightsVulnerability.js b/webpack/InsightsVulnerability/InsightsVulnerability.js deleted file mode 100644 index a77325dd4..000000000 --- a/webpack/InsightsVulnerability/InsightsVulnerability.js +++ /dev/null @@ -1,13 +0,0 @@ -import React from 'react'; -import PageLayout from 'foremanReact/routes/common/PageLayout/PageLayout'; -import { translate as __ } from 'foremanReact/common/I18n'; - -const InsightsVulnerability = () => ( - -
-

This page is under development. Please check back soon for updates.

-
-
-); - -export default InsightsVulnerability; diff --git a/webpack/InsightsVulnerability/InsightsVulnerability.test.js b/webpack/InsightsVulnerability/InsightsVulnerability.test.js deleted file mode 100644 index 479448c45..000000000 --- a/webpack/InsightsVulnerability/InsightsVulnerability.test.js +++ /dev/null @@ -1,18 +0,0 @@ -import React from 'react'; -import { render, screen } from '@testing-library/react'; -import '@testing-library/jest-dom'; -import InsightsVulnerability from './InsightsVulnerability'; - -describe('InsightsVulnerability component', () => { - it('renders the "under development" message', () => { - render(); - expect( - screen.getByText(/this page is under development/i) - ).toBeInTheDocument(); - }); - - it('renders the container with correct class', () => { - const { container } = render(); - expect(container.querySelector('.insights-vulnerability')).toBeTruthy(); - }); -}); diff --git a/webpack/InsightsVulnerability/InsightsVulnerabilityListPage.js b/webpack/InsightsVulnerability/InsightsVulnerabilityListPage.js new file mode 100644 index 000000000..fc17c3979 --- /dev/null +++ b/webpack/InsightsVulnerability/InsightsVulnerabilityListPage.js @@ -0,0 +1,21 @@ +import React from 'react'; +import { ScalprumComponent, ScalprumProvider } from '@scalprum/react-core'; +import { providerOptions } from '../common/ScalprumModule/ScalprumContext'; + +const InsightsVulnerabilityListPage = () => { + const scope = 'vulnerability'; + const module = './CveListPage'; + return ( +
+ +
+ ); +}; + +const InsightsVulnerabilityListPageWrap = () => ( + + + +); + +export default InsightsVulnerabilityListPageWrap; diff --git a/webpack/InsightsVulnerability/InsightsVulnerabilityListPage.test.js b/webpack/InsightsVulnerability/InsightsVulnerabilityListPage.test.js new file mode 100644 index 000000000..39aecb720 --- /dev/null +++ b/webpack/InsightsVulnerability/InsightsVulnerabilityListPage.test.js @@ -0,0 +1,20 @@ +import React from 'react'; +import { render } from '@testing-library/react'; +import '@testing-library/jest-dom'; +import InsightsVulnerabilityListPage from './InsightsVulnerabilityListPage'; + +jest.mock('@scalprum/react-core', () => ({ + ScalprumComponent: jest.fn(props => ( +
{JSON.stringify(props)}
+ )), + ScalprumProvider: jest.fn(({ children }) =>
{children}
), +})); + +describe('InsightsVulnerabilityListPage component', () => { + it('renders the container with correct class', () => { + const { container } = render(); + expect( + container.querySelector('.rh-cloud-insights-vulnerability-page') + ).toBeTruthy(); + }); +}); diff --git a/webpack/common/ScalprumModule/ScalprumContext.js b/webpack/common/ScalprumModule/ScalprumContext.js new file mode 100644 index 000000000..77829c2d6 --- /dev/null +++ b/webpack/common/ScalprumModule/ScalprumContext.js @@ -0,0 +1,63 @@ +export const modulesConfig = { + vulnerability: { + name: 'vulnerability', + manifestLocation: `${window.location.origin}/assets/apps/vulnerability/fed-mods.json`, + cdnPath: `${window.location.origin}/assets/apps/vulnerability/`, + }, +}; + +export const mockUser = { + entitlements: {}, + identity: { + account_number: 'string', + org_id: 'FOREMAN', + internal: { + org_id: 'string', + account_id: 'string', + }, + type: 'string', + user: { + username: 'string', + email: 'string', + first_name: 'string', + last_name: 'string', + is_active: 'boolean', + is_internal: 'boolean', + is_org_admin: 'boolean', + locale: 'string', + }, + }, +}; + +export const providerOptions = { + pluginSDKOptions: { + pluginLoaderOptions: { + transformPluginManifest: manifest => { + if ( + manifest.baseURL === 'auto' && + modulesConfig[manifest.name]?.cdnPath + ) { + const _cdnPath = modulesConfig[manifest.name]?.cdnPath; + return { + ...manifest, + baseURL: _cdnPath, + loadScripts: manifest.loadScripts.map( + script => `${_cdnPath}${script}` + ), + }; + } + return manifest; + }, + }, + }, + api: { + chrome: { + isBeta: () => false, + on: () => {}, + auth: { + getUser: () => Promise.resolve(mockUser), + }, + }, + }, + config: modulesConfig, +};