Skip to content

Commit 26a0307

Browse files
authored
UI tests for working with devfile registries in openshift view, fixes #2485 (#2729)
Signed-off-by: Ondrej Dockal <[email protected]>
1 parent c0fd875 commit 26a0307

File tree

5 files changed

+287
-6
lines changed

5 files changed

+287
-6
lines changed
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*-----------------------------------------------------------------------------------------------
2+
* Copyright (c) Red Hat, Inc. All rights reserved.
3+
* Licensed under the MIT License. See LICENSE file in the project root for license information.
4+
*-----------------------------------------------------------------------------------------------*/
5+
import { Editor, EditorView, WebView } from 'vscode-extension-tester';
6+
7+
/**
8+
* Web View form representation implementation
9+
* @author Ondrej Dockal <[email protected]>
10+
*/
11+
export abstract class WebViewForm {
12+
13+
private _editorName: string;
14+
private _editorView: EditorView;
15+
private _editor: Editor;
16+
17+
constructor(name: string) {
18+
this._editorName = name;
19+
this._editorView = new EditorView();
20+
}
21+
22+
public get editorView(): EditorView {
23+
return this._editorView;
24+
}
25+
26+
public get editor(): Editor {
27+
if (this._editor) {
28+
return this._editor;
29+
}
30+
throw TypeError('Editor was not initialized yet');
31+
}
32+
33+
public get editorName(): string {
34+
return this._editorName;
35+
}
36+
37+
public async initializeEditor(): Promise<void> {
38+
this._editor = await this._editorView.openEditor(this.editorName);
39+
}
40+
41+
public async enterWebView<T>(callbackFunction: (webView: WebView) => Promise<T>): Promise<T> {
42+
if (!this.editor) {
43+
await this.initializeEditor();
44+
}
45+
46+
const webView = new WebView();
47+
await webView.switchToFrame();
48+
let retValue: T;
49+
try {
50+
retValue = await callbackFunction(webView);
51+
} finally {
52+
await webView.switchBack();
53+
}
54+
return retValue;
55+
}
56+
}
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
/*-----------------------------------------------------------------------------------------------
2+
* Copyright (c) Red Hat, Inc. All rights reserved.
3+
* Licensed under the MIT License. See LICENSE file in the project root for license information.
4+
*-----------------------------------------------------------------------------------------------*/
5+
import { By, ModalDialog, WebElement, WebView } from 'vscode-extension-tester';
6+
import { WebViewForm } from './WebViewForm';
7+
8+
/**
9+
10+
* Class represents Registry Stack item in web View form
11+
*/
12+
export class RegistryStackItem {
13+
private _element: WebElement;
14+
15+
public constructor(element: WebElement) {
16+
this._element = element;
17+
}
18+
19+
public get element(): WebElement {
20+
return this._element;
21+
}
22+
23+
public async getStackName() {
24+
return await this._element.getText();
25+
}
26+
27+
public async selectStack() {
28+
await this._element.click();
29+
}
30+
}
31+
32+
export class RegistryWebViewProject {
33+
private _stackName: string;
34+
35+
public get stackName(): string {
36+
return this._stackName;
37+
}
38+
39+
public set stackName(value: string) {
40+
this._stackName = value;
41+
}
42+
43+
public constructor(stackName: string) {
44+
this._stackName = stackName;
45+
}
46+
47+
public async getParent(): Promise<string> {
48+
const modal = new ModalDialog();
49+
return await modal.getMessage();
50+
}
51+
}
52+
53+
export class RegistryWebViewEditor extends WebViewForm {
54+
55+
public constructor(name: string) {
56+
super(name);
57+
}
58+
59+
private async getRegistryStacks(webView: WebView): Promise<WebElement[]> {
60+
return await webView.findWebElements(By.xpath('//div[@class="box"][@id="root"]//li//div//h6'));
61+
}
62+
63+
private async getRegistryStacksItems(webView: WebView): Promise<RegistryStackItem[]> {
64+
const stacks = await this.getRegistryStacks(webView);
65+
const array = [] as RegistryStackItem[];
66+
for(const item of stacks) {
67+
const stack = new RegistryStackItem(item);
68+
array.push(stack);
69+
}
70+
return array;
71+
}
72+
73+
public async getRegistryStackNames(): Promise<string[]> {
74+
const items = await this.enterWebView(async (webView) => {
75+
const array = [] as string [];
76+
const stacks = await this.getRegistryStacksItems(webView);
77+
for(const stack of stacks) {
78+
array.push(await stack.getStackName());
79+
}
80+
return array;
81+
});
82+
return items;
83+
}
84+
85+
public async selectRegistryStack(stackName: string): Promise<void> {
86+
await this.enterWebView(async (webView) => {
87+
const stacks = await this.getRegistryStacksItems(webView);
88+
for(const stack of stacks) {
89+
if((await stack.getStackName()).includes(stackName)) {
90+
await stack.selectStack();
91+
}
92+
}
93+
});
94+
}
95+
}

