Merge remote-tracking branch 'upstream/master' into update_traefik

7.30.x
Flavius Lacatusu 2021-04-13 09:13:04 +02:00
commit 96e032a6c0
1218 changed files with 1876 additions and 49863 deletions

3
.github/CODEOWNERS vendored
View File

@ -34,9 +34,6 @@ wsmaster/che-core-api-workspace/** @skabashnyuk @mshaposhnik @metlos @nickboldt
deploy/** @tolusha @nickboldt
deploy/openshift/templates/monitoring/** @skabashnyuk @metlos @nickboldt
# selenium tests
tests/legacy-e2e/** @musienko-maxim @dmytro-ndp @Ohrimenko1988 @rhopp @nickboldt
# e2e tests
tests/e2e/** @musienko-maxim @Ohrimenko1988 @rhopp @nickboldt @Katka92 @ScrewTSW

View File

@ -1,72 +0,0 @@
#!/usr/bin/env bash
# Copyright (c) 2020 Red Hat, Inc.
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Eclipse Public License v1.0
# which accompanies this distribution, and is available at
# http://www.eclipse.org/legal/epl-v10.html
set -ex
source tests/.infra/centos-ci/functional_tests_utils.sh
eval "$(./env-toolkit load -f jenkins-env.json -r ^ghprbPullId)"
export PULL_REQUEST_ID="${ghprbPullId}"
export TAG=PR-${PULL_REQUEST_ID}
function prepareCustomResourcePatchFile() {
cat > /tmp/custom-resource-patch.yaml <<EOL
spec:
server:
cheImageTag: ${TAG}
customCheProperties:
CHE_LIMITS_USER_WORKSPACES_RUN_COUNT: '-1'
CHE_WORKSPACE_AGENT_DEV_INACTIVE__STOP__TIMEOUT__MS: '300000'
auth:
updateAdminPassword: false
openShiftoAuth: false
identityProviderPassword: admin
EOL
cat /tmp/custom-resource-patch.yaml
}
function buildCheServer() {
mvn clean install -Pintegration
bash dockerfiles/che/build.sh --organization:quay.io/eclipse --tag:${TAG} --dockerfile:Dockerfile
}
function pushImageToRegistry() {
docker login -u "${QUAY_ECLIPSE_CHE_USERNAME}" -p "${QUAY_ECLIPSE_CHE_PASSWORD}" "quay.io"
docker push "quay.io/eclipse/che-server:${TAG}"
}
setupEnvs
installDependencies
installDockerCompose
buildCheServer
pushImageToRegistry
installKVM
installAndStartMinishift
prepareCustomResourcePatchFile
installCheCtl
deployCheIntoCluster --che-operator-cr-patch-yaml=/tmp/custom-resource-patch.yaml
seleniumTestsSetup
createIndentityProvider
bash /root/payload/tests/legacy-e2e/che-selenium-test/selenium-tests.sh \
--threads=3 \
--host=${CHE_ROUTE} \
--https \
--port=443 \
--multiuser \
--fail-script-on-failed-tests \
|| IS_TESTS_FAILED=true
echo "=========================== THIS IS POST TEST ACTIONS =============================="
saveSeleniumTestResult
getOpenshiftLogs
archiveArtifacts "che-pullrequests-java-selenium-tests"
if [[ "$IS_TESTS_FAILED" == "true" ]]; then exit 1; fi

View File

@ -385,50 +385,12 @@ function setupEnvs() {
}
function configureGithubTestUser() {
echo "======== Configure GitHub test users ========"
cd /root/payload
mkdir -p che_local_conf_dir
export CHE_LOCAL_CONF_DIR=/root/payload/che_local_conf_dir/
rm -f che_local_conf_dir/selenium.properties
echo "github.username=che6ocpmulti" >> che_local_conf_dir/selenium.properties
echo "github.password=CheMain2017" >> che_local_conf_dir/selenium.properties
echo "github.auxiliary.username=iedexmain1" >> che_local_conf_dir/selenium.properties
echo "github.auxiliary.password=CodenvyMain15" >> che_local_conf_dir/selenium.properties
}
function installDockerCompose() {
echo "Install docker compose"
sudo curl -L "https://github.com/docker/compose/releases/download/1.25.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
}
function seleniumTestsSetup() {
echo "======== Start selenium tests ========"
cd /root/payload
export CHE_INFRASTRUCTURE=openshift
export CHE_OPENSHIFT_PROJECT=eclipse-che
defineCheRoute
mvn clean install -pl :che-selenium-test -am -DskipTests=true -U
configureGithubTestUser
}
function saveSeleniumTestResult() {
mkdir -p /root/payload/report
mkdir -p /root/payload/report/site
cp -r /root/payload/tests/legacy-e2e/che-selenium-test/target/site report
}
function createIndentityProvider() {
CHE_MULTI_USER_GITHUB_CLIENTID_OCP=04cbc0f8172109322223
CHE_MULTI_USER_GITHUB_SECRET_OCP=a0a9b8602bb0916d322223e71b7ed92036563b7a
keycloakPodName=$(oc get pod --namespace=eclipse-che | grep keycloak | awk '{print $1}')
/tmp/oc exec $keycloakPodName --namespace=eclipse-che -- /opt/jboss/keycloak/bin/kcadm.sh create identity-provider/instances -r che -s alias=github -s providerId=github -s enabled=true -s storeToken=true -s addReadTokenRoleOnCreate=true -s 'config.useJwksUrl="true"' -s config.clientId=$CHE_MULTI_USER_GITHUB_CLIENTID_OCP -s config.clientSecret=$CHE_MULTI_USER_GITHUB_SECRET_OCP -s 'config.defaultScope="repo,user,write:public_key"' --no-config --server http://localhost:8080/auth --user admin --password admin --realm master
}
function runDevfileTestSuite() {
defineCheRoute
### Create directory for report

View File

@ -1,58 +0,0 @@
#!/usr/bin/env bash
# Copyright (c) 2018 Red Hat, Inc.
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Eclipse Public License v1.0
# which accompanies this distribution, and is available at
# http://www.eclipse.org/legal/epl-v10.html
set -e
echo "========Starting nigtly test job $(date)========"
source tests/.infra/centos-ci/functional_tests_utils.sh
source .ci/cico_common.sh
function prepareCustomResourcePatchFile() {
cat > /tmp/custom-resource-patch.yaml <<EOL
spec:
server:
customCheProperties:
CHE_LIMITS_USER_WORKSPACES_RUN_COUNT: '-1'
CHE_WORKSPACE_AGENT_DEV_INACTIVE__STOP__TIMEOUT__MS: '300000'
auth:
updateAdminPassword: false
openShiftoAuth: false
identityProviderPassword: admin
EOL
cat /tmp/custom-resource-patch.yaml
}
installKVM
setupEnvs
installDependencies
prepareCustomResourcePatchFile
installCheCtl
installAndStartMinishift
deployCheIntoCluster --che-operator-cr-patch-yaml=/tmp/custom-resource-patch.yaml
createTestUserAndObtainUserToken
installDockerCompose
seleniumTestsSetup
createIndentityProvider
bash tests/legacy-e2e/che-selenium-test/selenium-tests.sh \
--threads=3 \
--host=${CHE_ROUTE} \
--https \
--port=443 \
--multiuser \
--include-tests-under-repair \
--include-flaky-tests \
--fail-script-on-failed-tests \
|| IS_TESTS_FAILED=true
echo "=========================== THIS IS POST TEST ACTIONS =============================="
saveSeleniumTestResult
getOpenshiftLogs
archiveArtifacts "che-nigthly-multiuser-all-test"
if [[ "$IS_TESTS_FAILED" == "true" ]]; then exit 1; fi

View File

@ -1,53 +0,0 @@
#!/usr/bin/env bash
# Copyright (c) 2018 Red Hat, Inc.
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Eclipse Public License v1.0
# which accompanies this distribution, and is available at
# http://www.eclipse.org/legal/epl-v10.html
set -e
echo "========Starting nigtly test job $(date)========"
source tests/.infra/centos-ci/functional_tests_utils.sh
function prepareCustomResourcePatchFile() {
cat > /tmp/custom-resource-patch.yaml <<EOL
spec:
server:
customCheProperties:
CHE_LIMITS_USER_WORKSPACES_RUN_COUNT: '-1'
auth:
updateAdminPassword: false
openShiftoAuth: false
identityProviderPassword: admin
EOL
cat /tmp/custom-resource-patch.yaml
}
setupEnvs
installKVM
installDependencies
installDockerCompose
installAndStartMinishift
installCheCtl
prepareCustomResourcePatchFile
deployCheIntoCluster --che-operator-cr-patch-yaml=/tmp/custom-resource-patch.yaml
seleniumTestsSetup
bash tests/legacy-e2e/che-selenium-test/selenium-tests.sh \
--host=${CHE_ROUTE} \
--https \
--port=443 \
--multiuser \
--threads=1 \
--fail-script-on-failed-tests \
--test=org.eclipse.che.selenium.hotupdate.rolling.** \
|| IS_TESTS_FAILED=true
echo "=========================== THIS IS POST TEST ACTIONS =============================="
saveSeleniumTestResult
getOpenshiftLogs
archiveArtifacts "cico-nightly-hot-update-test"
if [[ "$IS_TESTS_FAILED" == "true" ]]; then exit 1; fi

View File

@ -1,54 +0,0 @@
#!/usr/bin/env bash
# Copyright (c) 2018 Red Hat, Inc.
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Eclipse Public License v1.0
# which accompanies this distribution, and is available at
# http://www.eclipse.org/legal/epl-v10.html
set -x
echo "========Starting nigtly test job $(date)========"
./tests/.infra/centos-ci/nightly/
source tests/.infra/centos-ci/functional_tests_utils.sh
function prepareCustomResourcePatchFile() {
cat > /tmp/custom-resource-patch.yaml <<EOL
spec:
server:
customCheProperties:
CHE_LIMITS_USER_WORKSPACES_RUN_COUNT: '-1'
CHE_WORKSPACE_AGENT_DEV_INACTIVE__STOP__TIMEOUT__MS: '300000'
auth:
updateAdminPassword: false
openShiftoAuth: false
identityProviderPassword: admin
EOL
cat /tmp/custom-resource-patch.yaml
}
setupEnvs
installKVM
installDependencies
installCheCtl
installAndStartMinishift
prepareCustomResourcePatchFile
deployCheIntoCluster --che-operator-cr-patch-yaml=/tmp/custom-resource-patch.yaml
createTestUserAndObtainUserToken
installDockerCompose
seleniumTestsSetup
createIndentityProvider
bash tests/legacy-e2e/che-selenium-test/selenium-tests.sh \
--threads=3 \
--host=${CHE_ROUTE} \
--https \
--port=443 \
--multiuser \
--fail-script-on-failed-tests \
|| IS_TESTS_FAILED=true
echo "=========================== THIS IS POST TEST ACTIONS =============================="
saveSeleniumTestResult
getOpenshiftLogs
archiveArtifacts "che-nigthly-multiuser-stable-test"
if [[ "$IS_TESTS_FAILED" == "true" ]]; then exit 1; fi

View File

@ -1,62 +0,0 @@
#!/usr/bin/env bash
# Copyright (c) 2020 Red Hat, Inc.
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Eclipse Public License v1.0
# which accompanies this distribution, and is available at
# http://www.eclipse.org/legal/epl-v10.html
set -e
set +x
source tests/.infra/centos-ci/functional_tests_utils.sh
function prepareCustomResourcePatchFile() {
cat > /tmp/custom-resource-patch.yaml <<EOL
spec:
server:
customCheProperties:
CHE_LIMITS_USER_WORKSPACES_RUN_COUNT: '-1'
CHE_WORKSPACE_AGENT_DEV_INACTIVE__STOP__TIMEOUT__MS: '180000'
auth:
openShiftoAuth: true
updateAdminPassword: false
identityProviderPassword: admin
EOL
cat /tmp/custom-resource-patch.yaml
}
setupEnvs
installKVM
installDependencies
installDockerCompose
installAndStartMinishift
prepareCustomResourcePatchFile
installCheCtl
deployCheIntoCluster --che-operator-cr-patch-yaml=/tmp/custom-resource-patch.yaml
seleniumTestsSetup
export OPENSHIFT_USERNAME=developer
export OPENSHIFT_PASSWORD=123
export OPENSHIFT_REGULAR_USERNAME=developer
export OPENSHIFT_REGULAR_PASSWORD=123
export OPENSHIFT_REGULAR_EMAIL=${OPENSHIFT_REGULAR_USERNAME}@1.com
export TEST_USER_NAME=admin
export CHE_TESTUSER_NAME=${TEST_USER_NAME}
export CHE_TESTUSER_PASSWORD=admin
export CHE_TESTUSER_EMAIL=${TEST_USER_NAME}@admin.com
bash tests/legacy-e2e/che-selenium-test/selenium-tests.sh \
--threads=3 \
--host=${CHE_ROUTE} \
--https \
--port=443 \
--multiuser \
--fail-script-on-failed-tests \
|| IS_TESTS_FAILED=true
echo "=========================== THIS IS POST TEST ACTIONS =============================="
saveSeleniumTestResult
getOpenshiftLogs
archiveArtifacts "nightly-ocp-oauth-test"
if [[ "$IS_TESTS_FAILED" == "true" ]]; then exit 1; fi

View File

@ -1,23 +0,0 @@
#!/usr/bin/env bash
# Copyright (c) 2018 Red Hat, Inc.
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Eclipse Public License v1.0
# which accompanies this distribution, and is available at
# http://www.eclipse.org/legal/epl-v10.html
set -x
source tests/.infra/centos-ci/functional_tests_utils.sh
source tests/.infra/centos-ci/release/release_function_util.sh
setupEnvs
installKVM
installDependencies
installAndStartMinishift
prepareCustomResourcePatchFile false
installCheCtl stable
deployCheIntoCluster --che-operator-cr-patch-yaml=/tmp/custom-resource-patch.yaml
runDevfileTestSuite
echo "=========================== THIS IS POST TEST ACTIONS =============================="
getOpenshiftLogs
archiveArtifacts "release-devfile-test"
if [[ "$IS_TESTS_FAILED" == "true" ]]; then exit 1; fi

View File

@ -1,26 +0,0 @@
#!/usr/bin/env bash
# Copyright (c) 2020 Red Hat, Inc.
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Eclipse Public License v1.0
# which accompanies this distribution, and is available at
# http://www.eclipse.org/legal/epl-v10.html
set -e
set +x
source tests/.infra/centos-ci/functional_tests_utils.sh
source tests/.infra/centos-ci/release/release_function_util.sh
# It needs to implement the patch of 'devfile' yaml to appropriate release tags images
setupEnvs
installKVM
installDependencies
installAndStartMinishift
prepareCustomResourcePatchFile false
installCheCtl stable
deployCheIntoCluster --che-operator-cr-patch-yaml=/tmp/custom-resource-patch.yaml
createTestUserAndObtainUserToken
createTestWorkspaceAndRunTest --devfile=https://raw.githubusercontent.com/eclipse/che/cico-release-test/tests/e2e/files/happy-path/happy-path-workspace.yaml
getOpenshiftLogs
archiveArtifacts "release-multiuser-happy-path-test"
if [[ "$IS_TESTS_FAILED" == "true" ]]; then exit 1; fi

View File

@ -1,38 +0,0 @@
#!/usr/bin/env bash
# Copyright (c) 2020 Red Hat, Inc.
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Eclipse Public License v1.0
# which accompanies this distribution, and is available at
# http://www.eclipse.org/legal/epl-v10.html
set -e
set +x
source tests/.infra/centos-ci/functional_tests_utils.sh
source tests/.infra/centos-ci/release/release_function_util.sh
setupEnvs
installDependencies
installDockerCompose
installKVM
installAndStartMinishift
prepareCustomResourcePatchFile false
installCheCtl stable
deployCheIntoCluster --che-operator-cr-patch-yaml=/tmp/custom-resource-patch.yaml
createIndentityProvider
seleniumTestsSetup
bash /root/payload/tests/legacy-e2e/che-selenium-test/selenium-tests.sh \
--threads=3 \
--host=${CHE_ROUTE} \
--https \
--port=443 \
--multiuser \
--fail-script-on-failed-tests \
|| IS_TESTS_FAILED=true
echo "=========================== THIS IS POST TEST ACTIONS =============================="
saveSeleniumTestResult
getOpenshiftLogs
archiveArtifacts "release-multiuser-integration-tests"
if [[ "$IS_TESTS_FAILED" == "true" ]]; then exit 1; fi

View File

@ -1,37 +0,0 @@
#!/usr/bin/env bash
# Copyright (c) 2020 Red Hat, Inc.
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Eclipse Public License v1.0
# which accompanies this distribution, and is available at
# http://www.eclipse.org/legal/epl-v10.html
set -e
set +x
source tests/.infra/centos-ci/functional_tests_utils.sh
source tests/.infra/centos-ci/release/release_function_util.sh
setupEnvs
installDependencies
installDockerCompose
installKVM
installAndStartMinishift
prepareCustomResourcePatchFile true
installCheCtl stable
deployCheIntoCluster --che-operator-cr-patch-yaml=/tmp/custom-resource-patch.yaml
seleniumTestsSetup
bash tests/legacy-e2e/che-selenium-test/selenium-tests.sh \
--threads=1 \
--host=${CHE_ROUTE} \
--https \
--port=443 \
--multiuser \
--test=org.eclipse.che.selenium.site.ocpoauth.** \
--fail-script-on-failed-tests \
|| IS_TESTS_FAILED=true
echo "=========================== THIS IS POST TEST ACTIONS =============================="
saveSeleniumTestResult
getOpenshiftLogs
archiveArtifacts "release-ocp-oauth-test"
if [[ "$IS_TESTS_FAILED" == "true" ]]; then exit 1; fi

View File

@ -1,37 +0,0 @@
#!/usr/bin/env bash
# Copyright (c) 2020 Red Hat, Inc.
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Eclipse Public License v1.0
# which accompanies this distribution, and is available at
# http://www.eclipse.org/legal/epl-v10.html
set -e
set +x
source tests/.infra/centos-ci/functional_tests_utils.sh
source tests/.infra/centos-ci/release/release_function_util.sh
setupEnvs
installDependencies
installDockerCompose
installKVM
installAndStartMinishift
prepareCustomResourcePatchFile false
installCheCtl stable
deployCheIntoCluster --che-operator-cr-patch-yaml=/tmp/custom-resource-patch.yaml
seleniumTestsSetup
bash tests/legacy-e2e/che-selenium-test/selenium-tests.sh \
--threads=1 \
--host=${CHE_ROUTE} \
--https \
--port=443 \
--multiuser \
--test=org.eclipse.che.selenium.hotupdate.rolling.** \
--fail-script-on-failed-tests \
|| IS_TESTS_FAILED=true
echo "=========================== THIS IS POST TEST ACTIONS =============================="
saveSeleniumTestResult
getOpenshiftLogs
archiveArtifacts "release-rolling-strategy-test"
if [[ "$IS_TESTS_FAILED" == "true" ]]; then exit 1; fi

View File

@ -1,24 +0,0 @@
#!/usr/bin/env bash
# Copyright (c) 2020 Red Hat, Inc.
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Eclipse Public License v1.0
# which accompanies this distribution, and is available at
# http://www.eclipse.org/legal/epl-v10.html
function prepareCustomResourcePatchFile() {
cat > /tmp/custom-resource-patch.yaml <<EOL
spec:
server:
customCheProperties:
CHE_LIMITS_USER_WORKSPACES_RUN_COUNT: '-1'
CHE_WORKSPACE_AGENT_DEV_INACTIVE__STOP__TIMEOUT__MS: '300000'
auth:
openShiftoAuth: $1
updateAdminPassword: false
identityProviderPassword: admin
EOL
cat /tmp/custom-resource-patch.yaml
}

View File

@ -6,6 +6,7 @@ export * from './TimeoutConstants';
export * from './driver/ChromeDriver';
export * from './driver/IDriver';
export * from './utils/BrowserTabsUtil';
export * from './utils/DriverHelper';
export * from './utils/Logger';
export * from './utils/PreferencesHandler';
@ -22,8 +23,8 @@ export * from './utils/workspace/ITestWorkspaceUtil';
export * from './utils/WorkspaceNameHandler';
export * from './utils/workspace/TestWorkspaceUtil';
export * from './utils/workspace/WorkspaceStatus';
export * from './pageobjects/dashboard/CreateWorkspace';
export * from './pageobjects/dashboard/Dashboard';
export * from './pageobjects/dashboard/GetStarted';
export * from './pageobjects/dashboard/workspace-details/WorkspaceDetailsPlugins';
export * from './pageobjects/dashboard/workspace-details/WorkspaceDetails';
export * from './pageobjects/dashboard/Workspaces';
@ -57,4 +58,4 @@ export * from './pageobjects/openshift/OcpLoginPage';
export * from './testsLibrary/CodeExecutionTests';
export * from './testsLibrary/LsTests';
export * from './testsLibrary/ProjectAndFileTests';
export * from './testsLibrary/WorksapceHandlingTests';
export * from './testsLibrary/WorkspaceHandlingTests';

View File

@ -52,7 +52,7 @@ 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';
import { GetStarted } from './pageobjects/dashboard/GetStarted';
import { CreateWorkspace } from './pageobjects/dashboard/CreateWorkspace';
import { OpenshiftPlugin } from './pageobjects/ide/OpenshiftPlugin';
import { OpenDialogWidget } from './pageobjects/ide/OpenDialogWidget';
import { UpdateAccountInformationPage } from './pageobjects/login/UpdateAccountInformationPage';
@ -111,7 +111,7 @@ e2eContainer.bind<CheApiRequestHandler>(CLASSES.CheApiRequestHandler).to(CheApiR
e2eContainer.bind<CheGitApi>(CLASSES.CheGitApi).to(CheGitApi);
e2eContainer.bind<GitHubUtil>(CLASSES.GitHubUtil).to(GitHubUtil);
e2eContainer.bind<OpenshiftPlugin>(CLASSES.OpenshiftPlugin).to(OpenshiftPlugin);
e2eContainer.bind<GetStarted>(CLASSES.GetStarted).to(GetStarted);
e2eContainer.bind<CreateWorkspace>(CLASSES.CreateWorkspace).to(CreateWorkspace);
e2eContainer.bind<OpenDialogWidget>(CLASSES.OpenDialogWidget).to(OpenDialogWidget);
e2eContainer.bind<UpdateAccountInformationPage>(CLASSES.UpdateAccountInformationPage).to(UpdateAccountInformationPage);
e2eContainer.bind<KubernetesPlugin>(CLASSES.KubernetesPlugin).to(KubernetesPlugin);

View File

@ -51,7 +51,7 @@ const CLASSES = {
NotificationCenter: 'NotificationCenter',
PreferencesHandler: 'PreferencesHandler',
CheApiRequestHandler: 'CheApiRequestHandler',
GetStarted: 'GetStarted',
CreateWorkspace: 'CreateWorkspace',
OpenDialogWidget: 'OpenDialogWidget',
UpdateAccountInformationPage: 'UpdateAccountInformationPage',
KubernetesPlugin: 'KubernetesPlugin',

View File

@ -16,11 +16,11 @@ import { Logger } from '../../utils/Logger';
import { TimeoutConstants } from '../../TimeoutConstants';
@injectable()
export class GetStarted {
export class CreateWorkspace {
constructor(@inject(CLASSES.DriverHelper) private readonly driverHelper: DriverHelper) { }
async waitTitleContains(expectedText: string, timeout: number = TimeoutConstants.TS_COMMON_DASHBOARD_WAIT_TIMEOUT) {
Logger.debug(`GetStarted.waitTitleContains text: "${expectedText}"`);
Logger.debug(`CreateWorkspace.waitTitleContains text: "${expectedText}"`);
const pageTitleLocator: By = By.xpath(`//h1[contains(text(), '${expectedText}')]`);
@ -28,13 +28,13 @@ export class GetStarted {
}
async waitPage(timeout: number = TimeoutConstants.TS_SELENIUM_LOAD_PAGE_TIMEOUT) {
Logger.debug('GetStarted.waitPage');
Logger.debug('CreateWorkspace.waitPage');
await this.waitTitleContains('Getting Started', timeout);
}
async waitSample(sampleName: string, timeout: number = TimeoutConstants.TS_COMMON_DASHBOARD_WAIT_TIMEOUT) {
Logger.debug(`GetStarted.waitSample sampleName: "${sampleName}"`);
Logger.debug(`CreateWorkspace.waitSample sampleName: "${sampleName}"`);
const sampleLocator: By = this.getSampleLocator(sampleName);
@ -42,7 +42,7 @@ export class GetStarted {
}
async clickOnSample(sampleName: string, timeout: number = TimeoutConstants.TS_CLICK_DASHBOARD_ITEM_TIMEOUT) {
Logger.debug(`GetStarted.clickOnSample sampleName: "${sampleName}"`);
Logger.debug(`CreateWorkspace.clickOnSample sampleName: "${sampleName}"`);
const sampleLocator: By = this.getSampleLocator(sampleName);
@ -50,7 +50,7 @@ export class GetStarted {
}
private getSampleLocator(sampleName: string): By {
Logger.trace(`GetStarted.getSampleLocator sampleName: ${sampleName}`);
Logger.trace(`CreateWorkspace.getSampleLocator sampleName: ${sampleName}`);
return By.xpath(`//article[contains(@class, 'sample-card')]//div[text()='${sampleName}']`);
}

View File

@ -19,8 +19,7 @@ import { Logger } from '../../utils/Logger';
@injectable()
export class Dashboard {
private static readonly WORKSPACES_BUTTON_XPATH: string = `//div[@id='page-sidebar']//a[text()='Workspaces']`;
private static readonly GET_STARTED_BUTTON_XPATH: string = `//div[@id='page-sidebar']//a[text()='Get Started']`;
private static readonly WORKSPACES_BUTTON_XPATH: string = `//div[@id='page-sidebar']//a[contains(text(), 'Workspaces (')]`;
private static readonly CREATE_WORKSPACE_BUTTON_XPATH: string = `//div[@id='page-sidebar']//a[text()='Create Workspace']`;
private static readonly LOADER_PAGE_CSS: string = '.main-page-loader';
@ -79,7 +78,6 @@ export class Dashboard {
Logger.debug('Dashboard.waitPage');
await this.driverHelper.waitVisibility(By.xpath(Dashboard.WORKSPACES_BUTTON_XPATH), timeout);
await this.driverHelper.waitVisibility(By.xpath(Dashboard.GET_STARTED_BUTTON_XPATH), timeout);
await this.driverHelper.waitVisibility(By.xpath(Dashboard.CREATE_WORKSPACE_BUTTON_XPATH), timeout);
}
@ -95,12 +93,6 @@ export class Dashboard {
await this.driverHelper.waitAndClick(By.xpath(Dashboard.CREATE_WORKSPACE_BUTTON_XPATH), timeout);
}
async clickGetStartedButton(timeout: number = TimeoutConstants.TS_CLICK_DASHBOARD_ITEM_TIMEOUT) {
Logger.debug('Dashboard.clickGetStartedButton');
await this.driverHelper.waitAndClick(By.xpath(Dashboard.GET_STARTED_BUTTON_XPATH), timeout);
}
async waitLoader(timeout: number = TimeoutConstants.TS_WAIT_LOADER_PRESENCE_TIMEOUT) {
Logger.debug('Dashboard.waitLoader');

View File

@ -9,7 +9,7 @@
**********************************************************************/
import 'reflect-metadata';
import * as projectAndFileTests from '../../testsLibrary/ProjectAndFileTests';
import * as workspaceHandling from '../../testsLibrary/WorksapceHandlingTests';
import * as workspaceHandling from '../../testsLibrary/WorkspaceHandlingTests';
import * as commonLsTests from '../../testsLibrary/LsTests';
import * as codeExecutionTests from '../../testsLibrary/CodeExecutionTests';
import { e2eContainer } from '../../inversify.config';

View File

@ -10,7 +10,7 @@
import 'reflect-metadata';
import { WorkspaceNameHandler} from '../..';
import * as projectAndFileTests from '../../testsLibrary/ProjectAndFileTests';
import * as workspaceHandling from '../../testsLibrary/WorksapceHandlingTests';
import * as workspaceHandling from '../../testsLibrary/WorkspaceHandlingTests';
const workspaceSampleName: string = 'console-java-simple';
const workspaceRootFolderName: string = 'src';

View File

@ -12,7 +12,7 @@ import { WorkspaceNameHandler, Editor, CLASSES } from '../..';
import { e2eContainer } from '../../inversify.config';
import * as projectAndFileTests from '../../testsLibrary/ProjectAndFileTests';
import * as commonLsTests from '../../testsLibrary/LsTests';
import * as workspaceHandling from '../../testsLibrary/WorksapceHandlingTests';
import * as workspaceHandling from '../../testsLibrary/WorkspaceHandlingTests';
import * as codeExecutionTests from '../../testsLibrary/CodeExecutionTests';
const editor: Editor = e2eContainer.get(CLASSES.Editor);

View File

