#![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::{
ipc::{InvokeError, InvokeResponse, InvokeResponseBody},
webview::InvokeRequest,
App, Assets, Builder, Context, Pattern, Runtime, Webview,
};
use tauri_utils::{
acl::resolved::Resolved,
assets::{AssetKey, AssetsIter, CspHash},
config::{AppConfig, Config},
};
pub const INVOKE_KEY: &str = "__invoke-key__";
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())
}
}
pub fn noop_assets() -> NoopAsset {
NoopAsset {
assets: Default::default(),
csp_hashes: Default::default(),
}
}
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,
}
}
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
}
pub fn mock_app() -> App<MockRuntime> {
mock_builder().build(mock_context(noop_assets())).unwrap()
}
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)]
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:?}");
});
}
}