diff --git a/tests/e2e/.eslintrc.js b/tests/e2e/.eslintrc.js index 852e10710a4d..2a376d589d2a 100644 --- a/tests/e2e/.eslintrc.js +++ b/tests/e2e/.eslintrc.js @@ -93,7 +93,7 @@ module.exports = { '@typescript-eslint/no-unsafe-call': 'off', '@typescript-eslint/restrict-plus-operands': 'off', '@typescript-eslint/no-namespace': 'off', - '@typescript-eslint/no-unused-expressions': 'error', + '@typescript-eslint/no-unused-expressions': 'off', '@typescript-eslint/no-unused-vars': 'error', '@typescript-eslint/no-use-before-define': 'error', '@typescript-eslint/no-var-requires': 'off', diff --git a/tests/e2e/constants/BASE_TEST_CONSTANTS.ts b/tests/e2e/constants/BASE_TEST_CONSTANTS.ts index 6fb3f6a57ebe..6cab9182a61b 100644 --- a/tests/e2e/constants/BASE_TEST_CONSTANTS.ts +++ b/tests/e2e/constants/BASE_TEST_CONSTANTS.ts @@ -13,6 +13,7 @@ export enum Platform { } export const BASE_TEST_CONSTANTS: { + TESTING_APPLICATION_VERSION: string; TS_DEBUG_MODE: boolean; TS_PLATFORM: string; TS_SELENIUM_RESPONSE_INTERCEPTOR: boolean; @@ -24,12 +25,26 @@ export const BASE_TEST_CONSTANTS: { TS_SELENIUM_PROJECT_ROOT_FILE_NAME: string; TS_SELENIUM_HAPPY_PATH_WORKSPACE_NAME: string; IS_CLUSTER_DISCONNECTED: () => boolean; + APPLICATION_TYPE: () => string; } = { /** * base URL of the application which should be checked */ TS_SELENIUM_BASE_URL: !process.env.TS_SELENIUM_BASE_URL ? 'http://sample-url' : process.env.TS_SELENIUM_BASE_URL.replace(/\/$/, ''), + /** + * application type (che or devspaces) + */ + APPLICATION_TYPE: (): string => (BASE_TEST_CONSTANTS.TS_SELENIUM_BASE_URL.includes('devspaces') ? 'devspaces' : 'che'), + + /** + * testing application version + */ + TESTING_APPLICATION_VERSION: process.env.TESTING_APPLICATION_VERSION || '3.8', + + /** + * is cluster disconnected of online + */ IS_CLUSTER_DISCONNECTED: (): boolean => BASE_TEST_CONSTANTS.TS_SELENIUM_BASE_URL.includes('airgap'), /** diff --git a/tests/e2e/pageobjects/dashboard/Dashboard.ts b/tests/e2e/pageobjects/dashboard/Dashboard.ts index 0eae57ed112b..500e7fc595bd 100644 --- a/tests/e2e/pageobjects/dashboard/Dashboard.ts +++ b/tests/e2e/pageobjects/dashboard/Dashboard.ts @@ -26,10 +26,12 @@ export class Dashboard { private static readonly LOADER_ALERT: By = By.xpath('//*[@data-testid="loader-alert"]'); private static readonly LOGOUT_BUTTON: By = By.xpath('//button[text()="Logout"]'); private static readonly USER_SETTINGS_DROPDOWN: By = By.xpath('//header//button/span[text()!=""]//parent::button'); + private static readonly INFO_DROPDOWN_BUTTON: By = By.xpath('//button[@aria-label="About Menu"]'); + private static readonly ABOUT_DIALOG_WINDOW_CLOSE_BUTTON: By = By.xpath('//button[@aria-label="Close Dialog"]'); constructor( @inject(CLASSES.DriverHelper) - private readonly driverHelper: DriverHelper, + readonly driverHelper: DriverHelper, @inject(CLASSES.Workspaces) private readonly workspaces: Workspaces ) {} @@ -69,6 +71,37 @@ export class Dashboard { await this.waitPage(); } + async openAboutMenu(): Promise { + Logger.debug(); + + await this.driverHelper.waitAndClick(Dashboard.INFO_DROPDOWN_BUTTON); + } + + async selectAboutMenuItem(text: string): Promise { + Logger.debug(); + + await this.driverHelper.waitAndClick(this.getAboutMenuItemButton(text)); + } + + getAboutDialogWindowMenuElements(): By[] { + Logger.debug(); + + return [ + By.xpath('//dd[@data-testid="dashboard-version"]'), + this.getServerVersionItem(), + By.xpath('//dd[@data-testid="username"]'), + By.xpath('//dd[@data-testid="browser-name"]'), + By.xpath('//dd[@data-testid="browser-os"]'), + By.xpath('//dd[@data-testid="browser-version"]') + ]; + } + + async getApplicationVersionFromAboutDialogWindow(): Promise { + Logger.debug(); + + return await this.driverHelper.waitAndGetText(this.getServerVersionItem()); + } + async waitPage(timeout: number = TIMEOUT_CONSTANTS.TS_SELENIUM_LOAD_PAGE_TIMEOUT): Promise { Logger.debug(); @@ -107,6 +140,12 @@ export class Dashboard { await this.driverHelper.wait(TIMEOUT_CONSTANTS.TS_SELENIUM_DEFAULT_POLLING); } + async closeAboutDialogWindow(): Promise { + Logger.debug(); + + await this.driverHelper.waitAndClick(Dashboard.ABOUT_DIALOG_WINDOW_CLOSE_BUTTON); + } + async logout(timeout: number = TIMEOUT_CONSTANTS.TS_COMMON_DASHBOARD_WAIT_TIMEOUT): Promise { Logger.debug(); @@ -115,4 +154,12 @@ export class Dashboard { await this.driverHelper.waitAndClick(Dashboard.LOGOUT_BUTTON, timeout); await this.driverHelper.waitDisappearance(Dashboard.USER_SETTINGS_DROPDOWN, timeout); } + + private getAboutMenuItemButton(text: string): By { + return By.xpath(`//li/button[text()="${text}"]`); + } + + private getServerVersionItem(): By { + return By.xpath('//dd[@data-testid="server-version"]'); + } } diff --git a/tests/e2e/pageobjects/dashboard/Workspaces.ts b/tests/e2e/pageobjects/dashboard/Workspaces.ts index 812137a13d0f..fe108402a843 100644 --- a/tests/e2e/pageobjects/dashboard/Workspaces.ts +++ b/tests/e2e/pageobjects/dashboard/Workspaces.ts @@ -29,6 +29,7 @@ export class Workspaces { ); private static readonly DELETE_CONFIRMATION_CHECKBOX: By = By.xpath('//input[@data-testid="confirmation-checkbox"]'); private static readonly CONFIRMATION_WINDOW: By = By.xpath('//div[@aria-label="Delete workspaces confirmation window"]'); + private static readonly LEARN_MORE_DOC_LINK: By = By.xpath('//div/p/a'); constructor( @inject(CLASSES.DriverHelper) @@ -50,7 +51,7 @@ export class Workspaces { async clickOpenButton(workspaceName: string, timeout: number = TIMEOUT_CONSTANTS.TS_SELENIUM_LOAD_PAGE_TIMEOUT): Promise { Logger.debug(); - await this.driverHelper.waitAndClick(this.getOpenButtonLocator(workspaceName), timeout); + await this.driverHelper.waitAndClick(this.getOpenButton(workspaceName), timeout); } async waitWorkspaceListItem( @@ -59,7 +60,7 @@ export class Workspaces { ): Promise { Logger.debug(`"${workspaceName}"`); - await this.driverHelper.waitVisibility(this.getWorkspaceListItemLocator(workspaceName), timeout); + await this.driverHelper.waitVisibility(this.getWorkspaceListItem(workspaceName), timeout); } async waitWorkspaceWithRunningStatus( @@ -68,7 +69,7 @@ export class Workspaces { ): Promise { Logger.debug(`"${workspaceName}"`); - await this.driverHelper.waitVisibility(this.getWorkspaceStatusLocator(workspaceName, WorkspaceStatusUI.Running), timeout); + await this.driverHelper.waitVisibility(this.getWorkspaceStatus(workspaceName, WorkspaceStatusUI.Running), timeout); } async waitWorkspaceWithStoppedStatus( @@ -77,28 +78,28 @@ export class Workspaces { ): Promise { Logger.debug(`"${workspaceName}"`); - await this.driverHelper.waitVisibility(this.getWorkspaceStatusLocator(workspaceName, WorkspaceStatusUI.Stopped), timeout); + await this.driverHelper.waitVisibility(this.getWorkspaceStatus(workspaceName, WorkspaceStatusUI.Stopped), timeout); } - async clickWorkspaceListItem( + async clickWorkspaceListItemLink( workspaceName: string, timeout: number = TIMEOUT_CONSTANTS.TS_CLICK_DASHBOARD_ITEM_TIMEOUT ): Promise { Logger.debug(`"${workspaceName}"`); - await this.driverHelper.waitAndClick(this.getWorkspaceListItemLocator(workspaceName), timeout); + await this.driverHelper.waitAndClick(this.getOpenWorkspaceDetailsLink(workspaceName), timeout); } async clickActionsButton(workspaceName: string): Promise { Logger.debug(`of the '${workspaceName}' list item`); - await this.driverHelper.waitAndClick(this.getActionsLocator(workspaceName)); + await this.driverHelper.waitAndClick(this.getActions(workspaceName)); } async waitActionsPopup(workspaceName: string, timeout: number = TIMEOUT_CONSTANTS.TS_COMMON_DASHBOARD_WAIT_TIMEOUT): Promise { Logger.debug(`of the '${workspaceName}' list item`); - await this.driverHelper.waitVisibility(this.getExpandedActionsLocator(workspaceName), timeout); + await this.driverHelper.waitVisibility(this.getExpandedActions(workspaceName), timeout); } async openActionsPopup(workspaceName: string, timeout: number = TIMEOUT_CONSTANTS.TS_COMMON_DASHBOARD_WAIT_TIMEOUT): Promise { @@ -111,19 +112,19 @@ export class Workspaces { async clickActionsDeleteButton(workspaceName: string): Promise { Logger.debug(`for the '${workspaceName}' list item`); - await this.driverHelper.waitAndClick(this.getActionsPopupButtonLocator(workspaceName, 'Delete Workspace')); + await this.driverHelper.waitAndClick(this.getActionsPopupButton(workspaceName, 'Delete Workspace')); } async clickActionsStopWorkspaceButton(workspaceName: string): Promise { Logger.debug(`for the '${workspaceName}' list item`); // todo: workaround because of issue CRW-3649 try { - await this.driverHelper.waitAndClick(this.getActionsPopupButtonLocator(workspaceName, 'Stop Workspace')); + await this.driverHelper.waitAndClick(this.getActionsPopupButton(workspaceName, 'Stop Workspace')); } catch (e) { Logger.warn(`for the '${workspaceName}' list item - popup was missed, try to click one more time (issue CRW-3649).`); - await this.driverHelper.waitAndClick(this.getActionsLocator(workspaceName)); - await this.driverHelper.waitAndClick(this.getActionsPopupButtonLocator(workspaceName, 'Stop Workspace')); + await this.driverHelper.waitAndClick(this.getActions(workspaceName)); + await this.driverHelper.waitAndClick(this.getActionsPopupButton(workspaceName, 'Stop Workspace')); } } @@ -181,7 +182,7 @@ export class Workspaces { const polling: number = TIMEOUT_CONSTANTS.TS_SELENIUM_DEFAULT_POLLING; const attempts: number = Math.ceil(timeout / polling); - await this.driverHelper.waitDisappearance(this.getWorkspaceListItemLocator(workspaceName), attempts, polling); + await this.driverHelper.waitDisappearance(this.getWorkspaceListItem(workspaceName), attempts, polling); } async getAllCreatedWorkspacesNames(timeout: number = TIMEOUT_CONSTANTS.TS_COMMON_DASHBOARD_WAIT_TIMEOUT): Promise { @@ -206,33 +207,41 @@ export class Workspaces { return workspaceNames; } - private getWorkspaceListItemLocator(workspaceName: string): By { + async getLearnMoreDocumentationLink(): Promise { + Logger.debug(); + + return await this.driverHelper.waitAndGetElementAttribute(Workspaces.LEARN_MORE_DOC_LINK, 'href'); + } + + private getWorkspaceListItem(workspaceName: string): By { return By.xpath(`//tr[td//a[text()='${workspaceName}']]`); } - private getWorkspaceStatusLocator(workspaceName: string, workspaceStatus: WorkspaceStatusUI): By { + private getWorkspaceStatus(workspaceName: string, workspaceStatus: WorkspaceStatusUI): By { return By.xpath( `${ - this.getWorkspaceListItemLocator(workspaceName).value + this.getWorkspaceListItem(workspaceName).value }//span[@data-testid='workspace-status-indicator']//*[local-name()='svg' and @fill='${workspaceStatus}']` ); } - private getActionsLocator(workspaceName: string): By { - return By.xpath(`${this.getWorkspaceListItemLocator(workspaceName).value}/td/div/button[@aria-label='Actions']`); + private getActions(workspaceName: string): By { + return By.xpath(`${this.getWorkspaceListItem(workspaceName).value}/td/div/button[@aria-label='Actions']`); } - private getExpandedActionsLocator(workspaceName: string): By { - return By.xpath( - `${this.getWorkspaceListItemLocator(workspaceName).value}//button[@aria-label='Actions' and @aria-expanded='true']` - ); + private getExpandedActions(workspaceName: string): By { + return By.xpath(`${this.getWorkspaceListItem(workspaceName).value}//button[@aria-label='Actions' and @aria-expanded='true']`); + } + + private getActionsPopupButton(workspaceName: string, buttonText: string): By { + return By.xpath(`${this.getWorkspaceListItem(workspaceName).value}//li//button[text()='${buttonText}']`); } - private getActionsPopupButtonLocator(workspaceName: string, buttonText: string): By { - return By.xpath(`${this.getWorkspaceListItemLocator(workspaceName).value}//li//button[text()='${buttonText}']`); + private getOpenButton(workspaceName: string): By { + return By.xpath(`${this.getWorkspaceListItem(workspaceName).value}//td[@data-key=5]//a[text()='Open']`); } - private getOpenButtonLocator(workspaceName: string): By { - return By.xpath(`${this.getWorkspaceListItemLocator(workspaceName).value}//td[@data-key=5]//a[text()='Open']`); + private getOpenWorkspaceDetailsLink(workspaceName: string): By { + return By.xpath(`${this.getWorkspaceListItem(workspaceName).value}//a[text()='${workspaceName}']`); } } diff --git a/tests/e2e/pageobjects/dashboard/workspace-details/WorkspaceDetails.ts b/tests/e2e/pageobjects/dashboard/workspace-details/WorkspaceDetails.ts index 3d6ca24b0ec5..1f4be0791622 100644 --- a/tests/e2e/pageobjects/dashboard/workspace-details/WorkspaceDetails.ts +++ b/tests/e2e/pageobjects/dashboard/workspace-details/WorkspaceDetails.ts @@ -25,6 +25,10 @@ export class WorkspaceDetails { private static readonly SAVE_BUTTON: By = By.css('button[name="save-button"]'); private static readonly ENABLED_SAVE_BUTTON: By = By.css('button[name="save-button"][aria-disabled="false"]'); private static readonly WORKSPACE_DETAILS_LOADER: By = By.css('workspace-details-overview md-progress-linear'); + private static readonly STORAGE_TYPE_INFO_BUTTON: By = By.xpath('//label[@for="storage-type"]//following-sibling::button'); + private static readonly CLOSE_STORAGE_TYPE_INFO_BUTTON: By = By.xpath('//button[@aria-label="Close"]'); + private static readonly STORAGE_TYPE_DOC_LINK: By = By.xpath('//div/p/a'); + private static readonly DEVFILE_DOC_LINK: By = By.xpath('//a[text()="Devfile Documentation"]'); constructor( @inject(CLASSES.DriverHelper) @@ -101,20 +105,9 @@ export class WorkspaceDetails { } async waitTabsPresence(timeout: number = TIMEOUT_CONSTANTS.TS_COMMON_DASHBOARD_WAIT_TIMEOUT): Promise { - Logger.debug('WorkspaceDetails.waitTabsPresence'); - - const workspaceDetailsTabs: Array = [ - 'Overview', - 'Projects', - 'Containers', - 'Servers', - 'Env Variables', - 'Volumes', - 'Config', - 'SSH', - 'Plugins', - 'Editors' - ]; + Logger.debug(); + + const workspaceDetailsTabs: Array = ['Overview', 'Devfile', 'DevWorkspace', 'Logs', 'Events']; for (const tabTitle of workspaceDetailsTabs) { const workspaceDetailsTabLocator: By = this.getTabLocator(tabTitle); @@ -124,22 +117,39 @@ export class WorkspaceDetails { } async selectTab(tabTitle: string, timeout: number = TIMEOUT_CONSTANTS.TS_COMMON_DASHBOARD_WAIT_TIMEOUT): Promise { - Logger.debug(`WorkspaceDetails.selectTab ${tabTitle}`); + Logger.debug(`${tabTitle}`); await this.clickOnTab(tabTitle, timeout); - await this.waitTabSelected(tabTitle, timeout); } - private getWorkspaceTitleLocator(workspaceName: string): By { - return By.css(`che-row-toolbar[che-title='${workspaceName}']`); + async clickStorageTypeInfo(): Promise { + Logger.debug(); + + await this.driverHelper.waitAndClick(WorkspaceDetails.STORAGE_TYPE_INFO_BUTTON); } - private getTabLocator(tabTitle: string): By { - return By.xpath(`//md-tabs-canvas//md-tab-item//span[text()='${tabTitle}']`); + async getOpenStorageTypeDocumentationLink(): Promise { + Logger.debug(); + + return await this.driverHelper.waitAndGetElementAttribute(WorkspaceDetails.STORAGE_TYPE_DOC_LINK, 'href'); + } + + async closeStorageTypeInfo(): Promise { + Logger.debug(); + + await this.driverHelper.waitAndClick(WorkspaceDetails.CLOSE_STORAGE_TYPE_INFO_BUTTON); + } + + async getDevfileDocumentationLink(): Promise { + return await this.driverHelper.waitAndGetElementAttribute(WorkspaceDetails.DEVFILE_DOC_LINK, 'href'); + } + + private getWorkspaceTitleLocator(workspaceName: string): By { + return By.xpath(`//h1[text()='${workspaceName}']`); } - private getSelectedTabLocator(tabTitle: string): By { - return By.xpath(`//md-tabs-canvas[@role='tablist']//md-tab-item[@aria-selected='true']//span[text()='${tabTitle}']`); + private getTabLocator(tabTitle: string): By { + return By.xpath(`//button[contains(@id,'${tabTitle}')]`); } private async waitSaveButton(timeout: number = TIMEOUT_CONSTANTS.TS_COMMON_DASHBOARD_WAIT_TIMEOUT): Promise { @@ -165,9 +175,4 @@ export class WorkspaceDetails { const workspaceDetailsTabLocator: By = this.getTabLocator(tabTitle); await this.driverHelper.waitAndClick(workspaceDetailsTabLocator, timeout); } - - private async waitTabSelected(tabTitle: string, timeout: number = TIMEOUT_CONSTANTS.TS_COMMON_DASHBOARD_WAIT_TIMEOUT): Promise { - const selectedTabLocator: By = this.getSelectedTabLocator(tabTitle); - await this.driverHelper.waitVisibility(selectedTabLocator, timeout); - } } diff --git a/tests/e2e/resources/default-devfile.yaml b/tests/e2e/resources/default-devfile.yaml new file mode 100644 index 000000000000..727720d64df6 --- /dev/null +++ b/tests/e2e/resources/default-devfile.yaml @@ -0,0 +1,27 @@ +kind: DevWorkspace +apiVersion: workspace.devfile.io/v1alpha2 +metadata: + name: default +spec: + started: true + template: + projects: + - name: web-nodejs-sample + git: + remotes: + origin: "https://github.com/che-samples/web-nodejs-sample.git" + commands: + - id: say-hello + exec: + component: che-code-runtime-description + commandLine: echo "Hello from $(pwd)" + workingDir: ${PROJECT_SOURCE}/app + contributions: + - name: che-code + uri: https://eclipse-che.github.io/che-plugin-registry/main/v3/plugins/che-incubator/che-code/latest/devfile.yaml + components: + - name: che-code-runtime-description + container: + env: + - name: CODE_HOST + value: 0.0.0.0 diff --git a/tests/e2e/specs/dashboard-samples/Documentation.spec.ts b/tests/e2e/specs/dashboard-samples/Documentation.spec.ts new file mode 100644 index 000000000000..7cfc5715157f --- /dev/null +++ b/tests/e2e/specs/dashboard-samples/Documentation.spec.ts @@ -0,0 +1,147 @@ +/** ******************************************************************* + * copyright (c) 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 { KubernetesCommandLineToolsExecutor } from '../../utils/KubernetesCommandLineToolsExecutor'; +import fs from 'fs'; +import path from 'path'; +import YAML from 'yaml'; +import { expect } from 'chai'; +import { e2eContainer } from '../../configs/inversify.config'; +import { CLASSES } from '../../configs/inversify.types'; +import { LoginTests } from '../../tests-library/LoginTests'; +import { BASE_TEST_CONSTANTS } from '../../constants/BASE_TEST_CONSTANTS'; +import { Dashboard } from '../../pageobjects/dashboard/Dashboard'; +import { BrowserTabsUtil } from '../../utils/BrowserTabsUtil'; +import { Workspaces } from '../../pageobjects/dashboard/Workspaces'; +import { ShellExecutor } from '../../utils/ShellExecutor'; +import { WorkspaceDetails } from '../../pageobjects/dashboard/workspace-details/WorkspaceDetails'; + +suite('Check links to documentation page in Dashboard.', function (): void { + const pathToSampleFile: string = path.resolve('resources/default-devfile.yaml'); + const workspaceName: string = YAML.parse(fs.readFileSync(pathToSampleFile, 'utf8')).metadata.name; + const kubernetesCommandLineToolsExecutor: KubernetesCommandLineToolsExecutor = e2eContainer.get( + CLASSES.KubernetesCommandLineToolsExecutor + ); + kubernetesCommandLineToolsExecutor.workspaceName = workspaceName; + const loginTests: LoginTests = e2eContainer.get(CLASSES.LoginTests); + const dashboard: Dashboard = e2eContainer.get(CLASSES.Dashboard); + const workspaces: Workspaces = e2eContainer.get(CLASSES.Workspaces); + const workspaceDetails: WorkspaceDetails = e2eContainer.get(CLASSES.WorkspaceDetails); + const shellExecutor: ShellExecutor = e2eContainer.get(CLASSES.ShellExecutor); + const browserTabsUtil: BrowserTabsUtil = e2eContainer.get(CLASSES.BrowserTabsUtil); + + const testingVersion: string = BASE_TEST_CONSTANTS.TESTING_APPLICATION_VERSION; + const applicationType: string = BASE_TEST_CONSTANTS.APPLICATION_TYPE(); + let parentGUID: string = ''; + const documentationContent: any = { + topMenu: { + feature: { + che: { + text: 'Make a wish', + link: 'mailto:che-dev@eclipse.org' + }, + devspaces: { + text: 'Raise feature request', + link: 'https://issues.redhat.com/secure/CreateIssue.jspa?pid=12321720&issuetype=2' + } + }, + documentation: { + che: { + text: 'Documentation', + link: 'https://eclipse.dev/che/docs/stable/overview/introduction-to-eclipse-che/' + }, + devspaces: { + text: 'Documentation', + link: `https://access.redhat.com/documentation/en-us/red_hat_openshift_dev_spaces/${testingVersion}` + } + }, + support: { + che: { + text: 'Community', + link: 'https://eclipse.dev/che/' + }, + devspaces: { + text: 'Support', + link: 'https://access.redhat.com/products/red-hat-openshift-dev-spaces/' + } + } + }, + workspaces: { + learnMore: { + che: 'https://www.eclipse.org/che/docs/stable/end-user-guide/customizing-workspace-components/', + devspaces: `https://access.redhat.com/documentation/en-us/red_hat_openshift_dev_spaces/${testingVersion}/html-single/user_guide#developer-workspaces` + }, + storageType: { + che: 'https://www.eclipse.org/che/docs/stable/end-user-guide/url-parameter-for-the-workspace-storage/', + devspaces: `https://access.redhat.com/documentation/en-us/red_hat_openshift_dev_spaces/${testingVersion}/html-single/administration_guide#configuring-storage` + }, + devfile: { + che: 'https://www.eclipse.org/che/docs/stable/end-user-guide/devfile-introduction/', + devspaces: `https://access.redhat.com/documentation/en-us/red_hat_openshift_dev_spaces/${testingVersion}/html-single/user_guide#customizing-workspace-components` + } + } + }; + + suiteSetup('Login into OC client and apply default DevFile', function (): void { + kubernetesCommandLineToolsExecutor.loginToOcp(); + kubernetesCommandLineToolsExecutor.applyYamlConfigurationAsFile(pathToSampleFile); + shellExecutor.wait(5); + }); + + suiteTeardown('Delete default DevWorkspace', function (): void { + kubernetesCommandLineToolsExecutor.deleteDevWorkspace(); + }); + + loginTests.loginIntoChe(); + + test('Check if documentation section "About" present on Dashboard', async function (): Promise { + await dashboard.openAboutMenu(); + }); + + test('Check if documentation section "About" in top menu has required links', async function (): Promise { + parentGUID = await browserTabsUtil.getCurrentWindowHandle(); + for (const section of Object.keys(documentationContent.topMenu)) { + await dashboard.selectAboutMenuItem(documentationContent.topMenu[section][applicationType].text); + await browserTabsUtil.waitAndSwitchToAnotherWindow(parentGUID); + expect(await browserTabsUtil.getCurrentUrl()).eqls(documentationContent.topMenu[section][applicationType].link); + await browserTabsUtil.switchToWindow(parentGUID); + await browserTabsUtil.closeAllTabsExceptCurrent(); + } + }); + + test('Check if "About" dialog menu contains correct application version', async function (): Promise { + await dashboard.selectAboutMenuItem('About'); + for (const e of dashboard.getAboutDialogWindowMenuElements()) { + expect(await dashboard.driverHelper.waitVisibilityBoolean(e)).is.true; + } + expect(await dashboard.getApplicationVersionFromAboutDialogWindow()).contains(testingVersion); + await dashboard.closeAboutDialogWindow(); + }); + + test('Check if Workspaces page contains "Learn More" documentation link', async function (): Promise { + await dashboard.clickWorkspacesButton(); + await workspaces.waitPage(); + expect(await workspaces.getLearnMoreDocumentationLink()).eqls(documentationContent.workspaces.learnMore[applicationType]); + }); + + test('Check if Workspace Details page contains "Storage types" documentation link', async function (): Promise { + await workspaces.clickWorkspaceListItemLink(workspaceName); + await workspaceDetails.waitWorkspaceTitle(workspaceName); + await workspaceDetails.clickStorageTypeInfo(); + expect(await workspaceDetails.getOpenStorageTypeDocumentationLink()).eqls( + documentationContent.workspaces.storageType[applicationType] + ); + }); + + test('Check if Workspace Details page contains "Devfile" documentation link', async function (): Promise { + await workspaceDetails.closeStorageTypeInfo(); + await workspaceDetails.selectTab('Devfile'); + expect(await workspaceDetails.getDevfileDocumentationLink()).eqls(documentationContent.workspaces.devfile[applicationType]); + }); +}); diff --git a/tests/e2e/utils/BrowserTabsUtil.ts b/tests/e2e/utils/BrowserTabsUtil.ts index a38c58902326..cce2ee1bd99c 100644 --- a/tests/e2e/utils/BrowserTabsUtil.ts +++ b/tests/e2e/utils/BrowserTabsUtil.ts @@ -13,6 +13,7 @@ import { CLASSES } from '../configs/inversify.types'; import { DriverHelper } from './DriverHelper'; import { Logger } from './Logger'; import { CHROME_DRIVER_CONSTANTS } from '../constants/CHROME_DRIVER_CONSTANTS'; +import { TIMEOUT_CONSTANTS } from '../constants/TIMEOUT_CONSTANTS'; @injectable() export class BrowserTabsUtil { @@ -45,7 +46,10 @@ export class BrowserTabsUtil { await this.driverHelper.navigateToUrl(url); } - async waitAndSwitchToAnotherWindow(currentWindowHandle: string, timeout: number): Promise { + async waitAndSwitchToAnotherWindow( + currentWindowHandle: string, + timeout: number = TIMEOUT_CONSTANTS.TS_SELENIUM_WAIT_FOR_URL + ): Promise { Logger.debug(); await this.driverHelper.waitUntilTrue(async (): Promise => { diff --git a/tests/e2e/utils/DriverHelper.ts b/tests/e2e/utils/DriverHelper.ts index b62053e00ec3..54c64bc24821 100644 --- a/tests/e2e/utils/DriverHelper.ts +++ b/tests/e2e/utils/DriverHelper.ts @@ -215,7 +215,7 @@ export class DriverHelper { ); } - async waitAllVisibility(locators: Array, timeout: number): Promise { + async waitAllVisibility(locators: Array, timeout: number = TIMEOUT_CONSTANTS.TS_SELENIUM_CLICK_ON_VISIBLE_ITEM): Promise { Logger.trace(`${locators}`); for (const elementLocator of locators) {