diff --git a/tests/e2e/pageobjects/dashboard/CreateWorkspace.ts b/tests/e2e/pageobjects/dashboard/CreateWorkspace.ts index 5a280bc4c73..95cee2e4eb5 100644 --- a/tests/e2e/pageobjects/dashboard/CreateWorkspace.ts +++ b/tests/e2e/pageobjects/dashboard/CreateWorkspace.ts @@ -94,6 +94,22 @@ export class CreateWorkspace { await this.performTrustAuthorPopup(); } + async setGitRepositoryUrl(factoryUrl: string, timeout: number = TIMEOUT_CONSTANTS.TS_CLICK_DASHBOARD_ITEM_TIMEOUT): Promise { + Logger.debug(`factoryUrl: "${factoryUrl}"`); + await this.driverHelper.waitVisibility(CreateWorkspace.FACTORY_URL, timeout); + await this.driverHelper.type(CreateWorkspace.FACTORY_URL, Key.chord(factoryUrl), timeout); + } + + async getGitRepositoryUrl(timeout: number = TIMEOUT_CONSTANTS.TS_CLICK_DASHBOARD_ITEM_TIMEOUT): Promise { + Logger.debug(); + return await this.driverHelper.waitAndGetValue(CreateWorkspace.FACTORY_URL, timeout); + } + + async clickOnCreateAndOpenButton(timeout: number = TIMEOUT_CONSTANTS.TS_CLICK_DASHBOARD_ITEM_TIMEOUT): Promise { + Logger.debug(); + await this.driverHelper.waitAndClick(CreateWorkspace.CREATE_AND_OPEN_BUTTON, timeout); + } + async clickOnEditorsDropdownListButton(sampleName: string, timeout: number): Promise { Logger.debug(`sampleName: "${sampleName}, editor ${BASE_TEST_CONSTANTS.TS_SELENIUM_EDITOR}"`); diff --git a/tests/e2e/pageobjects/dashboard/Dashboard.ts b/tests/e2e/pageobjects/dashboard/Dashboard.ts index c0332ce20e6..99d7722c5ae 100644 --- a/tests/e2e/pageobjects/dashboard/Dashboard.ts +++ b/tests/e2e/pageobjects/dashboard/Dashboard.ts @@ -10,7 +10,7 @@ import { inject, injectable } from 'inversify'; import 'reflect-metadata'; import { CLASSES } from '../../configs/inversify.types'; -import { Alert, By } from 'selenium-webdriver'; +import { Alert, By, WebElement } from 'selenium-webdriver'; import { DriverHelper } from '../../utils/DriverHelper'; import { TIMEOUT_CONSTANTS } from '../../constants/TIMEOUT_CONSTANTS'; import { Workspaces } from './Workspaces'; @@ -28,7 +28,11 @@ export class Dashboard { 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"]'); - private static readonly EXISTING_WORKSPACE_FOUND_ALERT: By = By.xpath('//h4[text()="Existing workspace found"]'); + private static readonly EXISTING_WORKSPACE_FOUND_ALERT: By = By.xpath( + '//div[text()="Several workspaces created from the same repository have been found. Should you want to open one of the existing workspaces or create a new one, please choose the corresponding action."]' + ); + private static readonly EXISTING_WORKSPACE_FOUND_LIST: By = By.xpath('//button//span[text()="Open the existing workspace"]'); + private static readonly EXISTING_WORKSPACE_NAME: By = By.xpath('//li//a[text()="python-hello-world"]"]'); private static readonly CREATE_NEW_WORKSPACE_LINK: By = By.xpath('//button[text()="Create a new workspace"]'); private static readonly ABOUT_DIALOG_ITEM_DATA_TEST_IDS: any = { serverVersion: 'server-version', @@ -180,6 +184,15 @@ export class Dashboard { await this.driverHelper.waitVisibility(Dashboard.EXISTING_WORKSPACE_FOUND_ALERT, timeout); } + async startExistedWorkspace(workspaceName: string): Promise { + Logger.debug(); + + await this.driverHelper.waitVisibility(Dashboard.EXISTING_WORKSPACE_FOUND_LIST); + const element: WebElement = await this.driverHelper.waitPresence(Dashboard.EXISTING_WORKSPACE_FOUND_LIST); + await this.driverHelper.getDriver().executeScript('arguments[0].click();', element); + await this.driverHelper.waitAndClick(By.xpath(`//li//a[text()="${workspaceName}"]`)); + } + async clickOnCreateNewWorkspaceButton(timeout: number = TIMEOUT_CONSTANTS.TS_CLICK_DASHBOARD_ITEM_TIMEOUT): Promise { Logger.debug(); diff --git a/tests/e2e/specs/miscellaneous/CreateWorkspaceWithExistingNameFromGitUrl.spec.ts b/tests/e2e/specs/miscellaneous/CreateWorkspaceWithExistingNameFromGitUrl.spec.ts new file mode 100644 index 00000000000..dcc398d312a --- /dev/null +++ b/tests/e2e/specs/miscellaneous/CreateWorkspaceWithExistingNameFromGitUrl.spec.ts @@ -0,0 +1,150 @@ +/** ******************************************************************* + * copyright (c) 2020-2025 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 { e2eContainer } from '../../configs/inversify.config'; +import { ViewSection } from 'monaco-page-objects'; +import { CLASSES } from '../../configs/inversify.types'; +import { expect } from 'chai'; +import { WorkspaceHandlingTests } from '../../tests-library/WorkspaceHandlingTests'; +import { ProjectAndFileTests } from '../../tests-library/ProjectAndFileTests'; +import { LoginTests } from '../../tests-library/LoginTests'; +import { registerRunningWorkspace } from '../MochaHooks'; +import { BrowserTabsUtil } from '../../utils/BrowserTabsUtil'; +import { BASE_TEST_CONSTANTS } from '../../constants/BASE_TEST_CONSTANTS'; +import { Dashboard } from '../../pageobjects/dashboard/Dashboard'; +import { FACTORY_TEST_CONSTANTS } from '../../constants/FACTORY_TEST_CONSTANTS'; +import { CreateWorkspace } from '../../pageobjects/dashboard/CreateWorkspace'; +import { TIMEOUT_CONSTANTS } from '../../constants/TIMEOUT_CONSTANTS'; + +const projectName: string = FACTORY_TEST_CONSTANTS.TS_SELENIUM_PROJECT_NAME || 'python-hello-world'; + +suite(`"Start workspace with existed workspace name" test ${BASE_TEST_CONSTANTS.TEST_ENVIRONMENT}`, function (): void { + const workspaceHandlingTests: WorkspaceHandlingTests = e2eContainer.get(CLASSES.WorkspaceHandlingTests); + const projectAndFileTests: ProjectAndFileTests = e2eContainer.get(CLASSES.ProjectAndFileTests); + const loginTests: LoginTests = e2eContainer.get(CLASSES.LoginTests); + const browserTabsUtil: BrowserTabsUtil = e2eContainer.get(CLASSES.BrowserTabsUtil); + const dashboard: Dashboard = e2eContainer.get(CLASSES.Dashboard); + const createWorkspace: CreateWorkspace = e2eContainer.get(CLASSES.CreateWorkspace); + + let projectSection: ViewSection; + let firstWorkspaceName: string; + let secondWorkspaceName: string; + const factoryUrl: string = BASE_TEST_CONSTANTS.IS_CLUSTER_DISCONNECTED() + ? FACTORY_TEST_CONSTANTS.TS_SELENIUM_AIRGAP_FACTORY_GIT_REPO_URL || 'https://gh.crw-qe.com/test-automation-only/python-hello-world' + : FACTORY_TEST_CONSTANTS.TS_SELENIUM_FACTORY_GIT_REPO_URL || 'https://github.com/crw-qe/python-hello-world'; + + suiteSetup('Login', async function (): Promise { + await loginTests.loginIntoChe(); + }); + + async function waitDashboardPage(): Promise { + await dashboard.openDashboard(); + await dashboard.waitPage(); + await browserTabsUtil.closeAllTabsExceptCurrent(); + + await dashboard.clickCreateWorkspaceButton(); + await createWorkspace.waitPage(); + expect(await createWorkspace.isCreateNewWorkspaceCheckboxChecked()).to.be.true; + } + + async function waitWorkspaceReadiness(): Promise { + const originalWindowHandle: string = await browserTabsUtil.getCurrentWindowHandle(); + await browserTabsUtil.waitAndSwitchToAnotherWindow(originalWindowHandle, TIMEOUT_CONSTANTS.TS_IDE_LOAD_TIMEOUT); + + await workspaceHandlingTests.obtainWorkspaceNameFromStartingPage(); + + registerRunningWorkspace(WorkspaceHandlingTests.getWorkspaceName()); + + await projectAndFileTests.waitWorkspaceReadinessForCheCodeEditor(); + projectSection = await projectAndFileTests.getProjectViewSession(); + expect(await projectAndFileTests.getProjectTreeItem(projectSection, projectName), 'Project folder was not imported').not.undefined; + expect( + await projectAndFileTests.getProjectTreeItem(projectSection, BASE_TEST_CONSTANTS.TS_SELENIUM_PROJECT_ROOT_FILE_NAME), + 'Project files were not imported' + ).not.undefined; + } + + test('Verify "Create New" is off and a new workspace is created', async function (): Promise { + await waitDashboardPage(); + + await createWorkspace.setGitRepositoryUrl(factoryUrl); + expect(await createWorkspace.isCreateNewWorkspaceCheckboxChecked()).to.be.false; + expect(await createWorkspace.getGitRepositoryUrl()).to.be.equal(factoryUrl); + await createWorkspace.clickOnCreateAndOpenButton(); + await createWorkspace.performTrustAuthorPopup(); + + await waitWorkspaceReadiness(); + + firstWorkspaceName = WorkspaceHandlingTests.getWorkspaceName(); + }); + + test('Verify existing workspace opens instead of creating a duplicate', async function (): Promise { + await waitDashboardPage(); + + await createWorkspace.setGitRepositoryUrl(factoryUrl); + expect(await createWorkspace.getGitRepositoryUrl()).to.be.equal(factoryUrl); + await createWorkspace.clickOnCreateAndOpenButton(); + await createWorkspace.performTrustAuthorPopup(); + + await waitWorkspaceReadiness(); + + expect(WorkspaceHandlingTests.getWorkspaceName()).to.be.equal(firstWorkspaceName); + }); + + test('Ensure `new` is appended and a new workspace is created without warnings', async function (): Promise { + await waitDashboardPage(); + + await createWorkspace.setGitRepositoryUrl(factoryUrl); + await createWorkspace.setCreateNewWorkspaceCheckbox(true); + + expect(await createWorkspace.getGitRepositoryUrl()).to.be.equal(factoryUrl + '?new'); + + await createWorkspace.clickOnCreateAndOpenButton(); + await createWorkspace.performTrustAuthorPopup(); + + await waitWorkspaceReadiness(); + + secondWorkspaceName = WorkspaceHandlingTests.getWorkspaceName(); + // validate workspace name follows pattern: firstWorkspaceName + "-xxxx" (4 alphanumeric chars) + expect(secondWorkspaceName).to.match(new RegExp(`^${firstWorkspaceName}-[a-z0-9]{4}$`)); + }); + + test('Verify warning appears with list of existing workspaces and open the first created workspace', async function (): Promise { + await waitDashboardPage(); + + await createWorkspace.setGitRepositoryUrl(factoryUrl); + await createWorkspace.clickOnCreateAndOpenButton(); + await createWorkspace.performTrustAuthorPopup(); + const originalWindowHandle: string = await browserTabsUtil.getCurrentWindowHandle(); + await browserTabsUtil.waitAndSwitchToAnotherWindow(originalWindowHandle, TIMEOUT_CONSTANTS.TS_IDE_LOAD_TIMEOUT); + + await dashboard.waitExistingWorkspaceFoundAlert(); + await dashboard.startExistedWorkspace(firstWorkspaceName); + + await workspaceHandlingTests.obtainWorkspaceNameFromStartingPage(); + registerRunningWorkspace(WorkspaceHandlingTests.getWorkspaceName()); + + await projectAndFileTests.waitWorkspaceReadinessForCheCodeEditor(); + projectSection = await projectAndFileTests.getProjectViewSession(); + expect(await projectAndFileTests.getProjectTreeItem(projectSection, projectName), 'Project folder was not imported').not.undefined; + expect( + await projectAndFileTests.getProjectTreeItem(projectSection, BASE_TEST_CONSTANTS.TS_SELENIUM_PROJECT_ROOT_FILE_NAME), + 'Project files were not imported' + ).not.undefined; + }); + + suiteTeardown('Stop and delete all created workspaces', async function (): Promise { + await workspaceHandlingTests.stopAndRemoveWorkspace(firstWorkspaceName); + await workspaceHandlingTests.stopAndRemoveWorkspace(secondWorkspaceName); + }); + + suiteTeardown('Unregister running workspace', function (): void { + registerRunningWorkspace(''); + }); +}); diff --git a/tests/e2e/suites/disconnected-ocp/UITest.suite.ts b/tests/e2e/suites/disconnected-ocp/UITest.suite.ts index 879138158a0..505a8f175ed 100644 --- a/tests/e2e/suites/disconnected-ocp/UITest.suite.ts +++ b/tests/e2e/suites/disconnected-ocp/UITest.suite.ts @@ -11,6 +11,6 @@ import '../../specs/dashboard-samples/Quarkus.spec'; import '../../specs/dashboard-samples/RecommendedExtensions.spec'; import '../../specs/dashboard-samples/Documentation.spec'; import '../../specs/devconsole-intergration/DevConsoleIntegration.spec'; -import '../../specs/miscellaneous/CreateWorkspaceWithExistedName.spec'; +import '../../specs/miscellaneous/CreateWorkspaceWithExistingNameFromGitUrl.spec'; import '../../specs/miscellaneous/WorkspaceWithParent.spec'; import '../../specs/miscellaneous/PredefinedNamespace.spec'; diff --git a/tests/e2e/suites/online-ocp/UITest.suite.ts b/tests/e2e/suites/online-ocp/UITest.suite.ts index 0899211f776..2a8f42f4853 100644 --- a/tests/e2e/suites/online-ocp/UITest.suite.ts +++ b/tests/e2e/suites/online-ocp/UITest.suite.ts @@ -13,7 +13,7 @@ import '../../specs/dashboard-samples/Quarkus.spec'; import '../../specs/dashboard-samples/RecommendedExtensions.spec'; import '../../specs/dashboard-samples/Documentation.spec'; import '../../specs/devconsole-intergration/DevConsoleIntegration.spec'; -import '../../specs/miscellaneous/CreateWorkspaceWithExistedName.spec'; +import '../../specs/miscellaneous/CreateWorkspaceWithExistingNameFromGitUrl.spec'; import '../../specs/miscellaneous/KubedockPodmanTest.spec'; import '../../specs/miscellaneous/WorkspaceWithParent.spec'; import '../../specs/miscellaneous/PredefinedNamespace.spec';