@ -13,7 +13,7 @@ import 'reflect-metadata';
import * as codeExecutionHelper from '../../testsLibrary/CodeExecutionTests';
import * as commonLsTests from '../../testsLibrary/LsTests';
import * as projectManager from '../../testsLibrary/ProjectAndFileTests';
import * as workspaceHandling from '../../testsLibrary/WorksapceHandlingTests';
import * as workspaceHandling from '../../testsLibrary/WorkspaceHandlingTests';
import { Logger } from '../../utils/Logger';
import { PreferencesHandler } from '../../utils/PreferencesHandler';

View File

@ -11,7 +11,7 @@ import 'reflect-metadata';
import { WorkspaceNameHandler} from '../..';
import * as projectAndFileTests from '../../testsLibrary/ProjectAndFileTests';
import * as commonLsTests from '../../testsLibrary/LsTests';
import * as workspaceHandling from '../../testsLibrary/WorksapceHandlingTests';
import * as workspaceHandling from '../../testsLibrary/WorkspaceHandlingTests';
import * as codeExecutionTests from '../../testsLibrary/CodeExecutionTests';
const workspaceSampleName: string = 'console-java-simple';

View File

@ -11,7 +11,7 @@ import 'reflect-metadata';
import { WorkspaceNameHandler } from '../..';
import * as projectAndFileTests from '../../testsLibrary/ProjectAndFileTests';
import * as commonLsTests from '../../testsLibrary/LsTests';
import * as workspaceHandling from '../../testsLibrary/WorksapceHandlingTests';
import * as workspaceHandling from '../../testsLibrary/WorkspaceHandlingTests';
import * as codeExecutionTests from '../../testsLibrary/CodeExecutionTests';
const stack: string = 'Java Spring Boot';

View File

@ -9,7 +9,7 @@
**********************************************************************/
import 'reflect-metadata';
import * as projectAndFileTests from '../../testsLibrary/ProjectAndFileTests';
import * as workspaceHandling from '../../testsLibrary/WorksapceHandlingTests';
import * as workspaceHandling from '../../testsLibrary/WorkspaceHandlingTests';
import * as commonLsTests from '../../testsLibrary/LsTests';
import * as codeExecutionTests from '../../testsLibrary/CodeExecutionTests';
import { WorkspaceNameHandler } from '../..';

View File

@ -12,7 +12,7 @@ import 'reflect-metadata';
import * as codeExecutionHelper from '../../testsLibrary/CodeExecutionTests';
import * as commonLsTests from '../../testsLibrary/LsTests';
import * as projectManager from '../../testsLibrary/ProjectAndFileTests';
import * as workspaceHandling from '../../testsLibrary/WorksapceHandlingTests';
import * as workspaceHandling from '../../testsLibrary/WorkspaceHandlingTests';
const workspaceStack: string = 'NodeJS Express Web Application';
const workspaceSampleName: string = 'nodejs-web-app';

View File

@ -9,7 +9,7 @@
**********************************************************************/
import 'reflect-metadata';
import * as projectAndFileTests from '../../testsLibrary/ProjectAndFileTests';
import * as workspaceHandling from '../../testsLibrary/WorksapceHandlingTests';
import * as workspaceHandling from '../../testsLibrary/WorkspaceHandlingTests';
import * as commonLsTests from '../../testsLibrary/LsTests';
import * as codeExecutionTests from '../../testsLibrary/CodeExecutionTests';
import { e2eContainer } from '../../inversify.config';

View File

@ -13,7 +13,7 @@ import * as codeExecutionHelper from '../../testsLibrary/CodeExecutionTests';
import * as projectManager from '../../testsLibrary/ProjectAndFileTests';
import * as commonLsTests from '../../testsLibrary/LsTests';
import * as projectAndFileTests from '../../testsLibrary/ProjectAndFileTests';
import * as workspaceHandling from '../../testsLibrary/WorksapceHandlingTests';
import * as workspaceHandling from '../../testsLibrary/WorkspaceHandlingTests';
const workspaceStack: string = 'Python';
const workspaceSampleName: string = 'python-hello-world';

View File

@ -10,7 +10,7 @@
import { WorkspaceNameHandler } from '../..';
import 'reflect-metadata';
import * as codeExecutionHelper from '../../testsLibrary/CodeExecutionTests';
import * as workspaceHandling from '../../testsLibrary/WorksapceHandlingTests';
import * as workspaceHandling from '../../testsLibrary/WorkspaceHandlingTests';
import * as projectManager from '../../testsLibrary/ProjectAndFileTests';
const workspaceStack: string = 'Python Django';

View File

@ -11,7 +11,7 @@ import { WorkspaceNameHandler } from '../..';
import 'reflect-metadata';
import * as codeExecutionHelper from '../../testsLibrary/CodeExecutionTests';
import * as commonLsTests from '../../testsLibrary/LsTests';
import * as workspaceHandling from '../../testsLibrary/WorksapceHandlingTests';
import * as workspaceHandling from '../../testsLibrary/WorkspaceHandlingTests';
import * as projectManager from '../../testsLibrary/ProjectAndFileTests';
const workspaceStack: string = 'Quarkus CLI';

View File

@ -9,7 +9,7 @@
**********************************************************************/
import 'reflect-metadata';
import * as projectAndFileTests from '../../testsLibrary/ProjectAndFileTests';
import * as workspaceHandling from '../../testsLibrary/WorksapceHandlingTests';
import * as workspaceHandling from '../../testsLibrary/WorkspaceHandlingTests';
import * as commonLsTests from '../../testsLibrary/LsTests';
import * as codeExecutionTests from '../../testsLibrary/CodeExecutionTests';
import { WorkspaceNameHandler } from '../..';

View File

@ -13,7 +13,7 @@ import { CLASSES } from '../../inversify.types';
import { TestConstants } from '../../TestConstants';
import { DriverHelper } from '../../utils/DriverHelper';
import { WorkspaceNameHandler } from '../..';
import * as workspaceHandling from '../../testsLibrary/WorksapceHandlingTests';
import * as workspaceHandling from '../../testsLibrary/WorkspaceHandlingTests';
import * as projectAndFileTests from '../../testsLibrary/ProjectAndFileTests';
const driverHelper: DriverHelper = e2eContainer.get(CLASSES.DriverHelper);

View File

@ -13,7 +13,7 @@ import { CLASSES } from '../../inversify.types';
import { TestConstants } from '../../TestConstants';
import { DriverHelper } from '../../utils/DriverHelper';
import { WorkspaceNameHandler } from '../..';
import * as workspaceHandling from '../../testsLibrary/WorksapceHandlingTests';
import * as workspaceHandling from '../../testsLibrary/WorkspaceHandlingTests';
import * as projectAndFileTests from '../../testsLibrary/ProjectAndFileTests';
const driverHelper: DriverHelper = e2eContainer.get(CLASSES.DriverHelper);

View File

@ -13,7 +13,7 @@ import { CLASSES } from '../../inversify.types';
import { TestConstants } from '../../TestConstants';
import { DriverHelper } from '../../utils/DriverHelper';
import { WorkspaceNameHandler } from '../..';
import * as workspaceHandling from '../../testsLibrary/WorksapceHandlingTests';
import * as workspaceHandling from '../../testsLibrary/WorkspaceHandlingTests';
import * as projectAndFileTests from '../../testsLibrary/ProjectAndFileTests';
const driverHelper: DriverHelper = e2eContainer.get(CLASSES.DriverHelper);

View File

@ -13,7 +13,7 @@ import { CLASSES } from '../../inversify.types';
import { TestConstants } from '../../TestConstants';
import { DriverHelper } from '../../utils/DriverHelper';
import { WorkspaceNameHandler } from '../..';
import * as workspaceHandling from '../../testsLibrary/WorksapceHandlingTests';
import * as workspaceHandling from '../../testsLibrary/WorkspaceHandlingTests';
import * as projectAndFileTests from '../../testsLibrary/ProjectAndFileTests';
const driverHelper: DriverHelper = e2eContainer.get(CLASSES.DriverHelper);

View File

@ -9,7 +9,7 @@
**********************************************************************/
import { WorkspaceNameHandler } from '../..';
import 'reflect-metadata';
import * as workspaceHandling from '../../testsLibrary/WorksapceHandlingTests';
import * as workspaceHandling from '../../testsLibrary/WorkspaceHandlingTests';
import { DriverHelper } from '../../utils/DriverHelper';
import { e2eContainer } from '../../inversify.config';
import { CLASSES } from '../../inversify.types';

View File

@ -9,7 +9,7 @@
**********************************************************************/
import { WorkspaceNameHandler } from '../..';
import 'reflect-metadata';
import * as workspaceHandling from '../../testsLibrary/WorksapceHandlingTests';
import * as workspaceHandling from '../../testsLibrary/WorkspaceHandlingTests';
import { DriverHelper } from '../../utils/DriverHelper';
import { e2eContainer } from '../../inversify.config';
import { CLASSES } from '../../inversify.types';

View File

@ -9,7 +9,7 @@
**********************************************************************/
import { WorkspaceNameHandler } from '../..';
import 'reflect-metadata';
import * as workspaceHandling from '../../testsLibrary/WorksapceHandlingTests';
import * as workspaceHandling from '../../testsLibrary/WorkspaceHandlingTests';
import { DriverHelper } from '../../utils/DriverHelper';
import { e2eContainer } from '../../inversify.config';
import { CLASSES } from '../../inversify.types';

View File

@ -9,7 +9,7 @@
**********************************************************************/
import { WorkspaceNameHandler } from '../..';
import 'reflect-metadata';
import * as workspaceHandling from '../../testsLibrary/WorksapceHandlingTests';
import * as workspaceHandling from '../../testsLibrary/WorkspaceHandlingTests';
import { DriverHelper } from '../../utils/DriverHelper';
import { e2eContainer } from '../../inversify.config';
import { CLASSES } from '../../inversify.types';

View File

@ -10,22 +10,22 @@
import { CLASSES, Dashboard } from '..';
import { e2eContainer } from '../inversify.config';
import { GetStarted } from '../pageobjects/dashboard/GetStarted';
import { CreateWorkspace as CreateWorkspace } from '../pageobjects/dashboard/CreateWorkspace';
import { Logger } from '../utils/Logger';
const dashboard: Dashboard = e2eContainer.get(CLASSES.Dashboard);
const getStarted: GetStarted = e2eContainer.get(CLASSES.GetStarted);
const createWorkspace: CreateWorkspace = e2eContainer.get(CLASSES.CreateWorkspace);
export function createAndOpenWorkspace(stack: string) {
test(`Open 'New Workspace' page`, async () => {
Logger.trace(`WorkspaceHandlingTests.createAndOpenWorkspace wait for dashboard`);
await dashboard.waitPage();
Logger.trace(`WorkspaceHandlingTests.createAndOpenWorkspace click get started button`);
await dashboard.clickGetStartedButton();
Logger.trace(`WorkspaceHandlingTests.createAndOpenWorkspace click Create workspace button`);
await dashboard.clickCreateWorkspaceButton();
Logger.trace(`WorkspaceHandlingTests.createAndOpenWorkspace wait for getting started page`);
await getStarted.waitPage();
await createWorkspace.waitPage();
Logger.trace(`WorkspaceHandlingTests.createAndOpenWorkspace click on sample ${stack}`);
await getStarted.clickOnSample(stack);
await createWorkspace.clickOnSample(stack);
});
}

View File

