Add new test for checking git plus ssh workflow (#15561)
Add new test for checking Git plus SSH workflaw7.20.x
parent
68ac4db40f
commit
3af3742d6f
|
|
@ -49,7 +49,10 @@ pipeline {
|
|||
value: ''),
|
||||
|
||||
booleanParam(name: 'createTestWorkspace',
|
||||
value: true)
|
||||
value: true),
|
||||
|
||||
string(name: 'e2eTestParameters',
|
||||
value: '')
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
@ -83,7 +86,10 @@ pipeline {
|
|||
value: ''),
|
||||
|
||||
booleanParam(name: 'createTestWorkspace',
|
||||
value: false)
|
||||
value: false),
|
||||
|
||||
string(name: 'e2eTestParameters',
|
||||
value: '')
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ pipeline {
|
|||
stages {
|
||||
stage("Run E2E tests") {
|
||||
parallel {
|
||||
stage('Run Happy path tests against nightly build') {
|
||||
stage('Run Happy path tests') {
|
||||
steps {
|
||||
build job: 'basic-MultiUser-Che-check-e2e-tests-against-k8s',
|
||||
parameters: [
|
||||
|
|
@ -48,12 +48,15 @@ pipeline {
|
|||
value: ''),
|
||||
|
||||
booleanParam(name: 'createTestWorkspace',
|
||||
value: true)
|
||||
value: true),
|
||||
|
||||
string(name: 'e2eTestParameters',
|
||||
value: '')
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
stage('Run devfile tests against nightly build') {
|
||||
stage('Run devfile tests') {
|
||||
steps {
|
||||
build job: 'basic-MultiUser-Che-check-e2e-tests-against-k8s',
|
||||
parameters: [
|
||||
|
|
@ -82,10 +85,52 @@ pipeline {
|
|||
value: ''),
|
||||
|
||||
booleanParam(name: 'createTestWorkspace',
|
||||
value: false)
|
||||
value: false),
|
||||
|
||||
string(name: 'e2eTestParameters',
|
||||
value: '')
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
stage('Run Git SSH flow tests') {
|
||||
steps {
|
||||
withCredentials([string(credentialsId: 'e45af3e6-8061-4d02-b187-b1c3bb133d3a', variable: 'github_oauth_token')]) {
|
||||
build job: 'basic-MultiUser-Che-check-e2e-tests-against-k8s',
|
||||
parameters: [
|
||||
string(name: 'cheImageRepo',
|
||||
value: 'quay.io/eclipse/che-server'),
|
||||
|
||||
string(name: 'cheImageTag',
|
||||
value: 'nightly'),
|
||||
|
||||
booleanParam(name: 'buildChe',
|
||||
value: false),
|
||||
|
||||
string(name: 'ghprbSourceBranch',
|
||||
value: 'CRW-391'),
|
||||
|
||||
string(name: 'ghprbPullId',
|
||||
value: ''),
|
||||
|
||||
string(name: 'e2eTestToRun',
|
||||
value: 'test-git-ssh'),
|
||||
|
||||
string(name: 'testWorkspaceDevfileUrl',
|
||||
value: ''),
|
||||
|
||||
text(name: 'customResourceFileContent',
|
||||
value: ''),
|
||||
|
||||
booleanParam(name: 'createTestWorkspace',
|
||||
value: false),
|
||||
|
||||
string(name: 'e2eTestParameters',
|
||||
value: "-e TS_GITHUB_TEST_REPO_ACCESS_TOKEN=$github_oauth_token -e TS_GITHUB_TEST_REPO=chepullreq4/Spoon-Knife -e NODE_TLS_REJECT_UNAUTHORIZED=0")
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,6 +55,9 @@ pipeline {
|
|||
|
||||
string(name: 'ghprbSourceBranch',
|
||||
defaultValue: "master")
|
||||
|
||||
string(name: 'e2eTestParameters',
|
||||
defaultValue: "")
|
||||
}
|
||||
|
||||
stages {
|
||||
|
|
@ -311,7 +314,7 @@ pipeline {
|
|||
-e TS_SELENIUM_MULTIUSER="true" \\
|
||||
-e TS_SELENIUM_USERNAME="admin" \\
|
||||
-e TS_SELENIUM_PASSWORD="admin" \\
|
||||
-e TEST_SUITE="${e2eTestToRun}" \\
|
||||
-e TEST_SUITE="${e2eTestToRun}" ${e2eTestParameters} \\
|
||||
-v ${WORKSPACE}/tests/e2e:/tmp/e2e:Z \\
|
||||
quay.io/eclipse/che-e2e:nightly
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -116,7 +116,10 @@ pipeline {
|
|||
value: "$customResourceFileContent"),
|
||||
|
||||
booleanParam(name: 'createTestWorkspace',
|
||||
value: true)
|
||||
value: true),
|
||||
|
||||
string(name: 'e2eTestParameters',
|
||||
value: '')
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
@ -152,11 +155,53 @@ pipeline {
|
|||
value: "$customResourceFileContent"),
|
||||
|
||||
booleanParam(name: 'createTestWorkspace',
|
||||
value: false)
|
||||
value: false),
|
||||
|
||||
string(name: 'e2eTestParameters',
|
||||
value: '')
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage('Run Git SSH flow tests') {
|
||||
steps {
|
||||
withCredentials([string(credentialsId: 'e45af3e6-8061-4d02-b187-b1c3bb133d3a', variable: 'github_oauth_token')]) {
|
||||
build job: 'basic-MultiUser-Che-check-e2e-tests-against-k8s',
|
||||
parameters: [
|
||||
string(name: 'cheImageRepo',
|
||||
value: 'quay.io/eclipse/che-server'),
|
||||
|
||||
string(name: 'cheImageTag',
|
||||
value: 'nightly'),
|
||||
|
||||
booleanParam(name: 'buildChe',
|
||||
value: false),
|
||||
|
||||
string(name: 'ghprbSourceBranch',
|
||||
value: 'CRW-391'),
|
||||
|
||||
string(name: 'ghprbPullId',
|
||||
value: ''),
|
||||
|
||||
string(name: 'e2eTestToRun',
|
||||
value: 'test-git-ssh'),
|
||||
|
||||
string(name: 'testWorkspaceDevfileUrl',
|
||||
value: ''),
|
||||
|
||||
text(name: 'customResourceFileContent',
|
||||
value: ''),
|
||||
|
||||
booleanParam(name: 'createTestWorkspace',
|
||||
value: false),
|
||||
|
||||
string(name: 'e2eTestParameters',
|
||||
value: "-e TS_GITHUB_TEST_REPO_ACCESS_TOKEN=$github_oauth_token -e TS_GITHUB_TEST_REPO=chepullreq4/Spoon-Knife -e NODE_TLS_REJECT_UNAUTHORIZED=0")
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -89,11 +89,6 @@ export const TestConstants = {
|
|||
*/
|
||||
TS_SELENIUM_PLUGIN_PRECENCE_ATTEMPTS: Number(process.env.TS_SELENIUM_PLUGIN_PRECENCE_ATTEMPTS) || 20,
|
||||
|
||||
/**
|
||||
* Delay in milliseconds between checking plugin precence.
|
||||
*/
|
||||
TS_SELENIUM_PLUGIN_PRECENCE_POLLING: Number(process.env.TS_SELENIUM_PLUGIN_PRECENCE_POLLING) || 2000,
|
||||
|
||||
/**
|
||||
* Name of workspace created for 'Happy Path' scenario validation.
|
||||
*/
|
||||
|
|
@ -228,5 +223,16 @@ export const TestConstants = {
|
|||
/**
|
||||
* Running test suite - possible variants can be found in package.json scripts part.
|
||||
*/
|
||||
TEST_SUITE: process.env.TEST_SUITE || 'test-happy-path'
|
||||
TEST_SUITE: process.env.TEST_SUITE || 'test-happy-path',
|
||||
|
||||
/**
|
||||
* The repo (with README.md in root) and access token are needed for to run test-git-ssh
|
||||
*/
|
||||
TS_GITHUB_TEST_REPO: process.env.TS_GITHUB_TEST_REPO || '',
|
||||
|
||||
/**
|
||||
* Token for a github repository with permissions which allow add the ssh keys
|
||||
*/
|
||||
TS_GITHUB_TEST_REPO_ACCESS_TOKEN: process.env.TS_GITHUB_TEST_REPO_ACCESS_TOKEN || ''
|
||||
|
||||
};
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ class CheReporter extends mocha.reporters.Spec {
|
|||
TS_SELENIUM_WORKSPACE_STATUS_ATTEMPTS: ${TestConstants.TS_SELENIUM_WORKSPACE_STATUS_ATTEMPTS}
|
||||
TS_SELENIUM_WORKSPACE_STATUS_POLLING: ${TestConstants.TS_SELENIUM_WORKSPACE_STATUS_POLLING}
|
||||
TS_SELENIUM_PLUGIN_PRECENCE_ATTEMPTS: ${TestConstants.TS_SELENIUM_PLUGIN_PRECENCE_ATTEMPTS}
|
||||
TS_SELENIUM_PLUGIN_PRECENCE_POLLING: ${TestConstants.TS_SELENIUM_PLUGIN_PRECENCE_POLLING}
|
||||
TS_SELENIUM_PLUGIN_PRECENCE_POLLING: ${TestConstants.TS_SELENIUM_DEFAULT_POLLING}
|
||||
TS_SELENIUM_HAPPY_PATH_WORKSPACE_NAME: ${TestConstants.TS_SELENIUM_HAPPY_PATH_WORKSPACE_NAME}
|
||||
TS_SELENIUM_USERNAME: ${TestConstants.TS_SELENIUM_USERNAME}
|
||||
TS_SELENIUM_PASSWORD: ${TestConstants.TS_SELENIUM_PASSWORD}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@ export * from './utils/requestHandlers/headers/IAuthorizationHeaderHandler';
|
|||
export * from './utils/requestHandlers/tokens/CheMultiuserTokenHandler';
|
||||
export * from './utils/requestHandlers/tokens/ITokenHandler';
|
||||
export * from './utils/ScreenCatcher';
|
||||
export * from './utils/VCS/CheGitApi';
|
||||
export * from './utils/VCS/github/GitHubUtil';
|
||||
export * from './utils/workspace/ITestWorkspaceUtil';
|
||||
export * from './utils/workspace/TestWorkspaceUtil';
|
||||
export * from './utils/workspace/WorkspaceStatus';
|
||||
|
|
@ -28,7 +30,7 @@ export * from './pageobjects/ide/ContextMenu';
|
|||
export * from './pageobjects/ide/DebugView';
|
||||
export * from './pageobjects/ide/DialogWindow';
|
||||
export * from './pageobjects/ide/Editor';
|
||||
export * from './pageobjects/ide/GitHubPlugin';
|
||||
export * from './pageobjects/ide/GitPlugin';
|
||||
export * from './pageobjects/ide/Ide';
|
||||
export * from './pageobjects/ide/NotificationCenter';
|
||||
export * from './pageobjects/ide/OpenWorkspaceWidget';
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ import { Editor } from './pageobjects/ide/Editor';
|
|||
import { TopMenu } from './pageobjects/ide/TopMenu';
|
||||
import { QuickOpenContainer } from './pageobjects/ide/QuickOpenContainer';
|
||||
import { PreviewWidget } from './pageobjects/ide/PreviewWidget';
|
||||
import { GitHubPlugin } from './pageobjects/ide/GitHubPlugin';
|
||||
import { GitPlugin } from './pageobjects/ide/GitPlugin';
|
||||
import { RightToolbar } from './pageobjects/ide/RightToolbar';
|
||||
import { Terminal } from './pageobjects/ide/Terminal';
|
||||
import { DebugView } from './pageobjects/ide/DebugView';
|
||||
|
|
@ -52,7 +52,8 @@ import { CheMultiuserTokenHandler } from './utils/requestHandlers/tokens/CheMult
|
|||
import { CheSingleUserAuthorizationHeaderHandler } from './utils/requestHandlers/headers/CheSingleUserAuthorizationHeaderHandler';
|
||||
import { ITokenHandler } from './utils/requestHandlers/tokens/ITokenHandler';
|
||||
import { CheApiRequestHandler } from './utils/requestHandlers/CheApiRequestHandler';
|
||||
|
||||
import { CheGitApi } from './utils/VCS/CheGitApi';
|
||||
import { GitHubUtil} from './utils/VCS/github/GitHubUtil';
|
||||
|
||||
const e2eContainer: Container = new Container();
|
||||
|
||||
|
|
@ -89,7 +90,7 @@ e2eContainer.bind<Editor>(CLASSES.Editor).to(Editor).inSingletonScope();
|
|||
e2eContainer.bind<TopMenu>(CLASSES.TopMenu).to(TopMenu).inSingletonScope();
|
||||
e2eContainer.bind<QuickOpenContainer>(CLASSES.QuickOpenContainer).to(QuickOpenContainer).inSingletonScope();
|
||||
e2eContainer.bind<PreviewWidget>(CLASSES.PreviewWidget).to(PreviewWidget).inSingletonScope();
|
||||
e2eContainer.bind<GitHubPlugin>(CLASSES.GitHubPlugin).to(GitHubPlugin).inSingletonScope();
|
||||
e2eContainer.bind<GitPlugin>(CLASSES.GitPlugin).to(GitPlugin).inSingletonScope();
|
||||
e2eContainer.bind<RightToolbar>(CLASSES.RightToolbar).to(RightToolbar).inSingletonScope();
|
||||
e2eContainer.bind<Terminal>(CLASSES.Terminal).to(Terminal).inSingletonScope();
|
||||
e2eContainer.bind<DebugView>(CLASSES.DebugView).to(DebugView).inSingletonScope();
|
||||
|
|
@ -102,5 +103,6 @@ e2eContainer.bind<CheLoginPage>(CLASSES.CheLoginPage).to(CheLoginPage).inSinglet
|
|||
e2eContainer.bind<NotificationCenter>(CLASSES.NotificationCenter).to(NotificationCenter).inSingletonScope();
|
||||
e2eContainer.bind<PreferencesHandler>(CLASSES.PreferencesHandler).to(PreferencesHandler).inSingletonScope();
|
||||
e2eContainer.bind<CheApiRequestHandler>(CLASSES.CheApiRequestHandler).to(CheApiRequestHandler).inSingletonScope();
|
||||
|
||||
e2eContainer.bind<CheGitApi>(CLASSES.CheGitApi).to(CheGitApi).inSingletonScope();
|
||||
e2eContainer.bind<GitHubUtil>(CLASSES.GitHubUtil).to(GitHubUtil).inSingletonScope();
|
||||
export { e2eContainer };
|
||||
|
|
|
|||
|
|
@ -44,6 +44,9 @@ const CLASSES = {
|
|||
OpenWorkspaceWidget: 'OpenWorkspaceWidget',
|
||||
ContextMenu: 'ContextMenu',
|
||||
CheLoginPage: 'CheLoginPage',
|
||||
GitHubUtil: 'GitHubUtil',
|
||||
CheGitApi: 'CheGitApi',
|
||||
GitPlugin: 'GitPlugin',
|
||||
TestWorkspaceUtil: 'TestWorkspaceUtil',
|
||||
NotificationCenter: 'NotificationCenter',
|
||||
PreferencesHandler: 'PreferencesHandler',
|
||||
|
|
|
|||
|
|
@ -0,0 +1,7 @@
|
|||
--timeout 2200000
|
||||
--reporter 'dist/driver/CheReporter.js'
|
||||
-u tdd
|
||||
--bail
|
||||
--full-trace
|
||||
--spec dist/tests/e2e/GitSsh.spec.js
|
||||
--require source-map-support/register
|
||||
|
|
@ -14,6 +14,7 @@
|
|||
"test-operatorhub-installation": "./generateIndex.sh && npm run lint && npm run tsc && mocha --opts mocha-che-operatorhub.opts",
|
||||
"test-wkspc-creation-and-ls": "./generateIndex.sh && npm run lint && npm run tsc && mocha --opts mocha-wkspc-creation-and-ls.opts",
|
||||
"test-java-vertx": "./generateIndex.sh && npm run lint && npm run tsc && mocha --opts mocha-java-vertx.opts",
|
||||
"test-git-ssh": "./generateIndex.sh && npm run lint && npm run tsc && mocha --opts mocha-git-ssh.opts",
|
||||
"test-all-devfiles": "./generateIndex.sh && npm run lint && npm run tsc && mocha --opts mocha-all-devfiles.opts",
|
||||
"lint": "tslint --fix -p .",
|
||||
"tsc": "tsc -p ."
|
||||
|
|
@ -35,7 +36,8 @@
|
|||
"ts-node": "^8.0.3",
|
||||
"tslint": "5.10.0",
|
||||
"typed-rest-client": "^1.2.0",
|
||||
"typescript": "^3.4.3"
|
||||
"typescript": "^3.4.3",
|
||||
"@eclipse-che/api": "^7.5.0-SNAPSHOT"
|
||||
},
|
||||
"dependencies": {
|
||||
"inversify": "^5.0.1",
|
||||
|
|
|
|||
|
|
@ -1,85 +0,0 @@
|
|||
import { injectable, inject } from 'inversify';
|
||||
import { CLASSES } from '../../inversify.types';
|
||||
import { DriverHelper } from '../../utils/DriverHelper';
|
||||
import { TestConstants } from '../../TestConstants';
|
||||
import { By, WebElement } from 'selenium-webdriver';
|
||||
import { Ide, RightToolbarButton } from './Ide';
|
||||
import { Logger } from '../../utils/Logger';
|
||||
|
||||
/*********************************************************************
|
||||
* Copyright (c) 2019 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 GitHubPlugin {
|
||||
constructor(@inject(CLASSES.DriverHelper) private readonly driverHelper: DriverHelper,
|
||||
@inject(CLASSES.Ide) private readonly ide: Ide) { }
|
||||
|
||||
async openGitHubPluginContainer(timeout: number = TestConstants.TS_SELENIUM_DEFAULT_TIMEOUT) {
|
||||
Logger.debug('GitHubPlugin.openGitHubPluginContainer');
|
||||
|
||||
const selectedGitButtonLocator: By = By.xpath(Ide.SELECTED_GIT_BUTTON_XPATH);
|
||||
|
||||
await this.ide.waitRightToolbarButton(RightToolbarButton.Git, timeout);
|
||||
const isButtonEnabled: boolean = await this.driverHelper.waitVisibilityBoolean(selectedGitButtonLocator);
|
||||
|
||||
if (!isButtonEnabled) {
|
||||
await this.ide.waitAndClickRightToolbarButton(RightToolbarButton.Git);
|
||||
}
|
||||
|
||||
await this.waitGitHubContainer(timeout);
|
||||
}
|
||||
|
||||
async waitGitHubContainer(timeout: number = TestConstants.TS_SELENIUM_DEFAULT_TIMEOUT) {
|
||||
Logger.debug('GitHubPlugin.waitGitHubContainer');
|
||||
|
||||
const githubContainerLocator: By = By.css('#theia-gitContainer .theia-git-main-container');
|
||||
|
||||
await this.driverHelper.waitVisibility(githubContainerLocator, timeout);
|
||||
}
|
||||
|
||||
async getChangesList(): Promise<string[]> {
|
||||
Logger.debug('GitHubPlugin.getChangesList');
|
||||
|
||||
const gitHubChangesLocator: By = By.xpath('//div[@id=\'theia-gitContainer\']//div[@id=\'unstagedChanges\']//div[contains(@class, \'gitItem\')]');
|
||||
const changesElements: WebElement[] = await this.driverHelper.waitAllPresence(gitHubChangesLocator);
|
||||
const changesCount: number = changesElements.length;
|
||||
let gitHubChanges: string[] = [];
|
||||
|
||||
for (let i = 0; i < changesCount; i++) {
|
||||
const gitHubChangesItemLocator: By = By.xpath(this.getGitHubChangesItemXpathLocator(i));
|
||||
const changesText: string = await this.driverHelper.waitAndGetText(gitHubChangesItemLocator);
|
||||
|
||||
gitHubChanges.push(changesText);
|
||||
}
|
||||
|
||||
return gitHubChanges;
|
||||
}
|
||||
|
||||
async waitChangesPresence(changesText: string, timeout: number = TestConstants.TS_SELENIUM_DEFAULT_TIMEOUT) {
|
||||
Logger.debug(`GitHubPlugin.waitChangesPresence "${changesText}"`);
|
||||
|
||||
await this.driverHelper
|
||||
.getDriver()
|
||||
.wait(async () => {
|
||||
const changes: string[] = await this.getChangesList();
|
||||
const isChangesPresent: boolean = changes.indexOf(changesText) !== -1;
|
||||
|
||||
if (isChangesPresent) {
|
||||
return true;
|
||||
}
|
||||
|
||||
}, timeout);
|
||||
}
|
||||
|
||||
private getGitHubChangesItemXpathLocator(index: number): string {
|
||||
return `(//div[@id='theia-gitContainer']//div[@id='unstagedChanges']//div[contains(@class, 'gitItem')])[${index + 1}]`;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
import { injectable, inject } from 'inversify';
|
||||
import { CLASSES } from '../../inversify.types';
|
||||
import { DriverHelper } from '../../utils/DriverHelper';
|
||||
import { TestConstants } from '../../TestConstants';
|
||||
import { By } from 'selenium-webdriver';
|
||||
import { Logger } from '../../utils/Logger';
|
||||
|
||||
/*********************************************************************
|
||||
* Copyright (c) 2019 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 GitPlugin {
|
||||
private static readonly COMMIT_MESSAGE_TEXTAREA_CSS: string = 'textarea#theia-scm-input-message';
|
||||
|
||||
constructor(@inject(CLASSES.DriverHelper) private readonly driverHelper: DriverHelper) { }
|
||||
|
||||
async openGitPluginContainer(timeout: number = TestConstants.TS_SELENIUM_DEFAULT_TIMEOUT) {
|
||||
Logger.debug('GitPlugin.openGitPluginContainer');
|
||||
|
||||
const sourceControlGitBtnXpathLocator: string = '//li[@id=\'shell-tab-scm-view-container\' and contains(@style, \'height\')]';
|
||||
await this.driverHelper.waitAndClick(By.xpath(sourceControlGitBtnXpathLocator), timeout);
|
||||
await this.waitViewOfContainer(timeout);
|
||||
}
|
||||
|
||||
async waitViewOfContainer(timeout: number = TestConstants.TS_SELENIUM_DEFAULT_TIMEOUT) {
|
||||
Logger.debug('GitPlugin.waitViewOfContainer');
|
||||
|
||||
const gitHubContainerIdLocator: By = By.id('scm-view-container--scm-view');
|
||||
await this.driverHelper.waitVisibility(gitHubContainerIdLocator, timeout);
|
||||
}
|
||||
|
||||
async waitCommitMessageTextArea(timeout: number = TestConstants.TS_SELENIUM_DEFAULT_TIMEOUT) {
|
||||
Logger.debug('GitPlugin.waitCommitMessageTextArea');
|
||||
|
||||
const textAreaCssLocator: By = By.css(GitPlugin.COMMIT_MESSAGE_TEXTAREA_CSS);
|
||||
await this.driverHelper.waitVisibility(textAreaCssLocator, timeout);
|
||||
}
|
||||
|
||||
async typeCommitMessage(commitMessage: string, timeout: number = TestConstants.TS_SELENIUM_DEFAULT_TIMEOUT) {
|
||||
Logger.debug('GitPlugin.typeCommitMessage');
|
||||
|
||||
await this.waitCommitMessageTextArea(timeout);
|
||||
await this.driverHelper.type(By.css(GitPlugin.COMMIT_MESSAGE_TEXTAREA_CSS), commitMessage, timeout);
|
||||
}
|
||||
|
||||
async selectCommandInMoreActionsMenu(commandName: string, timeout: number = TestConstants.TS_SELENIUM_DEFAULT_TIMEOUT) {
|
||||
Logger.debug('GitPlugin.selectCommandInMoreActionsMenu');
|
||||
|
||||
await this.clickOnMoreActions(timeout);
|
||||
await this.driverHelper.waitAndClick(By.xpath(`//li[@data-command]/div[text()=\'${commandName}\']`), timeout);
|
||||
}
|
||||
|
||||
async clickOnMoreActions(timeout: number = TestConstants.TS_SELENIUM_DEFAULT_TIMEOUT) {
|
||||
Logger.debug('GitPlugin.clickOnMoreActions');
|
||||
|
||||
await this.driverHelper.waitAndClick(By.id('__more__'), timeout);
|
||||
}
|
||||
|
||||
async waitChangedFileInChagesList(expectedItem: string, timeout: number = TestConstants.TS_SELENIUM_DEFAULT_TIMEOUT) {
|
||||
Logger.debug('GitPlugin.waitChangedFileInChagesList');
|
||||
|
||||
await this.driverHelper.waitPresence(By.xpath(`//div[@class='changesContainer']//span[text()=\'${expectedItem}\']`), timeout);
|
||||
}
|
||||
|
||||
async waitStagedFileInStagedChanges(expectedStagedItem: string, timeout: number = TestConstants.TS_SELENIUM_DEFAULT_TIMEOUT) {
|
||||
Logger.debug('GitPlugin.waitStagedFileInStagedChanges');
|
||||
|
||||
await this.driverHelper.waitPresence(By.xpath(`//div[text()='Staged Changes']/parent::div/following-sibling::div//span[text()=\'${expectedStagedItem}\']`), timeout);
|
||||
}
|
||||
|
||||
async commitFromScmView(timeout: number = TestConstants.TS_SELENIUM_DEFAULT_TIMEOUT) {
|
||||
Logger.debug('GitPlugin.commitFromScmView');
|
||||
|
||||
await this.driverHelper.waitAndClick(By.id('__scm-view-container_title:__plugin.scm.title.action.git.commit'), timeout);
|
||||
}
|
||||
|
||||
async stageAllChanges(expectedStagedItem: string, timeout: number = TestConstants.TS_SELENIUM_DEFAULT_TIMEOUT) {
|
||||
Logger.debug('GitPlugin.stageAllChanges');
|
||||
|
||||
await this.driverHelper.scrollTo(By.xpath('//div[@class=\'changesContainer\']//div[text()=\'Changes\']'), timeout);
|
||||
await this.driverHelper.waitAndClick(By.xpath('//a[@title=\'Stage All Changes\']'), timeout);
|
||||
await this.waitStagedFileInStagedChanges(expectedStagedItem);
|
||||
}
|
||||
|
||||
async waitDataIsSynchronized(timeout: number = TestConstants.TS_SELENIUM_DEFAULT_TIMEOUT) {
|
||||
Logger.debug('GitPlugin.waitDataIsSynchronized');
|
||||
await this.driverHelper.waitDisappearance(By.xpath(`//div[contains(@title,'Synchronize Changes')]//span[contains(.,' 0↓')]`), timeout);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -18,7 +18,6 @@ import { Logger } from '../../utils/Logger';
|
|||
export class OpenWorkspaceWidget {
|
||||
private static readonly OPEN_WORKSPACE_MAIN_VIEW_XPATH = '//div[@class=\'dialogTitle\']/div[text()=\'Open Workspace\']';
|
||||
private static readonly OPEN_WORKSPACE_OPEN_BTN_CSS = 'div.dialogControl>button.main';
|
||||
private static readonly THEIA_LOCATION_LIST_CSS = 'select.theia-LocationList';
|
||||
|
||||
constructor(@inject(CLASSES.DriverHelper) private readonly driverHelper: DriverHelper) {
|
||||
}
|
||||
|
|
@ -63,12 +62,4 @@ export class OpenWorkspaceWidget {
|
|||
await this.driverHelper.waitAndClick(By.id(`/${currentPath}`));
|
||||
}
|
||||
}
|
||||
|
||||
async selectRootWorkspaceItemInDropDawn(rootProject: string) {
|
||||
Logger.debug(`OpenWorkspaceWidget.selectRootWorkspaceItemInDropDawn "${rootProject}"`);
|
||||
|
||||
await this.driverHelper.waitAndClick(By.css(OpenWorkspaceWidget.THEIA_LOCATION_LIST_CSS));
|
||||
await this.driverHelper.waitAndClick(By.css(`option[value=\'file:///${rootProject}']`));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,8 +36,7 @@ export class QuickOpenContainer {
|
|||
public async clickOnContainerItem(itemText: string, timeout: number = TestConstants.TS_SELENIUM_DEFAULT_TIMEOUT) {
|
||||
Logger.debug(`QuickOpenContainer.clickOnContainerItem "${itemText}"`);
|
||||
|
||||
const quickContainerItemLocator: By = By.xpath(`//div[@class='quick-open-entry']//span[text()='${itemText}']`);
|
||||
|
||||
const quickContainerItemLocator: By = By.css(`div[aria-label="${itemText}, picker"]`);
|
||||
await this.waitContainer(timeout);
|
||||
await this.driverHelper.waitAndClick(quickContainerItemLocator, timeout);
|
||||
await this.waitContainerDisappearance();
|
||||
|
|
@ -45,8 +44,14 @@ export class QuickOpenContainer {
|
|||
|
||||
public async type(text: string) {
|
||||
Logger.debug(`QuickOpenContainer.type "${text}"`);
|
||||
|
||||
await this.driverHelper.enterValue(By.css('.quick-open-input input'), text);
|
||||
}
|
||||
|
||||
public async typeAndSelectSuggestion(text: string, suggestedText: string) {
|
||||
Logger.debug('QuickOpenContainer.typeAndSelectSuggestion');
|
||||
|
||||
await this.driverHelper.type(By.css('div.monaco-inputbox input.input'), text);
|
||||
await this.clickOnContainerItem(suggestedText);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,127 @@
|
|||
/*********************************************************************
|
||||
* Copyright (c) 2019 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 { assert } from 'chai';
|
||||
import { test } from 'mocha';
|
||||
import { e2eContainer } from '../../inversify.config';
|
||||
import { CLASSES, TYPES } from '../../inversify.types';
|
||||
import { Editor } from '../../pageobjects/ide/Editor';
|
||||
import { GitPlugin } from '../../pageobjects/ide/GitPlugin';
|
||||
import { Ide } from '../../pageobjects/ide/Ide';
|
||||
import { ProjectTree } from '../../pageobjects/ide/ProjectTree';
|
||||
import { QuickOpenContainer } from '../../pageobjects/ide/QuickOpenContainer';
|
||||
import { ICheLoginPage } from '../../pageobjects/login/ICheLoginPage';
|
||||
import { TestConstants } from '../../TestConstants';
|
||||
import { DriverHelper } from '../../utils/DriverHelper';
|
||||
import { NameGenerator } from '../../utils/NameGenerator';
|
||||
import { CheGitApi } from '../../utils/VCS/CheGitApi';
|
||||
import { GitHubUtil } from '../../utils/VCS/github/GitHubUtil';
|
||||
import { TestWorkspaceUtil } from '../../utils/workspace/TestWorkspaceUtil';
|
||||
import { TopMenu } from '../../pageobjects/ide/TopMenu';
|
||||
|
||||
|
||||
|
||||
const driverHelper: DriverHelper = e2eContainer.get(CLASSES.DriverHelper);
|
||||
const ide: Ide = e2eContainer.get(CLASSES.Ide);
|
||||
const quickOpenContainer: QuickOpenContainer = e2eContainer.get(CLASSES.QuickOpenContainer);
|
||||
const editor: Editor = e2eContainer.get(CLASSES.Editor);
|
||||
const namespace: string = TestConstants.TS_SELENIUM_USERNAME;
|
||||
const workspaceName: string = TestConstants.TS_SELENIUM_HAPPY_PATH_WORKSPACE_NAME;
|
||||
const topMenu: TopMenu = e2eContainer.get(CLASSES.TopMenu);
|
||||
const loginPage: ICheLoginPage = e2eContainer.get<ICheLoginPage>(TYPES.CheLogin);
|
||||
const gitHubUtils: GitHubUtil = e2eContainer.get<GitHubUtil>(CLASSES.GitHubUtil);
|
||||
const cheGitAPI: CheGitApi = e2eContainer.get(CLASSES.CheGitApi);
|
||||
const projectTree: ProjectTree = e2eContainer.get(CLASSES.ProjectTree);
|
||||
const gitPlugin: GitPlugin = e2eContainer.get(CLASSES.GitPlugin);
|
||||
const testWorkspaceUtils: TestWorkspaceUtil = e2eContainer.get<TestWorkspaceUtil>(TYPES.WorkspaceUtil);
|
||||
|
||||
|
||||
suite('Git with ssh workflow', async () => {
|
||||
const workspacePrefixUrl: string = `${TestConstants.TS_SELENIUM_BASE_URL}/dashboard/#/ide/TestConstants.TS_SELENIUM_USERNAME/`;
|
||||
const wsNameCheckGeneratingKeys = 'checkGeneraringSsh';
|
||||
const wsNameCheckPropagatingKeys = 'checkPropagatingSsh';
|
||||
const committedFile = 'README.md';
|
||||
|
||||
suiteSetup(async function () {
|
||||
const wsConfig = await testWorkspaceUtils.getBaseDevfile();
|
||||
wsConfig.metadata!.name = wsNameCheckGeneratingKeys;
|
||||
await testWorkspaceUtils.createWsFromDevFile(wsConfig);
|
||||
});
|
||||
|
||||
test('Login into workspace and open tree container', async () => {
|
||||
await driverHelper.navigateToUrl(workspacePrefixUrl + wsNameCheckGeneratingKeys);
|
||||
await loginPage.login();
|
||||
await ide.waitWorkspaceAndIde(namespace, workspaceName);
|
||||
await projectTree.openProjectTreeContainer();
|
||||
});
|
||||
|
||||
test('Generate a SSH key', async () => {
|
||||
await topMenu.selectOption('View', 'Find Command...');
|
||||
await quickOpenContainer.typeAndSelectSuggestion('SSH', 'SSH: generate key pair...');
|
||||
await ide.waitNotificationAndClickOnButton('Key pair successfully generated, do you want to view the public key', 'View');
|
||||
await editor.waitEditorOpened('Untitled-0');
|
||||
await editor.waitText('Untitled-0', 'ssh-rsa');
|
||||
});
|
||||
|
||||
|
||||
test('Add a SSH key to GitHub side and clone by ssh link', async () => {
|
||||
const sshName: string = NameGenerator.generate('test-SSH-', 5);
|
||||
const publicSshKey = await cheGitAPI.getPublicSSHKey();
|
||||
await gitHubUtils.addPublicSshKeyToUserAccount(TestConstants.TS_GITHUB_TEST_REPO_ACCESS_TOKEN, sshName, publicSshKey);
|
||||
await cloneTestRepo();
|
||||
|
||||
});
|
||||
|
||||
test('Change commit and push', async function changeCommitAndPushFunc() {
|
||||
const currentDate: string = Date.now().toString();
|
||||
await projectTree.expandPathAndOpenFile('Spoon-Knife', committedFile);
|
||||
await editor.type(committedFile, currentDate + '\n', 1);
|
||||
await gitPlugin.openGitPluginContainer();
|
||||
await gitPlugin.waitChangedFileInChagesList(committedFile);
|
||||
await gitPlugin.stageAllChanges(committedFile);
|
||||
await gitPlugin.waitChangedFileInChagesList(committedFile);
|
||||
await gitPlugin.typeCommitMessage(this.test!.title + currentDate);
|
||||
await gitPlugin.commitFromScmView();
|
||||
await gitPlugin.selectCommandInMoreActionsMenu('Push');
|
||||
await gitPlugin.waitDataIsSynchronized();
|
||||
const rawDataFromFile: string = await gitHubUtils.getRawContentFromFile(TestConstants.TS_GITHUB_TEST_REPO + '/master/' + committedFile);
|
||||
assert.isTrue(rawDataFromFile.includes(currentDate));
|
||||
await testWorkspaceUtils.cleanUpAllWorkspaces();
|
||||
});
|
||||
|
||||
test('Check ssh key in a new workspace', async () => {
|
||||
const data = await testWorkspaceUtils.getBaseDevfile();
|
||||
|
||||
data.metadata!.name = wsNameCheckPropagatingKeys;
|
||||
await testWorkspaceUtils.createWsFromDevFile(data);
|
||||
await driverHelper.navigateToUrl(workspacePrefixUrl + wsNameCheckPropagatingKeys);
|
||||
await ide.waitWorkspaceAndIde(namespace, workspaceName);
|
||||
await projectTree.openProjectTreeContainer();
|
||||
await cloneTestRepo();
|
||||
await projectTree.waitItem('Spoon-Knife');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
suite('Cleanup', async () => {
|
||||
test('Remove test workspace', async () => {
|
||||
await testWorkspaceUtils.cleanUpAllWorkspaces();
|
||||
});
|
||||
});
|
||||
|
||||
async function cloneTestRepo() {
|
||||
const sshLinkToRepo: string = 'git@github.com:' + TestConstants.TS_GITHUB_TEST_REPO + '.git';
|
||||
const confirmMessage = 'Repository URL (Press \'Enter\' to confirm your input or \'Escape\' to cancel)';
|
||||
|
||||
await topMenu.selectOption('View', 'Find Command...');
|
||||
await quickOpenContainer.typeAndSelectSuggestion('clone', 'Git: Clone');
|
||||
await quickOpenContainer.typeAndSelectSuggestion(sshLinkToRepo, confirmMessage);
|
||||
}
|
||||
|
||||
|
|
@ -107,7 +107,6 @@ export class DriverHelper {
|
|||
await this.wait(polling);
|
||||
continue;
|
||||
}
|
||||
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,26 @@
|
|||
import { injectable, inject } from 'inversify';
|
||||
import { CLASSES } from '../../inversify.types';
|
||||
import { CheApiRequestHandler } from '../../utils/requestHandlers/CheApiRequestHandler';
|
||||
|
||||
|
||||
@injectable()
|
||||
export class CheGitApi {
|
||||
static readonly GIT_API_ENTRIPOINT_URL = 'api/ssh/vcs';
|
||||
|
||||
constructor(@inject(CLASSES.CheApiRequestHandler) private readonly processRequestHandler: CheApiRequestHandler) { }
|
||||
|
||||
|
||||
|
||||
public async getPublicSSHKey(): Promise<string> {
|
||||
|
||||
try {
|
||||
const responce = await this.processRequestHandler.get(CheGitApi.GIT_API_ENTRIPOINT_URL);
|
||||
return responce.data[0].publicKey;
|
||||
} catch (error) {
|
||||
console.error('Cannot get public ssh key with API \n' + error);
|
||||
throw error;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
import { injectable } from 'inversify';
|
||||
import axios from 'axios';
|
||||
|
||||
@injectable()
|
||||
export class GitHubUtil {
|
||||
private static readonly GITHUB_API_ENTRIPOINT_URL = 'https://api.github.com/';
|
||||
/**
|
||||
* add public part of ssh key to the defied github account
|
||||
* @param authToken
|
||||
* @param title
|
||||
* @param key
|
||||
*/
|
||||
async addPublicSshKeyToUserAccount(authToken: string, title: string, key: string) {
|
||||
const gitHubApiSshURL: string = GitHubUtil.GITHUB_API_ENTRIPOINT_URL + 'user/keys';
|
||||
const authHeader = { headers: { 'Authorization': 'token ' + authToken, 'Content-Type': 'application/json' } };
|
||||
|
||||
const data = {
|
||||
title: `${title}`,
|
||||
key: `${key}`
|
||||
};
|
||||
|
||||
try { await axios.post(gitHubApiSshURL, JSON.stringify(data), authHeader); } catch (error) {
|
||||
console.error('Cannot add the public key to the GitHub account: ');
|
||||
console.error(error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async getRawContentFromFile(pathToFile: string): Promise<string> {
|
||||
const gitHubContentEntryPointUrl: string = 'https://raw.githubusercontent.com/';
|
||||
const pathToRawContent: string = `${gitHubContentEntryPointUrl}${pathToFile}`;
|
||||
const authorization: string = 'Authorization';
|
||||
const contentType: string = 'Content-Type';
|
||||
|
||||
try {
|
||||
delete axios.defaults.headers.common[authorization];
|
||||
delete axios.defaults.headers.common[contentType];
|
||||
const response = await axios.get(`${gitHubContentEntryPointUrl}${pathToFile}`);
|
||||
return response.data;
|
||||
} catch (error) {
|
||||
console.error('Cannot get content form the raw github content: ' + pathToRawContent);
|
||||
console.error(error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -22,7 +22,7 @@ export class CheApiRequestHandler {
|
|||
return await axios.get(this.assembleUrl(relativeUrl), await this.headerHandler.get());
|
||||
}
|
||||
|
||||
async post(relativeUrl: string, data?: string): Promise<AxiosResponse> {
|
||||
async post(relativeUrl: string, data?: string | any ): Promise<AxiosResponse> {
|
||||
return await axios.post(this.assembleUrl(relativeUrl), data, await this.headerHandler.get());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,39 +8,35 @@
|
|||
* SPDX-License-Identifier: EPL-2.0
|
||||
**********************************************************************/
|
||||
|
||||
import { che } from '@eclipse-che/api';
|
||||
import { TestConstants } from '../../TestConstants';
|
||||
import { injectable, inject } from 'inversify';
|
||||
import { DriverHelper } from '../DriverHelper';
|
||||
import { CLASSES } from '../../inversify.types';
|
||||
import 'reflect-metadata';
|
||||
import { WorkspaceStatus } from './WorkspaceStatus';
|
||||
import { ITestWorkspaceUtil } from './ITestWorkspaceUtil';
|
||||
import axios from 'axios';
|
||||
import querystring from 'querystring';
|
||||
import { error } from 'selenium-webdriver';
|
||||
enum RequestType {
|
||||
GET,
|
||||
POST,
|
||||
DELETE
|
||||
}
|
||||
import { CheApiRequestHandler } from '../requestHandlers/CheApiRequestHandler';
|
||||
import { CLASSES } from '../../inversify.types';
|
||||
|
||||
@injectable()
|
||||
export class TestWorkspaceUtil implements ITestWorkspaceUtil {
|
||||
|
||||
workspaceApiUrl: string = `${TestConstants.TS_SELENIUM_BASE_URL}/api/workspace`;
|
||||
static readonly WORKSPACE_API_URL: string = 'api/workspace';
|
||||
|
||||
constructor(@inject(CLASSES.DriverHelper) private readonly driverHelper: DriverHelper) {
|
||||
|
||||
}
|
||||
constructor(
|
||||
@inject(CLASSES.DriverHelper) private readonly driverHelper: DriverHelper,
|
||||
@inject(CLASSES.CheApiRequestHandler) private readonly processRequestHandler: CheApiRequestHandler
|
||||
) { }
|
||||
|
||||
public async waitWorkspaceStatus(namespace: string, workspaceName: string, expectedWorkspaceStatus: WorkspaceStatus) {
|
||||
const workspaceStatusApiUrl: string = `${this.workspaceApiUrl}/${namespace}:${workspaceName}`;
|
||||
const workspaceStatusApiUrl: string = `${TestWorkspaceUtil.WORKSPACE_API_URL}/${namespace}:${workspaceName}`;
|
||||
const attempts: number = TestConstants.TS_SELENIUM_WORKSPACE_STATUS_ATTEMPTS;
|
||||
const polling: number = TestConstants.TS_SELENIUM_WORKSPACE_STATUS_POLLING;
|
||||
let workspaceStatus: string = '';
|
||||
|
||||
for (let i = 0; i < attempts; i++) {
|
||||
const response = await this.processRequest(RequestType.GET, workspaceStatusApiUrl);
|
||||
const response = await this.processRequestHandler.get(workspaceStatusApiUrl);
|
||||
|
||||
if (response.status !== 200) {
|
||||
await this.driverHelper.wait(polling);
|
||||
|
|
@ -60,12 +56,12 @@ export class TestWorkspaceUtil implements ITestWorkspaceUtil {
|
|||
}
|
||||
|
||||
public async waitPluginAdding(namespace: string, workspaceName: string, pluginName: string) {
|
||||
const workspaceStatusApiUrl: string = `${this.workspaceApiUrl}/${namespace}:${workspaceName}`;
|
||||
const workspaceStatusApiUrl: string = `${TestWorkspaceUtil.WORKSPACE_API_URL}/${namespace}:${workspaceName}`;
|
||||
const attempts: number = TestConstants.TS_SELENIUM_PLUGIN_PRECENCE_ATTEMPTS;
|
||||
const polling: number = TestConstants.TS_SELENIUM_PLUGIN_PRECENCE_POLLING;
|
||||
const polling: number = TestConstants.TS_SELENIUM_DEFAULT_POLLING;
|
||||
|
||||
for (let i = 0; i < attempts; i++) {
|
||||
const response = await this.processRequest(RequestType.GET, workspaceStatusApiUrl);
|
||||
const response = await this.processRequestHandler.get(workspaceStatusApiUrl);
|
||||
|
||||
if (response.status !== 200) {
|
||||
await this.driverHelper.wait(polling);
|
||||
|
|
@ -87,25 +83,34 @@ export class TestWorkspaceUtil implements ITestWorkspaceUtil {
|
|||
}
|
||||
}
|
||||
|
||||
public async getListOfWorkspaceId() {
|
||||
const getAllWorkspacesResponse = await this.processRequest(RequestType.GET, this.workspaceApiUrl);
|
||||
public async getListOfWorkspaceId(): Promise<string[]> {
|
||||
const getAllWorkspacesResponse = await this.processRequestHandler.get(TestWorkspaceUtil.WORKSPACE_API_URL);
|
||||
|
||||
interface IMyObj {
|
||||
id: string;
|
||||
status: string;
|
||||
}
|
||||
|
||||
let stringified = JSON.stringify(getAllWorkspacesResponse.data);
|
||||
let arrayOfWorkspaces = <IMyObj[]>JSON.parse(stringified);
|
||||
let wsList: Array<string> = [];
|
||||
|
||||
for (let entry of arrayOfWorkspaces) {
|
||||
wsList.push(entry.id);
|
||||
}
|
||||
|
||||
return wsList;
|
||||
}
|
||||
|
||||
public async getIdOfRunningWorkspace(wsName: string): Promise<string> {
|
||||
const getWorkspacesByNameResponse = await this.processRequestHandler.get(`${TestWorkspaceUtil.WORKSPACE_API_URL}/:${wsName}`);
|
||||
return getWorkspacesByNameResponse.data.id;
|
||||
|
||||
}
|
||||
|
||||
public async getIdOfRunningWorkspaces(): Promise<Array<string>> {
|
||||
try {
|
||||
const getAllWorkspacesResponse = await this.processRequest(RequestType.GET, this.workspaceApiUrl);
|
||||
const getAllWorkspacesResponse = await this.processRequestHandler.get(TestWorkspaceUtil.WORKSPACE_API_URL);
|
||||
|
||||
interface IMyObj {
|
||||
id: string;
|
||||
|
|
@ -123,97 +128,46 @@ export class TestWorkspaceUtil implements ITestWorkspaceUtil {
|
|||
|
||||
return idOfRunningWorkspace;
|
||||
} catch (err) {
|
||||
console.log(`Getting id of running workspaces failed. URL used: ${this.workspaceApiUrl}`);
|
||||
console.log(`Getting id of running workspaces failed. URL used: ${TestWorkspaceUtil.WORKSPACE_API_URL}`);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
getIdOfRunningWorkspace(namespace: string): Promise<string> {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
|
||||
public async removeWorkspaceById(id: string) {
|
||||
const workspaceIdUrl: string = `${this.workspaceApiUrl}/${id}`;
|
||||
const attempts: number = TestConstants.TS_SELENIUM_PLUGIN_PRECENCE_ATTEMPTS;
|
||||
const polling: number = TestConstants.TS_SELENIUM_PLUGIN_PRECENCE_POLLING;
|
||||
let stopped: Boolean = false;
|
||||
|
||||
for (let i = 0; i < attempts; i++) {
|
||||
|
||||
const getInfoResponse = await this.processRequest(RequestType.GET, workspaceIdUrl);
|
||||
|
||||
if (getInfoResponse.data.status === 'STOPPED') {
|
||||
stopped = true;
|
||||
break;
|
||||
}
|
||||
await this.driverHelper.wait(polling);
|
||||
}
|
||||
|
||||
if (stopped) {
|
||||
try {
|
||||
const deleteWorkspaceResponse = await this.processRequest(RequestType.DELETE, workspaceIdUrl);
|
||||
|
||||
// response code 204: "No Content" expected
|
||||
if (deleteWorkspaceResponse.status !== 204) {
|
||||
throw new Error(`Can not remove workspace. Code: ${deleteWorkspaceResponse.status} Data: ${deleteWorkspaceResponse.data}`);
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(`Removing of workspace failed.`);
|
||||
throw err;
|
||||
}
|
||||
} else {
|
||||
throw new Error(`Can not remove workspace with id ${id}, because it is still not in STOPPED state.`);
|
||||
}
|
||||
}
|
||||
|
||||
async getCheBearerToken(): Promise<string> {
|
||||
let params = {};
|
||||
|
||||
let keycloakUrl = TestConstants.TS_SELENIUM_BASE_URL;
|
||||
if ( keycloakUrl.substr(7, 4).includes('che')) {
|
||||
const keycloakAuthSuffix = '/auth/realms/che/protocol/openid-connect/token';
|
||||
keycloakUrl = keycloakUrl.replace('che', 'keycloak') + keycloakAuthSuffix;
|
||||
params = {
|
||||
client_id: 'che-public',
|
||||
username: TestConstants.TS_SELENIUM_USERNAME,
|
||||
password: TestConstants.TS_SELENIUM_PASSWORD,
|
||||
grant_type: 'password'
|
||||
};
|
||||
} else {
|
||||
const keycloakAuthSuffix = '/auth/realms/codeready/protocol/openid-connect/token';
|
||||
keycloakUrl = keycloakUrl.replace('codeready', 'keycloak') + keycloakAuthSuffix;
|
||||
params = {
|
||||
client_id: 'codeready-public',
|
||||
username: TestConstants.TS_SELENIUM_USERNAME,
|
||||
password: TestConstants.TS_SELENIUM_PASSWORD,
|
||||
grant_type: 'password'
|
||||
};
|
||||
}
|
||||
|
||||
const workspaceIdUrl: string = `${TestWorkspaceUtil.WORKSPACE_API_URL}/${id}`;
|
||||
try {
|
||||
const responseToObtainBearerToken = await axios.post(keycloakUrl, querystring.stringify(params));
|
||||
return responseToObtainBearerToken.data.access_token;
|
||||
const deleteWorkspaceResponse = await this.processRequestHandler.delete(workspaceIdUrl);
|
||||
// response code 204: "No Content" expected
|
||||
if (deleteWorkspaceResponse.status !== 204) {
|
||||
throw new Error(`Can not remove workspace. Code: ${deleteWorkspaceResponse.status} Data: ${deleteWorkspaceResponse.data}`);
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(`Can not get bearer token. URL used: ${keycloakUrl}`);
|
||||
console.log(`Removing of workspace failed.`);
|
||||
throw err;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public async stopWorkspaceById(id: string) {
|
||||
const stopWorkspaceApiUrl: string = `${this.workspaceApiUrl}/${id}/runtime`;
|
||||
try {
|
||||
const stopWorkspaceResponse = await this.processRequest(RequestType.DELETE, stopWorkspaceApiUrl);
|
||||
const stopWorkspaceApiUrl: string = `${TestWorkspaceUtil.WORKSPACE_API_URL}/${id}`;
|
||||
|
||||
try {
|
||||
const stopWorkspaceResponse = await this.processRequestHandler.delete(`${stopWorkspaceApiUrl}/runtime`);
|
||||
// response code 204: "No Content" expected
|
||||
if (stopWorkspaceResponse.status !== 204) {
|
||||
throw new Error(`Can not stop workspace. Code: ${stopWorkspaceResponse.status} Data: ${stopWorkspaceResponse.data}`);
|
||||
}
|
||||
|
||||
for (let i = 0; i < TestConstants.TS_SELENIUM_PLUGIN_PRECENCE_ATTEMPTS; i++) {
|
||||
const wsStatus = await this.processRequestHandler.get(stopWorkspaceApiUrl);
|
||||
if (wsStatus.data.status === 'STOPPED') {
|
||||
break;
|
||||
}
|
||||
await this.driverHelper.wait(TestConstants.TS_SELENIUM_DEFAULT_POLLING);
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(`Stopping workspace failed. URL used: ${stopWorkspaceApiUrl}`);
|
||||
throw err;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public async cleanUpAllWorkspaces() {
|
||||
|
|
@ -225,40 +179,29 @@ export class TestWorkspaceUtil implements ITestWorkspaceUtil {
|
|||
let listAllWorkspaces: Array<string> = await this.getListOfWorkspaceId();
|
||||
|
||||
for (const entry of listAllWorkspaces) {
|
||||
this.removeWorkspaceById(entry);
|
||||
await this.removeWorkspaceById(entry);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
removeWorkspace(namespace: string, workspaceId: string): void {
|
||||
throw new Error('Method not implemented.');
|
||||
async createWsFromDevFile(customTemplate: che.workspace.devfile.Devfile) {
|
||||
try {
|
||||
await this.processRequestHandler.post(TestWorkspaceUtil.WORKSPACE_API_URL + '/devfile', customTemplate);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
stopWorkspace(namespace: string, workspaceId: string): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
async getBaseDevfile(): Promise<che.workspace.devfile.Devfile> {
|
||||
const baseDevfile: che.workspace.devfile.Devfile = {
|
||||
apiVersion: '1.0.0',
|
||||
metadata: {
|
||||
name: 'test-workspace'
|
||||
}
|
||||
};
|
||||
|
||||
async processRequest(reqType: RequestType, url: string) {
|
||||
let response;
|
||||
// maybe this check can be moved somewhere else at the begining so it will be executed just once
|
||||
if (TestConstants.TS_SELENIUM_MULTIUSER === true) {
|
||||
let authorization = 'Authorization';
|
||||
axios.defaults.headers.common[authorization] = 'Bearer ' + await this.getCheBearerToken();
|
||||
}
|
||||
switch (reqType) {
|
||||
case RequestType.GET: {
|
||||
response = await axios.get(url);
|
||||
break;
|
||||
}
|
||||
case RequestType.DELETE: {
|
||||
response = await axios.delete(url);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
throw new Error('Unknown RequestType: ' + reqType);
|
||||
}
|
||||
}
|
||||
return response;
|
||||
return baseDevfile;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue