Skip to content

Commit 4e1f998

Browse files
Merge pull request #643 from etmurasaki/etmura-perses
OU-877: perses e2e testing
2 parents 98f538d + 4f4cb9d commit 4e1f998

9 files changed

Lines changed: 434 additions & 25 deletions

File tree

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { nav } from '../../views/nav';
2+
import { runBVTCOOPersesTests } from '../../support/perses/00.coo_bvt_perses.cy';
3+
import { guidedTour } from '../../views/tour';
4+
5+
// Set constants for the operators that need to be installed for tests.
6+
const MCP = {
7+
namespace: 'openshift-cluster-observability-operator',
8+
packageName: 'cluster-observability-operator',
9+
operatorName: 'Cluster Observability Operator',
10+
config: {
11+
kind: 'UIPlugin',
12+
name: 'monitoring',
13+
},
14+
};
15+
16+
const MP = {
17+
namespace: 'openshift-monitoring',
18+
operatorName: 'Cluster Monitoring Operator',
19+
};
20+
21+
describe('BVT: COO - Dashboards (Perses) - Administrator perspective', () => {
22+
23+
before(() => {
24+
cy.beforeBlockCOO(MCP, MP);
25+
});
26+
27+
beforeEach(() => {
28+
cy.visit('/');
29+
guidedTour.close();
30+
cy.validateLogin();
31+
nav.sidenav.clickNavLink(['Observe', 'Dashboards (Perses)']);
32+
});
33+
34+
runBVTCOOPersesTests({
35+
name: 'Administrator',
36+
});
37+
38+
});
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import { nav } from '../../views/nav';
2+
import { runBVTCOOPersesTests } from '../../support/perses/00.coo_bvt_perses.cy';
3+
import { guidedTour } from '../../views/tour';
4+
import { commonPages } from '../../views/common';
5+
6+
// Set constants for the operators that need to be installed for tests.
7+
const MCP = {
8+
namespace: 'openshift-cluster-observability-operator',
9+
packageName: 'cluster-observability-operator',
10+
operatorName: 'Cluster Observability Operator',
11+
config: {
12+
kind: 'UIPlugin',
13+
name: 'monitoring',
14+
},
15+
};
16+
17+
const MP = {
18+
namespace: 'openshift-monitoring',
19+
operatorName: 'Cluster Monitoring Operator',
20+
};
21+
22+
const KBV = {
23+
namespace: 'openshift-cnv',
24+
packageName: 'kubevirt-hyperconverged',
25+
config: {
26+
kind: 'HyperConverged',
27+
name: 'kubevirt-hyperconverged',
28+
},
29+
crd: {
30+
kubevirt: 'kubevirts.kubevirt.io',
31+
hyperconverged: 'hyperconvergeds.hco.kubevirt.io',
32+
}
33+
};
34+
35+
describe('Installation: COO and setting up Monitoring Plugin', () => {
36+
37+
before(() => {
38+
cy.beforeBlockCOO(MCP, MP);
39+
});
40+
41+
it('1. Installation: COO and setting up Monitoring Plugin', () => {
42+
cy.log('Installation: COO and setting up Monitoring Plugin');
43+
});
44+
});
45+
46+
describe('Installation: Virtualization', () => {
47+
48+
before(() => {
49+
cy.beforeBlockVirtualization(KBV);
50+
});
51+
52+
it('1. Installation: Virtualization', () => {
53+
cy.log('Installation: Virtualization');
54+
cy.switchPerspective('Virtualization');
55+
guidedTour.closeKubevirtTour();
56+
});
57+
});
58+
59+
describe('IVT: COO - Dashboards (Perses) - Virtualization perspective', () => {
60+
61+
beforeEach(() => {
62+
cy.visit('/');
63+
guidedTour.close();
64+
cy.validateLogin();
65+
cy.switchPerspective('Virtualization');
66+
guidedTour.closeKubevirtTour();
67+
nav.sidenav.clickNavLink(['Observe', 'Dashboards (Perses)']);
68+
commonPages.titleShouldHaveText('Dashboards');
69+
});
70+
71+
runBVTCOOPersesTests({
72+
name: 'Virtualization',
73+
});
74+
75+
});
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
export enum persesDashboardsTimeRange {
2+
CUSTOM_TIME_RANGE = 'Custom Time Range',
3+
LAST_5_MINUTES = 'Last 5 minutes',
4+
LAST_15_MINUTES = 'Last 15 minutes',
5+
LAST_30_MINUTES = 'Last 30 minutes',
6+
LAST_1_HOUR = 'Last 1 hour',
7+
LAST_6_HOURS = 'Last 6 hours',
8+
LAST_12_HOURS = 'Last 12 hours',
9+
LAST_24_HOURS = 'Last 24 hours',
10+
LAST_7_DAYS = 'Last 7 days',
11+
LAST_14_DAYS = 'Last 14 days',
12+
}
13+
14+
export enum persesDashboardsRefreshInterval {
15+
OFF = 'Off',
16+
FIVE_SECONDS = '5s',
17+
TEN_SECONDS = '10s',
18+
FIFTEEN_SECONDS = '15s',
19+
THIRTY_SECONDS = '30s',
20+
ONE_MINUTE = '1m',
21+
}
22+
23+
export const persesDashboardsDashboardDropdownCOO = {
24+
ACCELERATORS_COMMON_METRICS:['Accelerators common metrics', 'perses'],
25+
K8S_COMPUTE_RESOURCES_CLUSTER: ['Kubernetes / Compute Resources / Cluster', 'perses'],
26+
}
27+
28+
export const persesDashboardsDashboardDropdownPersesDev = {
29+
PERSES_DASHBOARD_SAMPLE: ['Perses Dashboard Sample', 'perses'],
30+
PROMETHEUS_OVERVIEW: ['Prometheus / Overview', 'perses'],
31+
THANOS_COMPACT_OVERVIEW: ['Thanos / Compact / Overview', 'perses'],
32+
}
33+
34+
export enum persesDashboardsAcceleratorsCommonMetricsPanels {
35+
GPU_UTILIZATION = 'GPU Utilization',
36+
MEMORY_USED_BYTES = 'Memory Used Bytes',
37+
MEMORY_TOTAL_BYTES = 'Memory Total Bytes',
38+
POWER_USAGE_WATTS = 'Power Usage (Watts)',
39+
TEMPERATURE_CELCIUS = 'Temperature (Celsius)',
40+
SM_CLOCK_HERTZ = 'SM Clock (Hertz)',
41+
MEMORY_CLOCK_HERTZ = 'Memory Clock (Hertz)',
42+
}

