diff --git a/frontend/integration-tests/protractor.conf.ts b/frontend/integration-tests/protractor.conf.ts index df2759ecb31..46205de12cc 100644 --- a/frontend/integration-tests/protractor.conf.ts +++ b/frontend/integration-tests/protractor.conf.ts @@ -8,11 +8,6 @@ import * as ConsoleReporter from 'jasmine-console-reporter'; import * as failFast from 'protractor-fail-fast'; import { createWriteStream, writeFileSync } from 'fs'; import { format } from 'util'; -import { - resolvePluginPackages, - reducePluginTestSuites, - mergeTestSuites, -} from '@console/plugin-sdk/src/codegen'; const tap = !!process.env.TAP; @@ -194,10 +189,103 @@ export const config: Config = { failFast.clean(); return new Promise((resolve) => htmlReporter.afterLaunch(resolve.bind(this, exitCode))); }, - suites: mergeTestSuites( - testSuites, - reducePluginTestSuites(resolvePluginPackages(), __dirname, suite), - ), + suites: { + dashboardsTests: ['tests/dashboards/dashboard.scenario.ts'], + dashboardsBareMetalHosts: [ + '../packages/metal3-plugin/integration-tests/tests/dashboards/dashboard.scenario.ts', + ], + filter: suite(['tests/filter.scenario.ts']), + annotation: suite(['tests/modal-annotations.scenario.ts']), + environment: suite(['tests/environment.scenario.ts']), + secrets: suite(['tests/secrets.scenario.ts']), + storage: suite(['tests/storage.scenario.ts']), + crud: suite([ + 'tests/crud.scenario.ts', + 'tests/secrets.scenario.ts', + 'tests/filter.scenario.ts', + 'tests/modal-annotations.scenario.ts', + 'tests/environment.scenario.ts', + ]), + monitoring: suite(['tests/monitoring.scenario.ts']), + newApp: suite(['tests/overview/overview.scenario.ts', 'tests/deploy-image.scenario.ts']), + olmFull: suite([ + '../packages/operator-lifecycle-manager/integration-tests/scenarios/descriptors.scenario.ts', + '../packages/operator-lifecycle-manager/integration-tests/scenarios/operator-hub.scenario.ts', + '../packages/operator-lifecycle-manager/integration-tests/scenarios/global-installmode.scenario.ts', + '../packages/operator-lifecycle-manager/integration-tests/scenarios/single-installmode.scenario.ts', + ]), + performance: suite(['tests/performance.scenario.ts']), + serviceCatalog: suite([ + 'tests/service-catalog/service-catalog.scenario.ts', + 'tests/service-catalog/service-broker.scenario.ts', + 'tests/service-catalog/service-class.scenario.ts', + 'tests/service-catalog/service-binding.scenario.ts', + 'tests/developer-catalog.scenario.ts', + ]), + overview: suite(['tests/overview/overview.scenario.ts']), + crdExtensions: suite(['tests/crd-extensions.scenario.ts']), + e2e: suite([ + 'tests/crud.scenario.ts', + 'tests/secrets.scenario.ts', + 'tests/storage.scenario.ts', + 'tests/filter.scenario.ts', + 'tests/modal-annotations.scenario.ts', + 'tests/environment.scenario.ts', + 'tests/overview/overview.scenario.ts', + 'tests/deploy-image.scenario.ts', + 'tests/performance.scenario.ts', + 'tests/monitoring.scenario.ts', + 'tests/crd-extensions.scenario.ts', + '../packages/operator-lifecycle-manager/integration-tests/scenarios/descriptors.scenario.ts', + '../packages/operator-lifecycle-manager/integration-tests/scenarios/operator-hub.scenario.ts', + '../packages/operator-lifecycle-manager/integration-tests/scenarios/global-installmode.scenario.ts', + '../packages/operator-lifecycle-manager/integration-tests/scenarios/single-installmode.scenario.ts', + ]), + release: suite([ + 'tests/crud.scenario.ts', + 'tests/secrets.scenario.ts', + 'tests/filter.scenario.ts', + 'tests/environment.scenario.ts', + 'tests/overview/overview.scenario.ts', + 'tests/deploy-image.scenario.ts', + 'tests/performance.scenario.ts', + 'tests/monitoring.scenario.ts', + 'tests/crd-extensions.scenario.ts', + ]), + 'kubevirt-plugin': suite([ + '../packages/kubevirt-plugin/integration-tests/tests/vm.wizard.scenario.ts', + '../packages/kubevirt-plugin/integration-tests/tests/vm.yaml.scenario.ts', + '../packages/kubevirt-plugin/integration-tests/tests/vm.actions.scenario.ts', + '../packages/kubevirt-plugin/integration-tests/tests/vm.migration.scenario.ts', + '../packages/kubevirt-plugin/integration-tests/tests/vm.resources.scenario.ts', + '../packages/kubevirt-plugin/integration-tests/tests/vm.clone.scenario.ts', + '../packages/kubevirt-plugin/integration-tests/tests/vm.detail.flavor.scenario.ts', + '../packages/kubevirt-plugin/integration-tests/tests/vm.template.wizard.scenario.ts', + ]), + all: suite([ + 'tests/crud.scenario.ts', + 'tests/overview/overview.scenareio.ts', + 'tests/secrets.scenario.ts', + 'tests/storage.scenario.ts', + 'tests/olm/**/*.scenario.ts', + 'tests/service-catalog/**/*.scenario.ts', + 'tests/filter.scenario.ts', + 'tests/modal-annotations.scenario.ts', + 'tests/deploy-image.scenario.ts', + 'tests/operator-hub/operator-hub.scenario.ts', + 'tests/developer-catalog.scenario.ts', + 'tests/monitoring.scenario.ts', + 'tests/devconsole/dev-perspective.scenario.ts', + 'tests/devconsole/git-import-flow.scenario.ts', + 'tests/crd-extensions.scenario.ts', + ]), + clusterSettings: suite(['tests/cluster-settings.scenario.ts']), + login: ['tests/login.scenario.ts'], + devconsole: [ + 'tests/devconsole/dev-perspective.scenario.ts', + 'tests/devconsole/git-import-flow.scenario.ts', + ], + }, params: { // Set to 'true' to enable OpenShift resources in the crud scenario. // Use a string rather than boolean so it can be specified on the command line: diff --git a/frontend/integration-tests/tests/dashboards/dashboard.scenario.ts b/frontend/integration-tests/tests/dashboards/dashboard.scenario.ts new file mode 100644 index 00000000000..f3b2ced8fb5 --- /dev/null +++ b/frontend/integration-tests/tests/dashboards/dashboard.scenario.ts @@ -0,0 +1,26 @@ +import { browser, ExpectedConditions as until } from 'protractor'; +const execSync = require('child_process').execSync; + +import { appHost } from '../../protractor.conf'; +import * as dashboardView from '../../views/dashboards/dashboards.view'; + +describe('Inventory card', () => { + beforeAll(async () => { + await browser.get(`${appHost}/dashboards`); + await dashboardView.isLoaded(); + // wait until the counters in the inventory card show up + await browser.wait( + until.textToBePresentInElement(dashboardView.inventoryNodesItemLabel, ' Nodes'), + 10000, + ); + }); + + it('Node count is displayed', async () => { + // get the number of ready and not ready nodes from the CLI + const output = execSync('oc get nodes -o json', { encoding: 'utf-8' }); + const nodes = JSON.parse(output); + const displayedLabel = await dashboardView.inventoryNodesItemLabel.getText(); + // comparing if the dashboards are displaying ${nodes.items.length} nodes total + expect(displayedLabel).toEqual(`${nodes.items.length} Nodes`); + }); +}); diff --git a/frontend/integration-tests/views/dashboards/dashboards.view.ts b/frontend/integration-tests/views/dashboards/dashboards.view.ts new file mode 100644 index 00000000000..4ac9a083727 --- /dev/null +++ b/frontend/integration-tests/views/dashboards/dashboards.view.ts @@ -0,0 +1,38 @@ +import { browser, $, $$ } from 'protractor'; +import { waitForNone } from '../../protractor.conf'; + +export const untilNoLoadersPresent = waitForNone($$('.co-m-loader')); +export const isLoaded = () => browser.wait(untilNoLoadersPresent).then(() => browser.sleep(2000)); + +export const inventoryNodesItemLabel = $('[data-test-id="console-dashboard-inventory-node"]') + .$('.co-inventory-card__item-title') + .$('a'); +export const inventoryNodesDownCounter = $('[data-test-id="console-dashboard-inventory-node"]').$( + '[data-test-id="console-dashboard-inventory-count-notready"]', +); + +export const inventoryPodsItemLabel = $('[data-test-id="console-dashboard-inventory-pod"]') + .$('.co-inventory-card__item-title') + .$('a'); +export const inventoryPodsDownCounter = $('[data-test-id="console-dashboard-inventory-pod"]').$( + '[data-test-id="console-dashboard-inventory-count-crashloopbackoff-failed"]', +); + +export const inventoryHostsItemLabel = $( + '[data-test-id="console-dashboard-inventory-baremetalhost"]', +) + .$('.co-inventory-card__item-title') + .$('a'); +export const inventoryHostsDownCounter = $( + '[data-test-id="console-dashboard-inventory-baremetalhost"]', +).$('[data-test-id="console-dashboard-inventory-count-notready"]'); + +// Utility function: getTextIfPresent +export async function getTextIfPresent(elem, textIfNotPresent = '') { + if (await elem.isPresent()) { + return elem.getText(); + } + return new Promise((resolve) => { + resolve(textIfNotPresent); + }); +} diff --git a/frontend/packages/console-shared/src/components/dashboard/inventory-card/InventoryItem.tsx b/frontend/packages/console-shared/src/components/dashboard/inventory-card/InventoryItem.tsx index 69837c679fe..020b157699c 100644 --- a/frontend/packages/console-shared/src/components/dashboard/inventory-card/InventoryItem.tsx +++ b/frontend/packages/console-shared/src/components/dashboard/inventory-card/InventoryItem.tsx @@ -69,6 +69,7 @@ const InventoryItem: React.FC = React.memo( error = false, TitleComponent, ExpandedComponent, + ...props }) => { const [expanded, setExpanded] = React.useState(false); const onClick = React.useCallback(() => setExpanded(!expanded), [expanded]); @@ -86,7 +87,7 @@ const InventoryItem: React.FC = React.memo( id={title} className="co-inventory-card__accordion-toggle" > -
+
{isLoading && !error &&
} {TitleComponent ? {titleMessage} : titleMessage} @@ -108,7 +109,10 @@ const InventoryItem: React.FC = React.memo( ) : ( -
+
{isLoading && !error &&
} {TitleComponent ? {titleMessage} : titleMessage} @@ -152,6 +156,7 @@ const StatusLink = connectToFlags( const statusItems = encodeURIComponent(statusIDs.join(',')); const namespacePath = namespace ? `ns/${namespace}` : 'all-namespaces'; const path = basePath || `/k8s/${namespacePath}/${kind.plural}`; + const cleanStatusItems = statusIDs.join('-').toLowerCase(); const to = filterType && statusItems.length > 0 ? `${path}?rowFilter-${filterType}=${statusItems}` : path; const statusGroupIcons = getStatusGroupIcons(flags); @@ -160,7 +165,12 @@ const StatusLink = connectToFlags(
{groupIcon} - {count} + + {count} +
); @@ -189,6 +199,7 @@ export const ResourceInventoryItem = connectToFlags( flags = {}, ExpandedComponent, basePath, + ...rest }) => { const TitleComponent = React.useCallback( (props) => ( @@ -211,6 +222,7 @@ export const ResourceInventoryItem = connectToFlags( error={error} TitleComponent={showLink ? TitleComponent : null} ExpandedComponent={ExpandedComponent} + data-test-id={rest['data-test-id']} > {top3Groups.map((key) => showLink ? ( @@ -257,6 +269,7 @@ type InventoryItemProps = { error?: boolean; TitleComponent?: React.ComponentType<{}>; ExpandedComponent?: React.ComponentType<{}>; + 'data-test-id'?: string; }; type StatusProps = WithFlagsProps & { @@ -295,4 +308,5 @@ type ResourceTitleComponentComponent = { kind: K8sKind; namespace: string; basePath?: string; + 'data-test-id'?: string; }; diff --git a/frontend/packages/metal3-plugin/integration-tests/tests/dashboards/dashboard.scenario.ts b/frontend/packages/metal3-plugin/integration-tests/tests/dashboards/dashboard.scenario.ts new file mode 100644 index 00000000000..94e1cf6618b --- /dev/null +++ b/frontend/packages/metal3-plugin/integration-tests/tests/dashboards/dashboard.scenario.ts @@ -0,0 +1,27 @@ +import { execSync } from 'child_process'; +import { browser, ExpectedConditions as until } from 'protractor'; +import { appHost } from '../../../../../integration-tests/protractor.conf.ts'; +import * as dashboardView from '../../../../../integration-tests/views/dashboards/dashboards.view'; + +describe('Inventory card', () => { + beforeAll(async () => { + await browser.get(`${appHost}/dashboards`); + await dashboardView.isLoaded(); + // wait until the counters in the inventory card show up + await browser.wait( + until.textToBePresentInElement(dashboardView.inventoryHostsItemLabel, ' Bare Metal Hosts'), + 10000, + ); + }); + + it('Host count is displayed', async () => { + // get the hosts and their statuses from the CLI + const output = execSync('oc get baremetalhosts -n openshift-machine-api -o json', { + encoding: 'utf-8', + }); + const hosts = JSON.parse(output); + const displayedLabel = await dashboardView.inventoryHostsItemLabel.getText(); + // comparing if the dashboards are displaying ${hosts.items.length} hosts total + expect(displayedLabel).toEqual(`${hosts.items.length} Bare Metal Hosts`); + }); +}); diff --git a/frontend/packages/metal3-plugin/package.json b/frontend/packages/metal3-plugin/package.json index 0e7bf5b18be..e410bcd7b76 100644 --- a/frontend/packages/metal3-plugin/package.json +++ b/frontend/packages/metal3-plugin/package.json @@ -8,6 +8,11 @@ "@console/shared": "0.0.0-fixed" }, "consolePlugin": { - "entry": "src/plugin.ts" + "entry": "src/plugin.ts", + "integrationTests": { + "dashboardsBareMetalHosts": [ + "integration-tests/tests/dashboards/dashboard.scenario.ts" + ] + } } } diff --git a/frontend/packages/metal3-plugin/src/components/baremetal-hosts/dashboard/InventoryCard.tsx b/frontend/packages/metal3-plugin/src/components/baremetal-hosts/dashboard/InventoryCard.tsx index 98d08ec8716..c4c382c97cc 100644 --- a/frontend/packages/metal3-plugin/src/components/baremetal-hosts/dashboard/InventoryCard.tsx +++ b/frontend/packages/metal3-plugin/src/components/baremetal-hosts/dashboard/InventoryCard.tsx @@ -97,10 +97,18 @@ const InventoryCard: React.FC = () => { TitleComponent={DiskTitleComponent} /> >>>>>> 2657874c6... Testing infra for the system dashboards /> diff --git a/frontend/public/components/dashboard/dashboards-page/overview-dashboard/inventory-card.tsx b/frontend/public/components/dashboard/dashboards-page/overview-dashboard/inventory-card.tsx index c8cce3be6f0..1d82c7929fb 100644 --- a/frontend/public/components/dashboard/dashboards-page/overview-dashboard/inventory-card.tsx +++ b/frontend/public/components/dashboard/dashboards-page/overview-dashboard/inventory-card.tsx @@ -49,6 +49,7 @@ const ClusterInventoryItem = withDashboardResources( useAbbr, additionalResources, expandedComponent, + ...props }: ClusterInventoryItemProps) => { React.useEffect(() => { const resource = getFirehoseResource(model); @@ -104,6 +105,7 @@ const ClusterInventoryItem = withDashboardResources( useAbbr={useAbbr} additionalResources={additionalResourcesData} ExpandedComponent={expandedComponent ? ExpandedComponent : null} + data-test-id={props['data-test-id']} /> ); }, @@ -120,14 +122,26 @@ export const InventoryCard = connectToFlags( Cluster Inventory - - - + + + + data-test-id="console-dashboard-inventory-pvcm" + /> {items.map((item) => ( ))} @@ -149,4 +164,5 @@ type ClusterInventoryItemProps = DashboardItemProps & { useAbbr?: boolean; additionalResources?: FirehoseResource[]; expandedComponent?: LazyLoader; + 'data-test-id'?: string; };