Remove unrelated source code

pull/3/head
Sergii Kabashniuk 2021-05-20 16:57:47 +03:00
parent 98b66ff1f6
commit aab541ad08
163 changed files with 2 additions and 15418 deletions

View File

@ -1,27 +0,0 @@
---
name: Question 🤔
about: Usage question or discussion about Eclipse Che.
title: ''
labels: 'kind/question'
assignees: ''
---
<!--
To make it easier for us to help you, please include as much useful information as possible.
Useful Links:
- Documentation: https://www.eclipse.org/che/docs
- Contributing: https://github.com/eclipse/che/blob/master/CONTRIBUTING.md
Eclipse Che has public chat on:
- Mattermost: https://mattermost.eclipse.org/eclipse/channels/eclipse-che
Before opening a new issue, please search existing issues https://github.com/eclipse/che/issues
-->
## Summary
## Relevant information
<!-- Provide as much useful information as you can -->

View File

@ -1,78 +0,0 @@
---
name: Bug report 🐞
about: Report a bug found in Eclipse Che
title: ''
labels: 'kind/bug'
assignees: ''
---
<!--
To make it easier for us to help you, please include as much useful information as possible.
Useful Links:
- Documentation: https://www.eclipse.org/che/docs
- Contributing: https://github.com/eclipse/che/blob/master/CONTRIBUTING.md
Eclipse Che has public chat on:
- Mattermost: https://mattermost.eclipse.org/eclipse/channels/eclipse-che
Before opening a new issue, please search existing issues https://github.com/eclipse/che/issues
-->
### Describe the bug
<!-- A clear and concise description of what the bug is. -->
### Che version
<!-- (if workspace is running, version can be obtained with help/about menu) -->
- [ ] latest
- [ ] nightly
- [ ] other: please specify
### Steps to reproduce
<!--
1. Do '...'
2. Click on '....'
3. See error
-->
### Expected behavior
<!-- A clear and concise description of what you expected to happen. -->
### Runtime
- [ ] kubernetes (include output of `kubectl version`)
- [ ] Openshift (include output of `oc version`)
- [ ] minikube (include output of `minikube version` and `kubectl version`)
- [ ] minishift (include output of `minishift version` and `oc version`)
- [ ] docker-desktop + K8S (include output of `docker version` and `kubectl version`)
- [ ] other: (please specify)
### Screenshots
<!-- If applicable, add screenshots to help explain your problem. -->
### Installation method
- [ ] chectl
* provide a full command that was used to deploy Eclipse Che (including the output)
* provide an output of `chectl version` command
- [ ] OperatorHub
- [ ] I don't know
### Environment
- [ ] my computer
- [ ] Windows
- [ ] Linux
- [ ] macOS
- [ ] Cloud
- [ ] Amazon
- [ ] Azure
- [ ] GCE
- [ ] other (please specify)
- [ ] Dev Sandbox (workspaces.openshift.com)
- [ ] other: please specify
### Eclipse Che Logs
<!-- https://www.eclipse.org/che/docs/che-7/collecting-logs-using-chectl -->
### Additional context
<!-- Add any other context about the problem here. -->

View File

@ -1,19 +0,0 @@
---
name: Enhancement💡
about: Suggest a enhancement for Eclipse Che
title: ''
labels: 'kind/enhancement'
assignees: ''
---
### Is your enhancement related to a problem? Please describe.
<!-- A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] -->
### Describe the solution you'd like
<!-- A clear and concise description of what you want to happen. -->
### Describe alternatives you've considered
<!--A clear and concise description of any alternative solutions or features you've considered. -->
### Additional context
<!-- Add any other context or screenshots about the enhancement here. -->

View File

@ -1,54 +0,0 @@
---
name: Release📦
about: Create new release issue for Eclipse Che
title: ''
labels: 'kind/release'
assignees: ''
---
### List of pending issues / PRs
* [ ] description #xxx https://github.com/eclipse/che/issues/xxx
### Release status
The following will be released via [che-release](https://github.com/eclipse/che-release/blob/master/cico_release.sh) according to a series of phases:
1. [ ] che-machine-exec, che-theia, che-devfile-registry, che-dashboard, devworkspace-operator, jwtproxy, kubernetes image puller
2. [ ] che-plugin-registry (once che-theia and machine-exec are done)
3. [ ] che-parent and che server
4. [ ] devworkspace-che-operator
5. [ ] che-operator
Each phase will [send a Mattermost notification to the Eclipse Che releases channel](https://mattermost.eclipse.org/eclipse/channels/eclipse-che-releases).
Then, these steps will be done, once the above projects are released and PRs are merged:
- [ ] [chectl](https://github.com/che-incubator/chectl/actions/workflows/release-stable-PRs.yml) _(depends on che-operator)_
- [ ] [Che community operator PRs](https://github.com/operator-framework/community-operators/pulls?q=%22Update+eclipse-che+operator%22+is%3Aopen) _(depends on che-operator)_
- [ ] [che-docs PR](https://github.com/eclipse/che-docs/pulls/che-bot) _(depends on che-operator)_
If this is a .0 release:
- [ ] complete current milestone
- [ ] move incomplete *deferred* issues to backlog
- [ ] move incomplete *WIP* issues to next milestone
- [ ] close completed issues
- [ ] close milestone
| Process <sup>[1]</sup> | Script | Action | Container(s) + Artifact(s) |
| --- | --- | --- | --- |
| [che-release](https://github.com/eclipse/che-release/blob/master/RELEASE.md) | [cico_release.sh](https://github.com/eclipse/che-release/blob/master/cico_release.sh) | [Action](https://github.com/eclipse/che-release/actions?query=workflow%3A%22Release+-+Orchestrate+Overall+Release+Phases%22) | n/a |
| [che-theia](https://github.com/eclipse/che-theia/blob/master/RELEASE.md) | [make-release.sh](https://github.com/eclipse/che-theia/blob/master/make-release.sh) | [Action](https://github.com/eclipse/che-theia/actions?query=workflow%3A%22Release+Che+Theia%22) | [`eclipse/che-theia`](https://quay.io/eclipse/che-theia) |
| [che-machine-exec](https://github.com/eclipse-che/che-machine-exec/blob/master/RELEASE.md) | [make-release.sh](https://github.com/eclipse-che/che-machine-exec/blob/master/make-release.sh) | [Action](https://github.com/eclipse-che/che-machine-exec/actions?query=workflow%3A%22Release+Che+Machine+Exec%22) | [`eclipse/che-machine-exec`](https://quay.io/eclipse/che-machine-exec)|
| [che-devfile-registry](https://github.com/eclipse/che-devfile-registry/blob/master/RELEASE.md) | [make-release.sh](https://github.com/eclipse/che-devfile-registry/blob/master/make-release.sh) | [Action](https://github.com/eclipse/che-devfile-registry/actions?query=workflow%3A%22Release+Che+Devfile+Registry%22) | [`eclipse/che-devfile-registry`](https://quay.io/eclipse/che-devfile-registry)|
| [che-plugin-registry](https://github.com/eclipse/che-plugin-registry/blob/master/RELEASE.md) | [make-release.sh](https://github.com/eclipse/che-plugin-registry/blob/master/make-release.sh) | [Action](https://github.com/eclipse/che-plugin-registry/actions?query=workflow%3A%22Release+Che+Plugin+Registry%22) | [`eclipse/che-plugin-registry`](https://quay.io/eclipse/che-plugin-registry)|
| [che-parent](https://github.com/eclipse/che-parent/blob/master/RELEASE.md) | [make-release.sh](https://github.com/eclipse/che-parent/blob/master/make-release.sh) | [Action](https://github.com/eclipse/che/actions?query=workflow%3A%22Release+Che+Server%22) | [che-server](https://search.maven.org/search?q=a:che-server) <sup>[2]</sup> |
| [che-dashboard](https://github.com/eclipse-che/che-dashboard/blob/main/RELEASE.md) | [make-release.sh](https://github.com/eclipse-che/che-dashboard/blob/master/make-release.sh) | [Action](https://github.com/eclipse-che/che-dashboard/actions?query=workflow%3A%22Release+Che+Dashboard%22) | [`che-dashboard`](https://quay.io/repository/eclipse/che-dashboard?tag=next&tab=tags) |
| [che](https://github.com/eclipse/che/blob/master/RELEASE.md) | [make-release.sh](https://github.com/eclipse/che/blob/master/make-release.sh) | [Action](https://github.com/eclipse/che/actions?query=workflow%3A%22Release+Che+Server%22) | [`eclipse/che-server`](https://quay.io/eclipse/che-server),<br/>[`eclipse/che-endpoint-watcher`](https://quay.io/eclipse/che-endpoint-watcher),<br/> [`eclipse/che-keycloak`](https://quay.io/eclipse/che-keycloak),<br/> [`eclipse/che-postgres`](https://quay.io/eclipse/che-postgres),<br/> [`eclipse/che-server`](https://quay.io/eclipse/che-server),<br/> [`eclipse/che-e2e`](https://quay.io/eclipse/che-e2e) |
| [devworkspace-operator (controller)](https://github.com/devfile/devworkspace-operator/) | [make-release.sh](https://github.com/devfile/devworkspace-operator/blob/main/make-release.sh) | [Action](https://github.com/devfile/devworkspace-operator/actions/workflows/release.yml) | [`devfile/devworkspace-controller`](https://quay.io/repository/devfile/devworkspace-controller?tab=tags)|
| [devworkspace-che-operator](https://github.com/che-incubator/devworkspace-che-operator/) | [make-release.sh](https://github.com/che-incubator/devworkspace-che-operator/blob/main/make-release.sh) | [Action](https://github.com/che-incubator/devworkspace-che-operator/actions/workflows/release.yml) | [`che-incubator/devworkspace-che-operator`](https://quay.io/repository/che-incubator/devworkspace-che-operator?tab=tags)|
| [che-operator](https://github.com/eclipse-che/che-operator/blob/master/RELEASE.md) | [make-release.sh](https://github.com/eclipse-che/che-operator/blob/master/make-release.sh) | [Action](https://github.com/eclipse-che/che-operator/actions?query=workflow%3A%22Release+Che+Operator%22) | [`eclipse/che-operator`](https://quay.io/eclipse/che-operator)|
| [chectl](https://github.com/che-incubator/chectl/blob/master/RELEASE.md) | [make-release.sh](https://github.com/che-incubator/chectl/blob/master/make-release.sh) | [Action](https://github.com/che-incubator/chectl/actions) | [chectl releases](https://github.com/che-incubator/chectl/releases)
<sup>[1]</sup> Overall process owner: @mkuznyetsov

View File

@ -1,19 +0,0 @@
---
name: Task 🔧
about: Internal things, technical debt, and to-do tasks to be performed.
title: ''
labels: 'kind/task'
assignees: ''
---
### Is your task related to a problem? Please describe.
<!-- A clear and concise description of what the problem is.-->
### Describe the solution you'd like
<!-- A clear and concise description of what you want to happen. -->
### Describe alternatives you've considered
<!--A clear and concise description of any alternative solutions or features you've considered. -->
### Additional context
<!-- Add any other context or screenshots about the task here. -->

View File

@ -1,50 +0,0 @@
# Contributor Code of Conduct
As contributors and maintainers of this project, and in the interest of
fostering an open and welcoming community, we pledge to respect all people who
contribute through reporting issues, posting feature requests, updating
documentation, submitting pull requests or patches, and other activities.
We are committed to making participation in this project a harassment-free
experience for everyone, regardless of level of experience, gender, gender
identity and expression, sexual orientation, disability, personal appearance,
body size, race, ethnicity, age, religion, or nationality.
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery
* Personal attacks
* Trolling or insulting/derogatory comments
* Public or private harassment
* Publishing other's private information, such as physical or electronic
addresses, without explicit permission
* Other unethical or unprofessional conduct
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
By adopting this Code of Conduct, project maintainers commit themselves to
fairly and consistently applying these principles to every aspect of managing
this project. Project maintainers who do not follow or enforce the Code of
Conduct may be permanently removed from the project team.
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community.
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting a project maintainer at che-dev@eclipse.org. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. Maintainers are
obligated to maintain confidentiality with regard to the reporter of an
incident.
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 1.3.0, available at
[http://contributor-covenant.org/version/1/3/0/][version]
[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/3/0/

View File

@ -1,242 +0,0 @@
# Contributing to Che
- [Other Che repositories](#other-che-repositories)
- [Devfile to contribute](#devfile-to-contribute)
- [Contribute to ...](#contribute-to-...)
- [Dashboard](#dashboard)
- [Che Server a.k.a WS master](#che-server-a.k.a-ws-master)
## Other Che repositories
Che is composed of multiple sub projects. For each projects we provide a *CONTRIBUTE.md* file describing how to setup the development environment to start your contribution. Most of the time, we encourage you to use Che to contribute to Che.
<!-- begin repository list -->
Repository | Component | Description | Devfile | Documentation
--- | --- | --- | --- | ---
[che](https://github.com/eclipse/che) | | (this repository) the main project repository | [devfile](https://github.com/eclipse/che/blob/master/devfile.yaml) | [doc](https://github.com/eclipse/che/blob/master/CONTRIBUTING.md#che-server-aka-ws-master)
---| [dockerfiles](https://github.com/eclipse/che/tree/master/dockerfiles) | source code, dockerfiles to build our main docker images. Note that Che-theia related dockerfiles are located in che-theia repo. | | |
---| [wsmaster](https://github.com/eclipse/che/tree/master/wsmaster) | orchestrates the Che workspaces with devfiles on Kubernetes | | |
---| [tests](https://github.com/eclipse/che/tree/master/tests) | source code of our integration tests. | | |
[che-theia](https://github.com/eclipse-che/che-theia) | | Theia IDE integrated in Che. | [devfile](https://github.com/eclipse-che/che-theia/blob/master/devfiles/che-theia-all.devfile.yaml) | [doc](https://github.com/eclipse-che/che-theia/blob/master/CONTRIBUTING.md)
---| [generator](https://github.com/eclipse-che/che-theia/tree/master/generator) | `che:theia init` CLI to prepare and build che-theia | | |
[chectl](https://github.com/che-incubator/chectl) | | The CLI to install Che, create and start workspaces and devfiles | [devfile](https://github.com/che-incubator/chectl/blob/master/devfile.yaml) | [doc](https://github.com/che-incubator/chectl/blob/master/CONTRIBUTING.md)
[dashboard](https://github.com/eclipse-che/che-dashboard) | | UI to manage workspaces, devfiles, etc. | [devfile](https://github.com/eclipse-che/che-dashboard/blob/main/devfile.yaml) | [doc](https://github.com/eclipse/che/blob/master/CONTRIBUTING.md#dashboard)
[devfile-registry](https://github.com/eclipse-che/che-devfile-registry) | | The default set of devfiles that would be made available on the Che dashboard stacks. | |
[docs](https://github.com/eclipse/che-docs) | | Eclipse Che documentation https://www.eclipse.org/che/docs/ source code. | [devfile](https://github.com/eclipse/che-docs/blob/master/devfile.yaml) | [doc](https://github.com/eclipse/che/blob/master/CONTRIBUTING.md#dashboard)
[machine-exec](https://github.com/eclipse-che/che-machine-exec) | | Interface to execute tasks and terminals on other containers within a workspace. | [devfile](https://github.com/eclipse-che/che-machine-exec/blob/master/devfile.yaml) | [doc](https://github.com/eclipse-che/che-machine-exec/blob/master/CONTRIBUTING.md)
[operator](https://github.com/eclipse-che/che-operator) | | Che operator to deploy, update and manage K8S/OpenShift resources of Che. | [devfile](https://github.com/eclipse-che/che-operator/blob/master/devfile.yaml) |
[plugin-broker](https://github.com/eclipse/che-plugin-broker) | | The workspace microservice that is in charge of analyzing, preparing and installing the workspace components defined in a Devfile. | [devfile](https://github.com/eclipse/che-plugin-broker/blob/master/devfile.yaml) | [doc](https://github.com/eclipse/che-plugin-broker/blob/master/CONTRIBUTING.md)
[plugin-registry](https://github.com/eclipse-che/che-plugin-registry) | | The default set of Che plugins (vscode extension + containers) or editors that could be installed on any Che workspaces. | |
[website](https://github.com/eclipse/che-website) | | https://eclipse.org/che website source code. | [devfile](https://github.com/eclipse/che-website/blob/master/devfile.yaml) |
[workspace-client](https://github.com/eclipse-che/che-workspace-client) | | JS library to interact with a che-server. | |
[che-sidecar-bazel](https://github.com/che-dockerfiles/che-sidecar-bazel) | | Eclipse Che Sidecar container for Bazel tooling | |
[che-sidecar-protobuf](https://github.com/che-dockerfiles/che-sidecar-protobuf) | | Eclipse Che Sidecar container for Protobuf tooling | |
[che-sidecar-tekton](https://github.com/che-dockerfiles/che-sidecar-tekton) | | Eclipse Che Sidecar container for Tekton tooling | |
[che-sidecar-kubernetes-tooling](https://github.com/che-dockerfiles/che-sidecar-kubernetes-tooling) | | Eclipse Che Sidecar container for Kubernetes tooling | |
[che-sidecar-openshift-connector](https://github.com/che-dockerfiles/che-sidecar-openshift-connector) | | Eclipse Che Sidecar container for OpenShift connector tooling | |
[che-container-tools](https://github.com/che-dockerfiles/che-container-tools) | | Base image used for sidecars that service container tooling plugins | |
[che-sidecar-python](https://github.com/che-dockerfiles/che-sidecar-python) | | Eclipse Che Sidecar container for python tooling | |
[che-custom-nodejs-deasync](https://github.com/che-dockerfiles/che-custom-nodejs-deasync) | | Provides a custom nodejs binary embedding deasync node-gyp module as builtin module | |
[che-sidecar-go](https://github.com/che-dockerfiles/che-sidecar-go) | | Eclipse Che sidecar container for go | |
[che-sidecar-sonarlint](https://github.com/che-dockerfiles/che-sidecar-sonarlint) | | Eclipse Che sidecar container for sonalint extension | |
[che-sidecar-dotnet](https://github.com/che-dockerfiles/che-sidecar-dotnet) | | Eclipse Che sidecar container for dotnet | |
[che-sidecar-shellcheck](https://github.com/che-dockerfiles/che-sidecar-shellcheck) | | Eclipse Che sidecar container for shellcheck | |
[che-sidecar-camelk](https://github.com/che-dockerfiles/che-sidecar-camelk) | | Eclipse Che sidecar container for camelk | |
[che-sidecar-vale](https://github.com/che-dockerfiles/che-sidecar-vale) | | Eclipse Che sidecar container for vale | |
[che-cert-manager-ca-cert-generator-image](https://github.com/che-dockerfiles/che-cert-manager-ca-cert-generator-image) | | CA cert generation job image used by chectl | |
[che-buildkit-base](https://github.com/che-dockerfiles/che-buildkit-base) | | Eclipse Che Sidecar container for buildkit tooling | |
[che-sidecar-scala](https://github.com/che-dockerfiles/che-sidecar-scala) | | Eclipse Che Sidecar container for scala tooling | |
[che-buildah-base](https://github.com/che-dockerfiles/che-buildah-base) | | Use this image to build docker images using buildah | |
[che-docker-registry-image-copier](https://github.com/che-dockerfiles/che-docker-registry-image-copier) | | copy images between public and private docker registry inside k8s cluster | |
[che-php-base](https://github.com/che-dockerfiles/che-php-base) | | Base image to be used for the PHP devfile | |
[che-tls-secret-creator](https://github.com/che-dockerfiles/che-tls-secret-creator) | | This images generates TLS certificates | |
[build-action](https://github.com/che-dockerfiles/build-action) | | Custom GitHub Action for building sidecar Dockerfiles | |
[che-sidecar-podman](https://github.com/che-dockerfiles/che-sidecar-podman) | | Eclipse Che Sidecar container for podman tooling | |
[che-sidecar-clang](https://github.com/che-dockerfiles/che-sidecar-clang) | | Eclipse Che Sidecar container for clang tooling | |
[che-sidecar-php](https://github.com/che-dockerfiles/che-sidecar-php) | | Eclipse Che Sidecar container for php tooling | |
[che-sidecar-java](https://github.com/che-dockerfiles/che-sidecar-java) | | Eclipse Che Sidecar container for java tooling | |
[che-sidecar-dependency-analytics](https://github.com/che-dockerfiles/che-sidecar-dependency-analytics) | | Eclipse Che Sidecar container for dependency analytics tooling | |
[che-sidecar-node](https://github.com/che-dockerfiles/che-sidecar-node) | | Eclipse Che Sidecar container for node tooling | |
[che-theia-openshift-auth](https://github.com/che-incubator/che-theia-openshift-auth) | | OpenShift authentication plugin | |
[configbump](https://github.com/che-incubator/configbump) | | Simple Kubernetes controller that is able to quickly synchronize a set of config maps | |
[workspace-data-sync](https://github.com/che-incubator/workspace-data-sync) | | Provides the ability to increase I/O performance for a developer workspaces | |
[che-workspace-telemetry-client](https://github.com/che-incubator/che-workspace-telemetry-client) | | abstract telemetry API and a Typescript implementation of the API. | |
[kubernetes-image-puller](https://github.com/che-incubator/kubernetes-image-puller) | | ensures that all nodes in the cluster have those images cached | |
<!-- end repository list -->
## Devfile to contribute
We are trying to provide a devfile for each areas where you could contribute. Each devfile could be run on any Che instances to setup a *ready-to-code* developer environment. Beware that each of them may need a certain amount of memory.
Devfile could be launched through a factory or [chectl](https://github.com/che-incubator/chectl) cli.
```bash
$ chectl workspace:start -f devfiles/che-theia-all.devfile.yaml
```
or
```bash
$ chectl workspace:start -f https://raw.githubusercontent.com/eclipse/che-theia/master/devfiles/che-theia-all.devfile.yaml
```
or `https://<CheInstance>/f?url=https://raw.githubusercontent.com/eclipse/che-theia/master/devfiles/che-theia-all.devfile.yaml`
## Contribute to ...
Let's cover the developer flow for theses projects:
### Dashboard
Dashboard source code is located in [https://github.com/eclipse-che/che-dashboard](https://github.com/eclipse-che/che-dashboard) repository.
It is an AngularJS application. Here is the developer workflow if you want to contribute to it:
#### Devfile for dashboard development
The devfile: [https://github.com/eclipse-che/che-dashboard/blob/master/devfile.yaml](https://github.com/eclipse-che/che-dashboard/blob/master/devfile.yaml)
In this section, we show how to setup a Che environment to work on the Che dashboard, and how to use it.
For the whole workflows, we will need a workspace with such containers:
- Dashboard Dev container (a.k.a dash-dev): Dashdev is a all in one container for running commands such as build, test or start the dashboard server.
All containers have `/projects` folder mounted, which is shared among them.
Developer workflow:
1. Start the workspace with the devfile, it is cloning Che repo.
2. Build
3. Code ...
4. Run unit test
5. Start dashboard server and preview
#### Step 1: Start the workspace with the devfile, it is cloning Che repo.
In this section we are going to start a new workspace to work on che-theia. The new workspace will have few projects cloned: `theia` and `che-theia`. It will also setup the containers and commands in the `My workspace` view. We will use these commands in the next steps.
The devfile could be started using `chectl`:
```bash
$ chectl workspace:start -f https://raw.githubusercontent.com/eclipse-che/che-dashboard/master/devfile.yaml
```
#### Step 2: Build
In this section we are going to build the dashboard project.
You can use the Che command `dashboard_build` (command pallette > Run task > … or containers view)
Basically, this command will run
```bash
# [dash-dev]
$ yarn
```
#### Step 3: Code ...
#### Step 4: Run unit test (optional)
In this step, we will run the Dashboard unit tests:
You can use the Che command `dashboard_test` (command pallette > Run task > … or containers view)
Basically, this command will run
```bash
# [dash-dev]
$ yarn test
```
#### Step 5: Start dashboard server and preview
In this step, we will run the dashboard server and see the live reloadable preview.
You can use the Che command `dashboard_dev_server` (command pallette > Run task > … or containers view)
```bash
# [dashboard_dev_server]
$ node_modules/.bin/gulp serve --server=<che_api_url>
```
### Che server a.k.a WS master
There is a [devfile](https://github.com/eclipse/che/blob/master/devfile.yaml) for development of Che server in Che.
To build Che one may run a predefined build task from the devfile.
Starting Che master requires some manual steps.
Open a terminal in runtime container (`che-server-runtime`) and perform:
- First, set `CHE_HOME` environment variable with absolute path to parent folder of Che master's Tomcat.
It might look like `/projects/che/assembly/assembly-main/target/eclipse-che-*-SNAPSHOT/eclipse-che-*-SNAPSHOT`.
- Then set `CHE_HOST` with the endpoint of new Che master.
If using the [devfile](devfile.yaml) the endpoint is `che-dev` and already set.
- After, set `CHE_INFRASTRUCTURE_ACTIVE` according to your environment.
For example: `openshift` (note, use `kubernetes` and `openshift` insted of `minikube` and `minishift` correspondingly).
- Run `/entrypoint.sh`.
After this, new Che master should be accesible from the `che-dev` endpoint.
To reach Swagger use url from `che-dev` endpoint with `/swagger` suffix.
To start a workspace from Che server under development some additional configuration of the cluster is needed.
One should add rights for the service account to be able to perform all needed for Che server actions.
Example for Openshift (in case of Kubernetes replace `oc` with `kubectl`):
```bash
cat << EOF | oc apply -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
labels:
app: che
component: che
name: che-workspace-admin
namespace: che
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: admin
subjects:
- kind: ServiceAccount
name: che-workspace
namespace: che
EOF
```
Also `CHE_API_INTERNAL`, `CHE_API_EXTERNAL` and `CHE_API` should be set in runner container and point to new Che server API.
If one uses provided devfile, they are already set to: `http://che-dev:8080/api`, which should be changed in case of https protocol.
## Pull Request Template and its Checklist
Che repositories includes a GitHub Pull Request Template. Contributors must read and complete the template. In particular there is a list of requirements that the author needs to fulfil to merge the PR. This sections goes into the details of this checklist.
### The Eclipse Contributor Agreement is valid
The author has completed the [Eclipse Contributor Agreement](https://accounts.eclipse.org/user/eca) and has signed the commits using his email.
### Code produced is complete
No `TODO` comments left in the PR source code.
### Code builds without errors
The author has verified that code builds, tests pass and linters are happy.
### Tests are covering the bugfix
If the Pull Request fixes a bug it must includes a new automated test. The test validates the fix and protect against future regressions.
### The repository devfile is up to date and works
The devfile commands used to build and run the application are still working.
### Sections "What issues does this PR fix or reference" and "How to test this PR" completed
Never omit the two sections "What issues does this PR fix or reference" and "How to test this PR".
### Relevant user documentation updated
The author has documented the changes to Che installation, usage or management in [Che documentation](https://github.com/eclipse/che-docs).
### Relevant contributing documentation updated
Document changes to the steps to contribute to the project in the `CONTRIBUTING.md` files.
### CI/CD changes implemented, documented and communicated
Update CI/CD scripts and documentation when the PR includes changes to the build, test, distribute or deploy procedures. Communicate CI/CD changes to the whole community with an email.

View File

@ -1,83 +1,2 @@
<div id="header" align="center">
[![Eclipse Che - Eclipse Next-Generation IDE](https://raw.githubusercontent.com/eclipse/che/assets/eclipseche.png)](
https://www.eclipse.org/che/)
**Next-generation container development platform, developer workspace server and cloud IDE**
[![Eclipse License](https://img.shields.io/badge/license-Eclipse-brightgreen.svg)](https://github.com/codenvy/che/blob/master/LICENSE)
<a href="https://sonarcloud.io/dashboard?id=org.eclipse.che%3Ache-parent%3Amaster">
<img src="https://sonarcloud.io/images/project_badges/sonarcloud-black.svg" width="94" height="20" href="" />
</a>
*Che is Kubernetes-native and places everything the developer needs into containers in Kube pods including dependencies, embedded containerized runtimes, a web IDE, and project code. This makes workspaces distributed, collaborative, and portable to run anywhere Kubernetes runs ... [Read More](https://www.eclipse.org/che/features/)*
</div>
![Eclipse Che](https://raw.githubusercontent.com/eclipse/che/assets/screenshoft_che7-quarkus-demo.png)
---
**Visit website at: https://www.eclipse.org/che/** and documentation at: https://www.eclipse.org/che/docs
- [**Getting Started**](#getting-started)
- [**Using Eclipse Che**](#using-eclipse-che)
- [**Feedback and Community**](#feedback-and-community)
- [**Contributing**](#contributing)
- [**Roadmap**](#roadmap)
- [**License**](#license)
---
### Getting Started
Here you can find links on how to get started with Eclipse Che:
- [Use Eclipse Che online](https://www.eclipse.org/che/getting-started/cloud/)
- [Run Eclipse Che on your own K8S cluster](https://www.eclipse.org/che/docs/che-7/che-quick-starts)
### Using Eclipse Che
Here you can find references to useful documentation and hands-on guides to learn how to get the most of Eclipse Che:
- [Customize Che workspaces for your projects](https://www.eclipse.org/che/docs/che-7/configuring-a-workspace-using-a-devfile/)
- [Run VSCode Extensions in Che workspaces](https://www.eclipse.org/che/docs/che-7/end-user-guide/adding-a-vs-code-extension-to-a-workspace/)
- [Creating and configuring a new Che 7 workspace](https://www.eclipse.org/che/docs/che-7/end-user-guide/creating-and-configuring-a-new-workspace/)
- [Making a workspace portable using a devfile](https://www.eclipse.org/che/docs/che-7/end-user-guide/making-a-workspace-portable-using-a-devfile/)
### Feedback and Community
We love to hear from users and developers. Here are the various ways to get in touch with us:
* **Support:** You can ask questions, report bugs, and request features using [GitHub issues](https://github.com/eclipse/che/issues).
* **Public Chat:** Join the public [eclipse-che](https://mattermost.eclipse.org/eclipse/channels/eclipse-che) Mattermost channel to discuss with community and contributors.
* **Twitter:** [@eclipse_che](https://twitter.com/eclipse_che)
* **Mailing List:** [che-dev@eclipse.org](https://accounts.eclipse.org/mailing-list/che-dev)
* **Weekly Meetings:** Join us in our [Che community meeting](https://github.com/eclipse/che/wiki/Che-Dev-Meetings) every second monday.
### Contributing
If you are interested in fixing issues and contributing directly to the code base:
- :bug: [Submitting bugs](https://github.com/eclipse/che/issues/new/choose)
- :page_facing_up: [Contributor license agreement](https://github.com/eclipse/che/wiki/Eclipse-Contributor-Agreement)
- :checkered_flag: [Development workflows](./CONTRIBUTING.md)
- :ok_hand: [Review source code changes](https://github.com/eclipse/che/pulls)
- :pencil: [Improve docs](https://github.com/eclipse/che-docs)
- :building_construction: [Che architecture](https://www.eclipse.org/che/docs/che-7/administration-guide/che-architecture-overview/)
- :octocat: [Che repositories](./CONTRIBUTING.md#other-che-repositories)
- :sparkles: [Good first issue for new contributors](https://github.com/eclipse/che/wiki/Labels#new-contributors)
#### Extending Eclipse Che
- [Add a new language support. (to be provided soon)](https://www.eclipse.org/che/docs/che-7/adding-support-for-a-new-language/)
- [Package your favorite VSCode extensions and make them available in Che.](https://www.eclipse.org/che/docs/che-7/end-user-guide/publishing-metadata-for-a-vs-code-extension/)
- [Write your own VSCode extension that runs on a dedicated side car container.](https://www.eclipse.org/che/docs/che-7/what-is-a-che-theia-plug-in/)
- [Build and package your custom Che-Theia editor with your extensions and plugins.](https://www.eclipse.org/che/docs/che-7/using-alternative-ides-in-che/)
### Roadmap
We maintain the [Che roadmap](https://github.com/eclipse/che/wiki/Roadmap) in the open way. We welcome anyone to ask question and contribute to the roadmap by joining our [community meetings](https://github.com/eclipse/che/wiki/Che-Dev-Meetings).
## CI
There are several [GitHub Actions](https://github.com/eclipse/che/actions) workflows implemented for this repository:
- [`nightly`](https://github.com/eclipse/che/actions/workflows/nightly-build.yml) - builds Maven artifacts, builds container images and pushes them to [quay.io](https://quay.io/organization/eclipse) on a daily basis from the [`master`](https://github.com/eclipse/che/tree/master) branch.
- [`release`](https://github.com/eclipse/che/actions/workflows/release.yml) - builds Maven artifacts and container images. Images are public and pushed to [quay.io](https://quay.io/organization/eclipse). See [RELEASE.md](https://github.com/eclipse/che/blob/master/RELEASE.md) for more information about this workflow.
### License
Che is open sourced under the Eclipse Public License 2.0.
TODO
### Che server

View File

@ -1,49 +0,0 @@
# How to use this functions
- Coppy and paste this block of code inside your script. This script utomatically download and import all necessary files
and all functions from the "common-qe" scripts may be invoked directly by function name without any additional actions.
```
#Download and import the "common-qe" functions
export IS_TESTS_FAILED="false"
DOWNLOADER_URL=https://raw.githubusercontent.com/eclipse/che/master/tests/.infra/centos-ci/common-qe/downloader.sh
curl $DOWNLOADER_URL -o downloader.sh
chmod u+x downloader.sh
. ./downloader.sh
```
- For correct displaying of the tests result add next block of code to the end of your script.
```
if [ "$IS_TESTS_FAILED" == "true" ]; then
exit 1;
fi
```
# How to configure this functions
- You can configure existing ```"common-qe-configuration.conf"``` which downloading automatically by "downloader.sh".
For configure it use next method:
```
setConfigProperty "<property>" "value"
```
Here an example:
```
setConfigProperty "test.suite" "test-all-devfiles"
```
- Or you can use your own configuration file. For this, export next variable , with path to file:
```
export PATH_TO_CONFIGURATION_FILE=<path_to_file>
```
Here an example
```
export PATH_TO_CONFIGURATION_FILE=/full/path/to/conf/file/qe-config.conf
#Download and import the "common-qe" functions
export IS_TESTS_FAILED="false"
DOWNLOADER_URL=https://raw.githubusercontent.com/eclipse/che/master/tests/.infra/centos-ci/common-qe/downloader.sh
curl $DOWNLOADER_URL -o downloader.sh
chmod u+x downloader.sh
. ./downloader.sh
```

View File

@ -1,37 +0,0 @@
#!/bin/bash
#
# Copyright (c) 2012-2020 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
#Declare CN
export CA_CN=eclipse-che-signer
export DOMAIN=*.$(minishift ip).nip.io
#Create Root Key
openssl genrsa -out rootCA.key 4096
#Create and self sign the Root Certificate
openssl req -x509 -new -nodes -key rootCA.key -subj /CN=${CA_CN} -sha256 -days 1024 -out rootCA.crt
#Create the certificate key
openssl genrsa -out domain.key 2048
#Create the signing (csr)
openssl req -new -sha256 -key domain.key -subj "/C=US/ST=CK/O=RedHat/CN=${DOMAIN}" -out domain.csr
#Verify Csr
openssl req -in domain.csr -noout -text
#Generate the certificate using the domain csr and key along with the CA Root key
openssl x509 -req -in domain.csr -CA rootCA.crt -CAkey rootCA.key -CAcreateserial -out domain.crt -days 500 -sha256
#Verify the certificate's content
openssl x509 -in domain.crt -text -noout

View File

@ -1,99 +0,0 @@
#!/bin/bash
#
# Copyright (c) 2012-2020 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
set -e
SCRIPT_PATH="${BASH_SOURCE[0]}"
SCRIPT_DIR="$(dirname $SCRIPT_PATH)"
. $SCRIPT_DIR/common-util.sh
function obtainUserToken() {
local username=$(readConfigProperty test.username)
local password=$(readConfigProperty test.password)
KEYCLOAK_URL=$(oc get checluster eclipse-che -o jsonpath='{.status.keycloakURL}')
KEYCLOAK_BASE_URL="${KEYCLOAK_URL}/auth"
local userAccessToken=$(curl -k -v -X POST $KEYCLOAK_BASE_URL/realms/che/protocol/openid-connect/token -H "Content-Type: application/x-www-form-urlencoded" -d "username=${username}" -d "password=${password}" -d "grant_type=password" -d "client_id=che-public" | jq -r .access_token)
echo "$userAccessToken"
}
function installChectl(){
bash <(curl -sL https://www.eclipse.org/che/chectl/) --channel=next
}
function createServerPatchFile(){
if [ -z "$1" ]
then
echo "Patch template has not been provided"
exit 1
fi
echo "$1" > /tmp/che-cr-patch.yaml
}
function startCheServer(){
createServerPatchFile "$1"
if chectl server:deploy --telemetry=off --listr-renderer=verbose -a operator -p openshift --k8spodreadytimeout=600000 --k8spodwaittimeout=600000 --k8spoddownloadimagetimeout=600000 --che-operator-cr-patch-yaml=/tmp/che-cr-patch.yaml --chenamespace=eclipse-che; then
echo "Started successfully"
oc get checluster -o yaml
else
echo "======== oc get events ========"
oc get events
echo "======== oc get all ========"
oc get all
getOpenshiftLogs
oc get checluster -o yaml || true
exit 133
fi
}
function createTestWorkspace(){
local devfile_url=$(readConfigProperty test.workspace.devfile.url)
local userAccessToken=$(obtainUserToken)
chectl workspace:create --start --access-token "$userAccessToken" --telemetry=off --chenamespace=eclipse-che --devfile="$devfile_url"
}
function runTest() {
local username=$(readConfigProperty test.username)
local password=$(readConfigProperty test.password)
local suite=$(readConfigProperty test.suite)
local multiuser=$(readConfigProperty test.multiuser)
local default_timeout=$(readConfigProperty timeout.default)
local workspace_status_polling=$(readConfigProperty timeout.workspace.status.polling)
local load_page_timeout=$(readConfigProperty timeout.load.page)
local additional_options=$(readConfigProperty test.additional.options)
local che_url=$(oc get checluster eclipse-che -o jsonpath='{.status.cheURL}')
# ### Create directory for report
cd /root/payload
mkdir report
REPORT_FOLDER=$(pwd)/report
### Run tests
docker run --shm-size=1g --net=host --ipc=host -v $REPORT_FOLDER:/tmp/e2e/report:Z \
-e TS_SELENIUM_BASE_URL="$che_url" \
-e TS_SELENIUM_LOG_LEVEL=DEBUG \
-e TS_SELENIUM_MULTIUSER="$multiuser" \
-e TS_SELENIUM_USERNAME="$username" \
-e TS_SELENIUM_PASSWORD="$password" \
-e TS_SELENIUM_DEFAULT_TIMEOUT="$default_timeout" \
-e TS_SELENIUM_WORKSPACE_STATUS_POLLING="$workspace_status_polling" \
-e TS_SELENIUM_LOAD_PAGE_TIMEOUT="$load_page_timeout" \
-e TEST_SUITE="$suite" \
-e NODE_TLS_REJECT_UNAUTHORIZED=0 \
$additional_options quay.io/eclipse/che-e2e:nightly || IS_TESTS_FAILED=true
export IS_TESTS_FAILED
}

View File

@ -1,17 +0,0 @@
# Environment
env.root.dir.path=
env.setup.environment.script.path=
env.setup.environment.method.name=
# Run test
test.username=admin
test.password=admin
test.suite=test-happy-path
test.multiuser=true
test.workspace.devfile.url=https://raw.githubusercontent.com/eclipse/che/master/tests/e2e/files/happy-path/happy-path-workspace.yaml
test.additional.options=
# Timeouts
timeout.default=20000
timeout.workspace.status.polling=20000
timeout.load.page=420000

View File

@ -1,79 +0,0 @@
#!/bin/bash
#
# Copyright (c) 2012-2020 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
set -e
SCRIPT_PATH="${BASH_SOURCE[0]}"
SCRIPT_DIR="$(dirname $SCRIPT_PATH)"
PATH_TO_CONFIGURATION_FILE=${PATH_TO_CONFIGURATION_FILE:="$SCRIPT_DIR/common-qe-configuration.conf"}
function printError(){
>&2 echo ""
>&2 echo "▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼ !!! ERROR !!! ▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼"
>&2 echo ""
>&2 echo "$1"
>&2 echo ""
>&2 echo "▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲"
>&2 echo ""
}
function readConfigProperty(){
if [ -z "$1" ]
then
printError "The 'readConfigProperty' function can't read property with the 'null' value."
exit 1
fi
local propertyRow=$(cat $PATH_TO_CONFIGURATION_FILE | grep $1)
if [ -z "$propertyRow" ]
then
printError "Can't read the '$1' property. Please revise config and correct the property name."
exit 1
fi
local propertyValue=$(echo "$propertyRow" | sed s@$1=@''@)
echo "$propertyValue"
}
function setConfigProperty(){
# Check of the property existing
readConfigProperty $1 > /dev/null
# Set property value
sed -i s@$1=.*@$1=$2@ $PATH_TO_CONFIGURATION_FILE
echo "Property value has been changed '$1=$2'"
}
function getOpenshiftLogs() {
echo "====== Che server logs ======"
oc logs $(oc get pods --selector=component=che -o jsonpath="{.items[].metadata.name}") || true
echo "====== Keycloak logs ======"
oc logs $(oc get pods --selector=component=keycloak -o jsonpath="{.items[].metadata.name}") || true
echo "====== Che operator logs ======"
oc logs $(oc get pods --selector=app=che-operator -o jsonpath="{.items[].metadata.name}") || true
}
function archiveArtifacts() {
JOB_NAME=$1
DATE=$(date +"%m-%d-%Y-%H-%M")
echo "Archiving artifacts from ${DATE} for ${JOB_NAME}/${BUILD_NUMBER}"
cd /root/payload
ls -la ./artifacts.key
chmod 600 ./artifacts.key
chown $(whoami) ./artifacts.key
mkdir -p ./che/${JOB_NAME}/${BUILD_NUMBER}
cp -R ./report ./che/${JOB_NAME}/${BUILD_NUMBER}/ || true
rsync --password-file=./artifacts.key -Hva --partial --relative ./che/${JOB_NAME}/${BUILD_NUMBER} devtools@artifacts.ci.centos.org::devtools/
}

View File

@ -1,54 +0,0 @@
#!/bin/bash
#
# Copyright (c) 2012-2020 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
COMMON_FOLDER_URL="https://raw.githubusercontent.com/eclipse/che/master/tests/.infra/centos-ci/common-qe"
COMMON_FOLDER_NAME="common-qe"
CERT_GENERATION_SCRIPT_NAME="che-cert-generation.sh"
CHE_UTIL_SCRIPT_NAME="che-util.sh"
COMMON_UTIL_SCRIPT_NAME="common-util.sh"
INSTALLATION_UTIL_SCRIPT_NAME="installation-util.sh"
CONFIG_FILE_NAME="common-qe-configuration.conf"
SCRIPT_PATH="${BASH_SOURCE[0]}"
SCRIPT_DIR="$(dirname $SCRIPT_PATH)"
ROOT_DIR_PATH="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
function downloadAndSetPermissions(){
local filename="$1"
local fileUrl="$COMMON_FOLDER_URL/$filename"
curl "$fileUrl" -o "$COMMON_FOLDER_NAME/$filename"
chmod u+x "$COMMON_FOLDER_NAME/$filename"
}
set -e
# clear destination folder
rm -rf "$COMMON_FOLDER_NAME"
mkdir "$COMMON_FOLDER_NAME"
# download scripts
downloadAndSetPermissions $CERT_GENERATION_SCRIPT_NAME
downloadAndSetPermissions $CHE_UTIL_SCRIPT_NAME
downloadAndSetPermissions $COMMON_UTIL_SCRIPT_NAME
downloadAndSetPermissions $INSTALLATION_UTIL_SCRIPT_NAME
downloadAndSetPermissions $CONFIG_FILE_NAME
# import common methods
. "$COMMON_FOLDER_NAME/$CERT_GENERATION_SCRIPT_NAME"
. "$COMMON_FOLDER_NAME/$CHE_UTIL_SCRIPT_NAME"
. "$COMMON_FOLDER_NAME/$COMMON_UTIL_SCRIPT_NAME"
. "$COMMON_FOLDER_NAME/$INSTALLATION_UTIL_SCRIPT_NAME"
setConfigProperty "env.root.dir.path" "$ROOT_DIR_PATH"

View File

@ -1,173 +0,0 @@
#!/bin/bash
#
# Copyright (c) 2012-2020 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
set -e
SCRIPT_PATH="${BASH_SOURCE[0]}"
SCRIPT_DIR="$(dirname $SCRIPT_PATH)"
. $SCRIPT_DIR/common-util.sh
function setupTestEnvironment(){
SCRIPT_PATH=$(readConfigProperty env.setup.environment.script.path)
if [[ ! -z "$SCRIPT_PATH" ]]
then
ROOT_DIR_PATH=$(readConfigProperty env.root.dir.path)
SETUP_ENV_SCRIPT_PATH=$ROOT_DIR_PATH/$SCRIPT_PATH
SETUP_ENV_METHOD_NAME=$(readConfigProperty env.setup.environment.method.name)
. $SETUP_ENV_SCRIPT_PATH
eval $SETUP_ENV_METHOD_NAME
else
echo "The 'env.setup.environment.script.path' property is not set, the 'setupTestEnvironment' method is ignored"
fi
}
function load_jenkins_vars() {
if [ -e "jenkins-env.json" ]; then
eval "$(./env-toolkit load -f jenkins-env.json \
DEVSHIFT_TAG_LEN \
QUAY_USERNAME \
QUAY_PASSWORD \
QUAY_ECLIPSE_CHE_USERNAME \
QUAY_ECLIPSE_CHE_PASSWORD \
JENKINS_URL \
GIT_BRANCH \
GIT_COMMIT \
BUILD_NUMBER \
ghprbSourceBranch \
ghprbActualCommit \
BUILD_URL \
ghprbPullId)"
fi
}
function install_tools() {
# We need to disable selinux for now, XXX
/usr/sbin/setenforce 0 || true
# Get all the deps in
yum install -d1 -y yum-utils device-mapper-persistent-data lvm2
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
yum install -d1 -y docker-ce \
git
service docker start
echo 'CICO: Dependencies installed'
}
function installOC() {
OC_DIR_NAME=openshift-origin-client-tools-v3.11.0-0cbc58b-linux-64bit
curl -vL "https://github.com/openshift/origin/releases/download/v3.11.0/${OC_DIR_NAME}.tar.gz" --output ${OC_DIR_NAME}.tar.gz
tar -xvf ${OC_DIR_NAME}.tar.gz
cp ${OC_DIR_NAME}/oc /usr/local/bin
cp ${OC_DIR_NAME}/oc /tmp
}
function installKVM() {
echo "======== Start to install KVM virtual machine ========"
yum install -y qemu-kvm libvirt libvirt-python libguestfs-tools virt-install
curl -L https://github.com/dhiltgen/docker-machine-kvm/releases/download/v0.10.0/docker-machine-driver-kvm-centos7 -o /usr/local/bin/docker-machine-driver-kvm
chmod +x /usr/local/bin/docker-machine-driver-kvm
systemctl enable libvirtd
systemctl start libvirtd
virsh net-list --all
echo "======== KVM has been installed successfully ========"
}
function installEpelRelease() {
if yum repolist | grep epel; then
echo "Epel already installed, skipping instalation."
else
#excluding mirror1.ci.centos.org
echo "exclude=mirror1.ci.centos.org" >>/etc/yum/pluginconf.d/fastestmirror.conf
echo "Installing epel..."
yum install -d1 --assumeyes epel-release
yum update --assumeyes -d1
fi
}
function installJQ() {
installEpelRelease
yum install --assumeyes -d1 jq
}
function installAndStartMinishift() {
echo "======== Start to install minishift ========"
curl -Lo minishift.tgz https://github.com/minishift/minishift/releases/download/v1.34.2/minishift-1.34.2-linux-amd64.tgz
tar -xvf minishift.tgz --strip-components=1
chmod +x ./minishift
mv ./minishift /usr/local/bin/minishift
#Setup GitHub token for minishift
if [ -z "$CHE_BOT_GITHUB_TOKEN" ]
then
echo "\$CHE_BOT_GITHUB_TOKEN is empty. Minishift start might fail with GitGub API rate limit reached."
else
echo "\$CHE_BOT_GITHUB_TOKEN is set, checking limits."
GITHUB_RATE_REMAINING=$(curl -slL "https://api.github.com/rate_limit?access_token=$CHE_BOT_GITHUB_TOKEN" | jq .rate.remaining)
if [ "$GITHUB_RATE_REMAINING" -gt 1000 ]
then
echo "Github rate greater than 1000. Using che-bot token for minishift startup."
export MINISHIFT_GITHUB_API_TOKEN=$CHE_BOT_GITHUB_TOKEN
else
echo "Github rate is lower than 1000. *Not* using che-bot for minishift startup."
echo "If minishift startup fails, please try again later."
fi
fi
minishift version
minishift config set memory 14GB
minishift config set cpus 4
echo "======== Launch minishift ========"
minishift start
oc login -u system:admin
oc adm policy add-cluster-role-to-user cluster-admin developer
oc login -u developer -p developer
. "${SCRIPT_DIR}"/che-cert-generation.sh
oc project default
oc delete secret router-certs
cat domain.crt domain.key > minishift.crt
oc create secret tls router-certs --key=domain.key --cert=minishift.crt
oc rollout status dc router
oc rollout latest router
oc rollout status dc router
oc create namespace eclipse-che
cp rootCA.crt ca.crt
oc create secret generic self-signed-certificate --from-file=ca.crt --namespace=eclipse-che
oc project eclipse-che
}
function setup_environment(){
load_jenkins_vars
install_tools
setupTestEnvironment
installOC
installKVM
installAndStartMinishift
installJQ
}

View File

@ -1,462 +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
buildAndDeployArtifacts() {
mvn clean install -U -Pintegration
if [[ $? -eq 0 ]]; then
echo 'Build Success!'
echo 'Going to deploy artifacts'
else
die_with 'Build Failed!'
fi
}
testImages() {
echo "Going to build and push docker images"
set -e
set -o pipefail
TAG=$1
if [[ ${TAG} != "nightly" ]]; then #if given tag 'nightly' means that don't need to checkout and going to build master
git checkout ${TAG}
fi
REGISTRY="quay.io"
ORGANIZATION="eclipse"
if [[ -n "${QUAY_ECLIPSE_CHE_USERNAME}" ]] && [[ -n "${QUAY_ECLIPSE_CHE_PASSWORD}" ]]; then
docker login -u "${QUAY_ECLIPSE_CHE_USERNAME}" -p "${QUAY_ECLIPSE_CHE_PASSWORD}" "${REGISTRY}"
else
echo "Could not login, missing credentials for pushing to the '${ORGANIZATION}' organization"
return
fi
# stop / rm all containers
if [[ $(docker ps -aq) != "" ]]; then
docker rm -f $(docker ps -aq)
fi
# KEEP RIGHT ORDER!!!
DOCKER_FILES_LOCATIONS=(
dockerfiles/endpoint-watcher
dockerfiles/keycloak
dockerfiles/postgres
dockerfiles/dev
dockerfiles/che
dockerfiles/e2e
)
IMAGES_LIST=(
eclipse/che-endpoint-watcher
eclipse/che-keycloak
eclipse/che-postgres
eclipse/che-dev
eclipse/che-server
eclipse/che-e2e
)
# BUILD IMAGES
for image_dir in ${DOCKER_FILES_LOCATIONS[@]}; do
bash $(pwd)/${image_dir}/build.sh --tag:${TAG}
if [[ ${image_dir} == "dockerfiles/che" ]]; then
#CENTOS SINGLE USER
BUILD_ASSEMBLY_DIR=$(echo assembly/assembly-main/target/eclipse-che-*/eclipse-che-*/)
LOCAL_ASSEMBLY_DIR="${image_dir}/eclipse-che"
if [[ -d "${LOCAL_ASSEMBLY_DIR}" ]]; then
rm -r "${LOCAL_ASSEMBLY_DIR}"
fi
cp -r "${BUILD_ASSEMBLY_DIR}" "${LOCAL_ASSEMBLY_DIR}"
docker build -t ${ORGANIZATION}/che-server:${TAG}-centos -f $(pwd)/${image_dir}/Dockerfile.centos $(pwd)/${image_dir}/
fi
if [[ $? -ne 0 ]]; then
echo "ERROR:"
echo "build of '${image_dir}' image is failed!"
exit 1
fi
done
echo '=========================== LIST OF IMAGES ==========================='
docker images -a
echo '=========================== LIST OF IMAGES ==========================='
}
function installOC() {
OC_DIR_NAME=openshift-origin-client-tools-v3.11.0-0cbc58b-linux-64bit
curl -vL "https://github.com/openshift/origin/releases/download/v3.11.0/${OC_DIR_NAME}.tar.gz" --output ${OC_DIR_NAME}.tar.gz
tar -xvf ${OC_DIR_NAME}.tar.gz
cp ${OC_DIR_NAME}/oc /usr/local/bin
cp ${OC_DIR_NAME}/oc /tmp
}
function installJQ() {
installEpelRelease
yum install --assumeyes -d1 jq
}
function installEpelRelease() {
if yum repolist | grep epel; then
echo "Epel already installed, skipping instalation."
else
#excluding mirror1.ci.centos.org
echo "exclude=mirror1.ci.centos.org" >>/etc/yum/pluginconf.d/fastestmirror.conf
echo "Installing epel..."
yum install -d1 --assumeyes epel-release
yum update --assumeyes -d1
fi
}
function installYQ() {
installEpelRelease
yum install --assumeyes -d1 python3-pip
pip3 install --upgrade setuptools
pip3 install yq
}
function installStartDocker() {
yum install --assumeyes -d1 yum-utils device-mapper-persistent-data lvm2
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
yum install --assumeyes -d1 docker-ce
mkdir -p /etc/docker
echo "{ \"insecure-registries\": [\"172.30.0.0/16\"] }" >/etc/docker/daemon.json
systemctl start docker
docker version
}
function installMvn() {
mkdir -p /opt/apache-maven && curl -sSL https://downloads.apache.org/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.tar.gz | tar -xz --strip=1 -C /opt/apache-maven
export JAVA_HOME=/usr/lib/jvm/java-11-openjdk
export PATH="/usr/lib/jvm/java-11-openjdk:/opt/apache-maven/bin:/usr/bin:${PATH:-/bin:/usr/bin}"
export JAVACONFDIRS="/etc/java${JAVACONFDIRS:+:}${JAVACONFDIRS:-}"
export M2_HOME="/opt/apache-maven"
}
function installNodejs() {
curl -sL https://rpm.nodesource.com/setup_10.x | bash -
yum install -y nodejs
}
function insalllYarn() {
yum-config-manager --add-repo https://dl.yarnpkg.com/rpm/yarn.repo
yum install -y yarn
}
function installGit() {
yum install --assumeyes -d1 git
}
function installWget() {
yum -y install wget
}
function installGssCompiler() {
yum install -y gcc-c++ make
}
function installDependencies() {
echo "======== Installing dependencies: ========"
start=$(date +%s)
installEpelRelease
installYQ
installStartDocker
installJQ
installOC
installGit
installWget
# Getting dependencies ready
yum install --assumeyes -d1 \
patch \
pcp \
bzip2 \
golang \
make \
java-11-openjdk-devel
installMvn
installNodejs
insalllYarn
stop=$(date +%s)
instal_dep_duration=$(($stop - $start))
echo "======== Installing all dependencies lasted $instal_dep_duration seconds. ========"
}
function checkAllCreds() {
echo "======== Checking credentials: ========"
CREDS_NOT_SET="false"
echo ${#QUAY_ECLIPSE_CHE_USERNAME}
echo ${#QUAY_ECLIPSE_CHE_PASSWORD}
if [[ -z "${QUAY_ECLIPSE_CHE_USERNAME}" || -z "${QUAY_ECLIPSE_CHE_PASSWORD}" ]]; then
echo "Docker registry credentials not set"
CREDS_NOT_SET="true"
fi
if [[ "${CREDS_NOT_SET}" = "true" ]]; then
echo "Failed to parse jenkins secure store credentials"
exit 2
else
echo "Credentials set successfully."
fi
}
function installKVM() {
echo "======== Start to install KVM virtual machine ========"
yum install -y qemu-kvm libvirt libvirt-python libguestfs-tools virt-install
curl -L https://github.com/dhiltgen/docker-machine-kvm/releases/download/v0.10.0/docker-machine-driver-kvm-centos7 -o /usr/local/bin/docker-machine-driver-kvm
chmod +x /usr/local/bin/docker-machine-driver-kvm
systemctl enable libvirtd
systemctl start libvirtd
virsh net-list --all
echo "======== KVM has been installed successfully ========"
}
function installAndStartMinishift() {
echo "======== Start to install minishift ========"
curl -Lo minishift.tgz https://github.com/minishift/minishift/releases/download/v1.34.2/minishift-1.34.2-linux-amd64.tgz
tar -xvf minishift.tgz --strip-components=1
chmod +x ./minishift
mv ./minishift /usr/local/bin/minishift
#Setup GitHub token for minishift
if [ -z "$CHE_BOT_GITHUB_TOKEN" ]
then
echo "\$CHE_BOT_GITHUB_TOKEN is empty. Minishift start might fail with GitGub API rate limit reached."
else
echo "\$CHE_BOT_GITHUB_TOKEN is set, checking limits."
GITHUB_RATE_REMAINING=$(curl -slL "https://api.github.com/rate_limit?access_token=$CHE_BOT_GITHUB_TOKEN" | jq .rate.remaining)
if [ "$GITHUB_RATE_REMAINING" -gt 1000 ]
then
echo "Github rate greater than 1000. Using che-bot token for minishift startup."
export MINISHIFT_GITHUB_API_TOKEN=$CHE_BOT_GITHUB_TOKEN
else
echo "Github rate is lower than 1000. *Not* using che-bot for minishift startup."
echo "If minishift startup fails, please try again later."
fi
fi
minishift version
minishift config set memory 14GB
minishift config set cpus 4
echo "======== Lunch minishift ========"
minishift start
loginToOpenshiftAndSetDevRole
setupSelfSignedCertificate
}
function installCheCtl() {
channel=${1:-next}
echo "======== Start to install chectl from channel $channel ========"
bash <(curl -sL https://www.eclipse.org/che/chectl/) --channel=$channel
echo "======== chectl has been installed successfully ========"
}
function getOpenshiftLogs() {
oc logs $(oc get pods --selector=component=che -o jsonpath="{.items[].metadata.name}") || true
oc logs $(oc get pods --selector=component=keycloak -o jsonpath="{.items[].metadata.name}") || true
}
function deployCheIntoCluster() {
echo "======== Start to install CHE ========"
if chectl server:deploy --telemetry=off --listr-renderer=verbose -a operator -p minishift --k8spodreadytimeout=600000 --k8spodwaittimeout=600000 --k8spoddownloadimagetimeout=600000 $1 --chenamespace=eclipse-che; then
echo "Started successfully"
oc get checluster -o yaml
else
echo "======== oc get events ========"
oc get events
echo "======== oc get all ========"
oc get all
# echo "==== docker ps ===="
# docker ps
# echo "==== docker ps -q | xargs -L 1 docker logs ===="
# docker ps -q | xargs -L 1 docker logs | true
getOpenshiftLogs
curl -kvL https://keycloak-che.$(minishift ip).nip.io/auth/realms/che/.well-known/openid-configuration || true
oc get checluster -o yaml || true
exit 1337
fi
}
function loginToOpenshiftAndSetDevRole() {
oc login -u system:admin
oc adm policy add-cluster-role-to-user cluster-admin developer
oc login -u developer -p pass
}
function archiveArtifacts() {
JOB_NAME=$1
DATE=$(date +"%m-%d-%Y-%H-%M")
echo "Archiving artifacts from ${DATE} for ${JOB_NAME}/${BUILD_NUMBER}"
cd /root/payload
ls -la ./artifacts.key
chmod 600 ./artifacts.key
chown $(whoami) ./artifacts.key
mkdir -p ./che/${JOB_NAME}/${BUILD_NUMBER}
cp -R ./report ./che/${JOB_NAME}/${BUILD_NUMBER}/ | true
rsync --password-file=./artifacts.key -Hva --partial --relative ./che/${JOB_NAME}/${BUILD_NUMBER} devtools@artifacts.ci.centos.org::devtools/
}
function defineCheRoute(){
CHE_ROUTE=$(oc get route che --template='{{ .spec.host }}')
echo "====== Check CHE ROUTE ======"
curl -kvL $CHE_ROUTE
}
createTestWorkspaceAndRunTest() {
defineCheRoute
### Create workspace
DEV_FILE_URL=$1
echo "====== Create test workspace ======"
if [[ ${DEV_FILE_URL} = "" ]]; then # by default it is used 'happy-path-devfile' yaml from CHE 'master' branch
chectl workspace:create --start --access-token "$USER_ACCESS_TOKEN" --telemetry=off --chenamespace=eclipse-che --devfile=https://raw.githubusercontent.com/eclipse/che/master/tests/e2e/files/happy-path/happy-path-workspace.yaml
else
chectl workspace:create --start --access-token "$USER_ACCESS_TOKEN" --telemetry=off --chenamespace=eclipse-che $1 # it can be directly indicated other URL to 'devfile' yaml
fi
### Create directory for report
cd /root/payload
mkdir report
REPORT_FOLDER=$(pwd)/report
### Run tests
docker run --shm-size=1g --net=host --ipc=host -v $REPORT_FOLDER:/tmp/e2e/report:Z \
-e TS_SELENIUM_BASE_URL="https://$CHE_ROUTE" \
-e TS_SELENIUM_MULTIUSER=true \
-e TS_SELENIUM_USERNAME="admin" \
-e TS_SELENIUM_PASSWORD="admin" \
-e TS_SELENIUM_LOG_LEVEL=TRACE \
-e TS_SELENIUM_START_WORKSPACE_TIMEOUT=720000 \
-e NODE_TLS_REJECT_UNAUTHORIZED=0 \
quay.io/eclipse/che-e2e:nightly || IS_TESTS_FAILED=true
}
function createTestUserAndObtainUserToken() {
### Create user and obtain token
KEYCLOAK_URL=$(oc get route/keycloak -o jsonpath='{.spec.host}')
KEYCLOAK_BASE_URL="https://${KEYCLOAK_URL}/auth"
ADMIN_USERNAME=admin
ADMIN_PASS=admin
TEST_USERNAME=admin
echo "======== Getting admin token ========"
ADMIN_ACCESS_TOKEN=$(curl -kX POST $KEYCLOAK_BASE_URL/realms/master/protocol/openid-connect/token -H "Content-Type: application/x-www-form-urlencoded" -d "username=admin" -d "password=admin" -d "grant_type=password" -d "client_id=admin-cli" | jq -r .access_token)
echo $ADMIN_ACCESS_TOKEN
echo "========Creating user========"
USER_JSON="{\"username\": \"${TEST_USERNAME}\",\"enabled\": true,\"emailVerified\": true,\"email\":\"test1@user.aa\"}"
echo $USER_JSON
curl -kX POST $KEYCLOAK_BASE_URL/admin/realms/che/users -H "Authorization: Bearer ${ADMIN_ACCESS_TOKEN}" -H "Content-Type: application/json" -d "${USER_JSON}" -v
USER_ID=$(curl -kX GET $KEYCLOAK_BASE_URL/admin/realms/che/users?username=${TEST_USERNAME} -H "Authorization: Bearer ${ADMIN_ACCESS_TOKEN}" | jq -r .[0].id)
echo "========User id: $USER_ID========"
echo "========Updating password========"
CREDENTIALS_JSON={\"type\":\"password\",\"value\":\"${TEST_USERNAME}\",\"temporary\":false}
echo $CREDENTIALS_JSON
curl -kX PUT $KEYCLOAK_BASE_URL/admin/realms/che/users/${USER_ID}/reset-password -H "Authorization: Bearer ${ADMIN_ACCESS_TOKEN}" -H "Content-Type: application/json" -d "${CREDENTIALS_JSON}" -v
export USER_ACCESS_TOKEN=$(curl -kX POST $KEYCLOAK_BASE_URL/realms/che/protocol/openid-connect/token -H "Content-Type: application/x-www-form-urlencoded" -d "username=${TEST_USERNAME}" -d "password=${TEST_USERNAME}" -d "grant_type=password" -d "client_id=che-public" | jq -r .access_token)
echo "========User Access Token: $USER_ACCESS_TOKEN "
}
function setupEnvs() {
eval "$(./env-toolkit load -f jenkins-env.json -r \
CHE_BOT_GITHUB_TOKEN \
CHE_MAVEN_SETTINGS \
CHE_GITHUB_SSH_KEY \
^BUILD_NUMBER$ \
CHE_OSS_SONATYPE_GPG_KEY \
CHE_OSS_SONATYPE_PASSPHRASE \
QUAY_ECLIPSE_CHE_USERNAME \
QUAY_ECLIPSE_CHE_PASSWORD)"
}
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 runDevfileTestSuite() {
defineCheRoute
### Create directory for report
cd /root/payload
mkdir report
REPORT_FOLDER=$(pwd)/report
### Run tests
docker run --shm-size=1g --net=host --ipc=host -v $REPORT_FOLDER:/tmp/e2e/report:Z \
-e TS_SELENIUM_BASE_URL="https://$CHE_ROUTE" \
-e TS_SELENIUM_LOG_LEVEL=DEBUG \
-e TS_SELENIUM_MULTIUSER=true \
-e TS_SELENIUM_USERNAME="admin" \
-e TS_SELENIUM_PASSWORD="admin" \
-e TEST_SUITE=test-all-devfiles \
-e TS_SELENIUM_DEFAULT_TIMEOUT=300000 \
-e TS_SELENIUM_LOAD_PAGE_TIMEOUT=240000 \
-e TS_SELENIUM_WORKSPACE_STATUS_POLLING=20000 \
-e NODE_TLS_REJECT_UNAUTHORIZED=0 \
quay.io/eclipse/che-e2e:nightly || IS_TESTS_FAILED=true
}
function setupSelfSignedCertificate() {
# Docs: https://www.eclipse.org/che/docs/che-7/installing-che-in-tls-mode-with-self-signed-certificates/#deploying-che-with-self-signed-tls-on-openshift3-using-operator_installing-che-in-tls-mode-with-self-signed-certificates
# 1. Generate self-signed certificate
## Declare CN
export CA_CN=eclipse-che-signer
export DOMAIN=*.$(minishift ip).nip.io
## Create Root Key
openssl genrsa -out rootCA.key 4096
## Create and self sign the Root Certificate
openssl req -x509 -new -nodes -key rootCA.key -subj /CN=${CA_CN} -sha256 -days 1024 -out rootCA.crt
## Create the certificate key
openssl genrsa -out domain.key 2048
## Create the signing (csr)
openssl req -new -sha256 -key domain.key -subj "/C=US/ST=CK/O=RedHat/CN=${DOMAIN}" -out domain.csr
## Verify Csr
openssl req -in domain.csr -noout -text
## Generate the certificate using the domain csr and key along with the CA Root key
openssl x509 -req -in domain.csr -CA rootCA.crt -CAkey rootCA.key -CAcreateserial -out domain.crt -days 500 -sha256
## Verify the certificate's content
openssl x509 -in domain.crt -text -noout
# 2. Configure che namespace to use self-signed certificate
## Re-configure the router with the generated certificate
oc project default
oc delete secret router-certs
cat domain.crt domain.key > minishift.crt
oc create secret tls router-certs --key=domain.key --cert=minishift.crt
oc rollout status dc router
oc rollout latest router
oc rollout status dc router
## Pre-create a namespace for Che
oc create namespace eclipse-che
## Create a secret from the CA certificate
cp rootCA.crt ca.crt
oc create secret generic self-signed-certificate --from-file=ca.crt --namespace=eclipse-che
oc project eclipse-che
}

View File

@ -1,35 +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)========"
source tests/.infra/centos-ci/functional_tests_utils.sh
function prepareCustomResourcePatchFile() {
cat > /tmp/custom-resource-patch.yaml <<EOL
spec:
auth:
updateAdminPassword: false
openShiftoAuth: false
EOL
cat /tmp/custom-resource-patch.yaml
}
setupEnvs
installKVM
installDependencies
prepareCustomResourcePatchFile
installCheCtl
installAndStartMinishift
deployCheIntoCluster --che-operator-cr-patch-yaml=/tmp/custom-resource-patch.yaml
runDevfileTestSuite
echo "=========================== THIS IS POST TEST ACTIONS =============================="
getOpenshiftLogs
archiveArtifacts "che-devfile-test"
if [[ "$IS_TESTS_FAILED" == "true" ]]; then exit 1; fi

View File

@ -1,69 +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)========"
source tests/.infra/centos-ci/functional_tests_utils.sh
function runOpenshiftConnectorTest(){
### Create directory for report
cd /root/payload
mkdir report
REPORT_FOLDER=$(pwd)/report
### Run tests
docker run --net=host --ipc=host -v $REPORT_FOLDER:/tmp/e2e/report:Z --shm-size=1g \
-e TS_SELENIUM_LOAD_PAGE_TIMEOUT=420000 \
-e TS_SELENIUM_WORKSPACE_STATUS_POLLING=20000 \
-e TS_SELENIUM_BASE_URL="https://$CHE_ROUTE" \
-e TS_SELENIUM_USERNAME=${TEST_USERNAME} \
-e TS_SELENIUM_PASSWORD=${TEST_USERNAME} \
-e TS_TEST_OPENSHIFT_PLUGIN_USERNAME=developer \
-e TS_TEST_OPENSHIFT_PLUGIN_PASSWORD=pass \
-e TS_TEST_OPENSHIFT_PLUGIN_PROJECT=eclipse-che \
-e TS_TEST_OPENSHIFT_PLUGIN_COMPONENT_TYPE="nodejs (s2i)" \
-e TS_TEST_OPENSHIFT_PLUGIN_COMPONENT_VERSION=latest \
-e TS_SELENIUM_MULTIUSER=true \
-e NODE_TLS_REJECT_UNAUTHORIZED=0 \
-e DELETE_WORKSPACE_ON_FAILED_TEST=true \
-e TS_SELENIUM_LOG_LEVEL=TRACE \
-e TS_SELENIUM_START_WORKSPACE_TIMEOUT=720000 \
-e TEST_SUITE=test-openshift-connector \
quay.io/eclipse/che-e2e:nightly || IS_TESTS_FAILED=true
}
function prepareCustomResourcePatchFile() {
cat > /tmp/custom-resource-patch.yaml <<EOL
spec:
server:
customCheProperties:
CHE_INFRA_KUBERNETES_WORKSPACE_START_TIMEOUT_MIN: '12'
auth:
updateAdminPassword: false
openShiftoAuth: false
EOL
cat /tmp/custom-resource-patch.yaml
}
setupEnvs
installKVM
installDependencies
prepareCustomResourcePatchFile
installCheCtl
installAndStartMinishift
deployCheIntoCluster --che-operator-cr-patch-yaml=/tmp/custom-resource-patch.yaml
defineCheRoute
createTestUserAndObtainUserToken
runOpenshiftConnectorTest
echo "=========================== THIS IS POST TEST ACTIONS =============================="
getOpenshiftLogs
archiveArtifacts "che-nightly-openshift-connector"
if [[ "$IS_TESTS_FAILED" == "true" ]]; then exit 1; fi

View File

@ -1,39 +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)========"
source tests/.infra/centos-ci/functional_tests_utils.sh
function prepareCustomResourcePatchFile() {
cat > /tmp/custom-resource-patch.yaml <<EOL
spec:
server:
customCheProperties:
CHE_INFRA_KUBERNETES_WORKSPACE_START_TIMEOUT_MIN: '12'
auth:
updateAdminPassword: false
openShiftoAuth: false
EOL
cat /tmp/custom-resource-patch.yaml
}
setupEnvs
installKVM
installDependencies
prepareCustomResourcePatchFile
installCheCtl
installAndStartMinishift
deployCheIntoCluster --che-operator-cr-patch-yaml=/tmp/custom-resource-patch.yaml
createTestUserAndObtainUserToken
createTestWorkspaceAndRunTest
echo "=========================== THIS IS POST TEST ACTIONS =============================="
getOpenshiftLogs
archiveArtifacts "che-nightly-happy-path"
if [[ "$IS_TESTS_FAILED" == "true" ]]; then exit 1; fi

View File

@ -1,55 +0,0 @@
# Module for launch E2E tests related to Che 7
## Requirements
- node 8.x
- "Chrome" browser 69.x or later
- deployed Che 7 with accessible URL
## Before launch
**Perform commands:**
- ```export TS_SELENIUM_BASE_URL=<Che7 URL>```
- ```npm install```
## Default launch
- ```npm test```
## Custom launch
- Use environment variables which described in the **```'TestConstants.ts'```** file
- Use environment variables for setting timeouts if needed. You can see the list in **```'TimeoutConstants.ts'```**. You can see the list of those variables and their value if you set the ```'TS_SELENIUM_PRINT_TIMEOUT_VARIABLES = true'```
## Docker launch
- open terminal and go to the "e2e" directory
- export the ```"TS_SELENIUM_BASE_URL"``` variable with "Che" url
- run command ```"npm run test-docker"```
## Docker launch with changed tests
**For launching tests with local changes perform next steps:**
- open terminal and go to the "e2e" directory
- export the ```"TS_SELENIUM_BASE_URL"``` variable with "Che" url
- run command ```"npm run test-docker-mount-e2e"```
## Debug docker launch
The ```'eclipse/che-e2e'``` docker image has VNC server instaled inside. For connecting use ```'0.0.0.0:5920'``` adress.
## The "Happy Path" scenario launching
**The easiest way to do that is to perform steps which are described in the "Docker launch" paragraph.
For running tests without docker, please perform next steps:**
- Deploy Che on Kubernetes infrastructure by using 'Minikube' and 'Chectl' <https://github.com/eclipse/che/blob/master/deploy/kubernetes/README.md>
- Create workspace by using 'Chectl' and devfile
- link to 'Chectl' manual <https://github.com/che-incubator/chectl#chectl-workspacestart>
- link to devfile ( **```For successfull test passing, exactly provided devfile should be used```** )
<https://gist.githubusercontent.com/Ohrimenko1988/93f5426f4ebc1705c55feb8ff0396a49/raw/cbea89ad145ba33ed34a151a12c50f045f9f3b78/yaml-ls-bug.yaml>
- Provide the **```'TS_SELENIUM_BASE_URL'```** environment variable as described above
- perform command **```'npm run test-happy-path'```**

View File

@ -1,238 +0,0 @@
/*********************************************************************
* Copyright (c) 2019 Red Hat, Inc.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/
function getBaseUrl(): string {
const baseUrl: string | undefined = process.env.TS_SELENIUM_BASE_URL;
if (!baseUrl) {
return 'http://sample-url';
}
return baseUrl.replace(/\/$/, '');
}
export const TestConstants = {
/**
* Base URL of the application which should be checked
*/
TS_SELENIUM_BASE_URL: getBaseUrl(),
/**
* Base URl of web console OpenShift which uses to test OperatorHub.
*/
TS_SELENIUM_WEB_CONSOLE_OCP_URL: process.env.TS_SELENIUM_WEB_CONSOLE_OCP_URL || 'https://console-openshift-console.apps.',
/**
* Run browser in "Headless" (hiden) mode, "false" by default.
*/
TS_SELENIUM_HEADLESS: process.env.TS_SELENIUM_HEADLESS === 'true',
/**
* Run browser in "Fullscreen" (kiosk) mode, "false" by default.
*/
TS_SELENIUM_LAUNCH_FULLSCREEN: process.env.TS_SELENIUM_LAUNCH_FULLSCREEN === 'true',
/**
* Run browser with an enabled or disabled W3C protocol (on Chrome 76 and upper, it is enabled by default), "true" by default.
*/
TS_SELENIUM_W3C_CHROME_OPTION: process.env.TS_SELENIUM_W3C_CHROME_OPTION !== 'false',
/**
* Browser width resolution, "1920" by default.
*/
TS_SELENIUM_RESOLUTION_WIDTH: Number(process.env.TS_SELENIUM_RESOLUTION_WIDTH) || 1920,
/**
* Browser height resolution, "1080" by default.
*/
TS_SELENIUM_RESOLUTION_HEIGHT: Number(process.env.TS_SELENIUM_RESOLUTION_HEIGHT) || 1080,
/**
* Default ammount of tries, "5" by default.
*/
TS_SELENIUM_DEFAULT_ATTEMPTS: Number(process.env.TS_SELENIUM_DEFAULT_ATTEMPTS) || 5,
/**
* Default delay in milliseconds between tries, "1000" by default.
*/
TS_SELENIUM_DEFAULT_POLLING: Number(process.env.TS_SELENIUM_DEFAULT_POLLING) || 1000,
/**
* Amount of tries for checking workspace status.
*/
TS_SELENIUM_WORKSPACE_STATUS_ATTEMPTS: Number(process.env.TS_SELENIUM_WORKSPACE_STATUS_ATTEMPTS) || 90,
/**
* Delay in milliseconds between checking workspace status tries.
*/
TS_SELENIUM_WORKSPACE_STATUS_POLLING: Number(process.env.TS_SELENIUM_WORKSPACE_STATUS_POLLING) || 10000,
/**
* Amount of tries for checking plugin precence.
*/
TS_SELENIUM_PLUGIN_PRECENCE_ATTEMPTS: Number(process.env.TS_SELENIUM_PLUGIN_PRECENCE_ATTEMPTS) || 20,
/**
* Name of workspace created for 'Happy Path' scenario validation.
*/
TS_SELENIUM_HAPPY_PATH_WORKSPACE_NAME: process.env.TS_SELENIUM_HAPPY_PATH_WORKSPACE_NAME || 'petclinic-dev-environment',
/**
* Using 'single-host' strategy, "false" by default.
*/
TS_SELENIUM_SINGLE_HOST: process.env.TS_SELENIUM_SINGLE_HOST === 'true',
/**
* Value of OpenShift oAuth property determines how to login in installed application,
* if 'false' as an user of application, if 'true' as a regular user of OCP.
*/
TS_SELENIUM_VALUE_OPENSHIFT_OAUTH: process.env.TS_SELENIUM_VALUE_OPENSHIFT_OAUTH || 'false',
/**
* Username used to log in MultiUser Che.
*/
TS_SELENIUM_USERNAME: process.env.TS_SELENIUM_USERNAME || 'che',
/**
* Password used to log in MultiUser Che.
*/
TS_SELENIUM_PASSWORD: process.env.TS_SELENIUM_PASSWORD || '',
/**
* Log into OCP by using appropriate provider title.
*/
TS_OCP_LOGIN_PAGE_PROVIDER_TITLE: process.env.TS_OCP_LOGIN_PAGE_PROVIDER_TITLE || '',
/**
* Path to folder with load tests execution report.
*/
TS_SELENIUM_LOAD_TEST_REPORT_FOLDER: process.env.TS_SELENIUM_LOAD_TEST_REPORT_FOLDER || './load-test-folder',
/**
* Regular username used to login in OCP.
*/
TS_SELENIUM_OCP_USERNAME: process.env.TS_SELENIUM_OCP_USERNAME || '',
/**
* Password regular user used to login in OCP.
*/
TS_SELENIUM_OCP_PASSWORD: process.env.TS_SELENIUM_OCP_PASSWORD || '',
/**
* Email of regular user OpenShift to login CHE.
*/
TS_SELENIUM_EMAIL_USER: process.env.TS_SELENIUM_EMAIL_USER || 'test@test.com',
/**
* First name of regular user OpenShift to login CHE.
*/
TS_SELENIUM_FIRST_NAME: process.env.TS_SELENIUM_FIRST_NAME || 'qa',
/**
* Last name of regular user Openshift to login CHE.
*/
TS_SELENIUM_LAST_NAME: process.env.TS_SELENIUM_LAST_NAME || 'test',
/**
* Delay between screenshots catching in the milliseconds for the execution screencast.
*/
TS_SELENIUM_DELAY_BETWEEN_SCREENSHOTS: Number(process.env.TS_SELENIUM_DELAY_BETWEEN_SCREENSHOTS) || 1000,
/**
* Path to folder with tests execution report.
*/
TS_SELENIUM_REPORT_FOLDER: process.env.TS_SELENIUM_REPORT_FOLDER || './report',
/**
* Enable or disable storing of execution screencast, "false" by default.
*/
TS_SELENIUM_EXECUTION_SCREENCAST: process.env.TS_SELENIUM_EXECUTION_SCREENCAST === 'true',
/**
* Delete screencast after execution if all tests passed, "true" by default.
*/
DELETE_SCREENCAST_IF_TEST_PASS: process.env.DELETE_SCREENCAST_IF_TEST_PASS !== 'false',
/**
* Remote driver URL.
*/
TS_SELENIUM_REMOTE_DRIVER_URL: process.env.TS_SELENIUM_REMOTE_DRIVER_URL || '',
/**
* Stop and remove workspace if a test fails.
*/
DELETE_WORKSPACE_ON_FAILED_TEST: process.env.DELETE_WORKSPACE_ON_FAILED_TEST === 'true',
/**
* Log level settings, possible variants: 'INFO' (by default), 'DEBUG', 'TRACE'.
*/
TS_SELENIUM_LOG_LEVEL: process.env.TS_SELENIUM_LOG_LEVEL || 'INFO',
/**
* Running test suite - possible variants can be found in package.json scripts part.
*/
TEST_SUITE: process.env.TEST_SUITE || 'test-happy-path',
/**
* The repo (with README.md in root) and access token are needed for to run test-git-ssh
*/
TS_GITHUB_TEST_REPO: process.env.TS_GITHUB_TEST_REPO || '',
/**
* Token for a github repository with permissions which allow add the ssh keys
*/
TS_GITHUB_TEST_REPO_ACCESS_TOKEN: process.env.TS_GITHUB_TEST_REPO_ACCESS_TOKEN || '',
/**
* Login for a user whom has been created in the test Openshift cluster. Need for Openshift connector test
*/
TS_TEST_OPENSHIFT_PLUGIN_USERNAME: process.env.TS_TEST_OPENSHIFT_PLUGIN_USERNAME || '',
/**
* Password for a user whom has been created in the test Openshift cluster. Need for Openshift connector test
*/
TS_TEST_OPENSHIFT_PLUGIN_PASSWORD: process.env.TS_TEST_OPENSHIFT_PLUGIN_PASSWORD || '',
/**
* The name of project in the Openshift plugin tree
*/
TS_TEST_OPENSHIFT_PLUGIN_PROJECT: process.env.TS_TEST_OPENSHIFT_PLUGIN_PROJECT || '',
/**
* The name of the Openshift connector plugin component type
*/
TS_TEST_OPENSHIFT_PLUGIN_COMPONENT_TYPE: process.env.TS_TEST_OPENSHIFT_PLUGIN_COMPONENT_TYPE || 'nodejs (s2i)',
/**
* The name of the Openshift connector plugin component version
*/
TS_TEST_OPENSHIFT_PLUGIN_COMPONENT_VERSION: process.env.TS_TEST_OPENSHIFT_PLUGIN_COMPONENT_VERSION || 'latest',
/**
* Print all timeout variables when tests launch, defaulte to false
*/
TS_SELENIUM_PRINT_TIMEOUT_VARIABLES: process.env.TS_SELENIUM_PRINT_TIMEOUT_VARIABLES || false,
/**
* URL of the workspace created by devworkspace-controller
*/
TS_SELENIUM_DEVWORKSPACE_URL: process.env.TS_SELENIUM_DEVWORKSPACE_URL,
/**
* This variable specifies that run test is used for load testing and that all artifacts will be sent to ftp client.
*/
TS_LOAD_TESTS: process.env.TS_LOAD_TESTS || 'false',
/**
* This variable determines whether to delete the workspace after the test or leave the workspace running.
*/
TS_DELETE_PLUGINS_TEST_WORKSPACE: process.env.TS_DELETE_PLUGINS_TEST_WORKSPACE || 'true'
};

View File

@ -1,210 +0,0 @@
/*********************************************************************
* Copyright (c) 2020 Red Hat, Inc.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/
export const TimeoutConstants = {
// -------------------------------------------- INSTALLING AND STARTUP --------------------------------------------
/**
* Wait between workspace started and IDE ready to be used, "20 000" by default.
*/
TS_IDE_LOAD_TIMEOUT: Number(process.env.TS_IDE_LOAD_TIMEOUT) || 20_000,
/**
* Timeout in milliseconds waiting for workspace start, "360 000" by default.
*/
TS_SELENIUM_START_WORKSPACE_TIMEOUT: Number(process.env.TS_SELENIUM_START_WORKSPACE_TIMEOUT) || 360_000,
/**
* Timeout in milliseconds waiting for page load, "20 000" by default.
*/
TS_SELENIUM_LOAD_PAGE_TIMEOUT: Number(process.env.TS_SELENIUM_LOAD_PAGE_TIMEOUT) || 20_000,
/**
* Wait for loader absence, "60 000" by default.
*/
TS_WAIT_LOADER_ABSENCE_TIMEOUT: Number(process.env.TS_WAIT_LOADER_ABSENCE_TIMEOUT) || 60_000,
/**
* Wait for loader absence, "60 000" by default.
*/
TS_WAIT_LOADER_PRESENCE_TIMEOUT: Number(process.env.TS_WAIT_LOADER_PRESENCE_TIMEOUT) || 60_000,
/**
* Timeout waiting for URL, "5 000" by default.
*/
TS_WAIT_URL_TIMEOUT: Number(process.env.TS_WAIT_URL_TIMEOUT) || 5_000,
// -------------------------------------------- DASHBOARD --------------------------------------------
/**
* Common timeout for dashboard items, "5 000" by default
*/
TS_COMMON_DASHBOARD_WAIT_TIMEOUT: Number(process.env.TS_COMMON_DASHBOARD_WAIT_TIMEOUT) || 5_000,
/**
* Timeout for clicking on dashboard menu items, "2 000" by default
*/
TS_CLICK_DASHBOARD_ITEM_TIMEOUT: Number(process.env.TS_CLICK_DASHBOARD_ITEM_TIMEOUT) || 2_000,
/**
* Timeout for workspace stopped status, "30 000" by default
*/
TS_DASHBOARD_WORKSPACE_STOP_TIMEOUT: Number(process.env.TS_DASHBOARD_WORKSPACE_STOP_TIMEOUT) || 30_000,
// -------------------------------------------- LANGUAGE SERVER VALIDATION --------------------------------------------
/**
* Timeout in milliseconds waiting for language server initialization, "180 000" by default.
*/
TS_SELENIUM_LANGUAGE_SERVER_START_TIMEOUT: Number(process.env.TS_SELENIUM_LANGUAGE_SERVER_START_TIMEOUT) || 180_000,
/**
* Timeout for suggestion invoking, "60 000" by default.
*/
TS_SUGGESTION_TIMEOUT: Number(process.env.TS_OPEN_PROJECT_TREE_TIMEOUT) || 60_000,
/**
* Timeout for error highlighting presence, "90 000" by default
*/
TS_ERROR_HIGHLIGHTING_TIMEOUT: Number(process.env.TS_OPEN_PROJECT_TREE_TIMEOUT) || 90_000,
// -------------------------------------------- PROJECT TREE --------------------------------------------
/**
* Wait for IDE showing project tree tab, "60 000" by default.
*/
TS_PROJECT_TREE_TIMEOUT: Number(process.env.TS_OPEN_PROJECT_TREE_TIMEOUT) || 60_000,
/**
* Click on item timeout (project tree), "10 000" by default.
*/
TS_PROJECT_TREE_CLICK_ON_ITEM_TIMEOUT: Number(process.env.TS_PROJECT_TREE_CLICK_ON_ITEM_TIMEOUT) || 10_000,
/**
* Expand item in project tree, "5 000" by default.
*/
TS_EXPAND_PROJECT_TREE_ITEM_TIMEOUT: Number(process.env.TS_EXPAND_PROJECT_TREE_ITEM_TIMEOUT) || 5_000,
/**
* Timeout for waiting workspace sample import, 50_000 by default.
*/
TS_IMPORT_PROJECT_DEFAULT_POLLING: Number(process.env.TS_SELENIUM_DEFAULT_POLLING) || 50_000,
// -------------------------------------------- EDITOR --------------------------------------------
/**
* Timeout for inetractions with editor tab - wait, click, select, "5 000" by default.
*/
TS_EDITOR_TAB_INTERACTION_TIMEOUT: Number(process.env.TS_OPEN_PROJECT_TREE_TIMEOUT) || 5_000,
/**
* Wait for file to be opened in editor, "30 000" by default.
*/
TS_OPEN_EDITOR_TIMEOUT: Number(process.env.TS_OPEN_PROJECT_TREE_TIMEOUT) || 30_000,
/**
* Wait for suggestion container closure, "3 000" by default.
*/
TS_CLOSE_SUGGESTION_CONTAINER_TIMEOUT: Number(process.env.TS_CLOSE_SUGGESTION_CONTAINER_TIMEOUT) || 3_000,
// -------------------------------------------- IDE --------------------------------------------
/**
* Timeout for context menu manipulation, "10 000" by default
*/
TS_CONTEXT_MENU_TIMEOUT: Number(process.env.TS_CONTEXT_MENU_TIMEOUT) || 10_000,
/**
* Timeout for interactions with Notification center - open, close, "10 000" by default.
*/
TS_NOTIFICATION_CENTER_TIMEOUT: Number(process.env.TS_OPEN_PROJECT_TREE_TIMEOUT) || 10_000,
/**
* Timeout for debugger to connect, "60 000" by default
*/
TS_DEBUGGER_CONNECTION_TIMEOUT: Number(process.env.TS_DEBUGGER_CONNECTION_TIMEOUT) || 60_000,
/**
* Timeout for context menu manipulation, "10 000" by default
*/
TS_DIALOG_WINDOW_DEFAULT_TIMEOUT: Number(process.env.TS_DIALOG_WINDOW_DEFAULT_TIMEOUT) || 10_000,
/**
* Timeout for breakpoint interactions, "20 000" by default
*/
TS_BREAKPOINT_DEFAULT_TIMEOUT: Number(process.env.TS_BREAKPOINT_DEFAULT_TIMEOUT) || 20_000,
/**
* Timeout for interactions with Git Plugin container, "20 000" by default
*/
TS_GIT_CONAINER_INTERACTION_TIMEOUT: Number(process.env.TS_GIT_CONAINER_INTERACTION_TIMEOUT) || 20_000,
/**
* Timeout for toolbars interaction, "30 000" by default
*/
TS_SELENIUM_TOOLBAR_TIMEOUT: Number(process.env.TS_SELENIUM_TOOLBAR_TIMEOUT) || 30_000,
/**
* Timeout for clicking on visible item, "3 000" by default
*/
TS_SELENIUM_CLICK_ON_VISIBLE_ITEM: Number(process.env.TS_SELENIUM_CLICK_ON_VISIBLE_ITEM) || 3_000,
/**
* Timeout for OpenDialogWidget class, "5 000" by default
*/
TS_SELENIUM_DIALOG_WIDGET_TIMEOUT: Number(process.env.TS_SELENIUM_DIALOG_WIDGET_TIMEOUT) || 5_000,
/**
* Default timeout for interaction with terminal, "3 000" by default
*/
TS_SELENIUM_TERMINAL_DEFAULT_TIMEOUT: Number(process.env.TS_SELENIUM_TERMINAL_DEFAULT_TIMEOUT) || 5_000,
/**
* Default timeout for preview widget, "10 000" by default
*/
TS_SELENIUM_PREVIEW_WIDGET_DEFAULT_TIMEOUT: Number(process.env.TS_SELENIUM_PREVIEW_WIDGET_DEFAULT_TIMEOUT) || 10_000,
/**
* Timeout for opening quick menu from top panel, "10 000" by default
*/
TS_SELENIUM_TOP_MENU_QUICK_CONTAINER_TIMEOUT: Number(process.env.TS_SELENIUM_TOP_MENU_QUICK_CONTAINER_TIMEOUT) || 10_000,
/**
* Timeout waiting for url, "10 000" by default
*/
TS_SELENIUM_WAIT_FOR_URL: Number(process.env.TS_SELENIUM_WAIT_FOR_URL) || 10_000,
/**
* Timeout waiting for an executed task to finish, waiting stops automatically if any exit code notification is present, "300 000" by default
*/
TS_SELENIUM_WAIT_TASK_EXIT_CODE_TIMEOUT: Number(process.env.TS_SELENIUM_WAIT_TASK_EXIT_CODE_TIMEOUT) || 300_000,
// ------------------------------------ OPENSHIFT RELATED ------------------------------------
/**
* Timeout for obtaining cluster IP, "10 000" by default.
*/
TS_GET_CLUSTER_IP_TIMEOUT: Number(process.env.TS_GET_CLUSTER_IP_TIMEOUT) || 60_000,
/**
* Timeout for waiting fr openshift connector tree, "10 000" by default.
*/
TS_WAIT_OPENSHIFT_CONNECTOR_TREE_TIMEOUT: Number(process.env.TS_WAIT_OPENSHIFT_CONNECTOR_TREE_TIMEOUT) || 120_000,
// ----------------------------------------- PLUGINS -----------------------------------------
/**
* Common timeout for plugins.
*/
TS_COMMON_PLUGIN_TEST_TIMEOUT: Number(process.env.TS_COMMON_PLUGIN_TEST_TIMEOUT) || 20_000
};

View File

@ -1,185 +0,0 @@
/*********************************************************************
* Copyright (c) 2019 Red Hat, Inc.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/
import * as mocha from 'mocha';
import { IDriver } from './IDriver';
import { inversifyConfig } from '..';
import { TYPES, CLASSES } from '..';
import * as fs from 'fs';
import * as rm from 'rimraf';
import { TestConstants } from '../TestConstants';
import { logging } from 'selenium-webdriver';
import { DriverHelper } from '../utils/DriverHelper';
import { ScreenCatcher } from '../utils/ScreenCatcher';
import { ITestWorkspaceUtil } from '../utils/workspace/ITestWorkspaceUtil';
import { PreferencesHandler, AskForConfirmationType, TerminalRendererType } from '../utils/PreferencesHandler';
import { CheApiRequestHandler } from '../utils/requestHandlers/CheApiRequestHandler';
import { TimeoutConstants } from '../TimeoutConstants';
import { Logger } from '../utils/Logger';
const e2eContainer = inversifyConfig.e2eContainer;
const driver: IDriver = e2eContainer.get(TYPES.Driver);
const driverHelper: DriverHelper = e2eContainer.get(CLASSES.DriverHelper);
const screenCatcher: ScreenCatcher = e2eContainer.get(CLASSES.ScreenCatcher);
let methodIndex: number = 0;
let deleteScreencast: boolean = true;
let testWorkspaceUtil: ITestWorkspaceUtil = e2eContainer.get(TYPES.WorkspaceUtil);
let preferencesHandler: PreferencesHandler = e2eContainer.get(CLASSES.PreferencesHandler);
class CheReporter extends mocha.reporters.Spec {
constructor(runner: mocha.Runner, options: mocha.MochaOptions) {
super(runner, options);
runner.on('start', async (test: mocha.Test) => {
let launchInformation: string =
`################## Launch Information ##################
TS_SELENIUM_BASE_URL: ${TestConstants.TS_SELENIUM_BASE_URL}
TS_SELENIUM_HEADLESS: ${TestConstants.TS_SELENIUM_HEADLESS}
TS_SELENIUM_USERNAME: ${TestConstants.TS_SELENIUM_USERNAME}
TS_SELENIUM_PASSWORD: ${TestConstants.TS_SELENIUM_PASSWORD}
TS_SELENIUM_HAPPY_PATH_WORKSPACE_NAME: ${TestConstants.TS_SELENIUM_HAPPY_PATH_WORKSPACE_NAME}
TS_SELENIUM_DELAY_BETWEEN_SCREENSHOTS: ${TestConstants.TS_SELENIUM_DELAY_BETWEEN_SCREENSHOTS}
TS_SELENIUM_REPORT_FOLDER: ${TestConstants.TS_SELENIUM_REPORT_FOLDER}
TS_SELENIUM_EXECUTION_SCREENCAST: ${TestConstants.TS_SELENIUM_EXECUTION_SCREENCAST}
DELETE_SCREENCAST_IF_TEST_PASS: ${TestConstants.DELETE_SCREENCAST_IF_TEST_PASS}
TS_SELENIUM_REMOTE_DRIVER_URL: ${TestConstants.TS_SELENIUM_REMOTE_DRIVER_URL}
DELETE_WORKSPACE_ON_FAILED_TEST: ${TestConstants.DELETE_WORKSPACE_ON_FAILED_TEST}
TS_SELENIUM_LOG_LEVEL: ${TestConstants.TS_SELENIUM_LOG_LEVEL}
`;
if (TestConstants.TS_SELENIUM_PRINT_TIMEOUT_VARIABLES) {
launchInformation += `\n TS_SELENIUM_PRINT_TIMEOUT_VARIABLES is set to true: \n`;
Object.entries(TimeoutConstants).forEach(
([key, value]) => launchInformation += `\n ${key}: ${value}`);
} else {
launchInformation += `\n to output timeout variables, set TS_SELENIUM_PRINT_TIMEOUT_VARIABLES to true`;
}
launchInformation += `\n ######################################################## \n`;
console.log(launchInformation);
rm.sync(TestConstants.TS_SELENIUM_REPORT_FOLDER);
if (TestConstants.TS_SELENIUM_LOG_LEVEL === 'TRACE') {
CheApiRequestHandler.enableRequestInteceptor();
CheApiRequestHandler.enableResponseInterceptor();
}
await preferencesHandler.setConfirmExit(AskForConfirmationType.never);
await preferencesHandler.setTerminalType(TerminalRendererType.dom);
});
runner.on('test', async function (test: mocha.Test) {
if (!TestConstants.TS_SELENIUM_EXECUTION_SCREENCAST) {
return;
}
methodIndex = methodIndex + 1;
const currentMethodIndex: number = methodIndex;
let iterationIndex: number = 1;
while (!(test.state === 'passed' || test.state === 'failed')) {
await screenCatcher.catchMethodScreen(test.title, currentMethodIndex, iterationIndex);
iterationIndex = iterationIndex + 1;
await driverHelper.wait(TestConstants.TS_SELENIUM_DELAY_BETWEEN_SCREENSHOTS);
}
});
runner.on('pass', async (test: mocha.Test) => {
if (TestConstants.TS_LOAD_TESTS) {
const loadTestReportFolder: string = TestConstants.TS_SELENIUM_LOAD_TEST_REPORT_FOLDER;
const loadTestFilePath: string = loadTestReportFolder + '/load-test-results.txt';
const report = test.title + ': ' + test.duration + '\r';
if (!fs.existsSync(loadTestReportFolder)) {
fs.mkdirSync(loadTestReportFolder);
}
fs.appendFileSync(loadTestFilePath, report);
}
});
runner.on('end', async function (test: mocha.Test) {
// ensure that fired events done
await driver.get().sleep(5000);
// close driver
await driver.get().quit();
// delete screencast folder if conditions matched
if (deleteScreencast && TestConstants.DELETE_SCREENCAST_IF_TEST_PASS) {
rm.sync(TestConstants.TS_SELENIUM_REPORT_FOLDER);
}
});
runner.on('fail', async function (test: mocha.Test) {
Logger.error(`CheReporter runner.on.fail: ${test.fullTitle()} failed after ${test.duration}ms`);
// raise flag for keeping the screencast
deleteScreencast = false;
const testFullTitle: string = test.fullTitle().replace(/\s/g, '_');
const testTitle: string = test.title.replace(/\s/g, '_');
const testReportDirPath: string = `${TestConstants.TS_SELENIUM_REPORT_FOLDER}/${testFullTitle}`;
const screenshotFileName: string = `${testReportDirPath}/screenshot-${testTitle}.png`;
const pageSourceFileName: string = `${testReportDirPath}/pagesource-${testTitle}.html`;
const browserLogsFileName: string = `${testReportDirPath}/browserlogs-${testTitle}.txt`;
// create reporter dir if not exist
const reportDirExists: boolean = fs.existsSync(TestConstants.TS_SELENIUM_REPORT_FOLDER);
if (!reportDirExists) {
fs.mkdirSync(TestConstants.TS_SELENIUM_REPORT_FOLDER);
}
// create dir for failed test report if not exist
const testReportDirExists: boolean = fs.existsSync(testReportDirPath);
if (!testReportDirExists) {
fs.mkdirSync(testReportDirPath);
}
// take screenshot and write to file
const screenshot: string = await driver.get().takeScreenshot();
const screenshotStream = fs.createWriteStream(screenshotFileName);
screenshotStream.write(Buffer.from(screenshot, 'base64'));
screenshotStream.end();
// take pagesource and write to file
const pageSource: string = await driver.get().getPageSource();
const pageSourceStream = fs.createWriteStream(pageSourceFileName);
pageSourceStream.write(Buffer.from(pageSource));
pageSourceStream.end();
// take browser console logs and write to file
const browserLogsEntries: logging.Entry[] = await driverHelper.getDriver().manage().logs().get('browser');
let browserLogs: string = '';
browserLogsEntries.forEach(log => {
browserLogs += `\"${log.level}\" \"${log.type}\" \"${log.message}\"\n`;
});
const browserLogsStream = fs.createWriteStream(browserLogsFileName);
browserLogsStream.write(Buffer.from(browserLogs));
browserLogsStream.end();
// stop and remove running workspace
if (TestConstants.DELETE_WORKSPACE_ON_FAILED_TEST) {
console.log('Property DELETE_WORKSPACE_ON_FAILED_TEST se to true - trying to stop and delete running workspace.');
testWorkspaceUtil.cleanUpAllWorkspaces();
}
});
}
}
export = CheReporter;

View File

@ -1,71 +0,0 @@
/*********************************************************************
* Copyright (c) 2019 Red Hat, Inc.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/
import 'chromedriver';
import 'reflect-metadata';
import { injectable } from 'inversify';
import { ThenableWebDriver, Builder } from 'selenium-webdriver';
import { IDriver } from './IDriver';
import { Options } from 'selenium-webdriver/chrome';
import { TestConstants } from '../TestConstants';
@injectable()
export class ChromeDriver implements IDriver {
private readonly driver: ThenableWebDriver;
constructor() {
const options: Options = this.getDriverOptions();
this.driver = this.getDriverBuilder(options).build();
this.driver
.manage()
.window()
.setSize(TestConstants.TS_SELENIUM_RESOLUTION_WIDTH, TestConstants.TS_SELENIUM_RESOLUTION_HEIGHT);
}
get(): ThenableWebDriver {
return this.driver;
}
private getDriverOptions(): Options {
let options: Options = new Options()
.addArguments('--no-sandbox')
.addArguments('--disable-web-security')
.addArguments('--allow-running-insecure-content')
.addArguments('--ignore-certificate-errors');
// if 'true' run in 'headless' mode
if (TestConstants.TS_SELENIUM_HEADLESS) {
options = options.addArguments('headless');
}
return options;
}
private getDriverBuilder(options: Options): Builder {
const disableW3copts = { 'goog:chromeOptions' : { 'w3c' : false }};
let builder: Builder = new Builder()
.forBrowser('chrome')
.setChromeOptions(options);
// if 'false' w3c protocl is disabled
if (! TestConstants.TS_SELENIUM_W3C_CHROME_OPTION) {
builder.withCapabilities(disableW3copts)
.forBrowser('chrome')
.setChromeOptions(options);
}
// if 'true' run with remote driver
if (TestConstants.TS_SELENIUM_REMOTE_DRIVER_URL) {
builder = builder.usingServer(TestConstants.TS_SELENIUM_REMOTE_DRIVER_URL);
}
return builder;
}
}

View File

@ -1,14 +0,0 @@
/*********************************************************************
* Copyright (c) 2019 Red Hat, Inc.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/
import { ThenableWebDriver } from 'selenium-webdriver';
export interface IDriver {
get(): ThenableWebDriver;
}

View File

@ -1,17 +0,0 @@
apiVersion: 1.0.0
metadata:
name: java11-plugin-test
projects:
- name: console-java-simple
source:
location: 'https://github.com/che-samples/console-java-simple.git'
type: git
branch: java1.11
components:
- type: cheEditor
id: eclipse/che-theia/next
memoryLimit: 512Mi
- id: redhat/java/latest
preferences:
java.server.launchMode: Standard
type: chePlugin

View File

@ -1,47 +0,0 @@
---
apiVersion: 1.0.0
metadata:
generateName: php-plugin-test
projects:
- name: php-web-simple
source:
type: git
location: "https://github.com/che-samples/web-php-simple"
components:
- type: chePlugin
id: bmewburn/vscode-intelephense-client/latest
- type: chePlugin
id: felixfbecker/php-debug/latest
- type: dockerimage
alias: php
image: quay.io/eclipse/che-php-7:nightly
memoryLimit: 512Mi
mountSources: true
endpoints:
- name: '8080-tcp'
port: 8080
volumes:
- name: composer
containerPath: "/home/user/.composer"
- name: symfony
containerPath: "/home/user/.symfony"
commands:
- name: Debug current file
actions:
- type: vscode-launch
referenceContent: |
{
"version": "0.2.0",
"configurations": [
{
"name": "Launch currently open script",
"type": "php",
"request": "launch",
"program": "${file}",
"stopOnEntry": true,
"cwd": "${fileDirname}",
"port": 9000,
"runtimeExecutable": "php"
}
]
}

View File

@ -1,14 +0,0 @@
apiVersion: 1.0.0
metadata:
name: python-plugin-test
projects:
- name: python-hello-world
source:
location: 'https://github.com/che-samples/python-hello-world.git'
type: git
components:
- id: ms-python/python/latest
type: chePlugin
- type: cheEditor
id: eclipse/che-theia/next
memoryLimit: 512Mi

View File

@ -1,52 +0,0 @@
apiVersion: 1.0.0
metadata:
name: typescript-debug-plugins
projects:
- name: nodejs-web-app
source:
location: 'https://github.com/che-samples/web-nodejs-sample.git'
branch: che-qe-tests
type: git
components:
- type: cheEditor
id: eclipse/che-theia/next
memoryLimit: 512Mi
- id: vscode/typescript-language-features/latest
type: chePlugin
- id: ms-vscode/node-debug2/latest
preferences:
debug.node.useV3: false
type: chePlugin
- mountSources: true
endpoints:
- name: nodejs
port: 3000
memoryLimit: 512Mi
type: dockerimage
alias: nodejs
image: 'quay.io/eclipse/che-nodejs10-ubi:nightly'
commands:
- name: run the web app (debugging enabled)
actions:
- workdir: '${CHE_PROJECTS_ROOT}/nodejs-web-app/app'
type: exec
command: npm install && nodemon --inspect app.js
component: nodejs
- name: Attach remote debugger
actions:
- referenceContent: |
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "attach",
"name": "Attach to Remote",
"address": "localhost",
"port": 9229,
"localRoot": "${workspaceFolder}",
"remoteRoot": "${workspaceFolder}"
}
]
}
type: vscode-launch

View File

@ -1,12 +0,0 @@
apiVersion: 1.0.0
metadata:
name: nodejs-24lop
projects:
- name: nodejs-web-app
source:
location: 'https://github.com/che-samples/web-nodejs-sample.git'
branch: che-qe-tests
type: git
components:
- type: chePlugin
id: ms-kubernetes-tools/vscode-kubernetes-tools/latest

View File

@ -1,12 +0,0 @@
apiVersion: 1.0.0
metadata:
name: nodejs-zmecm
projects:
- name: nodejs-web-app
source:
location: 'https://github.com/che-samples/web-nodejs-sample.git'
branch: che-qe-tests
type: git
components:
- id: timonwong/shellcheck/latest
type: chePlugin

View File

@ -1,32 +0,0 @@
apiVersion: 1.0.0
metadata:
name: che-docs-test
projects:
- name: che-docs
source:
location: 'https://github.com/eclipse/che-docs.git'
type: git
branch: master
components:
- mountSources: true
endpoints:
- name: Open-Livereload
port: 35729
- attributes:
path: /che-7/overview/introduction-to-eclipse-che/
name: Open-Preview-server
port: 4000
command:
- tail
args:
- '-f'
- /dev/null
memoryLimit: 512M
type: dockerimage
alias: che-docs
image: 'quay.io/eclipse/che-docs:latest'
- type: chePlugin
reference: 'https://che-plugin-registry-main.surge.sh/v3/plugins/errata-ai/vale-server/latest/meta.yaml'
alias: vale-server
preferences:
vale.core.useCLI: true

View File

@ -1,12 +0,0 @@
apiVersion: 1.0.0
metadata:
name: xml-plugin-test
projects:
- name: nodejs-web-app
source:
location: 'https://github.com/che-samples/web-nodejs-sample.git'
branch: che-qe-tests
type: git
components:
- id: redhat/vscode-xml/latest
type: chePlugin

View File

@ -1,12 +0,0 @@
apiVersion: 1.0.0
metadata:
name: nodejs-zmecm
projects:
- name: nodejs-web-app
source:
location: 'https://github.com/che-samples/web-nodejs-sample.git'
branch: che-qe-tests
type: git
components:
- id: redhat/vscode-yaml/latest
type: chePlugin

View File

@ -1,127 +0,0 @@
---
apiVersion: v1
kind: Service
metadata:
name: mysql
labels:
app.kubernetes.io/name: mysql
app.kubernetes.io/component: database
app.kubernetes.io/part-of: petclinic
spec:
ports:
- port: 3306
targetPort: 3306
selector:
app.kubernetes.io/name: mysql
app.kubernetes.io/component: database
app.kubernetes.io/part-of: petclinic
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: db
labels:
app.kubernetes.io/name: mysql
app.kubernetes.io/component: database
app.kubernetes.io/part-of: petclinic
spec:
selector:
matchLabels:
app.kubernetes.io/name: mysql
app.kubernetes.io/component: database
app.kubernetes.io/part-of: petclinic
replicas: 1
template:
metadata:
labels:
app.kubernetes.io/name: mysql
app.kubernetes.io/component: database
app.kubernetes.io/part-of: petclinic
spec:
containers:
- name: mysql
image: quay.io/eclipse/che--centos--mysql-57-centos7:latest-e08ee4d43b7356607685b69bde6335e27cf20c020f345b6c6c59400183882764
resources:
requests:
memory: 256Mi
env:
- name: MYSQL_USER
value: petclinic
- name: MYSQL_PASSWORD
value: petclinic
- name: MYSQL_ROOT_PASSWORD
value: petclinic
- name: MYSQL_DATABASE
value: petclinic
ports:
- containerPort: 3306
---
apiVersion: v1
kind: Service
metadata:
name: spring-boot-app
labels:
app.kubernetes.io/name: petclinic
app.kubernetes.io/component: webapp
app.kubernetes.io/part-of: petclinic
spec:
ports:
- port: 8080
targetPort: 8080
selector:
app.kubernetes.io/name: petclinic
app.kubernetes.io/component: webapp
app.kubernetes.io/part-of: petclinic
---
apiVersion: apps/v1 # for k8s versions before 1.9.0 use apps/v1beta2 and before 1.8.0 use extensions/v1beta1
kind: Deployment
metadata:
name: spring-boot-app
labels:
app.kubernetes.io/name: petclinic
app.kubernetes.io/component: webapp
app.kubernetes.io/part-of: petclinic
spec:
selector:
matchLabels:
app.kubernetes.io/name: petclinic
app.kubernetes.io/component: webapp
app.kubernetes.io/part-of: petclinic
replicas: 1
template:
metadata:
labels:
app.kubernetes.io/name: petclinic
app.kubernetes.io/component: webapp
app.kubernetes.io/part-of: petclinic
spec:
containers:
- name: spring-boot
image: quay.io/mloriedo/spring-petclinic
resources:
requests:
memory: 512Mi
ports:
- containerPort: 8080
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: spring-boot-app
labels:
app: spring-petclinic
tier: frontend
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
nginx.ingress.kubernetes.io/proxy-connect-timeout: "3600"
nginx.ingress.kubernetes.io/ssl-redirect: "false"
spec:
rules:
- host: 192.168.99.100.nip.io
http:
paths:
- path: /
backend:
serviceName: spring-boot-app
servicePort: 8080

View File

@ -1,94 +0,0 @@
---
apiVersion: 1.0.0
metadata:
name: petclinic-dev-environment
projects:
- name: petclinic
source:
type: git
location: "https://github.com/spring-projects/spring-petclinic.git"
components:
- type: cheEditor
id: eclipse/che-theia/next
memoryLimit: 512Mi
- type: kubernetes
alias: petclinic-web
reference: https://raw.githubusercontent.com/eclipse/che/master/tests/e2e/files/happy-path/containers-happy-path.yaml
selector:
app.kubernetes.io/component: webapp
entrypoints:
- containerName: spring-boot
command: ["tail"]
args: ["-f", "/dev/null"]
- type: kubernetes
alias: petclinic-db
reference: https://raw.githubusercontent.com/eclipse/che/master/tests/e2e/files/happy-path/containers-happy-path.yaml
selector:
app.kubernetes.io/component: database
- type: dockerimage
alias: maven-container
image: quay.io/eclipse/happy-path:nightly
env:
- name: MAVEN_CONFIG
value: /home/user/.m2
memoryLimit: 1500Mi
endpoints:
- name: '8080-tcp'
port: 8080
- name: 'debug'
port: 5005
attributes:
public: 'false'
mountSources: true
- type: chePlugin
id: redhat/java/latest
memoryLimit: "1000Mi"
preferences:
java.server.launchMode: Standard
- type: chePlugin
id: redhat/vscode-yaml/latest
commands:
- name: build
actions:
- type: exec
component: maven-container
command: mvn clean package | tee /workspace_logs/build.log && tail -n 40 /workspace_logs/build.log | grep 'BUILD SUCCESS' > /projects/petclinic/result-build.txt
workdir: /projects/petclinic
- name: build-file-output
actions:
- type: exec
component: maven-container
command: cd /projects/petclinic && mvn package | tee /workspace_logs/build-output.log && tail -n 40 /workspace_logs/build-output.log | grep 'BUILD SUCCESS' > /projects/petclinic/result-build-output.txt
- name: run
actions:
- type: exec
component: maven-container
command: java -jar spring-petclinic-2.4.5.jar --spring.profiles.active=mysql | tee /workspace_logs/run.log
workdir: /projects/petclinic/target
- name: run-with-changes
actions:
- type: exec
component: maven-container
command: java -jar spring-petclinic-2.4.5.jar --spring.profiles.active=mysql | tee /workspace_logs/run-with-changes.log
workdir: /projects/petclinic/target
- name: run-debug
actions:
- type: exec
component: maven-container
command: java -jar -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005 spring-petclinic-2.4.5.jar --spring.profiles.active=mysql | tee /workspace_logs/run-debug.log
workdir: /projects/petclinic/target
- name: Debug remote java application
actions:
- type: vscode-launch
referenceContent: |
{
"version": "0.2.0",
"configurations": [
{
"type": "java",
"name": "Debug (Attach) - Remote",
"request": "attach",
"hostName": "localhost",
"port": 5005
}]
}

View File

@ -1,49 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" output="target/classes" path="src/main/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" path="target/generated-sources/annotations">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
<attribute name="ignore_optional_problems" value="true"/>
<attribute name="m2e-apt" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="target/test-classes" path="target/generated-test-sources/test-annotations">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
<attribute name="ignore_optional_problems" value="true"/>
<attribute name="m2e-apt" value="true"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="target/classes"/>
</classpath>

View File

@ -1,35 +0,0 @@
#!/usr/bin/env bash
echo "Generating index.ts file..."
echo "import * as inversifyConfig from './inversify.config';
export { inversifyConfig };
export * from './inversify.types';
export * from './TestConstants';
export * from './TimeoutConstants';
" > index.ts
listOfDirs="driver utils pageobjects testsLibrary"
listOfExcludes="./driver/CheReporter.ts"
for dir in $listOfDirs
do
files=$(find ./$dir -type f | sort)
for file in $files
do
case $file in *ts)
for excludedFile in $listOfExcludes
do
if [ $excludedFile == $file ]; then
continue
else
end=$((${#file}-3))
file_without_ending=${file:0:end}
echo "export * from '$file_without_ending';" >> index.ts
fi
done
;;
*)
echo "Excluding file $file - not a typescript file"
;;
esac
done
done

View File

@ -1,59 +0,0 @@
import * as inversifyConfig from './inversify.config';
export { inversifyConfig };
export * from './inversify.types';
export * from './TestConstants';
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';
export * from './utils/requestHandlers/CheApiRequestHandler';
export * from './utils/requestHandlers/headers/CheMultiuserAuthorizationHeaderHandler';
export * from './utils/requestHandlers/headers/IAuthorizationHeaderHandler';
export * from './utils/requestHandlers/tokens/CheMultiuserTokenHandler';
export * from './utils/requestHandlers/tokens/ITokenHandler';
export * from './utils/ScreenCatcher';
export * from './utils/VCS/CheGitApi';
export * from './utils/VCS/github/GitHubUtil';
export * from './utils/workspace/ITestWorkspaceUtil';
export * from './utils/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/workspace-details/WorkspaceDetailsPlugins';
export * from './pageobjects/dashboard/workspace-details/WorkspaceDetails';
export * from './pageobjects/dashboard/Workspaces';
export * from './pageobjects/ide/ContextMenu';
export * from './pageobjects/ide/DebugView';
export * from './pageobjects/ide/DialogWindow';
export * from './pageobjects/ide/Editor';
export * from './pageobjects/ide/GitPlugin';
export * from './pageobjects/ide/Ide';
export * from './pageobjects/ide/LeftToolBar';
export * from './pageobjects/ide/NotificationCenter';
export * from './pageobjects/ide/OpenDialogWidget';
export * from './pageobjects/ide/OpenshiftPlugin';
export * from './pageobjects/ide/OpenWorkspaceWidget';
export * from './pageobjects/ide/plugins/KubernetesPlugin';
export * from './pageobjects/ide/PreviewWidget';
export * from './pageobjects/ide/ProjectTree';
export * from './pageobjects/ide/QuickOpenContainer';
export * from './pageobjects/ide/RightToolBar';
export * from './pageobjects/ide/Terminal';
export * from './pageobjects/ide/TopMenu';
export * from './pageobjects/login/ICheLoginPage';
export * from './pageobjects/login/IOcpLoginPage';
export * from './pageobjects/login/MultiUserLoginPage';
export * from './pageobjects/login/OcpUserLoginPage';
export * from './pageobjects/login/RegularUserOcpCheLoginPage';
export * from './pageobjects/login/UpdateAccountInformationPage';
export * from './pageobjects/openshift/CheLoginPage';
export * from './pageobjects/openshift/OcpLoginPage';
export * from './testsLibrary/CodeExecutionTests';
export * from './testsLibrary/LanguageServerTests';
export * from './testsLibrary/ProjectAndFileTests';
export * from './testsLibrary/WorkspaceHandlingTests';

View File

@ -1,48 +0,0 @@
#!/bin/bash
########################################
############# Methods ##################
########################################
launchAllUserstories(){
echo ""
echo "Launching all userstories";
echo ""
npm run lint && npm run tsc && mocha --opts mocha-all-devfiles.opts ;
}
launchSingleUserstory(){
echo ""
echo "Launching the \"${USERSTORY}\" userstory";
echo ""
tsc && mocha --opts mocha-single-devfile.opts --spec dist/tests/login/Login.spec.js --spec dist/tests/devfiles/${USERSTORY}.spec.js ;
}
checkUserstoryName(){
local checkedName="$(ls tests/devfiles | grep ${USERSTORY}.spec.ts)";
if [ -z "$checkedName" ]; then
echo ""
echo "Current value USERSTORY=\"${USERSTORY}\" doesn't match to any existed test:"
echo ""
echo "$(ls tests/devfiles | sed -e 's/.spec.ts/ /g')"
echo ""
echo "Please choose one of the tests above, or unset the \"USERSTORY\" variable for launching all of them."
echo ""
exit 1;
fi
}
########################################
############# Launching ################
########################################
if [ -z "$USERSTORY" ]; then
launchAllUserstories ;
else
checkUserstoryName ;
launchSingleUserstory ;
fi

View File

@ -1,120 +0,0 @@
/*********************************************************************
* Copyright (c) 2019 Red Hat, Inc.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/
import { Container } from 'inversify';
import { IDriver } from './driver/IDriver';
import { ChromeDriver } from './driver/ChromeDriver';
import { TYPES, CLASSES } from './inversify.types';
import { ITestWorkspaceUtil } from './utils/workspace/ITestWorkspaceUtil';
import { TestWorkspaceUtil } from './utils/workspace/TestWorkspaceUtil';
import { IOcpLoginPage } from './pageobjects/login/IOcpLoginPage';
import { OcpUserLoginPage } from './pageobjects/login/OcpUserLoginPage';
import { TestConstants } from './TestConstants';
import { ICheLoginPage } from './pageobjects/login/ICheLoginPage';
import { RegularUserOcpCheLoginPage } from './pageobjects/login/RegularUserOcpCheLoginPage';
import { MultiUserLoginPage } from './pageobjects/login/MultiUserLoginPage';
import { ContextMenu } from './pageobjects/ide/ContextMenu';
import { DriverHelper } from './utils/DriverHelper';
import { Dashboard } from './pageobjects/dashboard/Dashboard';
import { Workspaces } from './pageobjects/dashboard/Workspaces';
import { WorkspaceDetails } from './pageobjects/dashboard/workspace-details/WorkspaceDetails';
import { WorkspaceDetailsPlugins } from './pageobjects/dashboard/workspace-details/WorkspaceDetailsPlugins';
import { Ide } from './pageobjects/ide/Ide';
import { ProjectTree } from './pageobjects/ide/ProjectTree';
import { Editor } from './pageobjects/ide/Editor';
import { TopMenu } from './pageobjects/ide/TopMenu';
import { QuickOpenContainer } from './pageobjects/ide/QuickOpenContainer';
import { PreviewWidget } from './pageobjects/ide/PreviewWidget';
import { GitPlugin } from './pageobjects/ide/GitPlugin';
import { RightToolBar } from './pageobjects/ide/RightToolBar';
import { Terminal } from './pageobjects/ide/Terminal';
import { DebugView } from './pageobjects/ide/DebugView';
import { DialogWindow } from './pageobjects/ide/DialogWindow';
import { ScreenCatcher } from './utils/ScreenCatcher';
import { OcpLoginPage } from './pageobjects/openshift/OcpLoginPage';
import { OpenWorkspaceWidget } from './pageobjects/ide/OpenWorkspaceWidget';
import { CheLoginPage } from './pageobjects/openshift/CheLoginPage';
import { NotificationCenter } from './pageobjects/ide/NotificationCenter';
import { PreferencesHandler } from './utils/PreferencesHandler';
import { IAuthorizationHeaderHandler } from './utils/requestHandlers/headers/IAuthorizationHeaderHandler';
import { CheMultiuserAuthorizationHeaderHandler } from './utils/requestHandlers/headers/CheMultiuserAuthorizationHeaderHandler';
import { CheMultiuserTokenHandler } from './utils/requestHandlers/tokens/CheMultiuserTokenHandler';
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 { CreateWorkspace } from './pageobjects/dashboard/CreateWorkspace';
import { OpenshiftPlugin } from './pageobjects/ide/OpenshiftPlugin';
import { OpenDialogWidget } from './pageobjects/ide/OpenDialogWidget';
import { UpdateAccountInformationPage } from './pageobjects/login/UpdateAccountInformationPage';
import { LeftToolBar } from './pageobjects/ide/LeftToolBar';
import { KubernetesPlugin } from './pageobjects/ide/plugins/KubernetesPlugin';
import { BrowserTabsUtil } from './utils/BrowserTabsUtil';
import { PluginsView } from './pageobjects/ide/plugins/PluginsView';
import { LanguageServerTests } from './testsLibrary/LanguageServerTests';
import { CodeExecutionTests } from './testsLibrary/CodeExecutionTests';
import { ProjectAndFileTests } from './testsLibrary/ProjectAndFileTests';
import { WorkspaceHandlingTests } from './testsLibrary/WorkspaceHandlingTests';
const e2eContainer: Container = new Container({ defaultScope: 'Transient' });
e2eContainer.bind<IDriver>(TYPES.Driver).to(ChromeDriver).inSingletonScope();
e2eContainer.bind<ITestWorkspaceUtil>(TYPES.WorkspaceUtil).to(TestWorkspaceUtil);
e2eContainer.bind<IOcpLoginPage>(TYPES.OcpLogin).to(OcpUserLoginPage);
e2eContainer.bind<IAuthorizationHeaderHandler>(TYPES.IAuthorizationHeaderHandler).to(CheMultiuserAuthorizationHeaderHandler);
e2eContainer.bind<ITokenHandler>(TYPES.ITokenHandler).to(CheMultiuserTokenHandler);
if (JSON.parse(TestConstants.TS_SELENIUM_VALUE_OPENSHIFT_OAUTH)) {
e2eContainer.bind<ICheLoginPage>(TYPES.CheLogin).to(RegularUserOcpCheLoginPage);
} else {
e2eContainer.bind<ICheLoginPage>(TYPES.CheLogin).to(MultiUserLoginPage);
}
e2eContainer.bind<BrowserTabsUtil>(CLASSES.BrowserTabsUtil).to(BrowserTabsUtil);
e2eContainer.bind<ContextMenu>(CLASSES.ContextMenu).to(ContextMenu);
e2eContainer.bind<DriverHelper>(CLASSES.DriverHelper).to(DriverHelper);
e2eContainer.bind<Dashboard>(CLASSES.Dashboard).to(Dashboard);
e2eContainer.bind<Workspaces>(CLASSES.Workspaces).to(Workspaces);
e2eContainer.bind<WorkspaceDetails>(CLASSES.WorkspaceDetails).to(WorkspaceDetails);
e2eContainer.bind<WorkspaceDetailsPlugins>(CLASSES.WorkspaceDetailsPlugins).to(WorkspaceDetailsPlugins);
e2eContainer.bind<Ide>(CLASSES.Ide).to(Ide);
e2eContainer.bind<ProjectTree>(CLASSES.ProjectTree).to(ProjectTree);
e2eContainer.bind<Editor>(CLASSES.Editor).to(Editor);
e2eContainer.bind<TopMenu>(CLASSES.TopMenu).to(TopMenu);
e2eContainer.bind<QuickOpenContainer>(CLASSES.QuickOpenContainer).to(QuickOpenContainer);
e2eContainer.bind<PreviewWidget>(CLASSES.PreviewWidget).to(PreviewWidget);
e2eContainer.bind<GitPlugin>(CLASSES.GitPlugin).to(GitPlugin);
e2eContainer.bind<RightToolBar>(CLASSES.RightToolBar).to(RightToolBar);
e2eContainer.bind<LeftToolBar>(CLASSES.LeftToolBar).to(LeftToolBar);
e2eContainer.bind<Terminal>(CLASSES.Terminal).to(Terminal);
e2eContainer.bind<DebugView>(CLASSES.DebugView).to(DebugView);
e2eContainer.bind<DialogWindow>(CLASSES.DialogWindow).to(DialogWindow);
e2eContainer.bind<ScreenCatcher>(CLASSES.ScreenCatcher).to(ScreenCatcher);
e2eContainer.bind<OcpLoginPage>(CLASSES.OcpLoginPage).to(OcpLoginPage);
e2eContainer.bind<OpenWorkspaceWidget>(CLASSES.OpenWorkspaceWidget).to(OpenWorkspaceWidget);
e2eContainer.bind<CheLoginPage>(CLASSES.CheLoginPage).to(CheLoginPage);
e2eContainer.bind<NotificationCenter>(CLASSES.NotificationCenter).to(NotificationCenter);
e2eContainer.bind<PreferencesHandler>(CLASSES.PreferencesHandler).to(PreferencesHandler);
e2eContainer.bind<CheApiRequestHandler>(CLASSES.CheApiRequestHandler).to(CheApiRequestHandler);
e2eContainer.bind<CheGitApi>(CLASSES.CheGitApi).to(CheGitApi);
e2eContainer.bind<GitHubUtil>(CLASSES.GitHubUtil).to(GitHubUtil);
e2eContainer.bind<OpenshiftPlugin>(CLASSES.OpenshiftPlugin).to(OpenshiftPlugin);
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);
e2eContainer.bind<PluginsView>(CLASSES.PluginsView).to(PluginsView);
e2eContainer.bind<LanguageServerTests>(CLASSES.LanguageServerTests).to(LanguageServerTests);
e2eContainer.bind<CodeExecutionTests>(CLASSES.CodeExecutionTests).to(CodeExecutionTests);
e2eContainer.bind<ProjectAndFileTests>(CLASSES.ProjectAndFileTests).to(ProjectAndFileTests);
e2eContainer.bind<WorkspaceHandlingTests>(CLASSES.WorkspaceHandlingTests).to(WorkspaceHandlingTests);
export { e2eContainer };

View File

@ -1,66 +0,0 @@
/*********************************************************************
* Copyright (c) 2019 Red Hat, Inc.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/
const TYPES = {
Driver: Symbol.for('Driver'),
CheLogin: Symbol.for('CheLogin'),
OcpLogin: Symbol.for('OcpLogin'),
WorkspaceUtil: Symbol.for('WorkspaceUtil'),
IAuthorizationHeaderHandler: Symbol.for('IAuthorizationHeaderHandler'),
ITokenHandler: Symbol.for('ITokenHandler')
};
const CLASSES = {
DriverHelper: 'DriverHelper',
Dashboard: 'Dashboard',
Workspaces: 'Workspaces',
NewWorkspace: 'NewWorkspace',
WorkspaceDetails: 'WorkspaceDetails',
WorkspaceDetailsPlugins: 'WorkspaceDetailsPlugins',
Ide: 'Ide',
ProjectTree: 'ProjectTree',
Editor: 'Editor',
TopMenu: 'TopMenu',
QuickOpenContainer: 'QuickOpenContainer',
PreviewWidget: 'PreviewWidget',
GitHubPlugin: 'GitHubPlugin',
RightToolBar: 'RightToolBar',
LeftToolBar: 'LeftToolBar',
Terminal: 'Terminal',
DebugView: 'DebugView',
DialogWindow: 'DialogWindow',
ScreenCatcher: 'ScreenCatcher',
OpenshiftPlugin: 'OpenshiftPlugin',
OcpLoginPage: 'OcpLoginPage',
OpenWorkspaceWidget: 'OpenWorkspaceWidget',
ContextMenu: 'ContextMenu',
CheLoginPage: 'CheLoginPage',
GitHubUtil: 'GitHubUtil',
CheGitApi: 'CheGitApi',
GitPlugin: 'GitPlugin',
NotificationCenter: 'NotificationCenter',
PreferencesHandler: 'PreferencesHandler',
CheApiRequestHandler: 'CheApiRequestHandler',
CreateWorkspace: 'CreateWorkspace',
OpenDialogWidget: 'OpenDialogWidget',
UpdateAccountInformationPage: 'UpdateAccountInformationPage',
KubernetesPlugin: 'KubernetesPlugin',
BrowserTabsUtil: 'BrowserTabsUtil',
PluginsView: 'PluginsView',
LanguageServerTests: 'LanguageServerTests',
CodeExecutionTests: 'CodeExecutionTests',
ProjectAndFileTests: 'ProjectAndFileTests',
WorkspaceHandlingTests: 'WorkspaceHandlingTests'
};
export { TYPES, CLASSES };

View File

@ -1,8 +0,0 @@
--timeout 2200000
--reporter 'dist/driver/CheReporter.js'
-u tdd
--full-trace
--spec dist/tests/login/Login.spec.js
--spec dist/tests/devfiles/*.spec.js
--spec dist/tests/e2e/FactoryUrl.spec.js
--require source-map-support/register

View File

@ -1,11 +0,0 @@
--timeout 2200000
--reporter 'dist/driver/CheReporter.js'
-u tdd
--bail
--full-trace
--spec dist/tests/login/Login.spec.js
--spec dist/tests/e2e/DirectUrlFactoryWithKeepDirectoryTest.spec.js
--spec dist/tests/e2e/DirectUrlFactoryWithRootFolderTest.spec.js
--spec dist/tests/e2e/DirectUrlFactoryWithSpecificBranchTest.spec.js
--spec dist/tests/e2e/FactoryUrl.spec.js
--require source-map-support/register

View File

@ -1,7 +0,0 @@
--timeout 2200000
--reporter 'dist/driver/CheReporter.js'
-u tdd
--full-trace
--spec dist/tests/login/Login.spec.js
--spec dist/tests/plugins/*.spec.js
--require source-map-support/register

View File

@ -1,7 +0,0 @@
--timeout 2200000
--reporter 'dist/driver/CheReporter.js'
-u tdd
--bail
--full-trace
--spec dist/tests/e2e/OpenshiftConnector.spec.js
--require source-map-support/register

View File

@ -1,7 +0,0 @@
--timeout 2200000
--reporter 'dist/driver/CheReporter.js'
-u tdd
--full-trace
--spec dist/tests/login/Login.spec.js
--spec dist/tests/e2e_happy_path/DevWorkspaceHappyPath.spec.js
--require source-map-support/register

View File

@ -1,7 +0,0 @@
--timeout 2200000
--reporter 'dist/driver/CheReporter.js'
-u tdd
--full-trace
--spec dist/tests/login/Login.spec.js
--spec dist/tests/e2e/FactoryUrl.spec.js
--require source-map-support/register

View File

@ -1,7 +0,0 @@
--timeout 2200000
--reporter 'dist/driver/CheReporter.js'
-u tdd
--bail
--full-trace
--spec dist/tests/e2e/GitPublishBranch.spec.js
--require source-map-support/register

View File

@ -1,7 +0,0 @@
--timeout 2200000
--reporter 'dist/driver/CheReporter.js'
-u tdd
--bail
--full-trace
--spec dist/tests/e2e/GitSsh.spec.js
--require source-map-support/register

View File

@ -1,7 +0,0 @@
--timeout 2200000
--reporter 'dist/driver/CheReporter.js'
-u tdd
--bail
--full-trace
--spec dist/tests/e2e_happy_path/HappyPath.spec.js
--require source-map-support/register

View File

@ -1,7 +0,0 @@
--timeout 2200000
--reporter 'dist/driver/CheReporter.js'
-u tdd
--full-trace
--spec dist/tests/login/Login.spec.js
--spec dist/tests/devfiles/JavaVertx.spec.js
--require source-map-support/register

View File

@ -1,7 +0,0 @@
--timeout 2200000
--reporter 'dist/driver/CheReporter.js'
-u tdd
--bail
--full-trace
--spec dist/tests/load_test/LoadTest.spec
--require source-map-support/register

View File

@ -1,6 +0,0 @@
--timeout 2200000
--reporter 'dist/driver/CheReporter.js'
-u tdd
--full-trace
--bail
--require source-map-support/register

View File

@ -1,7 +0,0 @@
--timeout 2200000
--reporter 'dist/driver/CheReporter.js'
-u tdd
--bail
--full-trace
--spec dist/tests/e2e/WorkspaceCreationAndLsInitialization.spec.js
--require source-map-support/register

View File

@ -1,7 +0,0 @@
--timeout 1200000
-u tdd
--bail
--full-trace
--reporter './dist/driver/CheReporter.js'
--spec './dist/tests/login/Login.spec.js'
--spec './dist/tests/intelij/IntelijOpenWorkspace.spec.js'

View File

@ -1,6 +0,0 @@
--timeout 1200000
-u tdd
--bail
--full-trace
--reporter './dist/driver/CheReporter.js'
--spec './dist/tests/login/LinkCheAndOcpUsers.spec.js'

View File

@ -1,6 +0,0 @@
--timeout 1200000
--reporter 'dist/driver/CheReporter.js'
-u tdd
--bail
--full-trace
--spec dist/tests/e2e/*.spec.js

View File

@ -1,5 +0,0 @@
--timeout 1200000
-u tdd
--bail
--full-trace
--reporter './dist/driver/CheReporter.js'

File diff suppressed because it is too large Load Diff

View File

@ -1,58 +0,0 @@
{
"name": "e2e",
"version": "1.0.0",
"description": "",
"main": "dist/index.js",
"scripts": {
"cleanup-docker": "if [ $(docker ps -a | grep -c selenium-e2e) -gt 0 ]; then docker rm -f $(docker ps --filter \"name=selenium-e2e\" -aq); fi;",
"test-docker": "npm run cleanup-docker && docker run -it --shm-size=2g -p 5920:5920 --name selenium-e2e -e TS_SELENIUM_BASE_URL=$TS_SELENIUM_BASE_URL eclipse/che-e2e:nightly",
"test-docker-mount-e2e": "npm run cleanup-docker && docker run -it --shm-size=2g -p 5920:5920 --name selenium-e2e -e TS_SELENIUM_BASE_URL=$TS_SELENIUM_BASE_URL -v $(pwd):/tmp/e2e:Z eclipse/che-e2e:nightly",
"test": "./generateIndex.sh && npm run lint && npm run tsc && mocha --opts mocha.opts",
"load-test": "./generateIndex.sh && npm run lint && npm run tsc && mocha --opts mocha-load.opts",
"test-happy-path": "./generateIndex.sh && npm run lint && npm run tsc && mocha --opts mocha-happy-path.opts",
"test-devworkspace-happy-path": "./generateIndex.sh && npm run lint && npm run tsc && mocha --opts mocha-devworkspace-happy-path.opts",
"test-wkspc-creation-and-ls": "./generateIndex.sh && npm run lint && npm run tsc && mocha --opts mocha-wkspc-creation-and-ls.opts",
"test-java-vertx": "./generateIndex.sh && npm run lint && npm run tsc && mocha --opts mocha-java-vertx.opts",
"test-git-ssh": "./generateIndex.sh && npm run lint && npm run tsc && mocha --opts mocha-git-ssh.opts",
"test-git-publish-branch": "./generateIndex.sh && npm run lint && npm run tsc && mocha --opts mocha-git-publish-branch.opts",
"test-openshift-connector": "./generateIndex.sh && npm run lint && npm run tsc && mocha --opts mocha-connector.opts",
"test-all-devfiles": "./generateIndex.sh && ./initDevfileTests.sh",
"test-factory": "./generateIndex.sh && npm run lint && npm run tsc && mocha --opts mocha-factory.opts",
"test-all-factories": "./generateIndex.sh && npm run lint && npm run tsc && mocha --opts mocha-all-factories.opts",
"test-intelij": "tsc && mocha --opts mocha.intelij.opts",
"test-oauth": "tsc && mocha --opts mocha.ocp.link.opts",
"lint": "tslint --fix -p .",
"tsc": "tsc -p .",
"init-mocha-opts": "tsc && mocha --opts mocha-single-devfile.opts --spec dist/tests/login/Login.spec.js",
"test-plugin": "npm run init-mocha-opts -- --spec dist/tests/plugins/${USERSTORY}.spec.js",
"test-plugin-ci": "export TS_DELETE_PLUGINS_TEST_WORKSPACE=false && npm run init-mocha-opts -- --spec dist/tests/plugins/${USERSTORY}.spec.js",
"test-all-plugins": "tsc && mocha --opts mocha-all-plugins.opts"
},
"author": "Ihor Okhrimenko (iokhrime@redhat.com)",
"license": "ISC",
"devDependencies": {
"@types/chai": "4.1.7",
"@types/mocha": "5.2.6",
"@types/node": "11.13.4",
"@types/rimraf": "2.0.2",
"@types/selenium-webdriver": "3.0.16",
"axios": "0.21.1",
"chai": "4.2.0",
"chromedriver": "89.0.0",
"mocha": "7.1.1",
"rimraf": "2.6.2",
"selenium-webdriver": "3.6.0",
"ts-node": "8.0.3",
"tslint": "5.10.0",
"typed-rest-client": "1.2.0",
"typescript": "3.9.9"
},
"dependencies": {
"@eclipse-che/api": "7.5.0-SNAPSHOT",
"inversify": "5.0.1",
"reflect-metadata": "0.1.13"
},
"resolutions": {
"minimist": "^1.2.5"
}
}

View File

@ -1,58 +0,0 @@
/*********************************************************************
* Copyright (c) 2019 Red Hat, Inc.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/
import { injectable, inject } from 'inversify';
import { CLASSES } from '../../inversify.types';
import { DriverHelper } from '../../utils/DriverHelper';
import { By } from 'selenium-webdriver';
import { Logger } from '../../utils/Logger';
import { TimeoutConstants } from '../../TimeoutConstants';
@injectable()
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(`CreateWorkspace.waitTitleContains text: "${expectedText}"`);
const pageTitleLocator: By = By.xpath(`//h1[contains(text(), '${expectedText}')]`);
await this.driverHelper.waitVisibility(pageTitleLocator, timeout);
}
async waitPage(timeout: number = TimeoutConstants.TS_SELENIUM_LOAD_PAGE_TIMEOUT) {
Logger.debug('CreateWorkspace.waitPage');
await this.waitTitleContains('Create Workspace', timeout);
}
async waitSample(sampleName: string, timeout: number = TimeoutConstants.TS_COMMON_DASHBOARD_WAIT_TIMEOUT) {
Logger.debug(`CreateWorkspace.waitSample sampleName: "${sampleName}"`);
const sampleLocator: By = this.getSampleLocator(sampleName);
await this.driverHelper.waitVisibility(sampleLocator, timeout);
}
async clickOnSample(sampleName: string, timeout: number = TimeoutConstants.TS_CLICK_DASHBOARD_ITEM_TIMEOUT) {
Logger.debug(`CreateWorkspace.clickOnSample sampleName: "${sampleName}"`);
const sampleLocator: By = this.getSampleLocator(sampleName);
await this.driverHelper.waitAndClick(sampleLocator, timeout);
}
private getSampleLocator(sampleName: string): By {
Logger.trace(`CreateWorkspace.getSampleLocator sampleName: ${sampleName}`);
return By.xpath(`//article[contains(@class, 'sample-card')]//div[text()='${sampleName}']`);
}
}

View File

@ -1,114 +0,0 @@
/*********************************************************************
* Copyright (c) 2019 Red Hat, Inc.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/
import { inject, injectable } from 'inversify';
import 'reflect-metadata';
import { CLASSES } from '../../inversify.types';
import { By } from 'selenium-webdriver';
import { DriverHelper } from '../../utils/DriverHelper';
import { TestConstants } from '../../TestConstants';
import { TimeoutConstants } from '../../TimeoutConstants';
import { Workspaces } from './Workspaces';
import { Logger } from '../../utils/Logger';
@injectable()
export class Dashboard {
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';
constructor(@inject(CLASSES.DriverHelper) private readonly driverHelper: DriverHelper,
@inject(CLASSES.Workspaces) private readonly workspaces: Workspaces) { }
async stopWorkspaceByUI(workspaceName: string) {
Logger.debug(`Dashboard.stopWorkspaceByUI "${workspaceName}"`);
await this.openDashboard();
await this.clickWorkspacesButton();
await this.workspaces.waitPage();
await this.workspaces.waitWorkspaceListItem(workspaceName);
await this.workspaces.waitWorkspaceWithRunningStatus(workspaceName);
await this.workspaces.stopWorkspaceByActionsButton(workspaceName);
await this.workspaces.waitWorkspaceWithStoppedStatus(workspaceName);
}
async deleteWorkspaceByUI(workspaceName: string) {
Logger.debug(`Dashboard.deleteWorkspaceByUI "${workspaceName}"`);
await this.openDashboard();
await this.clickWorkspacesButton();
await this.workspaces.waitPage();
await this.workspaces.waitWorkspaceListItem(workspaceName);
await this.workspaces.deleteWorkspaceByActionsButton(workspaceName);
await this.workspaces.waitPage();
await this.workspaces.waitWorkspaceListItemAbcence(workspaceName);
}
async stopAndRemoveWorkspaceByUI(workspaceName: string) {
Logger.debug(`Dashboard.stopAndRemoveWorkspaceByUI "${workspaceName}"`);
await this.openDashboard();
await this.clickWorkspacesButton();
await this.workspaces.waitPage();
await this.workspaces.waitWorkspaceListItem(workspaceName);
await this.workspaces.waitWorkspaceWithRunningStatus(workspaceName);
await this.workspaces.stopWorkspaceByActionsButton(workspaceName);
await this.workspaces.waitWorkspaceWithStoppedStatus(workspaceName);
await this.workspaces.deleteWorkspaceByActionsButton(workspaceName);
await this.workspaces.waitWorkspaceListItemAbcence(workspaceName);
}
async openDashboard() {
Logger.debug('Dashboard.openDashboard');
await this.driverHelper.getDriver().navigate().to(TestConstants.TS_SELENIUM_BASE_URL);
await this.waitPage();
}
async waitPage(timeout: number = TimeoutConstants.TS_SELENIUM_LOAD_PAGE_TIMEOUT) {
Logger.debug('Dashboard.waitPage');
await this.driverHelper.waitVisibility(By.xpath(Dashboard.WORKSPACES_BUTTON_XPATH), timeout);
await this.driverHelper.waitVisibility(By.xpath(Dashboard.CREATE_WORKSPACE_BUTTON_XPATH), timeout);
}
async clickWorkspacesButton(timeout: number = TimeoutConstants.TS_CLICK_DASHBOARD_ITEM_TIMEOUT) {
Logger.debug('Dashboard.clickWorkspacesButton');
await this.driverHelper.waitAndClick(By.xpath(Dashboard.WORKSPACES_BUTTON_XPATH), timeout);
}
async clickCreateWorkspaceButton(timeout: number = TimeoutConstants.TS_CLICK_DASHBOARD_ITEM_TIMEOUT) {
Logger.debug('Dashboard.clickCreateWorkspaceButton');
await this.driverHelper.waitAndClick(By.xpath(Dashboard.CREATE_WORKSPACE_BUTTON_XPATH), timeout);
}
async waitLoader(timeout: number = TimeoutConstants.TS_WAIT_LOADER_PRESENCE_TIMEOUT) {
Logger.debug('Dashboard.waitLoader');
await this.driverHelper.waitVisibility(By.css(Dashboard.LOADER_PAGE_CSS), timeout);
}
async waitLoaderDisappearance(timeout: number = TimeoutConstants.TS_WAIT_LOADER_ABSENCE_TIMEOUT) {
Logger.debug('Dashboard.waitLoaderDisappearance');
await this.driverHelper.waitDisappearance(By.css(Dashboard.LOADER_PAGE_CSS), timeout);
}
async waitDisappearanceNavigationMenu(timeout: number = TimeoutConstants.TS_COMMON_DASHBOARD_WAIT_TIMEOUT) {
Logger.debug('Dashboard.waitDisappearanceNavigationMenu');
await this.driverHelper.waitDisappearance(By.id('chenavmenu'), timeout);
}
}

View File

@ -1,189 +0,0 @@
/*********************************************************************
* Copyright (c) 2019 Red Hat, Inc.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/
import { injectable, inject } from 'inversify';
import { DriverHelper } from '../../utils/DriverHelper';
import { CLASSES } from '../../inversify.types';
import { By } from 'selenium-webdriver';
import { Logger } from '../../utils/Logger';
import { TimeoutConstants } from '../../TimeoutConstants';
export enum WorkspaceStatusUI {
Running = 'green',
Stopped = 'grey'
}
@injectable()
export class Workspaces {
private static readonly ADD_WORKSPACE_BUTTON_XPATH: string = `//button[text()='Add Workspace']`;
constructor(@inject(CLASSES.DriverHelper) private readonly driverHelper: DriverHelper) { }
async waitPage(timeout: number = TimeoutConstants.TS_SELENIUM_LOAD_PAGE_TIMEOUT) {
Logger.debug('Workspaces.waitPage');
await this.driverHelper.waitVisibility(By.xpath(Workspaces.ADD_WORKSPACE_BUTTON_XPATH), timeout);
}
async clickAddWorkspaceButton(timeout: number = TimeoutConstants.TS_CLICK_DASHBOARD_ITEM_TIMEOUT) {
Logger.debug('Workspaces.clickAddWorkspaceButton');
await this.driverHelper.waitAndClick(By.xpath(Workspaces.ADD_WORKSPACE_BUTTON_XPATH), timeout);
}
async clickOpenButton(workspaceName: string, timeout: number = TimeoutConstants.TS_SELENIUM_LOAD_PAGE_TIMEOUT) {
Logger.debug('Workspaces.clickOpenButton');
await this.driverHelper.waitAndClick(this.getOpenButtonLocator(workspaceName), timeout);
}
async waitWorkspaceListItem(workspaceName: string, timeout: number = TimeoutConstants.TS_COMMON_DASHBOARD_WAIT_TIMEOUT) {
Logger.debug(`Workspaces.waitWorkspaceListItem "${workspaceName}"`);
const workspaceListItemLocator: By = By.xpath(this.getWorkspaceListItemLocator(workspaceName));
await this.driverHelper.waitVisibility(workspaceListItemLocator, timeout);
}
async waitWorkspaceWithRunningStatus(workspaceName: string, timeout: number = TimeoutConstants.TS_COMMON_DASHBOARD_WAIT_TIMEOUT) {
Logger.debug(`Workspaces.waitWorkspaceWithRunningStatus "${workspaceName}"`);
const runningStatusLocator: By = this.getWorkspaceStatusLocator(workspaceName, WorkspaceStatusUI.Running);
await this.driverHelper.waitVisibility(runningStatusLocator, timeout);
}
async waitWorkspaceWithStoppedStatus(workspaceName: string, timeout: number = TimeoutConstants.TS_DASHBOARD_WORKSPACE_STOP_TIMEOUT) {
Logger.debug(`Workspaces.waitWorkspaceWithStoppedStatus "${workspaceName}"`);
const stoppedStatusLocator: By = this.getWorkspaceStatusLocator(workspaceName, WorkspaceStatusUI.Stopped);
await this.driverHelper.waitVisibility(stoppedStatusLocator, timeout);
}
async clickWorkspaceListItem(workspaceName: string, timeout: number = TimeoutConstants.TS_CLICK_DASHBOARD_ITEM_TIMEOUT) {
Logger.debug(`Workspaces.clickWorkspaceListItem "${workspaceName}"`);
const workspaceListItemLocator: By = By.xpath(this.getWorkspaceListItemLocator(workspaceName));
await this.driverHelper.waitAndClick(workspaceListItemLocator, timeout);
}
async clickActionsButton(workspaceName: string) {
Logger.debug(`Workspaces.clickActionsButton of the '${workspaceName}' list item`);
await this.driverHelper.waitAndClick(this.getActionsLocator(workspaceName));
}
async waitActionsPopup(workspaceName: string, timeout: number = TimeoutConstants.TS_CONTEXT_MENU_TIMEOUT) {
Logger.debug(`Workspaces.waitActionsPopup of the '${workspaceName}' list item`);
await this.driverHelper.waitVisibility(this.getExpandedActionsLocator(workspaceName), timeout);
await this.driverHelper.wait(5000);
}
async openActionsPopup(workspaceName: string, timeout: number = TimeoutConstants.TS_CONTEXT_MENU_TIMEOUT) {
Logger.debug(`Workspaces.openActionsPopup for the '${workspaceName}' list item`);
await this.clickActionsButton(workspaceName);
await this.waitActionsPopup(workspaceName, timeout);
}
async clickActionsDeleteButton(workspaceName: string) {
Logger.debug(`Workspaces.clickActionsDeleteButton for the '${workspaceName}' list item`);
await this.driverHelper.waitAndClick(this.getActionsPopupButtonLocator(workspaceName, 'Delete Workspace'));
}
async clickActionsStopWorkspaceButton(workspaceName: string) {
Logger.debug(`Workspaces.clickActionsStopWorkspaceButton for the '${workspaceName}' list item`);
await this.driverHelper.waitAndClick(this.getActionsPopupButtonLocator(workspaceName, 'Stop Workspace'));
}
async waitDeleteWorkspaceConfirmationWindow(timeout: number = TimeoutConstants.TS_DASHBOARD_WORKSPACE_STOP_TIMEOUT) {
Logger.debug(`Workspaces.waitDeleteWorkspaceConfirmationWindow`);
const confirmationWindowLocator: By = By.xpath(`//div[@aria-label='Delete workspaces confirmation window']`);
await this.driverHelper.waitVisibility(confirmationWindowLocator, timeout);
await this.driverHelper.wait(5000);
}
async clickToDeleteConfirmationCheckbox(timeout: number = TimeoutConstants.TS_DASHBOARD_WORKSPACE_STOP_TIMEOUT) {
Logger.debug(`Workspaces.clickToDeleteConfirmationCheckbox`);
const deleteConfirmationCheckboxLocator: By = By.xpath(`//input[@data-testid='confirmation-checkbox']`);
await this.driverHelper.waitAndClick(deleteConfirmationCheckboxLocator, timeout);
}
async waitAndClickEnabledConfirmationWindowDeleteButton(timeout: number = TimeoutConstants.TS_DASHBOARD_WORKSPACE_STOP_TIMEOUT) {
Logger.debug(`Workspaces.waitEnabledConfirmationWindowDeleteButton`);
const enabledConfirmationWindowDeleteButton: By = By.xpath(`//button[@data-testid='delete-workspace-button' and not(@disabled)]`);
await this.driverHelper.waitAndClick(enabledConfirmationWindowDeleteButton, timeout);
}
async deleteWorkspaceByActionsButton(workspaceName: string, timeout: number = TimeoutConstants.TS_DASHBOARD_WORKSPACE_STOP_TIMEOUT) {
Logger.debug('Workspaces.deleteWorkspaceByActionsButton');
await this.waitWorkspaceListItem(workspaceName, timeout);
await this.openActionsPopup(workspaceName, timeout);
await this.clickActionsDeleteButton(workspaceName);
await this.waitDeleteWorkspaceConfirmationWindow(timeout);
await this.clickToDeleteConfirmationCheckbox(timeout);
await this.waitAndClickEnabledConfirmationWindowDeleteButton(timeout);
}
async stopWorkspaceByActionsButton(workspaceName: string, timeout: number = TimeoutConstants.TS_DASHBOARD_WORKSPACE_STOP_TIMEOUT) {
Logger.debug('Workspaces.stopWorkspaceByActionsButton');
await this.waitWorkspaceListItem(workspaceName, timeout);
await this.openActionsPopup(workspaceName, timeout);
await this.clickActionsStopWorkspaceButton(workspaceName);
}
async waitWorkspaceListItemAbcence(workspaceName: string, timeout: number = TimeoutConstants.TS_COMMON_DASHBOARD_WAIT_TIMEOUT) {
Logger.debug(`Workspaces.waitWorkspaceListItemAbcence "${workspaceName}"`);
const workspaceListItemLocator: By = By.xpath(this.getWorkspaceListItemLocator(workspaceName));
await this.driverHelper.waitDisappearance(workspaceListItemLocator, timeout);
}
private getWorkspaceListItemLocator(workspaceName: string): string {
return `//tr[td/span/a[text()='${workspaceName}']]`;
}
private getWorkspaceStatusLocator(workspaceName: string, workspaceStatus: WorkspaceStatusUI): By {
return By.xpath(`${this.getWorkspaceListItemLocator(workspaceName)}//span[@data-testid='workspace-status-indicator']//*[local-name()='svg' and @fill='${workspaceStatus}']`);
}
private getActionsLocator(workspaceName: string): By {
return By.xpath(`${this.getWorkspaceListItemLocator(workspaceName)}/td/div/button[@aria-label='Actions']`);
}
private getExpandedActionsLocator(workspaceName: string): By {
return By.xpath(`${this.getWorkspaceListItemLocator(workspaceName)}//button[@aria-label='Actions' and @aria-expanded='true']`);
}
private getActionsPopupButtonLocator(workspaceName: string, buttonText: string): By {
return By.xpath(`${this.getWorkspaceListItemLocator(workspaceName)}//li[@role='menuitem']//button[text()='${buttonText}']`);
}
private getOpenButtonLocator(workspaceName: string) {
return By.xpath(`${this.getWorkspaceListItemLocator(workspaceName)}//td[@data-key=5]//a[text()='Open']`);
}
}

View File

@ -1,153 +0,0 @@
/*********************************************************************
* Copyright (c) 2019 Red Hat, Inc.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/
import { DriverHelper } from '../../../utils/DriverHelper';
import { injectable, inject } from 'inversify';
import { CLASSES, TYPES } from '../../../inversify.types';
import 'reflect-metadata';
import { TestConstants } from '../../../TestConstants';
import { By } from 'selenium-webdriver';
import { Ide } from '../../ide/Ide';
import { ITestWorkspaceUtil } from '../../../utils/workspace/ITestWorkspaceUtil';
import { WorkspaceStatus } from '../../../utils/workspace/WorkspaceStatus';
import { Logger } from '../../../utils/Logger';
import { TimeoutConstants } from '../../../TimeoutConstants';
@injectable()
export class WorkspaceDetails {
private static readonly RUN_BUTTON_CSS: string = '#run-workspace-button[che-button-title=\'Run\']';
private static readonly OPEN_BUTTON_CSS: string = '#open-in-ide-button[che-button-title=\'Open\']';
private static readonly SAVE_BUTTON_CSS: string = 'button[name=\'save-button\']';
private static readonly ENABLED_SAVE_BUTTON_CSS: string = 'button[name=\'save-button\'][aria-disabled=\'false\']';
private static readonly WORKSPACE_DETAILS_LOADER_CSS: string = 'workspace-details-overview md-progress-linear';
constructor(@inject(CLASSES.DriverHelper) private readonly driverHelper: DriverHelper,
@inject(TYPES.WorkspaceUtil) private readonly testWorkspaceUtil: ITestWorkspaceUtil) { }
async waitLoaderDisappearance(attempts: number = TestConstants.TS_SELENIUM_DEFAULT_ATTEMPTS, polling: number = TestConstants.TS_SELENIUM_DEFAULT_POLLING) {
Logger.debug('WorkspaceDetails.waitLoaderDisappearance');
await this.driverHelper.waitDisappearance(By.css(WorkspaceDetails.WORKSPACE_DETAILS_LOADER_CSS), attempts, polling);
}
async saveChanges() {
Logger.debug('WorkspaceDetails.saveChanges');
await this.waitSaveButton();
await this.clickOnSaveButton();
await this.waitSaveButtonDisappearance();
}
async waitPage(workspaceName: string, timeout: number = TimeoutConstants.TS_SELENIUM_LOAD_PAGE_TIMEOUT) {
Logger.debug(`WorkspaceDetails.saveChanges workspace: "${workspaceName}"`);
await this.waitWorkspaceTitle(workspaceName, timeout);
await this.waitOpenButton(timeout);
await this.waitRunButton(timeout);
await this.waitTabsPresence(timeout);
await this.waitLoaderDisappearance(timeout);
}
async waitWorkspaceTitle(workspaceName: string, timeout: number = TimeoutConstants.TS_COMMON_DASHBOARD_WAIT_TIMEOUT) {
Logger.debug(`WorkspaceDetails.waitWorkspaceTitle title: "${workspaceName}"`);
const workspaceTitleLocator: By = By.css(this.getWorkspaceTitleCssLocator(workspaceName));
await this.driverHelper.waitVisibility(workspaceTitleLocator, timeout);
}
async waitRunButton(timeout: number = TimeoutConstants.TS_COMMON_DASHBOARD_WAIT_TIMEOUT) {
Logger.debug('WorkspaceDetails.waitRunButton');
await this.driverHelper.waitVisibility(By.css(WorkspaceDetails.RUN_BUTTON_CSS), timeout);
}
async clickOnRunButton(timeout: number = TimeoutConstants.TS_CLICK_DASHBOARD_ITEM_TIMEOUT) {
Logger.debug('WorkspaceDetails.clickOnRunButton');
await this.driverHelper.waitAndClick(By.css(WorkspaceDetails.RUN_BUTTON_CSS), timeout);
}
async waitOpenButton(timeout: number = TimeoutConstants.TS_COMMON_DASHBOARD_WAIT_TIMEOUT) {
Logger.debug('WorkspaceDetails.waitOpenButton');
await this.driverHelper.waitVisibility(By.css(WorkspaceDetails.OPEN_BUTTON_CSS), timeout);
}
async openWorkspace(namespace: string, workspaceName: string, timeout: number = TimeoutConstants.TS_SELENIUM_LOAD_PAGE_TIMEOUT) {
Logger.debug(`WorkspaceDetails.openWorkspace "${namespace}/${workspaceName}"`);
await this.clickOnOpenButton(timeout);
await this.driverHelper.waitVisibility(By.css(Ide.ACTIVATED_IDE_IFRAME_CSS), TimeoutConstants.TS_COMMON_DASHBOARD_WAIT_TIMEOUT);
await this.testWorkspaceUtil.waitWorkspaceStatus(namespace, workspaceName, WorkspaceStatus.STARTING);
}
async waitTabsPresence(timeout: number = TimeoutConstants.TS_COMMON_DASHBOARD_WAIT_TIMEOUT) {
Logger.debug('WorkspaceDetails.waitTabsPresence');
const workspaceDetailsTabs: Array<string> = ['Overview', 'Projects', 'Containers', 'Servers',
'Env Variables', 'Volumes', 'Config', 'SSH', 'Plugins', 'Editors'];
for (const tabTitle of workspaceDetailsTabs) {
const workspaceDetailsTabLocator: By = By.xpath(this.getTabXpathLocator(tabTitle));
await this.driverHelper.waitVisibility(workspaceDetailsTabLocator, timeout);
}
}
async selectTab(tabTitle: string, timeout: number = TimeoutConstants.TS_COMMON_DASHBOARD_WAIT_TIMEOUT) {
Logger.debug(`WorkspaceDetails.selectTab ${tabTitle}`);
await this.clickOnTab(tabTitle, timeout);
await this.waitTabSelected(tabTitle, timeout);
}
private getWorkspaceTitleCssLocator(workspaceName: string): string {
return `che-row-toolbar[che-title='${workspaceName}']`;
}
private getTabXpathLocator(tabTitle: string): string {
return `//md-tabs-canvas//md-tab-item//span[text()='${tabTitle}']`;
}
private getSelectedTabXpathLocator(tabTitle: string): string {
return `//md-tabs-canvas[@role='tablist']//md-tab-item[@aria-selected='true']//span[text()='${tabTitle}']`;
}
private async waitSaveButton(timeout: number = TimeoutConstants.TS_COMMON_DASHBOARD_WAIT_TIMEOUT) {
await this.driverHelper.waitVisibility(By.css(WorkspaceDetails.ENABLED_SAVE_BUTTON_CSS), timeout);
}
private async waitSaveButtonDisappearance(attempts: number = TestConstants.TS_SELENIUM_DEFAULT_ATTEMPTS, polling: number = TestConstants.TS_SELENIUM_DEFAULT_POLLING) {
await this.driverHelper.waitDisappearance(By.css(WorkspaceDetails.SAVE_BUTTON_CSS), attempts, polling);
}
private async clickOnSaveButton(timeout: number = TimeoutConstants.TS_CLICK_DASHBOARD_ITEM_TIMEOUT) {
await this.driverHelper.waitAndClick(By.css(WorkspaceDetails.ENABLED_SAVE_BUTTON_CSS), timeout);
}
private async clickOnOpenButton(timeout: number = TimeoutConstants.TS_CLICK_DASHBOARD_ITEM_TIMEOUT) {
await this.driverHelper.waitAndClick(By.css(WorkspaceDetails.OPEN_BUTTON_CSS), timeout);
}
private async clickOnTab(tabTitle: string, timeout: number = TimeoutConstants.TS_CLICK_DASHBOARD_ITEM_TIMEOUT) {
const workspaceDetailsTabLocator: By = By.xpath(this.getTabXpathLocator(tabTitle));
await this.driverHelper.waitAndClick(workspaceDetailsTabLocator, timeout);
}
private async waitTabSelected(tabTitle: string, timeout: number = TimeoutConstants.TS_COMMON_DASHBOARD_WAIT_TIMEOUT) {
const selectedTabLocator: By = By.xpath(this.getSelectedTabXpathLocator(tabTitle));
await this.driverHelper.waitVisibility(selectedTabLocator, timeout);
}
}

View File

@ -1,96 +0,0 @@
/*********************************************************************
* Copyright (c) 2019 Red Hat, Inc.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/
import { DriverHelper } from '../../../utils/DriverHelper';
import { injectable, inject } from 'inversify';
import 'reflect-metadata';
import { CLASSES, TYPES } from '../../../inversify.types';
import { By } from 'selenium-webdriver';
import { WorkspaceDetails } from './WorkspaceDetails';
import { ITestWorkspaceUtil } from '../../../utils/workspace/ITestWorkspaceUtil';
import { WorkspaceStatus } from '../../../utils/workspace/WorkspaceStatus';
import { Logger } from '../../../utils/Logger';
import { TimeoutConstants } from '../../../TimeoutConstants';
@injectable()
export class WorkspaceDetailsPlugins {
constructor(@inject(CLASSES.DriverHelper) private readonly driverHelper: DriverHelper,
@inject(CLASSES.WorkspaceDetails) private readonly workspaceDetails: WorkspaceDetails,
@inject(TYPES.WorkspaceUtil) private readonly testWorkspaceUtil: ITestWorkspaceUtil) { }
async waitPluginListItem(pluginName: string) {
Logger.debug(`WorkspaceDetailsPlugins.waitPluginListItem ${pluginName}`);
const pluginListItemLocator: By = By.css(this.getPluginListItemCssLocator(pluginName));
await this.driverHelper.waitVisibility(pluginListItemLocator, TimeoutConstants.TS_COMMON_DASHBOARD_WAIT_TIMEOUT);
}
async enablePlugin(pluginName: string, pluginVersion?: string) {
Logger.debug(`WorkspaceDetailsPlugins.enablePlugin ${pluginName}:${pluginVersion}`);
await this.waitPluginDisabling(pluginName, pluginVersion);
await this.clickOnPluginListItemSwitcher(pluginName, pluginVersion);
await this.waitPluginEnabling(pluginName, pluginVersion);
}
async disablePlugin(pluginName: string, pluginVersion?: string) {
Logger.debug(`WorkspaceDetailsPlugins.disablePlugin ${pluginName}:${pluginVersion}`);
await this.waitPluginEnabling(pluginName, pluginVersion);
await this.clickOnPluginListItemSwitcher(pluginName, pluginVersion);
await this.waitPluginDisabling(pluginName, pluginVersion);
}
async addPluginAndOpenWorkspace(namespace: string, workspaceName: string, pluginName: string, pluginId: string, pluginVersion?: string) {
Logger.debug(`WorkspaceDetailsPlugins.addPluginAndOpenWorkspace ${namespace}/${workspaceName} plugin: ${pluginName}:${pluginVersion}`);
await this.workspaceDetails.selectTab('Plugins');
await this.enablePlugin(pluginName, pluginVersion);
await this.workspaceDetails.saveChanges();
await this.workspaceDetails.openWorkspace(namespace, workspaceName);
await this.testWorkspaceUtil.waitWorkspaceStatus(namespace, workspaceName, WorkspaceStatus.RUNNING);
await this.testWorkspaceUtil.waitPluginAdding(namespace, workspaceName, pluginId);
}
private getPluginListItemCssLocator(pluginName: string, pluginVersion?: string): string {
if (pluginVersion) {
return `.plugin-item div[plugin-item-name*='${pluginName}'][plugin-item-version='${pluginVersion}']`;
}
return `.plugin-item div[plugin-item-name*='${pluginName}']`;
}
private getPluginListItemSwitcherCssLocator(pluginName: string, pluginVersion?: string): string {
return `${this.getPluginListItemCssLocator(pluginName, pluginVersion)} md-switch`;
}
private async clickOnPluginListItemSwitcher(pluginName: string,
pluginVersion?: string,
timeout: number = TimeoutConstants.TS_CLICK_DASHBOARD_ITEM_TIMEOUT) {
const pluginListItemSwitcherLocator = By.css(this.getPluginListItemSwitcherCssLocator(pluginName, pluginVersion));
await this.driverHelper.waitAndClick(pluginListItemSwitcherLocator, timeout);
}
private async waitPluginEnabling(pluginName: string, pluginVersion?: string, timeout: number = TimeoutConstants.TS_COMMON_DASHBOARD_WAIT_TIMEOUT) {
const enabledPluginSwitcherLocator: By = By.css(`${this.getPluginListItemCssLocator(pluginName, pluginVersion)} md-switch[aria-checked='true']`);
await this.driverHelper.waitVisibility(enabledPluginSwitcherLocator, timeout);
}
private async waitPluginDisabling(pluginName: string, pluginVersion?: string, timeout: number = TimeoutConstants.TS_COMMON_DASHBOARD_WAIT_TIMEOUT) {
const disabledPluginSwitcherLocator: By = By.css(`${this.getPluginListItemCssLocator(pluginName, pluginVersion)} md-switch[aria-checked='false']`);
await this.driverHelper.waitVisibility(disabledPluginSwitcherLocator, timeout);
}
}

View File

@ -1,47 +0,0 @@
import 'reflect-metadata';
import { injectable, inject } from 'inversify';
import { DriverHelper } from '../../utils/DriverHelper';
import { CLASSES } from '../../inversify.types';
import { WebElement, Button, By, Key } from 'selenium-webdriver';
import { Logger } from '../../utils/Logger';
import { TimeoutConstants } from '../../TimeoutConstants';
@injectable()
export class ContextMenu {
private static readonly SUGGESTION_WIDGET_BODY_CSS: string = 'ul.p-Menu-content';
constructor(@inject(CLASSES.DriverHelper) private readonly driverHelper: DriverHelper) { }
async invokeContextMenuOnTheElementWithMouse(elementLocator: By) {
Logger.debug(`ContextMenu.invokeContextMenuOnTheElementWithMouse ${elementLocator}`);
const webElement: WebElement = await this.driverHelper.waitVisibility(elementLocator, TimeoutConstants.TS_CONTEXT_MENU_TIMEOUT);
await this.driverHelper.getAction().click(webElement, Button.RIGHT).perform();
this.waitContextMenu();
}
async invokeContextMenuOnActiveElementWithKeys() {
Logger.debug('ContextMenu.invokeContextMenuOnActiveElementWithKeys');
this.driverHelper.getDriver().switchTo().activeElement().sendKeys(Key.SHIFT + Key.F10);
this.waitContextMenu();
}
async waitContextMenuAndClickOnItem(nameOfItem: string) {
Logger.debug(`ContextMenu.waitContextMenuAndClickOnItem "${nameOfItem}"`);
const itemLocator: string = `//div[@class='p-Menu-itemLabel' and text()='${nameOfItem}']`;
await this.waitContextMenu();
await this.driverHelper.waitAndClick(By.xpath(itemLocator), TimeoutConstants.TS_CONTEXT_MENU_TIMEOUT);
}
async waitContextMenu() {
Logger.debug(`ContextMenu.waitContextMenu`);
await this.driverHelper.waitVisibility(By.css(ContextMenu.SUGGESTION_WIDGET_BODY_CSS), TimeoutConstants.TS_CONTEXT_MENU_TIMEOUT);
}
}

View File

@ -1,85 +0,0 @@
/*********************************************************************
* Copyright (c) 2019 Red Hat, Inc.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/
import { inject, injectable } from 'inversify';
import { CLASSES } from '../../inversify.types';
import { TestConstants } from '../../TestConstants';
import { DriverHelper } from '../../utils/DriverHelper';
import { By, Key, WebElement, error } from 'selenium-webdriver';
import { Ide } from './Ide';
import { Logger } from '../../utils/Logger';
import { TimeoutConstants } from '../../TimeoutConstants';
@injectable()
export class DebugView {
constructor(@inject(CLASSES.DriverHelper) private readonly driverHelper: DriverHelper,
@inject(CLASSES.Ide) private readonly ide: Ide) { }
async clickOnDebugConfigurationDropDown() {
Logger.debug('DebugView.clickOnDebugConfigurationDropDown');
await this.driverHelper.waitAndClick(By.css('select.debug-configuration'));
}
async clickOnDebugConfigurationItem(itemText: string) {
Logger.debug(`DebugView.clickOnDebugConfigurationItem "${itemText}"`);
const configurationItemLocator: By = By.xpath(`//select[contains(@class,'debug-configuration')]//option[text()=\'${itemText}\']`);
await this.driverHelper.waitAndClick(configurationItemLocator);
await this.ide.performKeyCombination(Key.ESCAPE);
}
async clickOnRunDebugButton() {
Logger.debug('DebugView.clickOnRunDebugButton');
const runDebugButtonLocator: By = By.xpath('//span[@title=\'Start Debugging\']');
await this.driverHelper.waitAndClick(runDebugButtonLocator, TimeoutConstants.TS_DIALOG_WINDOW_DEFAULT_TIMEOUT);
}
/**
* Waits for number of threads in "Threads" view to be more than 1 - this should mean that the debugger is connected.
*
* @param timeout
*/
async waitForDebuggerToConnect(timeout: number = TimeoutConstants.TS_DEBUGGER_CONNECTION_TIMEOUT) {
await this.driverHelper.getDriver().wait(async () => {
Logger.debug(`Waiting for debugger to connect (threads to appear in "Threads" view)`);
const threadsTreeLocator = `//div[contains(@class, 'theia-debug-thread')]`;
try {
const threadElements: WebElement[] = await this.driverHelper.waitAllPresence(By.xpath(threadsTreeLocator));
if (threadElements.length > 1) {
return true;
}
} catch (err) {
if (!(err instanceof error.TimeoutError)) {
throw err;
}
return await this.driverHelper.wait(TestConstants.TS_SELENIUM_DEFAULT_POLLING);
}
}, timeout);
}
/**
* Click on "Threads" view title.
*/
async clickOnThreadsViewTitle() {
Logger.debug(`Click on "Threads" view title`);
const threadsViewTitleLocator: By = By.xpath('//div[@id="debug:view-container:-1--debug:threads:-1"]/*/span[@title="Threads"]');
await this.driverHelper.waitAndClick(threadsViewTitleLocator);
}
}

View File

@ -1,100 +0,0 @@
/*********************************************************************
* Copyright (c) 2019 Red Hat, Inc.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/
import { injectable, inject } from 'inversify';
import { CLASSES } from '../../inversify.types';
import { DriverHelper } from '../../utils/DriverHelper';
import { By } from 'selenium-webdriver';
import { Logger } from '../../utils/Logger';
import { Ide } from './Ide';
import { TimeoutConstants } from '../../TimeoutConstants';
@injectable()
export class DialogWindow {
private static readonly DIALOG_BODY_XPATH_LOCATOR: string = '//div[@id=\'theia-dialog-shell\']//div[@class=\'dialogBlock\']';
private static readonly CLOSE_BUTTON_XPATH_LOCATOR: string = `${DialogWindow.DIALOG_BODY_XPATH_LOCATOR}//button[text()='close']`;
constructor(@inject(CLASSES.DriverHelper) private readonly driverHelper: DriverHelper,
@inject(CLASSES.Ide) private readonly ide: Ide) { }
async dialogDisplayes(): Promise<boolean> {
Logger.debug('DialogWindow.dialogDisplayes');
return await this.driverHelper.isVisible(By.xpath(DialogWindow.DIALOG_BODY_XPATH_LOCATOR));
}
async waitAndCloseIfAppear() {
Logger.debug('DialogWindow.waitAndCloseIfAppear');
const dialogDisplayes: boolean = await this.driverHelper.waitVisibilityBoolean(By.xpath(DialogWindow.DIALOG_BODY_XPATH_LOCATOR));
if (dialogDisplayes) {
await this.closeDialog();
await this.waitDialogDissappearance();
}
}
async clickToButton(buttonText: string) {
Logger.debug('DialogWindow.clickToButton');
const buttonLocator: By = By.xpath(`${DialogWindow.DIALOG_BODY_XPATH_LOCATOR}//button[text()='${buttonText}']`);
await this.driverHelper.waitAndClick(buttonLocator, TimeoutConstants.TS_DIALOG_WINDOW_DEFAULT_TIMEOUT);
}
async closeDialog() {
Logger.debug('DialogWindow.closeDialog');
await this.clickToButton('close');
}
async clickToOpenLinkButton() {
Logger.debug('DialogWindow.clickToOpenLinkButton');
await this.clickToButton('Open Link');
}
async waitDialog(dialogText: string = '', timeout: number = TimeoutConstants.TS_DIALOG_WINDOW_DEFAULT_TIMEOUT) {
Logger.debug('DialogWindow.waitDialog');
// if dialog text is provided uses xpath with this text
// if not uses window body xpath
const dialogWithTextXpathLocator: string = `${DialogWindow.DIALOG_BODY_XPATH_LOCATOR}//*[contains(text(), '${dialogText}')]`;
const dialogXpathLocator: string = (dialogText ? dialogWithTextXpathLocator : DialogWindow.DIALOG_BODY_XPATH_LOCATOR);
await this.driverHelper.waitVisibility(By.xpath(dialogXpathLocator), timeout);
}
async waitDialogAndOpenLink(dialogText: string = '', applicationReaddyTimeout: number) {
Logger.debug('DialogWindow.waitDialogAndOpenLink');
await this.waitDialog(dialogText, applicationReaddyTimeout);
await this.ide.waitApllicationIsReady(await this.getApplicationUrlFromDialog(dialogText), applicationReaddyTimeout);
await this.clickToOpenLinkButton();
await this.waitDialogDissappearance();
}
async waitDialogDissappearance() {
Logger.debug('DialogWindow.waitDialogDissappearance');
await this.driverHelper.waitDisappearanceWithTimeout(By.xpath(DialogWindow.CLOSE_BUTTON_XPATH_LOCATOR), TimeoutConstants.TS_DIALOG_WINDOW_DEFAULT_TIMEOUT);
}
async getApplicationUrlFromDialog(dialogWindowText: string) {
const notificationTextLocator: By = By.xpath(`${DialogWindow.DIALOG_BODY_XPATH_LOCATOR}//*[contains(text(), '${dialogWindowText}')]`);
let dialogWindow = await this.driverHelper.waitAndGetText(notificationTextLocator);
let regexp: RegExp = new RegExp('^.*(https?://.*)$');
if (!regexp.test(dialogWindow)) {
throw new Error('Cannot obtaine url from notification message');
}
return dialogWindow.split(regexp)[1];
}
}

View File

@ -1,581 +0,0 @@
/*********************************************************************
* Copyright (c) 2019 Red Hat, Inc.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/
import 'reflect-metadata';
import { injectable, inject } from 'inversify';
import { DriverHelper } from '../../utils/DriverHelper';
import { CLASSES } from '../../inversify.types';
import { TestConstants } from '../../TestConstants';
import { By, Key, error, ActionSequence, Button } from 'selenium-webdriver';
import { Logger } from '../../utils/Logger';
import { TimeoutConstants } from '../../TimeoutConstants';
@injectable()
export class Editor {
private static readonly SUGGESTION_WIDGET_BODY_CSS: string = 'div.visible[widgetId=\'editor.widget.suggestWidget\']';
private static readonly SUGGESTION_LOADING_XPATH: string = '//div[@widgetid=\'editor.widget.suggestWidget\']//div[@class=\'message\' and contains(.,\'Loading...\')]';
private static readonly ADDITIONAL_SHIFTING_TO_Y: number = 19;
private static readonly ADDITIONAL_SHIFTING_TO_X: number = 1;
constructor(@inject(CLASSES.DriverHelper) private readonly driverHelper: DriverHelper) { }
public async waitSuggestionContainer(timeout: number = TimeoutConstants.TS_SUGGESTION_TIMEOUT) {
Logger.debug('Editor.waitSuggestionContainer');
await this.driverHelper.waitVisibility(By.css(Editor.SUGGESTION_WIDGET_BODY_CSS), timeout);
}
public async waitSuggestionContainerClosed(timeout: number = TimeoutConstants.TS_SUGGESTION_TIMEOUT) {
Logger.debug('Editor.waitSuggestionContainerClosed');
await this.driverHelper.waitDisappearanceWithTimeout(By.css(Editor.SUGGESTION_WIDGET_BODY_CSS), timeout);
}
public async waitSuggestion(editorTabTitle: string,
suggestionText: string,
timeout: number = TimeoutConstants.TS_SUGGESTION_TIMEOUT,
lineNumber?: number,
charNumber?: number) {
const charInLineNumber: number = (charNumber ? charNumber : 1);
// if line defined the method sets cursor to line and char
// before invoking suggestion container and repeat this
// cycle if suggestion didn't display
if (lineNumber) {
await this.waitSuggestionWithResettingCursor(editorTabTitle, suggestionText, timeout, lineNumber, charInLineNumber);
return;
}
// if line not defined the method just invoke suggestion container
// without setting cursor to line and char and repeat this
// cycle if suggestion didn't display
await this.waitSuggestionWithoutResettingCursor(editorTabTitle, suggestionText, timeout);
}
public async closeSuggestionContainer(editorTabTitle: string, timeout: number = TimeoutConstants.TS_SUGGESTION_TIMEOUT) {
Logger.debug(`Editor.closeSuggestionContainer tabTitle: "${editorTabTitle}"`);
await this.driverHelper.getDriver().wait(async () => {
// if container already closed stop the method execution
try {
// for avoiding problem when the inner timeout
// bigger than timeout of the method
const suggestionContainerTimeout: number = timeout / 2;
await this.waitSuggestionContainer(suggestionContainerTimeout);
} catch (err) {
if (err instanceof error.TimeoutError) {
return true;
}
throw err;
}
// try to close container
try {
await this.pressEscapeButton(editorTabTitle);
await this.waitSuggestionContainerClosed(2000);
return true;
} catch (err) {
if (!(err instanceof error.TimeoutError)) {
throw err;
}
}
}, timeout);
}
public async waitSuggestionWithScrolling(editorTabTitle: string,
suggestionText: string,
timeout: number = TimeoutConstants.TS_SUGGESTION_TIMEOUT) {
Logger.debug(`Editor.waitSuggestion tabTitle: "${editorTabTitle}" suggestion: "${suggestionText}"`);
const suggestionLocator: By = this.getSuggestionLineXpathLocator(suggestionText);
await this.driverHelper.getDriver().wait(async () => {
try {
await this.scrollAndSearchSuggestion(editorTabTitle, suggestionLocator, timeout / 3);
return true;
} catch (err) {
if (!(err instanceof error.TimeoutError)) {
throw err;
}
await this.closeSuggestionContainer(editorTabTitle, TimeoutConstants.TS_CLOSE_SUGGESTION_CONTAINER_TIMEOUT);
await this.pressControlSpaceCombination(editorTabTitle);
}
}, timeout);
}
public async pressControlSpaceCombination(editorTabTitle: string) {
Logger.debug(`Editor.pressControlSpaceCombination "${editorTabTitle}"`);
await this.performKeyCombination(editorTabTitle, Key.chord(Key.CONTROL, Key.SPACE));
}
public async pressEscapeButton(editorTabTitle: string) {
Logger.debug(`Editor.pressEscapeButton "${editorTabTitle}"`);
await this.performKeyCombination(editorTabTitle, Key.ESCAPE);
}
public async clickOnSuggestion(suggestionText: string, timeout: number = TimeoutConstants.TS_SUGGESTION_TIMEOUT) {
Logger.debug(`Editor.clickOnSuggestion "${suggestionText}"`);
await this.driverHelper.waitAndClick(this.getSuggestionLineXpathLocator(suggestionText), timeout);
}
public async waitTab(tabTitle: string, timeout: number = TimeoutConstants.TS_EDITOR_TAB_INTERACTION_TIMEOUT) {
Logger.debug(`Editor.waitTab "${tabTitle}"`);
await this.driverHelper.waitVisibility(By.xpath(this.getTabXpathLocator(tabTitle)), timeout);
}
public async waitTabDisappearance(tabTitle: string,
attempt: number = TestConstants.TS_SELENIUM_DEFAULT_ATTEMPTS,
polling: number = TestConstants.TS_SELENIUM_DEFAULT_POLLING) {
Logger.debug(`Editor.waitTabDisappearance "${tabTitle}"`);
await this.driverHelper.waitDisappearance(By.xpath(this.getTabXpathLocator(tabTitle)), attempt, polling);
}
public async clickOnTab(tabTitle: string, timeout: number = TimeoutConstants.TS_EDITOR_TAB_INTERACTION_TIMEOUT) {
Logger.debug(`Editor.clickOnTab "${tabTitle}"`);
await this.driverHelper.waitAndClick(By.xpath(this.getTabXpathLocator(tabTitle)), timeout);
}
public async waitTabFocused(tabTitle: string, timeout: number = TimeoutConstants.TS_EDITOR_TAB_INTERACTION_TIMEOUT) {
Logger.debug(`Editor.waitTabFocused "${tabTitle}"`);
const focusedTabLocator: By = By.xpath(`//li[contains(@class, 'p-TabBar-tab') and contains(@class, 'theia-mod-active')]//div[text()='${tabTitle}']`);
await this.driverHelper.waitVisibility(focusedTabLocator, timeout);
}
public async selectTab(tabTitle: string) {
Logger.debug(`Editor.selectTab "${tabTitle}"`);
await this.waitTab(tabTitle);
await this.clickOnTab(tabTitle);
await this.waitTabFocused(tabTitle);
}
async closeTab(tabTitle: string, timeout: number = TimeoutConstants.TS_EDITOR_TAB_INTERACTION_TIMEOUT) {
Logger.debug(`Editor.closeTab "${tabTitle}"`);
const tabCloseButtonLocator: By = By.xpath(`//div[text()='${tabTitle}']/parent::li//div[contains(@class, 'p-TabBar-tabCloseIcon')]`);
await this.driverHelper.waitAndClick(tabCloseButtonLocator, timeout);
}
async waitTabWithUnsavedStatus(tabTitle: string, timeout: number = TimeoutConstants.TS_EDITOR_TAB_INTERACTION_TIMEOUT) {
Logger.debug(`Editor.waitTabWithUnsavedStatus "${tabTitle}"`);
const unsavedTabLocator: By = this.getTabWithUnsavedStatus(tabTitle);
await this.driverHelper.waitVisibility(unsavedTabLocator, timeout);
}
async waitTabWithSavedStatus(tabTitle: string, timeout: number = TimeoutConstants.TS_EDITOR_TAB_INTERACTION_TIMEOUT) {
Logger.debug(`Editor.waitTabWithSavedStatus "${tabTitle}"`);
const unsavedTabLocator: By = this.getTabWithUnsavedStatus(tabTitle);
await this.driverHelper.getDriver().wait(async () => {
try {
await this.driverHelper.waitDisappearanceWithTimeout(unsavedTabLocator, TestConstants.TS_SELENIUM_DEFAULT_POLLING);
await this.waitTab(tabTitle, timeout);
return true;
} catch (err) {
if (!(err instanceof error.TimeoutError)) {
throw err;
}
console.log(`The editor tab with title "${tabTitle}" has unsaved status, wait once again`);
}
}, timeout);
}
async waitEditorOpened(editorTabTitle: string, timeout: number = TimeoutConstants.TS_EDITOR_TAB_INTERACTION_TIMEOUT) {
Logger.debug(`Editor.waitEditorOpened "${editorTabTitle}"`);
const firstEditorLineLocator: By = By.xpath(this.getEditorLineXpathLocator(1));
await this.driverHelper.waitPresence(this.getEditorBodyLocator(editorTabTitle), timeout);
await this.driverHelper.waitPresence(firstEditorLineLocator, timeout);
}
async waitEditorAvailable(tabTitle: string, timeout: number = TimeoutConstants.TS_EDITOR_TAB_INTERACTION_TIMEOUT) {
Logger.debug(`Editor.waitEditorAvailable "${tabTitle}"`);
await this.waitTab(tabTitle, timeout);
await this.waitEditorOpened(tabTitle, timeout);
}
async getLineText(tabTitle: string, lineNumber: number): Promise<string> {
Logger.debug(`Editor.getLineText "${tabTitle}"`);
const lineIndex: number = lineNumber - 1;
const editorText: string = await this.getEditorVisibleText(tabTitle);
const editorLines: string[] = editorText.split('\n');
const editorLine = editorLines[lineIndex] + '\n';
return editorLine;
}
async getEditorVisibleText(tabTitle: string): Promise<string> {
Logger.debug(`Editor.getEditorVisibleText "${tabTitle}"`);
const editorBodyLocator: By = By.xpath(`//div[contains(@data-uri, \'${tabTitle}')]//div[@class=\'view-lines\']`);
// const editorBodyLocator: By = By.xpath('//div[@class=\'view-lines\']');
const editorText: string = await this.driverHelper.waitAndGetText(editorBodyLocator);
return editorText;
}
async waitText(tabTitle: string, expectedText: string,
timeout: number = TimeoutConstants.TS_EDITOR_TAB_INTERACTION_TIMEOUT,
polling: number = TestConstants.TS_SELENIUM_DEFAULT_POLLING) {
Logger.debug(`Editor.waitText "${tabTitle}"`);
await this.driverHelper.getDriver().wait(async () => {
const editorText: string = await this.getEditorVisibleText(tabTitle);
const isEditorContainText: boolean = editorText.includes(expectedText);
if (isEditorContainText) {
return true;
}
await this.driverHelper.wait(polling);
}, timeout);
}
async followAndWaitForText(editorTabTitle: string,
expectedText: string,
timeout: number = TimeoutConstants.TS_EDITOR_TAB_INTERACTION_TIMEOUT,
polling: number = TestConstants.TS_SELENIUM_DEFAULT_POLLING) {
Logger.debug(`Editor.followAndWaitForText title: "${editorTabTitle}" text: "${expectedText}"`);
await this.selectTab(editorTabTitle);
await this.driverHelper.getDriver().wait(async () => {
await this.performKeyCombination(editorTabTitle, Key.chord(Key.CONTROL, Key.END));
const editorText: string = await this.getEditorVisibleText(editorTabTitle);
const isEditorContainText: boolean = editorText.includes(expectedText);
if (isEditorContainText) {
return true;
}
await this.driverHelper.wait(polling);
}, timeout);
}
async moveCursorToLineAndChar(editorTabTitle: string, line: number, char: number) {
Logger.debug(`Editor.moveCursorToLineAndChar title: "${editorTabTitle}" line: "${line}" char: "${char}"`);
// set cursor to the 1:1 position
await this.performKeyCombination(editorTabTitle, Key.chord(Key.CONTROL, Key.HOME));
// move cursor to line
for (let i = 1; i < line; i++) {
await this.performKeyCombination(editorTabTitle, Key.ARROW_DOWN);
}
// move cursor to char
for (let i = 1; i < char; i++) {
await this.performKeyCombination(editorTabTitle, Key.ARROW_RIGHT);
}
}
async performKeyCombination(editorTabTitle: string, text: string) {
Logger.debug(`Editor.performKeyCombination title: "${editorTabTitle}" text: "${text}"`);
const interactionContainerLocator: By = this.getEditorActionArreaLocator(editorTabTitle);
await this.driverHelper.type(interactionContainerLocator, text);
}
async type(editorTabTitle: string, text: string, line: number) {
Logger.debug(`Editor.type title: "${editorTabTitle}" text: "${text}"`);
await this.selectTab(editorTabTitle);
await this.moveCursorToLineAndChar(editorTabTitle, line, 1);
await this.performKeyCombination(editorTabTitle, text);
}
async waitErrorInLine(lineNumber: number, timeout: number = TimeoutConstants.TS_ERROR_HIGHLIGHTING_TIMEOUT) {
Logger.debug(`Editor.waitErrorInLine line: "${lineNumber}"`);
const errorInLineLocator: By = await this.getErrorInLineLocator(lineNumber);
await this.driverHelper.waitVisibility(errorInLineLocator, timeout);
}
async waitErrorInLineDisappearance(lineNumber: number, timeout: number = TimeoutConstants.TS_ERROR_HIGHLIGHTING_TIMEOUT) {
Logger.debug(`Editor.waitErrorInLineDisappearance line: "${lineNumber}"`);
const errorInLineLocator: By = await this.getErrorInLineLocator(lineNumber);
await this.driverHelper.waitDisappearanceWithTimeout(errorInLineLocator, timeout);
}
async waitWarningInLine(lineNumber: number, timeout: number = TimeoutConstants.TS_ERROR_HIGHLIGHTING_TIMEOUT) {
Logger.debug(`Editor.waitWarningInLine line: "${lineNumber}"`);
const warningInLineLocator: By = await this.getWarningInLineLocator(lineNumber);
await this.driverHelper.waitVisibility(warningInLineLocator, timeout);
}
async waitWarningInLineDisappearance(lineNumber: number, timeout: number = TimeoutConstants.TS_ERROR_HIGHLIGHTING_TIMEOUT) {
Logger.debug(`Editor.waitWarningInLineDisappearance line: "${lineNumber}"`);
const warningInLineLocator: By = await this.getWarningInLineLocator(lineNumber);
await this.driverHelper.waitDisappearanceWithTimeout(warningInLineLocator, timeout);
}
async waitStoppedDebugBreakpoint(tabTitle: string, lineNumber: number, timeout: number = TimeoutConstants.TS_BREAKPOINT_DEFAULT_TIMEOUT) {
Logger.debug(`Editor.waitStoppedDebugBreakpoint title: "${tabTitle}" line: "${lineNumber}"`);
await this.driverHelper.waitUntilTrue(() => this.isBreakpointPresent(tabTitle, lineNumber, true), timeout);
}
async waitBreakpoint(tabTitle: string, lineNumber: number, timeout: number = TimeoutConstants.TS_BREAKPOINT_DEFAULT_TIMEOUT) {
Logger.debug(`Editor.waitBreakpoint title: "${tabTitle}" line: "${lineNumber}"`);
await this.driverHelper.waitUntilTrue(() => this.isBreakpointPresent(tabTitle, lineNumber), timeout);
}
async waitBreakpointAbsence(tabTitle: string, lineNumber: number, timeout: number = TimeoutConstants.TS_BREAKPOINT_DEFAULT_TIMEOUT) {
Logger.debug(`Editor.waitBreakpointAbsence title: "${tabTitle}" line: "${lineNumber}"`);
await this.driverHelper.waitUntilTrue(() => !this.isBreakpointPresent(tabTitle, lineNumber), timeout);
}
async activateBreakpoint(tabTitle: string, lineNumber: number) {
Logger.debug(`Editor.activateBreakpoint title: "${tabTitle}" line: "${lineNumber}"`);
const attempts: number = TestConstants.TS_SELENIUM_DEFAULT_ATTEMPTS;
const polling: number = TestConstants.TS_SELENIUM_DEFAULT_POLLING;
for (let i = 0; i < attempts; i++) {
try {
await this.selectTab(tabTitle);
await this.moveCursorToLineAndChar(tabTitle, lineNumber, 1);
await this.performKeyCombination(tabTitle, Key.F9);
await this.waitBreakpoint(tabTitle, lineNumber);
return;
} catch (err) {
if (i === attempts - 1) {
throw new error.TimeoutError(`Exceeded maximum breakpoint activation attempts`);
}
// ignore errors and wait
Logger.debug(`Editor.activateBreakpoint - Error: ${err}`);
await this.driverHelper.wait(polling);
}
}
}
async getLineYCoordinates(lineNumber: number): Promise<number> {
Logger.debug(`Editor.getLineYCoordinates line: "${lineNumber}"`);
const lineNumberLocator: By = By.xpath(`//div[contains(@class, 'line-numbers') and text()='${lineNumber}']` +
`//parent::div[contains(@style, 'position')]`);
let elementStyleValue: string = await this.driverHelper.waitAndGetElementAttribute(lineNumberLocator, 'style', TimeoutConstants.TS_SELENIUM_CLICK_ON_VISIBLE_ITEM);
elementStyleValue = elementStyleValue.replace('position: absolute; top: ', '');
elementStyleValue = elementStyleValue.replace('px; width: 100%; height: 19px;', '');
const lineYCoordinate: number = Number.parseInt(elementStyleValue, 10);
if (Number.isNaN(lineYCoordinate)) {
throw new error.UnsupportedOperationError(`Failed to parse the ${elementStyleValue} row to number format`);
}
return lineYCoordinate;
}
async clickOnLineAndChar(line: number, char: number) {
Logger.debug(`Editor.clickOnLineAndChar line: "${line}" char: "${char}"`);
const yPosition: number = await this.getLineYCoordinates(line) + Editor.ADDITIONAL_SHIFTING_TO_Y;
const xPosition: number = char + Editor.ADDITIONAL_SHIFTING_TO_X;
new ActionSequence(this.driverHelper.getDriver()).
mouseMove({ x: xPosition, y: yPosition }).
click().
perform();
}
async goToDefinitionWithMouseClicking(line: number, char: number) {
Logger.debug(`Editor.goToDefinitionWithMouseClicking line: "${line}" char: "${char}"`);
const yPosition: number = await this.getLineYCoordinates(line) + Editor.ADDITIONAL_SHIFTING_TO_Y;
new ActionSequence(this.driverHelper.getDriver()).
keyDown(Key.CONTROL).
mouseMove({ x: char + Editor.ADDITIONAL_SHIFTING_TO_X, y: yPosition }).
click().
keyDown(Key.CONTROL).
perform();
}
async mouseRightButtonClick(line: number, char: number) {
Logger.debug(`Editor.mouseRightButtonClick line: "${line}" char: "${char}"`);
const yPosition: number = await this.getLineYCoordinates(line) + Editor.ADDITIONAL_SHIFTING_TO_Y;
new ActionSequence(this.driverHelper.getDriver()).
mouseMove({ x: char + Editor.ADDITIONAL_SHIFTING_TO_X, y: yPosition }).
click(Button.RIGHT).
perform();
}
private async scrollAndSearchSuggestion(editorTabTitle: string, suggestionLocator: By, timeout: number = 10000) {
await this.driverHelper.getDriver().wait(async () => {
const loadingLocator: By = By.xpath(Editor.SUGGESTION_LOADING_XPATH);
await this.waitSuggestionContainer();
await this.driverHelper.waitDisappearance(loadingLocator);
await this.driverHelper.wait(1000);
if (await this.driverHelper.isVisible(suggestionLocator)) {
return true;
}
await this.performKeyCombination(editorTabTitle, Key.ARROW_DOWN);
}, timeout);
}
private getTabWithUnsavedStatus(tabTitle: string): By {
return By.xpath(`//div[text()='${tabTitle}']/parent::li[contains(@class, 'theia-mod-dirty')]`);
}
private getEditorBodyLocator(editorTabTitle: string): By {
const editorXpathLocator: string = `//div[@id='theia-main-content-panel']//div[contains(@class, 'monaco-editor')` +
` and contains(@data-uri, '${editorTabTitle}')]//*[contains(@class, 'lines-content')]`;
return By.xpath(editorXpathLocator);
}
private getEditorActionArreaLocator(editorTabTitle: string): By {
const editorActionArreaXpathLocator: string = `//div[@id='theia-main-content-panel']//div[contains(@class, 'monaco-editor')` +
` and contains(@data-uri, '${editorTabTitle}')]//textarea`;
return By.xpath(editorActionArreaXpathLocator);
}
private getEditorLineXpathLocator(lineNumber: number): string {
return `(//div[contains(@class,'lines-content')]//div[@class='view-lines']/div[@class='view-line'])[${lineNumber}]`;
}
private getSuggestionLineXpathLocator(suggestionText: string): By {
return By.xpath(`//div[@widgetid='editor.widget.suggestWidget']//span[@class='monaco-highlighted-label' and contains(.,'${suggestionText}')]`);
}
private getTabXpathLocator(tabTitle: string): string {
return `//li[contains(@class, 'p-TabBar-tab')]//div[text()='${tabTitle}']`;
}
private async getErrorInLineLocator(lineNumber: number): Promise<By> {
const lineYCoordinates: number = await this.getLineYCoordinates(lineNumber);
return By.xpath(`//div[contains(@style, 'top:${lineYCoordinates}px')]//div[contains(@class, 'squiggly-error')]`);
}
private async getWarningInLineLocator(lineNumber: number): Promise<By> {
const lineYCoordinates: number = await this.getLineYCoordinates(lineNumber);
return By.xpath(`//div[contains(@style, 'top:${lineYCoordinates}px')]//div[contains(@class, 'squiggly-warning')]`);
}
private async waitSuggestionWithResettingCursor(editorTabTitle: string,
suggestionText: string,
timeout: number = TimeoutConstants.TS_SUGGESTION_TIMEOUT,
lineNumber: number,
charNumber: number) {
const suggestionLocator: By = this.getSuggestionLineXpathLocator(suggestionText);
const methodLogText: string = `Editor.waitSuggestion tabTitle: "${editorTabTitle}" ` +
`suggestion: "${suggestionText}" ` +
`line: "${lineNumber}" ` +
`char: "${charNumber}"`;
Logger.debug(methodLogText);
await this.driverHelper.getDriver().wait(async () => {
await this.selectTab(editorTabTitle);
await this.moveCursorToLineAndChar(editorTabTitle, lineNumber, charNumber);
await this.pressControlSpaceCombination(editorTabTitle);
try {
await this.driverHelper.waitVisibility(suggestionLocator, 5000);
await this.closeSuggestionContainer(editorTabTitle);
return true;
} catch (err) {
if (!(err instanceof error.TimeoutError)) {
throw err;
}
}
}, timeout);
}
private async waitSuggestionWithoutResettingCursor(editorTabTitle: string,
suggestionText: string,
timeout: number = TimeoutConstants.TS_SUGGESTION_TIMEOUT) {
Logger.debug(`Editor.waitSuggestion tabTitle: "${editorTabTitle}" suggestion: "${suggestionText}"`);
const suggestionLocator: By = this.getSuggestionLineXpathLocator(suggestionText);
await this.driverHelper.getDriver().wait(async () => {
try {
await this.driverHelper.waitVisibility(suggestionLocator, 5000);
await this.closeSuggestionContainer(editorTabTitle);
return true;
} catch (err) {
if (!(err instanceof error.TimeoutError)) {
throw err;
}
await this.closeSuggestionContainer(editorTabTitle, timeout);
await this.pressControlSpaceCombination(editorTabTitle);
}
}, timeout);
}
/**
* Checks for breakpoint presence in currently opened editor on given line.
*
* @param lineNumber Line number to check the breakpoint presence on.
* @param triggered Whether this breakpoint is triggered or not. Default false.
*/
private async isBreakpointPresent(tabTitle: string, lineNumber: number, triggered: boolean = false): Promise<boolean> {
Logger.debug('Editor.isBreakpointPresent');
const linesBarXpathLocator: string = `//div[contains(@id, '${tabTitle}')]//div[@class='margin']`;
const triggeredBreakpointXpathLocator: string = `//div[contains(@class, 'theia-debug-breakpoint') and contains(@class, 'theia-debug-top-stack-frame')]`;
const regularBreakpointXpathLocator: string = `//div[contains(@class, 'theia-debug-breakpoint')]`;
const lineNumberRelativeXpathLocator: string = `/parent::div/div[contains(@class, 'line-numbers') and text()=${lineNumber}]`;
const breakpointLocator: string = (triggered ? triggeredBreakpointXpathLocator : regularBreakpointXpathLocator);
const breakpointLineNumberXpathLocator = linesBarXpathLocator + breakpointLocator + lineNumberRelativeXpathLocator;
return await this.driverHelper.isVisible(By.xpath(breakpointLineNumberXpathLocator));
}
}

View File

@ -1,119 +0,0 @@
import { injectable, inject } from 'inversify';
import { CLASSES } from '../../inversify.types';
import { DriverHelper } from '../../utils/DriverHelper';
import { By } from 'selenium-webdriver';
import { Logger } from '../../utils/Logger';
import { TimeoutConstants } from '../../TimeoutConstants';
import { DialogWindow } from './DialogWindow';
import { TopMenu } from './TopMenu';
import { QuickOpenContainer } from './QuickOpenContainer';
/*********************************************************************
* Copyright (c) 2019 Red Hat, Inc.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/
@injectable()
export class GitPlugin {
private static readonly COMMIT_MESSAGE_TEXTAREA_CSS: string = 'textarea#theia-scm-input-message';
constructor(
@inject(CLASSES.DriverHelper) private readonly driverHelper: DriverHelper,
@inject(CLASSES.DialogWindow) private readonly dialogWindow: DialogWindow,
@inject(CLASSES.TopMenu) private readonly topMenu: TopMenu,
@inject(CLASSES.QuickOpenContainer) private readonly quickOpenContainer: QuickOpenContainer
) { }
async openGitPluginContainer(timeout: number = TimeoutConstants.TS_GIT_CONAINER_INTERACTION_TIMEOUT) {
Logger.debug('GitPlugin.openGitPluginContainer');
const sourceControlGitBtnXpathLocator: string = '//li[@id=\'shell-tab-scm-view-container\' and contains(@style, \'height\')]';
await this.driverHelper.waitAndClick(By.xpath(sourceControlGitBtnXpathLocator), timeout);
await this.waitViewOfContainer(timeout);
}
async waitViewOfContainer(timeout: number = TimeoutConstants.TS_GIT_CONAINER_INTERACTION_TIMEOUT) {
Logger.debug('GitPlugin.waitViewOfContainer');
const gitHubContainerIdLocator: By = By.id('scm-view-container--scm-view');
await this.driverHelper.waitVisibility(gitHubContainerIdLocator, timeout);
}
async waitCommitMessageTextArea(timeout: number = TimeoutConstants.TS_GIT_CONAINER_INTERACTION_TIMEOUT) {
Logger.debug('GitPlugin.waitCommitMessageTextArea');
const textAreaCssLocator: By = By.css(GitPlugin.COMMIT_MESSAGE_TEXTAREA_CSS);
await this.driverHelper.waitVisibility(textAreaCssLocator, timeout);
}
async typeCommitMessage(commitMessage: string, timeout: number = TimeoutConstants.TS_GIT_CONAINER_INTERACTION_TIMEOUT) {
Logger.debug('GitPlugin.typeCommitMessage');
await this.waitCommitMessageTextArea(timeout);
await this.driverHelper.type(By.css(GitPlugin.COMMIT_MESSAGE_TEXTAREA_CSS), commitMessage, timeout);
}
async selectCommandInMoreActionsMenu(commandName: string, timeout: number = TimeoutConstants.TS_GIT_CONAINER_INTERACTION_TIMEOUT) {
Logger.debug('GitPlugin.selectCommandInMoreActionsMenu');
await this.clickOnMoreActions(timeout);
await this.driverHelper.waitAndClick(By.xpath(`//li[@data-command]/div[text()=\'${commandName}\']`), timeout);
}
async clickOnMoreActions(timeout: number = TimeoutConstants.TS_GIT_CONAINER_INTERACTION_TIMEOUT) {
Logger.debug('GitPlugin.clickOnMoreActions');
await this.driverHelper.waitAndClick(By.id('__more__'), timeout);
}
async waitChangedFileInChagesList(expectedItem: string, timeout: number = TimeoutConstants.TS_GIT_CONAINER_INTERACTION_TIMEOUT) {
Logger.debug('GitPlugin.waitChangedFileInChagesList');
await this.driverHelper.waitPresence(By.xpath(`//span[@class='name' and text()=\'${expectedItem}\']`), timeout);
}
async waitStagedFileInStagedChanges(expectedStagedItem: string, timeout: number = TimeoutConstants.TS_GIT_CONAINER_INTERACTION_TIMEOUT) {
Logger.debug('GitPlugin.waitStagedFileInStagedChanges');
await this.driverHelper.waitPresence(By.xpath(`//div[text()='Staged Changes']/parent::div/parent::div/parent::div/following-sibling::div//span[text()=\'${expectedStagedItem}\']`), timeout);
}
async commitFromCommandMenu() {
Logger.debug('GitPlugin.commitFromScmView');
await this.topMenu.selectOption('View', 'Find Command...');
await this.quickOpenContainer.typeAndSelectSuggestion('Commit', 'Git: Commit');
}
async pushChangesFromCommandMenu() {
Logger.debug('GitPlugin.commitFromScmView');
await this.topMenu.selectOption('View', 'Find Command...');
await this.quickOpenContainer.typeAndSelectSuggestion('Push', 'Git: Push');
}
async stageAllChanges(expectedStagedItem: string, timeout: number = TimeoutConstants.TS_GIT_CONAINER_INTERACTION_TIMEOUT) {
Logger.debug('GitPlugin.stageAllChanges');
await this.driverHelper.waitVisibility(By.xpath('//div[@class=\'noWrapInfo theia-TreeNodeSegmentGrow\' and text()=\'Changes\']'), timeout);
await this.driverHelper.scrollTo(By.xpath('//div[@class=\'noWrapInfo theia-TreeNodeSegmentGrow\' and text()=\'Changes\']'));
await this.driverHelper.waitAndClick(By.xpath('//a[@title=\'Stage All Changes\']'), timeout);
await this.waitStagedFileInStagedChanges(expectedStagedItem);
}
async waitDataIsSynchronized(timeout: number = TimeoutConstants.TS_GIT_CONAINER_INTERACTION_TIMEOUT) {
Logger.debug('GitPlugin.waitDataIsSynchronized');
await this.driverHelper.waitDisappearance(By.xpath(`//div[contains(@title,'Synchronize Changes')]//span[contains(.,' 0↓')]`), timeout);
}
async clickOnSelectRepositoryButton(timeout: number = TimeoutConstants.TS_GIT_CONAINER_INTERACTION_TIMEOUT) {
Logger.debug('GitPlugin.clickOnSelectRepositoryButton');
await this.driverHelper.waitAndClick(By.xpath(`//button[@class='theia-button main' and text()='Select Repository Location']`), timeout);
await this.dialogWindow.waitDialogDissappearance();
}
}

View File

@ -1,356 +0,0 @@
/*********************************************************************
* Copyright (c) 2019 Red Hat, Inc.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/
import axios from 'axios';
import { DriverHelper } from '../../utils/DriverHelper';
import { injectable, inject } from 'inversify';
import { CLASSES } from '../../inversify.types';
import { TestConstants } from '../../TestConstants';
import { By, error } from 'selenium-webdriver';
import { Logger } from '../../utils/Logger';
import { NotificationCenter } from './NotificationCenter';
import { TimeoutConstants } from '../../TimeoutConstants';
export enum LeftToolbarButton {
Explorer = 'Explorer',
Git = 'Git',
Debug = 'Debug',
Openshift = 'OpenShift'
}
@injectable()
export class Ide {
public static readonly EXPLORER_BUTTON_ID: string = 'shell-tab-explorer-view-container';
public static readonly SELECTED_EXPLORER_BUTTON_CSS: string = 'li#shell-tab-explorer-view-container.theia-mod-active';
public static readonly ACTIVATED_IDE_IFRAME_CSS: string = '#ide-iframe-window[aria-hidden=\'false\']';
public static readonly SELECTED_GIT_BUTTON_XPATH: string = '(//ul[@class=\'p-TabBar-content\']//li[@title=\'Git\' and contains(@class, \'p-mod-current\')])[1]';
private static readonly TOP_MENU_PANEL_CSS: string = '#theia-app-shell #theia-top-panel .p-MenuBar-content';
private static readonly LEFT_CONTENT_PANEL_CSS: string = '#theia-left-content-panel';
private static readonly PRELOADER_CSS: string = '.theia-preload';
private static readonly IDE_IFRAME_CSS: string = 'iframe#ide-iframe';
constructor(
@inject(CLASSES.DriverHelper) private readonly driverHelper: DriverHelper,
@inject(CLASSES.NotificationCenter) private readonly notificationCenter: NotificationCenter
) { }
async waitAndSwitchToIdeFrame(timeout: number = TimeoutConstants.TS_SELENIUM_START_WORKSPACE_TIMEOUT) {
Logger.debug('Ide.waitAndSwitchToIdeFrame');
try {
await this.driverHelper.waitAndSwitchToFrame(By.css(Ide.IDE_IFRAME_CSS), timeout);
} catch (err) {
if (err instanceof error.StaleElementReferenceError) {
Logger.warn('StaleElementException occured during waiting for IDE. Sleeping for 2 secs and retrying.');
this.driverHelper.wait(2000);
await this.driverHelper.waitAndSwitchToFrame(By.css(Ide.IDE_IFRAME_CSS), timeout);
return;
}
if (err instanceof error.TimeoutError) {
Logger.error(`Switching to IDE frame failed after ${timeout} timeout.`);
throw err;
}
Logger.error(`Switching to IDE frame failed.`);
throw err;
}
}
async waitNotification(notificationText: string, timeout: number = TimeoutConstants.TS_NOTIFICATION_CENTER_TIMEOUT) {
Logger.debug(`Ide.waitNotification "${notificationText}"`);
const notificationLocator: By = By.xpath(this.getNotificationXpathLocator(notificationText));
await this.driverHelper.waitVisibility(notificationLocator, timeout);
}
async waitTaskExitCodeNotificationBoolean(exitCode: string, timeout: number = TimeoutConstants.TS_SELENIUM_WAIT_TASK_EXIT_CODE_TIMEOUT): Promise<boolean> {
Logger.debug(`Ide.waitTaskExitCodeNotification "has exited with code ${exitCode}."`);
const exitCodeNotificationLocator: By = By.xpath(this.getNotificationXpathLocator(`has exited with code`));
const notificationLocator: By = By.xpath(this.getNotificationXpathLocator(`has exited with code ${exitCode}.`));
Logger.info(`Ide.waitTaskExitCodeNotification waiting for any exit code notification.`);
try {
await this.driverHelper.waitVisibility(exitCodeNotificationLocator, timeout);
} catch (err) {
if (err instanceof error.TimeoutError) {
Logger.error(`Ide.waitTaskExitCodeNotificationBoolean wait for notification timed out after ${timeout}.`);
throw err;
}
Logger.error(`Waiting for task notification failed.`);
throw err;
}
Logger.info(`Ide.waitTaskExitCodeNotification checking for correct exit core:${exitCode}`);
return await this.driverHelper.waitVisibilityBoolean(notificationLocator, 1, 1000);
}
async waitNotificationAndClickOnButton(notificationText: string,
buttonText: string,
timeout: number = TimeoutConstants.TS_NOTIFICATION_CENTER_TIMEOUT) {
Logger.debug(`Ide.waitNotificationAndClickOnButton "${notificationText}" buttonText: "${buttonText}"`);
await this.driverHelper.getDriver().wait(async () => {
await this.waitNotification(notificationText, timeout);
await this.clickOnNotificationButton(notificationText, buttonText);
try {
await this.waitNotificationDisappearance(notificationText);
return true;
} catch (err) {
if (!(err instanceof error.TimeoutError)) {
throw err;
}
console.log(`After clicking on "${buttonText}" button of the notification with text "${notificationText}" \n` +
'it is still visible (issue #14121), try again.');
await this.driverHelper.wait(TestConstants.TS_SELENIUM_DEFAULT_POLLING);
}
}, timeout);
}
async waitNotificationAndConfirm(notificationText: string, timeout: number = TimeoutConstants.TS_NOTIFICATION_CENTER_TIMEOUT) {
Logger.debug(`Ide.waitNotificationAndConfirm "${notificationText}"`);
await this.waitNotificationAndClickOnButton(notificationText, 'yes', timeout);
}
async waitNotificationAndOpenLink(notificationText: string, timeout: number) {
Logger.debug(`Ide.waitNotificationAndOpenLink "${notificationText}"`);
await this.waitNotification(notificationText, timeout);
await this.waitNotificationAndClickOnButton(notificationText, 'Open Link', timeout);
}
async isNotificationPresent(notificationText: string): Promise<boolean> {
Logger.debug(`Ide.isNotificationPresent "${notificationText}"`);
const notificationLocator: By = By.xpath(this.getNotificationXpathLocator(notificationText));
return await this.driverHelper.waitVisibilityBoolean(notificationLocator);
}
async waitNotificationDisappearance(notificationText: string,
attempts: number = TestConstants.TS_SELENIUM_DEFAULT_ATTEMPTS,
polling: number = TestConstants.TS_SELENIUM_DEFAULT_POLLING) {
Logger.debug(`Ide.waitNotificationDisappearance "${notificationText}"`);
const notificationLocator: By = By.xpath(this.getNotificationXpathLocator(notificationText));
await this.driverHelper.waitDisappearance(notificationLocator, attempts, polling);
}
async clickOnNotificationButton(notificationText: string, buttonText: string) {
Logger.debug(`Ide.clickOnNotificationButton "${notificationText}" buttonText: "${buttonText}"`);
const yesButtonLocator: string = `//div[@class='theia-notification-list']//span[contains(.,'${notificationText}')]/parent::div/parent::div/parent::div/div[@class='theia-notification-list-item-content-bottom']//div[@class='theia-notification-buttons']//button[text()='${buttonText}'] `;
await this.driverHelper.waitAndClick(By.xpath(yesButtonLocator));
}
async waitWorkspaceAndIde(timeout: number = TimeoutConstants.TS_SELENIUM_START_WORKSPACE_TIMEOUT) {
Logger.debug('Ide.waitWorkspaceAndIde');
await this.waitAndSwitchToIdeFrame(timeout);
await this.waitIde(timeout);
}
async waitIde(timeout: number = TimeoutConstants.TS_IDE_LOAD_TIMEOUT) {
Logger.debug('Ide.waitIde');
const mainIdeParts: Array<By> = [By.css(Ide.TOP_MENU_PANEL_CSS), By.css(Ide.LEFT_CONTENT_PANEL_CSS), By.id(Ide.EXPLORER_BUTTON_ID)];
for (const idePartLocator of mainIdeParts) {
try {
await this.driverHelper.waitVisibility(idePartLocator, timeout);
} catch (err) {
if (err instanceof error.NoSuchWindowError) {
await this.driverHelper.waitVisibility(idePartLocator, timeout);
return;
}
if (err instanceof error.TimeoutError) {
Logger.error(`Waiting for ${idePartLocator} timeouted after ${timeout} timeout.`);
throw err;
}
Logger.error(`Waiting for ${idePartLocator} failed.`);
throw err;
}
}
}
async waitLeftToolbarButton(buttonTitle: LeftToolbarButton, timeout: number = TimeoutConstants.TS_SELENIUM_TOOLBAR_TIMEOUT) {
Logger.debug('Ide.waitLeftToolbarButton');
const buttonLocator: By = this.getLeftToolbarButtonLocator(buttonTitle);
await this.driverHelper.waitVisibility(buttonLocator, timeout);
}
async waitAndClickLeftToolbarButton(buttonTitle: LeftToolbarButton, timeout: number = TimeoutConstants.TS_SELENIUM_TOOLBAR_TIMEOUT) {
Logger.debug('Ide.waitAndClickLeftToolbarButton');
const buttonLocator: By = this.getLeftToolbarButtonLocator(buttonTitle);
await this.driverHelper.waitAndClick(buttonLocator, timeout);
}
async waitTopMenuPanel(timeout: number = TimeoutConstants.TS_SELENIUM_TOOLBAR_TIMEOUT) {
Logger.debug('Ide.waitTopMenuPanel');
await this.driverHelper.waitVisibility(By.css(Ide.TOP_MENU_PANEL_CSS), timeout);
}
async waitLeftContentPanel(timeout: number = TimeoutConstants.TS_SELENIUM_TOOLBAR_TIMEOUT) {
Logger.debug('Ide.waitLeftContentPanel');
await this.driverHelper.waitVisibility(By.css(Ide.LEFT_CONTENT_PANEL_CSS), timeout);
}
async waitPreloaderAbsent(timeout: number = TimeoutConstants.TS_SELENIUM_LOAD_PAGE_TIMEOUT) {
const polling: number = TestConstants.TS_SELENIUM_DEFAULT_POLLING;
const attempts: number = timeout / polling;
Logger.debug('Ide.waitPreloaderAbsent');
await this.driverHelper.waitDisappearance(By.css(Ide.PRELOADER_CSS), attempts, polling);
}
async waitPreloaderVisible(timeout: number = TimeoutConstants.TS_SELENIUM_START_WORKSPACE_TIMEOUT) {
Logger.debug('Ide.waitPreloaderVisible');
await this.driverHelper.waitVisibility(By.css(Ide.PRELOADER_CSS), timeout);
}
async waitStatusBarContains(expectedText: string, timeout: number = TimeoutConstants.TS_SELENIUM_LANGUAGE_SERVER_START_TIMEOUT) {
const statusBarLocator: By = By.css('div[id=\'theia-statusBar\']');
Logger.debug(`Ide.waitStatusBarContains "${expectedText}"`);
await this.driverHelper.getDriver().wait(async () => {
const elementText: string = await this.driverHelper.waitAndGetText(statusBarLocator, timeout);
const isTextPresent: boolean = elementText.search(expectedText) > 0;
if (isTextPresent) {
return true;
}
await this.driverHelper.wait(TestConstants.TS_SELENIUM_DEFAULT_POLLING * 2);
}, timeout);
}
async waitStatusBarTextAbsence(expectedText: string, timeout: number = TimeoutConstants.TS_SELENIUM_LANGUAGE_SERVER_START_TIMEOUT) {
const statusBarLocator: By = By.css('div[id=\'theia-statusBar\']');
Logger.debug(`Ide.waitStatusBarTextAbsence "${expectedText}"`);
// for ensuring that check is not invoked in the gap of status displaying
for (let i: number = 0; i < 3; i++) {
await this.driverHelper.getDriver().wait(async () => {
const elementText: string = await this.driverHelper.waitAndGetText(statusBarLocator, timeout);
const isTextAbsent: boolean = elementText.search(expectedText) === -1;
if (isTextAbsent) {
return true;
}
await this.driverHelper.wait(TestConstants.TS_SELENIUM_DEFAULT_POLLING * 2);
}, timeout);
}
}
async checkLsInitializationStart(expectedTextInStatusBar: string) {
Logger.debug('Ide.checkLsInitializationStart');
await this.waitStatusBarContains(expectedTextInStatusBar, 20000);
}
async performKeyCombination(keyCombination: string, timeout: number = TimeoutConstants.TS_SELENIUM_CLICK_ON_VISIBLE_ITEM) {
Logger.debug(`Ide.performKeyCombination "${keyCombination}"`);
const bodyLocator: By = By.tagName('body');
await this.driverHelper.type(bodyLocator, keyCombination, timeout);
}
async waitRightToolbarButtonSelection(buttonTitle: string, timeout: number = TimeoutConstants.TS_SELENIUM_TOOLBAR_TIMEOUT) {
Logger.debug('Ide.waitRightToolbarButtonSelection');
const selectedRightToolbarButtonLocator: By = this.getSelectedRightToolbarButtonLocator(buttonTitle);
await this.driverHelper.waitVisibility(selectedRightToolbarButtonLocator, timeout);
}
async getApplicationUrlFromNotification(notificationText: string, timeout: number = TimeoutConstants.TS_NOTIFICATION_CENTER_TIMEOUT) {
Logger.debug(`Ide.getApplicationUrlFromNotification ${notificationText}`);
const notificationTextLocator: By = By.xpath(`//div[@class='theia-notification-message']/span[contains(.,'${notificationText}')]`);
let notification = await this.driverHelper.waitAndGetText(notificationTextLocator, timeout);
let regexp: RegExp = new RegExp('^.*(https?://.*)$');
if (!regexp.test(notification)) {
throw new Error('Cannot obtaine url from notification message');
}
return notification.split(regexp)[1];
}
async closeAllNotifications(timeout: number = TimeoutConstants.TS_NOTIFICATION_CENTER_TIMEOUT) {
Logger.debug(`Ide.closeAllNotifications`);
for (let i: number = 0; i < 5; i++) {
await this.notificationCenter.open();
try {
await this.notificationCenter.closeAll(timeout);
break;
} catch (err) {
if (!(err instanceof error.TimeoutError)) {
throw err;
}
if (i === 4) {
Logger.debug('The last try to clear of the notification center was unsuccessful');
throw err;
}
}
}
}
async waitApllicationIsReady(url: string,
timeout: number) {
Logger.debug(`Ide.waitApllicationIsReady ${url}`);
await this.driverHelper.getDriver().wait(async () => {
try {
const res = await axios.get(url);
if (res.status === 200) {
return true;
}
} catch (error) {
await this.driverHelper.wait(TestConstants.TS_SELENIUM_DEFAULT_POLLING);
}
}, timeout);
}
private getSelectedRightToolbarButtonLocator(buttonTitle: string): By {
return By.xpath(`//div[@id='theia-left-content-panel']//ul[@class='p-TabBar-content']` +
`//li[@title[contains(.,'${buttonTitle}')] and contains(@id, 'shell-tab')] and contains(@class, 'p-mod-current')`);
}
private getLeftToolbarButtonLocator(buttonTitle: String): By {
return By.xpath(`//div[@id='theia-left-content-panel']//ul[@class='p-TabBar-content']` +
`//li[@title[contains(.,'${buttonTitle}')] and contains(@id, 'shell-tab')]`);
}
private getNotificationXpathLocator(notificationText: string): string {
return `//div[@class='theia-notification-message']/span[contains(.,'${notificationText}')]`;
}
}

View File

@ -1,80 +0,0 @@
/*********************************************************************
* Copyright (c) 2019 Red Hat, Inc.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/
import { injectable, inject } from 'inversify';
import { CLASSES } from '../../inversify.types';
import { DriverHelper } from '../../utils/DriverHelper';
import { By } from 'selenium-webdriver';
import { Logger } from '../../utils/Logger';
import { TimeoutConstants } from '../../TimeoutConstants';
@injectable()
export class LeftToolBar {
constructor(@inject(CLASSES.DriverHelper) private readonly driverHelper: DriverHelper) { }
async waitToolbar(timeout: number = TimeoutConstants.TS_SELENIUM_TOOLBAR_TIMEOUT) {
Logger.debug('LeftToolBar.waitToolbar');
await this.driverHelper.waitVisibility(By.css('div.theia-app-left'), timeout);
}
async clickOnToolIcon(iconTitle: string, timeout: number = TimeoutConstants.TS_SELENIUM_CLICK_ON_VISIBLE_ITEM) {
Logger.debug(`LeftToolBar.clickOnToolIcon "${iconTitle}"`);
const toolIconLocator: By = this.getViewLocator(iconTitle);
await this.driverHelper.waitAndClick(toolIconLocator, timeout);
}
async waitToolIcon(iconTitle: string, timeout: number = TimeoutConstants.TS_SELENIUM_CLICK_ON_VISIBLE_ITEM) {
Logger.debug(`LeftToolBar.waitToolIcon "${iconTitle}"`);
const toolIconLocator: By = this.getViewLocator(iconTitle);
await this.driverHelper.waitVisibility(toolIconLocator, timeout);
}
async isViewSelected(toolIconTitle: string): Promise<Boolean> {
Logger.debug(`LeftToolBar.isViewEnabled "${toolIconTitle}"`);
const selectedViewLocator: By = this.getSelectedViewLocator(toolIconTitle);
return await this.driverHelper.isVisible(selectedViewLocator);
}
async waitViewSelected(toolIconTitle: string, timeout: number = TimeoutConstants.TS_PROJECT_TREE_TIMEOUT) {
Logger.debug(`LeftToolBar.waitViewSelected "${toolIconTitle}"`);
const selectedViewLocator: By = this.getSelectedViewLocator(toolIconTitle);
return await this.driverHelper.waitVisibility(selectedViewLocator);
}
async selectView(toolIconTitle: string, timeout: number = TimeoutConstants.TS_PROJECT_TREE_TIMEOUT) {
Logger.debug(`LeftToolBar.selectView "${toolIconTitle}"`);
await this.waitToolIcon(toolIconTitle, timeout);
if ( await this.isViewSelected(toolIconTitle)) {
return;
}
await this.clickOnToolIcon(toolIconTitle, timeout);
await this.waitViewSelected(toolIconTitle, timeout);
}
private getSelectedViewLocator(viewTitle: string): By {
return By.css(`div.theia-app-left .p-TabBar-content li.p-mod-current[title='${viewTitle}']`);
}
private getViewLocator(viewTitle: string): By {
return By.css(`div.theia-app-left .p-TabBar-content li[title='${viewTitle}']`);
}
}

View File

@ -1,77 +0,0 @@
/*********************************************************************
* Copyright (c) 2019 Red Hat, Inc.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/
import { injectable, inject } from 'inversify';
import { CLASSES } from '../../inversify.types';
import { DriverHelper } from '../../utils/DriverHelper';
import { Logger } from '../../utils/Logger';
import { By } from 'selenium-webdriver';
import { TimeoutConstants } from '../../TimeoutConstants';
@injectable()
export class NotificationCenter {
constructor(@inject(CLASSES.DriverHelper) private readonly driverHelper: DriverHelper) { }
async waitOpening(timeout: number = TimeoutConstants.TS_NOTIFICATION_CENTER_TIMEOUT) {
Logger.debug('NotificationCenter.waitOpening');
await this.driverHelper.waitVisibility(By.css('div.theia-notification-center-header'), timeout);
}
async clickIconOnStatusBar(timeout: number = TimeoutConstants.TS_SELENIUM_CLICK_ON_VISIBLE_ITEM) {
Logger.debug('NotificationCenter.clickIconOnStatusBar');
const statusBarNotificationsLocator: By =
By.xpath('(//div[@id=\'theia-statusBar\']//div[@class=\'area right\']//div[@title=\'Toggle Bottom Panel\']/preceding-sibling::div)[last()]');
await this.driverHelper.waitAndClick(statusBarNotificationsLocator, timeout);
}
async open() {
Logger.debug(`NotificationCenter.open`);
await this.clickIconOnStatusBar(TimeoutConstants.TS_SELENIUM_CLICK_ON_VISIBLE_ITEM);
await this.waitOpening(TimeoutConstants.TS_NOTIFICATION_CENTER_TIMEOUT);
}
async clickCloseAllNotificationsButton(timeout: number = TimeoutConstants.TS_SELENIUM_CLICK_ON_VISIBLE_ITEM) {
Logger.debug(`NotificationCenter.clickCloseAllNotificationsButton`);
const closeAllButtonLocator: By = By.css('.theia-notification-center-header-actions .clear-all');
await this.driverHelper.waitAndClick(closeAllButtonLocator, timeout);
}
async waitClosing(timeout: number = TimeoutConstants.TS_NOTIFICATION_CENTER_TIMEOUT) {
Logger.debug(`NotificationCenter.waitClosing`);
const notificationCenterClosedLocator: By = By.css('.theia-notification-center.closed');
await this.driverHelper.waitPresence(notificationCenterClosedLocator, timeout);
}
async waitClearNotificationsList(timeout: number = TimeoutConstants.TS_NOTIFICATION_CENTER_TIMEOUT) {
Logger.debug(`NotificationCenter.waitClearNotificationsList`);
const notificationLocator: By = By.css('.theia-notification-center .theia-notification-list > *');
await this.driverHelper.waitDisappearance(notificationLocator, timeout);
}
async closeAll(timeout: number = TimeoutConstants.TS_NOTIFICATION_CENTER_TIMEOUT) {
Logger.debug('NotificationCenter.closeAll');
await this.clickCloseAllNotificationsButton(timeout);
await this.waitClearNotificationsList(timeout);
}
}

View File

@ -1,67 +0,0 @@
/*********************************************************************
* Copyright (c) 2019 Red Hat, Inc.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/
import { injectable, inject } from 'inversify';
import { CLASSES } from '../../inversify.types';
import { DriverHelper } from '../../utils/DriverHelper';
import { Logger } from '../../utils/Logger';
import { DialogWindow } from '../ide/DialogWindow';
import { OpenWorkspaceWidget } from '../ide/OpenWorkspaceWidget';
import { By } from 'selenium-webdriver';
import { TimeoutConstants } from '../../TimeoutConstants';
export enum Locations {
Theia = 'theia',
Home = 'home',
Root = '/'
}
export enum Buttons {
Cancel = 'Cancel',
AddContext = 'Add context folder for component in workspace.',
}
@injectable()
export class OpenDialogWidget {
constructor(
@inject(CLASSES.DialogWindow) private readonly dialogWindow: DialogWindow,
@inject(CLASSES.OpenWorkspaceWidget) private readonly openWorkspaceWidget: OpenWorkspaceWidget,
@inject(CLASSES.DriverHelper) private readonly driverHelper: DriverHelper
) { }
async selectLocation(location: Locations, timeout: number = TimeoutConstants.TS_SELENIUM_DIALOG_WIDGET_TIMEOUT) {
Logger.debug(`OpenDialogWidget.selectLocation`);
await this.driverHelper.type(By.css('div.theia-NavigationPanel select'), location, timeout);
}
async selectItemInTree(pathToItem: string) {
Logger.debug(`OpenDialogWidget.selectItemInTree "${pathToItem}"`);
await this.openWorkspaceWidget.selectItemInTree(pathToItem);
}
async expandItemInTreeToPath(pathToItem: string, timeout: number = TimeoutConstants.TS_SELENIUM_DIALOG_WIDGET_TIMEOUT) {
Logger.debug(`OpenDialogWidget.expandItemInTreeToPath "${pathToItem}"`);
await this.openWorkspaceWidget.expandTreeToPath(pathToItem, timeout);
}
async clickOnButton(button: Buttons) {
Logger.debug(`OpenDialogWidget.clickOnButton ${button}`);
await this.dialogWindow.clickToButton(button);
}
async selectLocationAndAddContextFolder(location: Locations, path: string, button: Buttons) {
await this.selectLocation(location);
await this.expandItemInTreeToPath(path);
await this.clickOnButton(button);
await this.dialogWindow.waitDialogDissappearance();
}
}

View File

@ -1,47 +0,0 @@
/*********************************************************************
* Copyright (c) 2019 Red Hat, Inc.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/
import { injectable, inject } from 'inversify';
import { CLASSES } from '../../inversify.types';
import { DriverHelper } from '../../utils/DriverHelper';
import { By } from 'selenium-webdriver';
import { Logger } from '../../utils/Logger';
import { TimeoutConstants } from '../../TimeoutConstants';
@injectable()
export class OpenWorkspaceWidget {
constructor(@inject(CLASSES.DriverHelper) private readonly driverHelper: DriverHelper) {
}
async selectItemInTree(pathToItem: string, timeout: number = TimeoutConstants.TS_SELENIUM_CLICK_ON_VISIBLE_ITEM) {
Logger.debug(`OpenWorkspaceWidget.selectItemInTree "${pathToItem}"`);
await this.driverHelper.waitAndClick(By.id(pathToItem), timeout);
}
async expandTreeToPath(path: string, timeout: number = TimeoutConstants.TS_SELENIUM_CLICK_ON_VISIBLE_ITEM): Promise<any> {
Logger.debug(`OpenWorkspaceWidget.expandTreeToPath "${path}"`);
const pathNodes: string[] = path.split('/');
let buildPath: string = '';
const promises = pathNodes.map(async (currentPath, index) => {
buildPath += `/${currentPath}`;
// the first item (index=0 -> /<item-1>) has locator which can be found 'By.id', but next (index=1 -> /<item-1>/<item-2>) requires another - 'By.xpath'.
if (index === 0) {
await this.driverHelper.waitAndClick(By.id(buildPath), timeout);
} else {
await this.driverHelper.waitAndClick(By.xpath(`(//div[@id='${buildPath}'])[position()=2]`), timeout);
}
});
return Promise.all(promises);
}
}

View File

@ -1,87 +0,0 @@
/*********************************************************************
* Copyright (c) 2019 Red Hat, Inc.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/
import { injectable, inject } from 'inversify';
import { CLASSES } from '../../inversify.types';
import { DriverHelper } from '../../utils/DriverHelper';
import { Ide, LeftToolbarButton } from './Ide';
import { Logger } from '../../utils/Logger';
import { By } from 'selenium-webdriver';
import { ContextMenu } from './ContextMenu';
import { TimeoutConstants } from '../../TimeoutConstants';
export enum OpenshiftAppExplorerToolbar {
ReportExtensionIssueOnGitHub = 'Report Extension Issue on GitHub',
RefreshView = 'Refresh View',
SwitchContexts = 'Switch Contexts',
LogIntoCluster = 'Login into Cluster'
}
export enum OpenshiftContextMenuItems {
NewComponent = 'New Component',
Push = 'Push'
}
@injectable()
export class OpenshiftPlugin {
constructor(@inject(CLASSES.DriverHelper) private readonly driverHelper: DriverHelper,
@inject(CLASSES.Ide) private readonly ide: Ide,
@inject(CLASSES.ContextMenu) private readonly contextMenu: ContextMenu
) {
}
async clickOnOpenshiftToollBarIcon(timeout: number = TimeoutConstants.TS_WAIT_OPENSHIFT_CONNECTOR_TREE_TIMEOUT) {
Logger.debug(`OpenshiftPlugin.clickOnOpenshiftTollBar`);
await this.ide.waitAndClickLeftToolbarButton(LeftToolbarButton.Openshift, timeout);
}
async waitOpenshiftConnectorTree(timeout: number = TimeoutConstants.TS_WAIT_OPENSHIFT_CONNECTOR_TREE_TIMEOUT) {
Logger.debug(`OpenshiftPlugin.waitOpenshiftConnectorTree`);
await this.driverHelper.waitPresence(By.id('openshiftProjectExplorer'), timeout);
}
async clickOnOpenshiftConnectorTree(timeout: number = TimeoutConstants.TS_WAIT_OPENSHIFT_CONNECTOR_TREE_TIMEOUT) {
Logger.debug(`OpenshiftPlugin.clickOnOpenshiftConnectorTree`);
await this.driverHelper.waitAndClick(By.id('plugin-view:openshiftProjectExplorer'), timeout);
}
async clickOnApplicationToolbarItem(item: OpenshiftAppExplorerToolbar, timeout: number = TimeoutConstants.TS_SELENIUM_CLICK_ON_VISIBLE_ITEM) {
Logger.debug(`OpenshiftPlugin.clickOnApplicationToolbarItem`);
await this.driverHelper.waitAndClick(By.css(`div [title='${item}']`), timeout);
}
async getClusterIP(timeout: number = TimeoutConstants.TS_GET_CLUSTER_IP_TIMEOUT): Promise<string> {
Logger.debug(`OpenshiftPlugin.getClusterIP`);
return await this.driverHelper.waitAndGetText(By.xpath('//div[@id=\'openshiftProjectExplorer\']//div[@title [contains(text(), https)]]'), timeout);
}
async waitItemInTree(item: string, timeout: number = TimeoutConstants.TS_SELENIUM_TERMINAL_DEFAULT_TIMEOUT) {
Logger.debug(`OpenshiftPlugin.waitItemInTree`);
await this.driverHelper.waitPresence(By.xpath(`//div[contains(@id, ':${item}')]`), timeout);
}
async clickOnItemInTree(item: string, timeout: number = TimeoutConstants.TS_SELENIUM_CLICK_ON_VISIBLE_ITEM) {
Logger.debug(`OpenshiftPlugin.clickOnItemInTree`);
await this.driverHelper.waitAndClick(By.xpath(`//div[contains(@id, ':${item}')]`), timeout);
}
async invokeContextMenuOnItem(treeItem: string) {
Logger.debug(`OpenshiftPlugin.invokeContextMenuOnItem`);
await this.contextMenu.invokeContextMenuOnTheElementWithMouse(By.xpath(`//div[contains(@id, ':${treeItem}')]`));
}
async invokeContextMenuCommandOnItem(treeItem: string, menuItem: OpenshiftContextMenuItems) {
Logger.debug(`OpenshiftPlugin.clickOnItemInTree`);
await this.contextMenu.invokeContextMenuOnTheElementWithMouse(By.xpath(`//div[contains(@id, ':${treeItem}')]`));
await this.contextMenu.waitContextMenuAndClickOnItem(menuItem);
}
}

View File

@ -1,131 +0,0 @@
/*********************************************************************
* Copyright (c) 2019 Red Hat, Inc.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/
import { injectable, inject } from 'inversify';
import { CLASSES } from '../../inversify.types';
import { DriverHelper } from '../../utils/DriverHelper';
import { By, error, Key } from 'selenium-webdriver';
import { TestConstants } from '../../TestConstants';
import { Ide } from './Ide';
import { Logger } from '../../utils/Logger';
import { TimeoutConstants } from '../../TimeoutConstants';
@injectable()
export class PreviewWidget {
private static readonly WIDGET_URL_LOCATOR: By = By.css('div.theia-mini-browser input');
constructor(@inject(CLASSES.DriverHelper) private readonly driverHelper: DriverHelper,
@inject(CLASSES.Ide) private readonly ide: Ide) { }
async waitUrl(expectedUrl: string, timeout: number = TimeoutConstants.TS_WAIT_URL_TIMEOUT) {
Logger.debug(`PreviewWidget.waitUrl ${expectedUrl}`);
await this.driverHelper.waitAttributeValue(PreviewWidget.WIDGET_URL_LOCATOR, 'value', expectedUrl, timeout);
}
async typeUrl(url: string, timeout: number = TimeoutConstants.TS_SELENIUM_CLICK_ON_VISIBLE_ITEM) {
Logger.debug(`PreviewWidget.typeUrl ${url}`);
await this.driverHelper.type(PreviewWidget.WIDGET_URL_LOCATOR, url, timeout);
}
async clearUrl() {
Logger.debug('PreviewWidget.clearUrl');
await this.typeUrl(Key.chord(Key.CONTROL, 'a', Key.DELETE));
await this.waitUrl('');
}
async typeAndApplyUrl(url: string, timeout: number = TimeoutConstants.TS_SELENIUM_CLICK_ON_VISIBLE_ITEM) {
Logger.debug(`PreviewWidget.typeAndApplyUrl ${url}`);
await this.clearUrl();
await this.typeUrl(Key.chord(url, Key.ENTER), timeout);
}
async waitApplicationOpened(expectedUrl: string, timeout: number) {
Logger.debug(`PreviewWidget.waitApplicationOpened ${expectedUrl}`);
await this.driverHelper.getDriver().wait(async () => {
try {
await this.waitUrl(expectedUrl, timeout / 5);
return true;
} catch (err) {
if (!(err instanceof error.TimeoutError)) {
throw err;
}
await this.typeAndApplyUrl(expectedUrl, timeout);
}
}, timeout);
}
async waitAndSwitchToWidgetFrame() {
Logger.debug('PreviewWidget.waitAndSwitchToWidgetFrame');
const iframeLocator: By = By.css('div.theia-mini-browser iframe');
await this.driverHelper.waitAndSwitchToFrame(iframeLocator, TimeoutConstants.TS_SELENIUM_PREVIEW_WIDGET_DEFAULT_TIMEOUT);
}
async waitPreviewWidgetAbsence() {
Logger.debug('PreviewWidget.waitPreviewWidgetAbsence');
await this.driverHelper.waitDisappearance(By.css('div.theia-mini-browser'));
}
async waitContentAvailable(contentLocator: By,
timeout: number,
polling: number = TestConstants.TS_SELENIUM_DEFAULT_POLLING * 5) {
Logger.debug(`PreviewWidget.waitContentAvailable ${contentLocator}`);
await this.waitAndSwitchToWidgetFrame();
await this.driverHelper.getDriver().wait(async () => {
const isApplicationTitleVisible: boolean = await this.driverHelper.isVisible(contentLocator);
if (isApplicationTitleVisible) {
await this.driverHelper.getDriver().switchTo().defaultContent();
await this.ide.waitAndSwitchToIdeFrame();
return true;
}
await this.switchBackToIdeFrame();
await this.refreshPage();
await this.waitAndSwitchToWidgetFrame();
await this.driverHelper.wait(polling);
}, timeout);
}
async waitVisibility(element: By, timeout: number) {
Logger.debug(`PreviewWidget.waitVisibility ${element}`);
await this.driverHelper.waitVisibility(element, timeout);
}
async waitAndClick(element: By, timeout: number = TimeoutConstants.TS_SELENIUM_PREVIEW_WIDGET_DEFAULT_TIMEOUT) {
Logger.debug(`PreviewWidget.waitAndClick ${element}`);
await this.driverHelper.waitAndClick(element, timeout);
}
async refreshPage() {
Logger.debug('PreviewWidget.refreshPage');
const refreshButtonLocator: By = By.css('.theia-mini-browser .theia-mini-browser-refresh');
await this.driverHelper.waitAndClick(refreshButtonLocator);
}
async switchBackToIdeFrame() {
Logger.debug('PreviewWidget.switchBackToIdeFrame');
await this.driverHelper.getDriver().switchTo().defaultContent();
await this.ide.waitAndSwitchToIdeFrame();
}
}

View File

@ -1,335 +0,0 @@
/*********************************************************************
* Copyright (c) 2019 Red Hat, Inc.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/
import 'reflect-metadata';
import { injectable, inject } from 'inversify';
import { DriverHelper } from '../../utils/DriverHelper';
import { CLASSES } from '../../inversify.types';
import { Ide, LeftToolbarButton } from './Ide';
import { TestConstants } from '../../TestConstants';
import { By, error } from 'selenium-webdriver';
import { Editor } from './Editor';
import { Logger } from '../../utils/Logger';
import { TimeoutConstants } from '../../TimeoutConstants';
@injectable()
export class ProjectTree {
private static readonly PROJECT_TREE_CONTAINER_CSS: string = '#theia-left-side-panel .theia-TreeContainer';
constructor(
@inject(CLASSES.DriverHelper) private readonly driverHelper: DriverHelper,
@inject(CLASSES.Ide) private readonly ide: Ide,
@inject(CLASSES.Editor) private readonly editor: Editor) { }
async clickCollapseAllButton() {
Logger.debug('ProjectTree.clickCollapseAllButton');
const collapseAllButtonLocator: By = By.id('navigator.collapse.all');
await this.driverHelper.waitAndClick(collapseAllButtonLocator);
}
async waitTreeCollapsed(projectName: string, rootSubItem: string) {
Logger.debug(`ProjectTree.waitTreeCollapsed project: "${projectName}", subitem: "${rootSubItem}"`);
const rootSubitemLocator: By = By.css(this.getTreeItemCssLocator(`${projectName}/${rootSubItem}`));
await this.driverHelper.waitDisappearanceWithTimeout(rootSubitemLocator, TimeoutConstants.TS_SELENIUM_CLICK_ON_VISIBLE_ITEM);
}
async collapseProjectTree(projectName: string, rootSubItem: string) {
Logger.debug(`ProjectTree.collapseProjectTree project: "${projectName}", subitem: "${rootSubItem}"`);
await this.clickCollapseAllButton();
await this.waitTreeCollapsed(projectName, rootSubItem);
}
async waitAssociatedWorkspaceProjectTreeCollapsed(projectName: string, expandedRootItem: string) {
Logger.debug(`ProjectTree.waitTreeCollapsed project name: "${projectName}", expanded root item: "${expandedRootItem}"`);
// const rootSubitemLocator: By = By.css(this.getTreeItemCssLocator(`${projectName}/${expandedRootItem}`));
await this.waitItemCollapsed(`${projectName}/${expandedRootItem}`);
}
async openProjectTreeContainer(timeout: number = TimeoutConstants.TS_PROJECT_TREE_TIMEOUT) {
Logger.debug('ProjectTree.openProjectTreeContainer');
const explorerButtonActiveLocator: By = this.getLeftToolbarButtonActiveLocator(LeftToolbarButton.Explorer);
Logger.trace(`ProjectTree.openProjectTreeContainer waitLeftToolbarButtonPresence`);
await this.ide.waitLeftToolbarButton(LeftToolbarButton.Explorer, timeout);
const isButtonActive: boolean = await this.driverHelper.waitVisibilityBoolean(explorerButtonActiveLocator);
Logger.trace(`ProjectTree.openProjectTreeContainer leftToolbarButtonActive:${isButtonActive}`);
if (!isButtonActive) {
await this.ide.waitAndClickLeftToolbarButton(LeftToolbarButton.Explorer, timeout);
}
await this.waitProjectTreeContainer();
}
async waitItemExpanded(itemPath: string, timeout: number = TimeoutConstants.TS_PROJECT_TREE_TIMEOUT) {
Logger.debug(`ProjectTree.waitItemExpanded "${itemPath}"`);
const locator: string = await this.getExpandedItemCssLocator(itemPath);
const expandedItemLocator: By = By.css(locator);
await this.driverHelper.waitVisibility(expandedItemLocator, timeout);
}
async waitItemCollapsed(itemPath: string, timeout: number = TimeoutConstants.TS_PROJECT_TREE_TIMEOUT) {
Logger.debug(`ProjectTree.waitItemCollapsed "${itemPath}"`);
const locator: string = await this.getCollapsedItemCssLocator(itemPath);
const collapsedItemLocator: By = By.css(locator);
await this.driverHelper.waitVisibility(collapsedItemLocator, timeout);
}
async waitProjectTreeContainer(timeout: number = TimeoutConstants.TS_PROJECT_TREE_TIMEOUT) {
Logger.debug('ProjectTree.waitProjectTreeContainer');
await this.driverHelper.waitPresence(By.css(ProjectTree.PROJECT_TREE_CONTAINER_CSS), timeout);
}
async waitProjectTreeContainerClosed(attempts: number = TestConstants.TS_SELENIUM_DEFAULT_ATTEMPTS,
polling: number = TestConstants.TS_SELENIUM_DEFAULT_POLLING) {
Logger.debug('ProjectTree.waitProjectTreeContainerClosed');
await this.driverHelper.waitDisappearance(By.css(ProjectTree.PROJECT_TREE_CONTAINER_CSS), attempts, polling);
}
async waitItem(itemPath: string, timeout: number = TimeoutConstants.TS_PROJECT_TREE_TIMEOUT) {
Logger.debug(`ProjectTree.waitItem "${itemPath}"`);
const locator: string = await this.getItemCss(itemPath);
await this.driverHelper.waitVisibility(By.css(locator), timeout);
}
async waitItemDisappearance(itemPath: string,
attempts: number = TestConstants.TS_SELENIUM_DEFAULT_ATTEMPTS,
polling: number = TestConstants.TS_SELENIUM_DEFAULT_POLLING) {
Logger.debug(`ProjectTree.waitItemDisappearance "${itemPath}"`);
const locator: string = await this.getItemCss(itemPath);
await this.driverHelper.waitDisappearance(By.css(locator), attempts, polling);
}
async clickOnItem(itemPath: string, timeout: number = TimeoutConstants.TS_PROJECT_TREE_CLICK_ON_ITEM_TIMEOUT) {
Logger.debug(`ProjectTree.clickOnItem "${itemPath}"`);
const locator: string = await this.getItemCss(itemPath);
await this.driverHelper.waitAndClick(By.css(locator), timeout);
await this.waitItemSelected(itemPath, timeout);
}
async waitItemSelected(itemPath: string, timeout: number = TimeoutConstants.TS_PROJECT_TREE_TIMEOUT) {
Logger.debug(`ProjectTree.waitItemSelected "${itemPath}"`);
const selectedItemLocator: By = By.css(`div[title='/projects/${itemPath}'].theia-mod-selected.theia-mod-focus`);
await this.driverHelper.waitVisibility(selectedItemLocator, timeout);
}
async expandItem(itemPath: string, timeout: number = TimeoutConstants.TS_PROJECT_TREE_CLICK_ON_ITEM_TIMEOUT) {
Logger.debug(`ProjectTree.expandItem "${itemPath}"`);
const locator: string = await this.getExpandIconCssLocator(itemPath);
const expandIconLocator: By = By.css(locator);
const treeItemLocator: By = By.css(this.getTreeItemCssLocator(itemPath));
await this.driverHelper.getDriver().wait(async () => {
const classAttributeValue: string = await this.driverHelper.waitAndGetElementAttribute(expandIconLocator, 'class', timeout);
const isItemCollapsed: boolean = classAttributeValue.search('theia-mod-collapsed') > 0;
if (isItemCollapsed) {
await this.driverHelper.waitAndClick(treeItemLocator, timeout);
}
try {
await this.waitItemExpanded(itemPath, TestConstants.TS_SELENIUM_DEFAULT_POLLING);
return true;
} catch (err) {
if (!(err instanceof error.TimeoutError)) {
throw err('Unexpected error during project tree expanding');
}
console.log(`The '${itemPath}' item has not been expanded, try again`);
await this.driverHelper.wait(TestConstants.TS_SELENIUM_DEFAULT_POLLING);
}
}, timeout);
}
async collapseItem(itemPath: string, timeout: number = TimeoutConstants.TS_PROJECT_TREE_CLICK_ON_ITEM_TIMEOUT) {
Logger.debug(`ProjectTree.collapseItem "${itemPath}"`);
const locator: string = await this.getExpandIconCssLocator(itemPath);
const expandIconLocator: By = By.css(locator);
const treeItemLocator: By = By.css(this.getTreeItemCssLocator(itemPath));
const classAttributeValue: string = await this.driverHelper.waitAndGetElementAttribute(expandIconLocator, 'class', timeout);
const isItemCollapsed: boolean = classAttributeValue.search('theia-mod-collapsed') > 0;
if (!isItemCollapsed) {
await this.driverHelper.waitAndClick(treeItemLocator, timeout);
}
await this.waitItemCollapsed(itemPath, timeout);
}
async expandPath(path: string, timeout: number = TimeoutConstants.TS_EXPAND_PROJECT_TREE_ITEM_TIMEOUT) {
Logger.debug(`ProjectTree.expandPath "${path}"`);
let items: Array<string> = path.split('/');
let projectName: string = items[0];
let paths: Array<string> = new Array();
paths.push(projectName);
// make direct path for each project tree item
for (let i = 1; i < items.length; i++) {
let item = items[i];
projectName = `${projectName}/${item}`;
paths.push(projectName);
}
// expand each project tree item
for (const path of paths) {
await this.expandItem(path, timeout);
}
}
/**
*
* @param pathToItem path to the file that should be opened
* @param fileName file that should be opened
* @param timeoutForSigleItem timeout applied for every item in path to be opened
*/
async expandPathAndOpenFile(pathToItem: string, fileName: string, timeoutForSigleItem: number = TimeoutConstants.TS_OPEN_EDITOR_TIMEOUT) {
Logger.debug(`ProjectTree.expandPathAndOpenFile "${pathToItem}" filename: ${fileName}`);
await this.expandPath(pathToItem, timeoutForSigleItem);
await this.clickOnItem(`${pathToItem}/${fileName}`, timeoutForSigleItem);
await this.editor.waitEditorOpened(fileName);
await this.editor.waitTab(fileName);
}
async waitProjectImported(projectName: string,
rootSubItem: string,
attempts: number = TestConstants.TS_SELENIUM_DEFAULT_ATTEMPTS,
visibilityItemPolling: number = TimeoutConstants.TS_IMPORT_PROJECT_DEFAULT_POLLING,
triesPolling: number = TestConstants.TS_SELENIUM_DEFAULT_POLLING * 30) {
Logger.debug(`ProjectTree.waitProjectImported "${projectName}" rootSubItem: "${rootSubItem}"`);
const rootItem: string = `${projectName}`;
const rootItemLocator: By = By.css(this.getTreeItemCssLocator(`${projectName}`));
const rootSubitemLocator: By = By.css(this.getTreeItemCssLocator(`${projectName}/${rootSubItem}`));
for (let i = 0; i < attempts; i++) {
// do five checks of the item in one fifth of the time given for root folder item (was causing frequent reloads of the workspace)
const isProjectFolderVisible = await this.driverHelper.waitVisibilityBoolean(rootItemLocator, 5, visibilityItemPolling / 5);
if (!isProjectFolderVisible) {
Logger.trace(`ProjectTree.waitProjectImported project not located, reloading page.`);
await this.driverHelper.reloadPage();
await this.ide.waitAndSwitchToIdeFrame();
await this.ide.waitIde();
await this.openProjectTreeContainer();
continue;
}
Logger.trace(`ProjectTree.waitProjectImported project found, waiting for sub-items`);
await this.expandItem(rootItem);
await this.waitItemExpanded(rootItem);
// do five checks of the item in one fifth of the time given for root folder item (was causing frequent reloads of the workspace)
const isRootSubItemVisible = await this.driverHelper.waitVisibilityBoolean(rootSubitemLocator, 5, visibilityItemPolling / 5);
if (!isRootSubItemVisible) {
Logger.trace(`ProjectTree.waitProjectImported sub-items not found, reloading page.`);
await this.driverHelper.reloadPage();
await this.ide.waitAndSwitchToIdeFrame();
await this.ide.waitIde();
await this.openProjectTreeContainer();
continue;
}
return;
}
throw new error.TimeoutError('Exceeded the maximum number of checking attempts, project has not been imported');
}
async waitProjectImportedNoSubfolder(projectName: string,
attempts: number = TestConstants.TS_SELENIUM_DEFAULT_ATTEMPTS,
visibilityItemPolling: number = TestConstants.TS_SELENIUM_DEFAULT_POLLING * 5,
triesPolling: number = TestConstants.TS_SELENIUM_DEFAULT_POLLING * 90) {
Logger.debug(`ProjectTree.waitProjectImportedNoSubfolder "${projectName}"`);
const rootItemLocator: By = By.css(this.getTreeItemCssLocator(`${projectName}`));
for (let i = 0; i < attempts; i++) {
const isProjectFolderVisible = await this.driverHelper.waitVisibilityBoolean(rootItemLocator, 1, visibilityItemPolling);
if (!isProjectFolderVisible) {
Logger.trace(`ProjectTree.waitProjectImportedNoSubfolder project not located, reloading page.`);
await this.driverHelper.reloadPage();
await this.driverHelper.wait(triesPolling);
await this.ide.waitAndSwitchToIdeFrame();
await this.ide.waitIde();
await this.openProjectTreeContainer();
continue;
}
return;
}
throw new error.TimeoutError('Exceeded the maximum number of checking attempts, project has not been imported');
}
private async getWorkspacePathEntry(): Promise<string> {
const nodeAttribute: string = 'data-node-id';
const splitDelimeter = ':';
const attribute: string = await this.driverHelper.waitAndGetElementAttribute(By.css(`div[${nodeAttribute}]`), nodeAttribute, TimeoutConstants.TS_SELENIUM_CLICK_ON_VISIBLE_ITEM);
return attribute.split(splitDelimeter)[0] + splitDelimeter;
}
private getLeftToolbarButtonActiveLocator(buttonTitle: String): By {
return By.xpath(`//div[@id='theia-left-content-panel']//ul[@class='p-TabBar-content']` +
`//li[@title[contains(.,'${buttonTitle}')] and contains(@id, 'shell-tab') and contains(@class, 'p-mod-current')]`);
}
private async getItemCss(itemPath: string): Promise<string> {
const entry: string = await this.getWorkspacePathEntry();
return `div[id='${entry}/projects/${itemPath}']`;
}
private async getCollapsedItemCssLocator(itemPath: string): Promise<string> {
const item: string = await this.getExpandIconCssLocator(itemPath);
return item + '.theia-mod-collapsed';
}
private async getExpandedItemCssLocator(itemPath: string): Promise<string> {
const item: string = await this.getExpandIconCssLocator(itemPath);
return item + ':not(.theia-mod-collapsed)';
}
private async getExpandIconCssLocator(itemPath: string): Promise<string> {
const items: Array<string> = itemPath.split('/');
const entry: string = items.length > 1 ? await this.getWorkspacePathEntry() : '';
return `div[data-node-id='${entry}/projects/${itemPath}']`;
}
private getTreeItemCssLocator(itemPath: string): string {
return `.theia-TreeNode[title='/projects/${itemPath}']`;
}
}

View File

@ -1,59 +0,0 @@
import { injectable, inject } from 'inversify';
import { CLASSES } from '../../inversify.types';
import { DriverHelper } from '../../utils/DriverHelper';
import { By } from 'selenium-webdriver';
import { Logger } from '../../utils/Logger';
import { TimeoutConstants } from '../../TimeoutConstants';
/*********************************************************************
* Copyright (c) 2019 Red Hat, Inc.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/
@injectable()
export class QuickOpenContainer {
constructor(@inject(CLASSES.DriverHelper) private readonly driverHelper: DriverHelper) { }
public async waitContainer(timeout: number = TimeoutConstants.TS_SELENIUM_TOP_MENU_QUICK_CONTAINER_TIMEOUT) {
Logger.debug('QuickOpenContainer.waitContainer');
const monacoQuickOpenContainerLocator: By = By.xpath('//div[@class=\'monaco-quick-open-widget\']');
await this.driverHelper.waitVisibility(monacoQuickOpenContainerLocator, timeout);
}
public async waitContainerDisappearance() {
Logger.debug('QuickOpenContainer.waitContainerDisappearance');
const monacoQuickOpenContainerLocator: By = By.xpath('//div[@class=\'monaco-quick-open-widget\' and @aria-hidden=\'true\']');
await this.driverHelper.waitDisappearance(monacoQuickOpenContainerLocator);
}
public async clickOnContainerItem(itemText: string, timeout: number = TimeoutConstants.TS_SELENIUM_TOP_MENU_QUICK_CONTAINER_TIMEOUT) {
Logger.debug(`QuickOpenContainer.clickOnContainerItem "${itemText}"`);
const quickContainerItemLocator: By = By.css(`div[aria-label="${itemText}, picker"]`);
await this.waitContainer(timeout);
await this.driverHelper.waitAndClick(quickContainerItemLocator, timeout);
await this.waitContainerDisappearance();
}
public async type(text: string) {
Logger.debug(`QuickOpenContainer.type "${text}"`);
await this.driverHelper.enterValue(By.css('.quick-open-input input'), text);
}
public async typeAndSelectSuggestion(text: string, suggestedText: string) {
Logger.debug('QuickOpenContainer.typeAndSelectSuggestion');
await this.driverHelper.type(By.css('div.monaco-inputbox input.input'), text);
// sometimes the UI dropdawn may closed unexpectedly for more stability add 500ms delay.
await this.driverHelper.wait(2000);
await this.clickOnContainerItem(suggestedText);
}
}

View File

@ -1,34 +0,0 @@
/*********************************************************************
* Copyright (c) 2019 Red Hat, Inc.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/
import { injectable, inject } from 'inversify';
import { CLASSES } from '../../inversify.types';
import { DriverHelper } from '../../utils/DriverHelper';
import { By } from 'selenium-webdriver';
import { Logger } from '../../utils/Logger';
import { TimeoutConstants } from '../../TimeoutConstants';
@injectable()
export class RightToolBar {
constructor(@inject(CLASSES.DriverHelper) private readonly driverHelper: DriverHelper) { }
async waitToolbar(timeout: number = TimeoutConstants.TS_SELENIUM_TOOLBAR_TIMEOUT) {
Logger.debug('RightToolbar.waitToolbar');
await this.driverHelper.waitVisibility(By.css('div.theia-app-right'), timeout);
}
async clickOnToolIcon(iconTitle: string, timeout: number = TimeoutConstants.TS_SELENIUM_CLICK_ON_VISIBLE_ITEM) {
Logger.debug(`RightToolbar.clickOnToolIcon "${iconTitle}"`);
const toolIconLocator: By = By.css(`div.theia-app-right .p-TabBar-content li[title='${iconTitle}']`);
await this.driverHelper.waitAndClick(toolIconLocator, timeout);
}
}

View File

@ -1,242 +0,0 @@
/*********************************************************************
* Copyright (c) 2019 Red Hat, Inc.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/
import { injectable, inject } from 'inversify';
import { CLASSES } from '../../inversify.types';
import { DriverHelper } from '../../utils/DriverHelper';
import { By, Key, WebElement, error } from 'selenium-webdriver';
import { Logger } from '../../utils/Logger';
import { TimeoutConstants } from '../../TimeoutConstants';
@injectable()
export class Terminal {
private static readonly TERMINAL_ROWS_XPATH_LOCATOR_PREFFIX = '(//div[contains(@class, \'terminal-container\')]//div[contains(@class, \'terminal\')]//div[contains(@class, \'xterm-rows\')])';
constructor(@inject(CLASSES.DriverHelper) private readonly driverHelper: DriverHelper) { }
async waitTab(tabTitle: string, timeout: number = TimeoutConstants.TS_SELENIUM_TERMINAL_DEFAULT_TIMEOUT) {
Logger.debug(`Terminal.waitTab "${tabTitle}"`);
const terminalTabLocator: By = By.css(this.getTerminalTabCssLocator(tabTitle));
await this.driverHelper.waitVisibility(terminalTabLocator, timeout);
}
async waitTabAbsence(tabTitle: string, timeout: number = TimeoutConstants.TS_SELENIUM_TERMINAL_DEFAULT_TIMEOUT) {
Logger.debug(`Terminal.waitTabAbsence "${tabTitle}"`);
const terminalTabLocator: By = By.css(this.getTerminalTabCssLocator(tabTitle));
await this.driverHelper.waitDisappearanceWithTimeout(terminalTabLocator, timeout);
}
async clickOnTab(tabTitle: string, timeout: number = TimeoutConstants.TS_SELENIUM_TERMINAL_DEFAULT_TIMEOUT) {
Logger.debug(`Terminal.clickOnTab "${tabTitle}"`);
const terminalTabLocator: By = By.css(`${this.getTerminalTabCssLocator(tabTitle)} div.theia-tab-icon-label`);
await this, this.driverHelper.waitAndClick(terminalTabLocator, timeout);
}
async waitTabFocused(tabTitle: string, timeout: number = TimeoutConstants.TS_SELENIUM_TERMINAL_DEFAULT_TIMEOUT) {
Logger.debug(`Terminal.waitTabFocused "${tabTitle}"`);
const focusedTerminalTabLocator: By = this.getFocusedTerminalTabLocator(tabTitle);
await this.driverHelper.waitVisibility(focusedTerminalTabLocator, timeout);
}
async selectTerminalTab(tabTitle: string, timeout: number = TimeoutConstants.TS_SELENIUM_TERMINAL_DEFAULT_TIMEOUT) {
Logger.debug(`Terminal.selectTerminalTab "${tabTitle}"`);
await this.clickOnTab(tabTitle, timeout);
await this.waitTabFocused(tabTitle, timeout);
}
async clickOnTabCloseIcon(tabTitle: string, timeout: number = TimeoutConstants.TS_SELENIUM_TERMINAL_DEFAULT_TIMEOUT) {
Logger.debug(`Terminal.clickOnTabCloseIcon "${tabTitle}"`);
const terminalTabCloseIconLocator: By =
By.css(`${this.getTerminalTabCssLocator(tabTitle)} div.p-TabBar-tabCloseIcon`);
await this.driverHelper.waitAndClick(terminalTabCloseIconLocator, timeout);
}
async closeTerminalTab(tabTitle: string, timeout: number = TimeoutConstants.TS_SELENIUM_TERMINAL_DEFAULT_TIMEOUT) {
Logger.debug(`Terminal.closeTerminalTab "${tabTitle}"`);
await this.clickOnTabCloseIcon(tabTitle, timeout);
await this.waitTabAbsence(tabTitle, timeout);
}
async type(terminalTabTitle: string, text: string) {
Logger.debug(`Terminal.type "${terminalTabTitle}"`);
const terminalIndex: number = await this.getTerminalIndex(terminalTabTitle);
const terminalInteractionContainer: By = this.getTerminalEditorInteractionEditorLocator(terminalIndex);
await this.driverHelper.typeToInvisible(terminalInteractionContainer, text);
}
async rejectTerminalProcess(tabTitle: string, timeout: number = TimeoutConstants.TS_SELENIUM_TERMINAL_DEFAULT_TIMEOUT) {
Logger.debug(`Terminal.rejectTerminalProcess "${tabTitle}"`);
await this.selectTerminalTab(tabTitle, timeout);
await this.type(tabTitle, Key.chord(Key.CONTROL, 'c'));
}
async getText(terminalTab: string, timeout: number = TimeoutConstants.TS_SELENIUM_TERMINAL_DEFAULT_TIMEOUT): Promise<string> {
Logger.debug(`Terminal.getText tab: ${terminalTab}`);
const terminalIndex: number = await this.getTerminalIndex(terminalTab);
await this.selectTerminalTab(terminalTab, timeout);
return await this.driverHelper.waitAndGetText(By.xpath(Terminal.TERMINAL_ROWS_XPATH_LOCATOR_PREFFIX + `[${terminalIndex}]`), timeout);
}
async getTextFromProblemsTab(timeout: number = TimeoutConstants.TS_SELENIUM_TERMINAL_DEFAULT_TIMEOUT): Promise<string> {
Logger.debug(`Terminal.getTextFromProblemsTab`);
const problemsTabBodyLocator: By = By.xpath(`//div[@id='problems']`);
return await this.driverHelper.waitAndGetText(problemsTabBodyLocator, timeout);
}
async selectTabByPrefixAndWaitText(terminalTab: string, expectedText: string, timeout: number = TimeoutConstants.TS_SELENIUM_TERMINAL_DEFAULT_TIMEOUT) {
Logger.debug(`Terminal.selectTabByPrefixAndWaitText tab: ${terminalTab} text: ${expectedText}`);
const terminalTabLocatorWithPreffix: string = `//li[contains(@title, '${terminalTab}')]`;
const terminalIndex: number = await this.getTerminalIndex(terminalTab);
await this.driverHelper.waitAndClick(By.xpath(terminalTabLocatorWithPreffix), timeout);
await this.driverHelper.waitUntilTrue(async () => {
const terminalText: string = await this.driverHelper.waitAndGetText(By.xpath(Terminal.TERMINAL_ROWS_XPATH_LOCATOR_PREFFIX + `[${terminalIndex}]`), timeout);
return terminalText.includes(expectedText);
}, timeout);
}
async waitText(terminalTab: string, expectedText: string, timeout: number) {
Logger.debug(`Terminal.waitText tab: ${terminalTab} text: ${expectedText}`);
await this.selectTerminalTab(terminalTab, timeout);
await this.driverHelper.waitUntilTrue(async () => {
// separates each method iteration to the readable blocks in the terminal log
Logger.debug('----------------------------------------------');
const terminalText: string = await this.getText(terminalTab, timeout);
if (terminalText.includes(expectedText)) {
Logger.debug('Expected text is present in the terminal output');
return true;
}
Logger.debug('Expected text is not present in the terminal output');
await this.driverHelper.wait(1000);
return false;
}, timeout);
}
async waitTextInProblemsTab(expectedText: string, timeout: number) {
Logger.debug(`Terminal.waitTextInProblemsTab`);
await this.selectTerminalTab('Problems', timeout);
await this.driverHelper.waitUntilTrue(async () => {
// separates each method iteration to the readable blocks in the terminal log
Logger.debug('----------------------------------------------');
const terminalText: string = await this.getTextFromProblemsTab(timeout);
if (terminalText.includes(expectedText)) {
Logger.debug('Expected text is present in the terminal output');
return true;
}
Logger.debug('Expected text is not present in the terminal output');
await this.driverHelper.wait(1000);
return false;
}, timeout);
}
public async waitIconSuccess(taskName: string, timeout: number) {
const terminalTabLocator: By = By.css(`${this.getTerminalTabCssLocator(taskName)} div.p-TabBar-tabIcon`);
await this.driverHelper.waitVisibility(terminalTabLocator, TimeoutConstants.TS_SELENIUM_TERMINAL_DEFAULT_TIMEOUT);
let terminalClass = await this.driverHelper.waitAndGetElementAttribute(terminalTabLocator, 'class');
await this.driverHelper.getDriver().wait(async () => {
terminalClass = await this.driverHelper.waitAndGetElementAttribute(terminalTabLocator, 'class');
if (terminalClass.includes('fa-check')) { // css for tick icon
return true;
}
if (terminalClass.includes('fa-times-circle')) { // css for failed icon
Logger.error('Task "' + taskName + '" failed.');
throw new Error('Task "' + taskName + '" failed.');
}
return false;
}, timeout, 'Timed out waiting for task ' + taskName + ' to succeed.');
}
private getTerminalTabCssLocator(tabTitle: string): string {
return `li[title='${tabTitle}']`;
}
private getFocusedTerminalTabLocator(tabTitle: string): By {
return By.css(`li[title='${tabTitle}'].p-mod-current.theia-mod-active`);
}
private async getTerminalIndex(terminalTitle: string): Promise<number> {
for (let i: number = 0; i < 10; i++) {
try {
return await this.searchTerminalIndex(terminalTitle);
} catch (err) {
if (!(err instanceof error.NoSuchElementError)) {
throw err;
}
if ((err instanceof error.NoSuchElementError) && (i === 9)) {
throw err;
}
await this.driverHelper.wait(2000);
}
}
throw new error.NoSuchElementError(`The terminal with title '${terminalTitle}' has not been found.`);
}
private async searchTerminalIndex(terminalTitle: string): Promise<number> {
const terminalTabTitleXpathLocator: string = `//div[@id='theia-bottom-content-panel']` +
`//li[contains(@id, 'shell-tab-terminal') or contains(@id, 'shell-tab-plugin')]` +
`//div[@class='p-TabBar-tabLabel']`;
const terminalTabs: WebElement[] = await this.driverHelper.waitAllPresence(By.xpath(terminalTabTitleXpathLocator));
let terminalTitles: string[] = [];
for (let i: number = 1; i <= terminalTabs.length; i++) {
const terminalTabLocator: By = By.xpath(`(${terminalTabTitleXpathLocator})[${i}]`);
const currentTerminalTitle: string = await this.driverHelper.waitAndGetText(terminalTabLocator);
if (currentTerminalTitle.search(terminalTitle) > -1) {
return i;
}
terminalTitles.push(currentTerminalTitle);
}
throw new error.NoSuchElementError(`The terminal with title '${terminalTitle}' has not been found.\n` +
` > List of the tabs:\n > ${terminalTitles}`);
}
private getTerminalEditorInteractionEditorLocator(terminalIndex: number): By {
return By.xpath(`(//textarea[@aria-label='Terminal input'])[${terminalIndex}]`);
}
}

View File

@ -1,103 +0,0 @@
import { injectable, inject } from 'inversify';
import { CLASSES } from '../../inversify.types';
import { DriverHelper } from '../../utils/DriverHelper';
import { By, error } from 'selenium-webdriver';
import { Logger } from '../../utils/Logger';
import { QuickOpenContainer } from './QuickOpenContainer';
import { TimeoutConstants } from '../../TimeoutConstants';
/*********************************************************************
* Copyright (c) 2019 Red Hat, Inc.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/
@injectable()
export class TopMenu {
private static readonly TOP_MENU_BUTTONS: string[] = ['File', 'Edit', 'Selection', 'View', 'Go', 'Run', 'Terminal', 'Help'];
constructor(@inject(CLASSES.DriverHelper) private readonly driverHelper: DriverHelper,
@inject(CLASSES.QuickOpenContainer) private readonly quickOpenContainer: QuickOpenContainer) { }
public async waitTopMenu(timeout: number = TimeoutConstants.TS_SELENIUM_TOOLBAR_TIMEOUT) {
Logger.debug('TopMenu.waitTopMenu');
for (const buttonText of TopMenu.TOP_MENU_BUTTONS) {
const buttonLocator: By = this.getTopMenuButtonLocator(buttonText);
await this.driverHelper.waitVisibility(buttonLocator, timeout);
}
}
public async selectOption(topMenuButtonText: string, submenuItemtext: string) {
Logger.debug(`TopMenu.selectOption "${topMenuButtonText}"`);
await this.clickOnTopMenuButton(topMenuButtonText);
await this.clickOnSubmenuItem(submenuItemtext);
}
public async clickOnTopMenuButton(buttonText: string, timeout: number = TimeoutConstants.TS_SELENIUM_CLICK_ON_VISIBLE_ITEM) {
Logger.debug(`TopMenu.clickOnTopMenuButton "${buttonText}"`);
const buttonLocator: By = this.getTopMenuButtonLocator(buttonText);
await this.driverHelper.waitAndClick(buttonLocator, timeout);
}
public async clickOnSubmenuItem(itemText: string, timeout: number = TimeoutConstants.TS_SELENIUM_CLICK_ON_VISIBLE_ITEM) {
Logger.debug(`TopMenu.clickOnSubmenuItem "${itemText}"`);
const submenuItemLocator: By = this.getSubmenuItemLocator(itemText);
// to ensure that drop-down animation is over
await this.driverHelper.wait(3000);
await this.driverHelper.waitAndClick(submenuItemLocator, timeout);
}
public async runTask(task: string) {
await this.selectOption('Terminal', 'Run Task...');
try {
await this.quickOpenContainer.waitContainer();
} catch (err) {
if (err instanceof error.TimeoutError) {
console.log(`After clicking to the "Terminal" -> "Run Task ..." the "Quick Open Container" has not been displayed, one more try`);
await this.selectOption('Terminal', 'Run Task...');
await this.quickOpenContainer.waitContainer();
}
}
await this.quickOpenContainer.clickOnContainerItem(task);
}
public async openTerminalForSpecificContainer(containerName: string) {
await this.selectOption('Terminal', 'Open Terminal in specific container');
try {
await this.quickOpenContainer.waitContainer();
} catch (err) {
if (err instanceof error.TimeoutError) {
Logger.info(`After clicking to the "Terminal" -> "Open Terminal in specific container" the "Quick Open Container" has not been displayed, one more try`);
await this.selectOption('Terminal', 'Open Terminal in specific container');
await this.quickOpenContainer.waitContainer();
}
}
await this.quickOpenContainer.clickOnContainerItem(containerName);
}
private getTopMenuButtonLocator(buttonText: string): By {
return By.xpath(`//div[@id='theia:menubar']//div[@class='p-MenuBar-itemLabel' and text()='${buttonText}']`);
}
private getSubmenuItemLocator(submenuItemtext: string): By {
return By.xpath(`//ul[@class='p-Menu-content']//li[@data-type='command']//div[text()='${submenuItemtext}']`);
}
}

View File

@ -1,105 +0,0 @@
import 'reflect-metadata';
import { injectable, inject } from 'inversify';
import { CLASSES } from '../../../inversify.types';
import { DriverHelper } from '../../../utils/DriverHelper';
import { Logger } from '../../../utils/Logger';
import { By } from 'selenium-webdriver';
import { TimeoutConstants } from '../../../TimeoutConstants';
import { LeftToolBar } from '../LeftToolBar';
@injectable()
export class KubernetesPlugin {
constructor(@inject(CLASSES.DriverHelper) private readonly driverHelper: DriverHelper,
@inject(CLASSES.LeftToolBar) private readonly leftToolbar: LeftToolBar) { }
async openView(timeout: number = TimeoutConstants.TS_PROJECT_TREE_TIMEOUT) {
Logger.debug(`KubernetesPlugin.openView`);
await this.leftToolbar.selectView('Kubernetes', timeout);
}
async clickToSection(sectionTitle: string, timeout: number = TimeoutConstants.TS_PROJECT_TREE_TIMEOUT) {
Logger.debug(`KubernetesPlugin.clickToSection ${sectionTitle}`);
const sectionLocator: By = By.xpath(this.getSectionLocator(sectionTitle));
await this.driverHelper.waitAndClick(sectionLocator, timeout);
}
async isSectionExpanded(sectionTitle: string): Promise<boolean> {
Logger.debug(`KubernetesPlugin.isSectionExpanded ${sectionTitle}`);
const expandedsectionLocator: By = this.getExpandedSectionLocator(sectionTitle);
return await this.driverHelper.isVisible(expandedsectionLocator);
}
async waitSectionExpanded(sectionTitle: string, timeout: number = TimeoutConstants.TS_PROJECT_TREE_TIMEOUT) {
Logger.debug(`KubernetesPlugin.waitSectionExpanded ${sectionTitle}`);
await this.driverHelper.waitVisibility(this.getExpandedSectionLocator(sectionTitle), timeout);
}
async waitSectionCollapsed(sectionTitle: string, timeout: number = TimeoutConstants.TS_PROJECT_TREE_TIMEOUT) {
Logger.debug(`KubernetesPlugin.waitSectionCollapsed ${sectionTitle}`);
await this.driverHelper.waitVisibility(this.getCollapsedSectionLocator(sectionTitle), timeout);
}
async expandSection(sectionTitle: string, timeout: number = TimeoutConstants.TS_PROJECT_TREE_TIMEOUT) {
Logger.debug(`KubernetesPlugin.expandSection ${sectionTitle}`);
if (await this.isSectionExpanded(sectionTitle)) {
return;
}
await this.clickToSection(sectionTitle, timeout);
await this.waitSectionExpanded(sectionTitle, timeout);
}
async clickToRefreshButton(sectionTitle: string, timeout: number = TimeoutConstants.TS_PROJECT_TREE_TIMEOUT) {
Logger.debug(`KubernetesPlugin.clickToRefreshButton`);
const refreshButtonLocator: By = By.xpath(`//div[contains(@class, 'theia-header')]//div[contains(@class, 'theia-view-container-part-title')]//div[@title='Refresh']`);
const sectionTitleLocator: By = By.xpath(this.getSectionLocator(sectionTitle));
await this.driverHelper.scrollTo(sectionTitleLocator, timeout);
await this.driverHelper.waitAndClick(refreshButtonLocator, timeout);
}
async waitListItemContains(partialText: string, timeout: number = TimeoutConstants.TS_PROJECT_TREE_TIMEOUT) {
Logger.debug(`KubernetesPlugin.waitListItemContains ${partialText}`);
await this.driverHelper.waitVisibility(this.getListItemPartialTextLocator(partialText), timeout);
}
async waitListItem(expectedText: string, timeout: number = TimeoutConstants.TS_PROJECT_TREE_TIMEOUT) {
Logger.debug(`KubernetesPlugin.waitListItem ${expectedText}`);
await this.driverHelper.waitVisibility(this.getListItemTextLocator(expectedText), timeout);
}
private getSectionLocator(sectionTitle: string): string {
return `//div[contains(@class, 'theia-header')]//span[@title='${sectionTitle}']`;
}
private getExpandedSectionLocator(sectionTitle: string): By {
return By.xpath(`${this.getSectionLocator(sectionTitle)}/parent::div/span[contains(@class, 'theia-ExpansionToggle') and not(contains(@class, 'theia-mod-collapsed'))]`);
}
private getCollapsedSectionLocator(sectionTitle: string): By {
return By.xpath(`${this.getSectionLocator(sectionTitle)}/parent::div/span[contains(@class, 'theia-ExpansionToggle') and contains(@class, 'theia-mod-collapsed')]`);
}
private getListItemPartialTextLocator(partialText: string): By {
return By.xpath(`//div[contains(@class, 'body')]//div[@class='theia-TreeContainer']//div[@class='theia-TreeNodeContent']//span[contains(text(), '${partialText}')]`);
}
private getListItemTextLocator(expectedText: string): By {
return By.xpath(`//div[contains(@class, 'body')]//div[@class='theia-TreeContainer']//div[@class='theia-TreeNodeContent']//span[text()='${expectedText}']`);
}
}

View File

@ -1,183 +0,0 @@
import 'reflect-metadata';
import { injectable, inject } from 'inversify';
import { CLASSES } from '../../../inversify.types';
import { DriverHelper } from '../../../utils/DriverHelper';
import { Logger } from '../../../utils/Logger';
import { By, error } from 'selenium-webdriver';
import { TimeoutConstants } from '../../../TimeoutConstants';
import { LeftToolBar } from '../LeftToolBar';
import { TopMenu } from '../TopMenu';
@injectable()
export class PluginsView {
private static readonly SEARCH_FIELD_LOCATOR: By = By.xpath(`//div[@class='che-plugin-control-panel']//input`);
private static readonly PLUGINS_LOADER: By = By.xpath(`//div[@id='theia-left-side-panel']//div[@class='spinnerContainer']`);
constructor(@inject(CLASSES.DriverHelper) private readonly driverHelper: DriverHelper,
@inject(CLASSES.LeftToolBar) private readonly leftToolbar: LeftToolBar,
@inject(CLASSES.TopMenu) private readonly topMenu: TopMenu) { }
async waitTitle(timeout: number = TimeoutConstants.TS_COMMON_PLUGIN_TEST_TIMEOUT) {
Logger.debug('PluginsView.waitTitle');
await this.driverHelper.waitVisibility(By.xpath(`//div[@title='Plugins']`), timeout);
}
async waitPluginsLoader(timeout: number = TimeoutConstants.TS_COMMON_PLUGIN_TEST_TIMEOUT) {
Logger.debug('PluginsView.waitPluginsLoader');
await this.driverHelper.waitVisibility(PluginsView.PLUGINS_LOADER, timeout);
}
async waitPluginsLoaderDisappearance(timeout: number = TimeoutConstants.TS_COMMON_PLUGIN_TEST_TIMEOUT) {
Logger.debug('PluginsView.waitPluginsLoaderDisappearance');
await this.driverHelper.waitDisappearance(PluginsView.PLUGINS_LOADER, timeout);
}
async openView(timeout: number = TimeoutConstants.TS_COMMON_PLUGIN_TEST_TIMEOUT) {
Logger.debug('PluginsView.openView');
await this.openViewByTopMenu();
await this.waitPluginsLoader(timeout);
await this.waitPluginsLoaderDisappearance(timeout);
await this.waitView(timeout);
}
async clickPluginsViewButton(timeout: number = TimeoutConstants.TS_COMMON_PLUGIN_TEST_TIMEOUT) {
Logger.debug('PluginsView.clickPluginsViewButton');
await this.leftToolbar.clickOnToolIcon('Plugins', timeout);
}
async selectPlugins(timeout: number = TimeoutConstants.TS_COMMON_PLUGIN_TEST_TIMEOUT) {
Logger.debug('PluginsView.selectPlugins');
await this.leftToolbar.selectView('Plugins', timeout);
}
async waitSearchField(timeout: number = TimeoutConstants.TS_COMMON_PLUGIN_TEST_TIMEOUT) {
Logger.debug('PluginsView.waitSearchField');
await this.driverHelper.waitVisibility(PluginsView.SEARCH_FIELD_LOCATOR, timeout);
}
async typeTextToSearchField(text: string, timeout: number = TimeoutConstants.TS_COMMON_PLUGIN_TEST_TIMEOUT) {
Logger.debug('PluginsView.typeTextToSearchField');
// search field performs searching during typing
// if try to write whole word at once
// it will cause to the random result
for (let i: number = 0; i < text.length; i++) {
await this.driverHelper.type(PluginsView.SEARCH_FIELD_LOCATOR, text.charAt(i), timeout);
await this.driverHelper.wait(2000);
}
}
async waitView(timeout: number = TimeoutConstants.TS_COMMON_PLUGIN_TEST_TIMEOUT) {
Logger.debug('PluginsView.waitView');
await this.waitTitle(timeout);
await this.waitSearchField(timeout);
}
async waitPlugin(pluginTitle: string, timeout: number = TimeoutConstants.TS_COMMON_PLUGIN_TEST_TIMEOUT) {
Logger.debug('PluginsView.waitPlugin');
const pluginLocator: By = By.xpath(`${this.getPluginBaseLocator(pluginTitle)}`);
await this.driverHelper.waitVisibility(pluginLocator, timeout);
}
async waitInstallButton(pluginTitle: string, timeout: number = TimeoutConstants.TS_COMMON_PLUGIN_TEST_TIMEOUT) {
Logger.debug('PluginsView.waitInstallButton');
const installButtonLocator: By = this.getInstallButtonLocator(pluginTitle);
await this.driverHelper.waitVisibility(installButtonLocator, timeout);
}
async clickInstallButton(pluginTitle: string, timeout: number = TimeoutConstants.TS_COMMON_PLUGIN_TEST_TIMEOUT) {
Logger.debug('PluginsView.clickInstallButton');
const installButtonLocator: By = this.getInstallButtonLocator(pluginTitle);
await this.driverHelper.waitAndClick(installButtonLocator, timeout);
}
async waitInstalledButton(pluginTitle: string, timeout: number = TimeoutConstants.TS_COMMON_PLUGIN_TEST_TIMEOUT) {
Logger.debug('PluginsView.waitInstalledButton');
const installedButtonLocator: By = this.getInstalledButtonLocator(pluginTitle);
await this.driverHelper.waitVisibility(installedButtonLocator, timeout);
}
async clickInstalledButton(pluginTitle: string, timeout: number = TimeoutConstants.TS_COMMON_PLUGIN_TEST_TIMEOUT) {
Logger.debug('PluginsView.clickInstalledButton');
const installedButtonLocator: By = this.getInstalledButtonLocator(pluginTitle);
await this.driverHelper.waitAndClick(installedButtonLocator, timeout);
}
async waitPluginNotification(notificationText: string, timeout: number = TimeoutConstants.TS_COMMON_PLUGIN_TEST_TIMEOUT) {
Logger.debug('PluginsView.waitPluginNotification');
const pluginNotificationLocator: By = this.getPluginNotificationLocator(notificationText);
await this.driverHelper.waitVisibility(pluginNotificationLocator);
}
async clickPluginNotification(notificationText: string, timeout: number = TimeoutConstants.TS_COMMON_PLUGIN_TEST_TIMEOUT) {
Logger.debug('PluginsView.clickPluginNotification');
const pluginNotificationLocator: By = this.getPluginNotificationLocator(notificationText);
await this.driverHelper.waitAndClick(pluginNotificationLocator);
}
private async openViewByTopMenu() {
await this.topMenu.clickOnTopMenuButton('View');
try {
await this.topMenu.clickOnSubmenuItem('Plugins');
} catch (err) {
if (!(err instanceof error.TimeoutError)) {
throw err;
}
Logger.debug('The "View" menu is not opened, try again');
await this.topMenu.clickOnTopMenuButton('View');
await this.topMenu.clickOnSubmenuItem('Plugins');
}
}
private getPluginNotificationLocator(notificationText: string): By {
const pluginNotificationXpath: string = `//div[@class='che-plugins-notification']//div[@class='notification-message-text' and text()='${notificationText}']`;
return By.xpath(pluginNotificationXpath);
}
private getPluginBaseLocator(pluginTitle: string): string {
return `//div[@class='che-plugin-content']//div[@class='che-plugin-name']/span[text()='${pluginTitle}']/parent::div/parent::div/parent::div/parent::div`;
}
private getInstallButtonLocator(pluginTitle: string): By {
const basePluginXpath: string = this.getPluginBaseLocator(pluginTitle);
const relativeInstallButtonXpath: string = `//div[@class='che-plugin-action-add' and text()='Install']`;
return By.xpath(`${basePluginXpath}${relativeInstallButtonXpath}`);
}
private getInstalledButtonLocator(pluginTitle: string): By {
const basePluginXpath: string = this.getPluginBaseLocator(pluginTitle);
const relativeInstalledButtonXpath: string = `//div[@class='che-plugin-action-remove' and text()='Installed']`;
return By.xpath(`${basePluginXpath}${relativeInstalledButtonXpath}`);
}
}

View File

@ -1,13 +0,0 @@
/*********************************************************************
* Copyright (c) 2019 Red Hat, Inc.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/
export interface ICheLoginPage {
login(): void;
}

View File

@ -1,13 +0,0 @@
/*********************************************************************
* Copyright (c) 2019 Red Hat, Inc.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/
export interface IOcpLoginPage {
login(): void;
}

View File

@ -1,33 +0,0 @@
/*********************************************************************
* Copyright (c) 2019 Red Hat, Inc.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/
import 'reflect-metadata';
import { ICheLoginPage } from './ICheLoginPage';
import { CheLoginPage } from '../openshift/CheLoginPage';
import { injectable, inject } from 'inversify';
import { CLASSES } from '../../inversify.types';
import { TestConstants } from '../../TestConstants';
import { Logger } from '../../utils/Logger';
@injectable()
export class MultiUserLoginPage implements ICheLoginPage {
constructor(
@inject(CLASSES.CheLoginPage) private readonly cheLogin: CheLoginPage) { }
async login() {
Logger.debug('MultiUserLoginPage.login');
await this.cheLogin.waitEclipseCheLoginFormPage();
await this.cheLogin.inputUserNameEclipseCheLoginPage(TestConstants.TS_SELENIUM_USERNAME);
await this.cheLogin.inputPaswordEclipseCheLoginPage(TestConstants.TS_SELENIUM_PASSWORD);
await this.cheLogin.clickEclipseCheLoginButton();
}
}

View File

@ -1,38 +0,0 @@
/*********************************************************************
* Copyright (c) 2019 Red Hat, Inc.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/
import 'reflect-metadata';
import { IOcpLoginPage } from './IOcpLoginPage';
import { injectable, inject } from 'inversify';
import { OcpLoginPage } from '../openshift/OcpLoginPage';
import { CLASSES } from '../../inversify.types';
import { TestConstants } from '../../TestConstants';
import { Logger } from '../../utils/Logger';
@injectable()
export class OcpUserLoginPage implements IOcpLoginPage {
constructor(
@inject(CLASSES.OcpLoginPage) private readonly ocpLogin: OcpLoginPage) { }
async login() {
Logger.debug('OcpUserLoginPage.login');
if (TestConstants.TS_OCP_LOGIN_PAGE_PROVIDER_TITLE !== '') {
await this.ocpLogin.clickOnLoginProviderTitle();
}
await this.ocpLogin.waitOpenShiftLoginWelcomePage();
await this.ocpLogin.enterUserNameOpenShift(TestConstants.TS_SELENIUM_OCP_USERNAME);
await this.ocpLogin.enterPasswordOpenShift(TestConstants.TS_SELENIUM_OCP_PASSWORD);
await this.ocpLogin.clickOnLoginButton();
await this.ocpLogin.waitDisappearanceOpenShiftLoginWelcomePage();
}
}

View File

@ -1,61 +0,0 @@
/*********************************************************************
* Copyright (c) 2019 Red Hat, Inc.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/
import 'reflect-metadata';
import { ICheLoginPage } from './ICheLoginPage';
import { OcpLoginPage } from '../openshift/OcpLoginPage';
import { CheLoginPage } from '../openshift/CheLoginPage';
import { injectable, inject } from 'inversify';
import { CLASSES } from '../../inversify.types';
import { TestConstants } from '../../TestConstants';
import { Logger } from '../../utils/Logger';
@injectable()
export class RegularUserOcpCheLoginPage implements ICheLoginPage {
constructor(
@inject(CLASSES.OcpLoginPage) private readonly ocpLogin: OcpLoginPage,
@inject(CLASSES.CheLoginPage) private readonly cheLogin: CheLoginPage) { }
async login() {
Logger.debug('RegularUserOcpCheLoginPage.login');
if (await this.ocpLogin.isIdentityProviderLinkVisible()) {
await this.ocpLogin.clickOnLoginProviderTitle();
}
await this.ocpLogin.waitOpenShiftLoginWelcomePage();
await this.ocpLogin.enterUserNameOpenShift(TestConstants.TS_SELENIUM_OCP_USERNAME);
await this.ocpLogin.enterPasswordOpenShift(TestConstants.TS_SELENIUM_OCP_PASSWORD);
await this.ocpLogin.clickOnLoginButton();
await this.ocpLogin.waitDisappearanceOpenShiftLoginWelcomePage();
if (await this.ocpLogin.isAuthorizeOpenShiftIdentityProviderPageVisible()) {
await this.ocpLogin.waitAuthorizeOpenShiftIdentityProviderPage();
await this.ocpLogin.clickOnApproveAuthorizeAccessButton();
}
if (await this.cheLogin.isFirstBrokerLoginPageVisible()) {
await this.cheLogin.waitFirstBrokerLoginPage();
await this.cheLogin.enterEmailFirstBrokerLoginPage(TestConstants.TS_SELENIUM_EMAIL_USER);
await this.cheLogin.enterFirstNameBrokerLoginPage(TestConstants.TS_SELENIUM_FIRST_NAME);
await this.cheLogin.enterLastNameBrokerLoginPage(TestConstants.TS_SELENIUM_LAST_NAME);
await this.cheLogin.clickOnSubmitButton();
await this.cheLogin.waitDisappearanceBrokerLoginPage();
}
if (await this.ocpLogin.isLinkAccountPageVisible()) {
await this.ocpLogin.clickOnLinkAccountButton();
await this.cheLogin.waitEclipseCheLoginFormPage();
await this.cheLogin.inputPaswordEclipseCheLoginPage(TestConstants.TS_SELENIUM_PASSWORD);
await this.cheLogin.clickEclipseCheLoginButton();
}
}
}

View File

@ -1,70 +0,0 @@
/*********************************************************************
* Copyright (c) 2019 Red Hat, Inc.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/
import 'reflect-metadata';
import { injectable, inject } from 'inversify';
import { Logger } from '../../utils/Logger';
import { DriverHelper } from '../../utils/DriverHelper';
import { CLASSES } from '../../inversify.types';
import { By } from 'selenium-webdriver';
@injectable()
export class UpdateAccountInformationPage {
constructor(@inject(CLASSES.DriverHelper) private readonly driverHelper: DriverHelper) { }
async enterEmail(email: string, timeout: number) {
Logger.debug('UpdateAccountInformationPage.enterEmail');
await this.driverHelper.enterValue(By.id('email'), email, timeout);
}
async enterFirstName(firstName: string, timeout: number) {
Logger.debug('UpdateAccountInformationPage.enterFirstName');
await this.driverHelper.enterValue(By.id('firstName'), firstName, timeout);
}
async enterLastName(lastName: string, timeout: number) {
Logger.debug('UpdateAccountInformationPage.enterLastName');
await this.driverHelper.enterValue(By.id('lastName'), lastName, timeout);
}
async clickConfirmButton(timeout: number) {
Logger.debug('UpdateAccountInformationPage.clickConfirmButton');
await this.driverHelper.waitAndClick(By.xpath('//input[@type=\'submit\']'), timeout);
}
async clickAddToExistingAccountButton(timeout: number) {
Logger.debug('UpdateAccountInformationPage.clickAddToExistingAccountButton');
await this.driverHelper.waitAndClick(By.id('linkAccount'), timeout);
}
async enterPassword(password: string, timeout: number) {
Logger.debug('UpdateAccountInformationPage.enterPassword');
await this.driverHelper.enterValue(By.id('password'), password, timeout);
}
async clickLogInButton(timeout: number) {
Logger.debug('UpdateAccountInformationPage.clickLogInButton');
await this.driverHelper.waitAndClick(By.id('kc-login'), timeout);
}
async clickToAllowSelectedPermissionsButton(timeout: number) {
Logger.debug('UpdateAccountInformationPage.clickToAllowSelectedPermissionsButton');
await this.driverHelper.waitAndClick(By.xpath('//input[@name=\'approve\']'), timeout);
}
}

View File

@ -1,91 +0,0 @@
/*********************************************************************
* Copyright (c) 2019 Red Hat, Inc.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/
import 'reflect-metadata';
import { injectable, inject } from 'inversify';
import { DriverHelper } from '../../utils/DriverHelper';
import { CLASSES } from '../../inversify.types';
import { By } from 'selenium-webdriver';
import { Logger } from '../../utils/Logger';
import { TimeoutConstants } from '../../TimeoutConstants';
@injectable()
export class CheLoginPage {
constructor(
@inject(CLASSES.DriverHelper) private readonly driverHelper: DriverHelper) { }
async waitEclipseCheLoginFormPage() {
Logger.debug('CheLoginPage.waitEclipseCheLoginFormPage');
await this.driverHelper.waitVisibility(By.id('kc-form-login'), TimeoutConstants.TS_SELENIUM_LOAD_PAGE_TIMEOUT);
}
async inputUserNameEclipseCheLoginPage(userName: string) {
Logger.debug(`CheLoginPage.inputUserNameEclipseCheLoginPage username: "${userName}"`);
await this.driverHelper.enterValue(By.id('username'), userName);
}
async inputPaswordEclipseCheLoginPage(passw: string) {
Logger.debug(`CheLoginPage.inputPaswordEclipseCheLoginPage password: "${passw}"`);
await this.driverHelper.enterValue(By.id('password'), passw);
}
async clickEclipseCheLoginButton() {
Logger.debug('CheLoginPage.clickEclipseCheLoginButton');
await this.driverHelper.waitAndClick(By.id('kc-login'));
}
async isFirstBrokerLoginPageVisible(): Promise<boolean> {
Logger.debug('CheLoginPage.waitFirstBrokerLoginPage');
return await this.driverHelper.isVisible(By.id('kc-update-profile-form'));
}
async waitFirstBrokerLoginPage() {
Logger.debug('CheLoginPage.waitFirstBrokerLoginPage');
await this.driverHelper.waitVisibility(By.id('kc-update-profile-form'), TimeoutConstants.TS_SELENIUM_LOAD_PAGE_TIMEOUT);
}
async enterEmailFirstBrokerLoginPage(email: string) {
Logger.debug(`CheLoginPage.enterEmailFirstBrokerLoginPage "${email}"`);
await this.driverHelper.enterValue(By.id('email'), email);
}
async enterFirstNameBrokerLoginPage(firstName: string) {
Logger.debug(`CheLoginPage.enterFirstNameBrokerLoginPage "${firstName}"`);
await this.driverHelper.enterValue(By.id('firstName'), firstName);
}
async enterLastNameBrokerLoginPage(lastName: string) {
Logger.debug(`CheLoginPage.enterLastNameBrokerLoginPage "${lastName}"`);
await this.driverHelper.enterValue(By.id('lastName'), lastName);
}
async clickOnSubmitButton() {
Logger.debug('CheLoginPage.clickOnSubmitButton');
const submitButtonlocator: By = By.css('input[type=submit]');
await this.driverHelper.waitAndClick(submitButtonlocator);
}
async waitDisappearanceBrokerLoginPage() {
Logger.debug('CheLoginPage.waitDisappearanceBrokerLoginPage');
await this.driverHelper.waitDisappearance(By.id('kc-update-profile-form'));
}
}

View File

@ -1,113 +0,0 @@
/*********************************************************************
* Copyright (c) 2019 Red Hat, Inc.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/
import 'reflect-metadata';
import { injectable, inject } from 'inversify';
import { DriverHelper } from '../../utils/DriverHelper';
import { CLASSES } from '../../inversify.types';
import { By } from 'selenium-webdriver';
import { Logger } from '../../utils/Logger';
import { TestConstants } from '../../TestConstants';
import { TimeoutConstants } from '../../TimeoutConstants';
@injectable()
export class OcpLoginPage {
private static readonly LOGIN_PAGE_OPENSHIFT_XPATH: string = '//*[contains(text(), \'Welcome\')]';
constructor(
@inject(CLASSES.DriverHelper) private readonly driverHelper: DriverHelper) { }
async openLoginPageOpenShift(url: string) {
Logger.debug('OcpLoginPage.openLoginPageOpenShift');
await this.driverHelper.navigateToUrl(url);
}
async waitOpenShiftLoginWelcomePage() {
Logger.debug('OcpLoginPage.waitOpenShiftLoginWelcomePage');
await this.driverHelper.waitVisibility(By.xpath(OcpLoginPage.LOGIN_PAGE_OPENSHIFT_XPATH), TimeoutConstants.TS_SELENIUM_LOAD_PAGE_TIMEOUT);
}
async clickOnLoginProviderTitle() {
Logger.debug('OcpLoginPage.clickOnLoginProviderTitle');
const loginProviderTitleLocator: By = By.xpath(`//a[text()=\'${TestConstants.TS_OCP_LOGIN_PAGE_PROVIDER_TITLE}\']`);
await this.driverHelper.waitAndClick(loginProviderTitleLocator);
}
async isIdentityProviderLinkVisible(): Promise<boolean> {
Logger.debug('OcpLoginPage.isIdentityProviderLinkVisible');
const loginWithHtpaswdLocator: By = By.xpath(`//a[text()=\'${TestConstants.TS_OCP_LOGIN_PAGE_PROVIDER_TITLE}\']`);
return await this.driverHelper.waitVisibilityBoolean(loginWithHtpaswdLocator, 3, 5000);
}
async isAuthorizeOpenShiftIdentityProviderPageVisible(): Promise<boolean> {
Logger.debug('OcpLoginPage.isAuthorizeOpenShiftIdentityProviderPageVisible');
const authorizeOpenshiftIdentityProviderPageLocator: By = By.xpath('//h1[text()=\'Authorize Access\']');
return await this.driverHelper.isVisible(authorizeOpenshiftIdentityProviderPageLocator);
}
async waitAuthorizeOpenShiftIdentityProviderPage() {
Logger.debug('OcpLoginPage.waitAuthorizeOpenShiftIdentityProviderPage');
const authorizeOpenshiftIdentityProviderPageLocator: By = By.xpath('//h1[text()=\'Authorize Access\']');
await this.driverHelper.waitVisibility(authorizeOpenshiftIdentityProviderPageLocator, TimeoutConstants.TS_SELENIUM_LOAD_PAGE_TIMEOUT);
}
async clickOnApproveAuthorizeAccessButton() {
Logger.debug('OcpLoginPage.clickOnApproveAuthorizeAccessOpenshift');
const approveAuthorizeAccessOcpLocator: By = By.css('input[name=\'approve\']');
await this.driverHelper.waitAndClick(approveAuthorizeAccessOcpLocator);
}
async enterUserNameOpenShift(userName: string) {
Logger.debug(`OcpLoginPage.enterUserNameOpenShift "${userName}"`);
await this.driverHelper.enterValue(By.id('inputUsername'), userName);
}
async enterPasswordOpenShift(passw: string) {
Logger.debug(`OcpLoginPage.enterPasswordOpenShift "${passw}"`);
await this.driverHelper.enterValue(By.id('inputPassword'), passw);
}
async clickOnLoginButton() {
Logger.debug('OcpLoginPage.clickOnLoginButton');
const loginButtonlocator: By = By.css('button[type=submit]');
await this.driverHelper.waitAndClick(loginButtonlocator);
}
async waitDisappearanceOpenShiftLoginWelcomePage() {
Logger.debug('OcpLoginPage.waitDisappearanceOpenShiftLoginWelcomePage');
await this.driverHelper.waitDisappearance(By.xpath(OcpLoginPage.LOGIN_PAGE_OPENSHIFT_XPATH));
}
async isLinkAccountPageVisible(): Promise<boolean> {
Logger.debug('OcpLoginPage.isLinkAccountPageVisible');
const linkAccountLocator: By = By.id(`linkAccount`);
return await this.driverHelper.waitVisibilityBoolean(linkAccountLocator, 3, 5000);
}
async clickOnLinkAccountButton() {
Logger.debug('OcpLoginPage.clickOnLinkAccountButton');
const linkAccountLocator: By = By.id(`linkAccount`);
this.driverHelper.waitAndClick(linkAccountLocator);
}
}

View File

@ -1,78 +0,0 @@
/*********************************************************************
* Copyright (c) 2020 Red Hat, Inc.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/
import 'reflect-metadata';
import { e2eContainer } from '../../inversify.config';
import { Editor, CLASSES } from '../..';
import { WorkspaceNameHandler } from '../../utils/WorkspaceNameHandler';
import { LanguageServerTests } from '../../testsLibrary/LanguageServerTests';
import { CodeExecutionTests } from '../../testsLibrary/CodeExecutionTests';
import { ProjectAndFileTests } from '../../testsLibrary/ProjectAndFileTests';
import { WorkspaceHandlingTests } from '../../testsLibrary/WorkspaceHandlingTests';
const workspaceHandlingTests: WorkspaceHandlingTests = e2eContainer.get(CLASSES.WorkspaceHandlingTests);
const projectAndFileTests: ProjectAndFileTests = e2eContainer.get(CLASSES.ProjectAndFileTests);
const commonLanguageServerTests: LanguageServerTests = e2eContainer.get(CLASSES.LanguageServerTests);
const codeExecutionTests: CodeExecutionTests = e2eContainer.get(CLASSES.CodeExecutionTests);
const editor: Editor = e2eContainer.get(CLASSES.Editor);
const workspaceSampleName: string = 'cpp-hello-world';
const fileFolderPath: string = `${workspaceSampleName}`;
const tabTitle: string = 'hello.cpp';
const buildTaskName: string = 'build';
const runTaskName: string = 'run';
const stack: string = 'C/C++';
suite(`${stack} test`, async () => {
suite(`Create ${stack} workspace`, async () => {
workspaceHandlingTests.createAndOpenWorkspace(stack);
projectAndFileTests.waitWorkspaceReadinessNoSubfolder(workspaceSampleName);
});
suite('Test opening file', async () => {
// opening file that soon should give time for LS to initialize
projectAndFileTests.openFile(fileFolderPath, tabTitle);
prepareEditorForLanguageServerTests();
});
suite('Validation of project build', async () => {
codeExecutionTests.runTask(buildTaskName, 30_000);
codeExecutionTests.runTask(runTaskName, 30_000);
});
suite('Language server validation', async () => {
commonLanguageServerTests.errorHighlighting(tabTitle, `error_text;`, 12);
commonLanguageServerTests.suggestionInvoking(tabTitle, 15, 22, 'test');
commonLanguageServerTests.autocomplete(tabTitle, 15, 9, 'printf');
// commonLanguageServerTests.codeNavigation(tabTitle, 15, 9, 'stdio.h'); currently not working because of LS not exposing Ctrl + F12 combination
});
suite('Stopping and deleting the workspace', async () => {
let workspaceName = 'not defined';
suiteSetup(async () => {
workspaceName = await WorkspaceNameHandler.getNameFromUrl();
});
test(`Stop and remowe workspace`, async () => {
await workspaceHandlingTests.stopAndRemoveWorkspace(workspaceName);
});
});
});
export function prepareEditorForLanguageServerTests() {
test(`Prepare file for LS tests`, async () => {
await editor.moveCursorToLineAndChar(tabTitle, 6, 1);
await editor.performKeyCombination(tabTitle, '#include <cstdio>\n');
await editor.moveCursorToLineAndChar(tabTitle, 10, 1);
await editor.performKeyCombination(tabTitle, '\nchar const *test = "test";\n');
await editor.moveCursorToLineAndChar(tabTitle, 15, 5);
await editor.performKeyCombination(tabTitle, 'printf("%s\\n", test);\n');
});
}

View File

@ -1,38 +0,0 @@
/*********************************************************************
* Copyright (c) 2020 Red Hat, Inc.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/
import 'reflect-metadata';
import { CLASSES, WorkspaceNameHandler } from '../..';
import { e2eContainer } from '../../inversify.config';
import { ProjectAndFileTests } from '../../testsLibrary/ProjectAndFileTests';
import { WorkspaceHandlingTests } from '../../testsLibrary/WorkspaceHandlingTests';
const workspaceHandlingTests: WorkspaceHandlingTests = e2eContainer.get(CLASSES.WorkspaceHandlingTests);
const projectAndFileTests: ProjectAndFileTests = e2eContainer.get(CLASSES.ProjectAndFileTests);
const workspaceSampleName: string = 'console-java-simple';
const workspaceRootFolderName: string = 'src';
const stack : string = 'Java Maven';
suite(`${stack} test`, async () => {
suite (`Create ${stack} workspace`, async () => {
workspaceHandlingTests.createAndOpenWorkspace(stack);
projectAndFileTests.waitWorkspaceReadiness(workspaceSampleName, workspaceRootFolderName);
});
suite ('Stopping and deleting the workspace', async () => {
let workspaceName = 'not defined';
suiteSetup(async () => {
workspaceName = await WorkspaceNameHandler.getNameFromUrl();
});
test(`Stop and remowe workspace`, async () => {
await workspaceHandlingTests.stopAndRemoveWorkspace(workspaceName);
});
});
});

View File

@ -1,86 +0,0 @@
/*********************************************************************
* Copyright (c) 2020 Red Hat, Inc.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/
import 'reflect-metadata';
import { WorkspaceNameHandler, Editor, CLASSES } from '../..';
import { e2eContainer } from '../../inversify.config';
import { LanguageServerTests } from '../../testsLibrary/LanguageServerTests';
import { CodeExecutionTests } from '../../testsLibrary/CodeExecutionTests';
import { ProjectAndFileTests } from '../../testsLibrary/ProjectAndFileTests';
import { WorkspaceHandlingTests } from '../../testsLibrary/WorkspaceHandlingTests';
const workspaceHandlingTests: WorkspaceHandlingTests = e2eContainer.get(CLASSES.WorkspaceHandlingTests);
const projectAndFileTests: ProjectAndFileTests = e2eContainer.get(CLASSES.ProjectAndFileTests);
const commonLanguageServerTests: LanguageServerTests = e2eContainer.get(CLASSES.LanguageServerTests);
const codeExecutionTests: CodeExecutionTests = e2eContainer.get(CLASSES.CodeExecutionTests);
const editor: Editor = e2eContainer.get(CLASSES.Editor);
const workspaceSampleName: string = 'dotnet-web-simple';
const fileFolderPath: string = `${workspaceSampleName}`;
const tabTitle: string = 'Program.cs';
// const codeNavigationClassName: string = '[metadata] Console.cs';
const stack : string = '.NET Core';
const updateDependenciesTaskName: string = 'update dependencies';
const buildTaskName: string = 'build';
const runTaskName: string = 'run';
const runTaskNameExpectedString: string = 'Process 5000-tcp is now listening on port 5000. Open it ?';
suite(`Test ${stack}`, async () => {
suite (`Create ${stack} workspace`, async () => {
workspaceHandlingTests.createAndOpenWorkspace(stack);
projectAndFileTests.waitWorkspaceReadinessNoSubfolder(workspaceSampleName);
});
suite('Test opening file', async () => {
// opening file that soon should give time for LS to initialize
projectAndFileTests.openFile(fileFolderPath, tabTitle);
prepareEditorForLanguageServerTests();
});
suite('Installing dependencies', async () => {
codeExecutionTests.runTask(updateDependenciesTaskName, 120_000);
codeExecutionTests.closeTerminal(updateDependenciesTaskName);
});
suite('Validation of workspace build', async () => {
codeExecutionTests.runTask(buildTaskName, 30_000);
codeExecutionTests.closeTerminal(buildTaskName);
});
suite('Run .NET Core example application', async () => {
codeExecutionTests.runTaskWithNotification(runTaskName, runTaskNameExpectedString , 30_000);
});
suite('Language server validation', async () => {
commonLanguageServerTests.suggestionInvoking(tabTitle, 22, 33, 'test');
commonLanguageServerTests.errorHighlighting(tabTitle, 'error_text;', 23);
commonLanguageServerTests.autocomplete(tabTitle, 22, 27, 'WriteLine');
// commonLanguageServerTests.codeNavigation(tabTitle, 22, 27, codeNavigationClassName); // codenavigation is inconsistent https://github.com/eclipse/che/issues/16929
});
suite ('Stopping and deleting the workspace', async () => {
let workspaceName = 'not defined';
suiteSetup(async () => {
workspaceName = await WorkspaceNameHandler.getNameFromUrl();
});
test(`Stop and remowe workspace`, async () => {
await workspaceHandlingTests.stopAndRemoveWorkspace(workspaceName);
});
});
});
export function prepareEditorForLanguageServerTests() {
test(`Prepare file for LS tests`, async () => {
await editor.moveCursorToLineAndChar(tabTitle, 18, 6);
await editor.performKeyCombination(tabTitle, '\nprivate static String test = "test";');
await editor.moveCursorToLineAndChar(tabTitle, 21, 10);
await editor.performKeyCombination(tabTitle, '\nConsole.WriteLine(test);\n');
});
}

View File

@ -1,81 +0,0 @@
/*********************************************************************
* Copyright (c) 2020 Red Hat, Inc.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/
import { CLASSES, WorkspaceNameHandler } from '../..';
import { e2eContainer } from '../../inversify.config';
import 'reflect-metadata';
import { Logger } from '../../utils/Logger';
import { PreferencesHandler } from '../../utils/PreferencesHandler';
import { LanguageServerTests } from '../../testsLibrary/LanguageServerTests';
import { CodeExecutionTests } from '../../testsLibrary/CodeExecutionTests';
import { ProjectAndFileTests } from '../../testsLibrary/ProjectAndFileTests';
import { WorkspaceHandlingTests } from '../../testsLibrary/WorkspaceHandlingTests';
const workspaceHandlingTests: WorkspaceHandlingTests = e2eContainer.get(CLASSES.WorkspaceHandlingTests);
const projectAndFileTests: ProjectAndFileTests = e2eContainer.get(CLASSES.ProjectAndFileTests);
const commonLanguageServerTests: LanguageServerTests = e2eContainer.get(CLASSES.LanguageServerTests);
const codeExecutionTests: CodeExecutionTests = e2eContainer.get(CLASSES.CodeExecutionTests);
const preferencesHandler: PreferencesHandler = e2eContainer.get(CLASSES.PreferencesHandler);
const workspaceStack: string = 'Go';
const workspaceSampleName: string = 'src';
const workspaceRootFolderName: string = 'github.com';
const fileFolderPath: string = `${workspaceSampleName}/${workspaceRootFolderName}/golang/example/outyet`;
const fileName: string = `main.go`;
const taskRunServer: string = '1.1 Run outyet';
const taskStopServer: string = '1.2 Stop outyet';
const taskTestOutyet: string = '1.3 Test outyet';
const notificationText: string = 'Process 8080-tcp is now listening on port 8080. Open it ?';
suite(`${workspaceStack} test`, async () => {
suite(`Create ${workspaceStack} workspace`, async () => {
test('Workaround for issue #16113', async () => {
Logger.warn(`Manually setting a preference for golang devfile LS based on issue: https://github.com/eclipse/che/issues/16113`);
await preferencesHandler.setUseGoLanaguageServer();
});
workspaceHandlingTests.createAndOpenWorkspace(workspaceStack);
projectAndFileTests.waitWorkspaceReadiness(workspaceSampleName, workspaceRootFolderName);
});
suite('Test opening file', async () => {
// opening file that soon should give time for LS to initialize
projectAndFileTests.openFile(fileFolderPath, fileName);
});
suite('Test golang example', async () => {
codeExecutionTests.runTask(taskTestOutyet, 60_000);
codeExecutionTests.closeTerminal(taskTestOutyet);
});
suite('Run golang example server', async () => {
codeExecutionTests.runTaskWithNotification(taskRunServer, notificationText, 40_000);
codeExecutionTests.runTask(taskStopServer, 5_000);
});
suite(`'Language server validation'`, async () => {
commonLanguageServerTests.suggestionInvoking(fileName, 42, 10, 'Parse');
commonLanguageServerTests.autocomplete(fileName, 42, 10, 'Parse');
commonLanguageServerTests.errorHighlighting(fileName, 'error;\n', 42);
// commonLanguageServerTests.codeNavigation(fileName, 42, 10, 'flag.go'); // codenavigation is inconsistent https://github.com/eclipse/che/issues/16929
});
suite('Stop and remove workspace', async() => {
let workspaceName = 'not defined';
suiteSetup(async () => {
workspaceName = await WorkspaceNameHandler.getNameFromUrl();
});
test(`Stop and remowe workspace`, async () => {
await workspaceHandlingTests.stopAndRemoveWorkspace(workspaceName);
});
});
});

View File

@ -1,64 +0,0 @@
/*********************************************************************
* Copyright (c) 2020 Red Hat, Inc.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/
import 'reflect-metadata';
import { CLASSES, WorkspaceNameHandler } from '../..';
import { LanguageServerTests } from '../../testsLibrary/LanguageServerTests';
import { e2eContainer } from '../../inversify.config';
import { CodeExecutionTests } from '../../testsLibrary/CodeExecutionTests';
import { ProjectAndFileTests } from '../../testsLibrary/ProjectAndFileTests';
import { WorkspaceHandlingTests } from '../../testsLibrary/WorkspaceHandlingTests';
const workspaceHandlingTests: WorkspaceHandlingTests = e2eContainer.get(CLASSES.WorkspaceHandlingTests);
const projectAndFileTests: ProjectAndFileTests = e2eContainer.get(CLASSES.ProjectAndFileTests);
const commonLanguageServerTests: LanguageServerTests = e2eContainer.get(CLASSES.LanguageServerTests);
const codeExecutionTests: CodeExecutionTests = e2eContainer.get(CLASSES.CodeExecutionTests);
const workspaceSampleName: string = 'console-java-simple';
const workspaceRootFolderName: string = 'src';
const fileFolderPath: string = `${workspaceSampleName}/${workspaceRootFolderName}/main/java/org/eclipse/che/examples`;
const tabTitle: string = 'HelloWorld.java';
const codeNavigationClassName: string = 'String.class';
const stack : string = 'Java Maven';
const taskName: string = 'maven build';
suite(`${stack} test`, async () => {
suite (`Create ${stack} workspace`, async () => {
workspaceHandlingTests.createAndOpenWorkspace(stack);
projectAndFileTests.waitWorkspaceReadiness(workspaceSampleName, workspaceRootFolderName);
});
suite('Test opening file', async () => {
// opening file that soon should give time for LS to initialize
projectAndFileTests.openFile(fileFolderPath, tabTitle);
});
suite('Validation of workspace build and run', async () => {
codeExecutionTests.runTask(taskName, 120_000);
codeExecutionTests.closeTerminal(taskName);
});
suite('Language server validation', async () => {
commonLanguageServerTests.suggestionInvoking(tabTitle, 10, 20, 'append(char c) : PrintStream');
commonLanguageServerTests.errorHighlighting(tabTitle, 'error_text', 11);
commonLanguageServerTests.autocomplete(tabTitle, 10, 11, 'System - java.lang');
commonLanguageServerTests.codeNavigation(tabTitle, 9, 10, codeNavigationClassName, 30_000); // extended timout to give LS enough time to start
});
suite ('Stopping and deleting the workspace', async () => {
let workspaceName = 'not defined';
suiteSetup(async () => {
workspaceName = await WorkspaceNameHandler.getNameFromUrl();
});
test(`Stop and remowe workspace`, async () => {
await workspaceHandlingTests.stopAndRemoveWorkspace(workspaceName);
});
});
});

View File

@ -1,71 +0,0 @@
/*********************************************************************
* Copyright (c) 2020 Red Hat, Inc.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/
import 'reflect-metadata';
import { CLASSES, WorkspaceNameHandler } from '../..';
import { LanguageServerTests } from '../../testsLibrary/LanguageServerTests';
import { e2eContainer } from '../../inversify.config';
import { CodeExecutionTests } from '../../testsLibrary/CodeExecutionTests';
import { ProjectAndFileTests } from '../../testsLibrary/ProjectAndFileTests';
import { WorkspaceHandlingTests } from '../../testsLibrary/WorkspaceHandlingTests';
const workspaceHandlingTests: WorkspaceHandlingTests = e2eContainer.get(CLASSES.WorkspaceHandlingTests);
const projectAndFileTests: ProjectAndFileTests = e2eContainer.get(CLASSES.ProjectAndFileTests);
const commonLanguageServerTests: LanguageServerTests = e2eContainer.get(CLASSES.LanguageServerTests);
const codeExecutionTests: CodeExecutionTests = e2eContainer.get(CLASSES.CodeExecutionTests);
const stack: string = 'Java Spring Boot';
const workspaceSampleName: string = 'java-web-spring';
const workspaceRootFolderName: string = 'src';
const fileFolderPath: string = `${workspaceSampleName}/${workspaceRootFolderName}/main/java/org/springframework/samples/petclinic`;
const tabTitle: string = 'PetClinicApplication.java';
const codeNavigationClassName: string = 'SpringApplication.class';
const buildTaskName: string = 'maven build';
const runTaskName: string = 'run webapp';
const runTaskExpectedDialogue: string = 'Process 8080-tcp is now listening on port 8080. Open it ?';
suite(`${stack} test`, async () => {
suite(`Create ${stack} workspace`, async () => {
workspaceHandlingTests.createAndOpenWorkspace(stack);
projectAndFileTests.waitWorkspaceReadiness(workspaceSampleName, workspaceRootFolderName);
});
suite('Test opening file', async () => {
// opening file that soon should give time for LS to initialize
projectAndFileTests.openFile(fileFolderPath, tabTitle);
});
suite('Validation of workspace build', async () => {
codeExecutionTests.runTask(buildTaskName, 420_000);
codeExecutionTests.closeTerminal(buildTaskName);
});
suite('Validation of workspace execution', async () => {
codeExecutionTests.runTaskWithNotification(runTaskName, runTaskExpectedDialogue, 120_000);
codeExecutionTests.closeTerminal(runTaskName);
});
suite('Language server validation', async () => {
commonLanguageServerTests.autocomplete(tabTitle, 32, 56, 'args : String[]');
commonLanguageServerTests.errorHighlighting(tabTitle, 'error_text', 30);
commonLanguageServerTests.codeNavigation(tabTitle, 32, 23, codeNavigationClassName);
commonLanguageServerTests.suggestionInvoking(tabTitle, 32, 23, 'run(Class<?>');
});
suite('Stopping and deleting the workspace', async () => {
let workspaceName = 'not defined';
suiteSetup(async () => {
workspaceName = await WorkspaceNameHandler.getNameFromUrl();
});
test(`Stop and remowe workspace`, async () => {
await workspaceHandlingTests.stopAndRemoveWorkspace(workspaceName);
});
});
});

View File

@ -1,65 +0,0 @@
/*********************************************************************
* Copyright (c) 2020 Red Hat, Inc.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/
import 'reflect-metadata';
import { CLASSES, WorkspaceNameHandler } from '../..';
import { LanguageServerTests } from '../../testsLibrary/LanguageServerTests';
import { e2eContainer } from '../../inversify.config';
import { CodeExecutionTests } from '../../testsLibrary/CodeExecutionTests';
import { ProjectAndFileTests } from '../../testsLibrary/ProjectAndFileTests';
import { WorkspaceHandlingTests } from '../../testsLibrary/WorkspaceHandlingTests';
const workspaceHandlingTests: WorkspaceHandlingTests = e2eContainer.get(CLASSES.WorkspaceHandlingTests);
const projectAndFileTests: ProjectAndFileTests = e2eContainer.get(CLASSES.ProjectAndFileTests);
const commonLanguageServerTests: LanguageServerTests = e2eContainer.get(CLASSES.LanguageServerTests);
const codeExecutionTests: CodeExecutionTests = e2eContainer.get(CLASSES.CodeExecutionTests);
const workspaceSampleName: string = 'vertx-http-example';
const workspaceRootFolderName: string = 'src';
const fileFolderPath: string = `${workspaceSampleName}/${workspaceRootFolderName}/main/java/io/openshift/example`;
const tabTitle: string = 'HttpApplication.java';
const codeNavigationClassName: string = 'RouterImpl.class';
const buildTaskName: string = 'maven build';
const stack: string = 'Java Vert.x';
suite(`${stack} test`, async () => {
suite (`Create ${stack} workspace`, async () => {
workspaceHandlingTests.createAndOpenWorkspace(stack);
projectAndFileTests.waitWorkspaceReadiness(workspaceSampleName, workspaceRootFolderName);
});
suite('Test opening file', async () => {
// opening file that soon should give time for LS to initialize
projectAndFileTests.openFile(fileFolderPath, tabTitle);
});
suite('Validation of project build', async () => {
codeExecutionTests.runTask(buildTaskName, 120_000);
codeExecutionTests.closeTerminal(buildTaskName);
});
suite('Language server validation', async () => {
commonLanguageServerTests.errorHighlighting(tabTitle, 'error_text;', 20);
commonLanguageServerTests.suggestionInvoking(tabTitle, 19, 31, 'router(Vertx vertx) : Router');
commonLanguageServerTests.autocomplete(tabTitle, 19, 7, 'Router - io.vertx.ext.web');
commonLanguageServerTests.codeNavigation(tabTitle, 19, 7, codeNavigationClassName, 30_000); // extended timout to give LS enough time to start
});
suite ('Stopping and deleting the workspace', async () => {
let workspaceName = 'not defined';
suiteSetup(async () => {
workspaceName = await WorkspaceNameHandler.getNameFromUrl();
});
test(`Stop and remowe workspace`, async () => {
await workspaceHandlingTests.stopAndRemoveWorkspace(workspaceName);
});
});
});

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