Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"DevConsole integration" regression test case automation #22181

Merged
merged 4 commits into from
May 3, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions tests/e2e/configs/inversify.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ import { ProjectAndFileTests } from '../tests-library/ProjectAndFileTests';
import { LoginTests } from '../tests-library/LoginTests';
import { RedHatLoginPage } from '../pageobjects/login/RedHatLoginPage';
import { OcpRedHatLoginPage } from '../pageobjects/login/OcpRedHatLoginPage';
import { OcpMainPage } from '../pageobjects/openshift/OcpMainPage';
import { OcpImportFromGitPage } from '../pageobjects/openshift/OcpImportFromGitPage';
import { OcpApplicationPage } from '../pageobjects/openshift/OcpApplicationPage';

const e2eContainer: Container = new Container({defaultScope: 'Transient'});

Expand All @@ -53,6 +56,12 @@ e2eContainer.bind<Workspaces>(CLASSES.Workspaces).to(Workspaces);
e2eContainer.bind<WorkspaceDetails>(CLASSES.WorkspaceDetails).to(WorkspaceDetails);
e2eContainer.bind<ScreenCatcher>(CLASSES.ScreenCatcher).to(ScreenCatcher);
e2eContainer.bind<OcpLoginPage>(CLASSES.OcpLoginPage).to(OcpLoginPage);

e2eContainer.bind<OcpMainPage>(CLASSES.OcpMainPage).to(OcpMainPage);
e2eContainer.bind<OcpImportFromGitPage>(CLASSES.OcpImportFromGitPage).to(OcpImportFromGitPage);
e2eContainer.bind<OcpApplicationPage>(CLASSES.OcpApplicationPage).to(OcpApplicationPage);


e2eContainer.bind<CheLoginPage>(CLASSES.CheLoginPage).to(CheLoginPage);
e2eContainer.bind<CheApiRequestHandler>(CLASSES.CheApiRequestHandler).to(CheApiRequestHandler);
e2eContainer.bind<CreateWorkspace>(CLASSES.CreateWorkspace).to(CreateWorkspace);
Expand All @@ -61,13 +70,10 @@ e2eContainer.bind<LoginTests>(CLASSES.LoginTests).to(LoginTests);
e2eContainer.bind<Sanitizer>(CLASSES.Sanitizer).to(Sanitizer);
e2eContainer.bind<ApiUrlResolver>(CLASSES.ApiUrlResolver).to(ApiUrlResolver);
e2eContainer.bind<WorkspaceHandlingTests>(CLASSES.WorkspaceHandlingTests).to(WorkspaceHandlingTests);
e2eContainer.bind<RedHatLoginPage>(CLASSES.RedHatLoginPage).to(RedHatLoginPage);

TestConstants.TS_SELENIUM_VALUE_OPENSHIFT_OAUTH ?
e2eContainer.bind<ICheLoginPage>(TYPES.CheLogin).to(RegularUserOcpCheLoginPage) :
e2eContainer.bind<ICheLoginPage>(TYPES.CheLogin).to(OcpRedHatLoginPage);

if (TestConstants.TS_OCP_LOGIN_PAGE_PROVIDER_TITLE === 'DevSandbox') {
e2eContainer.bind<RedHatLoginPage>(CLASSES.RedHatLoginPage).to(RedHatLoginPage);
}

export { e2eContainer };
3 changes: 3 additions & 0 deletions tests/e2e/configs/inversify.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ const CLASSES: any = {
WorkspaceHandlingTests: 'WorkspaceHandlingTests',
RedHatLoginPage: 'RedHatLoginPage',
OcpRedHatLoginPage: 'OcpRedHatLoginPage',
OcpApplicationPage: 'OcpApplicationPage',
OcpMainPage: 'OcpMainPage',
OcpImportFromGitPage: 'OcpImportFromGitPage'
};

