Skip to content

Commit

Permalink
adding bind service test
Browse files Browse the repository at this point in the history
Signed-off-by: Lukas Grossmann <[email protected]>
  • Loading branch information
Lukas Grossmann authored and vrubezhny committed Sep 20, 2024
1 parent b2f7fd5 commit 8e1c580
Show file tree
Hide file tree
Showing 6 changed files with 182 additions and 34 deletions.
2 changes: 1 addition & 1 deletion .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@
"max-classes-per-file": [0],
"no-alert": 2,
"no-caller": 2,
//"no-console": 2,
"no-console": 2,
"no-constant-condition": 2,
"no-debugger": 2,
"no-else-return": ["error"],
Expand Down
1 change: 1 addition & 0 deletions test/ui/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,4 +80,5 @@ export const NOTIFICATIONS = {
deleteConfig: (path: string) => `Are you sure you want to delete the configuration for the component ${path}? OpenShift Toolkit will no longer recognize the project as a component.`,
deleteSourceCodeFolder: (path: string) => `Are you sure you want to delete the folder containing the source code for ${path}?`,
serviceCreated: (name: string) => `Service ${name} successfully created.`,
lookingForBindableServices: 'Looking for bindable services',
};
34 changes: 31 additions & 3 deletions test/ui/common/overdrives.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,45 @@
* Copyright (c) Red Hat, Inc. All rights reserved.
* Licensed under the MIT License. See LICENSE file in the project root for license information.
*-----------------------------------------------------------------------------------------------*/
import { ViewSection, By, waitForAttributeValue } from 'vscode-extension-tester';
import { ViewSection, By, waitForAttributeValue, BottomBarPanel, VSBrowser, ActivityBar } from 'vscode-extension-tester';
import { activateCommand } from './command-activator';
import { VIEWS } from './constants';