web/cypress/support/commands/operator-commands.ts

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -250,17 +250,25 @@ const operatorUtils = {
250250

251251
waitForCOOReady(MCP: { namespace: string }): void {
252252
cy.log('Check Cluster Observability Operator status');
253-
cy.exec(
254-
`sleep 15 && oc wait --for=condition=Ready pods --selector=app.kubernetes.io/name=observability-operator -n ${MCP.namespace} --timeout=60s --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`,
255-
{
256-
timeout: readyTimeoutMilliseconds,
257-
failOnNonZeroExit: true
258-
}
259-
).then((result) => {
260-
expect(result.code).to.eq(0);
261-
cy.log(`Observability-operator pod is now running in namespace: ${MCP.namespace}`);
262-
});
263253

254+
cy.exec(`sleep 60 && oc get pods -n ${MCP.namespace} | grep observability-operator | awk '{print $1}'`, { timeout: readyTimeoutMilliseconds, failOnNonZeroExit: true })
255+
.its('stdout') // Get the captured output string
256+
.then((podName) => {
257+
// Trim any extra whitespace (newline, etc.)
258+
const COO_POD_NAME = podName.trim();
259+
cy.log(`Successfully retrieved Pod Name: ${COO_POD_NAME}`);
260+
cy.exec(
261+
`sleep 15 && oc wait --for=condition=Ready pods ${COO_POD_NAME} -n ${MCP.namespace} --timeout=60s --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`,
262+
{
263+
timeout: readyTimeoutMilliseconds,
264+
failOnNonZeroExit: true
265+
}
266+
).then((result) => {
267+
expect(result.code).to.eq(0);
268+
cy.log(`Observability-operator pod is now running in namespace: ${MCP.namespace}`);
269+
});
270+
});
271+
264272
cy.get('#page-sidebar').then(($sidebar) => {
265273
const section = $sidebar.text().includes('Ecosystem') ? 'Ecosystem' : 'Operators';
266274
nav.sidenav.clickNavLink([section, 'Installed Operators']);

web/cypress/support/commands/utility-commands.ts

Lines changed: 45 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { Classes, DataTestIDs, LegacyTestIDs } from "../../../src/components/data-test";
12
export {};
23

34
declare global {
@@ -57,21 +58,39 @@ Cypress.Commands.add('waitUntilWithCustomTimeout', (
5758

5859
Cypress.Commands.add('changeNamespace', (namespace: string) => {
5960
cy.log('Changing Namespace to: ' + namespace);
60-
cy.byLegacyTestID('namespace-bar-dropdown').find('button').scrollIntoView().should('be.visible').click();
61-
cy.get('[data-test="showSystemSwitch"]').then(($element)=> {
62-
if ($element.attr('data-checked-state') !== 'true') {
63-
cy.byTestID('showSystemSwitch').siblings('span').eq(0).should('be.visible').click();
61+
cy.wait(2000);
62+
cy.get('body').then(($body) => {
63+
const hasNamespaceBarDropdown = $body.find('[data-test-id="'+LegacyTestIDs.NamespaceBarDropdown+'"]').length > 0;
64+
if (hasNamespaceBarDropdown) {
65+
cy.byLegacyTestID(LegacyTestIDs.NamespaceBarDropdown).find('button').scrollIntoView().should('be.visible');
66+
cy.byLegacyTestID(LegacyTestIDs.NamespaceBarDropdown).find('button').scrollIntoView().should('be.visible').click({force: true});
67+
} else {
68+
cy.byClass(Classes.NamespaceDropdown).scrollIntoView().should('be.visible');
69+
cy.byClass(Classes.NamespaceDropdown).scrollIntoView().should('be.visible').click({force: true});
6470
}
6571
});
66-
cy.byTestID('dropdown-text-filter').type(namespace);
67-
cy.byTestID('dropdown-menu-item-link').contains(namespace).should('be.visible').click();
72+
cy.get('body').then(($body) => {
73+
const hasShowSystemSwitch = $body.find('[data-test="'+DataTestIDs.NamespaceDropdownShowSwitch+'"]').length > 0;
74+
if (hasShowSystemSwitch) {
75+
cy.get('[data-test="'+DataTestIDs.NamespaceDropdownShowSwitch+'"]').then(($element)=> {
76+
if ($element.attr('data-checked-state') !== 'true') {
77+
cy.byTestID(DataTestIDs.NamespaceDropdownShowSwitch).siblings('span').eq(0).should('be.visible');
78+
cy.byTestID(DataTestIDs.NamespaceDropdownShowSwitch).siblings('span').eq(0).should('be.visible').click({force: true});
79+
}
80+
});
81+
}
82+
});
83+
cy.byTestID(DataTestIDs.NamespaceDropdownTextFilter).type(namespace, {delay: 100});
84+
cy.byTestID(DataTestIDs.NamespaceDropdownMenuLink).contains(namespace).should('be.visible');
85+
cy.byTestID(DataTestIDs.NamespaceDropdownMenuLink).contains(namespace).should('be.visible').click({force: true});
6886
cy.log('Namespace changed to: ' + namespace);
6987
});
7088

7189
Cypress.Commands.add('aboutModal', () => {
7290
cy.log('Getting OCP version');
73-
cy.byTestID('help-dropdown-toggle').should('be.visible').click();
74-
cy.byTestID('application-launcher-item').contains('About').should('be.visible').click();
91+
cy.byTestID(DataTestIDs.MastHeadHelpIcon).should('be.visible');
92+
cy.byTestID(DataTestIDs.MastHeadHelpIcon).should('be.visible').click({force: true});
93+
cy.byTestID(DataTestIDs.MastHeadApplicationItem).contains('About').should('be.visible').click();
7594
cy.byAriaLabel('About modal').find('div[class*="co-select-to-copy"]').eq(0).should('be.visible').then(($ocpversion) => {
7695
cy.log('OCP version: ' + $ocpversion.text());
7796
});
@@ -97,14 +116,25 @@ Cypress.Commands.add('waitUntilWithCustomTimeout', (
97116
cy.log('Get pod image');
98117
cy.clickNavLink(['Workloads', 'Pods']);
99118
cy.changeNamespace(namespace);
100-
cy.byTestID('name-filter-input').should('be.visible').type(pod);
101-
cy.get(`a[data-test^="${pod}"]`).eq(0).as('podLink').click();
102-
cy.get('@podLink').should('be.visible').click();
103-
cy.byPFRole('rowgroup').find('td').eq(1).scrollIntoView().should('be.visible').then(($td) => {
104-
cy.log('Pod image: ' + $td.text());
105-
119+
cy.byTestID('page-heading').contains('Pods').should('be.visible');
120+
cy.wait(5000);
121+
// Check for DataViewFilters component using Cypress's built-in retry-ability
122+
cy.get('body').then(($body) => {
123+
const hasDataViewFilters = $body.find('[data-ouia-component-id="DataViewFilters"]').length > 0;
124+
if (hasDataViewFilters) {
125+
cy.byOUIAID('DataViewFilters').find('button').contains('Status').scrollIntoView().should('be.visible').click();
126+
cy.byOUIAID('OUIA-Generated-Menu').find('button').contains('Name').scrollIntoView().should('be.visible').click();
127+
cy.byAriaLabel('Name filter').scrollIntoView().should('be.visible').type(pod);
128+
} else {
129+
cy.byTestID('name-filter-input').should('be.visible').type(pod);
130+
}
106131
});
107-
cy.log('Get pod image completed');
132+
cy.get(`a[data-test^="${pod}"]`).eq(0).as('podLink').click();
133+
cy.get('@podLink').should('be.visible').click();
134+
cy.byPFRole('rowgroup').find('td').eq(1).scrollIntoView().should('be.visible').then(($td) => {
135+
cy.log('Pod image: ' + $td.text());
136+
});
137+
cy.log('Get pod image completed');
108138
});
109139

110140

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import { persesDashboardsAcceleratorsCommonMetricsPanels, persesDashboardsDashboardDropdownCOO, persesDashboardsDashboardDropdownPersesDev } from '../../fixtures/perses/constants';
2+
import { commonPages } from '../../views/common';
3+
import { persesDashboardsPage } from '../../views/perses-dashboards';
4+
import { persesDataTestIDs } from '../../../src/components/data-test';
5+
6+
export interface PerspectiveConfig {
7+
name: string;
8+
beforeEach?: () => void;
9+
}
10+
11+
export function runBVTCOOPersesTests(perspective: PerspectiveConfig) {
12+
testBVTCOOPerses(perspective);
13+
}
14+
15+
export function testBVTCOOPerses(perspective: PerspectiveConfig) {
16+
17+
it(`1.${perspective.name} perspective - Dashboards (Perses) page`, () => {
18+
cy.log(`1.1. use sidebar nav to go to Observe > Dashboards (Perses)`);
19+
commonPages.titleShouldHaveText('Dashboards');
20+
persesDashboardsPage.shouldBeLoaded();
21+
22+
persesDashboardsPage.timeRangeDropdownAssertion();
23+
persesDashboardsPage.refreshIntervalDropdownAssertion();
24+
persesDashboardsPage.dashboardDropdownAssertion(persesDashboardsDashboardDropdownCOO);
25+
cy.wait(1000);
26+
cy.changeNamespace('perses-dev');
27+
persesDashboardsPage.dashboardDropdownAssertion(persesDashboardsDashboardDropdownPersesDev);
28+
});
29+
30+
it(`2.${perspective.name} perspective - Accelerators common metrics dashboard `, () => {
31+
cy.log(`2.1. use sidebar nav to go to Observe > Dashboards (Perses) > Accelerators common metrics dashboard`);
32+
cy.changeNamespace('openshift-cluster-observability-operator');
33+
persesDashboardsPage.clickDashboardDropdown(persesDashboardsDashboardDropdownCOO.ACCELERATORS_COMMON_METRICS[0] as keyof typeof persesDashboardsDashboardDropdownCOO);
34+
cy.byDataTestID(persesDataTestIDs.variableDropdown+'-cluster').should('be.visible');
35+
persesDashboardsPage.panelGroupHeaderAssertion('Accelerators');
36+
persesDashboardsPage.panelHeadersAcceleratorsCommonMetricsAssertion();
37+
persesDashboardsPage.expandPanel(persesDashboardsAcceleratorsCommonMetricsPanels.GPU_UTILIZATION);
38+
persesDashboardsPage.collapsePanel(persesDashboardsAcceleratorsCommonMetricsPanels.GPU_UTILIZATION);
39+
});
40+
41+
it(`3.${perspective.name} perspective - Perses Dashboard Sample dashboard`, () => {
42+
cy.log(`3.1. use sidebar nav to go to Observe > Dashboards (Perses) > Perses Dashboard Sample dashboard`);
43+
cy.changeNamespace('perses-dev');
44+
persesDashboardsPage.clickDashboardDropdown(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0] as keyof typeof persesDashboardsDashboardDropdownPersesDev);
45+
cy.byDataTestID(persesDataTestIDs.variableDropdown+'-job').should('be.visible');
46+
cy.byDataTestID(persesDataTestIDs.variableDropdown+'-instance').should('be.visible');
47+
cy.byDataTestID(persesDataTestIDs.variableDropdown+'-interval').should('be.visible');
48+
cy.byDataTestID(persesDataTestIDs.variableDropdown+'-text').should('be.visible');
49+
persesDashboardsPage.panelGroupHeaderAssertion('Row 1');
50+
persesDashboardsPage.expandPanel('RAM Used');
51+
persesDashboardsPage.collapsePanel('RAM Used');
52+
persesDashboardsPage.statChartValueAssertion('RAM Used', true);
53+
persesDashboardsPage.searchAndSelectVariable('job', 'node-exporter');
54+
persesDashboardsPage.statChartValueAssertion('RAM Used', false);
55+
56+
});
57+
58+
}

web/cypress/support/selectors.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ declare global {
2222
bySemanticElement(element: string, text?: string): Chainable<JQuery<HTMLElement>>;
2323
byAriaLabel(label: string, options?: Partial<Loggable & Timeoutable & Withinable & Shadow>): Chainable<JQuery<HTMLElement>>;
2424
byPFRole(role: string, options?: Partial<Loggable & Timeoutable & Withinable & Shadow>): Chainable<JQuery<HTMLElement>>;
25+
byDataTestID(
26+
selector: string,
27+
options?: Partial<Loggable & Timeoutable & Withinable & Shadow>,
28+
): Chainable<Element>;
2529
}
2630
}
2731
}
@@ -38,6 +42,11 @@ Cypress.Commands.add(
3842
},
3943
);
4044

45+
//MaterialUI data-testid selectors
46+
Cypress.Commands.add('byDataTestID', (selector: string, options?: Partial<Loggable & Timeoutable & Withinable & Shadow>) => {
47+
cy.get(`[data-testid="${selector}"]`, options);
48+
});
49+
4150
// deprecated! new IDs should use 'data-test', ie. `cy.byTestID(...)`
4251
Cypress.Commands.add('byLegacyTestID', (selector: string) =>
4352
cy.get(`[data-test-id="${selector}"]`),

0 commit comments

Comments
 (0)