Skip to content

Commit

Permalink
Add tests for dashboard pages
Browse files Browse the repository at this point in the history
  • Loading branch information
rawagner committed Feb 4, 2020
1 parent 3368f38 commit d8cf59f
Show file tree
Hide file tree
Showing 21 changed files with 397 additions and 38 deletions.
10 changes: 10 additions & 0 deletions frontend/integration-tests/protractor.conf.ts
Expand Up @@ -91,6 +91,8 @@ const testSuites = {
'tests/alertmanager.scenario.ts',
'tests/crd-extensions.scenario.ts',
'tests/devconsole/pipeline.scenario.ts',
'tests/dashboards/cluster-dashboard.scenario.ts',
'tests/dashboards/project-dashboard.scenario.ts',
]),
release: suite([
'tests/crud.scenario.ts',
Expand All @@ -102,6 +104,8 @@ const testSuites = {
'tests/performance.scenario.ts',
'tests/monitoring.scenario.ts',
'tests/crd-extensions.scenario.ts',
'tests/dashboards/cluster-dashboard.scenario.ts',
'tests/dashboards/project-dashboard.scenario.ts',
]),
all: suite([
'tests/crud.scenario.ts',
Expand All @@ -120,10 +124,16 @@ const testSuites = {
'tests/devconsole/git-import-flow.scenario.ts',
'tests/devconsole/pipeline.scenario.ts',
'tests/crd-extensions.scenario.ts',
'tests/dashboards/cluster-dashboard.scenario.ts',
'tests/dashboards/project-dashboard.scenario.ts',
]),
clusterSettings: suite(['tests/cluster-settings.scenario.ts']),
alertmanager: suite(['tests/alertmanager.scenario.ts']),
login: ['tests/login.scenario.ts'],
dashboards: suite([
'tests/dashboards/cluster-dashboard.scenario.ts',
'tests/dashboards/project-dashboard.scenario.ts',
]),
};

export const config = {
Expand Down
@@ -0,0 +1,109 @@
import * as dashboardView from '@console/shared/src/test-views/dashboard-shared.view';
import * as clusterDashboardView from '../../views/dashboard.view';
import * as sideNavView from '../../views/sidenav.view';

const inventoryItems = [
{ title: 'Node', link: '/k8s/cluster/nodes' },
{ title: 'Pod', link: '/k8s/all-namespaces/pods' },
{ title: 'Storage Class', link: '/k8s/cluster/storageclasses' },
{ title: 'PVC', link: '/k8s/all-namespaces/persistentvolumeclaims' },
];

const utiliztionItems = ['CPU', 'Memory', 'Filesystem', 'Network Transfer', 'Pod count'];

describe('Cluster Dashboard', () => {
beforeAll(async () => {
await sideNavView.clickNavLink(['Home', 'Overview']);
await dashboardView.isLoaded();
});

describe('Details Card', () => {
it('has all fields populated', async () => {
expect(clusterDashboardView.detailsCard.isDisplayed()).toBe(true);
const items = clusterDashboardView.detailsCardList.$$('dt');
const values = clusterDashboardView.detailsCardList.$$('dd');

expect(items.count()).toBe(5);
expect(values.count()).toBe(5);
expect(items.get(0).getText()).toEqual('Cluster API Address');
expect(items.get(1).getText()).toEqual('Cluster ID');
expect(items.get(2).getText()).toEqual('Provider');
expect(items.get(3).getText()).toEqual('OpenShift Version');
expect(items.get(4).getText()).toEqual('Update Channel');
for (let i = 0; i < 5; i++) {
const text = values.get(i).getText();
expect(text.length).not.toBe(0);
expect(text).not.toBe('Not available');
}
});
it('has View settings link', () => {
const link = clusterDashboardView.detailsCard.$('[href="/settings/cluster/"]');
expect(link.isDisplayed()).toBe(true);
expect(link.getText()).toEqual('View settings');
});
});

describe('Status Card', () => {
it('has View alerts link', () => {
expect(clusterDashboardView.statusCard.isDisplayed()).toBe(true);
const link = clusterDashboardView.statusCard.$('[href="/monitoring/alerts"]');
expect(link.isDisplayed()).toBe(true);
expect(link.getText()).toEqual('View alerts');
});
it('has health indicators', () => {
const items = clusterDashboardView.statusCard.$$('.co-status-card__health-item');
expect(items.get(0).getText()).toEqual('Cluster');
expect(items.get(1).getText()).toMatch('Control Plane.*');
expect(items.get(2).getText()).toMatch('Operators.*');
});
});

describe('Inventory Card', () => {
it('has all items', async () => {
expect(clusterDashboardView.inventoryCard.isDisplayed()).toBe(true);
inventoryItems.forEach((item) => {
const link = clusterDashboardView.inventoryCard.$(`[href="${item.link}"]`);
expect(link.isDisplayed()).toBe(true);
expect(link.getText()).toMatch(`^[0-9]* ${item.title}?.*`);
});
});
});

describe('Utilization Card', () => {
it('has all items', () => {
expect(clusterDashboardView.utilizationCard.isDisplayed()).toBe(true);
const items = clusterDashboardView.utilizationCard.$$(
'.co-utilization-card__item-description',
);
expect(items.count()).toBe(5);
utiliztionItems.forEach((item, index) =>
expect(
items
.get(index)
.$('h4')
.getText(),
).toEqual(item),
);
});
it('has duration dropdown', () => {
expect(clusterDashboardView.durationDropdown.isDisplayed()).toBe(true);
expect(clusterDashboardView.durationDropdown.getText()).toEqual('1 Hour');
});
});

describe('Activity Card', () => {
it('has View events link', () => {
expect(clusterDashboardView.activityCard.isDisplayed()).toBe(true);
const link = clusterDashboardView.activityCard.$('[href="/k8s/all-namespaces/events"]');
expect(link.isDisplayed()).toBe(true);
expect(link.getText()).toEqual('View events');
});
it('has Pause events button', async () => {
const button = clusterDashboardView.eventsPauseButton;
expect(button.isDisplayed()).toBe(true);
expect(button.getText()).toEqual('Pause');
await button.click();
expect(button.getText()).toEqual('Unpause');
});
});
});
@@ -0,0 +1,221 @@
import { browser, ExpectedConditions as until } from 'protractor';
import * as dashboardView from '@console/shared/src/test-views/dashboard-shared.view';
import {
createResource,
addLeakableResource,
removeLeakedResources,
} from '@console/shared/src/test-utils/utils';
import { testName } from '../../protractor.conf';
import * as sideNavView from '../../views/sidenav.view';
import * as crudView from '../../views/crud.view';
import { horizontalTabFor, clickHorizontalTab } from '../../views/horizontal-nav.view';
import * as projectDashboardView from '../../views/dashboard.view';

const inventoryItems = [
{ title: 'Deployment', link: `/k8s/ns/${testName}/deployments` },
{ title: 'Pod', link: `/k8s/ns/${testName}/pods` },
{ title: 'PVC', link: `/k8s/ns/${testName}/persistentvolumeclaims` },
{ title: 'Service', link: `/k8s/ns/${testName}/services` },
{ title: 'Route', link: `/k8s/ns/${testName}/routes` },
{ title: 'Config Map', link: `/k8s/ns/${testName}/configmaps` },
{ title: 'Secret', link: `/k8s/ns/${testName}/secrets` },
];

const utiliztionItems = ['CPU', 'Memory', 'Filesystem', 'Network Transfer', 'Pod count'];

const launcherLink = {
apiVersion: 'console.openshift.io/v1',
kind: 'ConsoleLink',
metadata: {
name: `link-${testName}`,
},
spec: {
href: 'https://www.example.com/',
location: 'NamespaceDashboard',
namespaceDashboard: {
namespaces: [testName],
},
text: 'Help Menu Link',
},
};

const resourceQuota = {
apiVersion: 'v1',
kind: 'ResourceQuota',
metadata: {
name: 'example',
namespace: testName,
},
spec: {
hard: {
pods: '4',
'requests.cpu': '1',
'requests.memory': '1Gi',
'limits.cpu': '2',
'limits.memory': '2Gi',
},
},
};

describe('Project Dashboard', () => {
beforeAll(async () => {
await sideNavView.clickNavLink(['Home', 'Projects']);
await crudView.isLoaded();
await crudView.resourceRowsPresent();
// Filter by resource name to make sure the resource is on the first page of results.
// Otherwise the tests fail since we do virtual scrolling and the element isn't found.
await crudView.filterForName(testName);
expect(crudView.rowForName(testName).isPresent()).toBe(true);
await crudView
.rowForName(testName)
.$('a')
.click();
await dashboardView.isLoaded();
});

afterEach(async () => {
await clickHorizontalTab('Overview');
await dashboardView.isLoaded();
});

it('Dashboard is default details page', async () => {
const tab = await horizontalTabFor('Overview');
expect(tab.getAttribute('class')).toContain('co-m-horizontal-nav-item--active');
});

describe('Details Card', () => {
it('has all fields populated', async () => {
expect(projectDashboardView.detailsCard.isDisplayed()).toBe(true);
const items = projectDashboardView.detailsCardList.$$('dt');
const values = projectDashboardView.detailsCardList.$$('dd');

expect(items.count()).toBe(3);
expect(values.count()).toBe(3);
expect(items.get(0).getText()).toEqual('Name');
expect(values.get(0).getText()).toEqual(testName);
expect(items.get(1).getText()).toEqual('Requester');
expect(values.get(1).getText()).toEqual('kube:admin');
expect(items.get(2).getText()).toEqual('Labels');
expect(values.get(2).getText()).toEqual('No labels');
});
it('has View all link', async () => {
const link = projectDashboardView.detailsCard.$(
`[href="/k8s/cluster/projects/${testName}/details"]`,
);
expect(link.isDisplayed()).toBe(true);
expect(link.getText()).toEqual('View all');
await link.click();
const tab = await horizontalTabFor('Details');
expect(tab.getAttribute('class')).toContain('co-m-horizontal-nav-item--active');
});
});

describe('Status Card', () => {
it('has health indicator', async () => {
expect(projectDashboardView.statusCard.isDisplayed()).toBe(true);
const health = await projectDashboardView.statusCard.$('.co-icon-and-text');
expect(health.isDisplayed()).toBe(true);
expect(health.getText()).toEqual('Active');
});
});

describe('Inventory Card', () => {
it('has all items', async () => {
expect(projectDashboardView.inventoryCard.isDisplayed()).toBe(true);
inventoryItems.forEach((item) => {
const link = projectDashboardView.inventoryCard.$(`[href="${item.link}"]`);
expect(link.isDisplayed()).toBe(true);
expect(link.getText()).toMatch(`^[0-9]* ${item.title}?.*`);
});
});
});

describe('Utilization Card', () => {
it('has all items', () => {
expect(projectDashboardView.utilizationCard.isDisplayed()).toBe(true);
const items = projectDashboardView.utilizationCard.$$(
'.co-utilization-card__item-description',
);
expect(items.count()).toBe(5);
utiliztionItems.forEach((item, index) =>
expect(
items
.get(index)
.$('h4')
.getText(),
).toEqual(item),
);
});
it('has duration dropdown', () => {
expect(projectDashboardView.durationDropdown.isDisplayed()).toBe(true);
expect(projectDashboardView.durationDropdown.getText()).toEqual('1 Hour');
});
});

describe('Activity Card', () => {
it('has View events link', () => {
expect(projectDashboardView.activityCard.isDisplayed()).toBe(true);
const link = projectDashboardView.activityCard.$(`[href="/k8s/ns/${testName}/events"]`);
expect(link.isDisplayed()).toBe(true);
expect(link.getText()).toEqual('View events');
});
it('has Pause events button', async () => {
const button = projectDashboardView.eventsPauseButton;
expect(button.isDisplayed()).toBe(true);
expect(await button.getText()).toEqual('Pause');
await button.click();
expect(button.getText()).toEqual('Unpause');
});
});

describe('Launcher Card', () => {
const leakedResources = new Set<string>();

afterAll(() => {
removeLeakedResources(leakedResources);
});

it('is displayed when CR exists', async () => {
expect(projectDashboardView.launcherCard.isPresent()).toBe(false);
createResource(launcherLink);
addLeakableResource(leakedResources, launcherLink);
// refresh browser to reload launcher links
await browser.refresh();
await dashboardView.isLoaded();
expect(projectDashboardView.launcherCard.isDisplayed()).toBe(true);
const link = await projectDashboardView.launcherCard.$('a');
expect(link.getText()).toEqual(launcherLink.spec.text);
expect(link.getAttribute('href')).toEqual(launcherLink.spec.href);
});
});

describe('Resource Quotas Card', () => {
const leakedResources = new Set<string>();

afterAll(() => {
removeLeakedResources(leakedResources);
});

it('shows Resource Quotas', async () => {
expect(projectDashboardView.resourceQuotasCard.isDisplayed()).toBe(true);
expect(
await projectDashboardView.resourceQuotasCard.$('.co-dashboard-card__body').getText(),
).toEqual('No resource quotas');
createResource(resourceQuota);
addLeakableResource(leakedResources, resourceQuota);

await browser.wait(
until.presenceOf(projectDashboardView.resourceQuotasCard.$('.co-resource-item')),
);
expect(
projectDashboardView.resourceQuotasCard
.$('.co-resource-item')
.$('a')
.getText(),
).toEqual(resourceQuota.metadata.name);
expect(
projectDashboardView.resourceQuotasCard.$('.co-resource-quota-chart-row').isDisplayed(),
).toBe(true);
});
});
});
12 changes: 12 additions & 0 deletions frontend/integration-tests/views/dashboard.view.ts
@@ -0,0 +1,12 @@
import { $ } from 'protractor';

export const detailsCard = $('[data-test-id="details-card"]');
export const detailsCardList = detailsCard.$('dl');
export const statusCard = $('[data-test-id="status-card"]');
export const inventoryCard = $('[data-test-id="inventory-card"]');
export const utilizationCard = $('[data-test-id="utilization-card"]');
export const durationDropdown = utilizationCard.$('[data-test-id="dropdown-button"]');
export const activityCard = $('[data-test-id="activity-card"]');
export const eventsPauseButton = $('[data-test-id="events-pause-button"]');
export const launcherCard = $('[data-test-id="launcher-card"]');
export const resourceQuotasCard = $('[data-test-id="resource-quotas-card"]');

0 comments on commit d8cf59f

Please sign in to comment.