snapshot of https://github.com/tauri-apps/tauri.git (dev, 2026-09-23; blobs > 131072B omitted)
Some checks failed
Audit / audit-js (push) Failing after 0s
bench / bench (map[os:ubuntu-latest runner:xvfb-run --auto-servernum target:x86_64-unknown-linux-gnu], nightly) (push) Failing after 0s
covector version or publish / run-integration-tests (ubuntu-latest) (push) Failing after 0s
Audit / audit-rust (push) Failing after 0s
test `@tauri-apps/cli` / test (ubuntu-latest) (push) Failing after 0s
test `tauri-cli` / test (map[os:ubuntu-latest target:x86_64-unknown-linux-gnu]) (push) Failing after 0s
test core / test (map[args:--all-features key:all], map[cargo:cargo command:test os:ubuntu-latest target:x86_64-unknown-linux-gnu toolchain:1.90]) (push) Failing after 0s
test core / test (map[args:--no-default-features key:no-default], map[cargo:cargo command:test os:ubuntu-latest target:x86_64-unknown-linux-gnu toolchain:1.90]) (push) Failing after 0s
test core / test (map[args:--no-default-features key:no-default], map[cargo:cross command:build os:ubuntu-latest target:aarch64-linux-android toolchain:1.90]) (push) Failing after 0s
deploy schema worker / deploy (push) Failing after 0s
lint rust / clippy (map[cargo:cargo include: os:ubuntu-latest target:x86_64-unknown-linux-gnu]) (push) Failing after 0s
lint rust / clippy (map[cargo:cross include:--package api os:ubuntu-latest target:aarch64-linux-android]) (push) Failing after 0s
supply chain health status / check rust dependencies with cargo vet (push) Failing after 0s
test `@tauri-apps/api` e2e (mobile) / android (push) Failing after 0s
test `@tauri-apps/api` e2e / test (map[name:Linux os:ubuntu-latest]) (push) Failing after 0s
test core / test (map[args:--all-features key:all], map[cargo:cross command:build os:ubuntu-latest target:aarch64-linux-android toolchain:1.90]) (push) Failing after 0s
Udeps / changes (push) Failing after 0s
Udeps / setup (push) Has been skipped
Udeps / udeps (push) Has been skipped
bench / bench (map[os:macos-latest runner: target:aarch64-apple-darwin], nightly) (push) Has been cancelled
bench / bench (map[os:windows-latest runner: target:x86_64-pc-windows-msvc], nightly) (push) Has been cancelled
covector version or publish / run-integration-tests (macos-latest) (push) Has been cancelled
covector version or publish / run-integration-tests (windows-latest) (push) Has been cancelled
covector version or publish / version-or-publish (push) Has been cancelled
test `@tauri-apps/cli` / test (macos-latest) (push) Has been cancelled
test `tauri-cli` / test (map[args:--no-default-features --features native-tls-vendored os:windows-latest restore-only:true target:aarch64-pc-windows-msvc]) (push) Has been cancelled
test `tauri-cli` / test (map[os:macos-latest target:x86_64-apple-darwin]) (push) Has been cancelled
test `tauri-cli` / test (map[os:windows-latest target:x86_64-pc-windows-msvc]) (push) Has been cancelled
test core / test (map[args:--all-features key:all], map[cargo:cargo command:build os:macos-latest target:aarch64-apple-ios toolchain:1.90]) (push) Has been cancelled
test core / test (map[args:--all-features key:all], map[cargo:cargo command:test os:macos-14 target:aarch64-apple-darwin toolchain:1.90]) (push) Has been cancelled
lint rust / clippy (map[cargo:cargo include: os:macos-latest target:aarch64-apple-darwin]) (push) Has been cancelled
lint rust / clippy (map[cargo:cargo include: os:windows-latest target:x86_64-pc-windows-msvc]) (push) Has been cancelled
lint rust / clippy (map[cargo:cargo include:--package api os:macos-latest target:aarch64-apple-ios]) (push) Has been cancelled
test `@tauri-apps/api` e2e (mobile) / ios (push) Has been cancelled
test `@tauri-apps/api` e2e / test (map[name:Windows os:windows-latest]) (push) Has been cancelled
test `@tauri-apps/api` e2e / test (map[name:macOS os:macos-latest]) (push) Has been cancelled
test `@tauri-apps/cli` / test (windows-latest) (push) Has been cancelled
test core / test (map[args:--all-features key:all], map[cargo:cargo command:test os:windows-latest target:x86_64-pc-windows-msvc toolchain:1.90]) (push) Has been cancelled
test core / test (map[args:--no-default-features key:no-default], map[cargo:cargo command:build os:macos-latest target:aarch64-apple-ios toolchain:1.90]) (push) Has been cancelled
test core / test (map[args:--no-default-features key:no-default], map[cargo:cargo command:test os:macos-14 target:aarch64-apple-darwin toolchain:1.90]) (push) Has been cancelled
test core / test (map[args:--no-default-features key:no-default], map[cargo:cargo command:test os:windows-latest target:x86_64-pc-windows-msvc toolchain:1.90]) (push) Has been cancelled
Some checks failed
Audit / audit-js (push) Failing after 0s
bench / bench (map[os:ubuntu-latest runner:xvfb-run --auto-servernum target:x86_64-unknown-linux-gnu], nightly) (push) Failing after 0s
covector version or publish / run-integration-tests (ubuntu-latest) (push) Failing after 0s
Audit / audit-rust (push) Failing after 0s
test `@tauri-apps/cli` / test (ubuntu-latest) (push) Failing after 0s
test `tauri-cli` / test (map[os:ubuntu-latest target:x86_64-unknown-linux-gnu]) (push) Failing after 0s
test core / test (map[args:--all-features key:all], map[cargo:cargo command:test os:ubuntu-latest target:x86_64-unknown-linux-gnu toolchain:1.90]) (push) Failing after 0s
test core / test (map[args:--no-default-features key:no-default], map[cargo:cargo command:test os:ubuntu-latest target:x86_64-unknown-linux-gnu toolchain:1.90]) (push) Failing after 0s
test core / test (map[args:--no-default-features key:no-default], map[cargo:cross command:build os:ubuntu-latest target:aarch64-linux-android toolchain:1.90]) (push) Failing after 0s
deploy schema worker / deploy (push) Failing after 0s
lint rust / clippy (map[cargo:cargo include: os:ubuntu-latest target:x86_64-unknown-linux-gnu]) (push) Failing after 0s
lint rust / clippy (map[cargo:cross include:--package api os:ubuntu-latest target:aarch64-linux-android]) (push) Failing after 0s
supply chain health status / check rust dependencies with cargo vet (push) Failing after 0s
test `@tauri-apps/api` e2e (mobile) / android (push) Failing after 0s
test `@tauri-apps/api` e2e / test (map[name:Linux os:ubuntu-latest]) (push) Failing after 0s
test core / test (map[args:--all-features key:all], map[cargo:cross command:build os:ubuntu-latest target:aarch64-linux-android toolchain:1.90]) (push) Failing after 0s
Udeps / changes (push) Failing after 0s
Udeps / setup (push) Has been skipped
Udeps / udeps (push) Has been skipped
bench / bench (map[os:macos-latest runner: target:aarch64-apple-darwin], nightly) (push) Has been cancelled
bench / bench (map[os:windows-latest runner: target:x86_64-pc-windows-msvc], nightly) (push) Has been cancelled
covector version or publish / run-integration-tests (macos-latest) (push) Has been cancelled
covector version or publish / run-integration-tests (windows-latest) (push) Has been cancelled
covector version or publish / version-or-publish (push) Has been cancelled
test `@tauri-apps/cli` / test (macos-latest) (push) Has been cancelled
test `tauri-cli` / test (map[args:--no-default-features --features native-tls-vendored os:windows-latest restore-only:true target:aarch64-pc-windows-msvc]) (push) Has been cancelled
test `tauri-cli` / test (map[os:macos-latest target:x86_64-apple-darwin]) (push) Has been cancelled
test `tauri-cli` / test (map[os:windows-latest target:x86_64-pc-windows-msvc]) (push) Has been cancelled
test core / test (map[args:--all-features key:all], map[cargo:cargo command:build os:macos-latest target:aarch64-apple-ios toolchain:1.90]) (push) Has been cancelled
test core / test (map[args:--all-features key:all], map[cargo:cargo command:test os:macos-14 target:aarch64-apple-darwin toolchain:1.90]) (push) Has been cancelled
lint rust / clippy (map[cargo:cargo include: os:macos-latest target:aarch64-apple-darwin]) (push) Has been cancelled
lint rust / clippy (map[cargo:cargo include: os:windows-latest target:x86_64-pc-windows-msvc]) (push) Has been cancelled
lint rust / clippy (map[cargo:cargo include:--package api os:macos-latest target:aarch64-apple-ios]) (push) Has been cancelled
test `@tauri-apps/api` e2e (mobile) / ios (push) Has been cancelled
test `@tauri-apps/api` e2e / test (map[name:Windows os:windows-latest]) (push) Has been cancelled
test `@tauri-apps/api` e2e / test (map[name:macOS os:macos-latest]) (push) Has been cancelled
test `@tauri-apps/cli` / test (windows-latest) (push) Has been cancelled
test core / test (map[args:--all-features key:all], map[cargo:cargo command:test os:windows-latest target:x86_64-pc-windows-msvc toolchain:1.90]) (push) Has been cancelled
test core / test (map[args:--no-default-features key:no-default], map[cargo:cargo command:build os:macos-latest target:aarch64-apple-ios toolchain:1.90]) (push) Has been cancelled
test core / test (map[args:--no-default-features key:no-default], map[cargo:cargo command:test os:macos-14 target:aarch64-apple-darwin toolchain:1.90]) (push) Has been cancelled
test core / test (map[args:--no-default-features key:no-default], map[cargo:cargo command:test os:windows-latest target:x86_64-pc-windows-msvc toolchain:1.90]) (push) Has been cancelled
This commit is contained in:
91
crates/tauri-driver/CHANGELOG.md
Normal file
91
crates/tauri-driver/CHANGELOG.md
Normal file
@@ -0,0 +1,91 @@
|
||||
# Changelog
|
||||
|
||||
## \[2.0.6]
|
||||
|
||||
### What's Changed
|
||||
|
||||
- [`3057eda06`](https://www.github.com/tauri-apps/tauri/commit/3057eda067b87761644209adeec077f232585c5d) ([#15324](https://www.github.com/tauri-apps/tauri/pull/15324)) Support `eq-separator` for `tauri-driver`.
|
||||
|
||||
## \[2.0.5]
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- [`06f911aaf`](https://www.github.com/tauri-apps/tauri/commit/06f911aaff495121f08ebc77d9d1b41382298a1f) ([#14871](https://www.github.com/tauri-apps/tauri/pull/14871) by [@goosewobbler](https://www.github.com/tauri-apps/tauri/../../goosewobbler)) Prevent native WebDriver stdout from polluting tauri-driver's stdout used by test frameworks.
|
||||
|
||||
## \[2.0.4]
|
||||
|
||||
### Enhancements
|
||||
|
||||
- [`0cf2d9933`](https://www.github.com/tauri-apps/tauri/commit/0cf2d9933f20375349f9f307b4dd7049690030d9) ([#13238](https://www.github.com/tauri-apps/tauri/pull/13238)) Automatically append the `.exe` extension on the application path in `tauri:options`.
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- [`577c7ffc4`](https://www.github.com/tauri-apps/tauri/commit/577c7ffc45ef005403cdf698e595614038c7d1e1) ([#10108](https://www.github.com/tauri-apps/tauri/pull/10108)) Ensure the webdriver process is closed when the tauri-driver process finishes.
|
||||
|
||||
## \[2.0.3]
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- [`fb294af8e`](https://www.github.com/tauri-apps/tauri/commit/fb294af8e3717d547029f3bbf9323318e0d9861a) ([#12383](https://www.github.com/tauri-apps/tauri/pull/12383) by [@bicarlsen](https://www.github.com/tauri-apps/tauri/../../bicarlsen)) Parse ms:edgeOptions separately to prevent `invalid argument` errors.
|
||||
|
||||
## \[2.0.2]
|
||||
|
||||
### Enhancements
|
||||
|
||||
- [`70f96e322`](https://www.github.com/tauri-apps/tauri/commit/70f96e3222871a1931a18d6093d7efcbc59e7fee) ([#12240](https://www.github.com/tauri-apps/tauri/pull/12240) by [@getong](https://www.github.com/tauri-apps/tauri/../../getong)) Updated `hyper` to version 1. This won't affect the user facing API.
|
||||
|
||||
## \[2.0.1]
|
||||
|
||||
### What's Changed
|
||||
|
||||
- [`0ab2b3306`](https://www.github.com/tauri-apps/tauri/commit/0ab2b330644b6419f6cee1d5377bfb5cdda2ccf9) ([#11205](https://www.github.com/tauri-apps/tauri/pull/11205) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Downgrade MSRV to 1.77.2 to support Windows 7.
|
||||
|
||||
## \[2.0.0]
|
||||
|
||||
### What's Changed
|
||||
|
||||
- [`382ed482b`](https://www.github.com/tauri-apps/tauri/commit/382ed482bd08157c39e62f9a0aaad8802f1092cb) Bump MSRV to 1.78.
|
||||
- [`637285790`](https://www.github.com/tauri-apps/tauri/commit/6372857905ae9c0aedb7f482ddf6cf9f9836c9f2) Promote to v2 stable!
|
||||
|
||||
## \[0.1.5]
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- [`5f64ed2b7`](https://www.github.com/tauri-apps/tauri/commit/5f64ed2b78201b7e379b6234f7a799d9695b11d7) ([#10738](https://www.github.com/tauri-apps/tauri/pull/10738) by [@chippers](https://www.github.com/tauri-apps/tauri/../../chippers)) support both 1.x and 2.x automation env vars in `tauri-driver`
|
||||
|
||||
### What's Changed
|
||||
|
||||
- [`f4d5241b3`](https://www.github.com/tauri-apps/tauri/commit/f4d5241b377d0f7a1b58100ee19f7843384634ac) ([#10731](https://www.github.com/tauri-apps/tauri/pull/10731) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Update documentation icon path.
|
||||
|
||||
## \[0.1.4]
|
||||
|
||||
### New Features
|
||||
|
||||
- [`435d7513`](https://www.github.com/tauri-apps/tauri/commit/435d7513e45eab8b512e9a7e695a1adef8a98a46)([#8609](https://www.github.com/tauri-apps/tauri/pull/8609)) Added `webviewOptions` object to the `tauri:options` capability to configure the [Edge webview options](https://learn.microsoft.com/en-us/microsoft-edge/webdriver-chromium/capabilities-edge-options#webviewoptions-object) on Windows.
|
||||
|
||||
## \[0.1.3]
|
||||
|
||||
### What's Changed
|
||||
|
||||
- [`9edebbba`](https://www.github.com/tauri-apps/tauri/commit/9edebbba4ec472772b2f6307232e8d256f62c8ba)([#7475](https://www.github.com/tauri-apps/tauri/pull/7475)) Update locked dependencies to fix a Windows build issue when using them with a recent Rust compiler.
|
||||
- [`9edebbba`](https://www.github.com/tauri-apps/tauri/commit/9edebbba4ec472772b2f6307232e8d256f62c8ba)([#7475](https://www.github.com/tauri-apps/tauri/pull/7475)) Bump minimum Rust version to `1.60` to be in line with the rest of the Tauri project.
|
||||
|
||||
## \[0.1.2]
|
||||
|
||||
- Expose `native-host` option in tauri-driver and set default to `127.0.0.1`.
|
||||
- [cd9dfc7b](https://www.github.com/tauri-apps/tauri/commit/cd9dfc7b9a3fe0e04e40d9b0f9be674aefd0d725) fix(driver): expose native-host option and set default to 127.0.0.1 ([#3816](https://www.github.com/tauri-apps/tauri/pull/3816)) on 2022-03-31
|
||||
|
||||
## \[0.1.1]
|
||||
|
||||
- The minimum Rust version is now `1.56`.
|
||||
- [a9dfc015](https://www.github.com/tauri-apps/tauri/commit/a9dfc015505afe91281c2027954ffcc588b1a59c) feat: update to edition 2021 and set minimum rust to 1.56 ([#2789](https://www.github.com/tauri-apps/tauri/pull/2789)) on 2021-10-22
|
||||
- Add `args` field (array of application CLI arguments) to the `tauri:options` capabilities.
|
||||
- [d0970e34](https://www.github.com/tauri-apps/tauri/commit/d0970e3499297a6c102a36f2dc479d3d657bfaf3) feat(driver): add `args` to `tauri:options` ([#3154](https://www.github.com/tauri-apps/tauri/pull/3154)) on 2022-01-03
|
||||
|
||||
## \[0.1.0]
|
||||
|
||||
- Initial release including Linux and Windows support.
|
||||
- [be76fb1d](https://www.github.com/tauri-apps/tauri/commit/be76fb1dfe73a1605cc2ad246418579f4c2e1999) WebDriver support ([#1972](https://www.github.com/tauri-apps/tauri/pull/1972)) on 2021-06-23
|
||||
- [c22e5a7c](https://www.github.com/tauri-apps/tauri/commit/c22e5a7c2ebede41657973b80eff6b68106817fc) fix(covector): keep `tauri-driver` version as alpha on 2021-06-23
|
||||
- [b4426eda](https://www.github.com/tauri-apps/tauri/commit/b4426eda9e64fcdd25a2d72e548b8b0fbfa09619) Revert "WebDriver support ([#1972](https://www.github.com/tauri-apps/tauri/pull/1972))" on 2021-06-23
|
||||
- [4b2aa356](https://www.github.com/tauri-apps/tauri/commit/4b2aa35684632ed2afd7dec4ad848df5704868e4) Add back WebDriver support ([#2324](https://www.github.com/tauri-apps/tauri/pull/2324)) on 2021-08-01
|
||||
40
crates/tauri-driver/Cargo.toml
Normal file
40
crates/tauri-driver/Cargo.toml
Normal file
@@ -0,0 +1,40 @@
|
||||
[package]
|
||||
name = "tauri-driver"
|
||||
version = "2.0.6"
|
||||
authors = ["Tauri Programme within The Commons Conservancy"]
|
||||
categories = ["gui", "web-programming"]
|
||||
license = "Apache-2.0 OR MIT"
|
||||
homepage = "https://tauri.app"
|
||||
repository = "https://github.com/tauri-apps/tauri"
|
||||
description = "Webdriver server for Tauri applications"
|
||||
edition = "2024"
|
||||
rust-version = "1.90"
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1"
|
||||
futures = "0.3"
|
||||
futures-util = "0.3"
|
||||
http-body-util = "0.1"
|
||||
hyper = { version = "1", features = ["client", "http1", "server"] }
|
||||
hyper-util = { version = "0.1", features = [
|
||||
"client",
|
||||
"client-legacy",
|
||||
"http1",
|
||||
"server",
|
||||
"tokio",
|
||||
] }
|
||||
pico-args = { version = "0.5", features = ["eq-separator"] }
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
tokio = { version = "1", features = ["macros"] }
|
||||
which = "8"
|
||||
|
||||
[target."cfg(unix)".dependencies]
|
||||
signal-hook = "0.4"
|
||||
signal-hook-tokio = { version = "0.4", features = ["futures-v0_3"] }
|
||||
|
||||
[target."cfg(windows)".dependencies]
|
||||
win32job = "2"
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
1
crates/tauri-driver/LICENSE-APACHE-2.0
Normal file
1
crates/tauri-driver/LICENSE-APACHE-2.0
Normal file
@@ -0,0 +1 @@
|
||||
../../LICENSE-APACHE-2.0
|
||||
1
crates/tauri-driver/LICENSE-MIT
Normal file
1
crates/tauri-driver/LICENSE-MIT
Normal file
@@ -0,0 +1 @@
|
||||
../../LICENSE-MIT
|
||||
1
crates/tauri-driver/LICENSE.spdx
Normal file
1
crates/tauri-driver/LICENSE.spdx
Normal file
@@ -0,0 +1 @@
|
||||
../../LICENSE.spdx
|
||||
44
crates/tauri-driver/README.md
Normal file
44
crates/tauri-driver/README.md
Normal file
@@ -0,0 +1,44 @@
|
||||
# `tauri-driver` _(pre-alpha)_
|
||||
|
||||
Cross-platform WebDriver server for Tauri applications.
|
||||
|
||||
This is a [WebDriver Intermediary Node] that wraps the native WebDriver server
|
||||
for platforms that [Tauri] supports. Your WebDriver client will connect to the
|
||||
running `tauri-driver` server, and `tauri-driver` will handle starting the
|
||||
native WebDriver server for you behind the scenes. It requires two separate
|
||||
ports to be used since two distinct [WebDriver Remote Ends] run.
|
||||
|
||||
You can configure the ports used with arguments when starting the binary:
|
||||
|
||||
- `--port` (default: `4444`)
|
||||
- `--native-port` (default: `4445`)
|
||||
|
||||
Supported platforms:
|
||||
|
||||
- Linux via `WebKitWebDriver`
|
||||
- Windows via [Microsoft Edge Driver]
|
||||
- **[Todo]** macOS via [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]._
|
||||
|
||||
## Installation
|
||||
|
||||
You can install tauri-driver using Cargo:
|
||||
|
||||
```sh
|
||||
cargo install tauri-driver --locked
|
||||
```
|
||||
|
||||
## Trying it out
|
||||
|
||||
Check out the documentation at https://tauri.app/develop/tests/webdriver/,
|
||||
including a small example application with 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
|
||||
[Microsoft Edge Driver]: https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/
|
||||
[Appium Mac2 Driver]: https://github.com/appium/appium-mac2-driver
|
||||
[wry]: https://github.com/tauri-apps/wry
|
||||
[Tauri]: https://github.com/tauri-apps/tauri
|
||||
63
crates/tauri-driver/src/cli.rs
Normal file
63
crates/tauri-driver/src/cli.rs
Normal file
@@ -0,0 +1,63 @@
|
||||
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
const HELP: &str = "\
|
||||
USAGE: tauri-driver [FLAGS] [OPTIONS]
|
||||
|
||||
FLAGS:
|
||||
-h, --help Prints help information
|
||||
|
||||
OPTIONS:
|
||||
--port NUMBER Sets the tauri-driver intermediary port
|
||||
--native-port NUMBER Sets the port of the underlying WebDriver
|
||||
--native-host HOST Sets the host of the underlying WebDriver (Linux only)
|
||||
--native-driver PATH Sets the path to the native WebDriver binary
|
||||
";
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Args {
|
||||
pub port: u16,
|
||||
pub native_port: u16,
|
||||
pub native_host: String,
|
||||
pub native_driver: Option<PathBuf>,
|
||||
}
|
||||
|
||||
impl From<pico_args::Arguments> for Args {
|
||||
fn from(mut args: pico_args::Arguments) -> Self {
|
||||
// if the user wanted help, we don't care about parsing the rest of the args
|
||||
if args.contains(["-h", "--help"]) {
|
||||
println!("{HELP}");
|
||||
std::process::exit(0);
|
||||
}
|
||||
|
||||
let native_driver = match args.opt_value_from_str("--native-driver") {
|
||||
Ok(native_driver) => native_driver,
|
||||
Err(e) => {
|
||||
eprintln!("Error while parsing option --native-driver: {e}");
|
||||
std::process::exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
let parsed = Args {
|
||||
port: args.value_from_str("--port").unwrap_or(4444),
|
||||
native_port: args.value_from_str("--native-port").unwrap_or(4445),
|
||||
native_host: args
|
||||
.value_from_str("--native-host")
|
||||
.unwrap_or(String::from("127.0.0.1")),
|
||||
native_driver,
|
||||
};
|
||||
|
||||
// be strict about accepting args, error for anything extraneous
|
||||
let rest = args.finish();
|
||||
if !rest.is_empty() {
|
||||
eprintln!("Error: unused arguments left: {rest:?}");
|
||||
eprintln!("{HELP}");
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
||||
parsed
|
||||
}
|
||||
}
|
||||
52
crates/tauri-driver/src/main.rs
Normal file
52
crates/tauri-driver/src/main.rs
Normal file
@@ -0,0 +1,52 @@
|
||||
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
//! Cross-platform WebDriver server for Tauri applications.
|
||||
//!
|
||||
//! This is a [WebDriver Intermediary Node](https://www.w3.org/TR/webdriver/#dfn-intermediary-nodes) that wraps the native WebDriver server for platforms that [Tauri](https://github.com/tauri-apps/tauri) supports. Your WebDriver client will connect to the running `tauri-driver` server, and `tauri-driver` will handle starting the native WebDriver server for you behind the scenes. It requires two separate ports to be used since two distinct [WebDriver Remote Ends](https://www.w3.org/TR/webdriver/#dfn-remote-ends) run.
|
||||
|
||||
#![doc(
|
||||
html_logo_url = "https://github.com/tauri-apps/tauri/raw/dev/.github/icon.png",
|
||||
html_favicon_url = "https://github.com/tauri-apps/tauri/raw/dev/.github/icon.png"
|
||||
)]
|
||||
|
||||
#[cfg(any(target_os = "linux", windows))]
|
||||
mod cli;
|
||||
#[cfg(any(target_os = "linux", windows))]
|
||||
mod server;
|
||||
#[cfg(any(target_os = "linux", windows))]
|
||||
mod webdriver;
|
||||
|
||||
#[cfg(not(any(target_os = "linux", windows)))]
|
||||
fn main() {
|
||||
println!("tauri-driver is not supported on this platform");
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "linux", windows))]
|
||||
fn main() {
|
||||
let args = pico_args::Arguments::from_env().into();
|
||||
|
||||
#[cfg(windows)]
|
||||
let _job_handle = {
|
||||
let job = win32job::Job::create().unwrap();
|
||||
let mut info = job.query_extended_limit_info().unwrap();
|
||||
info.limit_kill_on_job_close();
|
||||
job.set_extended_limit_info(&info).unwrap();
|
||||
job.assign_current_process().unwrap();
|
||||
job
|
||||
};
|
||||
|
||||
// start the native webdriver on the port specified in args
|
||||
let mut driver = webdriver::native(&args);
|
||||
let driver = driver
|
||||
.spawn()
|
||||
.expect("error while running native webdriver");
|
||||
|
||||
// start our webdriver intermediary node
|
||||
if let Err(e) = server::run(args, driver) {
|
||||
eprintln!("error while running server: {e}");
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
245
crates/tauri-driver/src/server.rs
Normal file
245
crates/tauri-driver/src/server.rs
Normal file
@@ -0,0 +1,245 @@
|
||||
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
use crate::cli::Args;
|
||||
use anyhow::Error;
|
||||
use futures_util::TryFutureExt;
|
||||
use http_body_util::{BodyExt, Full};
|
||||
use hyper::{
|
||||
Method, Request, Response,
|
||||
body::{Bytes, Incoming},
|
||||
header::CONTENT_LENGTH,
|
||||
http::uri::Authority,
|
||||
service::service_fn,
|
||||
};
|
||||
use hyper_util::{
|
||||
client::legacy::{Client, connect::HttpConnector},
|
||||
rt::{TokioExecutor, TokioIo},
|
||||
server::conn::auto,
|
||||
};
|
||||
use serde::Deserialize;
|
||||
use serde_json::{Map, Value, json};
|
||||
use std::path::PathBuf;
|
||||
use std::process::Child;
|
||||
use tokio::net::TcpListener;
|
||||
|
||||
const TAURI_OPTIONS: &str = "tauri:options";
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
struct TauriOptions {
|
||||
application: PathBuf,
|
||||
#[serde(default)]
|
||||
args: Vec<String>,
|
||||
#[cfg(target_os = "windows")]
|
||||
#[serde(default)]
|
||||
webview_options: Option<Value>,
|
||||
}
|
||||
|
||||
impl TauriOptions {
|
||||
#[cfg(target_os = "linux")]
|
||||
fn into_native_object(self) -> Map<String, Value> {
|
||||
let mut map = Map::new();
|
||||
map.insert(
|
||||
"webkitgtk:browserOptions".into(),
|
||||
json!({"binary": self.application, "args": self.args}),
|
||||
);
|
||||
map
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
fn into_native_object(self) -> Map<String, Value> {
|
||||
let mut ms_edge_options = Map::new();
|
||||
ms_edge_options.insert(
|
||||
"binary".into(),
|
||||
json!(self.application.with_extension("exe")),
|
||||
);
|
||||
ms_edge_options.insert("args".into(), self.args.into());
|
||||
|
||||
if let Some(webview_options) = self.webview_options {
|
||||
ms_edge_options.insert("webviewOptions".into(), webview_options);
|
||||
}
|
||||
|
||||
let mut map = Map::new();
|
||||
map.insert("ms:edgeChromium".into(), json!(true));
|
||||
map.insert("browserName".into(), json!("webview2"));
|
||||
map.insert("ms:edgeOptions".into(), ms_edge_options.into());
|
||||
map
|
||||
}
|
||||
}
|
||||
|
||||
async fn handle(
|
||||
client: Client<HttpConnector, Full<Bytes>>,
|
||||
req: Request<Incoming>,
|
||||
args: Args,
|
||||
) -> Result<Response<Incoming>, Error> {
|
||||
// manipulate a new session to convert options to the native driver format
|
||||
let new_req: Request<Full<Bytes>> =
|
||||
if let (&Method::POST, "/session") = (req.method(), req.uri().path()) {
|
||||
let (mut parts, body) = req.into_parts();
|
||||
|
||||
// get the body from the future stream and parse it as json
|
||||
let body = body.collect().await?.to_bytes().to_vec();
|
||||
let json: Value = serde_json::from_slice(&body)?;
|
||||
|
||||
// manipulate the json to convert from tauri option to native driver options
|
||||
let json = map_capabilities(json);
|
||||
|
||||
// serialize json and update the content-length header to be accurate
|
||||
let bytes = serde_json::to_vec(&json)?;
|
||||
parts.headers.insert(CONTENT_LENGTH, bytes.len().into());
|
||||
|
||||
Request::from_parts(parts, Full::new(bytes.into()))
|
||||
} else {
|
||||
let (parts, body) = req.into_parts();
|
||||
|
||||
let body = body.collect().await?.to_bytes().to_vec();
|
||||
|
||||
Request::from_parts(parts, Full::new(body.into()))
|
||||
};
|
||||
|
||||
client
|
||||
.request(forward_to_native_driver(new_req, args)?)
|
||||
.err_into()
|
||||
.await
|
||||
}
|
||||
|
||||
/// Transform the request to a request for the native webdriver server.
|
||||
fn forward_to_native_driver(
|
||||
mut req: Request<Full<Bytes>>,
|
||||
args: Args,
|
||||
) -> Result<Request<Full<Bytes>>, Error> {
|
||||
let host: Authority = {
|
||||
let headers = req.headers_mut();
|
||||
headers.remove("host").expect("hyper request has host")
|
||||
}
|
||||
.to_str()?
|
||||
.parse()?;
|
||||
|
||||
let path = req
|
||||
.uri()
|
||||
.path_and_query()
|
||||
.expect("hyper request has uri")
|
||||
.clone();
|
||||
|
||||
let uri = format!(
|
||||
"http://{}:{}{}",
|
||||
host.host(),
|
||||
args.native_port,
|
||||
path.as_str()
|
||||
);
|
||||
|
||||
let (mut parts, body) = req.into_parts();
|
||||
parts.uri = uri.parse()?;
|
||||
Ok(Request::from_parts(parts, body))
|
||||
}
|
||||
|
||||
/// only happy path for now, no errors
|
||||
fn map_capabilities(mut json: Value) -> Value {
|
||||
let mut native = None;
|
||||
if let Some(capabilities) = json.get_mut("capabilities") {
|
||||
if let Some(always_match) = capabilities.get_mut("alwaysMatch") {
|
||||
if let Some(always_match) = always_match.as_object_mut() {
|
||||
if let Some(tauri_options) = always_match.remove(TAURI_OPTIONS) {
|
||||
if let Ok(options) = serde_json::from_value::<TauriOptions>(tauri_options) {
|
||||
native = Some(options.into_native_object());
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(native) = native.clone() {
|
||||
always_match.extend(native);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(native) = native {
|
||||
if let Some(desired) = json.get_mut("desiredCapabilities") {
|
||||
if let Some(desired) = desired.as_object_mut() {
|
||||
desired.remove(TAURI_OPTIONS);
|
||||
desired.extend(native);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
json
|
||||
}
|
||||
|
||||
#[tokio::main(flavor = "current_thread")]
|
||||
pub async fn run(args: Args, mut _driver: Child) -> Result<(), Error> {
|
||||
#[cfg(unix)]
|
||||
let (signals_handle, signals_task) = {
|
||||
use futures_util::StreamExt;
|
||||
use signal_hook::consts::signal::*;
|
||||
|
||||
let signals = signal_hook_tokio::Signals::new([SIGTERM, SIGINT, SIGQUIT])?;
|
||||
let signals_handle = signals.handle();
|
||||
let signals_task = tokio::spawn(async move {
|
||||
let mut signals = signals.fuse();
|
||||
#[allow(clippy::never_loop)]
|
||||
while let Some(signal) = signals.next().await {
|
||||
match signal {
|
||||
SIGTERM | SIGINT | SIGQUIT => {
|
||||
_driver
|
||||
.kill()
|
||||
.expect("unable to kill native webdriver server");
|
||||
std::process::exit(0);
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
});
|
||||
(signals_handle, signals_task)
|
||||
};
|
||||
|
||||
let address = std::net::SocketAddr::from(([127, 0, 0, 1], args.port));
|
||||
|
||||
// the client we use to proxy requests to the native webdriver
|
||||
let client = Client::builder(TokioExecutor::new())
|
||||
.http1_preserve_header_case(true)
|
||||
.http1_title_case_headers(true)
|
||||
.retry_canceled_requests(false)
|
||||
.build_http();
|
||||
|
||||
// set up a http1 server that uses the service we just created
|
||||
let srv = async move {
|
||||
if let Ok(listener) = TcpListener::bind(address).await {
|
||||
loop {
|
||||
let client = client.clone();
|
||||
let args = args.clone();
|
||||
if let Ok((stream, _)) = listener.accept().await {
|
||||
let io = TokioIo::new(stream);
|
||||
|
||||
tokio::task::spawn(async move {
|
||||
if let Err(err) = auto::Builder::new(TokioExecutor::new())
|
||||
.http1()
|
||||
.title_case_headers(true)
|
||||
.preserve_header_case(true)
|
||||
.serve_connection(
|
||||
io,
|
||||
service_fn(|request| handle(client.clone(), request, args.clone())),
|
||||
)
|
||||
.await
|
||||
{
|
||||
println!("Error serving connection: {err:?}");
|
||||
}
|
||||
});
|
||||
} else {
|
||||
println!("accept new stream fail, ignore here");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
println!("can not listen to address: {address:?}");
|
||||
}
|
||||
};
|
||||
srv.await;
|
||||
|
||||
#[cfg(unix)]
|
||||
{
|
||||
signals_handle.close();
|
||||
signals_task.await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
61
crates/tauri-driver/src/webdriver.rs
Normal file
61
crates/tauri-driver/src/webdriver.rs
Normal file
@@ -0,0 +1,61 @@
|
||||
// Copyright 2019-2026 Tauri Programme within The Commons Conservancy
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
use crate::cli::Args;
|
||||
use std::{
|
||||
env::current_dir,
|
||||
process::{Command, Stdio},
|
||||
};
|
||||
|
||||
// the name of the binary to find in $PATH
|
||||
#[cfg(target_os = "linux")]
|
||||
const DRIVER_BINARY: &str = "WebKitWebDriver";
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
const DRIVER_BINARY: &str = "msedgedriver.exe";
|
||||
|
||||
/// Find the native driver binary in the PATH, or exits the process with an error.
|
||||
pub fn native(args: &Args) -> Command {
|
||||
let native_binary = match args.native_driver.as_deref() {
|
||||
Some(custom) => {
|
||||
if custom.exists() {
|
||||
custom.to_owned()
|
||||
} else {
|
||||
eprintln!(
|
||||
"can not find the supplied binary path {}. This is currently required.",
|
||||
custom.display()
|
||||
);
|
||||
match current_dir() {
|
||||
Ok(cwd) => eprintln!("current working directory: {}", cwd.display()),
|
||||
Err(error) => eprintln!("can not find current working directory: {error}"),
|
||||
}
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
None => match which::which(DRIVER_BINARY) {
|
||||
Ok(binary) => binary,
|
||||
Err(error) => {
|
||||
eprintln!(
|
||||
"can not find binary {DRIVER_BINARY} in the PATH. This is currently required.\
|
||||
You can also pass a custom path with --native-driver"
|
||||
);
|
||||
eprintln!("{error:?}");
|
||||
std::process::exit(1);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
let mut cmd = Command::new(native_binary);
|
||||
cmd.env("TAURI_AUTOMATION", "true"); // 1.x
|
||||
cmd.env("TAURI_WEBVIEW_AUTOMATION", "true"); // 2.x
|
||||
cmd.arg(format!("--port={}", args.native_port));
|
||||
cmd.arg(format!("--host={}", args.native_host));
|
||||
|
||||
// Don't inherit stdout from parent to prevent native WebDriver binary/HTTP protocol data
|
||||
// from corrupting tauri-driver's stdout (which gets captured by the test framework).
|
||||
// Keep stderr inherited so WebDriver logs/errors are still visible.
|
||||
cmd.stdout(Stdio::null());
|
||||
|
||||
cmd
|
||||
}
|
||||
Reference in New Issue
Block a user