export { TYPES, CLASSES };
4 changes: 4 additions & 0 deletions tests/e2e/constants/TestConstants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ export const TestConstants: any = {
*/
TS_SELENIUM_BASE_URL: getBaseUrl(),

TS_SELENIUM_OPENSHIFT_CONSOLE_URL(): string {
dmytro-ndp marked this conversation as resolved.
Show resolved Hide resolved
return process.env.TS_SELENIUM_OPENSHIFT_CONSOLE_URL || TestConstants.TS_SELENIUM_BASE_URL.replace('devspaces', 'console-openshift-console');
},

/**
* Run browser in "Headless" (hidden) mode, "false" by default.
*/
Expand Down
3 changes: 3 additions & 0 deletions tests/e2e/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,10 @@ export * from './pageobjects/login/OcpUserLoginPage';
export * from './pageobjects/login/RedHatLoginPage';
export * from './pageobjects/login/RegularUserOcpCheLoginPage';
export * from './pageobjects/openshift/CheLoginPage';
export * from './pageobjects/openshift/OcpApplicationPage';
export * from './pageobjects/openshift/OcpImportFromGitPage';
export * from './pageobjects/openshift/OcpLoginPage';
export * from './pageobjects/openshift/OcpMainPage';
export * from './tests-library/LoginTests';
export * from './tests-library/ProjectAndFileTests';
export * from './tests-library/WorkspaceHandlingTests';
39 changes: 39 additions & 0 deletions tests/e2e/pageobjects/openshift/OcpApplicationPage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*********************************************************************
* Copyright (c) 2019-2023 Red Hat, Inc.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/
import 'reflect-metadata';
import { inject, injectable } from 'inversify';
import { DriverHelper } from '../../utils/DriverHelper';
import { CLASSES } from '../../configs/inversify.types';
import { By } from 'selenium-webdriver';
import { Logger } from '../../utils/Logger';
import { TimeoutConstants } from '../../constants/TimeoutConstants';
import { BrowserTabsUtil } from '../../utils/BrowserTabsUtil';

@injectable()
export class OcpApplicationPage {

constructor(
@inject(CLASSES.DriverHelper) private readonly driverHelper: DriverHelper,
@inject(CLASSES.BrowserTabsUtil) private readonly browserTabsUtil: BrowserTabsUtil) {
}

async waitApplicationIcon(): Promise<void> {
Logger.debug(`${this.constructor.name}.${this.waitApplicationIcon.name}`);

await this.driverHelper.waitPresence(By.xpath('//*[@data-test-id="base-node-handler"]'), TimeoutConstants.TS_SELENIUM_LOAD_PAGE_TIMEOUT);
dmytro-ndp marked this conversation as resolved.
Show resolved Hide resolved
}

async waitAndOpenEditSourceCodeIcon(): Promise<void> {
Logger.debug(`${this.constructor.name}.${this.waitAndOpenEditSourceCodeIcon.name}`);
const parentGUID: string = await this.browserTabsUtil.getCurrentWindowHandle();
await this.driverHelper.waitAndClick(By.xpath('//*[@aria-label="Edit source code"]'));
nallikaea marked this conversation as resolved.
Show resolved Hide resolved
await this.browserTabsUtil.waitAndSwitchToAnotherWindow(parentGUID, TimeoutConstants.TS_SELENIUM_LOAD_PAGE_TIMEOUT);
}
}
79 changes: 79 additions & 0 deletions tests/e2e/pageobjects/openshift/OcpImportFromGitPage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*********************************************************************
* Copyright (c) 2019-2023 Red Hat, Inc.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/
import 'reflect-metadata';
import { inject, injectable } from 'inversify';
import { DriverHelper } from '../../utils/DriverHelper';
import { CLASSES } from '../../configs/inversify.types';
import { By } from 'selenium-webdriver';
import { Logger } from '../../utils/Logger';
import { OcpApplicationPage } from './OcpApplicationPage';
import { BrowserTabsUtil } from '../../utils/BrowserTabsUtil';
import { e2eContainer } from '../../configs/inversify.config';

@injectable()
export class OcpImportFromGitPage {

constructor(
@inject(CLASSES.DriverHelper) private readonly driverHelper: DriverHelper,
@inject(CLASSES.BrowserTabsUtil) private readonly browserTabsUtil: BrowserTabsUtil) {
}

async enterGitRepoUrl(gitRepoUrl: string): Promise<void> {
Logger.debug(`${this.constructor.name}.${this.enterGitRepoUrl.name} "${gitRepoUrl}"`);

await this.driverHelper.enterValue(By.id('form-input-git-url-field'), gitRepoUrl);
}

async clickOnAdvancedOptionsButton(): Promise<void> {
Logger.debug(`${this.constructor.name}.${this.clickOnAdvancedOptionsButton.name}`);

if (!(await this.driverHelper.isVisible(By.xpath('//*[text()="Hide advanced Git options"]')))) {
await this.driverHelper.waitAndClick(By.xpath('//*[text()="Show advanced Git options"]//ancestor::button'));
}
}

async enterGitReference(gitReference: string): Promise<void> {
Logger.debug(`${this.constructor.name}.${this.enterGitReference.name} "${gitReference}"`);

await this.driverHelper.enterValue(By.id('form-input-git-ref-field'), gitReference);
}

async selectBuilderImageImportStrategy(): Promise<void> {
Logger.debug(`${this.constructor.name}.${this.selectBuilderImageImportStrategy.name}`);

await this.driverHelper.scrollToAndClick(By.xpath('//*[text()="Edit Import Strategy"]//ancestor::button'));
await this.driverHelper.scrollToAndClick(By.xpath('//*[text()="Builder Image"]//parent::div//parent::div'));
}

async addLabel(label: string): Promise<void> {
Logger.debug(`${this.constructor.name}.${this.addLabel.name} "${label}"`);

await this.driverHelper.scrollToAndClick(By.xpath('//button[text()="Labels"]'));
await this.driverHelper.scrollToAndEnterValue(By.id('form-selector-labels-field'), label);
}

async submitConfiguration(): Promise<OcpApplicationPage> {
Logger.debug(`${this.constructor.name}.${this.submitConfiguration.name}`);

await this.driverHelper.waitAndClick(By.xpath('//*[@data-test-id="submit-button"]'));
return e2eContainer.get(CLASSES.OcpApplicationPage);
}

async fitAndSubmitConfiguration(gitRepoUrl: string, gitReference: string, label: string): Promise<OcpApplicationPage> {
Logger.debug(`${this.constructor.name}.${this.fitAndSubmitConfiguration.name}`);

await this.enterGitRepoUrl(gitRepoUrl);
await this.clickOnAdvancedOptionsButton();
await this.enterGitReference(gitReference);
await this.selectBuilderImageImportStrategy();
await this.addLabel(label);
return await this.submitConfiguration();
}
}
6 changes: 3 additions & 3 deletions tests/e2e/pageobjects/openshift/OcpLoginPage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,13 +80,13 @@ export class OcpLoginPage {
async clickOnLoginButton(): Promise<void> {
Logger.debug('OcpLoginPage.clickOnLoginButton');

const loginButtonlocator: By = By.css('button[type=submit]');
await this.driverHelper.waitAndClick(loginButtonlocator);
const loginButtonLocator: By = By.css('button[type=submit]');
await this.driverHelper.waitAndClick(loginButtonLocator);
}

async waitDisappearanceOpenShiftLoginWelcomePage(): Promise<void> {
Logger.debug('OcpLoginPage.waitDisappearanceOpenShiftLoginWelcomePage');

await this.driverHelper.waitDisappearance(By.xpath(OcpLoginPage.LOGIN_PAGE_OPENSHIFT_XPATH));
await this.driverHelper.waitDisappearance(By.xpath(OcpLoginPage.LOGIN_PAGE_OPENSHIFT_XPATH), TestConstants.TS_SELENIUM_DEFAULT_ATTEMPTS * 10);
dmytro-ndp marked this conversation as resolved.
Show resolved Hide resolved
}
}
88 changes: 88 additions & 0 deletions tests/e2e/pageobjects/openshift/OcpMainPage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/*********************************************************************
* Copyright (c) 2019-2023 Red Hat, Inc.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/
import 'reflect-metadata';
import { inject, injectable } from 'inversify';
import { DriverHelper } from '../../utils/DriverHelper';
import { CLASSES } from '../../configs/inversify.types';
import { By } from 'selenium-webdriver';
import { Logger } from '../../utils/Logger';
import { TimeoutConstants } from '../../constants/TimeoutConstants';
import { OcpImportFromGitPage } from './OcpImportFromGitPage';
import { BrowserTabsUtil } from '../../utils/BrowserTabsUtil';
import { e2eContainer } from '../../configs/inversify.config';

@injectable()
export class OcpMainPage {

private static readonly MAIN_PAGE_HEADER_LOCATOR: By = By.id('page-main-header');
private static readonly SELECT_ROLE_BUTTON_LOCATOR: By = By.xpath('//*[@data-test-id="perspective-switcher-toggle"]');
private static readonly ADD_BUTTON_LOCATOR: By = By.xpath('//*[@data-test-id="+Add-header"]');
private static readonly IMPORT_FROM_GIT_ITEM_LOCATOR: By = By.xpath('//*[@data-test="item import-from-git"]');
private static readonly SELECT_PROJECT_DROPDOWN_LOCATOR: By = By.xpath('//div[@class="co-namespace-dropdown"]//button');
private static readonly PROJECT_FILTER_INPUT_LOCATOR: By = By.xpath('//*[@data-test="dropdown-text-filter"]');

constructor(
@inject(CLASSES.DriverHelper) private readonly driverHelper: DriverHelper) { }

async waitOpenMainPage(): Promise<void> {
Logger.debug(`${this.constructor.name}.${this.waitOpenMainPage.name}`);

await this.driverHelper.waitVisibility(OcpMainPage.MAIN_PAGE_HEADER_LOCATOR, TimeoutConstants.TS_SELENIUM_LOAD_PAGE_TIMEOUT);
}

async clickOnSelectRoleButton(): Promise<void> {
Logger.debug(`${this.constructor.name}.${this.clickOnSelectRoleButton.name}`);

await this.driverHelper.waitAndClick(OcpMainPage.SELECT_ROLE_BUTTON_LOCATOR);
}

async clickAddToProjectButton(): Promise<void> {
Logger.debug(`${this.constructor.name}.${this.clickAddToProjectButton.name}`);

await this.driverHelper.waitAndClick(OcpMainPage.ADD_BUTTON_LOCATOR);
}

async selectDeveloperRole(): Promise<void> {
Logger.debug(`${this.constructor.name}.${this.selectDeveloperRole.name}`);

await this.driverHelper.waitAndClick(this.getRoleLocator('Developer'));
}

async selectImportFromGitMethod(): Promise<OcpImportFromGitPage> {
Logger.debug(`${this.constructor.name}.${this.selectImportFromGitMethod.name}`);

await this.driverHelper.waitAndClick(OcpMainPage.IMPORT_FROM_GIT_ITEM_LOCATOR);
return e2eContainer.get(CLASSES.OcpImportFromGitPage);
}

async openImportFromGitPage(): Promise<OcpImportFromGitPage> {
await this.waitOpenMainPage();
await this.clickOnSelectRoleButton();
await this.selectDeveloperRole();
await this.clickAddToProjectButton();
return await this.selectImportFromGitMethod();
}

async selectProject(projectName: string): Promise<void> {
Logger.debug(`${this.constructor.name}.${this.selectProject.name}`);

await this.driverHelper.waitAndClick(OcpMainPage.SELECT_PROJECT_DROPDOWN_LOCATOR);
await this.driverHelper.enterValue(OcpMainPage.PROJECT_FILTER_INPUT_LOCATOR, projectName);
await this.driverHelper.waitAndClick(this.getProjectDropdownItemLocator(projectName));
}

private getRoleLocator(role: string): By {
return By.xpath(`//a//*[text()="${role}"]`);
}

private getProjectDropdownItemLocator(projectName: string): By {
return By.xpath(`//button//*[text()="${projectName}"]`);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
/*********************************************************************
* Copyright (c) 2019-2023 Red Hat, Inc.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/

import {
SideBarView,
ViewItem,
ViewSection
} from 'monaco-page-objects';
import { registerRunningWorkspace } from '../MochaHooks';
import { LoginTests } from '../../tests-library/LoginTests';
import { e2eContainer } from '../../configs/inversify.config';
import { CLASSES } from '../../configs/inversify.types';
import { WorkspaceHandlingTests } from '../../tests-library/WorkspaceHandlingTests';
import { ProjectAndFileTests } from '../../tests-library/ProjectAndFileTests';
import { Logger } from '../../utils/Logger';
import { expect } from 'chai';
import { TestConstants } from '../../constants/TestConstants';
import { OcpMainPage } from '../../pageobjects/openshift/OcpMainPage';
import { OcpImportFromGitPage } from '../../pageobjects/openshift/OcpImportFromGitPage';
import { KubernetesCommandLineToolsExecutor } from '../../utils/KubernetesCommandLineToolsExecutor';
import { GitUtil } from '../../utils/vsc/GitUtil';
import { OcpApplicationPage } from '../../pageobjects/openshift/OcpApplicationPage';

const projectAndFileTests: ProjectAndFileTests = e2eContainer.get(CLASSES.ProjectAndFileTests);
const loginTests: LoginTests = e2eContainer.get(CLASSES.LoginTests);
const workspaceHandlingTests: WorkspaceHandlingTests = e2eContainer.get(CLASSES.WorkspaceHandlingTests);
const ocpMainPage: OcpMainPage = e2eContainer.get(CLASSES.OcpMainPage);
let ocpImportPage: OcpImportFromGitPage;
let ocpApplicationPage: OcpApplicationPage;
const kubernetesCommandLineToolsExecutor: KubernetesCommandLineToolsExecutor = new KubernetesCommandLineToolsExecutor();

// works only with no-admin user
suite(`DevConsole Integration`, async function (): Promise<void> {
// test specific data
const gitImportRepo: string = 'https://github.com/musienko-maxim/summit-lab-spring-music';
dmytro-ndp marked this conversation as resolved.
Show resolved Hide resolved
const gitImportReference: string = 'pipeline';
const projectLabel: string = 'app.openshift.io/runtime=spring';
const projectName: string = 'devconsole-integration-test';

suiteSetup('Create new empty project using ocp', async function (): Promise<void> {
kubernetesCommandLineToolsExecutor.loginToOcp();
kubernetesCommandLineToolsExecutor.deleteProject(projectName);
kubernetesCommandLineToolsExecutor.createProject(projectName);
});

loginTests.loginIntoOcpConsole();

test('Select test project on DevConsole', async function (): Promise<void> {
await ocpMainPage.selectProject(projectName);
});

test('Open import from git project page as Developer', async function (): Promise<void> {
ocpImportPage = await ocpMainPage.openImportFromGitPage();
});

test('Fill and submit import data', async function (): Promise<void> {
ocpApplicationPage = await ocpImportPage.fitAndSubmitConfiguration(gitImportRepo, gitImportReference, projectLabel);
});

test('Wait until application creates', async function (): Promise<void> {
await ocpApplicationPage.waitApplicationIcon();
});

test('Check if application has worked link "Open Source Code"', async function (): Promise<void> {
await ocpApplicationPage.waitAndOpenEditSourceCodeIcon();
});

loginTests.loginIntoChe();

workspaceHandlingTests.obtainWorkspaceNameFromStartingPage();

test('Registering the running workspace', async function (): Promise<void> {
registerRunningWorkspace(WorkspaceHandlingTests.getWorkspaceName());
});

test('Check if application source code opens in workspace', async function (): Promise<void> {
await projectAndFileTests.waitWorkspaceReadinessForCheCodeEditor();
});

test('Check if project and files imported', async function (): Promise<void> {
const applicationSourceProjectName: string = GitUtil.getProjectNameFromGitUrl(gitImportRepo);
const projectSection: ViewSection = await new SideBarView().getContent().getSection(applicationSourceProjectName as unknown as string);
dmytro-ndp marked this conversation as resolved.
Show resolved Hide resolved
const isFileImported: ViewItem | undefined = await projectSection.findItem(TestConstants.TS_SELENIUM_PROJECT_ROOT_FILE_NAME);
expect(isFileImported).not.eqls(undefined);
});

loginTests.logoutFromChe();

suiteTeardown('Delete project using ocp', async function (): Promise<void> {
kubernetesCommandLineToolsExecutor.deleteProject(projectName);
});
});
Loading