Skip to content

Commit bed1cef

Browse files
committed
add tests & fixes
1 parent e694f66 commit bed1cef

File tree

3 files changed

+120
-2
lines changed

3 files changed

+120
-2
lines changed

Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ dunce = "1.0.5"
2626
[build-dependencies]
2727
tauri-plugin = { version = "2", features = ["build"] }
2828

29+
[dev-dependencies]
30+
tauri = { version = "2", features = ["test"] }
31+
2932
[features]
3033
venv = []
3134
default = ["venv", "pyo3"] # auto load src-python/.venv

src/lib.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,12 @@ if len(signature({}).parameters) != {}:
104104
.runner()
105105
.call_function(&function_name, payload.args)
106106
.await?;
107+
let value = match py_res.as_str() {
108+
Some(s) => s.to_string(),
109+
None => py_res.to_string(),
110+
};
107111
Ok(StringResponse {
108-
value: py_res.as_str().unwrap().to_string(),
112+
value,
109113
})
110114
}
111115

@@ -240,4 +244,7 @@ async fn register_python_functions<R: Runtime>(
240244
.await
241245
.unwrap();
242246
}
243-
}
247+
}
248+
249+
#[cfg(test)]
250+
mod tests;

src/tests.rs

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
// Tauri Python Plugin
2+
// © Copyright 2024, by Marco Mengelkoch
3+
// Licensed under MIT License, see License file for more details
4+
// git clone https://github.com/marcomq/tauri-plugin-python
5+
6+
use super::*;
7+
use tauri::{test::{self, MockRuntime}, AppHandle};
8+
9+
/// Creates a mock Tauri app and initializes the PyRunner state.
10+
/// It also runs some initial Python code to set up a variable and a function for testing.
11+
async fn mock_app_handle() -> AppHandle<MockRuntime> {
12+
let app = test::mock_app();
13+
let runner = PyRunner::new();
14+
app.manage(runner);
15+
16+
let runner = app.state::<PyRunner>().inner();
17+
runner
18+
.run("my_var = 123\ndef my_func(a, b):\n return a + b")
19+
.await
20+
.unwrap();
21+
22+
app.handle().clone()
23+
}
24+
25+
#[tokio::test]
26+
async fn test_read_variable() {
27+
let app = mock_app_handle().await;
28+
let payload = StringRequest {
29+
value: "my_var".into(),
30+
};
31+
let response = app.read_variable(payload).await.unwrap();
32+
assert_eq!(response.value, "123");
33+
}
34+
35+
#[tokio::test]
36+
async fn test_run_python() {
37+
let app = mock_app_handle().await;
38+
let payload = StringRequest {
39+
value: "new_var = 456".into(),
40+
};
41+
app.run_python(payload).await.unwrap();
42+
43+
// Verify the code was run by reading the variable back
44+
let read_payload = StringRequest {
45+
value: "new_var".into(),
46+
};
47+
let response = app.read_variable(read_payload).await.unwrap();
48+
assert_eq!(response.value, "456");
49+
}
50+
51+
#[tokio::test]
52+
async fn test_register_and_call_function() {
53+
let app = mock_app_handle().await;
54+
55+
// 1. Register the function
56+
let register_payload = RegisterRequest {
57+
python_function_call: "my_func".into(),
58+
number_of_args: Some(2),
59+
};
60+
app.register_function(register_payload).await.unwrap();
61+
62+
// 2. Call the registered function
63+
let call_payload = RunRequest {
64+
function_name: "my_func".into(),
65+
args: vec![serde_json::json!(10), serde_json::json!(20)],
66+
};
67+
let response = app.call_function(call_payload).await.unwrap();
68+
assert_eq!(response.value, "30");
69+
}
70+
71+
#[tokio::test]
72+
async fn test_call_unregistered_function_fails() {
73+
let app = mock_app_handle().await;
74+
let call_payload = RunRequest {
75+
function_name: "unregistered_func".into(),
76+
args: vec![],
77+
};
78+
let result = app.call_function(call_payload).await;
79+
assert!(result.is_err());
80+
let err_msg = result.unwrap_err().to_string();
81+
assert!(err_msg.contains("Function unregistered_func has not been registered yet"));
82+
}
83+
84+
#[tokio::test]
85+
async fn test_register_after_call_fails() {
86+
let app = mock_app_handle().await;
87+
88+
// 1. Register and call a function to set the INIT_BLOCKED flag
89+
let register_payload = RegisterRequest {
90+
python_function_call: "my_func".into(),
91+
number_of_args: Some(2),
92+
};
93+
app.register_function(register_payload).await.unwrap();
94+
let call_payload = RunRequest {
95+
function_name: "my_func".into(),
96+
args: vec![serde_json::json!(1), serde_json::json!(2)],
97+
};
98+
app.call_function(call_payload).await.unwrap();
99+
100+
// 2. Attempt to register another function, which should now fail
101+
let second_register_payload = RegisterRequest {
102+
python_function_call: "my_var".into(), // can be anything
103+
number_of_args: None,
104+
};
105+
let result = app.register_function(second_register_payload).await;
106+
assert!(result.is_err());
107+
assert!(result.unwrap_err().to_string().contains("Cannot register after function called"));
108+
}

0 commit comments

Comments
 (0)