Remove unrelated source code
parent
98b66ff1f6
commit
aab541ad08
|
|
@ -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 -->
|
||||
|
|
@ -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. -->
|
||||
|
|
@ -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. -->
|
||||
|
|
@ -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
|
||||
|
|
@ -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. -->
|
||||
|
|
@ -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/
|
||||
242
CONTRIBUTING.md
242
CONTRIBUTING.md
|
|
@ -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.
|
||||
85
README.md
85
README.md
|
|
@ -1,83 +1,2 @@
|
|||
<div id="header" align="center">
|
||||
|
||||
[](
|
||||
https://www.eclipse.org/che/)
|
||||
|
||||
**Next-generation container development platform, developer workspace server and cloud IDE**
|
||||
|
||||
[](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>
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
**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
|
||||
|
|
@ -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
|
||||
```
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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/
|
||||
}
|
||||
|
|
@ -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"
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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'```**
|
||||
|
|
@ -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'
|
||||
|
||||
};
|
||||
|
|
@ -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
|
||||
|
||||
};
|
||||
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
}]
|
||||
}
|
||||
|
|
@ -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>
|
||||
|
|
@ -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
|
||||
|
|
@ -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';
|
||||
|
|
@ -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
|
||||
|
|
@ -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 };
|
||||
|
|
@ -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 };
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
--timeout 2200000
|
||||
--reporter 'dist/driver/CheReporter.js'
|
||||
-u tdd
|
||||
--full-trace
|
||||
--bail
|
||||
--require source-map-support/register
|
||||
|
|
@ -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
|
||||
|
|
@ -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'
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
--timeout 1200000
|
||||
-u tdd
|
||||
--bail
|
||||
--full-trace
|
||||
--reporter './dist/driver/CheReporter.js'
|
||||
--spec './dist/tests/login/LinkCheAndOcpUsers.spec.js'
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
--timeout 1200000
|
||||
--reporter 'dist/driver/CheReporter.js'
|
||||
-u tdd
|
||||
--bail
|
||||
--full-trace
|
||||
--spec dist/tests/e2e/*.spec.js
|
||||
|
|
@ -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
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
|
@ -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}']`);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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']`);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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];
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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}')]`;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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}']`);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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}']`;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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}]`);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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}']`);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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}']`);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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}`);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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'));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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');
|
||||
});
|
||||
}
|
||||
|
|
@ -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);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -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');
|
||||
});
|
||||
}
|
||||
|
|
@ -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);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
|
@ -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);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -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);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -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
Loading…
Reference in New Issue