From 8ded9dd01b101b6b9947e02f541f7abfbd8bb839 Mon Sep 17 00:00:00 2001 From: Igor Ohrimenko Date: Mon, 1 Apr 2019 17:28:07 +0300 Subject: [PATCH] [Cypress] Rework "cypress-tests" module with using "InversifyJS" library (#13036) --- .gitignore | 2 +- ...ionAndLanguageServerInitialization.spec.ts | 8 +- .../cypress/inversifyJS/inversify.config.ts | 21 +++++ cypress-tests/cypress/inversifyJS/types.ts | 13 +++ .../pageobjects/dashboard/LoginPage.ts | 72 ----------------- .../dashboard/LoginPageMultiUser.ts | 81 +++++++++++++++++++ .../dashboard/LoginPageSingleUser.ts | 24 ++++++ .../dashboard/interfaces/ILoginPage.ts | 13 +++ .../cypress/pageobjects/ide/Editor.ts | 5 +- cypress-tests/cypress/pageobjects/ide/Ide.ts | 16 ++-- .../cypress/pageobjects/ide/ProjectTree.ts | 8 +- .../utils/workspace/TestWorkspaceUtil.ts | 8 +- cypress-tests/package-lock.json | 10 +++ cypress-tests/package.json | 4 + cypress-tests/tsconfig.json | 6 +- 15 files changed, 194 insertions(+), 97 deletions(-) create mode 100644 cypress-tests/cypress/inversifyJS/inversify.config.ts create mode 100644 cypress-tests/cypress/inversifyJS/types.ts delete mode 100644 cypress-tests/cypress/pageobjects/dashboard/LoginPage.ts create mode 100644 cypress-tests/cypress/pageobjects/dashboard/LoginPageMultiUser.ts create mode 100644 cypress-tests/cypress/pageobjects/dashboard/LoginPageSingleUser.ts create mode 100644 cypress-tests/cypress/pageobjects/dashboard/interfaces/ILoginPage.ts diff --git a/.gitignore b/.gitignore index 2ea73d7eab..6ad2c31082 100644 --- a/.gitignore +++ b/.gitignore @@ -92,4 +92,4 @@ requirements.lock */coverage */.grunt */.lock-wscript - +*/cypress-tests/dist diff --git a/cypress-tests/cypress/integration/WorkspaceCreationAndLanguageServerInitialization.spec.ts b/cypress-tests/cypress/integration/WorkspaceCreationAndLanguageServerInitialization.spec.ts index a0faa66fd7..be45a83d15 100644 --- a/cypress-tests/cypress/integration/WorkspaceCreationAndLanguageServerInitialization.spec.ts +++ b/cypress-tests/cypress/integration/WorkspaceCreationAndLanguageServerInitialization.spec.ts @@ -17,7 +17,6 @@ * 4. Check Language Server initialization * 5. Delete workspace using dashboard */ -import { LoginPage } from "../pageobjects/dashboard/LoginPage"; import { Dashboard } from "../pageobjects/dashboard/Dashboard"; import { Workspaces } from "../pageobjects/dashboard/Workspaces"; import { NewWorkspace } from "../pageobjects/dashboard/NewWorkspace"; @@ -25,12 +24,15 @@ import { Ide } from "../pageobjects/ide/Ide"; import { ProjectTree } from "../pageobjects/ide/ProjectTree"; import { Editor } from "../pageobjects/ide/Editor"; import { NameGenerator } from "../utils/NameGenerator"; +import { ILoginPage } from "../pageobjects/dashboard/interfaces/ILoginPage"; +import { e2eContainer } from "../inversifyJS/inversify.config"; +import { TYPES } from "../inversifyJS/types"; const workspaceName: string = NameGenerator.generate("wksp-test-", 5); const namespace: string = "che"; const sampleName: string = "console-java-simple"; -const loginPage: LoginPage = new LoginPage(); +const loginPage: ILoginPage = e2eContainer.get(TYPES.ILoginPage); const dashboard: Dashboard = new Dashboard(); const workspaces: Workspaces = new Workspaces(); const newWorkspace: NewWorkspace = new NewWorkspace(); @@ -43,7 +45,7 @@ describe("E2E test", () => { context("Prepare dashboard", () => { it("Open dashboard", () => { - dashboard.openDashboard(); + loginPage.login(); dashboard.waitLoaderPage(); dashboard.waitLoaderPageAbcence() dashboard.waitDashboard(); diff --git a/cypress-tests/cypress/inversifyJS/inversify.config.ts b/cypress-tests/cypress/inversifyJS/inversify.config.ts new file mode 100644 index 0000000000..d59debb0f5 --- /dev/null +++ b/cypress-tests/cypress/inversifyJS/inversify.config.ts @@ -0,0 +1,21 @@ +import { Container } from "inversify"; +import { ILoginPage } from "../pageobjects/dashboard/interfaces/ILoginPage"; +import { TYPES } from "./types"; +import { LoginPageSingleUser } from "../pageobjects/dashboard/LoginPageSingleUser"; + +/********************************************************************* + * Copyright (c) 2018 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 + **********************************************************************/ + +const e2eContainer = new Container(); + +e2eContainer.bind(TYPES.ILoginPage).to(LoginPageSingleUser) + + +export {e2eContainer} diff --git a/cypress-tests/cypress/inversifyJS/types.ts b/cypress-tests/cypress/inversifyJS/types.ts new file mode 100644 index 0000000000..2830f761c3 --- /dev/null +++ b/cypress-tests/cypress/inversifyJS/types.ts @@ -0,0 +1,13 @@ +/********************************************************************* + * Copyright (c) 2018 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 + **********************************************************************/ + +export const TYPES = { + ILoginPage: Symbol.for("ILoginPage") +} diff --git a/cypress-tests/cypress/pageobjects/dashboard/LoginPage.ts b/cypress-tests/cypress/pageobjects/dashboard/LoginPage.ts deleted file mode 100644 index 6aaa2543fc..0000000000 --- a/cypress-tests/cypress/pageobjects/dashboard/LoginPage.ts +++ /dev/null @@ -1,72 +0,0 @@ -/********************************************************************* - * Copyright (c) 2018 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 - **********************************************************************/ - -/// - -export class LoginPage { - private static readonly LOAD_PAGE_TIMEOUT: number = Cypress.env('load_page_timeout'); - private static readonly TEST_USER_NANE: string = Cypress.env('test_user_name'); - private static readonly TEST_USER_PASSWORD: string = Cypress.env('test_user_password'); - - - private static readonly USERNAME_FIELD: string = "#username"; - private static readonly PASSWORD_FIELD: string = "#password"; - private static readonly LOGIN_BUTTON: string = "[name='login']"; - - private typeToInputField(text: string, fieldLocator: string) { - cy.get(fieldLocator) - .click() - .focus() - .type(text); - } - - visitLoginPage() { - cy.visit("/"); - } - - typeUsername(username: string) { - this.typeToInputField(username, LoginPage.USERNAME_FIELD); - } - - typePassword(password: string) { - this.typeToInputField(password, LoginPage.PASSWORD_FIELD); - } - - clickOnLoginButton() { - cy.get(LoginPage.LOGIN_BUTTON).click(); - } - - waitPage() { - [LoginPage.LOGIN_BUTTON, LoginPage.USERNAME_FIELD, LoginPage.PASSWORD_FIELD] - .forEach(elementLocator => { - cy.get(elementLocator, { timeout: LoginPage.LOAD_PAGE_TIMEOUT }).should('be.visible'); - }) - } - - waitPageAbcence() { - [LoginPage.LOGIN_BUTTON, LoginPage.USERNAME_FIELD, LoginPage.PASSWORD_FIELD] - .forEach(elementLocator => { - cy.get(elementLocator, { timeout: LoginPage.LOAD_PAGE_TIMEOUT }).should('not.be.visible'); - }) - } - - login(username: string, password: string) { - this.waitPage(); - this.typeUsername(username); - this.typePassword(password); - this.clickOnLoginButton(); - this.waitPageAbcence(); - } - - defaultLogin() { - this.login(LoginPage.TEST_USER_NANE, LoginPage.TEST_USER_PASSWORD); - } - -} diff --git a/cypress-tests/cypress/pageobjects/dashboard/LoginPageMultiUser.ts b/cypress-tests/cypress/pageobjects/dashboard/LoginPageMultiUser.ts new file mode 100644 index 0000000000..3ab7533680 --- /dev/null +++ b/cypress-tests/cypress/pageobjects/dashboard/LoginPageMultiUser.ts @@ -0,0 +1,81 @@ +import { ILoginPage } from "./interfaces/ILoginPage"; +import { Dashboard } from "./Dashboard"; +import { injectable, inject } from "inversify"; +import "reflect-metadata"; + + +/********************************************************************* + * Copyright (c) 2018 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 + **********************************************************************/ + +/// + +@injectable() +export class LoginPageMultiUser implements ILoginPage { + private static readonly LOAD_PAGE_TIMEOUT: number = Cypress.env('load_page_timeout'); + private static readonly TEST_USER_NANE: string = Cypress.env('test_user_name'); + private static readonly TEST_USER_PASSWORD: string = Cypress.env('test_user_password'); + + private readonly dashboard: Dashboard = new Dashboard(); + + + private static readonly USERNAME_FIELD: string = "#username"; + private static readonly PASSWORD_FIELD: string = "#password"; + private static readonly LOGIN_BUTTON: string = "[name='login']"; + + private typeToInputField(text: string, fieldLocator: string) { + cy.get(fieldLocator) + .click() + .focus() + .type(text); + } + + private visitLoginPage() { + cy.visit("/"); + } + + private typeUsername(username: string) { + this.typeToInputField(username, LoginPageMultiUser.USERNAME_FIELD); + } + + private typePassword(password: string) { + this.typeToInputField(password, LoginPageMultiUser.PASSWORD_FIELD); + } + + private clickOnLoginButton() { + cy.get(LoginPageMultiUser.LOGIN_BUTTON) + .click(); + } + + private waitPage() { + [LoginPageMultiUser.LOGIN_BUTTON, LoginPageMultiUser.USERNAME_FIELD, LoginPageMultiUser.PASSWORD_FIELD] + .forEach(elementLocator => { + cy.get(elementLocator, { timeout: LoginPageMultiUser.LOAD_PAGE_TIMEOUT }) + .should('be.visible'); + }) + } + + private waitPageAbcence() { + [LoginPageMultiUser.LOGIN_BUTTON, LoginPageMultiUser.USERNAME_FIELD, LoginPageMultiUser.PASSWORD_FIELD] + .forEach(elementLocator => { + cy.get(elementLocator, { timeout: LoginPageMultiUser.LOAD_PAGE_TIMEOUT }) + .should('not.be.visible'); + }) + } + + login() { + this.visitLoginPage(); + this.waitPage(); + this.typeUsername(LoginPageMultiUser.TEST_USER_NANE); + this.typePassword(LoginPageMultiUser.TEST_USER_PASSWORD); + this.clickOnLoginButton(); + this.waitPageAbcence(); + } + +} diff --git a/cypress-tests/cypress/pageobjects/dashboard/LoginPageSingleUser.ts b/cypress-tests/cypress/pageobjects/dashboard/LoginPageSingleUser.ts new file mode 100644 index 0000000000..016c359826 --- /dev/null +++ b/cypress-tests/cypress/pageobjects/dashboard/LoginPageSingleUser.ts @@ -0,0 +1,24 @@ +import { injectable } from "inversify"; +import "reflect-metadata"; +import { ILoginPage } from "./interfaces/ILoginPage"; + + +/********************************************************************* + * Copyright (c) 2018 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 + **********************************************************************/ + +/// + + +@injectable() +export class LoginPageSingleUser implements ILoginPage { + login(){ + cy.visit("/"); + } +} diff --git a/cypress-tests/cypress/pageobjects/dashboard/interfaces/ILoginPage.ts b/cypress-tests/cypress/pageobjects/dashboard/interfaces/ILoginPage.ts new file mode 100644 index 0000000000..faa4b96757 --- /dev/null +++ b/cypress-tests/cypress/pageobjects/dashboard/interfaces/ILoginPage.ts @@ -0,0 +1,13 @@ +/********************************************************************* + * Copyright (c) 2018 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 + **********************************************************************/ + + export interface ILoginPage{ + login():void; + } diff --git a/cypress-tests/cypress/pageobjects/ide/Editor.ts b/cypress-tests/cypress/pageobjects/ide/Editor.ts index 0f44a564f4..3ec325e00a 100644 --- a/cypress-tests/cypress/pageobjects/ide/Editor.ts +++ b/cypress-tests/cypress/pageobjects/ide/Editor.ts @@ -10,7 +10,6 @@ /// -import { Promise, reject } from "bluebird"; export class Editor { @@ -95,8 +94,8 @@ export class Editor { return lineCoordinate; } - public addAttributeToLines(): Promise { - return new Promise((resolve, reject) => { + public addAttributeToLines(): PromiseLike { + return new Cypress.Promise((resolve:any, reject:any) => { let elementsArray: Array> = new Array(); cy.get(Editor.EDITOR_LINES) diff --git a/cypress-tests/cypress/pageobjects/ide/Ide.ts b/cypress-tests/cypress/pageobjects/ide/Ide.ts index fd6c4d2897..300c57dd2a 100644 --- a/cypress-tests/cypress/pageobjects/ide/Ide.ts +++ b/cypress-tests/cypress/pageobjects/ide/Ide.ts @@ -22,7 +22,7 @@ export class Ide { private static readonly TOP_MENU_PANEL: string = "#theia-app-shell #theia-top-panel .p-MenuBar-content"; private static readonly LEFT_CONTENT_PANEL: string = "#theia-left-content-panel"; - public static readonly FILES_BUTTON: string = ".theia-app-left .p-TabBar-content li[title='Files']"; + public static readonly EXPLORER_BUTTON: string = ".theia-app-left .p-TabBar-content li[title='Explorer']"; private static readonly PRELOADER: string = ".theia-preload"; private static readonly IDE_IFRAME: string = "iframe#ide-application-iframe"; @@ -57,7 +57,7 @@ export class Ide { cy.log("**Wait until defined parts of IDE are visible**") }) .then(() => { - [Ide.TOP_MENU_PANEL, Ide.LEFT_CONTENT_PANEL, Ide.FILES_BUTTON] + [Ide.TOP_MENU_PANEL, Ide.LEFT_CONTENT_PANEL, Ide.EXPLORER_BUTTON] .forEach(idePartLocator => { cy.get(Ide.IDE_IFRAME, { timeout: Ide.LOAD_PAGE_TIMEOUT }) .should(iframe => { @@ -74,7 +74,7 @@ export class Ide { this.testWorkspaceUtil.waitWorkspaceRunning(workspaceNamespace, workspaceName) }) .then(() => { - [Ide.TOP_MENU_PANEL, Ide.LEFT_CONTENT_PANEL, Ide.FILES_BUTTON] + [Ide.TOP_MENU_PANEL, Ide.LEFT_CONTENT_PANEL, Ide.EXPLORER_BUTTON] .forEach(idePart => { cy.get(idePart, { timeout: Ide.LOAD_PAGE_TIMEOUT }) .should('be.visible') @@ -83,7 +83,7 @@ export class Ide { } waitIde() { - [Ide.TOP_MENU_PANEL, Ide.LEFT_CONTENT_PANEL, Ide.FILES_BUTTON] + [Ide.TOP_MENU_PANEL, Ide.LEFT_CONTENT_PANEL, Ide.EXPLORER_BUTTON] .forEach(idePart => { cy.get(idePart, { timeout: Ide.LOAD_PAGE_TIMEOUT }) .should('be.visible') @@ -99,13 +99,13 @@ export class Ide { }) } - waitFilesButton() { - cy.get(Ide.FILES_BUTTON) + waitExplorerButton() { + cy.get(Ide.EXPLORER_BUTTON) .should('be.visible'); } - clickOnFilesButton() { - cy.get(Ide.FILES_BUTTON) + clickOnExplorerButton() { + cy.get(Ide.EXPLORER_BUTTON) .first() .click(); } diff --git a/cypress-tests/cypress/pageobjects/ide/ProjectTree.ts b/cypress-tests/cypress/pageobjects/ide/ProjectTree.ts index b4eaa26213..86d79ec109 100644 --- a/cypress-tests/cypress/pageobjects/ide/ProjectTree.ts +++ b/cypress-tests/cypress/pageobjects/ide/ProjectTree.ts @@ -33,14 +33,14 @@ export class ProjectTree { } openProjectTreeContainer() { - cy.get(Ide.FILES_BUTTON) + cy.get(Ide.EXPLORER_BUTTON) .should('be.visible') .then(filesButton => { let isProjectTreeContainerOpened: boolean = filesButton.hasClass("p-mod-current"); //if project tree container is not opened click on "Files" button if (!isProjectTreeContainerOpened) { - this.ide.clickOnFilesButton(); + this.ide.clickOnExplorerButton(); } }).then(() => { this.waitProjectTreeContainer(); @@ -170,8 +170,8 @@ export class ProjectTree { }) } - private doWaitProjectImported(projectName: string, rootSubitem: string, attempts: number, currentAttempt: number, pollingEvery: number): Promise { - return new Promise((resolve, reject) => { + private doWaitProjectImported(projectName: string, rootSubitem: string, attempts: number, currentAttempt: number, pollingEvery: number): PromiseLike { + return new Cypress.Promise((resolve:any, reject:any) => { let rootItem: string = `/${projectName}`; this.expandItem(rootItem) diff --git a/cypress-tests/cypress/utils/workspace/TestWorkspaceUtil.ts b/cypress-tests/cypress/utils/workspace/TestWorkspaceUtil.ts index 7d0ffa5d32..aebfb20aae 100644 --- a/cypress-tests/cypress/utils/workspace/TestWorkspaceUtil.ts +++ b/cypress-tests/cypress/utils/workspace/TestWorkspaceUtil.ts @@ -1,5 +1,3 @@ -import { Promise, resolve, reject } from "bluebird"; - /********************************************************************* * Copyright (c) 2018 Red Hat, Inc. * @@ -15,12 +13,12 @@ import { Promise, resolve, reject } from "bluebird"; export class TestWorkspaceUtil { - private waitRunningStatus(workspaceNamespace: string, workspaceName: string, attempt: number): Promise { + private waitRunningStatus(workspaceNamespace: string, workspaceName: string, attempt: number): PromiseLike { const maximumAttempts: number = Cypress.env("TestWorkspaceUtil.waitRunningStatusAttempts"); const delayBetweenAttempts: number = Cypress.env("TestWorkspaceUtil.waitRunningStatusPollingEvery"); const expectedWorkspaceStatus: string = 'RUNNING'; - return new Promise((resolve, reject) => { + return new Cypress.Promise((resolve:any, reject:any) => { cy.request('GET', `/api/workspace/${workspaceNamespace}:${workspaceName}`) .then(response => { @@ -50,7 +48,7 @@ export class TestWorkspaceUtil { } - waitWorkspaceRunning(workspaceNamespace: string, workspaceName: string): Promise { + waitWorkspaceRunning(workspaceNamespace: string, workspaceName: string): PromiseLike { let attempt: number = 0; return this.waitRunningStatus(workspaceNamespace, workspaceName, attempt) } diff --git a/cypress-tests/package-lock.json b/cypress-tests/package-lock.json index 306d42959a..fc01cfe9c1 100644 --- a/cypress-tests/package-lock.json +++ b/cypress-tests/package-lock.json @@ -3738,6 +3738,11 @@ "loose-envify": "^1.0.0" } }, + "inversify": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/inversify/-/inversify-5.0.1.tgz", + "integrity": "sha512-Ieh06s48WnEYGcqHepdsJUIJUXpwH5o5vodAX+DK2JA/gjy4EbEcQZxw+uFfzysmKjiLXGYwNG3qDZsKVMcINQ==" + }, "invert-kv": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", @@ -5192,6 +5197,11 @@ "readable-stream": "^2.0.2" } }, + "reflect-metadata": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", + "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==" + }, "regenerate": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", diff --git a/cypress-tests/package.json b/cypress-tests/package.json index 07e92a5d57..c542c53e74 100644 --- a/cypress-tests/package.json +++ b/cypress-tests/package.json @@ -18,5 +18,9 @@ "ts-loader": "^5.3.3", "typescript": "^3.3.3", "webpack": "^4.29.3" + }, + "dependencies": { + "inversify": "^5.0.1", + "reflect-metadata": "^0.1.13" } } diff --git a/cypress-tests/tsconfig.json b/cypress-tests/tsconfig.json index 4ee0d5d378..4f69c203b9 100644 --- a/cypress-tests/tsconfig.json +++ b/cypress-tests/tsconfig.json @@ -4,8 +4,12 @@ "noImplicitAny": true, "module": "es6", "target": "es5", + "lib": ["es6", "dom"], "jsx": "react", "allowJs": true, - "types": ["cypress"] + "moduleResolution": "node", + "types": ["cypress", "reflect-metadata"], + "experimentalDecorators": true, + "emitDecoratorMetadata": true } }