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:
338
crates/tauri/src/test/mod.rs
Normal file
338
crates/tauri/src/test/mod.rs
Normal file
@@ -0,0 +1,338 @@
|
||||
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
//! Utilities for unit testing on Tauri applications.
|
||||
//!
|
||||
//! # Stability
|
||||
//!
|
||||
//! This module is unstable.
|
||||
//!
|
||||
//! # Examples
|
||||
//!
|
||||
//! ```rust
|
||||
//! use tauri::test::{mock_builder, mock_context, noop_assets};
|
||||
//!
|
||||
//! #[tauri::command]
|
||||
//! fn ping() -> &'static str {
|
||||
//! "pong"
|
||||
//! }
|
||||
//!
|
||||
//! fn create_app<R: tauri::Runtime>(builder: tauri::Builder<R>) -> tauri::App<R> {
|
||||
//! builder
|
||||
//! .invoke_handler(tauri::generate_handler![ping])
|
||||
//! // remove the string argument to use your app's config file
|
||||
//! .build(tauri::generate_context!("test/fixture/src-tauri/tauri.conf.json"))
|
||||
//! .expect("failed to build app")
|
||||
//! }
|
||||
//!
|
||||
//! fn main() {
|
||||
//! // Use `tauri::Builder::default()` to use the default runtime rather than the `MockRuntime`;
|
||||
//! // let app = create_app(tauri::Builder::default());
|
||||
//! let app = create_app(mock_builder());
|
||||
//! let webview = tauri::WebviewWindowBuilder::new(&app, "main", Default::default()).build().unwrap();
|
||||
//!
|
||||
//! // run the `ping` command and assert it returns `pong`
|
||||
//! let res = tauri::test::get_ipc_response(
|
||||
//! &webview,
|
||||
//! tauri::webview::InvokeRequest {
|
||||
//! cmd: "ping".into(),
|
||||
//! callback: tauri::ipc::CallbackFn(0),
|
||||
//! error: tauri::ipc::CallbackFn(1),
|
||||
//! // alternatively use "tauri://localhost"
|
||||
//! url: "http://tauri.localhost".parse().unwrap(),
|
||||
//! body: tauri::ipc::InvokeBody::default(),
|
||||
//! headers: Default::default(),
|
||||
//! invoke_key: tauri::test::INVOKE_KEY.to_string(),
|
||||
//! },
|
||||
//! ).map(|b| b.deserialize::<String>().unwrap());
|
||||
//! }
|
||||
//! ```
|
||||
|
||||
#![allow(unused_variables)]
|
||||
|
||||
mod mock_runtime;
|
||||
pub use mock_runtime::*;
|
||||
use serde::Serialize;
|
||||
use serialize_to_javascript::DefaultTemplate;
|
||||
|
||||
use std::{borrow::Cow, collections::HashMap, fmt::Debug};
|
||||
|
||||
use crate::{
|
||||
App, Assets, Builder, Context, Pattern, Runtime, Webview,
|
||||
ipc::{InvokeError, InvokeResponse, InvokeResponseBody},
|
||||
webview::InvokeRequest,
|
||||
};
|
||||
use tauri_utils::{
|
||||
acl::resolved::Resolved,
|
||||
assets::{AssetKey, AssetsIter, CspHash},
|
||||
config::{AppConfig, Config},
|
||||
};
|
||||
|
||||
/// The invoke key used for tests.
|
||||
pub const INVOKE_KEY: &str = "__invoke-key__";
|
||||
|
||||
/// An empty [`Assets`] implementation.
|
||||
pub struct NoopAsset {
|
||||
assets: HashMap<String, Vec<u8>>,
|
||||
csp_hashes: Vec<CspHash<'static>>,
|
||||
}
|
||||
|
||||
impl<R: Runtime> Assets<R> for NoopAsset {
|
||||
fn get(&self, key: &AssetKey) -> Option<Cow<'_, [u8]>> {
|
||||
None
|
||||
}
|
||||
|
||||
fn iter(&self) -> Box<AssetsIter<'_>> {
|
||||
Box::new(
|
||||
self
|
||||
.assets
|
||||
.iter()
|
||||
.map(|(k, b)| (Cow::Borrowed(k.as_str()), Cow::Borrowed(b.as_slice()))),
|
||||
)
|
||||
}
|
||||
|
||||
fn csp_hashes(&self, html_path: &AssetKey) -> Box<dyn Iterator<Item = CspHash<'_>> + '_> {
|
||||
Box::new(self.csp_hashes.iter().copied())
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new empty [`Assets`] implementation.
|
||||
pub fn noop_assets() -> NoopAsset {
|
||||
NoopAsset {
|
||||
assets: Default::default(),
|
||||
csp_hashes: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new [`crate::Context`] for testing.
|
||||
pub fn mock_context<R: Runtime, A: Assets<R>>(assets: A) -> crate::Context<R> {
|
||||
Context {
|
||||
config: Config {
|
||||
schema: None,
|
||||
product_name: Default::default(),
|
||||
main_binary_name: Default::default(),
|
||||
version: Default::default(),
|
||||
identifier: Default::default(),
|
||||
app: AppConfig {
|
||||
with_global_tauri: Default::default(),
|
||||
windows: Vec::new(),
|
||||
security: Default::default(),
|
||||
tray_icon: None,
|
||||
macos_private_api: false,
|
||||
enable_gtk_app_id: false,
|
||||
},
|
||||
bundle: Default::default(),
|
||||
build: Default::default(),
|
||||
plugins: Default::default(),
|
||||
},
|
||||
assets: Box::new(assets),
|
||||
default_window_icon: None,
|
||||
app_icon: None,
|
||||
#[cfg(all(desktop, feature = "tray-icon"))]
|
||||
tray_icon: None,
|
||||
package_info: crate::PackageInfo {
|
||||
name: "test".into(),
|
||||
version: "0.1.0".parse().unwrap(),
|
||||
authors: "Tauri",
|
||||
description: "Tauri test",
|
||||
crate_name: "test",
|
||||
},
|
||||
pattern: Pattern::Brownfield,
|
||||
runtime_authority: crate::runtime_authority!(Default::default(), Resolved::default()),
|
||||
plugin_global_api_scripts: None,
|
||||
|
||||
#[cfg(dev)]
|
||||
config_parent: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new [`Builder`] using the [`MockRuntime`].
|
||||
///
|
||||
/// To use a dummy [`Context`], see [`mock_app`].
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// #[cfg(test)]
|
||||
/// fn do_something() {
|
||||
/// let app = tauri::test::mock_builder()
|
||||
/// // remove the string argument to use your app's config file
|
||||
/// .build(tauri::generate_context!("test/fixture/src-tauri/tauri.conf.json"))
|
||||
/// .unwrap();
|
||||
/// }
|
||||
/// ```
|
||||
pub fn mock_builder() -> Builder<MockRuntime> {
|
||||
let mut builder = Builder::<MockRuntime>::new().enable_macos_default_menu(false);
|
||||
|
||||
builder.invoke_initialization_script = crate::app::InvokeInitializationScript {
|
||||
process_ipc_message_fn: crate::manager::webview::PROCESS_IPC_MESSAGE_FN,
|
||||
os_name: std::env::consts::OS,
|
||||
fetch_channel_data_command: crate::ipc::channel::FETCH_CHANNEL_DATA_COMMAND,
|
||||
invoke_key: INVOKE_KEY,
|
||||
}
|
||||
.render_default(&Default::default())
|
||||
.unwrap()
|
||||
.into_string();
|
||||
|
||||
builder.invoke_key = INVOKE_KEY.to_string();
|
||||
|
||||
builder
|
||||
}
|
||||
|
||||
/// Creates a new [`App`] for testing using the [`mock_context`] with a [`noop_assets`].
|
||||
pub fn mock_app() -> App<MockRuntime> {
|
||||
mock_builder().build(mock_context(noop_assets())).unwrap()
|
||||
}
|
||||
|
||||
/// Executes the given IPC message and assert the response matches the expected value.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// use tauri::test::{mock_builder, mock_context, noop_assets};
|
||||
///
|
||||
/// #[tauri::command]
|
||||
/// fn ping() -> &'static str {
|
||||
/// "pong"
|
||||
/// }
|
||||
///
|
||||
/// fn create_app<R: tauri::Runtime>(builder: tauri::Builder<R>) -> tauri::App<R> {
|
||||
/// builder
|
||||
/// .invoke_handler(tauri::generate_handler![ping])
|
||||
/// // remove the string argument to use your app's config file
|
||||
/// .build(tauri::generate_context!("test/fixture/src-tauri/tauri.conf.json"))
|
||||
/// .expect("failed to build app")
|
||||
/// }
|
||||
///
|
||||
/// fn main() {
|
||||
/// let app = create_app(mock_builder());
|
||||
/// let webview = tauri::WebviewWindowBuilder::new(&app, "main", Default::default()).build().unwrap();
|
||||
///
|
||||
/// // run the `ping` command and assert it returns `pong`
|
||||
/// tauri::test::assert_ipc_response(
|
||||
/// &webview,
|
||||
/// tauri::webview::InvokeRequest {
|
||||
/// cmd: "ping".into(),
|
||||
/// callback: tauri::ipc::CallbackFn(0),
|
||||
/// error: tauri::ipc::CallbackFn(1),
|
||||
/// url: if cfg!(any(windows, target_os = "android")) {
|
||||
/// "http://tauri.localhost"
|
||||
/// } else {
|
||||
/// "tauri://localhost"
|
||||
/// }.parse().unwrap(),
|
||||
/// body: tauri::ipc::InvokeBody::default(),
|
||||
/// headers: Default::default(),
|
||||
/// invoke_key: tauri::test::INVOKE_KEY.to_string(),
|
||||
/// },
|
||||
/// Ok("pong")
|
||||
/// );
|
||||
/// }
|
||||
/// ```
|
||||
pub fn assert_ipc_response<
|
||||
T: Serialize + Debug + Send + Sync + 'static,
|
||||
W: AsRef<Webview<MockRuntime>>,
|
||||
>(
|
||||
webview: &W,
|
||||
request: InvokeRequest,
|
||||
expected: Result<T, T>,
|
||||
) {
|
||||
let response =
|
||||
get_ipc_response(webview, request).map(|b| b.deserialize::<serde_json::Value>().unwrap());
|
||||
assert_eq!(
|
||||
response,
|
||||
expected
|
||||
.map(|e| serde_json::to_value(e).unwrap())
|
||||
.map_err(|e| serde_json::to_value(e).unwrap())
|
||||
);
|
||||
}
|
||||
|
||||
#[allow(clippy::needless_doctest_main)]
|
||||
/// Executes the given IPC message and get the return value.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// use tauri::test::{mock_builder, mock_context, noop_assets};
|
||||
///
|
||||
/// #[tauri::command]
|
||||
/// fn ping() -> &'static str {
|
||||
/// "pong"
|
||||
/// }
|
||||
///
|
||||
/// fn create_app<R: tauri::Runtime>(builder: tauri::Builder<R>) -> tauri::App<R> {
|
||||
/// builder
|
||||
/// .invoke_handler(tauri::generate_handler![ping])
|
||||
/// // remove the string argument to use your app's config file
|
||||
/// .build(tauri::generate_context!("test/fixture/src-tauri/tauri.conf.json"))
|
||||
/// .expect("failed to build app")
|
||||
/// }
|
||||
///
|
||||
/// fn main() {
|
||||
/// let app = create_app(mock_builder());
|
||||
/// let webview = tauri::WebviewWindowBuilder::new(&app, "main", Default::default()).build().unwrap();
|
||||
///
|
||||
/// // run the `ping` command and assert it returns `pong`
|
||||
/// let res = tauri::test::get_ipc_response(
|
||||
/// &webview,
|
||||
/// tauri::webview::InvokeRequest {
|
||||
/// cmd: "ping".into(),
|
||||
/// callback: tauri::ipc::CallbackFn(0),
|
||||
/// error: tauri::ipc::CallbackFn(1),
|
||||
/// url: if cfg!(any(windows, target_os = "android")) {
|
||||
/// "http://tauri.localhost"
|
||||
/// } else {
|
||||
/// "tauri://localhost"
|
||||
/// }.parse().unwrap(),
|
||||
/// body: tauri::ipc::InvokeBody::default(),
|
||||
/// headers: Default::default(),
|
||||
/// invoke_key: tauri::test::INVOKE_KEY.to_string(),
|
||||
/// },
|
||||
/// );
|
||||
/// assert!(res.is_ok());
|
||||
/// assert_eq!(res.unwrap().deserialize::<String>().unwrap(), String::from("pong"));
|
||||
/// }
|
||||
///```
|
||||
pub fn get_ipc_response<W: AsRef<Webview<MockRuntime>>>(
|
||||
webview: &W,
|
||||
request: InvokeRequest,
|
||||
) -> Result<InvokeResponseBody, serde_json::Value> {
|
||||
let (tx, rx) = std::sync::mpsc::sync_channel(1);
|
||||
webview.as_ref().clone().on_message(
|
||||
request,
|
||||
Box::new(move |_window, _cmd, response, _callback, _error| {
|
||||
tx.send(response).unwrap();
|
||||
}),
|
||||
);
|
||||
|
||||
let res = rx.recv().expect("Failed to receive result from command");
|
||||
match res {
|
||||
InvokeResponse::Ok(b) => Ok(b),
|
||||
InvokeResponse::Err(InvokeError(v)) => Err(v),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::time::Duration;
|
||||
|
||||
use super::mock_app;
|
||||
|
||||
#[test]
|
||||
fn run_app() {
|
||||
let app = mock_app();
|
||||
|
||||
let w = crate::WebviewWindowBuilder::new(&app, "main", Default::default())
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
std::thread::spawn(move || {
|
||||
std::thread::sleep(Duration::from_secs(1));
|
||||
w.close().unwrap();
|
||||
});
|
||||
|
||||
app.run(|_app, event| {
|
||||
println!("{event:?}");
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user