test/ui/public-ui-test.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@
33
* Licensed under the MIT License. See LICENSE file in the project root for license information.
44
*-----------------------------------------------------------------------------------------------*/
55

6+
import { testDevfileRegistries } from './suite/devfileRegistries';
67
import { checkExtension } from './suite/extension';
78
import { checkOpenshiftView } from './suite/openshift';
8-
// import { createComponentTest } from './suite/component';
99

1010
describe('Extension public-facing UI tests', () => {
1111
checkExtension();
1212
checkOpenshiftView();
13+
testDevfileRegistries();
1314
});

test/ui/suite/devfileRegistries.ts

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
/*-----------------------------------------------------------------------------------------------
2+
* Copyright (c) Red Hat, Inc. All rights reserved.
3+
* Licensed under the MIT License. See LICENSE file in the project root for license information.
4+
*-----------------------------------------------------------------------------------------------*/
5+
import { expect } from 'chai';
6+
import { ActivityBar, CustomTreeSection, EditorView, InputBox, SideBarView, VSBrowser, ViewSection, WebDriver, Workbench } from 'vscode-extension-tester';
7+
import { VIEWS } from '../common/constants';
8+
import { RegistryWebViewEditor } from '../common/ui/webview/registryWebViewEditor';
9+
import { notificationExists } from '../common/conditions';
10+
11+
export function testDevfileRegistries() {
12+
describe('Devfile Registries', () => {
13+
let view: SideBarView;
14+
let registrySection: ViewSection;
15+
let driver: WebDriver;
16+
17+
before(async function context() {
18+
this.timeout(10000);
19+
driver = VSBrowser.instance.driver;
20+
view = await (await new ActivityBar().getViewControl(VIEWS.openshift)).openView();
21+
await new Promise(res => setTimeout(res, 5000));
22+
await (await new Workbench().openNotificationsCenter()).clearAllNotifications();
23+
registrySection = await view.getContent().getSection(VIEWS.compRegistries);
24+
});
25+
26+
it('registry actions are available', async function test() {
27+
this.timeout(5000);
28+
expect(await Promise.all((await registrySection.getActions()).map(async item => await item.getLabel()))).to.has.members(['Add Registry', 'Open Registry View', 'Refresh Components Types View']);
29+
});
30+
31+
it('default Devfile registry is present', async function test() {
32+
this.timeout(5000);
33+
await registrySection.expand();
34+
const registry = await registrySection.findItem(VIEWS.devFileRegistry);
35+
expect(registry).not.undefined;
36+
expect(await registry.getText()).to.equal('DefaultDevfileRegistry');
37+
});
38+
39+
it('add new Devfile registry', async function test() {
40+
this.timeout(10000);
41+
const addAction = await registrySection.getAction('Add Registry');
42+
await addAction.click();
43+
const input = await InputBox.create();
44+
// insert registry name into input box
45+
await input.setText('stageRegistry');
46+
await input.confirm();
47+
// insert staging devfile registry url
48+
await input.setText('https://stage.registry.devfile.io');
49+
await input.confirm();
50+
// pick unsecured registry
51+
await input.selectQuickPick('No');
52+
await new Promise((res) => { setTimeout(res, 2000); });
53+
// check registry exists
54+
await registrySection.expand();
55+
const stageRegistry = await (registrySection as CustomTreeSection).findItem('stageRegistry');
56+
expect(stageRegistry).not.undefined;
57+
});
58+
59+
it('edit existing Devfile registry', async function test() {
60+
this.timeout(10000);
61+
await registrySection.expand();
62+
const stageRegistry = await (registrySection as CustomTreeSection).findItem('stageRegistry');
63+
const menu = await stageRegistry.openContextMenu();
64+
await (await menu.getItem('Edit')).select();
65+
const input = await InputBox.create();
66+
// insert registry name into input box
67+
await input.setText('editedRegistry');
68+
await input.confirm();
69+
// insert staging devfile registry url
70+
await input.setText('https://stage.registry.devfile.io');
71+
await input.confirm();
72+
// pick unsecured registry
73+
await input.selectQuickPick('No');
74+
await new Promise((res) => { setTimeout(res, 2000); });
75+
// check registry exists
76+
await registrySection.expand();
77+
const editedRegistry = await (registrySection as CustomTreeSection).findItem('editedRegistry');
78+
expect(editedRegistry).not.undefined;
79+
});
80+
81+
it('remove Devfile registry', async function test() {
82+
this.timeout(10000);
83+
await registrySection.expand();
84+
let stageRegistry = await registrySection.findItem('editedRegistry');
85+
const menu = await stageRegistry.openContextMenu();
86+
await (await menu.getItem('Remove')).select();
87+
// find and confirm notification about registry deletion
88+
const notification = await notificationExists('Remove registry \'editedRegistry\'?', driver);
89+
await notification.takeAction('Yes');
90+
await new Promise((res) => { setTimeout(res, 2000); });
91+
stageRegistry = await registrySection.findItem('editedRegistry');
92+
expect(stageRegistry).is.undefined;
93+
});
94+
95+
it('open Devfile registry view from Section action', async function test() {
96+
this.timeout(10000);
97+
await (await registrySection.getAction('Open Registry View')).click();
98+
// open editor tab by title
99+
const editorView = new EditorView();
100+
const editor = await editorView.openEditor('Devfile Registry');
101+
expect(await editor.getTitle()).to.include('Devfile Registry');
102+
});
103+
104+
it('open Devfile registry view from item\'s context menu and verify the content of the registry', async function test() {
105+
this.timeout(10000);
106+
await new EditorView().closeAllEditors();
107+
const devfileRegistry = await registrySection.findItem('DefaultDevfileRegistry');
108+
await devfileRegistry.select();
109+
const menu = await devfileRegistry.openContextMenu();
110+
await (await menu.getItem('Open in Editor')).select();
111+
await new Promise((res) => { setTimeout(res, 3000); });
112+
// check opened editor tab by title
113+
const editorView = new EditorView();
114+
const editor = await editorView.openEditor('Devfile Registry - DefaultDevfileRegistry');
115+
expect(await editor.getTitle()).to.include('Devfile Registry - DefaultDevfileRegistry');
116+
// initialize web view editor
117+
const webView = new RegistryWebViewEditor('Devfile Registry - DefaultDevfileRegistry');
118+
await webView.initializeEditor();
119+
expect(await webView.getRegistryStackNames()).to.include.members(['Quarkus Java', 'Node.js Runtime', 'Python', 'Maven Java', 'Vert.x Java', 'Go Runtime', 'React']);
120+
});
121+
122+
after(async function context() {
123+
this.timeout(10000);
124+
await (await new Workbench().openNotificationsCenter()).clearAllNotifications();
125+
await new EditorView().closeAllEditors();
126+
});
127+
128+
});
129+
}

test/ui/suite/openshift.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -86,18 +86,18 @@ export function checkOpenshiftView() {
8686
});
8787
});
8888

89-
describe('Component Registries', () => {
90-
let types: CustomTreeSection;
89+
describe('Devfile Registries', () => {
90+
let registries: CustomTreeSection;
9191

9292
before(async () => {
93-
types = await view.getContent().getSection(VIEWS.compRegistries) as CustomTreeSection;
94-
await types.expand();
93+
registries = await view.getContent().getSection(VIEWS.compRegistries) as CustomTreeSection;
94+
await registries.expand();
9595
});
9696

9797
it('shows the default devfile registry', async function test() {
9898
this.timeout(10000);
9999
await new Promise((res) => { setTimeout(res, 6000); });
100-
const registry = await types.findItem(VIEWS.devFileRegistry);
100+
const registry = await registries.findItem(VIEWS.devFileRegistry);
101101
expect(registry).not.undefined;
102102
});
103103
});

0 commit comments

Comments
 (0)