export async function collapse(section: ViewSection){
export async function collapse(section: ViewSection) {
try {
await section.collapse();
} catch {
if (await section.isExpanded()) {
const mainPanel = await section.findElement(By.className('pane-header'));
const arrowPanel = await section.findElement(By.className('codicon'));
await arrowPanel.click();
await section.getDriver().wait(waitForAttributeValue(mainPanel, 'aria-expanded', 'false'), 2_000);
await section
.getDriver()
.wait(waitForAttributeValue(mainPanel, 'aria-expanded', 'false'), 2_000);
}
}
}

/**
* Closes BottomBarPanel and reloads window so openshift terminal is not loaded,
* then waits until window is loaded.
* Fixes issue where openshift terminal stoles focus during work with other webviews
*/
export async function reloadWindow() {
const bottomBar = new BottomBarPanel();
await bottomBar.toggle(false);
await activateCommand('>Developer: Reload Window');
await VSBrowser.instance.waitForWorkbench();

//wait for Activity Bar to be loaded
await VSBrowser.instance.driver.wait(async () => {
try {
const viewControl = await new ActivityBar().getViewControl(VIEWS.openshift);
if (viewControl) {
return true;
}
} catch {
return null;
}
});
}
85 changes: 85 additions & 0 deletions test/ui/common/ui/webview/addServiceBinding.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/*-----------------------------------------------------------------------------------------------
* Copyright (c) Red Hat, Inc. All rights reserved.
* Licensed under the MIT License. See LICENSE file in the project root for license information.
*-----------------------------------------------------------------------------------------------*/

import { By, WebElement, WebView } from 'vscode-extension-tester';
import { WebViewForm } from './WebViewForm';

export class AddServiceBindingWebView extends WebViewForm {

public constructor() {
super('Add service binding');
}

public async clickComboBox(): Promise<void> {
await this.enterWebView(async (webView) => {
const comboBox = await this.comboBoxExists(webView);
await comboBox.click();
});
}

public async selectItemFromComboBox(text: string): Promise<void> {
await this.enterWebView(async (webView) => {
const item = await this.getElementFromComboBox(webView, text);
await item.click();
});
}

public async setBindingName(name: string) {
await this.enterWebView(async (webView) => {
const item = await this.getBindingNameInput(webView);
await item.click();
await item.sendKeys(name);
});
}

public async clickAddServiceBindingButton(): Promise<void> {
await this.enterWebView(async (webView) => {
const button = await this.addServiceBindingButtonExists(webView);
await button.click();
});
}

private async getServiceToBindComboBox(webView: WebView): Promise<WebElement> {
return await webView.findWebElement(By.xpath('//div[@role="combobox"]'));
}

private async getElementFromComboBox(webView: WebView, text: string): Promise<WebElement> {
return await webView.findWebElement(By.xpath(`//li[contains(text(), "${text}")]`));
}

private async getBindingNameInput(webView: WebView): Promise<WebElement> {
return webView.findWebElement(By.xpath('//input[@id="binding-name"]'));
}

private async getAddServiceBindingButton(webView: WebView): Promise<WebElement> {
return webView.findWebElement(By.xpath('//button[contains(text(), "Add Service Binding")]'));
}

private async comboBoxExists(webView: WebView, timeout = 15_000): Promise<WebElement> {
return webView.getDriver().wait(async () => {
try {
const comboBox = await this.getServiceToBindComboBox(webView);
if (comboBox) {
return comboBox;
}
} catch {
return null;
}
}, timeout);
}

private async addServiceBindingButtonExists(webView: WebView, timeout = 10_000): Promise<WebElement> {
return webView.getDriver().wait(async () => {
try {
const button = await this.getAddServiceBindingButton(webView);
if (button) {
return button;
}
} catch {
return null;
}
}, timeout);
}
}
10 changes: 10 additions & 0 deletions test/ui/suite/componentCommands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import { OpenshiftTerminalWebviewView } from '../common/ui/webviewView/openshift
import * as yml from 'js-yaml';
import * as fs from 'fs';
import * as pth from 'path';
import { reloadWindow } from '../common/overdrives';
import { itemExists } from '../common/conditions';

export function testComponentCommands(path: string) {
describe('Component Commands', function () {
Expand All @@ -38,7 +40,15 @@ export function testComponentCommands(path: string) {
await (await view.getContent().getSection(item)).collapse();
}

//expect component is running
section = await view.getContent().getSection(VIEWS.components);
const item = await itemExists(`${componentName} (dev running)`, section);
expect(item).is.not.undefined;
});

after(async function () {
//close openshift terminal
await reloadWindow();
});

it('Commands are listed', async function () {
Expand Down
84 changes: 54 additions & 30 deletions test/ui/suite/operatorBackedService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@

import {
ActivityBar,
BottomBarPanel,
EditorView,
SideBarView,
TreeItem,
Expand All @@ -14,62 +13,50 @@ import {
Workbench,
before,
} from 'vscode-extension-tester';
import { activateCommand } from '../common/command-activator';
import { MENUS, NOTIFICATIONS, VIEWS } from '../common/constants';
import { itemExists, notificationExists } from '../common/conditions';
import { itemExists, notificationDoesNotExist, notificationExists } from '../common/conditions';
import { CreateServiceWebView, ServiceSetupPage } from '../common/ui/webview/createServiceWebView';
import { AddServiceBindingWebView } from '../common/ui/webview/addServiceBinding';
import { reloadWindow } from '../common/overdrives';

export function operatorBackedServiceTest() {
describe('Operator-Backed Service', () => {
describe('Operator-Backed Service', function () {
const cluster = process.env.CLUSTER_URL || 'https://api.crc.testing:6443';
const clusterName = cluster;

let view: SideBarView;
let section: ViewSection;
let projectName: string;
let serviceName: string;

before(async function () {
this.timeout(30_000)
/*
Workaround for not being able to access webview due to
openshift terminal stealing focus
*/
const bottomBar = new BottomBarPanel();
await bottomBar.toggle(false);
await activateCommand('>Developer: Reload Window');
await VSBrowser.instance.waitForWorkbench();

//wait for Activity Bar to be loaded
await VSBrowser.instance.driver.wait(async () => {
try {
const viewControl = await new ActivityBar().getViewControl(VIEWS.openshift);
if (viewControl) {
return true;
}
} catch {
return null;
}
});

view = await (await new ActivityBar().getViewControl(VIEWS.openshift)).openView();
section = await view.getContent().getSection(VIEWS.appExplorer);

await itemExists(clusterName, section);

await new EditorView().closeAllEditors();
await (await new Workbench().openNotificationsCenter()).clearAllNotifications();
});

it('Can create operator backed service', async () => {
after(async function () {
await reloadWindow();
});

it('Can create operator backed service', async function () {
this.timeout(60_000);

const clusterItem = await section.findItem(clusterName) as TreeItem;
//get project, open context menu and select create new operator backed service
const clusterItem = await itemExists(clusterName, section) as TreeItem;
await clusterItem.expand();
await clusterItem.getDriver().wait(async () => await clusterItem.hasChildren());
const children = await clusterItem.getChildren();
const project = children[0];
projectName = await project.getLabel();
const contextMenu = await project.openContextMenu();
await contextMenu.select(MENUS.create, MENUS.createOperatorBackedService);

//select service to be created
const createServiceWebView = new CreateServiceWebView();
await createServiceWebView.initializeEditor();
await createServiceWebView.clickComboBox();
Expand All @@ -79,22 +66,59 @@ export function operatorBackedServiceTest() {
);
await createServiceWebView.clickNext();

//finish creating service
const serviceSetupPage = new ServiceSetupPage();
await serviceSetupPage.initializeEditor();
const serviceName = await serviceSetupPage.getName();
serviceName = await serviceSetupPage.getName();
await serviceSetupPage.clickSubmit();

//wait for notification about successful service creation
await notificationExists(
NOTIFICATIONS.serviceCreated(serviceName),
VSBrowser.instance.driver,
);

//check that deployment is shown
await project.expand();
const deployments = await itemExists('Deployments', section) as TreeItem;
await deployments.expand();
await itemExists(serviceName, section);
});

it.skip('Can bind service to a component', async () => {});
it('Can bind service to a component', async function () {
this.timeout(60_000);
const componentName = 'nodejs-starter';
const bindingName = 'test-binding';
section = await view.getContent().getSection(VIEWS.components);

//open context menu on component and click bind service
const component = await section.findItem(componentName);
let contextMenu = await component.openContextMenu();
await contextMenu.select(MENUS.bindService);

//wait for look for available services to be completed
await notificationDoesNotExist(NOTIFICATIONS.lookingForBindableServices, VSBrowser.instance.driver);

//select service to bind
const addServiceBinding = new AddServiceBindingWebView();
await addServiceBinding.initializeEditor();
await addServiceBinding.clickComboBox();
await addServiceBinding.selectItemFromComboBox(`${projectName}/${serviceName}`);
await addServiceBinding.setBindingName(bindingName);
await addServiceBinding.clickAddServiceBindingButton();

//start dev on component
contextMenu = await component.openContextMenu();
await contextMenu.select(MENUS.startDev);

//wait for start dev to finish
await itemExists(`${componentName} (dev starting)`, section);
await itemExists(`${componentName} (dev running)`, section, 35_000);

//check service binding is shown in deployments
await section.collapse();
section = await view.getContent().getSection(VIEWS.appExplorer);
await itemExists(bindingName, section);
});
});
}

0 comments on commit 8e1c580

Please sign in to comment.