mirror of
https://github.com/tauri-apps/tauri.git
synced 2026-04-11 10:43:31 +02:00
Compare commits
7 Commits
feat/traci
...
feat/comma
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
83a9e6c572 | ||
|
|
f7e86798c2 | ||
|
|
936d46a41a | ||
|
|
a115f91c52 | ||
|
|
2624af9c24 | ||
|
|
b0485d0187 | ||
|
|
a2724b3e1c |
@@ -5,8 +5,8 @@
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::{ffi::OsStr, str::FromStr};
|
||||
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::quote;
|
||||
use proc_macro2::{Group, TokenStream, TokenTree};
|
||||
use quote::{quote, TokenStreamExt};
|
||||
use sha2::{Digest, Sha256};
|
||||
|
||||
use tauri_utils::assets::AssetKey;
|
||||
@@ -352,7 +352,7 @@ pub fn context_codegen(data: ContextData) -> Result<TokenStream, EmbeddedAssetsE
|
||||
|
||||
let info_plist_path = out_path.display().to_string();
|
||||
quote!({
|
||||
tauri::embed_plist::embed_info_plist!(#info_plist_path);
|
||||
#root::embed_plist::embed_info_plist!(#info_plist_path);
|
||||
})
|
||||
} else {
|
||||
quote!(())
|
||||
@@ -396,7 +396,7 @@ pub fn context_codegen(data: ContextData) -> Result<TokenStream, EmbeddedAssetsE
|
||||
assets: ::std::sync::Arc::new(#assets),
|
||||
schema: #schema.into(),
|
||||
key: #key.into(),
|
||||
crypto_keys: std::boxed::Box::new(::tauri::utils::pattern::isolation::Keys::new().expect("unable to generate cryptographically secure keys for Tauri \"Isolation\" Pattern")),
|
||||
crypto_keys: std::boxed::Box::new(#root::utils::pattern::isolation::Keys::new().expect("unable to generate cryptographically secure keys for Tauri \"Isolation\" Pattern")),
|
||||
})
|
||||
}
|
||||
};
|
||||
@@ -435,7 +435,70 @@ pub fn context_codegen(data: ContextData) -> Result<TokenStream, EmbeddedAssetsE
|
||||
#[cfg(not(feature = "shell-scope"))]
|
||||
let shell_scope_config = quote!();
|
||||
|
||||
Ok(quote!(#root::Context::new(
|
||||
fn compare_token_stream(a: TokenStream, b: TokenStream) -> bool {
|
||||
if a.clone().into_iter().count() != b.clone().into_iter().count() {
|
||||
return false;
|
||||
}
|
||||
for (a, b) in a.into_iter().zip(b) {
|
||||
if !compare_token_tree(a, b) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
fn compare_token_tree(a: TokenTree, b: TokenTree) -> bool {
|
||||
match (a, b) {
|
||||
(TokenTree::Group(a), TokenTree::Group(b)) => compare_token_stream(a.stream(), b.stream()),
|
||||
(TokenTree::Ident(a), TokenTree::Ident(b)) => b == a,
|
||||
(TokenTree::Punct(a), TokenTree::Punct(b)) => a.to_string() == b.to_string(),
|
||||
(TokenTree::Literal(a), TokenTree::Literal(b)) => a.to_string() == b.to_string(),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn change_tree_tauri_root(
|
||||
token: TokenTree,
|
||||
previous: &Option<TokenTree>,
|
||||
new: &mut TokenStream,
|
||||
) -> bool {
|
||||
match token {
|
||||
TokenTree::Ident(i) if i == "utils" => {
|
||||
new.append_all(quote!(tauri_utils));
|
||||
false
|
||||
}
|
||||
TokenTree::Ident(i) => {
|
||||
let ignore = match previous {
|
||||
Some(TokenTree::Punct(p)) if p.as_char() == ':' => i == "tauri",
|
||||
_ => false,
|
||||
};
|
||||
if !ignore {
|
||||
new.append(i);
|
||||
}
|
||||
ignore
|
||||
}
|
||||
TokenTree::Group(g) => {
|
||||
let mut stream = TokenStream::new();
|
||||
let mut ignore = false;
|
||||
let mut previous_token = None;
|
||||
for token in g.stream() {
|
||||
if ignore && matches!(token, TokenTree::Punct(_)) {
|
||||
continue;
|
||||
}
|
||||
ignore = change_tree_tauri_root(token.clone(), &previous_token, &mut stream);
|
||||
previous_token.replace(token);
|
||||
}
|
||||
new.append(Group::new(g.delimiter(), stream));
|
||||
false
|
||||
}
|
||||
_ => {
|
||||
new.append(token);
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let context = quote!(#root::Context::new(
|
||||
#config,
|
||||
::std::sync::Arc::new(#assets),
|
||||
#default_window_icon,
|
||||
@@ -445,7 +508,23 @@ pub fn context_codegen(data: ContextData) -> Result<TokenStream, EmbeddedAssetsE
|
||||
#info_plist,
|
||||
#pattern,
|
||||
#shell_scope_config
|
||||
)))
|
||||
));
|
||||
|
||||
if compare_token_stream(root, quote!(crate)) {
|
||||
let mut stream = TokenStream::new();
|
||||
let mut ignore = false;
|
||||
let mut previous_token = None;
|
||||
for token in context {
|
||||
if ignore && matches!(token, TokenTree::Punct(_)) {
|
||||
continue;
|
||||
}
|
||||
ignore = change_tree_tauri_root(token.clone(), &previous_token, &mut stream);
|
||||
previous_token.replace(token);
|
||||
}
|
||||
Ok(stream)
|
||||
} else {
|
||||
Ok(context)
|
||||
}
|
||||
}
|
||||
|
||||
fn ico_icon<P: AsRef<Path>>(
|
||||
|
||||
@@ -4,17 +4,18 @@
|
||||
|
||||
use heck::{ToLowerCamelCase, ToSnakeCase};
|
||||
use proc_macro::TokenStream;
|
||||
use proc_macro2::TokenStream as TokenStream2;
|
||||
use proc_macro2::{Ident, Span, TokenStream as TokenStream2};
|
||||
use quote::{format_ident, quote};
|
||||
use syn::{
|
||||
ext::IdentExt,
|
||||
parse::{Parse, ParseStream},
|
||||
parse_macro_input,
|
||||
spanned::Spanned,
|
||||
FnArg, Ident, ItemFn, Lit, Meta, Pat, Token, Visibility,
|
||||
FnArg, ItemFn, Lit, Meta, Pat, Token, Visibility,
|
||||
};
|
||||
|
||||
struct WrapperAttributes {
|
||||
root: TokenStream2,
|
||||
execution_context: ExecutionContext,
|
||||
argument_case: ArgumentCase,
|
||||
}
|
||||
@@ -22,6 +23,7 @@ struct WrapperAttributes {
|
||||
impl Parse for WrapperAttributes {
|
||||
fn parse(input: ParseStream) -> syn::Result<Self> {
|
||||
let mut wrapper_attributes = WrapperAttributes {
|
||||
root: quote!(::tauri),
|
||||
execution_context: ExecutionContext::Blocking,
|
||||
argument_case: ArgumentCase::Camel,
|
||||
};
|
||||
@@ -43,6 +45,11 @@ impl Parse for WrapperAttributes {
|
||||
}
|
||||
};
|
||||
}
|
||||
} else if v.path.is_ident("root") {
|
||||
if let Lit::Str(s) = v.lit {
|
||||
let ident = Ident::new(&s.value(), Span::call_site());
|
||||
wrapper_attributes.root = quote!(#ident);
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(Meta::Path(p)) => {
|
||||
@@ -104,21 +111,28 @@ pub fn wrapper(attributes: TokenStream, item: TokenStream) -> TokenStream {
|
||||
};
|
||||
|
||||
// body to the command wrapper or a `compile_error!` of an error occurred while parsing it.
|
||||
let body = syn::parse::<WrapperAttributes>(attributes)
|
||||
let (body, attributes) = syn::parse::<WrapperAttributes>(attributes)
|
||||
.map(|mut attrs| {
|
||||
if function.sig.asyncness.is_some() {
|
||||
attrs.execution_context = ExecutionContext::Async;
|
||||
}
|
||||
attrs
|
||||
})
|
||||
.and_then(|attrs| match attrs.execution_context {
|
||||
ExecutionContext::Async => body_async(&function, &invoke, attrs.argument_case),
|
||||
ExecutionContext::Blocking => body_blocking(&function, &invoke, attrs.argument_case),
|
||||
.and_then(|attrs| {
|
||||
let body = match attrs.execution_context {
|
||||
ExecutionContext::Async => body_async(&function, &invoke, &attrs),
|
||||
ExecutionContext::Blocking => body_blocking(&function, &invoke, &attrs),
|
||||
};
|
||||
body.map(|b| (b, Some(attrs)))
|
||||
})
|
||||
.unwrap_or_else(syn::Error::into_compile_error);
|
||||
.unwrap_or_else(|e| (syn::Error::into_compile_error(e), None));
|
||||
|
||||
let Invoke { message, resolver } = invoke;
|
||||
|
||||
let root = attributes
|
||||
.map(|a| a.root)
|
||||
.unwrap_or_else(|| quote!(::tauri));
|
||||
|
||||
// Rely on rust 2018 edition to allow importing a macro from a path.
|
||||
quote!(
|
||||
#function
|
||||
@@ -129,10 +143,10 @@ pub fn wrapper(attributes: TokenStream, item: TokenStream) -> TokenStream {
|
||||
// double braces because the item is expected to be a block expression
|
||||
($path:path, $invoke:ident) => {{
|
||||
#[allow(unused_imports)]
|
||||
use ::tauri::command::private::*;
|
||||
use #root::command::private::*;
|
||||
// prevent warnings when the body is a `compile_error!` or if the command has no arguments
|
||||
#[allow(unused_variables)]
|
||||
let ::tauri::Invoke { message: #message, resolver: #resolver } = $invoke;
|
||||
let #root::Invoke { message: #message, resolver: #resolver } = $invoke;
|
||||
|
||||
#body
|
||||
}};
|
||||
@@ -150,9 +164,13 @@ pub fn wrapper(attributes: TokenStream, item: TokenStream) -> TokenStream {
|
||||
/// See the [`tauri::command`] module for all the items and traits that make this possible.
|
||||
///
|
||||
/// [`tauri::command`]: https://docs.rs/tauri/*/tauri/runtime/index.html
|
||||
fn body_async(function: &ItemFn, invoke: &Invoke, case: ArgumentCase) -> syn::Result<TokenStream2> {
|
||||
fn body_async(
|
||||
function: &ItemFn,
|
||||
invoke: &Invoke,
|
||||
attributes: &WrapperAttributes,
|
||||
) -> syn::Result<TokenStream2> {
|
||||
let Invoke { message, resolver } = invoke;
|
||||
parse_args(function, message, case).map(|args| {
|
||||
parse_args(function, message, attributes).map(|args| {
|
||||
quote! {
|
||||
#resolver.respond_async_serialized(async move {
|
||||
let result = $path(#(#args?),*);
|
||||
@@ -171,10 +189,10 @@ fn body_async(function: &ItemFn, invoke: &Invoke, case: ArgumentCase) -> syn::Re
|
||||
fn body_blocking(
|
||||
function: &ItemFn,
|
||||
invoke: &Invoke,
|
||||
case: ArgumentCase,
|
||||
attributes: &WrapperAttributes,
|
||||
) -> syn::Result<TokenStream2> {
|
||||
let Invoke { message, resolver } = invoke;
|
||||
let args = parse_args(function, message, case)?;
|
||||
let args = parse_args(function, message, attributes)?;
|
||||
|
||||
// the body of a `match` to early return any argument that wasn't successful in parsing.
|
||||
let match_body = quote!({
|
||||
@@ -193,13 +211,13 @@ fn body_blocking(
|
||||
fn parse_args(
|
||||
function: &ItemFn,
|
||||
message: &Ident,
|
||||
case: ArgumentCase,
|
||||
attributes: &WrapperAttributes,
|
||||
) -> syn::Result<Vec<TokenStream2>> {
|
||||
function
|
||||
.sig
|
||||
.inputs
|
||||
.iter()
|
||||
.map(|arg| parse_arg(&function.sig.ident, arg, message, case))
|
||||
.map(|arg| parse_arg(&function.sig.ident, arg, message, attributes))
|
||||
.collect()
|
||||
}
|
||||
|
||||
@@ -208,7 +226,7 @@ fn parse_arg(
|
||||
command: &Ident,
|
||||
arg: &FnArg,
|
||||
message: &Ident,
|
||||
case: ArgumentCase,
|
||||
attributes: &WrapperAttributes,
|
||||
) -> syn::Result<TokenStream2> {
|
||||
// we have no use for self arguments
|
||||
let mut arg = match arg {
|
||||
@@ -243,7 +261,7 @@ fn parse_arg(
|
||||
));
|
||||
}
|
||||
|
||||
match case {
|
||||
match attributes.argument_case {
|
||||
ArgumentCase::Camel => {
|
||||
key = key.to_lower_camel_case();
|
||||
}
|
||||
@@ -252,8 +270,10 @@ fn parse_arg(
|
||||
}
|
||||
}
|
||||
|
||||
Ok(quote!(::tauri::command::CommandArg::from_command(
|
||||
::tauri::command::CommandItem {
|
||||
let root = &attributes.root;
|
||||
|
||||
Ok(quote!(#root::command::CommandArg::from_command(
|
||||
#root::command::CommandItem {
|
||||
name: stringify!(#command),
|
||||
key: #key,
|
||||
message: &#message,
|
||||
|
||||
@@ -119,10 +119,10 @@ quickcheck = "1.0.3"
|
||||
quickcheck_macros = "1.0.0"
|
||||
serde = { version = "1.0", features = [ "derive" ] }
|
||||
serde_json = "1.0"
|
||||
tauri = { path = ".", default-features = false, features = [ "wry" ] }
|
||||
tokio-test = "0.4.2"
|
||||
tokio = { version = "1", features = [ "full" ] }
|
||||
cargo_toml = "0.11"
|
||||
heck = "0.4"
|
||||
|
||||
[features]
|
||||
default = [ "wry", "compression", "objc-exception" ]
|
||||
|
||||
@@ -558,6 +558,7 @@ impl<T: UserEvent> Dispatch<T> for MockDispatcher {
|
||||
}
|
||||
|
||||
fn eval_script<S: Into<String>>(&self, script: S) -> Result<()> {
|
||||
println!("eval {}", script.into());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@@ -85,6 +85,10 @@ pub fn mock_context<A: Assets>(assets: A) -> crate::Context<A> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mock_builder() -> crate::Builder<MockRuntime> {
|
||||
crate::Builder::new()
|
||||
}
|
||||
|
||||
pub fn mock_app() -> crate::App<MockRuntime> {
|
||||
crate::Builder::<MockRuntime>::new()
|
||||
.build(mock_context(noop_assets()))
|
||||
|
||||
@@ -1599,9 +1599,310 @@ impl<R: Runtime> Window<R> {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::sync::mpsc::{sync_channel, SyncSender};
|
||||
|
||||
use super::{Window, WindowBuilder};
|
||||
use crate::{api::ipc::CallbackFn, test, InvokePayload, State};
|
||||
use serde_json::Value as JsonValue;
|
||||
|
||||
#[test]
|
||||
fn window_is_send_sync() {
|
||||
crate::test_utils::assert_send::<super::Window>();
|
||||
crate::test_utils::assert_sync::<super::Window>();
|
||||
crate::test_utils::assert_send::<Window>();
|
||||
crate::test_utils::assert_sync::<Window>();
|
||||
}
|
||||
|
||||
macro_rules! commands {
|
||||
(fn, $(#[$cmd_meta:meta])*) => {
|
||||
$(#[$cmd_meta])*
|
||||
fn cmd_state(channel: State<'_, Channel>) {
|
||||
println!("cmd state");
|
||||
channel.tx.send(Response::Cmd).unwrap();
|
||||
}
|
||||
|
||||
$(#[$cmd_meta])*
|
||||
fn cmd_state_return_val(channel: State<'_, Channel>) -> &'static str {
|
||||
println!("cmd state return val");
|
||||
channel.tx.send(Response::CmdReturnVal).unwrap();
|
||||
STATE_RETURN_VAL_RESPONSE
|
||||
}
|
||||
|
||||
$(#[$cmd_meta])*
|
||||
fn cmd_state_arg(channel: State<'_, Channel>, int_arg: usize) {
|
||||
println!("cmd state arg");
|
||||
channel.tx.send(Response::CmdArg(int_arg)).unwrap();
|
||||
}
|
||||
|
||||
$(#[$cmd_meta])*
|
||||
fn cmd_state_arg_return_val(channel: State<'_, Channel>, int_arg: usize) -> &'static str {
|
||||
println!("cmd state arg return val");
|
||||
channel.tx.send(Response::CmdArgReturnVal(int_arg)).unwrap();
|
||||
STATE_ARG_RETURN_VAL_RESPONSE
|
||||
}
|
||||
};
|
||||
|
||||
(async fn, $(#[$cmd_meta:meta])*) => {
|
||||
$(#[$cmd_meta])*
|
||||
async fn cmd_state(channel: State<'_, Channel>) -> crate::Result<()> {
|
||||
println!("cmd state");
|
||||
channel.tx.send(Response::Cmd).unwrap();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
$(#[$cmd_meta])*
|
||||
async fn cmd_state_return_val(channel: State<'_, Channel>) -> crate::Result<&'static str> {
|
||||
println!("cmd state return val");
|
||||
channel.tx.send(Response::CmdReturnVal).unwrap();
|
||||
Ok(STATE_RETURN_VAL_RESPONSE)
|
||||
}
|
||||
|
||||
$(#[$cmd_meta])*
|
||||
async fn cmd_state_arg(channel: State<'_, Channel>, int_arg: usize) -> crate::Result<()> {
|
||||
println!("cmd state arg");
|
||||
channel.tx.send(Response::CmdArg(int_arg)).unwrap();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
$(#[$cmd_meta])*
|
||||
async fn cmd_state_arg_return_val(
|
||||
channel: State<'_, Channel>,
|
||||
int_arg: usize,
|
||||
) -> crate::Result<&'static str> {
|
||||
println!("cmd state arg return val");
|
||||
channel.tx.send(Response::CmdArgReturnVal(int_arg)).unwrap();
|
||||
Ok(STATE_ARG_RETURN_VAL_RESPONSE)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! command_test {
|
||||
($test_name: ident, $($fn_kind: ident) +, $(#[$cmd_meta:meta])*, $case: path) => {
|
||||
#[test]
|
||||
fn $test_name() {
|
||||
const STATE_RETURN_VAL_RESPONSE: &str = "return-val";
|
||||
const STATE_ARG_RETURN_VAL_RESPONSE: &str = "arg-return-val";
|
||||
const FUTURE_RETURN_VAL_RESPONSE: &str = "future-return-val";
|
||||
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
enum Response {
|
||||
Cmd,
|
||||
CmdReturnVal,
|
||||
CmdArg(usize),
|
||||
CmdArgReturnVal(usize),
|
||||
CmdFutureReturnVal(usize),
|
||||
Person(Person),
|
||||
}
|
||||
|
||||
struct Channel {
|
||||
tx: SyncSender<Response>,
|
||||
}
|
||||
|
||||
#[derive(Debug, serde::Serialize, serde::Deserialize, Eq, PartialEq)]
|
||||
struct Person {
|
||||
name: String,
|
||||
age: u8,
|
||||
}
|
||||
|
||||
#[derive(serde::Serialize, serde::Deserialize)]
|
||||
struct InlinePerson(String, u8);
|
||||
|
||||
$(#[$cmd_meta])*
|
||||
$($fn_kind)* cmd() {
|
||||
println!("cmd");
|
||||
}
|
||||
|
||||
$(#[$cmd_meta])*
|
||||
$($fn_kind)* cmd_args_struct(Person { name, age }: Person) {
|
||||
println!("received person struct with name: {} | age: {}", name, age);
|
||||
}
|
||||
|
||||
$(#[$cmd_meta])*
|
||||
$($fn_kind)* cmd_args_tuple_struct(InlinePerson(name, age): InlinePerson) {
|
||||
println!("received person tuple with name: {} | age: {}", name, age);
|
||||
}
|
||||
|
||||
$(#[$cmd_meta])*
|
||||
$($fn_kind)* cmd_state_args_struct_return_val(
|
||||
channel: State<'_, Channel>,
|
||||
person: Person,
|
||||
) -> crate::Result<()> {
|
||||
println!("received person struct with name: {} | age: {}", person.name, person.age);
|
||||
channel.tx.send(Response::Person(person)).unwrap();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
$(#[$cmd_meta])*
|
||||
$($fn_kind)* cmd_state_args_tuple_struct_return_val(
|
||||
channel: State<'_, Channel>,
|
||||
InlinePerson(name, age): InlinePerson
|
||||
) -> crate::Result<()> {
|
||||
println!("received person tuple with name: {} | age: {}", name, age);
|
||||
channel.tx.send(Response::Person(Person { name, age })).unwrap();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[crate::command(root = "crate", async)]
|
||||
fn cmd_state_arg_return_future(
|
||||
channel: State<'_, Channel>,
|
||||
int_arg: usize,
|
||||
) -> impl std::future::Future<Output = String> {
|
||||
println!("cmd state arg return future");
|
||||
channel.tx.send(Response::CmdFutureReturnVal(int_arg)).unwrap();
|
||||
std::future::ready(FUTURE_RETURN_VAL_RESPONSE.into())
|
||||
}
|
||||
|
||||
#[crate::command(root = "crate", async)]
|
||||
fn cmd_state_arg_return_future_result(
|
||||
channel: State<'_, Channel>,
|
||||
int_arg: usize,
|
||||
) -> impl std::future::Future<Output = crate::Result<String>> {
|
||||
println!("cmd state arg return future result");
|
||||
channel.tx.send(Response::CmdFutureReturnVal(int_arg)).unwrap();
|
||||
std::future::ready(Ok(FUTURE_RETURN_VAL_RESPONSE.into()))
|
||||
}
|
||||
|
||||
commands!($($fn_kind)*, $(#[$cmd_meta])*);
|
||||
|
||||
let (tx, rx) = sync_channel(1);
|
||||
let channel = Channel { tx };
|
||||
|
||||
let app = test::mock_builder()
|
||||
.manage(channel)
|
||||
.invoke_handler(crate::generate_handler![
|
||||
cmd,
|
||||
cmd_args_struct,
|
||||
cmd_args_tuple_struct,
|
||||
cmd_state_args_struct_return_val,
|
||||
cmd_state_args_tuple_struct_return_val,
|
||||
cmd_state,
|
||||
cmd_state_return_val,
|
||||
cmd_state_arg,
|
||||
cmd_state_arg_return_val,
|
||||
cmd_state_arg_return_future,
|
||||
cmd_state_arg_return_future_result
|
||||
])
|
||||
.build(test::mock_context(test::noop_assets()))
|
||||
.unwrap();
|
||||
let window = WindowBuilder::new(&app, "test", Default::default())
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
#[derive(Default)]
|
||||
struct JsonMap(serde_json::Map<String, JsonValue>);
|
||||
|
||||
impl From<JsonMap> for JsonValue {
|
||||
fn from(map: JsonMap) -> Self {
|
||||
map.0.into()
|
||||
}
|
||||
}
|
||||
|
||||
impl JsonMap {
|
||||
fn insert(mut self, key: impl Into<String>, value: impl serde::Serialize) -> Self {
|
||||
self.0.insert(key.into(), serde_json::to_value(value).unwrap());
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
struct UnitTest {
|
||||
cmd: &'static str,
|
||||
response: Option<Response>,
|
||||
arg: Option<JsonValue>,
|
||||
}
|
||||
|
||||
let tests = vec![
|
||||
UnitTest {
|
||||
cmd: "cmd",
|
||||
response: None,
|
||||
arg: None,
|
||||
},
|
||||
UnitTest {
|
||||
cmd: "cmd_args_struct",
|
||||
response: None,
|
||||
arg: Some(JsonMap::default().insert("person", Person { name: "Tauri".into(), age: 1 }).into()),
|
||||
},
|
||||
UnitTest {
|
||||
cmd: "cmd_args_tuple_struct",
|
||||
response: None,
|
||||
arg: Some(JsonMap::default().insert($case("inline_person").to_string(), InlinePerson("Tauri".into(), 3)).into()),
|
||||
},
|
||||
UnitTest {
|
||||
cmd: "cmd_state_args_struct_return_val",
|
||||
response: Some(Response::Person(Person { name: "Tauri".into(), age: 1 })),
|
||||
arg: Some(JsonMap::default().insert("person", Person { name: "Tauri".into(), age: 1 }).into()),
|
||||
},
|
||||
UnitTest {
|
||||
cmd: "cmd_state_args_tuple_struct_return_val",
|
||||
response: Some(Response::Person(Person { name: "Tauri".into(), age: 3 })),
|
||||
arg: Some(JsonMap::default().insert($case("inline_person").to_string(), InlinePerson("Tauri".into(), 3)).into()),
|
||||
},
|
||||
UnitTest {
|
||||
cmd: "cmd_state",
|
||||
response: Some(Response::Cmd),
|
||||
arg: None,
|
||||
},
|
||||
UnitTest {
|
||||
cmd: "cmd_state_return_val",
|
||||
response: Some(Response::CmdReturnVal),
|
||||
arg: None,
|
||||
},
|
||||
UnitTest {
|
||||
cmd: "cmd_state_arg",
|
||||
response: Some(Response::CmdArg(1)),
|
||||
arg: Some(JsonMap::default().insert($case("int_arg").to_string(), 1).into()),
|
||||
},
|
||||
UnitTest {
|
||||
cmd: "cmd_state_arg_return_val",
|
||||
response: Some(Response::CmdArgReturnVal(2)),
|
||||
arg: Some(JsonMap::default().insert($case("int_arg").to_string(), 2).into()),
|
||||
},
|
||||
UnitTest {
|
||||
cmd: "cmd_state_arg_return_future",
|
||||
response: Some(Response::CmdFutureReturnVal(2)),
|
||||
arg: Some(JsonMap::default().insert("intArg", 2).into()),
|
||||
},
|
||||
UnitTest {
|
||||
cmd: "cmd_state_arg_return_future_result",
|
||||
response: Some(Response::CmdFutureReturnVal(2)),
|
||||
arg: Some(JsonMap::default().insert("intArg", 2).into()),
|
||||
},
|
||||
];
|
||||
|
||||
for test in tests {
|
||||
window
|
||||
.clone()
|
||||
.on_message(InvokePayload {
|
||||
cmd: test.cmd.into(),
|
||||
tauri_module: None,
|
||||
callback: CallbackFn(0),
|
||||
error: CallbackFn(0),
|
||||
inner: test.arg.unwrap_or_default(),
|
||||
})
|
||||
.unwrap();
|
||||
if let Some(response) = test.response {
|
||||
assert_eq!(rx.recv_timeout(std::time::Duration::from_secs(3)).unwrap(), response);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
command_test!(regular_commands, fn, #[crate::command(root = "crate")], heck::AsLowerCamelCase);
|
||||
command_test!(async_commands, async fn, #[crate::command(root = "crate")], heck::AsLowerCamelCase);
|
||||
command_test!(
|
||||
async_attr_commands,
|
||||
fn,
|
||||
#[crate::command(root = "crate", async)],
|
||||
heck::AsLowerCamelCase
|
||||
);
|
||||
command_test!(
|
||||
regular_rename_all_snake_case_commands,
|
||||
fn,
|
||||
#[crate::command(root = "crate", rename_all = "snake_case")],
|
||||
heck::AsSnakeCase
|
||||
);
|
||||
command_test!(
|
||||
regular_rename_all_camel_case_commands,
|
||||
fn,
|
||||
#[crate::command(root = "crate", rename_all = "camelCase")],
|
||||
heck::AsLowerCamelCase
|
||||
);
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ fn build_app(
|
||||
bundle_updater: bool,
|
||||
target: BundleTarget,
|
||||
) {
|
||||
let mut command = Command::new(&cli_bin_path);
|
||||
let mut command = Command::new(cli_bin_path);
|
||||
command
|
||||
.args(["build", "--debug", "--verbose"])
|
||||
.arg("--config")
|
||||
|
||||
Reference in New Issue
Block a user