@ -1,995 +0,0 @@
#!/bin/bash
#
# Copyright (c) 2012-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
#
# Contributors:
# Red Hat, Inc. - initial API and implementation
#
getRecommendedThreadCount() {
local threadCount=$MIN_THREAD_COUNT
if [[ "$OSTYPE" == "darwin"* ]]; then
local totalMemory=$(sysctl -a | awk '/hw./' | grep hw.memsize | awk '{print $2}')
if [[ -n "$totalNumber" ]]; then
threadCount=$(( ${totalMemory} / 6000000 ))
fi
else
local freeMemory=$(grep MemFree /proc/meminfo | awk '{print $2}')
if [[ -n "$freeMemory" ]]; then
threadCount=$(( ${freeMemory} / 4000000 ))
fi
fi
if [[ $threadCount < ${MIN_THREAD_COUNT} ]]; then
threadCount=${MIN_THREAD_COUNT}
elif [[ $threadCount > ${MAX_THREAD_COUNT} ]]; then
threadCount=${MAX_THREAD_COUNT}
fi
echo $threadCount
}
detectDockerInterfaceIp() {
docker run --rm --net host eclipse/che-ip:6.19.0
}
initVariables() {
# we need to have at least 2 threads for tests which start several WebDriver instances at once, for example, tests of File Watcher
readonly MIN_THREAD_COUNT=2
# having more than 5 threads doesn't impact on performance significantly
readonly MAX_THREAD_COUNT=5
readonly FAILSAFE_DIR="target/failsafe-reports"
readonly TESTNG_FAILED_SUITE=${FAILSAFE_DIR}"/testng-failed.xml"
readonly FAILSAFE_REPORT="target/site/failsafe-report.html"
readonly SINGLE_TEST_MSG="single test/package"
export CHE_MULTIUSER=${CHE_MULTIUSER:-false}
export CHE_INFRASTRUCTURE=${CHE_INFRASTRUCTURE:-docker}
# CALLER variable contains parent caller script name
# CUR_DIR variable contains the current directory where CALLER is executed
[[ -z ${CALLER+x} ]] && { CALLER=$(basename $0); }
[[ -z ${CUR_DIR+x} ]] && { CUR_DIR=$(cd "$(dirname "$0")"; pwd); }
[[ -z ${API_SUFFIX+x} ]] && { API_SUFFIX="/api/"; }
MODE="grid"
GRID_OPTIONS="-Dgrid.mode=true"
RERUN_ATTEMPTS=0
BROWSER="GOOGLE_CHROME"
WEBDRIVER_VERSION=$(curl -s http://chromedriver.storage.googleapis.com/LATEST_RELEASE)
WEBDRIVER_PORT="9515"
NODE_CHROME_DEBUG_SUFFIX=
THREADS=$(getRecommendedThreadCount)
WORKSPACE_POOL_SIZE=0
ACTUAL_RESULTS=()
COMPARE_WITH_CI=false
PRODUCT_PROTOCOL="http"
PRODUCT_HOST=$(detectDockerInterfaceIp)
PRODUCT_PORT=8080
INCLUDE_TESTS_UNDER_REPAIR=false
INCLUDE_FLAKY_TESTS=false
FAIL_SCRIPT_ON_FAILED_TESTS=false
unset DEBUG_OPTIONS
unset MAVEN_OPTIONS
unset TMP_SUITE_PATH
unset ORIGIN_TESTS_SCOPE
unset TMP_DIR
unset EXCLUDE_PARAM
unset TOTAL_FAILS
}
cleanUpEnvironment() {
if [[ ${MODE} == "grid" ]]; then
stopWebDriver
stopSeleniumDockerContainers
fi
}
checkParameters() {
for var in "$@"; do
if [[ "$var" =~ --web-driver-version=.* ]]; then :
elif [[ "$var" =~ --web-driver-port=[0-9]+$ ]]; then :
elif [[ "$var" == --http ]]; then :
elif [[ "$var" == --https ]]; then :
elif [[ "$var" == --che ]]; then :
elif [[ "$var" =~ --host=.* ]]; then :
elif [[ "$var" =~ --port=.* ]]; then :
elif [[ "$var" =~ --threads=[0-9]+$ ]]; then :
elif [[ "$var" == --rerun ]]; then :
elif [[ "$var" =~ ^[0-9]+$ ]] && [[ $@ =~ --rerun[[:space:]]$var ]]; then :
elif [[ "$var" == --debug ]]; then :
elif [[ "$var" == --all-tests ]]; then
echo "[WARN] '--all-tests' parameter is outdated and is being ignored"
elif [[ "$var" =~ --test=.* ]]; then
local fileName=$(basename $(echo "$var" | sed -e "s/--test=//g"))
find "target/test-classes" | grep "${fileName}.[class|java]" > /dev/null
[[ $? != 0 ]] && {
echo "[TEST] Test "${fileName}" not found";
echo "[TEST] Proper way to use --test parameter:";
echo -e "[TEST] \t--test=DialogAboutTest";
echo -e "[TEST] \t--test=org.eclipse.che.selenium.miscellaneous.DialogAboutTest";
echo -e "[TEST] \t--test=org.eclipse.che.selenium.miscellaneous.**";
exit 1;
}
elif [[ "$var" =~ --suite=.* ]]; then
local suite=$(basename $(echo "$var" | sed -e "s/--suite=//g"))
find "target/test-classes/suites" | grep ${suite} > /dev/null
[[ $? != 0 ]] && {
echo "[TEST] Suite "${suite}" not found";
echo "[TEST] Proper way to use --suite parameter:";
echo -e "[TEST] \t--suite=CheSuite.xml";
exit 1;
}
elif [[ "$var" == --failed-tests ]]; then :
elif [[ "$var" == --regression-tests ]]; then :
elif [[ "$var" =~ -M.* ]]; then :
elif [[ "$var" =~ -P.* ]]; then :
elif [[ "$var" == --help ]]; then :
elif [[ "$var" == --compare-with-ci ]]; then :
elif [[ "$var" =~ ^[0-9]+$ ]] && [[ $@ =~ --compare-with-ci[[:space:]]$var ]]; then :
elif [[ "$var" =~ ^--workspace-pool-size=(auto|[0-9]+)$ ]]; then :
elif [[ "$var" =~ ^-D.* ]]; then :
elif [[ "$var" =~ ^-[[:alpha:]]$ ]]; then :
elif [[ "$var" == --skip-sources-validation ]]; then :
elif [[ "$var" == --multiuser ]]; then :
elif [[ "$var" =~ --exclude=.* ]]; then :
elif [[ "$var" =~ --include-tests-under-repair ]]; then :
elif [[ "$var" =~ --include-flaky-tests ]]; then :
elif [[ "$var" =~ --fail-script-on-failed-tests ]]; then :
else
printHelp
echo "[TEST] Unrecognized or misused parameter "${var}
exit 1
fi
done
}
applyCustomOptions() {
for var in "$@"; do
if [[ "$var" =~ --web-driver-version=.* ]]; then
if [[ ${MODE} == "local" ]]; then
WEBDRIVER_VERSION=$(echo "$var" | sed -e "s/--web-driver-version=//g")
fi
elif [[ "$var" =~ --web-driver-port=.* ]]; then
if [[ ${MODE} == "local" ]]; then
WEBDRIVER_PORT=$(echo "$var" | sed -e "s/--web-driver-port=//g")
fi
elif [[ "$var" == --http ]]; then
PRODUCT_PROTOCOL="http"
elif [[ "$var" == --https ]]; then
PRODUCT_PROTOCOL="https"
elif [[ "$var" =~ --host=.* ]]; then
PRODUCT_HOST=$(echo "$var" | sed -e "s/--host=//g")
elif [[ "$var" =~ --port=.* ]]; then
PRODUCT_PORT=$(echo "$var" | sed -e "s/--port=//g")
elif [[ "$var" =~ --threads=.* ]]; then
THREADS=$(echo "$var" | sed -e "s/--threads=//g")
elif [[ "$var" =~ --workspace-pool-size=.* ]]; then
WORKSPACE_POOL_SIZE=$(echo "$var" | sed -e "s/--workspace-pool-size=//g")
elif [[ "$var" =~ --rerun ]]; then
local rerunAttempts=$(echo $@ | sed 's/.*--rerun\W\+\([0-9]\+\).*/\1/')
if [[ "$rerunAttempts" =~ ^[0-9]+$ ]]; then
RERUN_ATTEMPTS=$rerunAttempts
else
RERUN_ATTEMPTS=1
fi
elif [[ "$var" == --debug ]]; then
DEBUG_OPTIONS="-Dmaven.failsafe.debug"
NODE_CHROME_DEBUG_SUFFIX="-debug"
elif [[ "$var" == --compare-with-ci ]]; then
COMPARE_WITH_CI=true
elif [[ "$var" == --multiuser ]]; then
CHE_MULTIUSER=true
elif [[ "$var" =~ --exclude=.* ]]; then
EXCLUDE_PARAM=$(echo "$var" | sed -e "s/--exclude=//g")
elif [[ "$var" == --include-tests-under-repair ]]; then
INCLUDE_TESTS_UNDER_REPAIR=true
elif [[ "$var" == --include-flaky-tests ]]; then
INCLUDE_FLAKY_TESTS=true
elif [[ "$var" == --fail-script-on-failed-tests ]]; then
FAIL_SCRIPT_ON_FAILED_TESTS=true
fi
done
}
extractMavenOptions() {
for var in "$@"; do
if [[ "$var" =~ ^-D.* ]]; then
MAVEN_OPTIONS="${MAVEN_OPTIONS} $var"
elif [[ "$var" =~ ^-[[:alpha:]]$ ]]; then :
MAVEN_OPTIONS="${MAVEN_OPTIONS} $var"
elif [[ "$var" == "--skip-sources-validation" ]]; then :
MAVEN_OPTIONS="${MAVEN_OPTIONS} -Dskip-enforce -Dskip-validate-sources"
fi
done
}
defineTestsScope() {
for var in "$@"; do
if [[ "$var" =~ --test=.* ]]; then
TESTS_SCOPE="-Dit.test="$(echo "$var" | sed -e "s/--test=//g")
THREADS=1
elif [[ "$var" =~ --suite=.* ]]; then
TESTS_SCOPE="-DrunSuite=target/test-classes/suites/"$(echo "$var" | sed -e "s/--suite=//g")
elif [[ "$var" == --failed-tests ]]; then
generateTestNgFailedReport $(fetchFailedTests)
TESTS_SCOPE="-DrunSuite=${TESTNG_FAILED_SUITE}"
elif [[ "$var" == --regression-tests ]]; then
generateTestNgFailedReport $(findRegressions)
TESTS_SCOPE="-DrunSuite=${TESTNG_FAILED_SUITE}"
fi
done
ORIGIN_TESTS_SCOPE=${TESTS_SCOPE}
}
defineOperationSystemSpecificVariables() {
if [[ "$OSTYPE" == "darwin"* ]]; then
TMP_DIR=$(echo ${TMPDIR})
else
TMP_DIR="/tmp"
fi
}
init() {
BLUE='\033[1;34m'
GREEN='\033[0;32m'
RED='\033[0;31m'
YELLOW='\033[0;33m'
NO_COLOUR='\033[0m'
}
defineRunMode() {
for var in "$@"; do
if [[ "$var" =~ -M.* ]]; then
MODE=$(echo "$var" | sed -e "s/-M//g")
fi
done
if [[ ${MODE} == "grid" ]]; then
WEBDRIVER_PORT="4444"
checkDockerRequirements
checkDockerComposeRequirements
elif [[ ${MODE} == "local" ]]; then
GRID_OPTIONS="-Dgrid.mode=false"
else
echo "[TEST] Unrecognized mode "${MODE}
echo "[TEST] Available modes: -M[local|grid]"
exit 1
fi
}
stopWebDriver() {
if [[ "$OSTYPE" == "darwin"* ]]; then
ps -cf | grep chromedriver | awk '{if(NR>0) print $2}' | while read -r pid; do kill "${pid}" > /dev/null; done
else
ps -fC chromedriver | awk '{if(NR>1) print $2}' | while read -r pid; do kill "${pid}" > /dev/null; done
fi
}
startWebDriver() {
if [[ "$OSTYPE" == "darwin"* ]]; then
curl -s -o ${TMP_DIR}chromedriver_mac64.zip http://chromedriver.storage.googleapis.com/${WEBDRIVER_VERSION}/chromedriver_mac64.zip
unzip -o ${TMP_DIR}chromedriver_mac64.zip -d ${TMP_DIR} > /dev/null
chmod +x ${TMP_DIR}chromedriver
${TMP_DIR}chromedriver --port=9515 --no-sandbox > /dev/null &
else
curl -s -o ${TMP_DIR}/chromedriver_linux64.zip http://chromedriver.storage.googleapis.com/${WEBDRIVER_VERSION}/chromedriver_linux64.zip
unzip -o ${TMP_DIR}/chromedriver_linux64.zip -d ${TMP_DIR} > /dev/null
chmod +x ${TMP_DIR}/chromedriver
${TMP_DIR}/chromedriver --port=9515 --no-sandbox > /dev/null &
fi
}
initRunMode() {
if [[ ${MODE} == "local" ]]; then
startWebDriver
elif [[ ${MODE} == "grid" ]]; then
export NODE_CHROME_DEBUG_SUFFIX
docker-compose -p=selenium up -d > /dev/null
docker-compose -p=selenium scale chromenode=${THREADS} > /dev/null
else
echo "[TEST] Unrecognized mode "${MODE}
exit 1
fi
}
stopSeleniumDockerContainers() {
local containers=$(docker ps -qa --filter="name=selenium_*" | wc -l)
if [[ ${containers} != "0" ]]; then
echo "[TEST] Stopping and removing selenium docker containers..."
docker rm -f $(docker ps -qa --filter="name=selenium_*") > /dev/null
fi
}
checkDockerRequirements() {
command -v docker >/dev/null 2>&1 || {
echo >&2 -e "[TEST] Could not find Docker client, please install it.\n https://docs.docker.com/engine/installation/"
exit 1;
}
}
checkDockerComposeRequirements() {
command -v docker-compose >/dev/null 2>&1 || {
echo >&2 -e "[TEST] Could not find Docker Compose client, please install it.\n https://docs.docker.com/compose/install/"
exit 1;
}
}
checkIfProductIsRun() {
local url=${PRODUCT_PROTOCOL}"://"${PRODUCT_HOST}:${PRODUCT_PORT}${API_SUFFIX};
curl -s -k -X OPTIONS ${url} > /dev/null
if [[ $? != 0 ]]; then
echo "[TEST] "${url}" is down"
exit 1
fi
}
prepareTestSuite() {
local suitePath=${ORIGIN_TESTS_SCOPE:11}
TMP_SUITE_PATH="/tmp/"$(basename "${suitePath}")
rm -f ${TMP_SUITE_PATH}
cp -f ${suitePath} /tmp
TESTS_SCOPE="-DrunSuite=${TMP_SUITE_PATH}"
# set number of threads directly in the suite
sed -i -e "s#thread-count=\"[^\"]*\"#thread-count=\"${THREADS}\"#" "$TMP_SUITE_PATH"
}
printHelp() {
local usage="
Usage: ${CALLER} [-Mmode] [options] [tests scope]
Options:
--http Use 'http' protocol to connect to product
--https Use 'https' protocol to connect to product
--host=<PRODUCT_HOST> Set host where product is deployed
--port=<PRODUCT_PORT> Set port of the product, default is 8080
--multiuser Run tests of Multi User Che
Modes (defines environment to run tests):
-Mlocal All tests will be run in a Web browser on the developer machine.
Recommended if test visualization is needed and for debugging purpose.
Options that go with 'local' mode:
--web-driver-version=<VERSION> To use the specific version of the WebDriver, be default the latest will be used: "${WEBDRIVER_VERSION}"
--web-driver-port=<PORT> To run WebDriver on the specific port, by default: "${WEBDRIVER_PORT}"
--threads=<THREADS> Number of tests that will be run simultaneously. It also means the very same number of
Web browsers will be opened on the developer machine.
Default value is in range [2,5] and depends on available RAM.
-Mgrid (default) All tests will be run in parallel among several docker containers.
One container per thread. Recommended to run test suite.
Options that go with 'grid' mode:
--threads=<THREADS> Number of tests that will be run simultaneously.
Default value is in range [2,5] and depends on available RAM.
Define tests scope:
--test=<TEST_CLASS> Single test/package to run.
For example: '--test=DialogAboutTest', '--test=org.eclipse.che.selenium.git.**'.
--suite=<SUITE> Test suite to run, found ('CheSuite.xml' is default one):
"$(for x in $(ls -1 target/test-classes/suites); do echo " * "$x; done)"
--exclude=<TEST_GROUPS_TO_EXCLUDE> Comma-separated list of test groups to exclude from execution.
For example, use '--exclude=github' to exclude GitHub-related tests.
Handle failing tests:
--failed-tests Rerun failed tests that left after the previous try
--regression-tests Rerun regression tests that left after the previous try
--rerun [ATTEMPTS] Automatically rerun failing tests.
Default attempts number is 1.
--compare-with-ci [BUILD NUMBER] Compare failed tests with results on CI server.
Default build is the latest.
--fail-script-on-failed-tests Fail webdriver.sh if tests failed.
Other options:
--debug Run tests in debug mode
--skip-sources-validation Fast build. Skips source validation and enforce plugins
--workspace-pool-size=[<SIZE>|auto] Size of test workspace pool.
Default value is 0, that means that test workspaces are created on demand.
--include-tests-under-repair Include tests which permanently fail and so belong to group 'UNDER REPAIR'
--include-flaky-tests Include tests which randomly fail and so belong to group 'FLAKY'
HOW TO of usage:
Test Eclipse Che single user assembly:
${CALLER}
Test Eclipse Che multi user assembly:
${CALLER} --multiuser
Test Eclipse Che assembly and automatically rerun failing tests:
${CALLER} --rerun [ATTEMPTS]
Run single test or package of tests:
${CALLER} <...> --test=<TEST>
Run suite:
${CALLER} <...> --suite=<PATH_TO_SUITE>
Include tests which belong to groups 'UNDER REPAIR' and 'FLAKY'
./selenium-tests.sh --include-tests-under-repair --include-flaky-tests
Rerun failed tests:
${CALLER} <...> --failed-tests
${CALLER} <...> --failed-tests --rerun [ATTEMPTS]
Debug selenium test:
${CALLER} -Mlocal --test=<TEST> --debug
Analyse tests results:
${CALLER} --compare-with-ci [BUILD NUMBER]
"
printf "%s" "${usage}"
}
printRunOptions() {
echo "[TEST]"
echo "[TEST] =========== RUN OPTIONS ==========================="
echo "[TEST] Mode : ${MODE}"
echo "[TEST] Rerun attempts : ${RERUN_ATTEMPTS}"
echo "[TEST] ==================================================="
echo "[TEST] Product Protocol : ${PRODUCT_PROTOCOL}"
echo "[TEST] Product Host : ${PRODUCT_HOST}"
echo "[TEST] Product Port : ${PRODUCT_PORT}"
echo "[TEST] Product Config : $(getProductConfig)"
echo "[TEST] Tests scope : ${TESTS_SCOPE}"
echo "[TEST] Tests to exclude : $(getExcludedGroups)"
echo "[TEST] Threads : ${THREADS}"
echo "[TEST] Workspace pool size : ${WORKSPACE_POOL_SIZE}"
echo "[TEST] Web browser : ${BROWSER}"
echo "[TEST] Web driver ver : ${WEBDRIVER_VERSION}"
echo "[TEST] Web driver port : ${WEBDRIVER_PORT}"
echo "[TEST] Additional opts : ${GRID_OPTIONS} ${DEBUG_OPTIONS} ${MAVEN_OPTIONS}"
echo "[TEST] ==================================================="
}
# convert failed tests methods in the unique list of test classes
# a.b.c.SomeTest.someMethod1
# a.b.c.SomeTest.someMethod2
# |------> a.b.c.SomeTest
getTestClasses() {
local tests=$@
for t in ${tests[*]}
do
echo $(echo ${t} | sed 's/\(.*\)[.][^.]*/\1/')
done
}
fetchRunTestsNumber() {
local run=0
for report in target/failsafe-reports/*.txt
do
if [[ -f ${report} ]]; then
run=$((run + $(cat ${report} | grep "Tests run" | sed 's/Tests run:[[:space:]]\([0-9]*\).*/\1/')))
fi
done
echo ${run}
}
# Returns unique records.
fetchFailedTests() {
local fails=()
for report in target/failsafe-reports/*.txt
do
if [[ -f ${report} ]]; then
for item in $(cat ${report} | grep "<<< FAILURE!" | grep -e '(.*).*' | tr ' ' '_')
do
local method=$(echo ${item} | sed 's/\(.*\)(.*)_.*/\1/')
local class=$(echo ${item} | sed 's/.*(\(.*\))_.*/\1/')
fails+=(${class}'.'${method})
done
fi
done
for f in $(echo ${fails[@]} | tr ' ' '\n' | sort | uniq)
do
echo ${f}
done
}
fetchFailedTestsNumber() {
echo $(fetchFailedTests) | wc -w
}
detectLatestResultsUrl() {
local build=$(curl -s ${BASE_ACTUAL_RESULTS_URL} | tr '\n' ' ' | sed 's/.*Last build (#\([0-9]\+\)).*/\1/')
echo ${BASE_ACTUAL_RESULTS_URL}${build}"/testReport/"
}
# Fetches list of failed tests and failed configurations.
# Combines them into a single unique list.
fetchActualResults() {
unset ACTUAL_RESULTS
unset ACTUAL_RESULTS_URL
# define the URL of CI job to compare local result with result on CI
local multiuserToken=$([[ "$CHE_MULTIUSER" == true ]] && echo "-multiuser")
local infrastructureToken=$([[ "$CHE_INFRASTRUCTURE" == "openshift" ]] && echo "-ocp" || echo "-$CHE_INFRASTRUCTURE")
local nameOfCIJob="che-integration-tests${multiuserToken}-master${infrastructureToken}"
[[ -z ${BASE_ACTUAL_RESULTS_URL+x} ]] && { BASE_ACTUAL_RESULTS_URL="https://ci.codenvycorp.com/view/qa/job/${nameOfCIJob}/"; }
local build=$(echo $@ | sed 's/.*--compare-with-ci\W\+\([0-9]\+\).*/\1/')
if [[ ! ${build} =~ ^[0-9]+$ ]]; then
ACTUAL_RESULTS_URL=$(detectLatestResultsUrl)
else
ACTUAL_RESULTS_URL=${BASE_ACTUAL_RESULTS_URL}${build}"/testReport/"
fi
# get list of failed tests from CI server, remove duplicates from it and sort
ACTUAL_RESULTS=$(echo $( curl -s ${ACTUAL_RESULTS_URL} | \
tr '>' '\n' | tr '<' '\n' | tr '"' '\n' | \
grep --extended-regexp "^[a-z_$][a-z0-9_$.]*\.[A-Z_$][a-zA-Z0-9_$]*\.[a-z_$][a-zA-Z0-9_$]*$" | \
tr ' ' '\n' | sort | uniq ))
}
findRegressions() {
local expected=(${ACTUAL_RESULTS[*]})
local failed=$(fetchFailedTests)
for f in ${failed[*]}
do
local skip=false
for e in ${expected[*]}
do
[[ ${f} == ${e} ]] && { skip=true; break; }
done
[[ ${skip} == true ]] || echo ${f}
done
}
# Analyses tests results by comparing with the actual ones.
analyseTestsResults() {
echo "[TEST]"
echo -e "[TEST] "${YELLOW}"RESULTS ANALYSE:"${NO_COLOUR}
echo "[TEST]"
echo -e "[TEST] Command line: ${BLUE}${CUR_DIR}/${CALLER} $@${NO_COLOUR}"
echo "[TEST]"
if [[ ${COMPARE_WITH_CI} == true ]]; then
echo -e "[TEST] CI results ${BLUE}${ACTUAL_RESULTS_URL}${NO_COLOUR}"
echo -e "[TEST] \t- Failed: $(printf "%5s" "$(echo ${ACTUAL_RESULTS[@]} | wc -w)") (unique tests)"
echo "[TEST]"
fi
local run=$(fetchRunTestsNumber)
local runToDisplay=$(printf "%7s" "${run}")
local fails=$(fetchFailedTests)
TOTAL_FAILS=$(echo ${fails[@]} | wc -w)
local totalFailsToDisplay=$(printf "%5s" "${TOTAL_FAILS}")
echo "[TEST] Local results:"
echo -e "[TEST] \t- Run: \t${runToDisplay}"
echo -e "[TEST] \t- Failed: ${totalFailsToDisplay}"
if [[ ${COMPARE_WITH_CI} == true ]]; then
if [[ ! ${TOTAL_FAILS} -eq 0 ]]; then
for r in $(echo ${fails[@]} | tr ' ' '\n' | sort)
do
echo -e "[TEST] \t"${r}
done
fi
echo "[TEST]"
echo -e -n "[TEST] Comparing with "${BLUE}${ACTUAL_RESULTS_URL}${NO_COLOUR}
if [[ ${ACTUAL_RESULTS_URL} != $(detectLatestResultsUrl) ]]; then
echo -e ${RED}" (not the latest results)"${NO_COLOUR}
else
echo
fi
echo "[TEST] If a test failed then it is NOT marked as regression."
fi
echo "[TEST]"
if [[ ${run} == "0" ]]; then
echo -e "[TEST] "${RED}"NO RESULTS"${NO_COLOUR}
else
local regressions=$(findRegressions)
local totalRegressions=$(echo ${regressions[@]} | wc -w)
if [[ ${totalRegressions} -eq 0 ]]; then
echo -e -n "[TEST] "${GREEN}"NO REGRESSION! "${NO_COLOUR}
if [[ ! ${TOTAL_FAILS} -eq 0 ]]; then
echo -e ${RED}"CHECK THE FAILED TESTS. THEY MIGHT FAIL DUE TO DIFFERENT REASON."${NO_COLOUR}
else
echo -e ${GREEN}"NO FAILED TESTS, GREAT JOB!"${NO_COLOUR}
fi
else
echo -e "[TEST] "${RED}"REGRESSION"${NO_COLOUR}" ("${totalRegressions}"):"
for r in $(echo ${regressions[@]} | tr ' ' '\n' | sort)
do
echo -e "[TEST] \t"${r}
done
fi
fi
echo "[TEST]"
echo "[TEST]"
}
printProposals() {
echo -e "[TEST] "${YELLOW}"PROPOSALS:"${NO_COLOUR}
local cmd=$(echo $@ | sed -e "s/--rerun\W*[0-9]*//g" | \
sed -e "s/-M[^ ]*//g" | \
sed -e "s/--failed-tests//g" | \
sed -e "s/--regression-tests//g" | \
sed -e "s/--suite=[^ ]*//g " | \
sed -e "s/--test*=[^ ]*//g " | \
sed -e "s/--compare-with-ci\W*[0-9]*//g" | \
sed -e "s/--threads=[0-9]*//g" | \
sed -e "s/--workspace-pool-size=auto|[0-9]*//g")
local regressions=$(findRegressions)
local total=$(echo ${regressions[@]} | wc -w)
if [[ ! ${total} -eq 0 ]]; then
echo "[TEST]"
echo "[TEST] Try rerun all tests:"
echo -e "[TEST] \t${BLUE}${CUR_DIR}/${CALLER} ${cmd} --threads=${THREADS} -Mlocal --failed-tests${NO_COLOUR}"
echo -e "[TEST] \t${BLUE}${CUR_DIR}/${CALLER} ${cmd} --threads=${THREADS} -Mgrid --failed-tests${NO_COLOUR}"
echo "[TEST]"
if [[ ${total} -lt 50 ]]; then
echo "[TEST] Or run them one by one:"
for r in $(echo ${regressions[@]} | tr ' ' '\n' | sed 's/\(.*\)[.][^.]*/\1/' | sort | uniq)
do
echo -e "[TEST] \t${BLUE}${CUR_DIR}/${CALLER} ${cmd} -Mlocal --test=${r}${NO_COLOUR}"
done
echo "[TEST]"
echo -e "[TEST] You might need add ${BLUE}--debug${NO_COLOUR} option for debugging purpose."
fi
fi
echo "[TEST]"
echo "[TEST] To compare tests results with the latest results on CI job"
echo -e "[TEST] \t${BLUE}${CUR_DIR}/${CALLER} ${cmd} --compare-with-ci${NO_COLOUR}"
echo "[TEST]"
echo "[TEST] To compare local tests results with certain build on CI job"
echo -e "[TEST] \t${BLUE}${CUR_DIR}/${CALLER} ${cmd} --compare-with-ci [BUILD NUMBER]${NO_COLOUR}"
echo "[TEST]"
echo "[TEST]"
}
printElapsedTime() {
local totalTime=$(($(date +%s)-${START_TIME}))
echo "[TEST]"
echo "[TEST] Elapsed time: "$((${totalTime} / 3600))"hrs "$(( $((${totalTime} / 60)) % 60))"min "$((${totalTime} % 60))"sec"
}
runTests() {
if [[ ${TESTS_SCOPE} =~ -DrunSuite ]]; then
prepareTestSuite
fi
printRunOptions
mvn clean verify -Pselenium-test \
${TESTS_SCOPE} \
-Dche.host=${PRODUCT_HOST} \
-Dche.port=${PRODUCT_PORT} \
-Dche.protocol=${PRODUCT_PROTOCOL} \
-Ddocker.interface.ip=$(detectDockerInterfaceIp) \
-Ddriver.port=${WEBDRIVER_PORT} \
-Ddriver.version=${WEBDRIVER_VERSION} \
-Dbrowser=${BROWSER} \
-Dche.threads=${THREADS} \
-Dche.workspace_pool_size=${WORKSPACE_POOL_SIZE} \
-DexcludedGroups="$(getExcludedGroups)" \
${DEBUG_OPTIONS} \
${GRID_OPTIONS} \
${MAVEN_OPTIONS}
}
# Return list of product features
getProductConfig() {
local testGroups=${CHE_INFRASTRUCTURE}
if [[ ${CHE_MULTIUSER} == true ]]; then
testGroups=${testGroups},multiuser
else
testGroups=${testGroups},singleuser
fi
echo ${testGroups}
}
# Prepare list of test groups to exclude.
getExcludedGroups() {
local excludeParamArray=(${EXCLUDE_PARAM//,/ })
if [[ ${INCLUDE_TESTS_UNDER_REPAIR} == false ]]; then
excludeParamArray+=( 'under_repair' )
fi
if [[ ${INCLUDE_FLAKY_TESTS} == false ]]; then
excludeParamArray+=( 'flaky' )
fi
echo $(IFS=$','; echo "${excludeParamArray[*]}")
}
# Reruns failed tests
rerunTests() {
local regressions=$(findRegressions)
local total=$(echo ${regressions[@]} | wc -w)
if [[ ! ${total} -eq 0 ]]; then
local rerunCounter=$1 && shift
analyseTestsResults $@
generateFailSafeReport
printProposals $@
storeTestReport
printElapsedTime
echo -e "[TEST]"
echo -e "[TEST] ${YELLOW}---------------------------------------------------${NO_COLOUR}"
echo -e "[TEST] ${YELLOW}RERUNNING FAILED TESTS IN ONE THREAD: ATTEMPT #${rerunCounter}${NO_COLOUR}"
echo -e "[TEST] ${YELLOW}---------------------------------------------------${NO_COLOUR}"
defineTestsScope "--failed-tests"
runTests
if [[ ${rerunCounter} < ${RERUN_ATTEMPTS} ]]; then
rerunTests $(($rerunCounter+1)) $@
fi
fi
}
# Finds regressions and generates testng-failed.xml suite bases on them.
generateTestNgFailedReport() {
local failsClasses=$(getTestClasses $@)
if [[ -d ${FAILSAFE_DIR} ]]; then
echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" > ${TESTNG_FAILED_SUITE}
echo "<suite thread-count=\"1\" verbose=\"0\" parallel=\"classes\" name=\"Failed suite\">" >> ${TESTNG_FAILED_SUITE}
echo -e "\t<test name=\"Surefire test\">" >> ${TESTNG_FAILED_SUITE}
echo -e "\t\t<classes>" >> ${TESTNG_FAILED_SUITE}
for f in $(echo ${failsClasses[@]} | tr ' ' '\n' | sort | uniq)
do
echo -e -n "\t\t\t<class name=\"" >> ${TESTNG_FAILED_SUITE}
echo -e -n ${f} >> ${TESTNG_FAILED_SUITE}
echo -e "\"/>" >> ${TESTNG_FAILED_SUITE}
done
echo -e "\t\t</classes>" >> ${TESTNG_FAILED_SUITE}
echo -e "\t</test>" >> ${TESTNG_FAILED_SUITE}
echo -e "</suite>" >> ${TESTNG_FAILED_SUITE}
fi
}
# generates and updates failsafe report
generateFailSafeReport () {
mvn -q surefire-report:failsafe-report-only
mvn -q site -DgenerateReports=false
echo "[TEST]"
echo -e "[TEST] ${YELLOW}REPORT:${NO_COLOUR}"
if [[ ! -f ${FAILSAFE_REPORT} ]]; then
echo -e "[TEST] Failsafe report: ${BLUE}file://${CUR_DIR}/${FAILSAFE_REPORT}${NO_COLOUR} not found."
echo "[TEST] Either maven surefire report plugin failed or tests haven't been run at all."
echo "[TEST]"
echo "[TEST] To regenerate report manually use the command below:"
echo -e "[TEST] \t${BLUE}${CUR_DIR}/${CALLER} --compare-with-ci${NO_COLOUR}"
echo "[TEST]"
echo "[TEST]"
exit 1
fi
local regressions=$(findRegressions)
# add REGRESSION marks
for r in ${regressions[*]}
do
local test=$(basename $(echo ${r} | tr '.' '/') | sed 's/\(.*\)_.*/\1/')
local aTag="<a href=\"#"${r}"\">"${test}"<\/a>"
local divRegTag="<h2>REGRESSION<\/h2>"${aTag}
sed -i "s/${aTag}/${divRegTag}/" ${FAILSAFE_REPORT}
done
# pack logs of workspaces which failed on start when injecting into test object and add link into the 'Summary' section of failsafe report
local dirWithFailedWorkspacesLogs="target/site/workspace-logs/injecting_workspaces_which_did_not_start"
if [[ -d ${dirWithFailedWorkspacesLogs} ]]; then
cd ${dirWithFailedWorkspacesLogs}
zip -qr "../injecting_workspaces_which_did_not_start_logs.zip" .
cd - > /dev/null
rm -rf ${dirWithFailedWorkspacesLogs}
summaryTag="Summary<\/h2><a name=\"Summary\"><\/a>"
linkToFailedWorkspacesLogsTag="<p>\[<a href=\"workspace-logs\/injecting_workspaces_which_did_not_start_logs.zip\" target=\"_blank\">Injecting workspaces which didn't start logs<\/a>\]<\/p>"
sed -i "s/${summaryTag}/${summaryTag}${linkToFailedWorkspacesLogsTag}/" ${FAILSAFE_REPORT}
fi
# add link the che server logs archive into the 'Summary' section of failsafe report
local summaryTag="Summary<\/h2><a name=\"Summary\"><\/a>"
local linkToCheServerLogsTag="<p>\[<a href=\"che_server_logs.zip\" target=\"_blank\">Eclipse Che Server logs<\/a>\]<\/p>"
sed -i "s/${summaryTag}/${summaryTag}${linkToCheServerLogsTag}/" ${FAILSAFE_REPORT}
# attach screenshots
if [[ -d "target/site/screenshots" ]]; then
for file in $(ls target/site/screenshots/* | sort -r)
do
local test=$(basename ${file} | sed 's/\(.*\)_.*/\1/')
local testDetailTag="<div id=\"${test}-failure\" style=\"display:none;\">"
local screenshotTag="<p><img src=\"screenshots\/"$(basename ${file})"\"><p>"
sed -i "s/${testDetailTag}/${testDetailTag}${screenshotTag}/" ${FAILSAFE_REPORT}
done
fi
attachLinkToTestReport workspace-logs "Workspace logs"
attachLinkToTestReport webdriver-logs "Browser logs"
attachLinkToTestReport htmldumps "Web page source"
echo "[TEST]"
echo "[TEST] Failsafe report"
echo -e "[TEST] \t${BLUE}file://${CUR_DIR}/${FAILSAFE_REPORT}${NO_COLOUR}"
echo "[TEST]"
echo "[TEST]"
}
# first argument - relative path to directory inside target/site
# second argument - title of the link
attachLinkToTestReport() {
# attach links to resource related to failed test
local relativePathToResource=$1
local titleOfLink=$2
local dirWithResources="target/site/$relativePathToResource"
# return if directory doesn't exist
[[ ! -d ${dirWithResources} ]] && return
# return if directory is empty
[[ -z "$(ls -A ${dirWithResources})" ]] && return
for file in $(ls ${dirWithResources}/* | sort -r)
do
local test=$(basename ${file} | sed 's/\(.*\)_.*/\1/')
local testDetailTag="<div id=\"${test}-failure\" style=\"display:none;\">"
local filename=$(basename ${file})
local linkTag="<p><li><a href=\"$relativePathToResource\/$filename\" target=\"_blank\"><b>$titleOfLink<\/b>: $filename<\/a><\/li><\/p>"
sed -i "s/${testDetailTag}/${testDetailTag}${linkTag}/" ${FAILSAFE_REPORT}
done
}
storeTestReport() {
mkdir -p ${TMP_DIR}/webdriver
local report="${TMP_DIR}/webdriver/report$(date +%s).zip"
rm -rf ${TMP_DIR}/webdriver/tmp
mkdir target/suite
if [[ -f ${TMP_SUITE_PATH} ]]; then
cp ${TMP_SUITE_PATH} target/suite;
fi
zip -qr ${report} target/screenshots target/htmldumps target/workspace-logs target/webdriver-logs target/site target/failsafe-reports target/log target/bin target/suite
echo -e "[TEST] Tests results and reports are saved to ${BLUE}${report}${NO_COLOUR}"
echo "[TEST]"
echo "[TEST] If target directory is accidentally cleaned it is possible to restore it: "
echo -e "[TEST] \t${BLUE}rm -rf ${CUR_DIR}/target && unzip -q ${report} -d ${CUR_DIR}${NO_COLOUR}"
echo "[TEST]"
}
checkBuild() {
mvn package ${MAVEN_OPTIONS}
[[ $? != 0 ]] && { exit 1; }
}
prepareToFirstRun() {
checkIfProductIsRun
cleanUpEnvironment
initRunMode
}
getKeycloakContainerId() {
if [[ "${CHE_INFRASTRUCTURE}" == "openshift" ]]; then
echo $(docker ps | grep 'keycloak_keycloak-' | cut -d ' ' -f1)
else
echo $(docker ps | grep che_keycloak | cut -d ' ' -f1)
fi
}
testProduct() {
runTests
if [[ ${RERUN_ATTEMPTS} > 0 ]]; then
MAVEN_OPTIONS="${MAVEN_OPTIONS} -o"
rerunTests 1 $@
fi
}
run() {
if [[ $@ =~ --help ]]; then
printHelp
exit
fi
START_TIME=$(date +%s)
trap cleanUpEnvironment EXIT
initVariables
init
extractMavenOptions $@
checkBuild
checkParameters $@
defineOperationSystemSpecificVariables
defineRunMode $@
defineTestsScope $@
applyCustomOptions $@
if [[ ${COMPARE_WITH_CI} == true ]]; then
fetchActualResults $@
else
prepareToFirstRun
testProduct $@
fi
analyseTestsResults $@
if [[ ${COMPARE_WITH_CI} == false ]]; then
generateFailSafeReport
printProposals $@
storeTestReport
printElapsedTime
fi
}
run "$@"
if [[ ${TOTAL_FAILS} -ne 0 && ${FAIL_SCRIPT_ON_FAILED_TESTS} == true ]]; then
exit 1
fi

View File

@ -1,168 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2012-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
Contributors:
Red Hat, Inc. - initial API and implementation
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>che-selenium-parent</artifactId>
<groupId>org.eclipse.che.selenium</groupId>
<version>7.29.0-SNAPSHOT</version>
</parent>
<artifactId>che-selenium-core</artifactId>
<packaging>jar</packaging>
<name>Che Legacy E2E :: Core</name>
<dependencies>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
<dependency>
<groupId>com.google.inject</groupId>
<artifactId>guice</artifactId>
</dependency>
<dependency>
<groupId>com.google.inject.extensions</groupId>
<artifactId>guice-assistedinject</artifactId>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
</dependency>
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
</dependency>
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-api-core</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-api-dto</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-api-factory-shared</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-api-model</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-api-ssh-shared</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-api-user-shared</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-api-workspace-shared</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-commons-annotations</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-commons-json</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-commons-lang</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.multiuser</groupId>
<artifactId>che-multiuser-api-organization-shared</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.multiuser</groupId>
<artifactId>che-multiuser-api-permission-shared</artifactId>
</dependency>
<dependency>
<groupId>org.kohsuke</groupId>
<artifactId>github-api</artifactId>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-api</artifactId>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-chrome-driver</artifactId>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-remote-driver</artifactId>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-support</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-commons-inject</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-testng</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>bin</directory>
</resource>
<resource>
<directory>src/main/java</directory>
</resource>
<resource>
<directory>src/main/resources</directory>
</resource>
</resources>
</build>
</project>

View File

@ -1,383 +0,0 @@
/*
* Copyright (c) 2012-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
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.selenium.core;
import static java.lang.String.format;
import static org.eclipse.che.selenium.core.constant.TestTimeoutsConstants.APPLICATION_START_TIMEOUT_SEC;
import static org.eclipse.che.selenium.core.constant.TestTimeoutsConstants.LOADER_TIMEOUT_SEC;
import static org.eclipse.che.selenium.core.utils.WaitUtils.sleepQuietly;
import static org.openqa.selenium.support.ui.ExpectedConditions.frameToBeAvailableAndSwitchToIt;
import static org.openqa.selenium.support.ui.ExpectedConditions.visibilityOfElementLocated;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import com.google.inject.name.Named;
import java.io.Closeable;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;
import java.util.logging.Level;
import org.eclipse.che.api.core.BadRequestException;
import org.eclipse.che.api.core.ConflictException;
import org.eclipse.che.api.core.ForbiddenException;
import org.eclipse.che.api.core.NotFoundException;
import org.eclipse.che.api.core.ServerException;
import org.eclipse.che.api.core.UnauthorizedException;
import org.eclipse.che.api.core.rest.HttpJsonRequestFactory;
import org.eclipse.che.commons.annotation.Nullable;
import org.eclipse.che.selenium.core.constant.TestBrowser;
import org.eclipse.che.selenium.core.utils.DockerUtil;
import org.openqa.selenium.By;
import org.openqa.selenium.Dimension;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebDriverException;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.interactions.HasInputDevices;
import org.openqa.selenium.interactions.Keyboard;
import org.openqa.selenium.interactions.Mouse;
import org.openqa.selenium.logging.LogType;
import org.openqa.selenium.logging.LoggingPreferences;
import org.openqa.selenium.remote.CapabilityType;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.openqa.selenium.support.ui.ExpectedCondition;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Wrapper for {@link WebDriver} to have ability to use in Guice container.
*
* @author Anatolii Bazko
*/
@Singleton
public class SeleniumWebDriver
implements Closeable, WebDriver, JavascriptExecutor, TakesScreenshot, HasInputDevices {
private static final Logger LOG = LoggerFactory.getLogger(SeleniumWebDriver.class);
private static final int MAX_ATTEMPTS = 5;
private static final int DELAY_IN_SECONDS = 5;
private TestBrowser browser;
private boolean gridMode;
private String gridNodeContainerId;
private String webDriverPort;
private final RemoteWebDriver driver;
private final HttpJsonRequestFactory httpJsonRequestFactory;
private final DockerUtil dockerUtil;
private final String downloadDir;
@Inject
public SeleniumWebDriver(
@Named("sys.browser") TestBrowser browser,
@Named("sys.driver.port") String webDriverPort,
@Named("sys.grid.mode") boolean gridMode,
HttpJsonRequestFactory httpJsonRequestFactory,
DockerUtil dockerUtil,
@Named("tests.tmp_dir") String downloadDir) {
this.browser = browser;
this.webDriverPort = webDriverPort;
this.gridMode = gridMode;
this.httpJsonRequestFactory = httpJsonRequestFactory;
this.dockerUtil = dockerUtil;
this.downloadDir = downloadDir;
try {
URL webDriverUrl =
new URL(format("http://localhost:%s%s", webDriverPort, gridMode ? "/wd/hub" : ""));
this.driver = createDriver(webDriverUrl);
} catch (MalformedURLException e) {
throw new RuntimeException("Error of construction URL to web driver.", e);
}
}
@Override
public void get(String url) {
driver.get(url);
}
@Override
public String getCurrentUrl() {
return driver.getCurrentUrl();
}
@Override
public String getTitle() {
return driver.getTitle();
}
@Override
public List<WebElement> findElements(By by) {
return driver.findElements(by);
}
@Override
public WebElement findElement(By by) {
return driver.findElement(by);
}
@Override
public String getPageSource() {
return driver.getPageSource();
}
@Override
public void close() {
driver.close();
}
@Override
public void quit() {
driver.quit();
}
@Override
public Set<String> getWindowHandles() {
return driver.getWindowHandles();
}
@Override
public String getWindowHandle() {
return driver.getWindowHandle();
}
@Override
public TargetLocator switchTo() {
return driver.switchTo();
}
@Override
public Navigation navigate() {
return driver.navigate();
}
@Override
public Options manage() {
return driver.manage();
}
@Override
public Object executeScript(String script, Object... args) {
return driver.executeScript(script, args);
}
@Override
public Object executeAsyncScript(String script, Object... args) {
return driver.executeAsyncScript(script, args);
}
@Override
public <X> X getScreenshotAs(OutputType<X> target) throws WebDriverException {
return driver.getScreenshotAs(target);
}
@Override
public Keyboard getKeyboard() {
return driver.getKeyboard();
}
@Override
public Mouse getMouse() {
return driver.getMouse();
}
private RemoteWebDriver createDriver(URL webDriverUrl) {
for (int i = 1; ; ) {
try {
return doCreateDriver(webDriverUrl);
} catch (WebDriverException e) {
if (i++ >= MAX_ATTEMPTS) {
throw e;
}
}
sleepQuietly(DELAY_IN_SECONDS);
}
}
/**
* Read supported version info from official site.
*
* @param webDriverOfficialNotes address of official page with Google driver info
* @return string with supported version range (for example, "36-40"), or null if version info
* doesn't found inside the official notes.
* @throws IOException
*/
@Nullable
private String readSupportedVersionInfoForGoogleDriver(URL webDriverOfficialNotes)
throws IOException {
try (Scanner scanner = new Scanner(webDriverOfficialNotes.openStream(), "UTF-8")) {
while (scanner.hasNextLine()) {
String versionLine = scanner.findInLine("Supports Chrome v([\\d-]+)");
if (versionLine != null) {
return scanner.match().group(1);
}
scanner.nextLine();
}
}
return null;
}
private RemoteWebDriver doCreateDriver(URL webDriverUrl) {
DesiredCapabilities capability;
switch (browser) {
case GOOGLE_CHROME:
LoggingPreferences loggingPreferences = new LoggingPreferences();
loggingPreferences.enable(LogType.PERFORMANCE, Level.ALL);
loggingPreferences.enable(LogType.BROWSER, Level.ALL);
ChromeOptions options = new ChromeOptions();
options.addArguments("--no-sandbox");
options.addArguments("--dns-prefetch-disable");
options.addArguments("--ignore-certificate-errors");
// set parameters required for automatic download capability
Map<String, Object> chromePrefs = new HashMap<>();
chromePrefs.put("download.default_directory", downloadDir);
chromePrefs.put("download.prompt_for_download", false);
chromePrefs.put("download.directory_upgrade", true);
chromePrefs.put("safebrowsing.enabled", true);
chromePrefs.put("profile.default_content_settings.popups", 0);
chromePrefs.put("plugins.plugins_disabled", "['Chrome PDF Viewer']");
options.setExperimentalOption("prefs", chromePrefs);
capability = DesiredCapabilities.chrome();
capability.setCapability(ChromeOptions.CAPABILITY, options);
capability.setCapability(CapabilityType.LOGGING_PREFS, loggingPreferences);
capability.setCapability(CapabilityType.ACCEPT_SSL_CERTS, true);
break;
default:
capability = DesiredCapabilities.firefox();
capability.setCapability("dom.max_script_run_time", 240);
capability.setCapability("dom.max_chrome_script_run_time", 240);
}
RemoteWebDriver driver = new RemoteWebDriver(webDriverUrl, capability);
if (driver.getErrorHandler().isIncludeServerErrors()
&& driver.getCapabilities().getCapability("message") != null) {
String errorMessage =
format(
"Web driver creation error occurred: %s",
driver.getCapabilities().getCapability("message"));
LOG.error(errorMessage);
throw new RuntimeException(errorMessage);
}
driver.manage().window().setSize(new Dimension(1920, 1080));
return driver;
}
/** wait while in a browser appears more the 1 window */
public void waitOpenedSomeWin() {
new WebDriverWait(this, 30)
.until(
(ExpectedCondition<Boolean>)
input -> {
Set<String> driverWindows = getWindowHandles();
return (driverWindows.size() > 1);
});
}
/**
* calculate name of workspace from browser url cut symbols from end of slash symbol ("/") to end
*/
public String getWorkspaceNameFromBrowserUrl() {
String currentUrl = getCurrentUrl();
return currentUrl.substring(currentUrl.lastIndexOf("/") + 1, currentUrl.length());
}
/**
* switch to the next browser window (this means that if opened 2 windows, and we are in the
* window 1, we will be switched into the window 2 )
*
* @param currentWindowHandler
*/
public void switchToNoneCurrentWindow(String currentWindowHandler) {
waitOpenedSomeWin();
for (String handle : getWindowHandles()) {
if (!currentWindowHandler.equals(handle)) {
switchTo().window(handle);
break;
}
}
}
public void switchFromDashboardIframeToIde() {
switchFromDashboardIframeToIde(APPLICATION_START_TIMEOUT_SEC);
}
public void switchFromDashboardIframeToIde(int timeout) {
wait(timeout).until(visibilityOfElementLocated(By.id("ide-application-iframe")));
wait(LOADER_TIMEOUT_SEC)
.until(
(ExpectedCondition<Boolean>)
driver ->
(((JavascriptExecutor) driver)
.executeScript("return angular.element('body').scope().showIDE"))
.toString()
.equals("true"));
wait(timeout).until(frameToBeAvailableAndSwitchToIt(By.id("ide-application-iframe")));
}
private WebDriverWait wait(int timeOutInSeconds) {
return new WebDriverWait(this, timeOutInSeconds);
}
public String getGridNodeContainerId() throws IOException {
if (!gridMode) {
throw new UnsupportedOperationException("We can't get grid node container id in local mode.");
}
if (gridNodeContainerId == null) {
String getGridNodeInfoUrl =
format(
"http://localhost:%s/grid/api/testsession?session=%s",
webDriverPort, driver.getSessionId());
Map<String, String> gridNodeInfo;
try {
gridNodeInfo = httpJsonRequestFactory.fromUrl(getGridNodeInfoUrl).request().asProperties();
} catch (ServerException
| UnauthorizedException
| ForbiddenException
| NotFoundException
| ConflictException
| BadRequestException e) {
throw new IOException(e);
}
if (!gridNodeInfo.containsKey("proxyId")) {
throw new IOException("Proxy ID of grid node wasn't found.");
}
URL proxyId = new URL(gridNodeInfo.get("proxyId"));
gridNodeContainerId = dockerUtil.findGridNodeContainerByIp(proxyId.getHost());
}
return gridNodeContainerId;
}
}

View File

@ -1,25 +0,0 @@
/*
* Copyright (c) 2012-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
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.selenium.core;
/** @author Dmytro Nochevnov */
public interface TestGroup {
String MULTIUSER = "multiuser";
String SINGLEUSER = "singleuser";
String OPENSHIFT = "openshift";
String DOCKER = "docker";
String GITHUB = "github";
String OSIO = "osio";
String K8S = "k8s";
String UNDER_REPAIR = "under_repair";
String FLAKY = "flaky";
}

View File

@ -1,31 +0,0 @@
/*
* Copyright (c) 2012-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
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.selenium.core.action;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.interactions.Actions;
/**
* Main interface for producing new instances of {@link Actions}.
*
* @author Vlad Zhukovskyi
*/
public interface ActionsFactory {
/**
* Creates a new instance of {@link Actions} based on input {@code webDriver}
*
* @param webDriver instance of {@link WebDriver}
* @return a new instance of {@link Actions}
*/
Actions createAction(WebDriver webDriver);
}

View File

@ -1,33 +0,0 @@
/*
* Copyright (c) 2012-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
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.selenium.core.action;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.interactions.Actions;
/**
* Generic actions. Default extension of the {@link Actions} which actually doesn't modify a
* behavior of internal {@link Actions}.
*
* @author Vlad Zhukovskyi
* @see Actions
*/
public class GenericActions extends PlatformBasedActions {
public GenericActions(WebDriver driver) {
super(driver);
}
@Override
protected CharSequence[] modifyCharSequence(CharSequence... keysToSend) {
return keysToSend;
}
}

View File

@ -1,31 +0,0 @@
/*
* Copyright (c) 2012-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
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.selenium.core.action;
import com.google.inject.Singleton;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.interactions.Actions;
/**
* Default actions factory for the generic operation system, linux, windows, etc.
*
* @author Vlad Zhukovskyi
* @see GenericActions
* @see ActionsFactory
*/
@Singleton
public class GenericActionsFactory implements ActionsFactory {
@Override
public Actions createAction(WebDriver webDriver) {
return new GenericActions(webDriver);
}
}

View File

@ -1,78 +0,0 @@
/*
* Copyright (c) 2012-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
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.selenium.core.action;
import static com.google.common.collect.Lists.newArrayList;
import java.util.List;
import org.openqa.selenium.Keys;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.interactions.Actions;
import org.openqa.selenium.interactions.SendKeysAction;
/**
* Mac OS based extension of {@link Actions}. Modifies the behavior of {@link SendKeysAction} by
* replacing key press calls. Unfortunately this may need for that reason, that some of selenium
* tests may send:
*
* <ul>
* <li>{@link Keys#END}
* <li>{@link Keys#HOME}
* <li>{@link Keys#PAGE_DOWN}
* <li>{@link Keys#PAGE_UP}
* </ul>
*
* which don't work in current operation system. So some tests may fail. but for above key press in
* Mac OS there are equivalence:
*
* <ul>
* <li>Command+Right
* <li>Command+Left
* <li>Command+Down
* <li>Command+Up
* </ul>
*
* and method may look for non-working key presses from the input array of {@link CharSequence} and
* replace them with equivalence. So for test it will looks like it runs transparently on any OS.
*
* <p>For more information see {@link #modifyCharSequence(CharSequence...)}
*
* @author Vlad Zhukovskyi
*/
public class MacOSActions extends PlatformBasedActions {
public MacOSActions(WebDriver driver) {
super(driver);
}
@Override
protected CharSequence[] modifyCharSequence(CharSequence... keysToSend) {
final List<CharSequence> modKeysToSend = newArrayList();
for (CharSequence charSequence : keysToSend) {
final String key = charSequence.toString();
if (Keys.END.toString().equals(key)) {
modKeysToSend.add(Keys.chord(Keys.COMMAND, Keys.RIGHT));
} else if (Keys.HOME.toString().equals(key)) {
modKeysToSend.add(Keys.chord(Keys.COMMAND, Keys.LEFT));
} else if (Keys.PAGE_UP.toString().equals(key)) {
modKeysToSend.add(Keys.chord(Keys.COMMAND, Keys.UP));
} else if (Keys.PAGE_DOWN.toString().equals(key)) {
modKeysToSend.add(Keys.chord(Keys.COMMAND, Keys.DOWN));
} else {
modKeysToSend.add(charSequence);
}
}
return modKeysToSend.toArray(new CharSequence[modKeysToSend.size()]);
}
}

View File

@ -1,32 +0,0 @@
/*
* Copyright (c) 2012-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
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.selenium.core.action;
import com.google.inject.Singleton;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.interactions.Actions;
/**
* Mac OS based actions factory.
*
* @author Vlad Zhukovskyi
* @see MacOSActions
* @see ActionsFactory
*/
@Singleton
public class MacOSActionsFactory implements ActionsFactory {
@Override
public Actions createAction(WebDriver webDriver) {
return new MacOSActions(webDriver);
}
}

View File

@ -1,40 +0,0 @@
/*
* Copyright (c) 2012-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
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.selenium.core.action;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.interactions.Actions;
import org.openqa.selenium.interactions.SendKeysAction;
import org.openqa.selenium.internal.Locatable;
/**
* Abstract class for platform based actions. Generify the interface for using selenium action
* independently from the OS on which tests are running.
*
* @author Vlad Zhukovskyi
*/
public abstract class PlatformBasedActions extends Actions {
public PlatformBasedActions(WebDriver driver) {
super(driver);
}
@Override
public Actions sendKeys(WebElement element, CharSequence... keysToSend) {
action.addAction(
new SendKeysAction(keyboard, mouse, (Locatable) element, modifyCharSequence(keysToSend)));
return this;
}
protected abstract CharSequence[] modifyCharSequence(CharSequence... keysToSend);
}

View File

@ -1,366 +0,0 @@
/*
* Copyright (c) 2012-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
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.selenium.core.client;
import static java.lang.String.format;
import static java.lang.String.valueOf;
import static org.eclipse.che.api.core.model.workspace.WorkspaceStatus.STOPPED;
import static org.eclipse.che.api.core.model.workspace.WorkspaceStatus.STOPPING;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import org.eclipse.che.api.core.NotFoundException;
import org.eclipse.che.api.core.model.workspace.Workspace;
import org.eclipse.che.api.core.model.workspace.WorkspaceStatus;
import org.eclipse.che.api.core.model.workspace.runtime.Machine;
import org.eclipse.che.api.core.model.workspace.runtime.Server;
import org.eclipse.che.api.core.rest.HttpJsonRequestFactory;
import org.eclipse.che.api.workspace.shared.Constants;
import org.eclipse.che.api.workspace.shared.dto.WorkspaceDto;
import org.eclipse.che.commons.annotation.Nullable;
import org.eclipse.che.selenium.core.constant.TestTimeoutsConstants;
import org.eclipse.che.selenium.core.provider.TestApiEndpointUrlProvider;
import org.eclipse.che.selenium.core.requestfactory.TestUserHttpJsonRequestFactoryCreator;
import org.eclipse.che.selenium.core.user.TestUser;
import org.eclipse.che.selenium.core.utils.WaitUtils;
import org.eclipse.che.selenium.core.workspace.MemoryMeasure;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author Musienko Maxim
* @author Dmytro Nochevnov
*/
public abstract class AbstractTestWorkspaceServiceClient implements TestWorkspaceServiceClient {
private static final Logger LOG =
LoggerFactory.getLogger(AbstractTestWorkspaceServiceClient.class);
protected final TestApiEndpointUrlProvider apiEndpointProvider;
protected final HttpJsonRequestFactory requestFactory;
public AbstractTestWorkspaceServiceClient(
TestApiEndpointUrlProvider apiEndpointProvider, HttpJsonRequestFactory requestFactory) {
this.apiEndpointProvider = apiEndpointProvider;
this.requestFactory = requestFactory;
}
public AbstractTestWorkspaceServiceClient(
TestApiEndpointUrlProvider apiEndpointProvider,
TestUserHttpJsonRequestFactoryCreator userHttpJsonRequestFactoryCreator,
TestUser testUser) {
this(apiEndpointProvider, userHttpJsonRequestFactoryCreator.create(testUser));
}
protected String getBaseUrl() {
return apiEndpointProvider.get() + "workspace";
}
/** Returns the list of workspaces names that belongs to the user. */
@Override
public List<String> getAll() throws Exception {
List<WorkspaceDto> workspaces =
requestFactory.fromUrl(getBaseUrl()).request().asList(WorkspaceDto.class);
return workspaces.stream().map(ws -> ws.getConfig().getName()).collect(Collectors.toList());
}
/** Returns the number of workspaces that belongs to the user. */
@Override
public int getWorkspacesCount() throws Exception {
List<WorkspaceDto> workspaces =
requestFactory.fromUrl(getBaseUrl()).request().asList(WorkspaceDto.class);
return workspaces.size();
}
/** Stops workspace. */
@Override
public void stop(String workspaceName, String userName) throws Exception {
sendStopRequest(workspaceName, userName);
waitStatus(workspaceName, userName, STOPPED);
}
/** Returns workspace of default user by its name. */
@Override
public Workspace getByName(String workspace, String username) throws Exception {
return requestFactory
.fromUrl(getNameBasedUrl(workspace, username))
.request()
.asDto(WorkspaceDto.class);
}
/** Indicates if workspace exists. */
@Override
public boolean exists(String workspace, String username) throws Exception {
try {
requestFactory.fromUrl(getNameBasedUrl(workspace, username)).request();
} catch (NotFoundException e) {
return false;
}
return true;
}
/** Deletes workspace of default user. */
@Override
public void delete(String workspaceName, String userName) throws Exception {
if (!exists(workspaceName, userName)) {
return;
}
Workspace workspace = getByName(workspaceName, userName);
if (workspace.getStatus() == STOPPING) {
waitStatus(workspaceName, userName, STOPPED);
} else if (workspace.getStatus() != STOPPED) {
stop(workspaceName, userName);
}
requestFactory.fromUrl(getIdBasedUrl(workspace.getId())).useDeleteMethod().request();
WaitUtils.waitSuccessCondition(
() -> {
try {
return !exists(workspaceName, userName);
} catch (Exception e) {
throw new RuntimeException(
format(
"Error of waiting on workspace name='%s', id='%s', username='%s' removal.",
workspaceName, workspace.getId(), userName),
e);
}
},
TestTimeoutsConstants.PREPARING_WS_TIMEOUT_SEC,
500,
TimeUnit.SECONDS);
LOG.info(
"Workspace name='{}', id='{}', username='{}' removed",
workspaceName,
workspace.getId(),
userName);
}
/** Waits workspace is started. */
@Override
public void waitWorkspaceStart(String workspaceName, String userName) throws Exception {
WaitUtils.sleepQuietly(5); // delay 5 secs to obtain starting status for sure
WaitUtils.waitSuccessCondition(
() -> {
WorkspaceStatus status;
try {
status = getByName(workspaceName, userName).getStatus();
} catch (Exception e) {
throw new RuntimeException(e.getMessage(), e);
}
switch (status) {
case RUNNING:
return true;
case STARTING:
return false;
default:
throw new RuntimeException(
format("Workspace with name '%s' didn't start", workspaceName));
}
},
600,
1000,
TimeUnit.SECONDS);
}
/** Waits needed status. */
@Override
public void waitStatus(String workspaceName, String userName, WorkspaceStatus expectedStatus)
throws Exception {
waitStatus(workspaceName, userName, expectedStatus, 600);
}
public void waitStatus(
String workspaceName, String userName, WorkspaceStatus expectedStatus, int timeoutSeconds)
throws Exception {
WaitUtils.waitSuccessCondition(
() -> {
try {
if (getByName(workspaceName, userName).getStatus() == expectedStatus) {
return true;
}
} catch (Exception e) {
throw new RuntimeException(e.getMessage(), e);
}
return false;
},
timeoutSeconds,
1000,
TimeUnit.SECONDS);
}
/** Sends start workspace request. */
@Override
public void sendStartRequest(String workspaceId, String workspaceName) throws Exception {
requestFactory
.fromUrl(getIdBasedUrl(workspaceId) + "/runtime")
.addQueryParam("environment", workspaceName)
.usePostMethod()
.request();
}
/** Gets workspace by its id. */
@Override
public WorkspaceDto getById(String workspaceId) throws Exception {
return requestFactory.fromUrl(getIdBasedUrl(workspaceId)).request().asDto(WorkspaceDto.class);
}
/** Gets workspace status by id. */
@Override
public WorkspaceStatus getStatus(String workspaceId) throws Exception {
return getById(workspaceId).getStatus();
}
/**
* Return server URL related with defined port
*
* @deprecated use {@link #getServerFromDevMachineBySymbolicName(String, String)} to retrieve
* server URL from instead
*/
@Override
@Deprecated
@Nullable
public String getServerAddressByPort(String workspaceId, int port) throws Exception {
Workspace workspace = getById(workspaceId);
ensureRunningStatus(workspace);
Map<String, ? extends Machine> machines = workspace.getRuntime().getMachines();
for (Machine machine : machines.values()) {
if (containsWsAgentServer(machine)) {
return machine.getServers().get(valueOf(port) + "/tcp").getUrl();
}
}
return null;
}
/**
* Return ServerDto object from runtime by it's symbolic name
*
* @param workspaceId workspace id of current user
* @param serverName server name
* @return ServerDto object
*/
@Override
@Nullable
public Server getServerFromDevMachineBySymbolicName(String workspaceId, String serverName)
throws Exception {
Workspace workspace =
requestFactory.fromUrl(getIdBasedUrl(workspaceId)).request().asDto(WorkspaceDto.class);
ensureRunningStatus(workspace);
Map<String, ? extends Machine> machines = workspace.getRuntime().getMachines();
for (Machine machine : machines.values()) {
if (containsWsAgentServer(machine)) {
return machine.getServers().get(serverName);
}
}
return null;
}
/**
* Ensure workspace has running status, or throw IllegalStateException.
*
* @param workspace workspace description to get status and id.
* @throws IllegalStateException if workspace with certain workspaceId doesn't have RUNNING
* status.
*/
@Override
public void ensureRunningStatus(Workspace workspace) throws IllegalStateException {
if (workspace.getStatus() != WorkspaceStatus.RUNNING) {
throw new IllegalStateException(
format(
"Workspace with id='%s' should has '%s' status, but its actual state='%s'",
workspace.getId(), WorkspaceStatus.RUNNING, workspace.getStatus()));
}
}
/**
* Delete workspaces which could be created from factory
*
* @param originalName name workspace which was used to create factory
*/
@Override
public void deleteFactoryWorkspaces(String originalName, String username) throws Exception {
String workspace2delete = originalName;
for (int i = 1; ; i++) {
if (!exists(workspace2delete, username)) {
break;
}
delete(workspace2delete, username);
workspace2delete = originalName + "_" + i;
}
}
// ================= //
// PRIVATE METHODS //
// ================= //
/** Sends stop workspace request. */
private void sendStopRequest(String workspaceName, String userName) throws Exception {
if (!exists(workspaceName, userName)) {
return;
}
Workspace workspace = getByName(workspaceName, userName);
String apiUrl = getIdBasedUrl(workspace.getId()) + "/runtime/";
requestFactory.fromUrl(apiUrl).useDeleteMethod().request();
}
protected String getNameBasedUrl(String workspaceName, String username) {
return getBaseUrl() + "/" + username + "/" + workspaceName;
}
protected String getIdBasedUrl(String workspaceId) {
return getBaseUrl() + "/" + workspaceId;
}
protected long convertToByte(int numberOfMemValue, MemoryMeasure desiredMeasureMemory) {
long calculatedValue = 0;
// represents values of bytes in 1 megabyte (2x20)
final long MEGABYTES_CONST = 1048576;
// represents values of bytes in 1 gygabyte (2x30)
final long GYGABYTES_CONST = 1073741824;
switch (desiredMeasureMemory) {
case MB:
calculatedValue = numberOfMemValue * MEGABYTES_CONST;
break;
case GB:
calculatedValue = numberOfMemValue * GYGABYTES_CONST;
break;
}
return calculatedValue;
}
/**
* Checks whether provided {@link Machine} contains wsagent server.
*
* @param machine machine to check
* @return true when wsagent server is found in provided machine, false otherwise
*/
public static boolean containsWsAgentServer(Machine machine) {
return machine.getServers().keySet().contains(Constants.SERVER_WS_AGENT_HTTP_REFERENCE);
}
}

View File

@ -1,39 +0,0 @@
/*
* Copyright (c) 2012-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
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.selenium.core.client;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import org.eclipse.che.api.core.BadRequestException;
import org.eclipse.che.api.core.ConflictException;
import org.eclipse.che.api.core.ServerException;
import org.eclipse.che.selenium.core.provider.TestApiEndpointUrlProvider;
import org.eclipse.che.selenium.core.requestfactory.TestUserHttpJsonRequestFactory;
/** @author Anton Korneta */
@Singleton
public class CheTestUserServiceClient extends TestUserServiceClientImpl {
@Inject
public CheTestUserServiceClient(
TestApiEndpointUrlProvider apiEndpointProvider,
TestUserHttpJsonRequestFactory requestFactory) {
super(apiEndpointProvider, requestFactory);
}
@Override
public void create(String name, String email, String password)
throws BadRequestException, ConflictException, ServerException {}
@Override
public void remove(String id) throws ServerException, ConflictException {}
}

View File

@ -1,71 +0,0 @@
/*
* Copyright (c) 2012-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
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.selenium.core.client;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import com.google.inject.assistedinject.AssistedInject;
import org.eclipse.che.api.core.model.workspace.Workspace;
import org.eclipse.che.api.core.rest.HttpJsonRequestFactory;
import org.eclipse.che.api.workspace.shared.dto.WorkspaceConfigDto;
import org.eclipse.che.api.workspace.shared.dto.WorkspaceDto;
import org.eclipse.che.selenium.core.provider.TestApiEndpointUrlProvider;
import org.eclipse.che.selenium.core.requestfactory.TestUserHttpJsonRequestFactoryCreator;
import org.eclipse.che.selenium.core.user.TestUser;
import org.eclipse.che.selenium.core.workspace.MemoryMeasure;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class CheTestWorkspaceServiceClient extends AbstractTestWorkspaceServiceClient {
private static final Logger LOG = LoggerFactory.getLogger(CheTestWorkspaceServiceClient.class);
@Inject
public CheTestWorkspaceServiceClient(
TestApiEndpointUrlProvider apiEndpointProvider, HttpJsonRequestFactory requestFactory) {
super(apiEndpointProvider, requestFactory);
}
@AssistedInject
public CheTestWorkspaceServiceClient(
TestApiEndpointUrlProvider apiEndpointProvider,
TestUserHttpJsonRequestFactoryCreator userHttpJsonRequestFactoryCreator,
@Assisted TestUser testUser) {
super(apiEndpointProvider, userHttpJsonRequestFactoryCreator, testUser);
}
@Override
public Workspace createWorkspace(
String workspaceName, int memory, MemoryMeasure memoryUnit, WorkspaceConfigDto workspace)
throws Exception {
workspace.setName(workspaceName);
workspace.setDefaultEnv(workspaceName);
WorkspaceDto workspaceDto =
requestFactory
.fromUrl(getBaseUrl())
.usePostMethod()
.setBody(workspace)
.request()
.asDto(WorkspaceDto.class);
LOG.info("Workspace name='{}' and id='{}' created", workspaceName, workspaceDto.getId());
return workspaceDto;
}
@Override
public void start(String workspaceId, String workspaceName, TestUser workspaceOwner)
throws Exception {
sendStartRequest(workspaceId, workspaceName);
waitWorkspaceStart(workspaceName, workspaceOwner.getName());
}
}

View File

@ -1,54 +0,0 @@
/*
* Copyright (c) 2012-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
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.selenium.core.client;
import org.eclipse.che.dto.shared.DTO;
@DTO
public class GitHubKey {
private int id;
private String key;
private String url;
private String title;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}

View File

@ -1,21 +0,0 @@
/*
* Copyright (c) 2012-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
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.selenium.core.client;
/** @author Anatolii Bazko */
public interface TestAuthServiceClient {
/** Logs user into the system and returns auth token. */
String login(String username, String password) throws Exception;
void logout(String token) throws Exception;
}

View File

@ -1,59 +0,0 @@
/*
* Copyright (c) 2012-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
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.selenium.core.client;
import com.google.common.collect.ImmutableMap;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import org.eclipse.che.api.core.rest.HttpJsonRequestFactory;
import org.eclipse.che.api.workspace.shared.dto.CommandDto;
import org.eclipse.che.dto.server.DtoFactory;
import org.eclipse.che.selenium.core.provider.TestApiEndpointUrlProvider;
/** @author Musienko Maxim */
@Singleton
public class TestCommandServiceClient {
private final String apiEndpoint;
private final HttpJsonRequestFactory requestFactory;
@Inject
public TestCommandServiceClient(
TestApiEndpointUrlProvider apiEndpointProvider, HttpJsonRequestFactory requestFactory) {
this.apiEndpoint = apiEndpointProvider.get().toString();
this.requestFactory = requestFactory;
}
public void createCommand(String commandLine, String commandName, String commandType, String wsId)
throws Exception {
CommandDto commandDto = DtoFactory.newDto(CommandDto.class);
commandDto.setName(commandName);
commandDto.setType(commandType);
commandDto.setCommandLine(commandLine);
commandDto.setAttributes(ImmutableMap.of("previewUrl", ""));
createCommand(commandDto, wsId);
}
public void createCommand(CommandDto command, String wsId) throws Exception {
requestFactory
.fromUrl(apiEndpoint + "workspace/" + wsId + "/command")
.usePostMethod()
.setBody(command)
.request();
}
public void deleteCommand(String commandName, String wsId) throws Exception {
requestFactory
.fromUrl(apiEndpoint + "workspace/" + wsId + "/command/" + commandName)
.useDeleteMethod()
.request();
}
}

View File

@ -1,125 +0,0 @@
/*
* Copyright (c) 2012-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
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.selenium.core.client;
import static java.lang.String.format;
import static java.util.Collections.emptyList;
import static java.util.Optional.ofNullable;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.io.IOException;
import java.util.List;
import org.eclipse.che.api.core.ApiException;
import org.eclipse.che.api.core.NotFoundException;
import org.eclipse.che.api.core.rest.HttpJsonRequestFactory;
import org.eclipse.che.api.core.rest.HttpJsonResponse;
import org.eclipse.che.api.factory.shared.dto.FactoryDto;
import org.eclipse.che.selenium.core.provider.TestApiEndpointUrlProvider;
import org.eclipse.che.selenium.core.provider.TestIdeUrlProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** @author Musienko Maxim */
@Singleton
public class TestFactoryServiceClient {
private static final Logger LOG = LoggerFactory.getLogger(TestFactoryServiceClient.class);
private final String factoryApiEndpoint;
private final String ideUrl;
private final HttpJsonRequestFactory requestFactory;
@Inject
public TestFactoryServiceClient(
TestApiEndpointUrlProvider testApiEndpointUrlProvider,
TestIdeUrlProvider ideUrlProvider,
HttpJsonRequestFactory requestFactory)
throws Exception {
this.factoryApiEndpoint = testApiEndpointUrlProvider.get() + "factory/";
this.ideUrl = ideUrlProvider.get().toString();
this.requestFactory = requestFactory;
}
/**
* Creates factory
*
* @param createFactoryDto DTO object to create the factory
* @return URL for the saved factory
*/
public String createFactory(FactoryDto createFactoryDto) throws Exception {
HttpJsonResponse request =
requestFactory
.fromUrl(factoryApiEndpoint)
.usePostMethod()
.setBody(createFactoryDto)
.request();
FactoryDto responseDto =
ofNullable(request.asDto(FactoryDto.class))
.orElseThrow(() -> new RuntimeException("There is a problem creation of factory."));
LOG.debug(
"Factory with name='{}' and id='{}' has been created without errors",
responseDto.getName(),
responseDto.getId());
return format("%sf?id=%s", ideUrl, responseDto.getId());
}
/**
* Search for factories of certain name.
*
* @param name name of factory to find.
* @return List of factory DTOs with certain name.
* @throws ApiException
* @throws IOException
*/
public List<FactoryDto> findFactory(String name) throws ApiException, IOException {
String queryParamPrefix = "find?name=" + name;
HttpJsonResponse request;
try {
request = requestFactory.fromUrl(factoryApiEndpoint + queryParamPrefix).request();
} catch (NotFoundException e) {
return emptyList();
}
return request.asList(FactoryDto.class);
}
public void deleteFactory(String name) {
List<FactoryDto> factories;
try {
factories = findFactory(name);
if (factories.isEmpty()) {
return;
}
} catch (NotFoundException e) {
// ignore in case of there is no factory with certain name
return;
} catch (ApiException | IOException e) {
LOG.error(
format("Error of getting info about factory with name='%s': %s", name, e.getMessage()),
e);
return;
}
FactoryDto factory = factories.get(0);
try {
requestFactory.fromUrl(factoryApiEndpoint + factory.getId()).useDeleteMethod().request();
} catch (IOException | ApiException e) {
LOG.error(format("Error of deletion of factory with name='%s': %s", name, e.getMessage()), e);
return;
}
LOG.info("Factory name='{}' removed", name);
}
}

View File

@ -1,56 +0,0 @@
/*
* Copyright (c) 2012-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
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.selenium.core.client;
import static org.slf4j.LoggerFactory.getLogger;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import com.google.inject.name.Named;
import org.eclipse.che.api.core.ConflictException;
import org.slf4j.Logger;
/** @author Dmytro Nochevnov */
@Singleton
public class TestGitHubKeyUploader {
public static final String GITHUB_COM = "github.com";
private static final Logger LOG = getLogger(TestGitHubKeyUploader.class);
@Inject private TestGitHubServiceClient testGitHubServiceClient;
@Inject private TestSshServiceClient testSshServiceClient;
@Inject
@Named("github.username")
private String gitHubUsername;
@Inject
@Named("github.password")
private String gitHubPassword;
public synchronized void updateGithubKey() throws Exception {
testSshServiceClient.deleteVCSKey(GITHUB_COM);
try {
String publicKey = testSshServiceClient.generateVCSKey(GITHUB_COM);
testGitHubServiceClient.uploadPublicKey(
gitHubUsername, gitHubPassword, publicKey, "Eclipse Che Key");
} catch (ConflictException e) {
// ignore if ssh-key for github.com has already existed
LOG.debug("Ssh key for {} has already existed.", GITHUB_COM);
return;
}
LOG.debug("Ssh key for {} has been generated.", GITHUB_COM);
}
}

View File

@ -1,453 +0,0 @@
/*
* Copyright (c) 2012-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
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.selenium.core.client;
import static java.lang.String.format;
import static org.eclipse.che.selenium.core.utils.WaitUtils.sleepQuietly;
import com.google.inject.Inject;
import com.google.inject.name.Named;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PreDestroy;
import org.apache.commons.io.IOUtils;
import org.eclipse.che.commons.lang.NameGenerator;
import org.kohsuke.github.GHCommit;
import org.kohsuke.github.GHContent;
import org.kohsuke.github.GHFileNotFoundException;
import org.kohsuke.github.GHRef;
import org.kohsuke.github.GHRepository;
import org.kohsuke.github.GitHub;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* This is facade and helper for {@link GHRepository}.
*
* @author Dmytro Nochevnov
*/
public class TestGitHubRepository {
private static final int GITHUB_OPERATION_TIMEOUT_SEC = 1;
private static final int REPO_CREATION_ATTEMPTS = 6;
private final String repoName = NameGenerator.generate("EclipseCheTestRepo-", 5);
private static final Logger LOG = LoggerFactory.getLogger(TestGitHubRepository.class);
private GHRepository ghRepo;
private final GitHub gitHub;
private final String gitHubUsername;
private final String gitHubPassword;
private final List<TestGitHubRepository> submodules = new ArrayList<>();
/**
* Creates repository with semi-random name on GitHub for certain {@code gitHubUsername}. Waits
* until repository is really created.
*
* @param gitHubUsername github user name
* @param gitHubPassword github user password
* @throws IOException
*/
@Inject
public TestGitHubRepository(
@Named("github.username") String gitHubUsername,
@Named("github.password") String gitHubPassword)
throws IOException {
gitHub = GitHub.connectUsingPassword(gitHubUsername, gitHubPassword);
ghRepo = create();
this.gitHubUsername = gitHubUsername;
this.gitHubPassword = gitHubPassword;
}
/**
* Gets repository on GitHub with predefined name for certain {@code gitHubUsername}.
*
* @param gitHubUsername github user name
* @param gitHubPassword github user password
* @param repoName name of repo on GitHub
* @throws IOException
*/
public TestGitHubRepository(String gitHubUsername, String gitHubPassword, String repoName)
throws IOException {
gitHub = GitHub.connectUsingPassword(gitHubUsername, gitHubPassword);
ghRepo = gitHub.getRepository(gitHubUsername + "/" + repoName);
this.gitHubUsername = gitHubUsername;
this.gitHubPassword = gitHubPassword;
}
public enum TreeElementMode {
BLOB("100644"),
EXECUTABLE_BLOB("100755"),
SUBDIRECTORY("040000"),
SUBMODULE("160000"),
BLOB_SYMLINK("120000");
private final String mode;
TreeElementMode(String mode) {
this.mode = mode;
}
public String get() {
return this.mode;
}
}
public enum GitNodeType {
BLOB("blob"),
TREE("tree"),
COMMIT("commit");
private final String nodeType;
GitNodeType(String nodeType) {
this.nodeType = nodeType;
}
public String get() {
return this.nodeType;
}
}
public String getName() {
return repoName;
}
public String getFullName() {
return ghRepo.getFullName();
}
public String getSha1(String branchName) throws IOException {
return ghRepo.getBranch(branchName).getSHA1();
}
/**
* Creates reference to the new branch with {@code branch} from default branch.
*
* @param branchName name of the branch which should be created
* @return reference to the new branch
* @throws IOException
*/
public GHRef createBranch(String branchName) throws IOException {
GHRef defaultBranch = getReferenceToDefaultBranch();
return ghRepo.createRef("refs/heads/" + branchName, defaultBranch.getObject().getSha());
}
/**
* Creates reference to the new tag with {@code tagName} from default branch.
*
* @param tagName is a name of new tag
* @return reference to the new tag
* @throws IOException
*/
public GHRef createTag(String tagName) throws IOException {
GHRef defaultBranch = getReferenceToDefaultBranch();
return ghRepo.createRef("refs/tags/" + tagName, defaultBranch.getObject().getSha());
}
private GHRef getReferenceToDefaultBranch() throws IOException {
return ghRepo.getRef("heads/" + ghRepo.getDefaultBranch());
}
public void setDefaultBranch(String branchName) throws IOException {
ghRepo.setDefaultBranch(branchName);
ghRepo = gitHub.getRepository(ghRepo.getFullName());
}
/**
* Copies content of directory {@code pathToRootContentDirectory} to the GitHub repository. It
* tries to recreate the file ones again in case of FileNotFoundException occurs.
*
* @param pathToRootContentDirectory path to the directory with content
* @throws IOException
*/
public void addContent(Path pathToRootContentDirectory) throws IOException {
addContent(pathToRootContentDirectory, null);
}
/**
* Copies content of directory {@code pathToRootContentDirectory} to the specified branch in the
* GitHub repository. It tries to recreate the file ones again in case of FileNotFoundException
* occurs.
*
* @param pathToRootContentDirectory path to the directory with content
* @param branch name of the target branch
* @throws IOException
*/
public void addContent(Path pathToRootContentDirectory, String branch) throws IOException {
Files.walk(pathToRootContentDirectory)
.filter(Files::isRegularFile)
.forEach(
pathToFile -> {
try {
createFile(pathToRootContentDirectory, pathToFile, branch);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
});
}
/**
* Changes content of the file
*
* @param pathToFile path to specified file
* @param content content to change
* @throws IOException
*/
public void changeFileContent(String pathToFile, String content) throws IOException {
changeFileContent(pathToFile, content, format("Change file %s", pathToFile));
}
/**
* Changes content of the file
*
* @param pathToFile path to specified file
* @param content content to change
* @param commitMessage message to commit
* @throws IOException
*/
public void changeFileContent(String pathToFile, String content, String commitMessage)
throws IOException {
ghRepo.getFileContent(String.format("/%s", pathToFile)).update(content, commitMessage);
}
public void deleteFile(String pathToFile) throws IOException {
ghRepo.getFileContent(pathToFile).delete("Delete file " + pathToFile);
}
/**
* Delete folder with content inside the repository on GitHub.
*
* @param folder folder to delete
* @param deleteCommitMessage commit message which is used to delete the message
* @throws IOException
*/
public void deleteFolder(Path folder, String deleteCommitMessage) throws IOException {
for (GHContent ghContent : ghRepo.getDirectoryContent(folder.toString())) {
ghContent.delete(deleteCommitMessage);
}
}
@PreDestroy
public void delete() {
try {
ghRepo.delete();
} catch (IOException e) {
throw new RuntimeException(e.getMessage(), e);
}
submodules.forEach(TestGitHubRepository::delete);
LOG.info("GitHub repo {} has been removed", ghRepo.getHtmlUrl());
}
public static void deleteAllRepos(String repoPrefix, String gitHubUsername, String gitHubPassword)
throws IOException {
GitHub gitHub = GitHub.connectUsingPassword(gitHubUsername, gitHubPassword);
gitHub
.getMyself()
.getAllRepositories()
.keySet()
.stream()
.filter(repoName -> repoName.startsWith(repoPrefix))
.forEach(
repoName -> {
String repoAddress = gitHubUsername + "/" + repoName;
LOG.info("Removing repo " + repoAddress + "...");
try {
gitHub.getRepository(repoAddress).delete();
} catch (IOException e) {
e.printStackTrace();
}
});
}
public String getHtmlUrl() {
return ghRepo.getHtmlUrl().toString();
}
public String getHttpsTransportUrl() {
return ghRepo.gitHttpTransportUrl();
}
public String getSshUrl() {
return ghRepo.getSshUrl();
}
private GHRepository create() throws IOException {
GHRepository repo = gitHub.createRepository(repoName).create();
ensureRepositoryCreated(repo, System.currentTimeMillis());
LOG.info("GitHub repo {} has been created", repo.getHtmlUrl());
return repo;
}
private void ensureRepositoryCreated(GHRepository repo, long startCreationTimeInMillisec)
throws IOException {
Throwable lastIOException = null;
for (int i = 0; i < REPO_CREATION_ATTEMPTS; i++) {
try {
gitHub.getRepository(repo.getFullName());
return;
} catch (IOException e) {
lastIOException = e;
LOG.info("Waiting for {} to be created", repo.getHtmlUrl());
sleepQuietly(GITHUB_OPERATION_TIMEOUT_SEC); // sleep one second
}
}
long durationOfRepoCreationInSec =
(System.currentTimeMillis() - startCreationTimeInMillisec) / 1000;
throw new IOException(
format(
"GitHub repo %s hasn't been created in %s seconds",
repo.getHtmlUrl(), durationOfRepoCreationInSec),
lastIOException);
}
/**
* Creates file in GitHub repository in the specified {@code branch}.
*
* @param pathToRootContentDirectory path to the root directory of file locally
* @param pathToFile path to file locally
* @param branch name of the target branch
* @throws IOException
*/
private void createFile(Path pathToRootContentDirectory, Path pathToFile, String branch)
throws IOException {
byte[] contentBytes = Files.readAllBytes(pathToFile);
String relativePath = pathToRootContentDirectory.relativize(pathToFile).toString();
String commitMessage = String.format("Add file %s", relativePath);
try {
ghRepo.createContent(contentBytes, commitMessage, relativePath, branch);
} catch (GHFileNotFoundException e) {
// try to create content once again
LOG.warn(
"Error of creation of {} occurred. Is trying to create it once again...",
ghRepo.getHtmlUrl() + "/" + relativePath);
sleepQuietly(GITHUB_OPERATION_TIMEOUT_SEC);
ghRepo.createContent(contentBytes, commitMessage, relativePath);
}
}
public String getFileContent(String pathToFile) throws IOException {
return IOUtils.toString(ghRepo.getFileContent(pathToFile).read(), "UTF-8");
}
public String getDefaultBranchSha() throws IOException {
return getReferenceToDefaultBranch().getObject().getSha();
}
public void addSubmodule(Path pathToRootContentDirectory, String submoduleName)
throws IOException {
TestGitHubRepository submodule = new TestGitHubRepository(gitHubUsername, gitHubPassword);
submodule.addContent(pathToRootContentDirectory);
createSubmodule(submodule, submoduleName);
submodules.add(submodule);
}
private void createSubmodule(
TestGitHubRepository pathToRootContentDirectory, String pathForSubmodule) throws IOException {
String submoduleSha = createTreeWithSubmodule(pathToRootContentDirectory, pathForSubmodule);
GHCommit treeCommit =
ghRepo.createCommit().tree(submoduleSha).message("Create submodule").create();
getReferenceToDefaultBranch().updateTo(treeCommit.getSHA1(), true);
setupSubmoduleConfig(pathToRootContentDirectory, pathForSubmodule);
}
private boolean isGitmodulesFileExist() throws IOException {
return 0
< ghRepo
.getDirectoryContent("")
.stream()
.filter(item -> item.getName().equals(".gitmodules"))
.count();
}
private String createTreeWithSubmodule(TestGitHubRepository submodule, String pathForSubmodule)
throws IOException {
return ghRepo
.createTree()
.baseTree(this.getDefaultBranchSha())
.entry(
pathForSubmodule,
TreeElementMode.SUBMODULE.get(),
GitNodeType.COMMIT.get(),
submodule.getDefaultBranchSha(),
null)
.create()
.getSha();
}
private String getSubmoduleConfig(TestGitHubRepository submodule, String pathToSubmoduleContent) {
String repoName = Paths.get(pathToSubmoduleContent).getFileName().toString();
String repoUrl = submodule.getHtmlUrl() + ".git";
String modulePattern = "[submodule \"%s\"]\n\tpath = %s\n\turl = %s";
return String.format(modulePattern, repoName, pathToSubmoduleContent, repoUrl);
}
/**
* Creates ".gitmodules" file or updates if it already exist.
*
* @see <a href="https://git-scm.com/docs/gitmodules">gitmodules </a>
*/
private void setupSubmoduleConfig(TestGitHubRepository submodule, String pathToSubmoduleContent)
throws IOException {
final String gitmodulesFileName = ".gitmodules";
String submoduleConfig = getSubmoduleConfig(submodule, pathToSubmoduleContent);
if (isGitmodulesFileExist()) {
GHContent submoduleFileContent = ghRepo.getFileContent(gitmodulesFileName);
String newFileContent = getFileContent(gitmodulesFileName) + "\n" + submoduleConfig;
submoduleFileContent.update(newFileContent, "Update " + gitmodulesFileName);
return;
}
ghRepo.createContent(submoduleConfig, "Add " + gitmodulesFileName, gitmodulesFileName);
}
public String getPullRequestTitle(int requestNumber) throws IOException {
return ghRepo.getPullRequest(requestNumber).getTitle();
}
public String getPullRequestBaseBranchName(int requestNumber) throws IOException {
return ghRepo.getPullRequest(requestNumber).getBase().getRef();
}
public String getPullRequestHeadBranchName(int requestNumber) throws IOException {
return ghRepo.getPullRequest(requestNumber).getHead().getRef();
}
public String getPullRequestBody(int requestNumber) throws IOException {
return ghRepo.getPullRequest(requestNumber).getBody();
}
public String getPullRequestUserName(int requestNumber) throws IOException {
return ghRepo.getPullRequest(requestNumber).getUser().getLogin();
}
}

View File

@ -1,228 +0,0 @@
/*
* Copyright (c) 2012-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
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.selenium.core.client;
import static java.util.Optional.ofNullable;
import static java.util.stream.Collectors.toList;
import static org.eclipse.che.dto.server.DtoFactory.newDto;
import static org.slf4j.LoggerFactory.getLogger;
import com.google.common.collect.ImmutableMap;
import com.google.common.reflect.TypeToken;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Base64;
import java.util.List;
import java.util.Map;
import org.eclipse.che.api.core.ApiException;
import org.eclipse.che.api.core.rest.HttpJsonRequestFactory;
import org.eclipse.che.api.core.rest.HttpJsonResponse;
import org.eclipse.che.dto.server.JsonStringMapImpl;
import org.slf4j.Logger;
/** @author Mihail Kuznyetsov. */
@Singleton
public class TestGitHubServiceClient {
private static final Logger LOG = getLogger(TestGitHubServiceClient.class);
private final HttpJsonRequestFactory requestFactory;
@Inject
public TestGitHubServiceClient(HttpJsonRequestFactory requestFactory) {
this.requestFactory = requestFactory;
}
public void deletePublicKeys(final String username, final String password, final String keyTitle)
throws Exception {
List<GitHubKey> keys = getPublicKeys(username, password, keyTitle);
for (GitHubKey key : keys) {
requestFactory
.fromUrl(key.getUrl())
.setAuthorizationHeader(createBasicAuthHeader(username, password))
.useDeleteMethod()
.request();
}
}
public void createPublicKey(final String username, final String password, final GitHubKey key)
throws Exception {
requestFactory
.fromUrl("https://api.github.com/user/keys")
.setAuthorizationHeader(createBasicAuthHeader(username, password))
.usePostMethod()
.setBody(key)
.request();
}
public void uploadPublicKey(
final String username, final String password, final String key, String keyTitle)
throws Exception {
GitHubKey publicSshKey = newDto(GitHubKey.class);
publicSshKey.setTitle(keyTitle);
publicSshKey.setKey(key);
deletePublicKeys(username, password, keyTitle);
createPublicKey(username, password, publicSshKey);
}
public List<GitHubKey> getPublicKeys(
final String username, final String password, final String title) throws Exception {
List<GitHubKey> keys =
requestFactory
.fromUrl("https://api.github.com/user/keys")
.setAuthorizationHeader(createBasicAuthHeader(username, password))
.useGetMethod()
.request()
.asList(GitHubKey.class);
return keys.stream().filter(key -> title.equals(key.getTitle())).collect(toList());
}
public void hardResetHeadToCommit(
final String repository, final String commitSha, final String username, final String password)
throws Exception {
ImmutableMap<String, Object> m = ImmutableMap.of("sha", commitSha, "force", true);
String url =
"https://api.github.com/repos/" + username + "/" + repository + "/git/refs/heads/master";
requestFactory
.fromUrl(url)
.usePostMethod()
.setAuthorizationHeader(createBasicAuthHeader(username, password))
.setBody(new JsonStringMapImpl<Object>(m))
.request();
}
@SuppressWarnings("unchecked")
public List<String> getNumbersOfOpenedPullRequests(
final String repository, final String username, final String password) throws Exception {
String url = "https://api.github.com/repos/" + username + "/" + repository + "/pulls";
HttpJsonResponse response =
requestFactory
.fromUrl(url)
.useGetMethod()
.setAuthorizationHeader(createBasicAuthHeader(username, password))
.request();
List<Map<String, String>> prs =
response.as(List.class, new TypeToken<List<Map<String, String>>>() {}.getType());
return prs.stream()
.filter(g -> g.get("state").equals("open"))
.map(g -> g.get("number"))
.collect(toList());
}
public void closePullRequest(
final String repo, final String number, final String username, final String password)
throws Exception {
String url = "https://api.github.com/repos/" + username + "/" + repo + "/pulls/" + number;
requestFactory
.fromUrl(url)
.usePostMethod()
.setAuthorizationHeader(createBasicAuthHeader(username, password))
.setBody(ImmutableMap.of("state", "close"))
.request();
}
public void deleteBranch(
final String repository,
final String branchName,
final String username,
final String password)
throws Exception {
String url =
"https://api.github.com/repos/"
+ username
+ "/"
+ repository
+ "/git/refs/heads/"
+ branchName;
requestFactory
.fromUrl(url)
.useDeleteMethod()
.setAuthorizationHeader(createBasicAuthHeader(username, password))
.request();
}
public void deleteRepo(final String repository, final String username, final String password)
throws Exception {
String url = "https://api.github.com/repos/" + username + "/" + repository;
requestFactory
.fromUrl(url)
.useDeleteMethod()
.setAuthorizationHeader(createBasicAuthHeader(username, password))
.request();
}
public List<String> getAllGrants(final String username, final String password) throws Exception {
String url = "https://api.github.com/applications/grants";
HttpJsonResponse response =
requestFactory
.fromUrl(url)
.useGetMethod()
.setAuthorizationHeader(createBasicAuthHeader(username, password))
.request();
@SuppressWarnings("unchecked")
List<Map<String, String>> grants =
response.as(List.class, new TypeToken<List<Map<String, String>>>() {}.getType());
return grants.stream().map(g -> g.get("id")).collect(toList());
}
public void deleteAllGrants(final String username, final String password) throws Exception {
List<String> grandsId = getAllGrants(username, password);
for (String grandId : grandsId) {
String url = "https://api.github.com/applications/grants/" + grandId;
requestFactory
.fromUrl(url)
.useDeleteMethod()
.setAuthorizationHeader(createBasicAuthHeader(username, password))
.request();
}
LOG.debug("Application grants '{}' were removed from github.com", grandsId);
}
public String getName(final String username, final String password)
throws IOException, ApiException {
String url = "https://api.github.com/users/" + username;
HttpJsonResponse response =
requestFactory
.fromUrl(url)
.useGetMethod()
.setAuthorizationHeader(createBasicAuthHeader(username, password))
.request();
return obtainNameFromResponse(response);
}
/**
* Obtain name of github user from github response
*
* @param response
* @return name if it presents in response and != null, or login otherwise.
*/
private String obtainNameFromResponse(HttpJsonResponse response) throws IOException {
Map<String, String> properties = response.asProperties();
String login = properties.get("login");
return ofNullable(properties.getOrDefault("name", login)).orElse(login);
}
private String createBasicAuthHeader(String username, String password)
throws UnsupportedEncodingException {
byte[] nameAndPass = (username + ":" + password).getBytes("UTF-8");
String base64 = Base64.getEncoder().encodeToString(nameAndPass);
return "Basic " + base64;
}
}

View File

@ -1,25 +0,0 @@
/*
* Copyright (c) 2012-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
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.selenium.core.client;
/** @author Musienko Maxim */
public interface TestMachineServiceClient {
/**
* Returns machine token for current workspace
*
* @param authToken the authorization token
* @param workspaceId the workspace id
* @return the machine token for current workspace
*/
String getMachineApiToken(String workspaceId) throws Exception;
}

View File

@ -1,163 +0,0 @@
/*
* Copyright (c) 2012-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
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.selenium.core.client;
import static java.lang.String.format;
import static java.util.Arrays.asList;
import static org.eclipse.che.dto.server.DtoFactory.newDto;
import com.google.inject.assistedinject.Assisted;
import com.google.inject.assistedinject.AssistedInject;
import java.util.List;
import org.eclipse.che.api.core.NotFoundException;
import org.eclipse.che.api.core.rest.HttpJsonRequestFactory;
import org.eclipse.che.commons.annotation.Nullable;
import org.eclipse.che.multiuser.api.permission.shared.dto.PermissionsDto;
import org.eclipse.che.multiuser.organization.shared.dto.OrganizationDto;
import org.eclipse.che.selenium.core.provider.TestApiEndpointUrlProvider;
import org.eclipse.che.selenium.core.requestfactory.TestUserHttpJsonRequestFactoryCreator;
import org.eclipse.che.selenium.core.user.TestUser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** This util is handling the requests to Organization API. */
public class TestOrganizationServiceClient {
private static final Logger LOG = LoggerFactory.getLogger(TestOrganizationServiceClient.class);
private final String apiEndpoint;
private final HttpJsonRequestFactory requestFactory;
public TestOrganizationServiceClient(
TestApiEndpointUrlProvider apiEndpointUrlProvider, HttpJsonRequestFactory requestFactory) {
this.apiEndpoint = apiEndpointUrlProvider.get().toString();
this.requestFactory = requestFactory;
}
@AssistedInject
public TestOrganizationServiceClient(
TestApiEndpointUrlProvider apiEndpointUrlProvider,
TestUserHttpJsonRequestFactoryCreator testUserHttpJsonRequestFactoryCreator,
@Assisted TestUser testUser) {
this.apiEndpoint = apiEndpointUrlProvider.get().toString();
this.requestFactory = testUserHttpJsonRequestFactoryCreator.create(testUser);
}
public List<OrganizationDto> getAll() throws Exception {
return requestFactory.fromUrl(getApiUrl()).request().asList(OrganizationDto.class);
}
public List<OrganizationDto> getAllRoot() throws Exception {
List<OrganizationDto> organizations =
requestFactory.fromUrl(getApiUrl()).request().asList(OrganizationDto.class);
organizations.removeIf(o -> o.getParent() != null);
return organizations;
}
private String getApiUrl() {
return apiEndpoint + "organization/";
}
public OrganizationDto create(String name, @Nullable String parentId) throws Exception {
OrganizationDto data = newDto(OrganizationDto.class).withName(name).withParent(parentId);
OrganizationDto organizationDto =
requestFactory
.fromUrl(getApiUrl())
.setBody(data)
.usePostMethod()
.request()
.asDto(OrganizationDto.class);
LOG.info(
"Organization with name='{}', id='{}', parent's id='{}' created",
name,
organizationDto.getId(),
parentId);
return organizationDto;
}
public OrganizationDto create(String name) throws Exception {
return create(name, null);
}
public void deleteById(String id) throws Exception {
String apiUrl = format("%s%s", getApiUrl(), id);
try {
requestFactory.fromUrl(apiUrl).useDeleteMethod().request();
LOG.info("Organization with id='{}' removed", id);
} catch (NotFoundException e) {
// ignore if there is no organization of certain id
}
}
public void deleteByName(String name) throws Exception {
try {
String organizationId = get(name).getId();
deleteById(organizationId);
} catch (NotFoundException e) {
// ignore if there is no organization of certain id
}
}
public void deleteAll() throws Exception {
getAll()
.stream()
.filter(organization -> organization.getParent() != null)
.forEach(
organization -> {
try {
deleteById(organization.getId());
} catch (Exception e) {
throw new RuntimeException(e.getMessage(), e);
}
});
}
public OrganizationDto get(String organizationName) throws Exception {
String apiUrl = format("%sfind?name=%s", getApiUrl(), organizationName);
return requestFactory.fromUrl(apiUrl).request().asDto(OrganizationDto.class);
}
public void addMember(String organizationId, String userId) throws Exception {
addMember(organizationId, userId, asList("createWorkspaces"));
}
public void addAdmin(String organizationId, String userId) throws Exception {
addMember(
organizationId,
userId,
asList(
"update",
"setPermissions",
"manageResources",
"manageWorkspaces",
"createWorkspaces",
"delete",
"manageSuborganizations"));
}
public void addMember(String organizationId, String userId, List<String> actions)
throws Exception {
String apiUrl = apiEndpoint + "permissions";
PermissionsDto data =
newDto(PermissionsDto.class)
.withDomainId("organization")
.withInstanceId(organizationId)
.withUserId(userId)
.withActions(actions);
requestFactory.fromUrl(apiUrl).setBody(data).usePostMethod().request();
}
}

View File

@ -1,20 +0,0 @@
/*
* Copyright (c) 2012-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
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.selenium.core.client;
import com.google.inject.assistedinject.Assisted;
import org.eclipse.che.selenium.core.user.TestUser;
/** @author Dmytro Nochevnov */
public interface TestOrganizationServiceClientFactory {
TestOrganizationServiceClient create(@Assisted TestUser testUser);
}

View File

@ -1,55 +0,0 @@
/*
* Copyright (c) 2012-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
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.selenium.core.client;
import com.google.common.collect.ImmutableMap;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.util.Map;
import org.eclipse.che.api.core.rest.HttpJsonRequestFactory;
import org.eclipse.che.selenium.core.provider.TestApiEndpointUrlProvider;
import org.eclipse.che.selenium.core.user.DefaultTestUser;
/** @author Musienko Maxim */
@Singleton
public class TestProfileServiceClient {
private final String apiEndpoint;
private final HttpJsonRequestFactory requestFactory;
private final DefaultTestUser defaultTestUser;
@Inject
public TestProfileServiceClient(
TestApiEndpointUrlProvider apiEndpointProvider,
HttpJsonRequestFactory requestFactory,
DefaultTestUser defaultTestUser) {
this.apiEndpoint = apiEndpointProvider.get().toString();
this.requestFactory = requestFactory;
this.defaultTestUser = defaultTestUser;
}
public void setAttributes(Map<String, String> attributes) throws Exception {
requestFactory
.fromUrl(apiEndpoint + "profile/attributes")
.usePutMethod()
.setBody(attributes)
.request();
}
public void setUserNames(String name, String lastName) throws Exception {
Map<String, String> attributes =
ImmutableMap.of(
"firstName", name,
"lastName", lastName);
setAttributes(attributes);
}
}

View File

@ -1,325 +0,0 @@
/*
* Copyright (c) 2012-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
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.selenium.core.client;
import static com.google.common.base.Charsets.UTF_8;
import static com.google.common.io.Resources.getResource;
import static com.google.common.io.Resources.toByteArray;
import static java.lang.String.format;
import static java.nio.file.Files.createFile;
import static java.nio.file.Files.write;
import static java.util.Optional.ofNullable;
import static org.eclipse.che.dto.server.DtoFactory.getInstance;
import static org.eclipse.che.selenium.core.project.ProjectTemplates.PLAIN_JAVA;
import com.google.common.io.Resources;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.zip.ZipOutputStream;
import org.eclipse.che.api.core.model.workspace.config.ProjectConfig;
import org.eclipse.che.api.core.rest.HttpJsonRequestFactory;
import org.eclipse.che.api.workspace.shared.dto.ProjectConfigDto;
import org.eclipse.che.api.workspace.shared.dto.SourceStorageDto;
import org.eclipse.che.commons.lang.IoUtil;
import org.eclipse.che.commons.lang.ZipUtils;
import org.eclipse.che.selenium.core.provider.TestWorkspaceAgentApiEndpointUrlProvider;
/**
* @author Musienko Maxim
* @author Mykola Morhun
*/
@Singleton
public class TestProjectServiceClient {
private static final String BEARER_TOKEN_PREFIX = "Bearer ";
private final TestMachineServiceClient machineServiceClient;
private final HttpJsonRequestFactory requestFactory;
private final TestWorkspaceAgentApiEndpointUrlProvider workspaceAgentApiEndpointUrlProvider;
@Inject
public TestProjectServiceClient(
TestMachineServiceClient machineServiceClient,
HttpJsonRequestFactory requestFactory,
TestWorkspaceAgentApiEndpointUrlProvider workspaceAgentApiEndpointUrlProvider) {
this.machineServiceClient = machineServiceClient;
this.requestFactory = requestFactory;
this.workspaceAgentApiEndpointUrlProvider = workspaceAgentApiEndpointUrlProvider;
}
/** Set type for existing project on vfs */
public void setProjectType(String workspaceId, String template, String projectName)
throws Exception {
InputStream in = getClass().getResourceAsStream("/templates/project/" + template);
String json = IoUtil.readAndCloseQuietly(in);
ProjectConfigDto project = getInstance().createDtoFromJson(json, ProjectConfigDto.class);
project.setName(projectName);
requestFactory
.fromUrl(workspaceAgentApiEndpointUrlProvider.get(workspaceId) + "project/" + projectName)
.usePutMethod()
.setAuthorizationHeader(
BEARER_TOKEN_PREFIX + machineServiceClient.getMachineApiToken(workspaceId))
.setBody(project)
.request();
}
/** Delete resource. */
public void deleteResource(String workspaceId, String path) throws Exception {
requestFactory
.fromUrl(workspaceAgentApiEndpointUrlProvider.get(workspaceId) + "project/" + path)
.setAuthorizationHeader(
BEARER_TOKEN_PREFIX + machineServiceClient.getMachineApiToken(workspaceId))
.useDeleteMethod()
.request();
}
public void createFolder(String workspaceId, String folder) throws Exception {
String url = workspaceAgentApiEndpointUrlProvider.get(workspaceId) + "project/folder/" + folder;
requestFactory
.fromUrl(url)
.setAuthorizationHeader(
BEARER_TOKEN_PREFIX + machineServiceClient.getMachineApiToken(workspaceId))
.usePostMethod()
.request();
}
/** Import zip project from file system into user workspace. */
public void importZipProject(
String workspaceId, Path zipFile, String projectName, String template) throws Exception {
String url =
workspaceAgentApiEndpointUrlProvider.get(workspaceId) + "project/import/" + projectName;
// createFolder(workspaceId, projectName);
HttpURLConnection httpConnection = null;
try {
httpConnection = (HttpURLConnection) new URL(url).openConnection();
httpConnection.setRequestMethod("POST");
httpConnection.setRequestProperty("Content-Type", "application/zip");
httpConnection.addRequestProperty(
"Authorization",
BEARER_TOKEN_PREFIX + machineServiceClient.getMachineApiToken(workspaceId));
httpConnection.setDoOutput(true);
try (OutputStream outputStream = httpConnection.getOutputStream()) {
Files.copy(zipFile, outputStream);
if (httpConnection.getResponseCode() != 201) {
throw new RuntimeException(
"Cannot deploy requested project using ProjectServiceClient REST API. Server response "
+ httpConnection.getResponseCode()
+ " "
+ IoUtil.readStream(httpConnection.getErrorStream())
+ "REST url: "
+ url);
}
}
} finally {
ofNullable(httpConnection).ifPresent(HttpURLConnection::disconnect);
}
setProjectType(workspaceId, template, projectName);
}
/** Import project from file system into a user workspace */
public void importProject(
String workspaceId, Path sourceFolder, String projectName, String template) throws Exception {
if (!Files.exists(sourceFolder)) {
throw new IOException(format("%s not found", sourceFolder));
}
if (!Files.isDirectory(sourceFolder)) {
throw new IOException(format("%s not a directory", sourceFolder));
}
Path zip = Files.createTempFile("project", projectName);
try (ZipOutputStream out = ZipUtils.stream(zip)) {
ZipUtils.add(out, sourceFolder, sourceFolder);
if (PLAIN_JAVA.equals(template)) {
Path tmpDir = Files.createTempDirectory("TestProject");
Path dotClasspath = createFile(tmpDir.resolve(".classpath"));
Path dotProject = Files.createFile(tmpDir.resolve(".project"));
write(
dotProject,
format(
Resources.toString(getResource("projects/jdt-ls-project-files/project"), UTF_8),
projectName)
.getBytes(UTF_8));
write(dotClasspath, toByteArray(getResource("projects/jdt-ls-project-files/classpath")));
ZipUtils.add(out, dotClasspath);
ZipUtils.add(out, dotProject);
}
}
importZipProject(workspaceId, zip, projectName, template);
}
/** Import project from file system into a user workspace */
public void importProject(
String workspaceId,
String projectName,
String location,
String type,
Map<String, String> parameters)
throws Exception {
SourceStorageDto source = getInstance().createDto(SourceStorageDto.class);
source.setLocation(location);
source.setType(type);
source.setParameters(parameters);
importProject(workspaceId, projectName, source);
}
/** Import project from file system into a user workspace */
public void importProject(String workspaceId, String projectName, SourceStorageDto source)
throws Exception {
requestFactory
.fromUrl(
workspaceAgentApiEndpointUrlProvider.get(workspaceId) + "project/import/" + projectName)
.usePostMethod()
.setAuthorizationHeader(machineServiceClient.getMachineApiToken(workspaceId))
.setBody(source)
.request();
}
/** Creates file in the project. */
public void createFileInProject(
String workspaceId, String parentFolder, String fileName, String content) throws Exception {
String apiRESTUrl =
workspaceAgentApiEndpointUrlProvider.get(workspaceId)
+ "project/file/"
+ parentFolder
+ "?name="
+ fileName;
HttpURLConnection httpConnection = null;
try {
httpConnection = (HttpURLConnection) new URL(apiRESTUrl).openConnection();
httpConnection.setRequestMethod("POST");
httpConnection.setRequestProperty("Content-Type", "text/plain");
httpConnection.addRequestProperty(
"Authorization",
BEARER_TOKEN_PREFIX + machineServiceClient.getMachineApiToken(workspaceId));
httpConnection.setDoOutput(true);
try (OutputStream output = httpConnection.getOutputStream()) {
output.write(content.getBytes("UTF-8"));
if (httpConnection.getResponseCode() != 201) {
throw new RuntimeException(
"Cannot create requested content in the current project: "
+ apiRESTUrl
+ " something went wrong "
+ httpConnection.getResponseCode()
+ IoUtil.readStream(httpConnection.getErrorStream()));
}
}
} finally {
ofNullable(httpConnection).ifPresent(HttpURLConnection::disconnect);
}
}
public ProjectConfigDto getFirstProject(String workspaceId) throws Exception {
String apiUrl = workspaceAgentApiEndpointUrlProvider.get(workspaceId) + "project";
return requestFactory
.fromUrl(apiUrl)
.setAuthorizationHeader(
BEARER_TOKEN_PREFIX + machineServiceClient.getMachineApiToken(workspaceId))
.request()
.asList(ProjectConfigDto.class)
.get(0);
}
/** Updates file content. */
public void updateFile(String workspaceId, String pathToFile, String content) throws Exception {
String url =
workspaceAgentApiEndpointUrlProvider.get(workspaceId) + "project/file/" + pathToFile;
HttpURLConnection httpConnection = null;
try {
httpConnection = (HttpURLConnection) new URL(url).openConnection();
httpConnection.setRequestMethod("PUT");
httpConnection.setRequestProperty("Content-Type", "text/plain");
httpConnection.addRequestProperty(
"Authorization",
BEARER_TOKEN_PREFIX + machineServiceClient.getMachineApiToken(workspaceId));
httpConnection.setDoOutput(true);
try (OutputStream output = httpConnection.getOutputStream()) {
output.write(content.getBytes("UTF-8"));
if (httpConnection.getResponseCode() != 200) {
throw new RuntimeException(
"Cannot update content in the current file: "
+ url
+ " something went wrong "
+ httpConnection.getResponseCode()
+ IoUtil.readStream(httpConnection.getErrorStream()));
}
}
} finally {
ofNullable(httpConnection).ifPresent(HttpURLConnection::disconnect);
}
}
public boolean checkProjectType(String wokspaceId, String projectName, String projectType)
throws Exception {
return getProject(wokspaceId, projectName).getType().equals(projectType);
}
public boolean checkProjectLanguage(String workspaceId, String projectName, String language)
throws Exception {
return getProject(workspaceId, projectName).getAttributes().get("language").contains(language);
}
public boolean checkProjectLanguage(
String workspaceId, String projectName, List<String> languages) throws Exception {
return getProject(workspaceId, projectName)
.getAttributes()
.get("language")
.containsAll(languages);
}
public List<String> getExternalLibraries(String workspaceId, String projectName)
throws Exception {
return requestFactory
.fromUrl(
workspaceAgentApiEndpointUrlProvider.get(workspaceId) + "java/navigation/libraries")
.useGetMethod()
.addQueryParam("projectpath", "/" + projectName)
.request()
.asList(ProjectConfigDto.class)
.stream()
.map(e -> e.getName())
.collect(Collectors.toList());
}
private ProjectConfig getProject(String workspaceId, String projectName) throws Exception {
return requestFactory
.fromUrl(workspaceAgentApiEndpointUrlProvider.get(workspaceId) + "project/" + projectName)
.useGetMethod()
.setAuthorizationHeader(
BEARER_TOKEN_PREFIX + machineServiceClient.getMachineApiToken(workspaceId))
.request()
.asDto(ProjectConfigDto.class);
}
}

View File

@ -1,84 +0,0 @@
/*
* Copyright (c) 2012-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
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.selenium.core.client;
import static java.lang.String.format;
import static org.eclipse.che.dto.server.DtoFactory.newDto;
import static org.slf4j.LoggerFactory.getLogger;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.util.List;
import org.eclipse.che.api.core.NotFoundException;
import org.eclipse.che.api.core.rest.HttpJsonRequestFactory;
import org.eclipse.che.api.core.rest.HttpJsonResponse;
import org.eclipse.che.api.ssh.shared.dto.GenerateSshPairRequest;
import org.eclipse.che.api.ssh.shared.dto.SshPairDto;
import org.eclipse.che.selenium.core.provider.TestApiEndpointUrlProvider;
import org.slf4j.Logger;
/** @author Musienko Maxim */
@Singleton
public class TestSshServiceClient {
private static final Logger LOG = getLogger(TestSshServiceClient.class);
private static final String MACHINE_SERVICE = "machine";
private static final String VCS_SERVICE = "vcs";
private final String apiEndpoint;
private final HttpJsonRequestFactory requestFactory;
@Inject
public TestSshServiceClient(
TestApiEndpointUrlProvider apiEndpointProvider, HttpJsonRequestFactory requestFactory) {
this.apiEndpoint = apiEndpointProvider.get().toString();
this.requestFactory = requestFactory;
}
public String getPrivateMachineKey(String keyName) throws Exception {
HttpJsonResponse request =
requestFactory
.fromUrl(format("%sssh/%s/?name=%s", apiEndpoint, MACHINE_SERVICE, keyName))
.useGetMethod()
.request();
List<SshPairDto> sshPair = request.asList(SshPairDto.class);
return sshPair.isEmpty() ? null : sshPair.get(0).getPrivateKey();
}
public String generateVCSKey(String keyName) throws Exception {
GenerateSshPairRequest generateSshKeyData =
newDto(GenerateSshPairRequest.class).withName(keyName).withService(VCS_SERVICE);
HttpJsonResponse response =
requestFactory
.fromUrl(apiEndpoint + "ssh/generate")
.usePostMethod()
.setBody(generateSshKeyData)
.request();
return response.asDto(SshPairDto.class).getPublicKey();
}
public void deleteVCSKey(String keyName) throws Exception {
deleteKey(VCS_SERVICE, keyName);
}
private void deleteKey(String serviceName, String keyName) throws Exception {
try {
requestFactory
.fromUrl(format("%sssh/%s/?name=%s", apiEndpoint, serviceName, keyName))
.useDeleteMethod()
.request();
} catch (NotFoundException e) {
// ignore absence of key
LOG.debug("Ssh key for '{}' with name '{}' is absent.", serviceName, keyName);
}
}
}

View File

@ -1,85 +0,0 @@
/*
* Copyright (c) 2012-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
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.selenium.core.client;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.io.IOException;
import org.eclipse.che.api.core.BadRequestException;
import org.eclipse.che.api.core.ConflictException;
import org.eclipse.che.api.core.ForbiddenException;
import org.eclipse.che.api.core.NotFoundException;
import org.eclipse.che.api.core.ServerException;
import org.eclipse.che.api.core.UnauthorizedException;
import org.eclipse.che.api.core.rest.HttpJsonRequestFactory;
import org.eclipse.che.api.core.rest.HttpJsonResponse;
import org.eclipse.che.selenium.core.provider.TestApiEndpointUrlProvider;
/** @author Musienko Maxim */
@Singleton
public class TestUserPreferencesServiceClient {
private static final String ACTIVATE_CONTRIBUTION_TAB_BY_PROJECT_SELECTION_PROPERTY =
"git.contribute.activate.projectSelection";
private final String apiEndpoint;
private final HttpJsonRequestFactory httpRequestFactory;
@Inject
public TestUserPreferencesServiceClient(
TestApiEndpointUrlProvider apiEndpointProvider, HttpJsonRequestFactory httpRequestFactory)
throws Exception {
this.apiEndpoint = apiEndpointProvider.get().toString();
this.httpRequestFactory = httpRequestFactory;
// Set application.confirmExit property to 'never' to avoid web page closing confirmation pop-up
this.setProperty("theia-user-preferences", "{\"application.confirmExit\":\"never\"}");
}
public void addGitCommitter(String committerName, String committerEmail) throws Exception {
httpRequestFactory
.fromUrl(apiEndpoint + "preferences")
.usePutMethod()
.setBody(
ImmutableMap.of(
"git.committer.name", committerName,
"git.committer.email", committerEmail))
.request();
}
public HttpJsonResponse setProperty(String propertyName, String propertyValue) throws Exception {
return httpRequestFactory
.fromUrl(apiEndpoint + "preferences")
.usePutMethod()
.setBody(ImmutableMap.of(propertyName, propertyValue))
.request();
}
public String getPreferences() throws Exception {
return httpRequestFactory
.fromUrl(apiEndpoint + "preferences")
.useGetMethod()
.request()
.asString();
}
public void restoreDefaultContributionTabPreference()
throws ForbiddenException, BadRequestException, IOException, ConflictException,
NotFoundException, ServerException, UnauthorizedException {
httpRequestFactory
.fromUrl(apiEndpoint + "preferences")
.useDeleteMethod()
.setBody(ImmutableList.of(ACTIVATE_CONTRIBUTION_TAB_BY_PROJECT_SELECTION_PROPERTY))
.request();
}
}

View File

@ -1,79 +0,0 @@
/*
* Copyright (c) 2012-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
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.selenium.core.client;
import org.eclipse.che.api.core.BadRequestException;
import org.eclipse.che.api.core.ConflictException;
import org.eclipse.che.api.core.NotFoundException;
import org.eclipse.che.api.core.ServerException;
import org.eclipse.che.api.core.model.user.User;
/**
* @author Mihail Kuznyetsov
* @author Anton Korneta
*/
public interface TestUserServiceClient {
/**
* Creates user form provided data.
*
* @param name user name
* @param email user email
* @param password user password
* @throws BadRequestException when user data validation failed
* @throws ConflictException when user with given email/name exists
* @throws ServerException when any other exception occurs
*/
void create(String name, String email, String password)
throws BadRequestException, ConflictException, ServerException;
/**
* Gets user by id.
*
* @param id user identifier
* @return user with given identifier
* @throws NotFoundException when user with given id not found
* @throws ServerException when any other exception occurs
*/
User getById(String id) throws NotFoundException, ServerException;
/**
* Gets user by email.
*
* @param email user email
* @return user with given email
* @throws BadRequestException when specified email is null or empty
* @throws NotFoundException User with requested email not found
* @throws ServerException when any other exception occurs
*/
User findByEmail(String email) throws NotFoundException, ServerException, BadRequestException;
/**
* Gets user by name.
*
* @param name user name
* @return user with given name
* @throws BadRequestException when specified name is null or empty
* @throws NotFoundException User with requested name not found
* @throws ServerException when any other exception occurs
*/
User findByName(String name) throws NotFoundException, ServerException, BadRequestException;
/**
* Deletes user by its id.
*
* @param id user identifier
* @throws ConflictException when conflicts occurs e.g. user has related entities
* @throws ServerException when any other exception occurs
*/
void remove(String id) throws ServerException, ConflictException;
}

View File

@ -1,20 +0,0 @@
/*
* Copyright (c) 2012-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
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.selenium.core.client;
import com.google.inject.assistedinject.Assisted;
import org.eclipse.che.selenium.core.user.TestUser;
/** @author Dmytro Nochevnov */
public interface TestUserServiceClientFactory {
TestUserServiceClientImpl create(@Assisted TestUser testUser);
}

View File

@ -1,128 +0,0 @@
/*
* Copyright (c) 2012-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
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.selenium.core.client;
import static org.eclipse.che.dto.server.DtoFactory.newDto;
import com.google.inject.assistedinject.Assisted;
import com.google.inject.assistedinject.AssistedInject;
import java.io.IOException;
import java.net.URLEncoder;
import org.eclipse.che.api.core.BadRequestException;
import org.eclipse.che.api.core.ConflictException;
import org.eclipse.che.api.core.ForbiddenException;
import org.eclipse.che.api.core.NotFoundException;
import org.eclipse.che.api.core.ServerException;
import org.eclipse.che.api.core.UnauthorizedException;
import org.eclipse.che.api.core.model.user.User;
import org.eclipse.che.api.user.shared.dto.UserDto;
import org.eclipse.che.selenium.core.provider.TestApiEndpointUrlProvider;
import org.eclipse.che.selenium.core.requestfactory.TestHttpJsonRequestFactory;
import org.eclipse.che.selenium.core.requestfactory.TestUserHttpJsonRequestFactory;
import org.eclipse.che.selenium.core.requestfactory.TestUserHttpJsonRequestFactoryCreator;
import org.eclipse.che.selenium.core.user.TestUser;
/** @author Musienko Maxim */
public class TestUserServiceClientImpl implements TestUserServiceClient {
private final String userServiceEndpoint;
private final TestHttpJsonRequestFactory requestFactory;
public TestUserServiceClientImpl(
TestApiEndpointUrlProvider apiEndpointProvider,
TestUserHttpJsonRequestFactory userHttpJsonRequestFactory) {
this.userServiceEndpoint = apiEndpointProvider.get().toString() + "user/";
this.requestFactory = userHttpJsonRequestFactory;
}
@AssistedInject
public TestUserServiceClientImpl(
TestApiEndpointUrlProvider apiEndpointProvider,
TestUserHttpJsonRequestFactoryCreator userHttpJsonRequestFactoryCreator,
@Assisted TestUser testUser) {
this(apiEndpointProvider, userHttpJsonRequestFactoryCreator.create(testUser));
}
@Override
public void create(String name, String email, String password)
throws BadRequestException, ConflictException, ServerException {
try {
requestFactory
.fromUrl(userServiceEndpoint)
.usePostMethod()
.setBody(newDto(UserDto.class).withEmail(email).withName(name).withPassword(password))
.request();
} catch (IOException | UnauthorizedException | NotFoundException | ForbiddenException ex) {
throw new ServerException(ex);
}
}
@Override
public User getById(String id) throws NotFoundException, ServerException {
try {
return requestFactory
.fromUrl(userServiceEndpoint + id)
.useGetMethod()
.request()
.asDto(UserDto.class);
} catch (IOException
| BadRequestException
| UnauthorizedException
| ForbiddenException
| ConflictException ex) {
throw new ServerException(ex);
}
}
@Override
public User findByEmail(String email)
throws BadRequestException, NotFoundException, ServerException {
try {
return requestFactory
.fromUrl(userServiceEndpoint + "find")
.useGetMethod()
.addQueryParam("email", URLEncoder.encode(email, "UTF-8"))
.request()
.asDto(UserDto.class);
} catch (IOException | UnauthorizedException | ForbiddenException | ConflictException ex) {
throw new ServerException(ex);
}
}
@Override
public User findByName(String name)
throws BadRequestException, NotFoundException, ServerException {
try {
return requestFactory
.fromUrl(userServiceEndpoint + "find")
.useGetMethod()
.addQueryParam("name", name)
.request()
.asDto(UserDto.class);
} catch (IOException | UnauthorizedException | ForbiddenException | ConflictException ex) {
throw new ServerException(ex);
}
}
@Override
public void remove(String id) throws ConflictException, ServerException {
try {
requestFactory.fromUrl(userServiceEndpoint + id).useDeleteMethod().request();
} catch (IOException
| BadRequestException
| NotFoundException
| UnauthorizedException
| ForbiddenException ex) {
throw new ServerException(ex);
}
}
}

View File

@ -1,68 +0,0 @@
/*
* Copyright (c) 2012-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
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.selenium.core.client;
import java.util.List;
import org.eclipse.che.api.core.model.workspace.Workspace;
import org.eclipse.che.api.core.model.workspace.WorkspaceStatus;
import org.eclipse.che.api.core.model.workspace.runtime.Server;
import org.eclipse.che.api.workspace.shared.dto.WorkspaceConfigDto;
import org.eclipse.che.api.workspace.shared.dto.WorkspaceDto;
import org.eclipse.che.commons.annotation.Nullable;
import org.eclipse.che.selenium.core.user.TestUser;
import org.eclipse.che.selenium.core.workspace.MemoryMeasure;
public interface TestWorkspaceServiceClient {
List<String> getAll() throws Exception;
int getWorkspacesCount() throws Exception;
void stop(String workspaceName, String userName) throws Exception;
Workspace getByName(String workspace, String username) throws Exception;
boolean exists(String workspace, String username) throws Exception;
void delete(String workspaceName, String userName) throws Exception;
void waitStatus(String workspaceName, String userName, WorkspaceStatus expectedStatus)
throws Exception;
void waitWorkspaceStart(String workspaceName, String userName) throws Exception;
/** Creates a new workspace. */
Workspace createWorkspace(
String workspaceName, int memory, MemoryMeasure memoryUnit, WorkspaceConfigDto workspace)
throws Exception;
void sendStartRequest(String workspaceId, String workspaceName) throws Exception;
/** Starts workspace. */
void start(String workspaceId, String workspaceName, TestUser workspaceOwner) throws Exception;
WorkspaceDto getById(String workspaceId) throws Exception;
WorkspaceStatus getStatus(String workspaceId) throws Exception;
@Deprecated
@Nullable
String getServerAddressByPort(String workspaceId, int port) throws Exception;
@Nullable
Server getServerFromDevMachineBySymbolicName(String workspaceId, String serverName)
throws Exception;
void ensureRunningStatus(Workspace workspace) throws IllegalStateException;
void deleteFactoryWorkspaces(String originalName, String username) throws Exception;
}

View File

@ -1,20 +0,0 @@
/*
* Copyright (c) 2012-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
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.selenium.core.client;
import com.google.inject.assistedinject.Assisted;
import org.eclipse.che.selenium.core.user.TestUser;
/** @author Dmytro Nochevnov */
public interface TestWorkspaceServiceClientFactory {
TestWorkspaceServiceClient create(@Assisted TestUser testUser);
}

View File

@ -1,23 +0,0 @@
/*
* Copyright (c) 2012-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
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.selenium.core.configuration;
/**
* Exception happen in case of some problems with configuration.
*
* @author Sergii Kabashniuk
*/
public class ConfigurationException extends RuntimeException {
public ConfigurationException(String message) {
super(message);
}
}

View File

@ -1,107 +0,0 @@
/*
* Copyright (c) 2012-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
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.selenium.core.configuration;
import com.google.common.collect.ImmutableMap;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;
import org.eclipse.che.inject.CheBootstrap;
/** In memory storage of TestConfiguration based on Map<String, String> config */
public class InMemoryTestConfiguration implements TestConfiguration {
private final Map<String, String> config;
public InMemoryTestConfiguration() {
this(new HashMap<>());
}
public InMemoryTestConfiguration(TestConfiguration... configuration) {
this();
for (TestConfiguration testConfiguration : configuration) {
addAll(testConfiguration.getMap());
}
// convert value of CHE_INFRASTRUCTURE to upper case to comply with Infrastructure
// enumeration;
config.put("che.infrastructure", config.get("che.infrastructure").toUpperCase());
}
public InMemoryTestConfiguration(Map<String, String> config) {
this.config = config;
}
void addAll(Map<String, String> config) {
this.config.putAll(config);
}
@Override
public boolean isConfigured(String key) {
return config.containsKey(key);
}
@Override
public String getString(String key) {
String value = config.get(key);
if (value == null) {
StringBuilder builder = new StringBuilder();
builder
.append("\n")
.append("======== IMPORTANT =========\n")
.append("Key ")
.append(key)
.append(" is not configured\n")
.append("You can configure it as :\n")
.append("1. System property. Example: \t-D")
.append(key)
.append("=yourvalue \n")
.append("2. Environment variable. Example: \texport CODENVY_")
.append(key.toUpperCase().replace("_", "=").replace('.', '_').replace("=", "__"))
.append("=yourvalue \n")
.append("3. Or configured it in a property file in folder declared as ")
.append(CheBootstrap.CHE_LOCAL_CONF_DIR)
.append(" environment variable\n")
.append("============================\n");
throw new ConfigurationException(builder.toString());
}
return value;
}
@Override
public Boolean getBoolean(String key) {
return Boolean.parseBoolean(config.get(key));
}
@Override
public Integer getInt(String key) {
return Integer.parseInt(config.get(key));
}
@Override
public Long getLong(String key) {
return Long.parseLong(config.get(key));
}
@Override
public Map<String, String> getMap() {
return ImmutableMap.copyOf(config);
}
@Override
public Map<String, String> getMap(String keyPrefix) {
return config
.entrySet()
.stream()
.filter(e -> e.getKey().startsWith(keyPrefix))
.collect(Collectors.toMap(p -> p.getKey(), p -> p.getValue()));
}
}

View File

@ -1,177 +0,0 @@
/*
* Copyright (c) 2012-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
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.selenium.core.configuration;
import com.google.common.collect.Maps;
import com.google.common.io.Files;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.io.File;
import java.io.IOException;
import java.io.Reader;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.AbstractMap;
import java.util.AbstractMap.SimpleEntry;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import org.eclipse.che.inject.CheBootstrap;
/**
* Represents in memory based storage of the test configuration.
*
* <p>Values of configuration are loaded in the following sequence:<br>
* 1. Default configuration from target/conf/selenium.properties file.<br>
* 2. All properties from CHE_LOCAL_CONF_DIR directory.<br>
* 3. From java system properties (will be given prefix "sys.").<br>
* 4. From environment variables (will be given prefix "env."). Symbol "_" is replaced by "." and
* "__" is replaced by "_" in names of environment variables.<br>
* Variables which start from "che." or "codenvy." don't have an additional prefix "sys." or "env.".
*
* @author Sergii Kabashniuk
*/
@Singleton
public class SeleniumTestConfiguration extends InMemoryTestConfiguration {
@Inject
public SeleniumTestConfiguration() {
super(
new DefaultConfiguration(),
new PropertiesConfiguration(),
new SystemPropertiesConfiguration(),
new EnvironmentVariablesConfiguration());
}
static class SystemPropertiesConfiguration extends InMemoryTestConfiguration {
SystemPropertiesConfiguration() {
super();
addAll(
System.getProperties()
.entrySet()
.stream()
.filter(new PropertyNamePrefixPredicate<>("che.", "codenvy."))
.map(e -> new AbstractMap.SimpleEntry<>((String) e.getKey(), ((String) e.getValue())))
.collect(Collectors.toMap(SimpleEntry::getKey, SimpleEntry::getValue)));
addAll(
System.getProperties()
.entrySet()
.stream()
.map(e -> new AbstractMap.SimpleEntry<>("sys." + e.getKey(), ((String) e.getValue())))
.collect(Collectors.toMap(SimpleEntry::getKey, SimpleEntry::getValue)));
}
}
static class EnvironmentVariablesConfiguration extends InMemoryTestConfiguration {
EnvironmentVariablesConfiguration() {
super();
addAll(
System.getenv()
.entrySet()
.stream()
.filter(new PropertyNamePrefixPredicate<>("CHE_", "CODENVY_"))
.map(new EnvironmentVariableToSystemPropertyFormatNameConverter())
.collect(Collectors.toMap(Entry::getKey, Entry::getValue)));
addAll(
System.getenv()
.entrySet()
.stream()
.map(new EnvironmentVariableToSystemPropertyFormatNameConverter())
.map(e -> new AbstractMap.SimpleEntry<>("env." + e.getKey(), e.getValue()))
.collect(Collectors.toMap(SimpleEntry::getKey, SimpleEntry::getValue)));
}
}
static class PropertyNamePrefixPredicate<K, V> implements Predicate<Map.Entry<K, V>> {
final String[] prefixes;
PropertyNamePrefixPredicate(String... prefix) {
this.prefixes = prefix;
}
@Override
public boolean test(Map.Entry<K, V> entry) {
for (String prefix : prefixes) {
if (((String) entry.getKey()).startsWith(prefix)) {
return true;
}
}
return false;
}
}
static class EnvironmentVariableToSystemPropertyFormatNameConverter
implements Function<Map.Entry<String, String>, Map.Entry<String, String>> {
@Override
public Map.Entry<String, String> apply(Map.Entry<String, String> entry) {
String name = entry.getKey();
name = name.toLowerCase();
// replace single underscore with dot and double underscores with single underscore
// at first replace double underscores with equal sign which is forbidden in env variable name
// then replace single underscores
// then recover underscore from equal sign
name = name.replace("__", "=");
name = name.replace('_', '.');
name = name.replace("=", "_");
return new AbstractMap.SimpleEntry<>(name, entry.getValue());
}
}
static class DefaultConfiguration extends PropertiesConfiguration {
DefaultConfiguration() {
URL defaultConfig = getClass().getClassLoader().getResource("conf/selenium.properties");
if (defaultConfig != null) {
addFile(new File(defaultConfig.getFile()));
}
}
}
/** Implementation of TestConfiguration based on folder with properties files inside. */
static class PropertiesConfiguration extends InMemoryTestConfiguration {
PropertiesConfiguration() {
String extConfig = System.getenv(CheBootstrap.CHE_LOCAL_CONF_DIR);
if (extConfig != null) {
File extConfigFile = new File(extConfig);
if (extConfigFile.isDirectory() && extConfigFile.exists()) {
final File[] files = extConfigFile.listFiles();
if (files != null) {
for (File file : files) {
addFile(file);
}
}
}
}
}
void addFile(File file) {
if (!file.isDirectory()) {
if ("properties".equals(Files.getFileExtension(file.getName()))) {
Properties properties = new Properties();
try (Reader reader = Files.newReader(file, Charset.forName("UTF-8"))) {
properties.load(reader);
} catch (IOException e) {
throw new IllegalStateException(
String.format("Unable to read configuration file %s", file), e);
}
addAll(Maps.fromProperties(properties));
}
}
}
}
}

View File

@ -1,67 +0,0 @@
/*
* Copyright (c) 2012-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
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.selenium.core.configuration;
import java.util.Map;
/**
* Represents configuration of testing framework
*
* @author Sergii Kabashniuk
*/
public interface TestConfiguration {
/**
* Test if configuration contains parameter.
*
* @param key configuration key.
* @return - true if key is configured.
*/
boolean isConfigured(String key);
/**
* @param key - configuration key.
* @return String based value of configuration property.
* @throws ConfigurationException if kys is not configured
*/
String getString(String key) throws ConfigurationException;
/**
* @param key - configuration key.
* @return Boolean based value of configuration property.
* @throws ConfigurationException if kys is not configured
*/
Boolean getBoolean(String key) throws ConfigurationException;
/**
* @param key - configuration key.
* @return Integer based value of configuration property.
* @throws ConfigurationException if kys is not configured
*/
Integer getInt(String key) throws ConfigurationException;
/**
* @param key - configuration key.
* @return Long based value of configuration property.
* @throws ConfigurationException if kys is not configured
*/
Long getLong(String key) throws ConfigurationException;
/** @return all configuration parameters. */
Map<String, String> getMap();
/**
* @param keyPrefix - filter all properties with given prefix
* @return - key/value map of configuration.
*/
Map<String, String> getMap(String keyPrefix);
}

View File

@ -1,27 +0,0 @@
/*
* Copyright (c) 2012-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
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.selenium.core.constant;
import com.google.inject.Singleton;
/**
* Reflects values of environment variable CHE_INFRASTRUCTURE
*
* @author Dmytro Nochevnov
*/
@Singleton
public enum Infrastructure {
DOCKER,
OPENSHIFT,
K8S,
OSIO
}

View File

@ -1,17 +0,0 @@
/*
* Copyright (c) 2012-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
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.selenium.core.constant;
/** @author Aleksandr Shmaraev */
public enum TestBrowser {
GOOGLE_CHROME
}

View File

@ -1,29 +0,0 @@
/*
* Copyright (c) 2012-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
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.selenium.core.constant;
/** Represent of main constants for tests in seconds */
public final class TestTimeoutsConstants {
public static final int MULTIPLE = 1;
public static final int APPLICATION_START_TIMEOUT_SEC = 300 * MULTIPLE;
public static final int PREPARING_WS_TIMEOUT_SEC = 240 * MULTIPLE;
public static final int UPDATING_PROJECT_TIMEOUT_SEC = 180 * MULTIPLE;
public static final int EXPECTED_MESS_IN_CONSOLE_SEC = 120 * MULTIPLE;
public static final int LOADER_TIMEOUT_SEC = 60 * MULTIPLE;
public static final int WIDGET_TIMEOUT_SEC = 40 * MULTIPLE;
public static final int ELEMENT_TIMEOUT_SEC = 20 * MULTIPLE;
public static final int LOAD_PAGE_TIMEOUT_SEC = 10 * MULTIPLE;
public static final int REDRAW_UI_ELEMENTS_TIMEOUT_SEC = 5 * MULTIPLE;
public static final int ATTACHING_ELEM_TO_DOM_SEC = 3 * MULTIPLE;
public static final int MINIMUM_SEC = MULTIPLE;
public static final int DEFAULT_TIMEOUT = LOAD_PAGE_TIMEOUT_SEC;
}

View File

@ -1,24 +0,0 @@
/*
* Copyright (c) 2012-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
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.selenium.core.entrance;
import org.eclipse.che.selenium.core.user.TestUser;
/** @author Dmytro Nochevnov */
public interface Entrance {
/**
* Login to product.
*
* @param user user to login
*/
void login(TestUser user);
}

View File

@ -1,23 +0,0 @@
/*
* Copyright (c) 2012-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
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.selenium.core.factory;
/**
* Factory templates.
*
* @author Anatolii Bazko
*/
public class FactoryTemplate {
public static final String MINIMAL = "minimal.json";
private FactoryTemplate() {}
}

View File

@ -1,93 +0,0 @@
/*
* Copyright (c) 2012-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
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.selenium.core.factory;
import org.eclipse.che.api.core.model.workspace.WorkspaceStatus;
import org.eclipse.che.api.factory.shared.dto.FactoryDto;
import org.eclipse.che.selenium.core.SeleniumWebDriver;
import org.eclipse.che.selenium.core.client.TestFactoryServiceClient;
import org.eclipse.che.selenium.core.client.TestWorkspaceServiceClient;
import org.eclipse.che.selenium.core.entrance.Entrance;
import org.eclipse.che.selenium.core.provider.TestDashboardUrlProvider;
import org.eclipse.che.selenium.core.user.DefaultTestUser;
import org.eclipse.che.selenium.core.webdriver.SeleniumWebDriverHelper;
import org.openqa.selenium.WebDriver;
/** @author Anatolii Bazko */
public class TestFactory {
private final DefaultTestUser owner;
private final FactoryDto factoryDto;
private final TestDashboardUrlProvider dashboardUrl;
private final TestFactoryServiceClient testFactoryServiceClient;
private final TestWorkspaceServiceClient workspaceServiceClient;
private final Entrance entrance;
private final String factoryUrl;
private final SeleniumWebDriver seleniumWebDriver;
private final SeleniumWebDriverHelper seleniumWebDriverHelper;
public TestFactory(
String factoryUrl,
DefaultTestUser owner,
FactoryDto factoryDto,
TestDashboardUrlProvider dashboardUrl,
TestFactoryServiceClient factoryServiceClient,
TestWorkspaceServiceClient workspaceServiceClient,
Entrance entrance,
SeleniumWebDriver seleniumWebDriver,
SeleniumWebDriverHelper seleniumWebDriverHelper) {
this.factoryDto = factoryDto;
this.owner = owner;
this.factoryUrl = factoryUrl;
this.dashboardUrl = dashboardUrl;
this.testFactoryServiceClient = factoryServiceClient;
this.workspaceServiceClient = workspaceServiceClient;
this.entrance = entrance;
this.seleniumWebDriver = seleniumWebDriver;
this.seleniumWebDriverHelper = seleniumWebDriverHelper;
}
/** Login to factory and open it by url. */
public void authenticateAndOpen() {
seleniumWebDriver.get(dashboardUrl.get().toString());
entrance.login(owner);
seleniumWebDriver.get(factoryUrl);
}
/** Opens factory url. */
public void open(WebDriver driver) {
driver.get(factoryUrl);
}
public void delete() throws Exception {
seleniumWebDriver.quit();
workspaceServiceClient.deleteFactoryWorkspaces(
factoryDto.getWorkspace().getName(), owner.getName());
deleteFactory();
}
private void deleteFactory() {
if (isNamedFactory()) {
testFactoryServiceClient.deleteFactory(factoryDto.getName());
}
}
private boolean isNamedFactory() {
return factoryDto.getName() != null;
}
public WorkspaceStatus getWorkspaceStatusAssociatedWithFactory() throws Exception {
return workspaceServiceClient
.getByName(factoryDto.getWorkspace().getName(), owner.getName())
.getStatus();
}
}

View File

@ -1,307 +0,0 @@
/*
* Copyright (c) 2012-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
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.selenium.core.factory;
import static java.lang.String.format;
import static java.util.Collections.singletonMap;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.List;
import javax.inject.Named;
import org.eclipse.che.api.core.rest.HttpJsonRequest;
import org.eclipse.che.api.core.rest.HttpJsonRequestFactory;
import org.eclipse.che.api.core.rest.HttpJsonResponse;
import org.eclipse.che.api.core.rest.shared.dto.Link;
import org.eclipse.che.api.factory.shared.dto.AuthorDto;
import org.eclipse.che.api.factory.shared.dto.FactoryDto;
import org.eclipse.che.api.factory.shared.dto.IdeDto;
import org.eclipse.che.api.factory.shared.dto.PoliciesDto;
import org.eclipse.che.api.workspace.shared.dto.WorkspaceConfigDto;
import org.eclipse.che.api.workspace.shared.dto.devfile.DevfileDto;
import org.eclipse.che.commons.lang.IoUtil;
import org.eclipse.che.commons.lang.NameGenerator;
import org.eclipse.che.dto.server.DtoFactory;
import org.eclipse.che.selenium.core.SeleniumWebDriver;
import org.eclipse.che.selenium.core.client.TestFactoryServiceClient;
import org.eclipse.che.selenium.core.client.TestUserPreferencesServiceClient;
import org.eclipse.che.selenium.core.client.TestWorkspaceServiceClient;
import org.eclipse.che.selenium.core.constant.Infrastructure;
import org.eclipse.che.selenium.core.entrance.Entrance;
import org.eclipse.che.selenium.core.provider.TestApiEndpointUrlProvider;
import org.eclipse.che.selenium.core.provider.TestDashboardUrlProvider;
import org.eclipse.che.selenium.core.provider.TestIdeUrlProvider;
import org.eclipse.che.selenium.core.user.DefaultTestUser;
import org.eclipse.che.selenium.core.webdriver.SeleniumWebDriverHelper;
/** @author Anatolii Bazko */
@Singleton
public class TestFactoryInitializer {
@Inject private DefaultTestUser defaultUser;
@Inject private TestIdeUrlProvider ideUrlProvider;
@Inject private TestDashboardUrlProvider dashboardUrlProvider;
@Inject private TestApiEndpointUrlProvider apiEndpointProvider;
@Inject private HttpJsonRequestFactory requestFactory;
@Inject private TestFactoryServiceClient testFactoryServiceClient;
@Inject private TestWorkspaceServiceClient workspaceServiceClient;
@Inject private Entrance entrance;
@Inject private SeleniumWebDriver seleniumWebDriver;
@Inject private SeleniumWebDriverHelper seleniumWebDriverHelper;
@Inject private TestUserPreferencesServiceClient testUserPreferencesServiceClient;
@Inject
@Named("che.infrastructure")
private Infrastructure infrastructure;
/**
* Initialize {@link TestFactory} base upon template.
*
* @see FactoryTemplate
*/
public TestFactoryBuilder fromTemplate(String template) throws Exception {
String name = NameGenerator.generate("factory", 6);
InputStream resource = TestFactory.class.getResourceAsStream(getTemplateDirectory(template));
if (resource == null) {
throw new IOException(format("Factory template '%s' not found", template));
}
String factoryTemplate = IoUtil.readStream(resource);
FactoryDto factoryDto =
DtoFactory.getInstance()
.createDtoFromJson(factoryTemplate, FactoryDto.class)
.withName(name);
factoryDto.getWorkspace().setName(name);
return new TestFactoryBuilder(factoryDto);
}
private String getTemplateDirectory(String template) {
String templateDirectoryName;
switch (infrastructure) {
case OSIO:
templateDirectoryName = Infrastructure.OPENSHIFT.toString().toLowerCase();
break;
default:
templateDirectoryName = infrastructure.toString().toLowerCase();
}
return String.format("/templates/factory/%s/%s", templateDirectoryName, template);
}
/** Initialize {@link TestFactory} base upon url. Can't be modified. */
public TestFactory fromUrl(String url) throws Exception {
HttpJsonRequest httpJsonRequest =
requestFactory.fromUrl(apiEndpointProvider.get() + "factory/resolver");
httpJsonRequest.setBody(singletonMap("url", url));
HttpJsonResponse response = httpJsonRequest.request();
FactoryDto factoryDto = response.asDto(FactoryDto.class);
String factoryUrl = ideUrlProvider.get() + "f?url=" + URLEncoder.encode(url, "UTF8");
return new TestFactory(
factoryUrl,
defaultUser,
factoryDto,
dashboardUrlProvider,
testFactoryServiceClient,
workspaceServiceClient,
entrance,
seleniumWebDriver,
seleniumWebDriverHelper);
}
/** Builder for {@link TestFactory}. */
public class TestFactoryBuilder implements FactoryDto {
private final FactoryDto factoryDto;
private TestFactoryBuilder(FactoryDto factoryDto) {
this.factoryDto = factoryDto;
}
public TestFactory build() throws Exception {
String factoryUrl = testFactoryServiceClient.createFactory(factoryDto);
return new TestFactory(
factoryUrl,
defaultUser,
factoryDto,
dashboardUrlProvider,
testFactoryServiceClient,
workspaceServiceClient,
entrance,
seleniumWebDriver,
seleniumWebDriverHelper);
}
@Override
public List<Link> getLinks() {
return factoryDto.getLinks();
}
@Override
public void setLinks(List<Link> links) {
factoryDto.setLinks(links);
}
@Override
public List<Link> getLinks(String rel) {
return factoryDto.getLinks(rel);
}
@Override
public Link getLink(String rel) {
return factoryDto.getLink(rel);
}
@Override
public String getV() {
return factoryDto.getV();
}
@Override
public void setV(String v) {
factoryDto.setV(v);
}
@Override
public FactoryDto withV(String v) {
return factoryDto.withV(v);
}
@Override
public DevfileDto getDevfile() {
return factoryDto.getDevfile();
}
@Override
public void setDevfile(DevfileDto workspace) {
factoryDto.setDevfile(workspace);
}
@Override
public FactoryDto withDevfile(DevfileDto devfileDto) {
return factoryDto.withDevfile(devfileDto);
}
@Override
public WorkspaceConfigDto getWorkspace() {
return factoryDto.getWorkspace();
}
@Override
public void setWorkspace(WorkspaceConfigDto workspace) {
factoryDto.setWorkspace(workspace);
}
@Override
public FactoryDto withWorkspace(WorkspaceConfigDto workspace) {
return factoryDto.withWorkspace(workspace);
}
@Override
public PoliciesDto getPolicies() {
return factoryDto.getPolicies();
}
@Override
public void setPolicies(PoliciesDto policies) {
factoryDto.setPolicies(policies);
}
@Override
public FactoryDto withPolicies(PoliciesDto policies) {
return factoryDto.withPolicies(policies);
}
@Override
public AuthorDto getCreator() {
return factoryDto.getCreator();
}
@Override
public void setCreator(AuthorDto creator) {
factoryDto.setCreator(creator);
}
@Override
public FactoryDto withCreator(AuthorDto creator) {
return factoryDto.withCreator(creator);
}
@Override
public IdeDto getIde() {
return factoryDto.getIde();
}
@Override
public void setIde(IdeDto ide) {
factoryDto.setIde(ide);
}
@Override
public FactoryDto withIde(IdeDto ide) {
return factoryDto.withIde(ide);
}
@Override
public String getId() {
return factoryDto.getId();
}
@Override
public void setId(String id) {
factoryDto.setId(id);
}
@Override
public FactoryDto withId(String id) {
return factoryDto.withId(id);
}
@Override
public String getName() {
return factoryDto.getName();
}
@Override
public void setName(String name) {
factoryDto.setName(name);
}
@Override
public FactoryDto withName(String name) {
return factoryDto.withName(name);
}
@Override
public FactoryDto withLinks(List<Link> links) {
return factoryDto.withLinks(links);
}
@Override
public String getSource() {
return factoryDto.getSource();
}
@Override
public void setSource(String source) {
factoryDto.setSource(source);
}
@Override
public FactoryDto withSource(String source) {
return factoryDto.withSource(source);
}
}
}

View File

@ -1,101 +0,0 @@
/*
* Copyright (c) 2012-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
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.selenium.core.inject;
import static com.google.inject.matcher.Matchers.any;
import com.google.inject.AbstractModule;
import com.google.inject.Injector;
import com.google.inject.Provider;
import com.google.inject.TypeLiteral;
import com.google.inject.spi.TypeEncounter;
import com.google.inject.spi.TypeListener;
import java.lang.reflect.Field;
import java.util.function.Consumer;
import org.eclipse.che.selenium.core.SeleniumWebDriver;
import org.eclipse.che.selenium.core.organization.InjectTestOrganization;
import org.eclipse.che.selenium.core.organization.TestOrganization;
import org.eclipse.che.selenium.core.organization.TestOrganizationInjector;
import org.eclipse.che.selenium.core.workspace.InjectTestWorkspace;
import org.eclipse.che.selenium.core.workspace.TestWorkspace;
import org.eclipse.che.selenium.core.workspace.TestWorkspaceInjector;
/**
* Guice module per test class.
*
* @author Anatolii Bazko
*/
public class SeleniumClassModule extends AbstractModule {
@Override
public void configure() {
bind(SeleniumWebDriver.class);
bindListener(any(), new WorkspaceTypeListener(binder().getProvider(Injector.class)));
bindListener(any(), new OrganizationTypeListener(binder().getProvider(Injector.class)));
}
private class WorkspaceTypeListener implements TypeListener {
private final Provider<Injector> injectorProvider;
public WorkspaceTypeListener(Provider<Injector> injector) {
this.injectorProvider = injector;
}
@Override
public <I> void hear(TypeLiteral<I> type, TypeEncounter<I> encounter) {
traverseClassHierarchy(
type.getRawType(),
(clazz) -> {
for (Field field : clazz.getDeclaredFields()) {
if (field.getType() == TestWorkspace.class
&& field.isAnnotationPresent(InjectTestWorkspace.class)) {
encounter.register(
new TestWorkspaceInjector<>(
field,
field.getAnnotation(InjectTestWorkspace.class),
injectorProvider.get()));
}
}
});
}
private void traverseClassHierarchy(Class clazz, Consumer<Class> handler) {
if (clazz == null || clazz.equals(Object.class)) {
return;
}
traverseClassHierarchy(clazz.getSuperclass(), handler);
handler.accept(clazz);
}
}
private class OrganizationTypeListener implements TypeListener {
private final Provider<Injector> injectorProvider;
public OrganizationTypeListener(Provider<Injector> injector) {
this.injectorProvider = injector;
}
@Override
public <I> void hear(TypeLiteral<I> type, TypeEncounter<I> encounter) {
Class<?> clazz = type.getRawType();
for (Field field : clazz.getDeclaredFields()) {
if (field.getType() == TestOrganization.class
&& field.isAnnotationPresent(InjectTestOrganization.class)) {
encounter.register(
new TestOrganizationInjector<>(
field, field.getAnnotation(InjectTestOrganization.class), injectorProvider));
}
}
}
}
}

View File

@ -1,721 +0,0 @@
/*
* Copyright (c) 2012-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
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.selenium.core.inject;
import static com.google.inject.Guice.createInjector;
import static java.lang.Runtime.getRuntime;
import static java.lang.String.format;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Module;
import com.google.inject.name.Named;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;
import java.util.stream.Stream;
import java.util.zip.ZipOutputStream;
import javax.annotation.PreDestroy;
import javax.validation.constraints.NotNull;
import org.apache.commons.io.FileUtils;
import org.eclipse.che.commons.json.JsonParseException;
import org.eclipse.che.commons.lang.ZipUtils;
import org.eclipse.che.selenium.core.SeleniumWebDriver;
import org.eclipse.che.selenium.core.TestGroup;
import org.eclipse.che.selenium.core.client.TestGitHubServiceClient;
import org.eclipse.che.selenium.core.organization.InjectTestOrganization;
import org.eclipse.che.selenium.core.pageobject.InjectPageObject;
import org.eclipse.che.selenium.core.pageobject.PageObjectsInjector;
import org.eclipse.che.selenium.core.user.DefaultTestUser;
import org.eclipse.che.selenium.core.webdriver.SeleniumWebDriverFactory;
import org.eclipse.che.selenium.core.webdriver.log.WebDriverLogsReaderFactory;
import org.eclipse.che.selenium.core.workspace.InjectTestWorkspace;
import org.eclipse.che.selenium.core.workspace.TestWorkspace;
import org.eclipse.che.selenium.core.workspace.TestWorkspaceLogsReader;
import org.eclipse.che.selenium.core.workspace.TestWorkspaceProvider;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebDriverException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.IAnnotationTransformer2;
import org.testng.IConfigurationListener;
import org.testng.IExecutionListener;
import org.testng.IInvokedMethod;
import org.testng.IInvokedMethodListener;
import org.testng.ISuite;
import org.testng.ISuiteListener;
import org.testng.ITestContext;
import org.testng.ITestListener;
import org.testng.ITestNGMethod;
import org.testng.ITestResult;
import org.testng.SkipException;
import org.testng.TestException;
import org.testng.annotations.IConfigurationAnnotation;
import org.testng.annotations.IDataProviderAnnotation;
import org.testng.annotations.IFactoryAnnotation;
import org.testng.annotations.ITestAnnotation;
/**
* Tests lifecycle handler.
*
* <p>Adding {@link IConfigurationListener} brings bug when all methods of the listener will be
* invoked twice.
*
* @author Anatolii Bazko
* @author Dmytro Nochevnov
*/
public abstract class SeleniumTestHandler
implements ITestListener,
ISuiteListener,
IInvokedMethodListener,
IExecutionListener,
IAnnotationTransformer2,
IConfigurationListener {
private static final Logger LOG = LoggerFactory.getLogger(SeleniumTestHandler.class);
private static final AtomicBoolean isCleanUpCompleted = new AtomicBoolean();
@Inject private SeleniumWebDriverFactory seleniumWebDriverFactory;
@Inject
@Named("tests.screenshots_dir")
private String screenshotsDir;
@Inject
@Named("tests.htmldumps_dir")
private String htmldumpsDir;
@Inject
@Named("tests.webdriverlogs_dir")
private String webDriverLogsDir;
@Inject
@Named("tests.workspacelogs_dir")
private String workspaceLogsDir;
@Inject private PageObjectsInjector pageObjectsInjector;
@Inject
@Named("github.username")
private String gitHubUsername;
@Inject
@Named("github.password")
private String gitHubPassword;
@Inject
@Named("sys.excludedGroups")
private String excludedGroups;
@Inject private DefaultTestUser defaultTestUser;
@Inject private TestWorkspaceProvider testWorkspaceProvider;
@Inject private TestGitHubServiceClient gitHubClientService;
@Inject private TestWorkspaceLogsReader testWorkspaceLogsReader;
@Inject private SeleniumTestStatistics seleniumTestStatistics;
@Inject private WebDriverLogsReaderFactory webDriverLogsReaderFactory;
@Inject private TestFilter testFilter;
private final Injector injector;
// this is the map {thread ID} -> {test instance}
private final Map<Long, Object> runningTests = new ConcurrentHashMap<>();
// this is the map {test class FQN} -> {failed test method}
private final Map<String, ITestResult> testsWithFailure = new ConcurrentHashMap<>();
public SeleniumTestHandler() {
injector = createInjector(getParentModules());
injector.injectMembers(this);
getRuntime().addShutdownHook(new Thread(this::shutdown));
revokeGithubOauthToken();
checkWebDriverSessionCreation();
}
private void revokeGithubOauthToken() {
// do not revoke if github tests are not being executed
if (excludedGroups != null && excludedGroups.contains(TestGroup.GITHUB)) {
return;
}
try {
gitHubClientService.deleteAllGrants(gitHubUsername, gitHubPassword);
} catch (Exception e) {
LOG.warn("There was an error of revoking the github oauth token.", e);
}
}
@Override
public void onTestStart(ITestResult result) {
LOG.info(
"Starting test #{} {}. {}",
seleniumTestStatistics.hitStart(),
getStartingTestLabel(result.getMethod()),
seleniumTestStatistics.toString());
skipTestIfNeeded(result);
}
@Override
public void onTestSuccess(ITestResult result) {
seleniumTestStatistics.hitPass();
onTestFinish(result);
}
@Override
public void onTestFailure(ITestResult result) {
seleniumTestStatistics.hitFail();
onTestFinish(result);
}
@Override
public void onTestSkipped(ITestResult result) {
seleniumTestStatistics.hitSkip();
onTestFinish(result);
}
@Override
public void onTestFailedButWithinSuccessPercentage(ITestResult result) {
seleniumTestStatistics.hitFail();
onTestFinish(result);
}
@Override
public void onStart(ITestContext context) {}
@Override
public void onFinish(ITestContext context) {}
@Override
public void onStart(ISuite suite) {
suite.setParentInjector(injector);
long numberOfEnabledTests =
suite.getAllMethods().parallelStream().filter(ITestNGMethod::getEnabled).count();
LOG.info("Starting suite '{}' with {} test methods.", suite.getName(), numberOfEnabledTests);
}
/** Check if webdriver session can be created without errors. */
private void checkWebDriverSessionCreation() {
SeleniumWebDriver seleniumWebDriver = null;
try {
seleniumWebDriver = seleniumWebDriverFactory.create();
} finally {
Optional.ofNullable(seleniumWebDriver)
.ifPresent(SeleniumWebDriver::quit); // finish webdriver session
}
}
@Override
public void onFinish(ISuite suite) {}
@Override
public void beforeInvocation(IInvokedMethod method, ITestResult testResult) {
Object invokingTestInstance = method.getTestMethod().getInstance();
if (runningTests.containsValue(invokingTestInstance)) {
return;
}
long currentThreadId = Thread.currentThread().getId();
if (isNewTestInProgress(invokingTestInstance)) {
Object previousTestInstance = runningTests.remove(currentThreadId);
preDestroy(previousTestInstance);
testsWithFailure.remove(previousTestInstance.getClass().getName());
}
String testName = invokingTestInstance.getClass().getName();
try {
LOG.info("Dependencies injection in {}", testName);
injectDependencies(testResult.getTestContext(), invokingTestInstance);
} catch (Exception e) {
String errorMessage = "Failed to inject fields in " + testName;
LOG.error(errorMessage, e);
throw new TestException(errorMessage, e);
} finally {
runningTests.put(currentThreadId, invokingTestInstance);
}
}
private boolean isNewTestInProgress(Object testInstance) {
Thread currentThread = Thread.currentThread();
return runningTests.containsKey(currentThread.getId())
&& runningTests.get(currentThread.getId()) != testInstance;
}
@Override
public void afterInvocation(IInvokedMethod method, ITestResult result) {}
@Override
public void onExecutionStart() {}
@Override
public void onExecutionFinish() {
shutdown();
}
@Override
public void transform(
ITestAnnotation annotation, Class testClass, Constructor testConstructor, Method testMethod) {
testFilter.excludeTestOfImproperGroup(annotation);
}
@Override
public void transform(
IConfigurationAnnotation annotation,
Class testClass,
Constructor testConstructor,
Method testMethod) {
testFilter.excludeTestOfImproperGroup(annotation);
}
@Override
public void transform(IDataProviderAnnotation annotation, Method method) {}
@Override
public void transform(IFactoryAnnotation annotation, Method method) {}
@Override
public void onConfigurationSuccess(ITestResult result) {}
@Override
public void onConfigurationFailure(ITestResult result) {
onTestFinish(result);
}
@Override
public void onConfigurationSkip(ITestResult result) {
onTestFinish(result);
}
/** Injects dependencies into the given test class using {@link Guice} and custom injectors. */
private void injectDependencies(ITestContext testContext, Object testInstance) throws Exception {
Injector injector = testContext.getSuite().getParentInjector();
List<Module> childModules = new ArrayList<>(getChildModules());
childModules.add(new SeleniumClassModule());
Injector classInjector = injector.createChildInjector(childModules);
classInjector.injectMembers(testInstance);
pageObjectsInjector.injectMembers(testInstance, classInjector);
}
/** Is invoked when test or configuration is finished. */
private void onTestFinish(ITestResult result) {
// do not treat SeleniumTestHandler error as test failure
if (testsWithFailure.containsKey(result.getTestClass().getRealClass().getName())
&& testsWithFailure
.get(result.getTestClass().getRealClass().getName())
.getMethod()
.equals(result.getMethod())
&& result.getMethod().getCurrentInvocationCount() == 1) {
// restore initial test exception
result.setThrowable(
testsWithFailure.get(result.getTestClass().getRealClass().getName()).getThrowable());
return;
}
if (result.getStatus() == ITestResult.FAILURE || result.getStatus() == ITestResult.SKIP) {
switch (result.getStatus()) {
case ITestResult.FAILURE:
if (result.getMethod().isTest()) {
String errorDetails =
result.getThrowable() != null
? " Error: " + result.getThrowable().getLocalizedMessage()
: "";
LOG.error("Test {} failed.{}", getCompletedTestLabel(result.getMethod()), errorDetails);
LOG.debug(result.getThrowable().getLocalizedMessage(), result.getThrowable());
testsWithFailure.put(result.getTestClass().getRealClass().getName(), result);
}
captureWebDriver(result);
captureTestWorkspaceLogs(result);
break;
case ITestResult.SKIP:
String skipReasonDetails =
result.getThrowable() != null
? " The reason: " + result.getThrowable().getLocalizedMessage()
: "";
if (result.getMethod().isTest()) {
LOG.warn(
"Test {} skipped.{}", getCompletedTestLabel(result.getMethod()), skipReasonDetails);
}
// don't capture test data if test is skipped because of previous test with higher
// priority failed
if (testsWithFailure.containsKey(result.getMethod().getInstance().getClass().getName())) {
return;
}
break;
default:
}
}
}
private void captureTestWorkspaceLogs(ITestResult result) {
Object testInstance = result.getInstance();
traverseClassHierarchy(
testInstance.getClass(),
(clazz) -> {
for (Field field : clazz.getDeclaredFields()) {
field.setAccessible(true);
Object obj;
try {
obj = field.get(testInstance);
} catch (IllegalAccessException e) {
LOG.error(
"Field {} is inaccessible in {}.",
field.getName(),
testInstance.getClass().getName());
continue;
}
if (!(obj instanceof TestWorkspace)) {
continue;
}
try {
if (((TestWorkspace) obj).getId() == null) {
continue;
}
} catch (ExecutionException | InterruptedException e) {
continue;
}
String testReference = getTestReference(result);
Path pathToStoreWorkspaceLogs = Paths.get(workspaceLogsDir, testReference);
testWorkspaceLogsReader.store((TestWorkspace) obj, pathToStoreWorkspaceLogs, false);
Path pathToZipWithWorkspaceLogs =
pathToStoreWorkspaceLogs
.getParent()
.resolve(getTestResultFilename(testReference, "zip"));
if (!Files.exists(pathToStoreWorkspaceLogs)) {
return;
}
try {
Path zip = Files.createFile(pathToZipWithWorkspaceLogs);
try (ZipOutputStream out = ZipUtils.stream(zip)) {
ZipUtils.add(out, pathToStoreWorkspaceLogs);
}
FileUtils.deleteQuietly(pathToStoreWorkspaceLogs.toFile());
} catch (IOException | IllegalArgumentException e) {
LOG.warn("Error of creation zip-file with workspace logs.", e);
}
}
});
}
private boolean isInjectedWorkspace(Field field) {
return field.isAnnotationPresent(com.google.inject.Inject.class)
|| field.isAnnotationPresent(javax.inject.Inject.class)
|| field.isAnnotationPresent(InjectTestWorkspace.class);
}
/** Releases resources by invoking methods annotated with {@link PreDestroy} */
private void preDestroy(Object testInstance) {
LOG.info("Processing @PreDestroy annotation in {}", testInstance.getClass().getName());
traverseClassHierarchy(
testInstance.getClass(),
(clazz) -> {
for (Field field : clazz.getDeclaredFields()) {
field.setAccessible(true);
Object obj;
try {
obj = field.get(testInstance);
} catch (IllegalAccessException e) {
LOG.error(
"Field {} is inaccessible in {}.",
field.getName(),
testInstance.getClass().getName());
continue;
}
if (obj == null || !hasInjectAnnotation(field)) {
continue;
}
for (Method m : obj.getClass().getMethods()) {
if (m.isAnnotationPresent(PreDestroy.class)) {
try {
m.invoke(obj);
} catch (Exception e) {
LOG.error(
format(
"Failed to invoke method %s annotated with @PreDestroy in %s. Test instance: %s",
m.getName(), obj.getClass().getName(), testInstance.getClass().getName()),
e);
}
}
}
}
});
}
private boolean hasInjectAnnotation(AccessibleObject f) {
return f.isAnnotationPresent(com.google.inject.Inject.class)
|| f.isAnnotationPresent(javax.inject.Inject.class)
|| f.isAnnotationPresent(InjectTestWorkspace.class)
|| f.isAnnotationPresent(InjectTestOrganization.class)
|| f.isAnnotationPresent(InjectPageObject.class);
}
private void captureWebDriver(ITestResult result) {
Set<SeleniumWebDriver> webDrivers = new HashSet<>();
Object testInstance = result.getInstance();
collectInjectedWebDrivers(testInstance, webDrivers);
webDrivers.forEach(webDriver -> captureWebDriver(result, webDriver));
}
/**
* Iterates recursively throw all fields and collects instances of {@link SeleniumWebDriver}.
*
* @param testInstance the based object to examine
* @param webDrivers as the result of the method will contain all {@link WebDriver}
*/
private void collectInjectedWebDrivers(Object testInstance, Set<SeleniumWebDriver> webDrivers) {
traverseClassHierarchy(
testInstance.getClass(),
(clazz) -> {
for (Field field : clazz.getDeclaredFields()) {
field.setAccessible(true);
Object obj;
try {
obj = field.get(testInstance);
} catch (IllegalAccessException e) {
LOG.error(
"Field {} is inaccessible in {}.",
field.getName(),
testInstance.getClass().getName());
continue;
}
if (obj == null) {
continue;
}
Optional<Constructor<?>> injectedConstructor =
Stream.of(obj.getClass().getConstructors())
.filter(this::hasInjectAnnotation)
.findAny();
if (!hasInjectAnnotation(field) && !injectedConstructor.isPresent()) {
continue;
}
if (obj instanceof com.google.inject.Provider || obj instanceof javax.inject.Provider) {
continue;
}
if (obj instanceof SeleniumWebDriver) {
webDrivers.add((SeleniumWebDriver) obj);
} else {
collectInjectedWebDrivers(obj, webDrivers);
}
}
});
}
private void traverseClassHierarchy(Class clazz, Consumer<Class> handler) {
if (clazz == null || clazz.equals(Object.class)) {
return;
}
traverseClassHierarchy(clazz.getSuperclass(), handler);
handler.accept(clazz);
}
private void captureScreenshotFromCurrentWindow(ITestResult result, SeleniumWebDriver webDriver) {
String testReference = getTestReference(result);
String filename = getTestResultFilename(testReference, "png");
try {
byte[] data = webDriver.getScreenshotAs(OutputType.BYTES);
Path screenshot = Paths.get(screenshotsDir, filename);
Files.createDirectories(screenshot.getParent());
Files.copy(new ByteArrayInputStream(data), screenshot);
} catch (WebDriverException | IOException e) {
LOG.error(format("Can't capture screenshot for test %s", testReference), e);
}
}
private String getTestResultFilename(String testReference, String fileExtension) {
return format("%s_time-%s-millis.%s", testReference, System.currentTimeMillis(), fileExtension);
}
private String getTestReference(ITestResult result) {
return format("%s.%s", result.getTestClass().getName(), result.getMethod().getMethodName());
}
private void captureWebDriver(ITestResult result, SeleniumWebDriver webDriver) {
webDriver
.getWindowHandles()
.forEach(
currentWin -> {
webDriver.switchTo().window(currentWin);
captureScreenshotFromCurrentWindow(result, webDriver);
captureHtmlDumpFromCurrentWindow(result, webDriver);
storeLogsFromCurrentWindow(result, webDriver);
});
}
private void storeLogsFromCurrentWindow(ITestResult result, SeleniumWebDriver webDriver) {
String testReference = getTestReference(result);
try {
String filename = getTestResultFilename(testReference, "log");
Path webDriverLogsDirectory = Paths.get(webDriverLogsDir, filename);
Files.createDirectories(webDriverLogsDirectory.getParent());
Files.write(
webDriverLogsDirectory,
webDriverLogsReaderFactory
.create(webDriver)
.getAllLogs()
.getBytes(Charset.forName("UTF-8")),
StandardOpenOption.CREATE);
} catch (WebDriverException | IOException | JsonParseException e) {
LOG.error(format("Can't store web driver logs related to test %s.", testReference), e);
}
}
private void captureHtmlDumpFromCurrentWindow(ITestResult result, SeleniumWebDriver webDriver) {
String testReference = getTestReference(result);
String filename = getTestResultFilename(testReference, "html");
try {
String pageSource = webDriver.getPageSource();
Path dumpDirectory = Paths.get(htmldumpsDir, filename);
Files.createDirectories(dumpDirectory.getParent());
Files.write(
dumpDirectory, pageSource.getBytes(Charset.forName("UTF-8")), StandardOpenOption.CREATE);
} catch (WebDriverException | IOException e) {
LOG.error(format("Can't dump of html source for test %s", testReference), e);
}
}
/** Cleans up test environment. */
private void shutdown() {
if (isCleanUpCompleted.get()) {
return;
}
LOG.info("Cleaning up test environment...");
for (Object testInstance : runningTests.values()) {
preDestroy(testInstance);
testsWithFailure.remove(testInstance.getClass().getName());
}
if (testWorkspaceProvider != null) {
testWorkspaceProvider.shutdown();
}
if (defaultTestUser != null) {
try {
defaultTestUser.delete();
} catch (IOException e) {
throw new RuntimeException(e.getMessage(), e);
}
}
isCleanUpCompleted.set(true);
}
/**
* Skip test if preceding test with higher priority from the same test class has failed.
*
* @param result holds result of test execution
* @throws SkipException if test should be skipped
*/
private void skipTestIfNeeded(ITestResult result) {
ITestNGMethod testMethodToSkip = result.getMethod();
ITestResult failedTestResult =
testsWithFailure.get(testMethodToSkip.getInstance().getClass().getName());
// skip test with lower priority value and if it shouldn't always run
if (failedTestResult != null
&& testMethodToSkip.getPriority() > failedTestResult.getMethod().getPriority()
&& !testMethodToSkip.isAlwaysRun()) {
throw new SkipException(
format(
"Skipping test %s because it depends on test %s which has failed earlier.",
getStartingTestLabel(testMethodToSkip),
getCompletedTestLabel(failedTestResult.getMethod())));
}
}
private String getStartingTestLabel(ITestNGMethod test) {
String invocationLabel = "";
if (test.getCurrentInvocationCount() > 0) {
invocationLabel = format(" (run %d)", test.getCurrentInvocationCount() + 1);
}
return getTestLabel(test, invocationLabel);
}
private String getCompletedTestLabel(ITestNGMethod test) {
String invocationLabel = "";
if (test.getCurrentInvocationCount() > 1) {
invocationLabel = format(" (run %d)", test.getCurrentInvocationCount());
}
return getTestLabel(test, invocationLabel);
}
private String getTestLabel(ITestNGMethod test, String invocationLabel) {
return format(
"%s.%s%s",
test.getInstance().getClass().getSimpleName(), test.getMethodName(), invocationLabel);
}
/** Returns list of parent modules */
@NotNull
public abstract List<Module> getParentModules();
/** Returns list of child modules */
@NotNull
public abstract List<Module> getChildModules();
}

View File

@ -1,49 +0,0 @@
/*
* Copyright (c) 2012-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
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.selenium.core.inject;
import static java.lang.String.format;
import java.util.concurrent.atomic.AtomicInteger;
/** @author Dmytro Nochevnov */
public class SeleniumTestStatistics {
private static final String statisticsTemplate = "Passed: %d, failed: %d, skipped: %d.";
private final AtomicInteger runTests = new AtomicInteger();
private final AtomicInteger failedTests = new AtomicInteger();
private final AtomicInteger passedTests = new AtomicInteger();
private final AtomicInteger skippedTests = new AtomicInteger();
public int hitStart() {
return runTests.incrementAndGet();
}
public int hitPass() {
return passedTests.incrementAndGet();
}
public int hitFail() {
return failedTests.incrementAndGet();
}
public int hitSkip() {
return skippedTests.incrementAndGet();
}
@Override
public String toString() {
synchronized (this) {
return format(statisticsTemplate, passedTests.get(), failedTests.get(), skippedTests.get());
}
}
}

View File

@ -1,93 +0,0 @@
/*
* Copyright (c) 2012-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
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.selenium.core.inject;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import com.google.inject.name.Named;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.eclipse.che.selenium.core.TestGroup;
import org.eclipse.che.selenium.core.constant.Infrastructure;
import org.testng.annotations.ITestOrConfiguration;
/**
* This class is aimed to filter TestNG tests.
*
* @author Dmytro Nochevnov
*/
@Singleton
public class TestFilter {
private final boolean isMultiuser;
private final Infrastructure infrastructure;
private final String excludedGroups;
@Inject
public TestFilter(
@Named("sys.excludedGroups") String excludedGroups,
@Named("che.multiuser") boolean isMultiuser,
@Named("che.infrastructure") Infrastructure infrastructure) {
this.isMultiuser = isMultiuser;
this.infrastructure = infrastructure;
this.excludedGroups = excludedGroups;
}
/**
* This method disable the test which belongs to test group which is being excluded or doesn't
* comply current infrastructure, or doesn't support Singleuser/Multiuser type of Eclipse Che.
*
* @param annotation annotation of test method which reflects {@link org.testng.annotations.Test}
* annotation attributes.
*/
public void excludeTestOfImproperGroup(ITestOrConfiguration annotation) {
if (annotation.getGroups().length == 0) {
return;
}
List<String> groups = new ArrayList<>(Arrays.asList(annotation.getGroups()));
// exclude test with group from excludedGroups
if (excludedGroups != null
&& Arrays.stream(excludedGroups.split(",")).anyMatch(groups::contains)) {
annotation.setEnabled(false);
return;
}
// exclude test which doesn't comply multiuser flag
if (isMultiuser
&& groups.contains(TestGroup.SINGLEUSER)
&& !groups.contains(TestGroup.MULTIUSER)) {
annotation.setEnabled(false);
return;
}
// exclude test which doesn't comply singleuser flag
if (!isMultiuser
&& groups.contains(TestGroup.MULTIUSER)
&& !groups.contains(TestGroup.SINGLEUSER)) {
annotation.setEnabled(false);
return;
}
// exclude test which doesn't support current infrastructure
groups.remove(TestGroup.SINGLEUSER);
groups.remove(TestGroup.MULTIUSER);
groups.remove(TestGroup.GITHUB);
groups.remove(TestGroup.UNDER_REPAIR);
groups.remove(TestGroup.FLAKY);
if (!groups.isEmpty() && !groups.contains(infrastructure.toString().toLowerCase())) {
annotation.setEnabled(false);
}
}
}

View File

@ -1,35 +0,0 @@
/*
* Copyright (c) 2012-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
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.selenium.core.organization;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
/**
* To instantiate {@link TestOrganization} in test classes.
*
* @author Dmytro Nochevnov
*/
@Target({FIELD})
@Retention(RUNTIME)
@Documented
public @interface InjectTestOrganization {
/** Organization name prefix. */
String prefix() default "";
/** Parent organization name prefix. */
String parentPrefix() default "";
}

View File

@ -1,67 +0,0 @@
/*
* Copyright (c) 2012-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
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.selenium.core.organization;
import javax.annotation.PreDestroy;
import org.eclipse.che.multiuser.organization.shared.dto.OrganizationDto;
import org.eclipse.che.selenium.core.client.TestOrganizationServiceClient;
/**
* Represents organization in a test environment.
*
* @author Dmytro Nochevnov
*/
public class TestOrganization {
private final OrganizationDto organization;
private final TestOrganizationServiceClient testOrganizationServiceClient;
public TestOrganization(String name, TestOrganizationServiceClient testOrganizationServiceClient)
throws Exception {
this.testOrganizationServiceClient = testOrganizationServiceClient;
organization = testOrganizationServiceClient.create(name);
}
public TestOrganization(
String name, String parentId, TestOrganizationServiceClient testOrganizationServiceClient)
throws Exception {
this.testOrganizationServiceClient = testOrganizationServiceClient;
organization = testOrganizationServiceClient.create(name, parentId);
}
/** Returns the name of the organization. */
public String getName() {
return organization.getName();
}
/** Returns the id of the organization. */
public String getId() {
return organization.getId();
}
public void addAdmin(String userId) throws Exception {
testOrganizationServiceClient.addAdmin(getId(), userId);
}
public void addMember(String userId) throws Exception {
testOrganizationServiceClient.addMember(getId(), userId);
}
/** Deletes organization. */
@PreDestroy
public void delete() throws Exception {
testOrganizationServiceClient.deleteById(getId());
}
public String getQualifiedName() {
return organization.getQualifiedName();
}
}

View File

@ -1,117 +0,0 @@
/*
* Copyright (c) 2012-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
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.selenium.core.organization;
import static java.lang.String.format;
import static org.eclipse.che.commons.lang.NameGenerator.generate;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.MembersInjector;
import com.google.inject.Provider;
import java.lang.reflect.Field;
import org.eclipse.che.selenium.core.client.TestOrganizationServiceClient;
import org.eclipse.che.selenium.core.client.TestOrganizationServiceClientFactory;
import org.eclipse.che.selenium.core.user.AdminTestUser;
/**
* Injector for custom annotation {@link InjectTestOrganization}.
*
* @author Dmytro Nochevnov
*/
public class TestOrganizationInjector<T> implements MembersInjector<T> {
private final Field field;
private final InjectTestOrganization injectTestOrganization;
private final Provider<Injector> injectorProvider;
public TestOrganizationInjector(
Field field,
InjectTestOrganization injectTestOrganization,
Provider<Injector> injectorProvider) {
this.field = field;
this.injectTestOrganization = injectTestOrganization;
this.injectorProvider = injectorProvider;
}
@Override
public void injectMembers(T instance) {
Injector injector = injectorProvider.get();
String name = generateName();
String parentPrefix = injectTestOrganization.parentPrefix();
AdminTestUser adminTestUser = injector.getInstance(Key.get(AdminTestUser.class));
TestOrganizationServiceClientFactory testOrganizationServiceClient =
injector.getInstance(Key.get(TestOrganizationServiceClientFactory.class));
TestOrganizationServiceClient adminOrganizationServiceClient =
testOrganizationServiceClient.create(adminTestUser);
TestOrganization testOrganization;
try {
if (parentPrefix.isEmpty()) {
testOrganization = new TestOrganization(name, adminOrganizationServiceClient);
} else {
String parentId = findInjectedOrganization(instance, parentPrefix);
testOrganization = new TestOrganization(name, parentId, adminOrganizationServiceClient);
}
field.setAccessible(true);
field.set(instance, testOrganization);
} catch (Exception e) {
throw new RuntimeException(
format(
"Failed to instantiate organization with name '%s' in class '%s'",
injectTestOrganization.prefix(), instance.getClass().getName()),
e);
}
}
private String generateName() {
String fieldNamePrefix = field.getName().substring(0, Math.min(field.getName().length(), 12));
String annotationPrefix = injectTestOrganization.prefix();
String prefix = annotationPrefix.isEmpty() ? fieldNamePrefix : annotationPrefix;
return generate(prefix + "-", 5);
}
/**
* @return id of organization among the fields of instance with name which starts from
* orgNamePrefix
*/
private String findInjectedOrganization(T instance, String orgNamePrefix) {
for (Field field : instance.getClass().getDeclaredFields()) {
if (field.getType() == TestOrganization.class) {
field.setAccessible(true);
TestOrganization org;
try {
org = (TestOrganization) field.get(instance);
} catch (IllegalAccessException e) {
throw new IllegalArgumentException(e);
}
if (org != null && org.getName().startsWith(orgNamePrefix)) {
return org.getId();
}
}
}
throw new IllegalArgumentException(
format(
"Organization with name which starts from '%s' not found or isn't instantiated in class '%s'",
orgNamePrefix, instance.getClass().getName()));
}
}

View File

@ -1,31 +0,0 @@
/*
* Copyright (c) 2012-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
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.selenium.core.pageobject;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
/**
* To instantiate different instances of the same page object.
*
* @author Anatolii Bazko
*/
@Target({FIELD})
@Retention(RUNTIME)
@Documented
public @interface InjectPageObject {
int driverId();
}

View File

@ -1,130 +0,0 @@
/*
* Copyright (c) 2012-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
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.selenium.core.pageobject;
import static java.lang.String.format;
import com.google.inject.Inject;
import com.google.inject.Injector;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Stream;
import org.eclipse.che.commons.annotation.Nullable;
import org.eclipse.che.selenium.core.SeleniumWebDriver;
import org.eclipse.che.selenium.core.webdriver.SeleniumWebDriverFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Injects fields annotated with {@link InjectPageObject}. All page objects with the same {@link
* InjectPageObject#driverId()} must share a common {@link SeleniumWebDriver} instance.
*
* @author Anatolii Bazko
*/
public abstract class PageObjectsInjector {
private static final Logger LOG = LoggerFactory.getLogger(PageObjectsInjector.class);
@Inject private SeleniumWebDriverFactory seleniumWebDriverFactory;
public void injectMembers(Object testInstance, Injector injector) throws Exception {
Map<Integer, Set<Field>> toInject = collectFieldsToInject(testInstance);
for (Integer poIndex : toInject.keySet()) {
Map<Class<?>, Object> container = new HashMap<>();
SeleniumWebDriver seleniumWebDriver = seleniumWebDriverFactory.create();
container.put(SeleniumWebDriver.class, seleniumWebDriver);
container.putAll(getDependenciesWithWebdriver(seleniumWebDriver));
for (Field f : toInject.get(poIndex)) {
try {
injectField(f, testInstance, container, injector);
} catch (Exception e) {
throw new RuntimeException(
format("Error of injection member '%s' into test '%s'.", f, testInstance), e);
}
}
}
}
public abstract Map<Class<?>, Object> getDependenciesWithWebdriver(
SeleniumWebDriver seleniumWebDriver);
private void injectField(
Field field, Object instance, Map<Class<?>, Object> container, Injector injector)
throws Exception {
Object object = instantiate(field.getType(), container, injector);
field.setAccessible(true);
field.set(instance, object);
}
private Object instantiate(Class<?> type, Map<Class<?>, Object> container, Injector injector)
throws Exception {
Object obj;
Optional<Constructor<?>> constructor = findConstructor(type);
if (!constructor.isPresent()) {
// interface? get instance from a guice container
obj = injector.getInstance(type);
} else {
Class<?>[] parameterTypes = constructor.get().getParameterTypes();
Object[] params = new Object[parameterTypes.length];
for (int i = 0; i < parameterTypes.length; i++) {
Object pt = container.get(parameterTypes[i]);
if (pt == null) {
pt = instantiate(parameterTypes[i], container, injector);
}
params[i] = pt;
}
obj = constructor.get().newInstance(params);
}
container.put(obj.getClass(), obj);
return obj;
}
@Nullable
private Optional<Constructor<?>> findConstructor(Class<?> type) {
return Stream.of(type.getConstructors())
.filter(
c ->
c.isAnnotationPresent(com.google.inject.Inject.class)
|| c.isAnnotationPresent(javax.inject.Inject.class))
.findAny();
}
/** Find class fields annotated with {@link InjectPageObject}. */
private Map<Integer, Set<Field>> collectFieldsToInject(Object testInstance) {
Map<Integer, Set<Field>> toInject = new HashMap<>();
for (Field f : testInstance.getClass().getDeclaredFields()) {
if (f.isAnnotationPresent(InjectPageObject.class)) {
InjectPageObject pageObject = f.getAnnotation(InjectPageObject.class);
int poIndex = pageObject.driverId();
Set<Field> fields = toInject.computeIfAbsent(poIndex, k -> new HashSet<>());
fields.add(f);
}
}
return toInject;
}
}

View File

@ -1,31 +0,0 @@
/*
* Copyright (c) 2012-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
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.selenium.core.project;
/** @author Musienko Maxim */
public class ProjectTemplates {
public static final String C = "c.json";
public static final String CPP = "cpp.json";
public static final String PHP = "php.json";
public static final String PYTHON = "python.json";
public static final String NODE_JS = "node_js.json";
public static final String MAVEN_SPRING = "maven_spring.json";
public static final String MAVEN_SIMPLE = "maven_simple.json";
public static final String MAVEN_JAVA_MULTIMODULE = "maven_java_multimodule.json";
public static final String PLAIN_JAVA = "plain_java.json";
public static final String CONSOLE_JAVA_SIMPLE = "console_java_simple.json";
public static final String GO = "go.json";
public static final String DOT_NET = "dotNet.json";
public static final String PROJECT_OF_UNDEFINED_TYPE = "undefined.json";
private ProjectTemplates() {}
}

View File

@ -1,21 +0,0 @@
/*
* Copyright (c) 2012-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
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.selenium.core.provider;
import org.eclipse.che.selenium.core.user.AdminTestUser;
/**
* Admin test user provider.
*
* @author Dmytro Nochevnov
*/
public interface AdminTestUserProvider extends RemovableUserProvider<AdminTestUser> {}

View File

@ -1,21 +0,0 @@
/*
* Copyright (c) 2012-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
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.selenium.core.provider;
import org.eclipse.che.selenium.core.user.DefaultTestUser;
/**
* Default test user provider.
*
* @author Dmytro Nochevnov
*/
public interface DefaultTestUserProvider extends RemovableUserProvider<DefaultTestUser> {}

View File

@ -1,27 +0,0 @@
/*
* Copyright (c) 2012-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
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.selenium.core.provider;
import com.google.inject.Provider;
import java.io.IOException;
import org.eclipse.che.selenium.core.user.TestUser;
/**
* Removable user provider.
*
* @author Dmytro Nochevnov
*/
public interface RemovableUserProvider<T extends TestUser> extends Provider<T> {
/** Deletes user. */
void delete() throws IOException;
}

View File

@ -1,22 +0,0 @@
/*
* Copyright (c) 2012-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
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.selenium.core.provider;
import com.google.inject.Provider;
import java.net.URL;
/**
* Api endpoint.
*
* @author Anatolii Bazko
*/
public interface TestApiEndpointUrlProvider extends Provider<URL> {}

View File

@ -1,22 +0,0 @@
/*
* Copyright (c) 2012-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
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.selenium.core.provider;
import com.google.inject.Provider;
import java.net.URL;
/**
* Url to Dashboard.
*
* @author Anatolii Bazko
*/
public interface TestDashboardUrlProvider extends Provider<URL> {}

View File

@ -1,22 +0,0 @@
/*
* Copyright (c) 2012-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
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.selenium.core.provider;
import com.google.inject.Provider;
import java.net.URL;
/**
* Url to IDE.
*
* @author Anatolii Bazko
*/
public interface TestIdeUrlProvider extends Provider<URL> {}

View File

@ -1,21 +0,0 @@
/*
* Copyright (c) 2012-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
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.selenium.core.provider;
import org.eclipse.che.selenium.core.user.TestUser;
/**
* New test user provider.
*
* @author Dmytro Nochevnov
*/
public interface TestUserProvider extends RemovableUserProvider<TestUser> {}

Some files were not shown because too many files have changed in this diff Show More