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

CRW-1121 Automate testing of links to documentation page in Dashboard #22497

Merged
merged 1 commit into from
Sep 21, 2023
Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 1 addition & 1 deletion tests/e2e/.eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
16 changes: 16 additions & 0 deletions tests/e2e/constants/BASE_TEST_CONSTANTS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ export enum Platform {
}

export const BASE_TEST_CONSTANTS: {
IS_PRODUCT_DOCUMENTATION_RELEASED: any;
TESTING_APPLICATION_VERSION: string;
TS_DEBUG_MODE: boolean;
TS_PLATFORM: string;
TS_SELENIUM_RESPONSE_INTERCEPTOR: boolean;
Expand All @@ -31,6 +33,20 @@ export const BASE_TEST_CONSTANTS: {
*/
TS_SELENIUM_BASE_URL: !process.env.TS_SELENIUM_BASE_URL ? 'http://sample-url' : process.env.TS_SELENIUM_BASE_URL.replace(/\/$/, ''),

/**
* testing application version
*/
TESTING_APPLICATION_VERSION: process.env.TESTING_APPLICATION_VERSION || '3.8',

/**
* is "https://access.redhat.com/documentation/en-us/red_hat_openshift_dev_spaces/{TESTING_APPLICATION_VERSION}/" available online
* false by default
*/
IS_PRODUCT_DOCUMENTATION_RELEASED: process.env.IS_PRODUCT_DOCUMENTATION_RELEASED === 'true',

/**
* is cluster disconnected of online
*/
IS_CLUSTER_DISCONNECTED: (): boolean => BASE_TEST_CONSTANTS.TS_SELENIUM_BASE_URL.includes('airgap'),

/**
Expand Down
4 changes: 2 additions & 2 deletions tests/e2e/pageobjects/dashboard/CreateWorkspace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ export class CreateWorkspace {

Logger.debug(`sampleName: "${sampleName}"`);

const sampleLocator: By = this.getSampleLocatorWithSpecificEditor(sampleName);
const sampleLocator: By = this.getSampleWithSpecificEditorLocator(sampleName);
await this.driverHelper.waitAndClick(sampleLocator, timeout);
}

Expand All @@ -80,7 +80,7 @@ export class CreateWorkspace {
return By.xpath(`//div[text()=\'${sampleName}\']//parent::article//button`);
}

private getSampleLocatorWithSpecificEditor(sampleName: string): By {
private getSampleWithSpecificEditorLocator(sampleName: string): By {
let editor: string = '';
switch (process.env.TS_SELENIUM_EDITOR) {
case 'che-code':
Expand Down
64 changes: 63 additions & 1 deletion tests/e2e/pageobjects/dashboard/Dashboard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,22 @@ 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"]');
private static readonly EXISTING_WORKSPACE_FOUND_ALERT: By = By.xpath('//h4[text()="Existing workspace found"]');
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',
dashboardVersion: 'dashboard-version',
browserName: 'browser-name',
browserOs: 'browser-os',
browserVersion: 'browser-version',
username: 'username'
};

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

Expand Down Expand Up @@ -71,6 +81,44 @@ export class Dashboard {
await this.waitPage();
}

async openAboutMenu(): Promise<void> {
Logger.debug();

await this.driverHelper.waitAndClick(Dashboard.INFO_DROPDOWN_BUTTON);
}

async selectAboutMenuItem(text: string): Promise<void> {
Logger.debug();

await this.driverHelper.waitAndClick(this.getAboutMenuItemButtonLocator(text));
}

async waitAboutDialogWindowMenuElements(timeout: number = TIMEOUT_CONSTANTS.TS_COMMON_DASHBOARD_WAIT_TIMEOUT): Promise<void> {
Logger.debug();

for (const testId of Object.values(Dashboard.ABOUT_DIALOG_ITEM_DATA_TEST_IDS)) {
const workspaceDetailsTabLocator: By = this.getAboutDialogWindowItemLocator(<string>testId);

await this.driverHelper.waitVisibility(workspaceDetailsTabLocator, timeout);
}
}

async getApplicationVersionFromAboutDialogWindow(): Promise<string> {
Logger.debug();

return await this.driverHelper.waitAndGetText(
this.getAboutDialogWindowItemLocator(Dashboard.ABOUT_DIALOG_ITEM_DATA_TEST_IDS.serverVersion)
);
}

async getUsernameFromAboutDialogWindow(): Promise<string> {
Logger.debug();

return await this.driverHelper.waitAndGetText(
this.getAboutDialogWindowItemLocator(Dashboard.ABOUT_DIALOG_ITEM_DATA_TEST_IDS.username)
);
}

async waitPage(timeout: number = TIMEOUT_CONSTANTS.TS_SELENIUM_LOAD_PAGE_TIMEOUT): Promise<void> {
Logger.debug();

Expand Down Expand Up @@ -109,6 +157,12 @@ export class Dashboard {
await this.driverHelper.wait(TIMEOUT_CONSTANTS.TS_SELENIUM_DEFAULT_POLLING);
}

async closeAboutDialogWindow(): Promise<void> {
Logger.debug();

await this.driverHelper.waitAndClick(Dashboard.ABOUT_DIALOG_WINDOW_CLOSE_BUTTON);
}

async waitExistingWorkspaceFoundAlert(timeout: number = TIMEOUT_CONSTANTS.TS_COMMON_DASHBOARD_WAIT_TIMEOUT): Promise<void> {
Logger.debug();

Expand All @@ -129,4 +183,12 @@ export class Dashboard {
await this.driverHelper.waitAndClick(Dashboard.LOGOUT_BUTTON, timeout);
await this.driverHelper.waitDisappearance(Dashboard.USER_SETTINGS_DROPDOWN, timeout);
}

private getAboutMenuItemButtonLocator(text: string): By {
return By.xpath(`//li/button[text()="${text}"]`);
}

private getAboutDialogWindowItemLocator(itemDataTestId: string): By {
return By.xpath(`//dd[@data-testid="${itemDataTestId}"]`);
}
}
15 changes: 13 additions & 2 deletions tests/e2e/pageobjects/dashboard/Workspaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -80,13 +81,13 @@ export class Workspaces {
await this.driverHelper.waitVisibility(this.getWorkspaceStatusLocator(workspaceName, WorkspaceStatusUI.Stopped), timeout);
}

async clickWorkspaceListItem(
async clickWorkspaceListItemLink(
workspaceName: string,
timeout: number = TIMEOUT_CONSTANTS.TS_CLICK_DASHBOARD_ITEM_TIMEOUT
): Promise<void> {
Logger.debug(`"${workspaceName}"`);

await this.driverHelper.waitAndClick(this.getWorkspaceListItemLocator(workspaceName), timeout);
await this.driverHelper.waitAndClick(this.getOpenWorkspaceDetailsLinkLocator(workspaceName), timeout);
}

async clickActionsButton(workspaceName: string): Promise<void> {
Expand Down Expand Up @@ -206,6 +207,12 @@ export class Workspaces {
return workspaceNames;
}

async getLearnMoreDocumentationLink(): Promise<string> {
Logger.debug();

return await this.driverHelper.waitAndGetElementAttribute(Workspaces.LEARN_MORE_DOC_LINK, 'href');
}

private getWorkspaceListItemLocator(workspaceName: string): By {
return By.xpath(`//tr[td//a[text()='${workspaceName}']]`);
}
Expand Down Expand Up @@ -235,4 +242,8 @@ export class Workspaces {
private getOpenButtonLocator(workspaceName: string): By {
return By.xpath(`${this.getWorkspaceListItemLocator(workspaceName).value}//td[@data-key=5]//a[text()='Open']`);
}

private getOpenWorkspaceDetailsLinkLocator(workspaceName: string): By {
return By.xpath(`${this.getWorkspaceListItemLocator(workspaceName).value}//a[text()='${workspaceName}']`);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -101,20 +105,9 @@ export class WorkspaceDetails {
}

async waitTabsPresence(timeout: number = TIMEOUT_CONSTANTS.TS_COMMON_DASHBOARD_WAIT_TIMEOUT): Promise<void> {
Logger.debug('WorkspaceDetails.waitTabsPresence');

const workspaceDetailsTabs: Array<string> = [
'Overview',
'Projects',
'Containers',
'Servers',
'Env Variables',
'Volumes',
'Config',
'SSH',
'Plugins',
'Editors'
];
Logger.debug();

const workspaceDetailsTabs: Array<string> = ['Overview', 'Devfile', 'DevWorkspace', 'Logs', 'Events'];

for (const tabTitle of workspaceDetailsTabs) {
const workspaceDetailsTabLocator: By = this.getTabLocator(tabTitle);
Expand All @@ -124,22 +117,39 @@ export class WorkspaceDetails {
}

async selectTab(tabTitle: string, timeout: number = TIMEOUT_CONSTANTS.TS_COMMON_DASHBOARD_WAIT_TIMEOUT): Promise<void> {
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<void> {
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<string> {
Logger.debug();

return await this.driverHelper.waitAndGetElementAttribute(WorkspaceDetails.STORAGE_TYPE_DOC_LINK, 'href');
}

async closeStorageTypeInfo(): Promise<void> {
Logger.debug();

await this.driverHelper.waitAndClick(WorkspaceDetails.CLOSE_STORAGE_TYPE_INFO_BUTTON);
}

async getDevfileDocumentationLink(): Promise<string> {
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<void> {
Expand All @@ -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<void> {
const selectedTabLocator: By = this.getSelectedTabLocator(tabTitle);
await this.driverHelper.waitVisibility(selectedTabLocator, timeout);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,6 @@ export class RegularUserOcpCheLoginPage implements ICheLoginPage {
private readonly driverHelper: DriverHelper
) {}

/**
* @param userName
* @param password
*/
async login(
userName: string = OAUTH_CONSTANTS.TS_SELENIUM_OCP_USERNAME,
password: string = OAUTH_CONSTANTS.TS_SELENIUM_OCP_PASSWORD
Expand Down
27 changes: 27 additions & 0 deletions tests/e2e/resources/default-devfile.yaml
Original file line number Diff line number Diff line change
@@ -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
Loading
Loading