mirror of
https://github.com/tauri-apps/tauri.git
synced 2025-01-01 23:42:33 +03:00
docs: webdriver guide (#2461)
Co-authored-by: Ngo Iok Ui (Wu Yu Wei) <wusyong9104@gmail.com>
This commit is contained in:
parent
17500cbadb
commit
40d08a60fe
@ -69,6 +69,23 @@
|
||||
"usage/guides/visual/menu",
|
||||
"usage/guides/visual/system-tray"
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": "WebDriver Testing",
|
||||
"type": "category",
|
||||
"items": [
|
||||
"usage/guides/webdriver/introduction",
|
||||
{
|
||||
"label": "Example Application",
|
||||
"type": "category",
|
||||
"items": [
|
||||
"usage/guides/webdriver/example/setup",
|
||||
"usage/guides/webdriver/example/webdriverio",
|
||||
"usage/guides/webdriver/example/selenium"
|
||||
]
|
||||
},
|
||||
"usage/guides/webdriver/ci"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
|
100
docs/usage/guides/webdriver/ci.md
Normal file
100
docs/usage/guides/webdriver/ci.md
Normal file
@ -0,0 +1,100 @@
|
||||
---
|
||||
title: Continuous Integration
|
||||
---
|
||||
|
||||
Utilizing Linux and some programs to create a fake display, it is possible to run [WebDriver] tests with
|
||||
[`tauri-driver`] on your CI. The following example will use the [WebdriverIO] example we [previously built together] and
|
||||
GitHub Actions.
|
||||
|
||||
This means the following assumptions:
|
||||
|
||||
1. The Tauri application is in the repository root and the binary builds when running `cargo build --release`.
|
||||
2. The [WebDriverIO] test runner is in the `webdriver/webdriverio` directory and runs when `yarn test` is used in that
|
||||
directory.
|
||||
|
||||
The following is a commented GitHub Actions workflow file at `.github/workflows/webdriver.yml`
|
||||
|
||||
```yaml
|
||||
# run this action when the repository is pushed to
|
||||
on: [ push ]
|
||||
|
||||
# the name of our workflow
|
||||
name: WebDriver
|
||||
|
||||
jobs:
|
||||
# a single job named test
|
||||
test:
|
||||
# the display name the test job
|
||||
name: WebDriverIO Test Runner
|
||||
|
||||
# we want to run on the latest linux environment
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
# the steps our job runs **in order**
|
||||
steps:
|
||||
# checkout the code on the workflow runner
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
# install system dependencies that Tauri needs to compile on Linux.
|
||||
# note the extra dependencies for `tauri-driver` to run which are `webkit2gtk-driver` and `xvfb`
|
||||
- name: Tauri dependencies
|
||||
run: >-
|
||||
sudo apt-get update &&
|
||||
sudo apt-get install -y
|
||||
libgtk-3-dev
|
||||
libgtksourceview-3.0-dev
|
||||
webkit2gtk-4.0
|
||||
libappindicator3-dev
|
||||
webkit2gtk-driver
|
||||
xvfb
|
||||
|
||||
# install the latest Rust stable
|
||||
- name: Rust stable
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
|
||||
# we run our rust tests before the webdriver tests to avoid testing a broken application
|
||||
- name: Cargo test
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: test
|
||||
|
||||
# build a release build of our application to be used during our WebdriverIO tests
|
||||
- name: Cargo build
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: build
|
||||
args: --release
|
||||
|
||||
# install the latest stable node version at the time of writing
|
||||
- name: Node v16
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 16.x
|
||||
|
||||
# install our Node.js dependencies with Yarn
|
||||
- name: Yarn install
|
||||
run: yarn install
|
||||
working-directory: webdriver/webdriverio
|
||||
|
||||
# install the latest version of `tauri-driver`.
|
||||
# note: the tauri-driver version is independent of any other Tauri versions
|
||||
- name: Install tauri-driver
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: install
|
||||
args: tauri-driver
|
||||
|
||||
# run the WebdriverIO test suite.
|
||||
# we run it through `xvfb-run` (the dependency we installed earlier) to have a fake
|
||||
# display server which allows our application to run headless without any changes to the code
|
||||
- name: WebdriverIO
|
||||
run: xvfb-run yarn test
|
||||
working-directory: webdriver/webdriverio
|
||||
```
|
||||
|
||||
[WebDriver]: https://www.w3.org/TR/webdriver/
|
||||
[`tauri-driver`]: https://crates.io/crates/tauri-driver
|
||||
[WebdriverIO]: https://webdriver.io/
|
||||
[previously built together]: example/webdriverio
|
256
docs/usage/guides/webdriver/example/selenium.md
Normal file
256
docs/usage/guides/webdriver/example/selenium.md
Normal file
@ -0,0 +1,256 @@
|
||||
---
|
||||
title: Selenium
|
||||
---
|
||||
import Alert from '@theme/Alert'
|
||||
import Tabs from '@theme/Tabs'
|
||||
import TabItem from '@theme/TabItem'
|
||||
|
||||
<Alert title="Example Application" type="info" icon="info-alt">
|
||||
|
||||
This [Selenium] guide expects you to have already gone through the [example Application setup] in order to follow
|
||||
step-by-step. The general information may still be useful otherwise.
|
||||
</Alert>
|
||||
|
||||
This WebDriver testing example will use [Selenium] and a popular Node.js testing suite. It is expected to already have
|
||||
Node.js installed, along with `npm` or `yarn` although the [finished example project] uses `yarn`.
|
||||
|
||||
## Create a Directory for the Tests
|
||||
|
||||
Let's start off by creating a space in our project to write these tests. We are going to be using a nested directory for
|
||||
this example project as we will later also go over other frameworks, but typically you will only need to use one. Create
|
||||
the directory we will use with `mkdir -p webdriver/selenium`. The rest of this guide will assume you are inside the
|
||||
`webdriver/selenium` directory.
|
||||
|
||||
## Initializing a Selenium Project
|
||||
|
||||
We will be using a pre-existing `package.json` to bootstrap this test suite because we have already chosen specific
|
||||
dependencies to use and want to showcase a simple working solution. The bottom of this section has a collapsed
|
||||
guide on how to set it up from scratch.
|
||||
|
||||
`package.json`:
|
||||
```json
|
||||
{
|
||||
"name": "selenium",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"test": "mocha"
|
||||
},
|
||||
"dependencies": {
|
||||
"chai": "^4.3.4",
|
||||
"mocha": "^9.0.3",
|
||||
"selenium-webdriver": "^4.0.0-beta.4"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
We have a script which runs [Mocha] as a test framework exposed as the `test` command. We also have various dependencies
|
||||
that we will be using to run the tests. [Mocha] as the testing framework, [Chai] as the assertion library, and
|
||||
[`selenium-webdriver`] which is the Node.js [Selenium] package.
|
||||
|
||||
<details><summary>Click me if you want to see how to set a project up from scratch</summary>
|
||||
|
||||
If you wanted to install the dependencies from scratch, just run the following command.
|
||||
|
||||
<Tabs groupId="package-manager"
|
||||
defaultValue="yarn"
|
||||
values={[
|
||||
{label: 'npm', value: 'npm'}, {label: 'Yarn', value: 'yarn'},
|
||||
]}>
|
||||
<TabItem value="npm">
|
||||
|
||||
```sh
|
||||
npm install mocha chai selenium-webdriver
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
|
||||
<TabItem value="yarn">
|
||||
|
||||
```sh
|
||||
yarn add mocha chai selenium-webdriver
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
I suggest also adding a `"test": "mocha"` item in the `package.json` `"scripts"` key so that running mocha can be called
|
||||
simply with
|
||||
|
||||
<Tabs groupId="package-manager"
|
||||
defaultValue="yarn"
|
||||
values={[
|
||||
{label: 'npm', value: 'npm'}, {label: 'Yarn', value: 'yarn'},
|
||||
]}>
|
||||
<TabItem value="npm">
|
||||
|
||||
```sh
|
||||
npm test
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
|
||||
<TabItem value="yarn">
|
||||
|
||||
```sh
|
||||
yarn test
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
</details>
|
||||
|
||||
## Testing
|
||||
|
||||
Unlike the [WebdriverIO Test Suite](webdriverio#config), Selenium does not come out of the box with a Test Suite and
|
||||
leaves it up to the developer to build those out. We chose [Mocha] which is pretty neutral, and not related to WebDrivers
|
||||
at all, so our script will need to do a bit of work to set up everything for us in the right order. [Mocha] expects a
|
||||
testing file at `test/test.js` by default, so let's create that file now.
|
||||
|
||||
`test/test.js`:
|
||||
```js
|
||||
const os = require("os");
|
||||
const path = require("path");
|
||||
const { expect } = require("chai");
|
||||
const { spawn, spawnSync } = require("child_process");
|
||||
const { Builder, By, Capabilities } = require("selenium-webdriver");
|
||||
|
||||
// create the path to the expected application binary
|
||||
const application = path.resolve(
|
||||
__dirname,
|
||||
"..",
|
||||
"..",
|
||||
"..",
|
||||
"target",
|
||||
"release",
|
||||
"hello-tauri-webdriver"
|
||||
);
|
||||
|
||||
// keep track of the webdriver instance we create
|
||||
let driver;
|
||||
|
||||
// keep track of the tauri-driver process we start
|
||||
let tauriDriver;
|
||||
|
||||
before(async function() {
|
||||
// set timeout to 2 minutes to allow the program to build if it needs to
|
||||
this.timeout(120000)
|
||||
|
||||
// ensure the program has been built
|
||||
spawnSync("cargo", ["build", "--release"]);
|
||||
|
||||
// start tauri-driver
|
||||
tauriDriver = spawn(
|
||||
path.resolve(os.homedir(), ".cargo", "bin", "tauri-driver"),
|
||||
[],
|
||||
{ stdio: [null, process.stdout, process.stderr] }
|
||||
);
|
||||
|
||||
const capabilities = new Capabilities();
|
||||
capabilities.set("tauri:options", { application });
|
||||
capabilities.setBrowserName("wry");
|
||||
|
||||
// start the webdriver client
|
||||
driver = await new Builder()
|
||||
.withCapabilities(capabilities)
|
||||
.usingServer("http://localhost:4444/")
|
||||
.build();
|
||||
});
|
||||
|
||||
after(async function() {
|
||||
// stop the webdriver session
|
||||
await driver.quit();
|
||||
|
||||
// kill the tauri-driver process
|
||||
tauriDriver.kill();
|
||||
});
|
||||
|
||||
describe("Hello Tauri", () => {
|
||||
it("should be cordial", async () => {
|
||||
const text = await driver.findElement(By.css("body > h1")).getText();
|
||||
expect(text).to.match(/^[hH]ello/);
|
||||
});
|
||||
|
||||
it("should be excited", async () => {
|
||||
const text = await driver.findElement(By.css("body > h1")).getText();
|
||||
expect(text).to.match(/!$/);
|
||||
});
|
||||
|
||||
it("should be easy on the eyes", async () => {
|
||||
// selenium returns color css values as rgb(r, g, b)
|
||||
const text = await driver.findElement(By.css("body")).getCssValue("background-color");
|
||||
|
||||
const rgb = text.match(/^rgb\((?<r>\d+), (?<g>\d+), (?<b>\d+)\)$/).groups;
|
||||
expect(rgb).to.have.all.keys('r','g','b');
|
||||
|
||||
const luma = 0.2126 * rgb.r + 0.7152 * rgb.g + 0.0722 * rgb.b ;
|
||||
expect(luma).to.be.lessThan(100)
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
If you are familiar with JS testing frameworks, `describe`, `it`, and `expect` should look familiar. We also have
|
||||
semi-complex `before()` and `after()` callbacks to setup and teardown mocha. Lines that are not the tests themselves
|
||||
have comments explaining what the setup and teardown code is doing. If you were familiar with the Spec file from the
|
||||
[WebdriverIO example](webdriverio#spec), you will notice a lot more code that isn't tests, as we have to set up a few
|
||||
more WebDriver related items.
|
||||
|
||||
## Running the Test Suite
|
||||
|
||||
Now that we are all set up with our dependencies and our test script, lets run it!
|
||||
|
||||
<Tabs groupId="package-manager"
|
||||
defaultValue="yarn"
|
||||
values={[
|
||||
{label: 'npm', value: 'npm'}, {label: 'Yarn', value: 'yarn'},
|
||||
]}>
|
||||
<TabItem value="npm">
|
||||
|
||||
```sh
|
||||
npm test
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
|
||||
<TabItem value="yarn">
|
||||
|
||||
```sh
|
||||
yarn test
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
We should see output the following output:
|
||||
|
||||
```text
|
||||
➜ selenium git:(main) ✗ yarn test
|
||||
yarn run v1.22.11
|
||||
$ mocha
|
||||
|
||||
|
||||
Hello Tauri
|
||||
✔ should be cordial (120ms)
|
||||
✔ should be excited
|
||||
✔ should be easy on the eyes
|
||||
|
||||
|
||||
3 passing (588ms)
|
||||
|
||||
Done in 0.93s.
|
||||
```
|
||||
|
||||
We can see that our `Hello Tauri` sweet we created with `decribe` had all 3 items we created with `it` pass their
|
||||
tests!
|
||||
|
||||
With [Selenium] and some hooking up to a test suite, we just enabled e2e testing without modifying our Tauri
|
||||
application at all!
|
||||
|
||||
|
||||
[Selenium]: https://selenium.dev/
|
||||
[finished example project]: https://github.com/chippers/hello_tauri
|
||||
[example Application setup]: setup
|
||||
[Mocha]: https://mochajs.org/
|
||||
[Chai]: https://www.chaijs.com/
|
||||
[`selenium-webdriver`]: https://www.npmjs.com/package/selenium-webdriver
|
190
docs/usage/guides/webdriver/example/setup.md
Normal file
190
docs/usage/guides/webdriver/example/setup.md
Normal file
@ -0,0 +1,190 @@
|
||||
---
|
||||
title: Setup Example
|
||||
---
|
||||
|
||||
import HelloTauriWebdriver from '@site/static/img/webdriver/hello-tauri-webdriver.png'
|
||||
|
||||
This example application is going to solely focus on adding WebDriver testing to an already existing project. To have a
|
||||
project to test on in the next two sections, we are going to set up an extremely minimal Tauri application for use in
|
||||
our testing. We will not use the Tauri CLI, any frontend dependencies or build steps, and not be bundling the
|
||||
application afterwards. This is to showcase exactly a minimal suite to show off adding WebDriver testing to an existing
|
||||
application.
|
||||
|
||||
If you just want to see the finished example project that utilizes what will be shown in this example guide, then you
|
||||
can see https://github.com/chippers/hello_tauri.
|
||||
|
||||
## Initializing a Cargo Project
|
||||
|
||||
We want to create a new binary Cargo project to house this example application. We can easily do this from the command
|
||||
line with `cargo new hello-tauri-webdriver --bin` which will scaffold a minimal binary Cargo project for us. This
|
||||
directory will serve as the working directory for the rest of this guide, so make sure commands you run are inside this
|
||||
new `hello-tauri-webdriver/` directory.
|
||||
|
||||
## Creating a Minimal Frontend
|
||||
|
||||
We will create a minimal HTML file to act as the frontend to our example application. We will also be using a few things
|
||||
from this frontend later during our WebDriver tests.
|
||||
|
||||
First, let's create our Tauri `distDir` that we know we will need once building the Tauri portion of the application.
|
||||
`mkdir dist` should create a new directory called `dist/` in which we will be placing the following `index.html` file.
|
||||
|
||||
`dist/index.html`:
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Hello Tauri!</title>
|
||||
<style>
|
||||
body {
|
||||
/* Add a nice colorscheme */
|
||||
background-color: #222831;
|
||||
color: #ececec;
|
||||
|
||||
/* Make the body the exact size of the window */
|
||||
margin: 0;
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
|
||||
/* Vertically and horizontally center children of the body tag */
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hello, Tauri!</h1>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
## Adding Tauri to the Cargo Project
|
||||
|
||||
Next, we will add some necessary items to make our Cargo project into a Tauri project. First, is adding the dependencies
|
||||
to the Cargo Manifest (`Cargo.toml`) so that Cargo knows to pull in our dependencies while building.
|
||||
|
||||
`Cargo.toml`:
|
||||
|
||||
```toml
|
||||
[package]
|
||||
name = "hello-tauri-webdriver"
|
||||
version = "0.1.0"
|
||||
edition = "2018"
|
||||
|
||||
# Needed to set up some things for Tauri at build time
|
||||
[build-dependencies]
|
||||
tauri-build = "1.0.0-beta.4"
|
||||
|
||||
# The actual Tauri dependency, along with `custom-protocol` to serve the pages.
|
||||
[dependencies]
|
||||
tauri = { version = "1.0.0-beta.6", features = ["custom-protocol"] }
|
||||
|
||||
# Make --release build a binary that is small (opt-level = "s") and fast (lto = true).
|
||||
# This is completely optional, but shows that testing the application as close to the
|
||||
# typical release settings is possible. Note: this will slow down compilation.
|
||||
[profile.release]
|
||||
incremental = false
|
||||
codegen-units = 1
|
||||
panic = "abort"
|
||||
opt-level = "s"
|
||||
lto = true
|
||||
```
|
||||
|
||||
As you may have noticed, we added a `[build-dependency]`. To use the build dependency, we must use it from a build
|
||||
script. We will create one now at `build.rs`.
|
||||
|
||||
`build.rs`:
|
||||
|
||||
```rust
|
||||
fn main() {
|
||||
// Only watch the `dist/` directory for recompiling, preventing unnecessary
|
||||
// changes when we change files in other project subdirectories.
|
||||
println!("cargo:rerun-if-changed=dist");
|
||||
|
||||
// Run the Tauri build-time helpers
|
||||
tauri_build::build()
|
||||
}
|
||||
```
|
||||
|
||||
With all that setup, our Cargo Project now knows how to pull in and build our Tauri dependencies. Let's finish making
|
||||
this minimal example a Tauri application by setting up Tauri in the actual project code. We will be editing
|
||||
the `src/main.rs`
|
||||
file to add this Tauri functionality.
|
||||
|
||||
`src/main.rs`:
|
||||
|
||||
```rust
|
||||
fn main() {
|
||||
tauri::Builder::default()
|
||||
.run(tauri::generate_context!())
|
||||
.expect("unable to run Tauri application");
|
||||
}
|
||||
```
|
||||
|
||||
Pretty simple, right?
|
||||
|
||||
## Tauri Configuration
|
||||
|
||||
We are going to need 2 things to successfully build the application. First, we need an icon file. You can use any PNG
|
||||
for this next part and copy it into `icon.png`. Typically, this will be provided as part of the scaffolding when you use
|
||||
the Tauri CLI to create a project. To get the default Tauri icon, we can download the icon used by the Hello Tauri
|
||||
example repository with the
|
||||
command `curl -L "https://github.com/chippers/hello_tauri/raw/main/icon.png" --output icon.png`.
|
||||
|
||||
The second thing we will need is a `tauri.conf.json` to specify some important configuration values to Tauri. Again,
|
||||
this would typically come from the `tauri init` scaffolding command, but we will be creating our own minimal config
|
||||
here.
|
||||
|
||||
`tauri.conf.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"build": {
|
||||
"distDir": "dist"
|
||||
},
|
||||
"tauri": {
|
||||
"bundle": {
|
||||
"identifier": "studio.tauri.hello_tauri_webdriver",
|
||||
"icon": [
|
||||
"icon.png"
|
||||
]
|
||||
},
|
||||
"allowlist": {
|
||||
"all": false
|
||||
},
|
||||
"windows": [
|
||||
{
|
||||
"width": 800,
|
||||
"height": 600,
|
||||
"resizable": true,
|
||||
"fullscreen": false
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
I'll go over some of these. You can see the `dist/` directory we created earlier specified as the `distDir` property. We
|
||||
set a bundle identifier so that the built application has a unique id, along with setting the `icon.png` as the only
|
||||
icon. We aren't using any Tauri apis or features, so we just disable all them in `allowlist` by setting `"all": false`.
|
||||
The window values just sets a single window to be created with some reasonable default values.
|
||||
|
||||
At this point, we have a basic Hello World application that when ran, should display a simple greeting.
|
||||
|
||||
## Running the Example Application
|
||||
|
||||
To make sure we did it right, let's build this application! We will run this as a `--release` application because we
|
||||
will also run our WebDriver tests with a release profile. Run `cargo run --release` and after some compiling we should
|
||||
see the following application pop up.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img src={HelloTauriWebdriver}/>
|
||||
</div>
|
||||
|
||||
_Note: If you are modifying the application and want to use the Devtools, then run it without `--release` and "Inspect
|
||||
Element" should be available in the right click menu._
|
||||
|
||||
We should now be ready to start testing this application with some WebDriver frameworks. This guide will go over both
|
||||
[WebdriverIO](webdriverio) and [Selenium](selenium) in that order.
|
275
docs/usage/guides/webdriver/example/webdriverio.md
Normal file
275
docs/usage/guides/webdriver/example/webdriverio.md
Normal file
@ -0,0 +1,275 @@
|
||||
---
|
||||
title: WebdriverIO
|
||||
---
|
||||
import Alert from '@theme/Alert'
|
||||
import Tabs from '@theme/Tabs'
|
||||
import TabItem from '@theme/TabItem'
|
||||
|
||||
<Alert title="Example Application" type="info" icon="info-alt">
|
||||
|
||||
This [WebdriverIO] guide expects you to have already gone through the [example Application setup] in order to follow
|
||||
step-by-step. The general information may still be useful otherwise.
|
||||
</Alert>
|
||||
|
||||
This WebDriver testing example will use [WebdriverIO] and its testing suite. It is expected to already have Node.js
|
||||
installed, along with `npm` or `yarn` although the [finished example project] uses `yarn`.
|
||||
|
||||
## Create a Directory for the Tests
|
||||
|
||||
Let's start off by creating a space in our project to write these tests. We are going to be using a nested directory for
|
||||
this example project as we will later also go over other frameworks, but typically you will only need to use one. Create
|
||||
the directory we will use with `mkdir -p webdriver/webdriverio`. The rest of this guide will assume you are inside the
|
||||
`webdriver/webdriverio` directory.
|
||||
|
||||
## Initializing a WebdriverIO Project
|
||||
|
||||
We will be using a pre-existing `package.json` to bootstrap this test suite because we have already chosen specific
|
||||
[WebdriverIO] config options and want to showcase a simple working solution. The bottom of this section has a collapsed
|
||||
guide on how to set it up from scratch.
|
||||
|
||||
`package.json`:
|
||||
```json
|
||||
{
|
||||
"name": "webdriverio",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"test": "wdio run wdio.conf.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@wdio/cli": "^7.9.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@wdio/local-runner": "^7.9.1",
|
||||
"@wdio/mocha-framework": "^7.9.1",
|
||||
"@wdio/spec-reporter": "^7.9.0"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
We have a script which runs a [WebdriverIO] config as a test suite exposed as the `test` command. We also have various
|
||||
dependencies that were added by the `@wdio/cli` command when we first set it up. In short, these dependencies are for
|
||||
the most simple setup using a local WebDriver runner, [Mocha] as the test framework, and a simple Spec Reporter.
|
||||
|
||||
<details><summary>Click me if you want to see how to set a project up from scratch</summary>
|
||||
|
||||
The CLI is interactive, and you may choose the tools to work with yourself. Note that you will likely diverge from
|
||||
the rest of the guide, and need to set up the differences yourself.
|
||||
|
||||
Let's add the [WebdriverIO] CLI to this npm project.
|
||||
|
||||
<Tabs groupId="package-manager"
|
||||
defaultValue="yarn"
|
||||
values={[
|
||||
{label: 'npm', value: 'npm'}, {label: 'Yarn', value: 'yarn'},
|
||||
]}>
|
||||
<TabItem value="npm">
|
||||
|
||||
```sh
|
||||
npm install @wdio/cli
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
|
||||
<TabItem value="yarn">
|
||||
|
||||
```sh
|
||||
yarn add @wdio/cli
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
To then run the interactive config command to set up a [WebdriverIO] test suite, you can then run:
|
||||
|
||||
<Tabs groupId="package-manager"
|
||||
defaultValue="yarn"
|
||||
values={[
|
||||
{label: 'npm', value: 'npm'}, {label: 'Yarn', value: 'yarn'},
|
||||
]}>
|
||||
<TabItem value="npm">
|
||||
|
||||
```sh
|
||||
npx wdio config
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
|
||||
<TabItem value="yarn">
|
||||
|
||||
```sh
|
||||
yarn wdio config
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
</details>
|
||||
|
||||
## Config
|
||||
|
||||
You may have noticed that the `test` script in our `package.json` mentions a file `wdio.conf.js`. That's the [WebdriverIO]
|
||||
config file which controls most aspects of our testing suite.
|
||||
|
||||
`wdio.conf.js`:
|
||||
```js
|
||||
const os = require("os");
|
||||
const path = require("path");
|
||||
const { spawn, spawnSync } = require("child_process");
|
||||
|
||||
// keep track of the `tauri-driver` child process
|
||||
let tauriDriver;
|
||||
|
||||
exports.config = {
|
||||
specs: ["./test/specs/**/*.js"],
|
||||
maxInstances: 1,
|
||||
capabilities: [
|
||||
{
|
||||
maxInstances: 1,
|
||||
"tauri:options": {
|
||||
application: "../../target/release/hello-tauri-webdriver",
|
||||
},
|
||||
},
|
||||
],
|
||||
reporters: ["spec"],
|
||||
framework: "mocha",
|
||||
mochaOpts: {
|
||||
ui: "bdd",
|
||||
timeout: 60000,
|
||||
},
|
||||
|
||||
// ensure the rust project is built since we expect this binary to exist for the webdriver sessions
|
||||
onPrepare: () => spawnSync("cargo", ["build", "--release"]),
|
||||
|
||||
// ensure we are running `tauri-driver` before the session starts so that we can proxy the webdriver requests
|
||||
beforeSession: () =>
|
||||
(tauriDriver = spawn(
|
||||
path.resolve(os.homedir(), ".cargo", "bin", "tauri-driver"),
|
||||
[],
|
||||
{ stdio: [null, process.stdout, process.stderr] }
|
||||
)),
|
||||
|
||||
// clean up the `tauri-driver` process we spawned at the start of the session
|
||||
afterSession: () => tauriDriver.kill(),
|
||||
};
|
||||
```
|
||||
|
||||
If you are interested in the properties on `exports.config` object, then I [suggest reading the documentation] for it.
|
||||
For non-WDIO specific items, there are comments explaining why we are running commands in `onPrepare`, `beforeSession`,
|
||||
and `afterSession`. We also have our specs set to `"./test/specs/**/*.js"`, so let's create a spec now.
|
||||
|
||||
## Spec
|
||||
|
||||
A spec contains the code that is testing your actual application. The test runner will load these specs and automatically
|
||||
run them as it sees fit. Let's create our spec now in the directory we specified.
|
||||
|
||||
`test/specs/example.e2e.js`:
|
||||
```js
|
||||
// calculates the luma from a hex color `#abcdef`
|
||||
function luma(hex) {
|
||||
if (hex.startsWith("#")) {
|
||||
hex = hex.substring(1);
|
||||
}
|
||||
|
||||
const rgb = parseInt(hex, 16);
|
||||
const r = (rgb >> 16) & 0xff;
|
||||
const g = (rgb >> 8) & 0xff;
|
||||
const b = (rgb >> 0) & 0xff;
|
||||
return 0.2126 * r + 0.7152 * g + 0.0722 * b;
|
||||
}
|
||||
|
||||
describe("Hello Tauri", () => {
|
||||
it("should be cordial", async () => {
|
||||
const header = await $("body > h1");
|
||||
const text = await header.getText();
|
||||
expect(text).toMatch(/^[hH]ello/);
|
||||
});
|
||||
|
||||
it("should be excited", async () => {
|
||||
const header = await $("body > h1");
|
||||
const text = await header.getText();
|
||||
expect(text).toMatch(/!$/);
|
||||
});
|
||||
|
||||
it("should be easy on the eyes", async () => {
|
||||
const body = await $("body");
|
||||
const backgroundColor = await body.getCSSProperty("background-color");
|
||||
expect(luma(backgroundColor.parsed.hex)).toBeLessThan(100);
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
The `luma` function on top is just a helper function for one of our tests and is not related to the actual testing of
|
||||
the application. If you are familiar with other testing frameworks, you may notice similar functions being exposed that
|
||||
are used such as `describe`, `it`, and `expect`. The other APIs, such as items like `$` and the methods it exposes is
|
||||
covered by the [WebdriverIO API docs](https://webdriver.io/docs/api).
|
||||
|
||||
## Running the Test Suite
|
||||
|
||||
Now that we are all set up with a config and a spec, let's run it!
|
||||
|
||||
<Tabs groupId="package-manager"
|
||||
defaultValue="yarn"
|
||||
values={[
|
||||
{label: 'npm', value: 'npm'}, {label: 'Yarn', value: 'yarn'},
|
||||
]}>
|
||||
<TabItem value="npm">
|
||||
|
||||
```sh
|
||||
npm test
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
|
||||
<TabItem value="yarn">
|
||||
|
||||
```sh
|
||||
yarn test
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
We should see output the following output:
|
||||
|
||||
```text
|
||||
➜ webdriverio git:(main) ✗ yarn test
|
||||
yarn run v1.22.11
|
||||
$ wdio run wdio.conf.js
|
||||
|
||||
Execution of 1 workers started at 2021-08-17T08:06:10.279Z
|
||||
|
||||
[0-0] RUNNING in undefined - /test/specs/example.e2e.js
|
||||
[0-0] PASSED in undefined - /test/specs/example.e2e.js
|
||||
|
||||
"spec" Reporter:
|
||||
------------------------------------------------------------------
|
||||
[wry 0.12.1 linux #0-0] Running: wry (v0.12.1) on linux
|
||||
[wry 0.12.1 linux #0-0] Session ID: 81e0107b-4d38-4eed-9b10-ee80ca47bb83
|
||||
[wry 0.12.1 linux #0-0]
|
||||
[wry 0.12.1 linux #0-0] » /test/specs/example.e2e.js
|
||||
[wry 0.12.1 linux #0-0] Hello Tauri
|
||||
[wry 0.12.1 linux #0-0] ✓ should be cordial
|
||||
[wry 0.12.1 linux #0-0] ✓ should be excited
|
||||
[wry 0.12.1 linux #0-0] ✓ should be easy on the eyes
|
||||
[wry 0.12.1 linux #0-0]
|
||||
[wry 0.12.1 linux #0-0] 3 passing (244ms)
|
||||
|
||||
|
||||
Spec Files: 1 passed, 1 total (100% completed) in 00:00:01
|
||||
|
||||
Done in 1.98s.
|
||||
```
|
||||
|
||||
We see the Spec Reporter tell us that all 3 tests from the `test/specs/example.e2e.js` file, along with the final report
|
||||
`Spec Files: 1 passed, 1 total (100% completed) in 00:00:01`.
|
||||
|
||||
Using the [WebdriverIO] test suite, we just easily enabled e2e testing for our Tauri application from just a few lines
|
||||
of configuration and a single command to run it! Even better, we didn't have to modify the application at all.
|
||||
|
||||
|
||||
[WebdriverIO]: https://webdriver.io/
|
||||
[finished example project]: https://github.com/chippers/hello_tauri
|
||||
[example Application setup]: setup
|
||||
[Mocha]: https://mochajs.org/
|
||||
[suggest reading the documentation]: (https://webdriver.io/docs/configurationfile)
|
56
docs/usage/guides/webdriver/introduction.md
Normal file
56
docs/usage/guides/webdriver/introduction.md
Normal file
@ -0,0 +1,56 @@
|
||||
---
|
||||
title: Introduction
|
||||
---
|
||||
import Alert from '@theme/Alert'
|
||||
|
||||
<Alert title="Currently in pre-alpha" type="info" icon="info-alt">
|
||||
|
||||
Webdriver support for Tauri is still in pre-alpha. Tooling that is dedicated to it such as [tauri-driver] is still in
|
||||
active development and may change as necessary over time. Additionally, only Windows and Linux are currently supported.
|
||||
</Alert>
|
||||
|
||||
[WebDriver] is a standardized interface to interact with web documents that is primarily intended for automated testing.
|
||||
Tauri supports the [WebDriver] interface by leveraging the native platform's [WebDriver] server underneath a
|
||||
cross-platform wrapper [`tauri-driver`].
|
||||
|
||||
## System Dependencies
|
||||
|
||||
Install the latest [`tauri-driver`] or update an existing installation by running:
|
||||
|
||||
```sh
|
||||
cargo install tauri-driver
|
||||
```
|
||||
|
||||
Because we currently utilize the platform's native [WebDriver] server, there are some requirements for running
|
||||
[`tauri-driver`] on supported platforms. Platform support is currently limited to Linux and Windows.
|
||||
|
||||
### Linux
|
||||
|
||||
We use `WebKitWebDriver` on linux platforms. Check if this binary exists already (command `which WebKitWebDriver`) as
|
||||
some distributions bundle it with the regular webkit package. Other platforms may have a separate package for them such
|
||||
as `webkit2gtk-driver` on Debian based distributions.
|
||||
|
||||
### Windows
|
||||
|
||||
Make sure to grab the version of [Microsoft Edge Driver] that matches your Windows' Edge version that the application is
|
||||
being built and tested on. On up-to-date Window installs, this should almost always be the latest stable version. If the
|
||||
two versions do not match, you may experience your WebDriver testing suite hanging while trying to connect.
|
||||
|
||||
The download contains a binary called `msedgedriver.exe`. [`tauri-driver`] looks for that binary in the `$PATH` so make
|
||||
sure it's either available on the path or use the `--native-driver` option on [`tauri-driver`]. On Windows CI machines,
|
||||
you may want to download this automatically as part of the CI setup process to ensure the Edge and Edge Driver versions
|
||||
stay in sync. A guide on how to do this may be added at a later date.
|
||||
|
||||
## Example Application
|
||||
|
||||
The [next section](example/setup) of the guide will show step-by-step how to create a minimal example application that
|
||||
is tested with WebDriver.
|
||||
|
||||
If you prefer to just see the result of the guide and look over a finished minimal codebase that utilizes it then you
|
||||
can look at https://github.com/chippers/hello_tauri. That example also comes with a CI script to test with GitHub
|
||||
actions, but you may still be interested in the [WebDriver CI](ci) guide as it explains the concept a bit more.
|
||||
|
||||
[WebDriver]: https://www.w3.org/TR/webdriver/
|
||||
[`tauri-driver`]: https://crates.io/crates/tauri-driver
|
||||
[tauri-driver]: https://crates.io/crates/tauri-driver
|
||||
[Microsoft Edge Driver]: https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/
|
@ -13,26 +13,18 @@ You can configure the ports used with arguments when starting the binary:
|
||||
* `--native-port` (default: `4445`)
|
||||
|
||||
Supported platforms:
|
||||
* **[In Progress]** Linux w/ `WebKitWebDriver`
|
||||
* **[In Progress]** Windows w/ [Microsoft Edge Driver]
|
||||
* **[pre-alpha]** Linux w/ `WebKitWebDriver`
|
||||
* **[pre-alpha]** Windows w/ [Microsoft Edge Driver]
|
||||
* **[Todo]** macOS w/ [Appium Mac2 Driver] (probably)
|
||||
|
||||
_note: the (probably) items haven't been proof-of-concept'd yet, and if it is
|
||||
not possible to use the listed native webdriver, then a custom implementation
|
||||
will be used that wraps around [wry]._
|
||||
|
||||
|
||||
## Trying it out
|
||||
|
||||
**Until this branch is merged into Tauri `dev`, this code works for pure [wry]
|
||||
applications only.**
|
||||
|
||||
Currently, this uses a branch on [wry] `feat/webdriver`. The support for
|
||||
automated actions goes all the way down to wry with no real layer for just
|
||||
Tauri yet. For Windows, the [wry] branch only supports the `win32` backend
|
||||
and not `winrt`, unless you are okay with the webview not being closable by
|
||||
the webdriver.
|
||||
|
||||
Check out the documentation at https://tauri.studio/en/docs/usage/guides/webdriver/ci to build a small example
|
||||
application that had WebDriver tests.
|
||||
|
||||
[WebDriver Intermediary Node]: https://www.w3.org/TR/webdriver/#dfn-intermediary-nodes
|
||||
[WebDriver Remote Ends]: https://www.w3.org/TR/webdriver/#dfn-remote-ends
|
||||
|
Loading…
Reference in New Issue
Block a user