Skip to content
This repository has been archived by the owner on Mar 1, 2024. It is now read-only.

Commit

Permalink
Added tests for vm list/vies actions (start, stop, ...)
Browse files Browse the repository at this point in the history
  • Loading branch information
Radim Hrazdil committed Jan 9, 2019
1 parent 19f5e85 commit 97fc678
Show file tree
Hide file tree
Showing 3 changed files with 196 additions and 1 deletion.
2 changes: 1 addition & 1 deletion frontend/integration-tests/protractor.conf.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ export const config: Config = {
catalog: ['tests/base.scenario.ts', 'tests/catalog.scenario.ts'],
marketplace: ['tests/base.scenario.ts', 'tests/marketplace/kubernetes-marketplace.scenario.ts'],
overview: ['tests/base.scenario.ts', 'tests/overview/overview.scenario.ts'],
kubevirt: ['tests/base.scenario.ts', 'tests/kubevirt/vm.wizard.scenario.ts'],
kubevirt: ['tests/base.scenario.ts', 'tests/kubevirt/vm.wizard.scenario.ts', 'tests/kubevirt/vm.actions.scenario.ts'],
all: ['tests/base.scenario.ts',
'tests/crud.scenario.ts',
'tests/overview/overview.scenareio.ts',
Expand Down
162 changes: 162 additions & 0 deletions frontend/integration-tests/tests/kubevirt/vm.actions.scenario.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
/* eslint-disable no-undef */

import { execSync } from 'child_process';
import { browser, ExpectedConditions as until } from 'protractor';
import { appHost, testName } from '../../protractor.conf';
import { resourceRowsPresent, filterForName, isLoaded } from '../../views/crud.view';
import * as vmActionsView from '../../views/kubevirt/vm.actions.view';

describe('Test VM actions', () => {
const leakedResources = new Set<string>();
const testVM = {
apiVersion: 'kubevirt.io/v1alpha2',
kind: 'VirtualMachine',
metadata: {
name: testName,
namespace: testName,
},
spec: {
running: false,
template: {
spec: {
domain: {
cpu: {
cores: 1,
},
devices: {
disks: [
{
bootOrder: 1,
disk: {
bus: 'virtio',
},
name: 'rootdisk',
volumeName: 'rootdisk',
},
],
interfaces: [
{
bridge: {},
name: 'eth0',
},
],
},
resources: {
requests: {
memory: '2G',
},
},
},
networks: [
{
name: 'eth0',
pod: {},
},
],
volumes: [
{
containerDisk: {
image: 'kubevirt/cirros-registry-disk-demo:latest',
},
name: 'rootdisk',
},
],
},
},
},
};

afterAll(async() => {
const leakedArray: Array<string> = [...leakedResources];
if (leakedArray.length > 0) {
console.error(`Leaked ${leakedArray.join()}`);
leakedArray.map(r => JSON.parse(r) as {name: string, namespace: string, kind: string})
.forEach(({name, namespace, kind}) => {
try {
execSync(`kubectl delete -n ${namespace} --cascade ${kind} ${name}`);
} catch (error) {
console.error(`Failed to delete ${kind} ${name}:\n${error}`);
}
});
}
});

describe('Test VM list view kebab actions', () => {
const vmName = `vm-list-view-actions-${testName}`;
beforeAll(async() => {
testVM.metadata.name = vmName;
execSync(`echo '${JSON.stringify(testVM)}' | kubectl create -f -`);
leakedResources.add(JSON.stringify({name: vmName, namespace: testName, kind: 'vm'}));
});

it('Navigates to VMs', async() => {
await browser.get(`${appHost}/k8s/all-namespaces/virtualmachines`);
await isLoaded();
await filterForName(vmName);
await resourceRowsPresent();
});

it('Starts VM', async() => {
await vmActionsView.listViewAction(vmName)('Start');
await browser.wait(until.textToBePresentInElement(vmActionsView.listViewVMmStatus(vmName), 'Running'), 20000);
});

it('Restarts VM', async() => {
await isLoaded();
await vmActionsView.listViewAction(vmName)('Restart');
await browser.wait(until.textToBePresentInElement(vmActionsView.listViewVMmStatus(vmName), 'Running'), 20000);
});

it('Stops VM', async() => {
await isLoaded();
await vmActionsView.listViewAction(vmName)('Stop');
await browser.wait(until.textToBePresentInElement(vmActionsView.listViewVMmStatus(vmName), 'Off'), 10000);
});

it('Deletes VM', async() => {
await isLoaded();
await vmActionsView.listViewAction(vmName)('Delete');

await browser.wait(until.not(until.presenceOf(vmActionsView.listViewVMmStatus(vmName))));
leakedResources.delete(JSON.stringify({name: vmName, namespace: testName, kind: 'vm'}));
});
});

describe('Test VM detail view kebab actions', () => {
const vmName = `vm-detail-view-actions-${testName}`;

beforeAll(async() => {
testVM.metadata.name = vmName;
execSync(`echo '${JSON.stringify(testVM)}' | kubectl create -f -`);
leakedResources.add(JSON.stringify({name: vmName, namespace: testName, kind: 'vm'}));
});

it('Navigates to VMs detail page', async() => {
await browser.get(`${appHost}/k8s/all-namespaces/virtualmachines/${vmName}`);
});

it('Starts VM', async() => {
await isLoaded();
await vmActionsView.detailViewAction('Start');
await browser.wait(until.textToBePresentInElement(vmActionsView.detailViewVMmStatus, 'Running'), 20000);
});

it('Restarts VM', async() => {
isLoaded();
await vmActionsView.detailViewAction('Restart');
await browser.wait(until.textToBePresentInElement(vmActionsView.detailViewVMmStatus, 'Running'), 20000);
});

it('Stops VM', async() => {
isLoaded();
await vmActionsView.detailViewAction('Stop');
await browser.wait(until.textToBePresentInElement(vmActionsView.detailViewVMmStatus, 'Off'), 10000);
});

it('Deletes VM', async() => {
isLoaded();
await vmActionsView.detailViewAction('Delete');
leakedResources.delete(JSON.stringify({name: vmName, namespace: testName, kind: 'vm'}));
});
});
});
33 changes: 33 additions & 0 deletions frontend/integration-tests/views/kubevirt/vm.actions.view.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { $, browser, ExpectedConditions as until } from 'protractor';
import { rowForName, actionsDropdown, actionsDropdownMenu } from '../crud.view';


/**
* Performs action for VM via list view kebab menu..
*/
export const listViewAction = (name: string) => (action: string) => rowForName(name).$$('.co-kebab__button').first().click()
//.then(() => browser.wait(until.elementToBeClickable(rowForName(name).$('.co-kebab__dropdown'))))
.then(() => browser.wait(until.elementToBeClickable(rowForName(name).$('.co-kebab__dropdown').$$('a').filter(link => link.getText().then(text => text.startsWith(action))).first())))
.then(() => rowForName(name).$('.co-kebab__dropdown').$$('a').filter(link => link.getText().then(text => text.startsWith(action))).first().click())
.then(async() => {
await browser.wait(until.presenceOf($('#confirm-action')));
await $('#confirm-action').click();

await browser.wait(until.not(until.presenceOf(rowForName(name).$('.co-kebab__dropdown'))));
});

/**
* Performs action for VM on its detail page..
*/
export const detailViewAction = (action: string) => actionsDropdown.click()
.then(() => browser.wait(until.elementToBeClickable(actionsDropdownMenu.$$('a').filter(link => link.getText().then(text => text.startsWith(action))).first())))
.then(() => actionsDropdownMenu.$$('a').filter(link => link.getText().then(text => text.startsWith(action))).first().click())
.then(async() => {
await browser.wait(until.presenceOf($('#confirm-action')));
await $('#confirm-action').click();

await browser.wait(until.not(until.presenceOf(actionsDropdownMenu)));
});

export const listViewVMmStatus = (name: string) => rowForName(name).$('div.co-m-row:first-child > div:first-child > div:nth-child(3)');
export const detailViewVMmStatus = $('#details-column-1 > dl:nth-child(1) > dd:nth-child(2)');

0 comments on commit 97fc678

Please sign in to comment.