You like WebdriverIO and want to help making it better? Awesome! We are working to make this process as easy and transparent as possible. We might be not quite there yet but this guide will help you to ramp you up as a contributor and give you everything you need to make your first contribution. If there is any information missing that prevents you from sending in a pull request, please let us know. We treat these kind of issues like actual bugs.
Everyone who participates in this project, either as a user or a contributor, is obliged to follow the projects Code of Conduct. Every violation against it will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
The project offers a variety of ways to contribute. If you struggle to find something suited for you, join the WebdriverIO support channel on Gitter and reach out to the maintainer there. Don't be shy, they are there to help!
You can participate by:
- contributing code
- improving documentation
- help out in the Gitter support channel
- create educational content (blog posts, tutorials, videos, etc.)
- spread the good word about the project (e.g. via Twitter)
- create bugs if you discover them while using WebdriverIO
- make feature requests if you are missing something in the project
- if you'd like to support us monetarily, consider donating to the project
The maintainers of the project try to organize all issues in the way that should allow anyone to have enough context to start working on it. If this is not the case please mention it in the issue thread so that either the issue creator or a maintainer can provide more information.
If you want to contribute code, a general good first way to find a task to work on is to look into all tickets with the label
help wanted and/or
good first pick. All these tickets are up for grab if they haven't a user assigned to them. If you find something that interests you, ensure to let us know in the issue thread that you have the intend to work on it.
Often issues require some amount of context to the problem which makes it difficult to get an idea about what needs to be done. Depending on your experience using / working with the project this context can be missing. Often it helps to start with tasks around missing documentation or just increase test coverage of some parts in the code. After some time you will get more familiar with the codebase which allows you to pick up more difficult tasks.
If you can't find something that suits you, look into the project roadmap to see if there is something interesting for you. At the end you can also always reach out to the maintainers in the Gitter support channel. They are responsible to find a task for you.
We are happy for every idea you have that improves the usability of the framework. If you have an idea about a new feature please raise a feature request first to get feedback by the maintainer team on it. This lets us reach an agreement on your proposal before you put significant effort into it.
If you’re only fixing a bug, it’s fine to submit a pull request right away, but we still recommend to file an issue detailing what you’re fixing. This is helpful in case we don’t accept that specific fix but want to keep track of the issue.
If you make any changes to the code, you want to test it quickly to see if they do what you expect. There are a couple of ways to do that in WebdriverIO. For one, you can link single sub-packages into your own project to see if the changes you've made have the effect you expected.
Another way to test changes in WebdriverIO is by using its example directory or by running its smoke test suite. The example directory is a set of sample scripts that use WebdriverIO in various of ways. Here, you need to have a browser driver running to run the scripts. With the smoke test suite you can run various flavors of WebdriverIO within a predefined execution scenario. All of these scenarios are defined in our WebDriver Mock Service that mimics a browser driver by stubbing the endpoints with predefined responses. It is a great way to run WebdriverIO suites quickly without having to setup anything.
Once you have a fix implemented or finished a feature implementation you can make a pull request. Your changes needs to be pushed on your WebdriverIO fork. In the GitHub UI you should see a button popping up that allows you to raise a PR to the main repository.
We already provide a template for you to fill out. There are not many rules to follow here. Just try to explain your change with as much detail as possible. Make sure that you have written enough unit tests for your changes otherwise the code coverage check will let the build fail.
Like in many Open Source projects we ask you to sign a CLA which is a Contributor License Agreement that ensures that all contributions to the project are licensed under the project's respective open source license, which is MIT. It regulates the legal implications of you providing us (as the OpenJS Foundation) code changes.
The WebdriverIO maintainer will review your pull request as soon as possible. They will then either approve and merge your changes, request modifications or close with an explanation.
In order to set up this project and start contributing follow this step by step guide:
Fork the project.
Clone the project somewhere on your computer$ git clone firstname.lastname@example.org:<your-username>/webdriverio.git
On Windows, you need to set git config
trueas we currently have some symbolic links for type definition committed to our repo.
- To set git config globally:
git config --global --add core.symlinks true
- To set git config locally when cloning the repo:
git -c core.symlinks=true clone email@example.com:<your-username>/webdriverio.git.
See https://github.com/git-for-windows/git/wiki/Symbolic-Links for more information
- To set git config globally:
If you need to update your fork you can do so following the steps here
Switch to Node v14 LTS (you should be able to use older/newer versions of Node but we recommend to use v14 LTS so all developers are on the same side). We recommend to use
nvmto switch between Node.js versions.
Set up the project:$ npm install$ npm run setup-full
The second command does two things:
Bootstraps sub-projects via
npm run bootstrap
Many packages depend on each other, in order to properly set up the dependency tree you need to run the Lerna Bootstrap command to create all necessary links. As this project also does some other house keeping tasks, it is recommended to use the package bootstrap command.
Builds all subpackages via
npm run build
As the last step you need to build all sub-packages in order to resolve the internal dependencies. WebdriverIO uses TypeScript as a compiler. We are currently transitioning to TypeScript so you will see a mixture of normal JS files and TypeScript files.
Run Tests to ensure that everything is set up correctly$ npm run test# run test for a specific sub project (e.g. webdriver)$ npx jest ./packages/webdriver/tests --collectCoverage=false
It should give you a passing result. Now you can move on to set up your development environment and start working on some code. If tests do not pass please create an issue and provide logs to the error.
If you start making changes to specific packages, make sure you listen to file changes and transpile the code every time you press save. To do that for all packages, run:
If you only work on a single package, you can watch only for that one by calling:
It is also a good idea to run jest in watch mode while developing on a single package to see if changes affect any tests:
WebdriverIO uses TypeScript to ensure that code is statically typed and common mistakes misusing them are avoided. If you are new to TypeScript have a look at these awesome essential resources to get started with it.
provides its own type definitions for projects that use TypeScript. Given the large amount of commands it would make it unmaintainable to not automate the process of generating these. However there are certain edge cases where manual work is required.
All type definitions are generated by the TypeScript compiler. There are some essential packages for that:
@wdio/typespackage provides all general types that are used across the code based, e.g. Capabilities, Options etc. If you need a type definitions across multiple packages it is a good idea to define them in here
@wdio/protocolpackage defines all protocol commands, their function parameters and return types
- all other types should be defined in the package where they are used, here we tend to have general types defined in a
You can find all files responsible for the generating the typings here. You can trigger the process by calling:
This will run the scripts in the directory shown above and generate the typings for all protocol commands. Whenever you change those protocol commands, make sure you re-generate the types with the command shown above.
For the development on the WebdriverIO code base you can use examples files that have been created by the maintainers in the examples directory. They cover various use cases and are setup so that they a run with the code from the repository. Let's say you make changes to the WDIO testrunner and want to see if they are applied correctly you can just run the testrunner examples by calling:
This will run a simple test suite using the testrunner with Mochajs. There are similar examples for other frameworks, custom services and reporters as well as using the devtools protocol as automation engine. Feel free to add examples if they help testing features you are working on.
When a PR gets submitted, WebdriverIO runs the following checks:
- Dependency Checks
We automatically check if every sub-package has all the dependencies from its
package.jsoninstalled. You can manually trigger this check by calling:$ npm run test:depcheck
A common ESLint test to align code styles and detect syntax errors early.
You can manually trigger this check by calling:$ npm run test:eslint
- TypeScript Definition Tests
As we generate our type definitions, we want to be cautious that the generated definitions actually define the interface as expected. Read more
on that at Testing Type Definitions.
You can manually trigger this check by calling:$ npm run test:typings
- Unit Tests
Like every project we unit-test our code and ensure that new patches are properly tested. The coverage threshold is pretty high so ensure that
your changes cover all necessary code paths. We are using Jest as a unit test framework here.
You can manually trigger this check by calling:$ npm run test:coverage
- Smoke Tests
While unit tests already cover a lot of cases, we run in addition to that smoke tests that simulate test scenarios which are difficult to test
on a unit level as they include functionality of dependencies that are stubbed out in unit tests. Such scenarios are, for example, proper
test retries or failure handling. Smoke tests run actual e2e tests where the driver is being stubbed (via
@wdio/smoke-test-service) to return fake results. You can manually trigger this check by calling:$ npm run test:smoke
- e2e Tests
Last but not least, we run actual e2e tests with a real browser to ensure that our WebDriver DevTools implementation is working as expected. These
tests spin up headless Chrome and Firefox browsers to test the commands implemented in the
devtoolspackage. Given that the WebDriver functionality is already tested with WPT, we don't need to do it there. In order to run these tests, an installation of Firefox Nightly and Google Chrome is required. You can manually trigger this check by calling:$ npm run test:e2e
The project tries to keep a high test coverage to ensure that changes to code are intentional and well thought through. Therefor "normally" there is a unit test file for every code file, located in a test directory. For example the unit tests for:
are located in
If that is not the case the functionality of that file might be tested through a different file. We recommend to write unit tests for every new function being written in the code base. We advise to mock out every dependency to either other packages or modules using Jests mock capabilities.
During development it makes sense to focus running unit tests for a single file rather the whole code base. For example if you work on the
getCSSProperty command it makes sense to run only the unit test for that specific command by calling:
--watch flag the unit tests will be re-run as soon as you change something within the file.
WebdriverIO maintains a set of smoke test suites that allows to represent the full e2e experience of a user running the wdio testrunner. It is set up in a way so it doesn't require an actual browser driver since all requests are mocked using the
@wdio/webdriver-mock-service. This offers you an opportunity to run a wdio test suite without setting up a browser driver and a test page. You can run all smoke tests via:
There is one
smoke.runner.js file that triggers all tests. It contains several test suites defined that run in different environments, e.g. Mocha, Jasmine and Cucumber. You can run a specific test suite by calling, e.g.:
Every of these test suites are functions that trigger the wdio testrunner programmatically using the
launch helper method. All you need to pass in is a path to your config file and with what you want to overwrite the config. Most of the smoke test use a common config file and overwrite properties specific for their use case.
If you test custom WebDriver commands, you can define your own scenario of mock responses in the
To make sure that we don't accidentally change the types and cause users' test to break, we run some simple TypeScript checks. You can run all the type definition tests by running:
This will run all the tests for all the type definitions WebdriverIO provides. These tests just check if TypeScript can compile them according to the generated type definitions. All the type checks are located in
/webdriverio/tests/typings. If you extend a WebdriverIO command or interfaces for other type definitions, please ensure that you have used it in these files. The directory contains tests for the asynchronous usage of WebdriverIO.
For example, to test the
touchActions properties, we have it tested in
as well as in
This repository contains everything to set up, build and deploy the WebdriverIO documentation pages. We are using Docusaurus (v2) to generate the page. The content is generated based off:
- the guidelines pages from markdown files of the docs directory
- service and reporter docs from the readme files of those packages within this repository
- service and reporter docs from 3rd party plugins (defined in these JSON files) that are downloaded from GitHub and parsed
- the protocol APIs from the
- the WebdriverIO API that is parsed out of the JSDoc comments of individual commands (e.g.,
Changes to the docs need to be done in one of these places. Please note that changes to e.g. the config file have to be updated in multiple places given that config files are wide spread (as examples or test files) within this repository. A good way to go about this is to look for all occurrences of a certain string of the config and update changes in all findings.
After you have set up the project you can go into the
website directory to set up the docs page and run it on your local machine. To do so, run:
This will set up everything needed to run the page on
localhost:3000. If you need to run on a different host or port, pass them as additional arguments to npm start, like
-- --host 0.0.0.0.
You can now modify the content of the
/website/docs files as well as change styles and templates. The page will be automatically updated. If you add documentation in other places, you have to rerun the
npm start script to re-generate the docs.
Every time a new release is pushed to GitHub the WebdriverIO docs need to be build and re-deployed to the project's S3 bucket. The process is defined in a GitHub Actions pipeline. All you need to do (as maintainer) is to trigger the pipeline. The rest is handled by the workflow.
All WebdriverIO sub packages require a certain structure to work within the wdio ecosystem. To simplify the process of creating a new sub package, we built an NPM script that does all the boilerplate work for you. Just run:
It will ask you about the type and name of the new package and create all the files for you.
Starting from v6 the WebdriverIO team tries to backport all features that would be still backwards compatible with older versions. The team tries to release a new major version every year (usually around December/January). With a new major version update (e.g. v7) we continue to maintain the last version (e.g. v6) and deprecate the previous maintained version (e.g. v5, v4 and lower). With that the team commits to always support 2 major versions.
Everyone triaging or reviewing a PR should label it with
backport-requested if the changes can be applied to the maintained (previous) version. Generally every PR that would not be a breaking change for the previous version should be considered to be ported back. If a change relies on features or code pieces that are only available in the current version, then a back port can still be considered if you feel comfortable making the necessary adjustments. That said, don't feel forced to back port code if the time investment and complexity is too high. Backporting functionality is a reasonable contribution that can be made by any contributor.
Once a PR with a
backport-requested label got merged, you are responsible for backporting the patch to the older version. To do so, pull the latest code from GitHub:
Before you can start, please export an
GITHUB_AUTH token into your environment in order to allow the executing script to fetch data about pull requests and set proper labels. Go to your personal access token settings page and generate such a token with only having the
public_repo field enabled. Then export it into your environment and run the backport script. It fetches all commits connected with PRs that are labeled with
backport-requested and cherry-picks them into the maintenance branch. Via an interactive console you can get the chance to review the PR again and whether you want to backport it or not. To start the process, just execute:
If during the process a cherry-pick fails, you can always abort and manually troubleshoot. If you are not able to resolve the problem, create an issue in the repo and include the author of that PR. A successful backport of two PRs will look like this:
You can always reach out to the
webdriverio/ProjectCommitters channel on Gitter for questions.
Package releases are made using Lerna's release capabilities as GitHub workflow and executed by the technical steering committee only. All you need to do is go to the
Manual NPM Publish workflow and trigger a new run. Choose the appropriate version upgrade based on the Semantic Versioning. To help choose the right release type, here are some general guidelines:
- Breaking Changes: never do these by yourself! A major release is always a collaborative effort between all TSC members. It requires consensus from all of them.
- Minor Release: minor releases are always required if a new, user focused feature was added to one of the packages. For example, if a command was added to WebdriverIO or if a service provides a new form of integration, a minor version bump would be appropriate. However if an internal package like
@wdio/local-runnerexposes a new interface that is solely used internally, we can consider that as a patch release.
- Patch Release: every time a bug is fixed, documentation (this includes TypeScript definitions) gets updated or existing functionality is improved, we should do a patch release.
If you are unsure about which release type to pick, reach out in the TSC Gitter channel. By setting an NPM tag you can also release a current version with e.g. a
next tag to test changes before we roll them out to all users.
As part of the OpenJS World 2020 Collaborator Summit the WebdriverIO team hosted a workshop on "Contributing to WebdriverIO" that can help you get familiar with the code base and the project. Have a watch:
This repository contains all necessary packages of the WebdriverIO project (excluding plugins that were contributed by 3rd party developers). These packages have individual descriptions in their README files (
/packages/<package>/README.md) providing information about their scope and responsibilities. Even though the build commands might differ from package to package the way to work with these is the same. This project uses Lerna to manage all its subprojects in this monolith repository.