Our Approach to Interactive and Tested Documentation
The WebdriverIO framework is a versatile tool that offers a lot of features for you to play around with. The goal of our project documentation is to communicate these features well and give you an understanding, on how they could be applied in your project. A central contributor to this are code examples. Many times they can convey the principle idea of a feature like a picture that is worth a thousand words.
It is not a surprise that many projects out there have code examples embedded in their project documentation. Many of them are even interactive and allow users to fiddle around with the code in real time, e.g. the new React Docs, or provide "playgrounds" with live examples, like on svelte.dev.
When it comes to having code examples on a documentation page, a common problem that arises with them is that examples:
- are made up and often don't reflect reality
- contain errors because we are all just humans
- are getting outdated as interfaces change
- can be difficult to apply in your own project
As an attempt to improve our code examples on this project page we started to roll out some changes to the documentation that hopefully addresses these issues:
loading...
As you can see, some examples now have two buttons that allow you to run them or view them on GitHub. But what does that mean?
Extract Examples from Docs
As a first step we started to remove all code examples from our documentation page and moved them into a dedicated repository. This allows us to treat these examples as code and set-up the necessary infrastructure, e.g. CI/CD or automated dependency updates, to ensure quality and correctness.
So say hello 👋 to this new repository in our organization that now contains a lot of examples that we re-use on this website.
You can see that every example is self contained in its own directory to keep everything very simple. A big list of NPM scripts allows you to run specific examples with just a single command.
In order to embed the examples back into the website, we are using a plugin for Docusaurus that downloads the code based on a simple GitHub reference link. So instead of having code within our markdown files, we just reference the location on Github, e.g.:
loading...
The plugin then downloads the code and only shows provided code lines of that file. Here is the final result of that:
loading...
If you are using a different tool for building your static docs, chances are that it has similar plugins available to just do that.
Testing Examples
Now that we have everything nicely encapsulated into a dedicated repository, we can use CI/CD to test all examples on regular basis. A simple GitHub workflow can trigger the execution of these examples and have the pipeline fail if any of them have an error:
name: Test
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
exampleDir:
- click
# more example directories here
# ...
- api/webdriver
steps:
- name: Checkout
uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 18
- name: Install
run: npm install
- name: Test
run: npm run ${{ matrix.exampleDir }}
working-directory: ${{ matrix.exampleDir }}
Most of the examples are written as normal WebdriverIO test files and contain normal assertions like any other test would do, e.g. an example that shows how to fetch elements using command chaining would be written as following:
it('should get the text of a menu link', async () => {
const menu$ = await $('#menu') // or `browser.$('#menu')`
console.log(await menu$.$$('li')[2].$('a').getText()) // outputs: "API"
await expect(menu$.$$('li')[2].$('a')).toHaveText('API')
})
With the ability to reference certain code lines we can just strip out the testing part of the example and focus on what's important:
loading...