-
Notifications
You must be signed in to change notification settings - Fork 2
Add initial glsp-playwright implementation #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
aa8e476
Add initial glsp-playwright implementation
haydar-metin 7ff4d57
Add more documentation to the page objects and reuse Playwright docum…
haydar-metin f618142
Update README.md files concerning the new tasks
haydar-metin afbd819
Update scripts and readme
haydar-metin File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| /** @type {import('eslint').Linter.Config} */ | ||
| module.exports = { | ||
| root: true, | ||
| extends: ['@eclipse-glsp'], | ||
| ignorePatterns: ['**/{node_modules,lib}', '**/.eslintrc.js'], | ||
| parserOptions: { | ||
| tsconfigRootDir: __dirname, | ||
| project: 'tsconfig.eslint.json' | ||
| }, | ||
| settings: { | ||
| // Necessary for aliasing paths: https://www.typescriptlang.org/tsconfig#paths | ||
| 'import/resolver': { | ||
| typescript: { | ||
| project: ['packages/glsp-playwright/tsconfig.json', 'tsconfig.json'] | ||
| } | ||
| } | ||
| }, | ||
| rules: { | ||
| 'no-null/no-null': 'off', // Accessing the browser DOM returns "null" instead of "undefined" | ||
| 'no-restricted-imports': [ | ||
| 'error', | ||
| { | ||
| paths: [ | ||
| { | ||
| name: 'sprotty', | ||
| message: | ||
| "The sprotty default exports are customized and reexported by GLSP. Please use '@eclipse-glsp/client' instead" | ||
| }, | ||
| { | ||
| name: 'sprotty-protocol', | ||
| message: | ||
| "The sprotty-protocol default exports are customized and reexported by GLSP. Please use '@eclipse-glsp/client' instead" | ||
| } | ||
| ], | ||
| patterns: ['../../../../*', '**/../index'] | ||
| } | ||
| ] | ||
| } | ||
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| !.gitkeep | ||
|
|
||
| node_modules/ | ||
| test-results/ | ||
| playwright-report/ | ||
| playwright/.cache/ | ||
| lib/ | ||
|
|
||
| examples/workflow-test/server/ | ||
| examples/workflow-test/playwright/.storage/*.json | ||
|
|
||
| *.tsbuildinfo | ||
| *.log | ||
| *.jar | ||
| *.vsix | ||
| !*.env.example | ||
| *.env | ||
|
|
||
|
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| "@eclipse-glsp/prettier-config" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| { | ||
| // See http://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations. | ||
| // Extension identifier format: ${publisher}.${name}. Example: vscode.csharp | ||
| // List of extensions which should be recommended for users of this workspace. | ||
| "recommendations": [ | ||
| "dbaeumer.vscode-eslint", | ||
| "esbenp.prettier-vscode", | ||
| "DavidAnson.vscode-markdownlint" | ||
| ], | ||
| // List of extensions recommended by VS Code that should not be recommended for users of this workspace. | ||
| "unwantedRecommendations": [] | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| // If one would like to add/remove/modify user preferences without modifying the content of the | ||
| // workspace settings file, then one would need to modify the `settings.json` under here: | ||
| // - Windows: %APPDATA%\Code\User\settings.json | ||
| // - Linux: $HOME/.config/Code/User/settings.json | ||
| // - Mac: $HOME/Library/Application Support/Code/User/settings.json | ||
| { | ||
| "editor.formatOnSave": true, | ||
| "editor.codeActionsOnSave": { | ||
| "source.fixAll.eslint": true, | ||
| "source.organizeImports": true | ||
| }, | ||
| "eslint.validate": ["javascript", "typescript"], | ||
| "prettier.prettierPath": "node_modules/prettier", | ||
| "search.exclude": { | ||
| "**/node_modules": true, | ||
| "**/lib": true | ||
| }, | ||
| "task.autoDetect": "off", | ||
| "typescript.tsdk": "node_modules/typescript/lib", | ||
| "typescript.preferences.importModuleSpecifier": "relative", | ||
| "typescript.preferences.autoImportFileExcludePatterns": ["packages/*/src/index.ts"], | ||
| "[css]": { | ||
| "editor.defaultFormatter": "esbenp.prettier-vscode" | ||
| }, | ||
| "[javascript]": { | ||
| "editor.defaultFormatter": "esbenp.prettier-vscode" | ||
| }, | ||
| "[javascriptreact]": { | ||
| "editor.defaultFormatter": "esbenp.prettier-vscode" | ||
| }, | ||
| "[json]": { | ||
| "editor.defaultFormatter": "esbenp.prettier-vscode" | ||
| }, | ||
| "[markdown]": { | ||
| "editor.defaultFormatter": "esbenp.prettier-vscode" | ||
| }, | ||
| "[typescript]": { | ||
| "editor.defaultFormatter": "esbenp.prettier-vscode" | ||
| }, | ||
| "[typescriptreact]": { | ||
| "editor.defaultFormatter": "esbenp.prettier-vscode" | ||
| }, | ||
| "[yaml]": { | ||
| "editor.defaultFormatter": "esbenp.prettier-vscode" | ||
| }, | ||
| "markdownlint.config": { | ||
| "MD007": { | ||
| "indent": 4 | ||
| }, | ||
| "MD030": { | ||
| "ul_single": 3, | ||
| "ul_multi": 3 | ||
| } | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| { | ||
| // See https://go.microsoft.com/fwlink/?LinkId=733558 | ||
| // for the documentation about the tasks.json format | ||
| "version": "2.0.0", | ||
| "tasks": [ | ||
| { | ||
| "label": "Build all", | ||
| "detail": "Build all packages & examples", | ||
| "type": "shell", | ||
| "group": "build", | ||
| "command": "yarn", | ||
| "presentation": { | ||
| "reveal": "always", | ||
| "panel": "new" | ||
| }, | ||
| "problemMatcher": ["$tsc", "$eslint-stylish"] | ||
| }, | ||
| { | ||
| "label": "Watch all", | ||
| "detail": "Watch all packages & examples", | ||
| "type": "shell", | ||
| "group": "build", | ||
| "command": "yarn watch", | ||
| "presentation": { | ||
| "reveal": "always", | ||
| "panel": "new" | ||
| }, | ||
| "problemMatcher": ["$tsc-watch"] | ||
| }, | ||
| { | ||
| "label": "Download server", | ||
| "detail": "Download Workflow Diagram example server", | ||
| "type": "shell", | ||
| "group": "none", | ||
| "command": "cd examples/workflow-test && yarn download:server", | ||
| "presentation": { | ||
| "reveal": "always", | ||
| "panel": "new" | ||
| }, | ||
| "problemMatcher": [] | ||
| }, | ||
| { | ||
| "label": "Test standalone", | ||
| "detail": "Run test cases for standalone integration", | ||
| "type": "shell", | ||
| "group": "test", | ||
| "command": "cd examples/workflow-test && yarn test:standalone", | ||
| "presentation": { | ||
| "reveal": "always", | ||
| "panel": "new" | ||
| }, | ||
| "problemMatcher": [] | ||
| } | ||
| ] | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,52 @@ | ||
| # Eclipse GLSP - Playwright | ||
|
|
||
| We are planning to provide an end-to-end testing library for [GLSP diagrams](https://github.com/eclipse-glsp/glsp) based on [Playwright](https://playwright.dev). | ||
| A Playwright-based framework for testing the [Graphical Language Server Platform (GLSP)](https://github.com/eclipse-glsp/glsp). | ||
|
|
||
| ## Structure | ||
|
|
||
| - `@eclipse-glsp/glsp-playwright`: Generic Playwright testing framework | ||
|
|
||
| ## Building | ||
|
|
||
| This project is built with `yarn`. | ||
|
|
||
| ## Workflow Diagram Example | ||
|
|
||
| The workflow diagram is a consistent example provided by all GLSP components. The example implements a simple flow chart diagram editor with different types of nodes and edges (see below). | ||
| The example can be used to try out different GLSP features, as well as several available integrations with IDE platforms (Theia, VSCode, Eclipse, Standalone). | ||
|
|
||
| The example test cases test the features provided by the GLSP client. The test cases in the [Workflow Example](https://github.com/eclipse-glsp/glsp-playwright/examples/workflow-test) demonstrate all supported features. | ||
|
|
||
| https://user-images.githubusercontent.com/588090/154459938-849ca684-11b3-472c-8a59-98ea6cb0b4c1.mp4 | ||
|
|
||
| ### How to test the Workflow Diagram example? | ||
|
|
||
| Clone this repository and build the packages: | ||
|
|
||
| ```bash | ||
| yarn install | ||
| ``` | ||
|
|
||
| This command will also install Playwright and the necessary browsers. | ||
|
|
||
| Next, download a pre-built version of the Workflow Example diagram server by executing the task `Download server` or running the command: | ||
|
|
||
| ```bash | ||
| cd examples/workflow-test | ||
| yarn download:server | ||
| ``` | ||
|
|
||
| Once the server has been downloaded, run the task `Test standalone` or the command `yarn test:standalone` in the root folder. Alternatively, the command `yarn test:standalone` in the `examples/workflow-test` folder can be also run. | ||
|
|
||
| ### Tasks | ||
|
|
||
| The repository also provides build & watch tasks, so that you can build all packages with the task `Build all` or start watching all packages with `Watch all`. | ||
|
|
||
| ## Documentation | ||
|
|
||
| We provide a [Documentation](./docs) for further information on the used concepts. | ||
|
|
||
| ## More information | ||
|
|
||
| For more information, please visit the [Eclipse GLSP Umbrella repository](https://github.com/eclipse-glsp/glsp) and the [Eclipse GLSP Website](https://www.eclipse.org/glsp/). | ||
| If you have questions, please raise them in the [discussions](https://github.com/eclipse-glsp/glsp/discussions) and have a look at our [communication and support options](https://www.eclipse.org/glsp/contact/). |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,139 @@ | ||
| # Extension | ||
|
|
||
| To provide the developers the possibility to write more accessible page objects and tests, we provide **Extensions**. | ||
|
|
||
| --- | ||
|
|
||
| An **Extension** is a small isolated reusable unit that can provide new functionality to page objects. Those reusable units allow developers to add, for example, `click` functionality by reusing a default implementation provided by the framework. | ||
|
|
||
| ## Categories | ||
|
|
||
| We differentiate between **Capabilities**, **Flows**, and **Models**. | ||
|
|
||
| ### Capability | ||
|
|
||
| Capabilities provide GLSP-Client-specific functionality like accessing the `command-palette` or `popup`. Complex interaction possibilities with GLSP are defined there. | ||
|
|
||
| ### Flow | ||
|
|
||
| Flows define an action or sequence of actions the user would typically do, like `clicking`, `hovering`, or `renaming` an element. | ||
|
|
||
| - The `Click` flow consists of only a single action, namely clicking on an element. | ||
| - The `Rename` flow consists of actions like double-clicking on the element, writing the new name, and pressing enter. | ||
|
|
||
| ### Model | ||
|
|
||
| Models are mainly used to provide semantics to page objects. The framework sometimes requires further information from the page objects to enable better usability. For example, the `PLabelledElement` allows the page objects to define a label for an element. Afterward, elements based on those labels can be searched in the graph. | ||
|
|
||
| Capabilities and Flows provide default implementations most of the time; however, for **Models**, this is not always possible. Thus, making it necessary to use the interfaces directly. | ||
|
|
||
| ## Mixin | ||
|
|
||
| The basis for **Extensions** are [Mixins](https://www.typescriptlang.org/docs/handbook/mixins.html). Mixins allow us to define the class hierarchy for the page objects dynamically. Due to this reason, it is possible to reuse functionality as necessary without polluting the prototype chain and to only use the necessary functionality in the page objects. | ||
|
|
||
| ### Using Extensions | ||
|
|
||
| ```ts | ||
| const TaskManualMixin = Mix(PNode) | ||
| .flow(useClickableFlow) | ||
| .flow(useHoverableFlow) | ||
| .flow(useDeletableFlow) | ||
| .capability(useResizeHandleCapability) | ||
| .capability(usePopupCapability) | ||
| .capability(useCommandPaletteCapability) | ||
| .build(); | ||
| ``` | ||
|
|
||
| The code builds the class hierarchy for a page object. It can be read as follows. The root class is of class `PNode`. The class `PNode` is extended with `Clickable`, `Hoverable` and `Deletable` functionality. Finally, the capabilities `ResizeHandleCapability`, `PopupCapability`, and `CommandPaletteCapability` are added. | ||
|
|
||
| The result of this chaining is a new base class with all the functionality (e.g., `clicking`, `deleting`, accessing the `popup`) as listed. The `TaskManualMixin` can be again the base class for any other mixin or used as the base class for a page object. | ||
|
|
||
| ```ts | ||
| export class TaskManual extends TaskManualMixin implements PLabelledElement {...} | ||
| ``` | ||
|
|
||
| **Models** can not be always used similary to **Capabilities** and **Flows**. In this case, the page object needs to implement the `PLabelledElement` interface directly and provide the necessary implementation. Afterward, the `TaskManual` can be used in places where the `PLabelledElement` is required. | ||
|
|
||
| ### Defining new Extensions | ||
|
|
||
| **Capabilities** and **Flows** always consist of two necessary parts, namely the `Extension-Declaration` and `Extension-Provider`. **Models** have mostly only the `Extension-Declaration` part. No default implementation is available in this case, and the developers must provide it themselves. | ||
|
|
||
| #### Extension-Declaration | ||
|
|
||
| The `Extension-Declaration` interface defines the functionality the **Extension** wants to provide. | ||
|
|
||
| ```ts | ||
| export interface PopupCapability<TPopup extends Popup = Popup> { | ||
| popup(): TPopup; | ||
| popupText(): Promise<string>; | ||
| } | ||
| ``` | ||
|
|
||
| The `Extension-Declaration` of the capability `Popup` is defined in the interface `PopupCapability`. It describes two methods, namely `popup()` and `popupText()`. The former returns the `popup` page object, and the latter the popup's text directly. | ||
|
|
||
| ```ts | ||
| export interface Clickable { | ||
| click(): Promise<void>; | ||
| dblclick(): Promise<void>; | ||
| } | ||
| ``` | ||
|
|
||
| The `Extension-Declaration` of the flow `Clickable` defines two methods that trigger different click actions. | ||
|
|
||
| The framework uses those interfaces, and the final implementation is open to the users. They can reuse default implementations or provide their custom implementations. This approach allows the developers to override, restructure, or extend the functionality when necessary. | ||
|
|
||
| #### Extension-Provider | ||
|
|
||
| The `Extension-Provider` provides the default implementation for the specific `Extension-Declaration`. | ||
|
|
||
| ```ts | ||
| export function usePopupCapability<TBase extends ConstructorA<Locateable & Hoverable>>(Base: TBase): Capability<TBase, PopupCapability> { | ||
| abstract class Mixin extends Base implements PopupCapability { | ||
| popup(): Popup { | ||
| return new Popup(this); | ||
| } | ||
|
|
||
| async popupText(): Promise<string> { | ||
| await this.hover(); | ||
|
|
||
| return this.popup().innerText(); | ||
| } | ||
| } | ||
|
|
||
| return Mixin; | ||
| } | ||
| ``` | ||
|
|
||
| The `Extension-Provider` is a function that returns the class implementing the interface of the `Extension-Declaration`. The function requires a base class to allow correct prototype chaining. Constraining the possible base class (e.g., `TBase extends ConstructorA<Locateable & Hoverable>`) is also possible. Only base classes that fulfill the specific constraint are allowed in this case. The implementation is up to the developers. The framework provides a default implementation. | ||
|
|
||
| Regardless, as the `provider` and the `declaration` is separated, it is possible to use completely new implementations without reusing the default `providers`. It is only necessary to define a new function that returns a class implementing the `Extension-Declaration` while respecting the class hierarchy and using it in the `Mix.flow` or `Mix.capability` methods. | ||
|
|
||
| Overriding only some aspects of a default `provider` is also possible. As the providers always return a class, the returned class from the `provider` could be used as the base class, as visible in the following snippet: | ||
|
|
||
| ```ts | ||
| export function useCustomPopupCapability<TBase extends ConstructorA<Locateable & Hoverable>>( | ||
| Base: TBase | ||
| ): Capability<TBase, PopupCapability> { | ||
| abstract class Mixin extends usePopupCapability(Base) implements PopupCapability { | ||
| override async popupText(): Promise<string> { | ||
| await this.hover(); | ||
|
|
||
| return `Prefix: ${await this.popup().innerText()}`; | ||
| } | ||
| } | ||
|
|
||
| return Mixin; | ||
| } | ||
|
|
||
| const CustomTaskManualMixin = Mix(PNode) | ||
| .flow(useClickableFlow) | ||
| .flow(useHoverableFlow) | ||
| .flow(useDeletableFlow) | ||
| .capability(useResizeHandleCapability) | ||
| .capability(useCustomPopupCapability) | ||
| .capability(useCommandPaletteCapability) | ||
| .build(); | ||
|
|
||
| // Or reuse | ||
| const CustomTaskManualMixin = Mix(TaskManualMixin).capability(useCustomPopupCapability).build(); | ||
| ``` |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.