use std::path::PathBuf; use std::time::{SystemTime, UNIX_EPOCH}; use app_tauri_lib::{commands, state::AppState}; use serde_json::{json, Value}; use tauri::test::{get_ipc_response, mock_builder, mock_context, noop_assets, INVOKE_KEY}; fn test_app_data_dir(label: &str) -> PathBuf { let nanos = SystemTime::now() .duration_since(UNIX_EPOCH) .unwrap() .as_nanos(); std::env::temp_dir().join(format!( "idea-managed-temp-handlers-{label}-{}-{nanos}", std::process::id() )) } fn invoke_command>>( webview: &W, command: &str, body: Value, ) -> Result { get_ipc_response( webview, tauri::webview::InvokeRequest { cmd: command.to_owned(), callback: tauri::ipc::CallbackFn(0), error: tauri::ipc::CallbackFn(1), url: "tauri://localhost".parse().unwrap(), body: tauri::ipc::InvokeBody::Json(body), headers: Default::default(), invoke_key: INVOKE_KEY.to_owned(), }, ) .map(|body| body.deserialize::().unwrap()) } #[test] fn managed_temp_handlers_round_trip_via_tauri_invoke_handler() { let app_data = test_app_data_dir("round-trip"); let app = mock_builder() .manage(AppState::build(app_data.clone())) .invoke_handler(tauri::generate_handler![ commands::managed_temp_allocate, commands::managed_temp_resolve, commands::managed_temp_release, commands::managed_temp_gc, ]) .build(mock_context(noop_assets())) .expect("mock app builds"); let webview = tauri::WebviewWindowBuilder::new(&app, "main", Default::default()) .build() .expect("mock webview builds"); let allocated = invoke_command( &webview, "managed_temp_allocate", json!({ "request": { "kind": "directory", "purpose": "scratch" } }), ) .expect("allocate must succeed"); let handle = allocated["lease"]["handle"] .as_str() .expect("opaque handle") .to_owned(); let path = allocated["lease"]["path"] .as_str() .expect("lease path") .to_owned(); assert!( path.contains("/managed-tmp/"), "real AppState store should allocate under managed-tmp, got {path}" ); let resolved = invoke_command( &webview, "managed_temp_resolve", json!({ "request": { "handle": handle } }), ) .expect("resolve must succeed while lease is active"); assert_eq!(resolved["lease"]["path"], allocated["lease"]["path"]); assert_eq!(resolved["lease"]["handle"], allocated["lease"]["handle"]); let released = invoke_command( &webview, "managed_temp_release", json!({ "request": { "handle": handle } }), ) .expect("release must succeed"); assert_eq!(released["lease"]["handle"], allocated["lease"]["handle"]); assert_eq!(released["lease"]["state"], json!("released")); let err = invoke_command( &webview, "managed_temp_resolve", json!({ "request": { "handle": handle } }), ) .expect_err("resolve after release must fail"); assert_eq!(err["code"], "NOT_FOUND"); let gc = invoke_command(&webview, "managed_temp_gc", json!({})) .expect("gc must succeed after release"); assert_eq!(gc["deleted"], 1); std::fs::remove_dir_all(app_data).ok(); }