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

Commit 208ce97

Browse files
author
Radim Hrazdil
committed
Added tests for vm list/vies actions (start, stop, ...)
1 parent 19f5e85 commit 208ce97

File tree

3 files changed

+196
-2
lines changed

3 files changed

+196
-2
lines changed

frontend/integration-tests/protractor.conf.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ export const config: Config = {
3232
chromeOptions: {
3333
args: [
3434
'--disable-gpu',
35-
'--headless',
3635
'--no-sandbox',
3736
'--window-size=1920,1200',
3837
'--disable-background-timer-throttling',
@@ -101,7 +100,7 @@ export const config: Config = {
101100
catalog: ['tests/base.scenario.ts', 'tests/catalog.scenario.ts'],
102101
marketplace: ['tests/base.scenario.ts', 'tests/marketplace/kubernetes-marketplace.scenario.ts'],
103102
overview: ['tests/base.scenario.ts', 'tests/overview/overview.scenario.ts'],
104-
kubevirt: ['tests/base.scenario.ts', 'tests/kubevirt/vm.wizard.scenario.ts'],
103+
kubevirt: ['tests/base.scenario.ts', 'tests/kubevirt/vm.wizard.scenario.ts', 'tests/kubevirt/vm.actions.scenario.ts'],
105104
all: ['tests/base.scenario.ts',
106105
'tests/crud.scenario.ts',
107106
'tests/overview/overview.scenareio.ts',
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
/* eslint-disable no-undef */
2+
3+
import { execSync } from 'child_process';
4+
import { browser, ExpectedConditions as until } from 'protractor';
5+
import { appHost, testName } from '../../protractor.conf';
6+
import { resourceRowsPresent, filterForName, isLoaded } from '../../views/crud.view';
7+
import * as vmActionsView from '../../views/kubevirt/vm.actions.view';
8+
9+
describe('Test VM actions', () => {
10+
const leakedResources = new Set<string>();
11+
const testVM = {
12+
apiVersion: 'kubevirt.io/v1alpha2',
13+
kind: 'VirtualMachine',
14+
metadata: {
15+
name: testName,
16+
namespace: testName,
17+
},
18+
spec: {
19+
running: false,
20+
template: {
21+
spec: {
22+
domain: {
23+
cpu: {
24+
cores: 1,
25+
},
26+
devices: {
27+
disks: [
28+
{
29+
bootOrder: 1,
30+
disk: {
31+
bus: 'virtio',
32+
},
33+
name: 'rootdisk',
34+
volumeName: 'rootdisk',
35+
},
36+
],
37+
interfaces: [
38+
{
39+
bridge: {},
40+
name: 'eth0',
41+
},
42+
],
43+
},
44+
resources: {
45+
requests: {
46+
memory: '2G',
47+
},
48+
},
49+
},
50+
networks: [
51+
{
52+
name: 'eth0',
53+
pod: {},
54+
},
55+
],
56+
volumes: [
57+
{
58+
containerDisk: {
59+
image: 'kubevirt/cirros-registry-disk-demo:latest',
60+
},
61+
name: 'rootdisk',
62+
},
63+
],
64+
},
65+
},
66+
},
67+
};
68+
69+
afterAll(async() => {
70+
const leakedArray: Array<string> = [...leakedResources];
71+
if (leakedArray.length > 0) {
72+
console.error(`Leaked ${leakedArray.join()}`);
73+
leakedArray.map(r => JSON.parse(r) as {name: string, namespace: string, kind: string})
74+
.forEach(({name, namespace, kind}) => {
75+
try {
76+
execSync(`kubectl delete -n ${namespace} --cascade ${kind} ${name}`);
77+
} catch (error) {
78+
console.error(`Failed to delete ${kind} ${name}:\n${error}`);
79+
}
80+
});
81+
}
82+
});
83+
84+
describe('Test VM list view kebab actions', () => {
85+
const vmName = `vm-list-view-actions-${testName}`;
86+
beforeAll(async() => {
87+
testVM.metadata.name = vmName;
88+
execSync(`echo '${JSON.stringify(testVM)}' | kubectl create -f -`);
89+
leakedResources.add(JSON.stringify({name: vmName, namespace: testName, kind: 'vm'}));
90+
});
91+
92+
it('Navigates to VMs', async() => {
93+
await browser.get(`${appHost}/k8s/all-namespaces/virtualmachines`);
94+
await isLoaded();
95+
await filterForName(vmName);
96+
await resourceRowsPresent();
97+
});
98+
99+
it('Starts VM', async() => {
100+
await vmActionsView.listViewAction(vmName)('Start');
101+
await browser.wait(until.textToBePresentInElement(vmActionsView.listViewVMmStatus(vmName), 'Running'), 20000);
102+
});
103+
104+
it('Restarts VM', async() => {
105+
await isLoaded();
106+
await vmActionsView.listViewAction(vmName)('Restart');
107+
await browser.wait(until.textToBePresentInElement(vmActionsView.listViewVMmStatus(vmName), 'Running'), 20000);
108+
});
109+
110+
it('Stops VM', async() => {
111+
await isLoaded();
112+
await vmActionsView.listViewAction(vmName)('Stop');
113+
await browser.wait(until.textToBePresentInElement(vmActionsView.listViewVMmStatus(vmName), 'Off'), 10000);
114+
});
115+
116+
it('Deletes VM', async() => {
117+
await isLoaded();
118+
await vmActionsView.listViewAction(vmName)('Delete');
119+
120+
await browser.wait(until.not(until.presenceOf(vmActionsView.listViewVMmStatus(vmName))));
121+
leakedResources.delete(JSON.stringify({name: vmName, namespace: testName, kind: 'vm'}));
122+
});
123+
});
124+
125+
describe('Test VM detail view kebab actions', () => {
126+
const vmName = `vm-detail-view-actions-${testName}`;
127+
128+
beforeAll(async() => {
129+
testVM.metadata.name = vmName;
130+
execSync(`echo '${JSON.stringify(testVM)}' | kubectl create -f -`);
131+
leakedResources.add(JSON.stringify({name: vmName, namespace: testName, kind: 'vm'}));
132+
});
133+
134+
it('Navigates to VMs detail page', async() => {
135+
await browser.get(`${appHost}/k8s/all-namespaces/virtualmachines/${vmName}`);
136+
});
137+
138+
it('Starts VM', async() => {
139+
await isLoaded();
140+
await vmActionsView.detailViewAction('Start');
141+
await browser.wait(until.textToBePresentInElement(vmActionsView.detailViewVMmStatus, 'Running'), 20000);
142+
});
143+
144+
it('Restarts VM', async() => {
145+
isLoaded();
146+
await vmActionsView.detailViewAction('Restart');
147+
await browser.wait(until.textToBePresentInElement(vmActionsView.detailViewVMmStatus, 'Running'), 20000);
148+
});
149+
150+
it('Stops VM', async() => {
151+
isLoaded();
152+
await vmActionsView.detailViewAction('Stop');
153+
await browser.wait(until.textToBePresentInElement(vmActionsView.detailViewVMmStatus, 'Off'), 10000);
154+
});
155+
156+
it('Deletes VM', async() => {
157+
isLoaded();
158+
await vmActionsView.detailViewAction('Delete');
159+
leakedResources.delete(JSON.stringify({name: vmName, namespace: testName, kind: 'vm'}));
160+
});
161+
});
162+
});
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { $, browser, ExpectedConditions as until } from 'protractor';
2+
import { rowForName, actionsDropdown, actionsDropdownMenu } from '../crud.view';
3+
4+
5+
/**
6+
* Performs action for VM via list view kebab menu..
7+
*/
8+
export const listViewAction = (name: string) => (action: string) => rowForName(name).$$('.co-kebab__button').first().click()
9+
//.then(() => browser.wait(until.elementToBeClickable(rowForName(name).$('.co-kebab__dropdown'))))
10+
.then(() => browser.wait(until.elementToBeClickable(rowForName(name).$('.co-kebab__dropdown').$$('a').filter(link => link.getText().then(text => text.startsWith(action))).first())))
11+
.then(() => rowForName(name).$('.co-kebab__dropdown').$$('a').filter(link => link.getText().then(text => text.startsWith(action))).first().click())
12+
.then(async() => {
13+
await browser.wait(until.presenceOf($('#confirm-action')));
14+
await $('#confirm-action').click();
15+
16+
await browser.wait(until.not(until.presenceOf(rowForName(name).$('.co-kebab__dropdown'))));
17+
});
18+
19+
/**
20+
* Performs action for VM on its detail page..
21+
*/
22+
export const detailViewAction = (action: string) => actionsDropdown.click()
23+
.then(() => browser.wait(until.elementToBeClickable(actionsDropdownMenu.$$('a').filter(link => link.getText().then(text => text.startsWith(action))).first())))
24+
.then(() => actionsDropdownMenu.$$('a').filter(link => link.getText().then(text => text.startsWith(action))).first().click())
25+
.then(async() => {
26+
await browser.wait(until.presenceOf($('#confirm-action')));
27+
await $('#confirm-action').click();
28+
29+
await browser.wait(until.not(until.presenceOf(actionsDropdownMenu)));
30+
});
31+
32+
export const listViewVMmStatus = (name: string) => rowForName(name).$('div.co-m-row:first-child > div:first-child > div:nth-child(3)');
33+
export const detailViewVMmStatus = $('#details-column-1 > dl:nth-child(1) > dd:nth-child(2)');

0 commit comments

Comments
 (0)