use serde::{Deserialize, Serialize};
use serde_json::json;
use tauri_plugin_sync_state::{Error, StateRegistry, SyncState};
#[derive(SyncState, Serialize, Deserialize, Clone, Default, PartialEq, Debug)]
struct Counter {
value: i32,
}
#[derive(SyncState, Serialize, Deserialize, Clone, Default, PartialEq, Debug)]
struct Settings {
dark_mode: bool,
}
#[derive(SyncState, Serialize, Deserialize, Clone, Default)]
#[sync_state(name = "my_custom_key")]
struct Renamed {
x: i32,
}
#[test]
fn derive_defaults_name_to_type_ident() {
assert_eq!(Counter::NAME, "Counter");
assert_eq!(Settings::NAME, "Settings");
}
#[test]
fn derive_honours_custom_name_attribute() {
assert_eq!(Renamed::NAME, "my_custom_key");
}
#[test]
fn insert_then_read_round_trips() {
let registry = StateRegistry::new();
registry.insert(Counter { value: 7 }).unwrap();
let read = registry.read::<Counter>().unwrap();
assert_eq!(read, Counter { value: 7 });
}
#[test]
fn mutate_updates_and_returns_the_new_value() {
let registry = StateRegistry::new();
registry.insert(Counter { value: 1 }).unwrap();
let returned = registry.mutate::<Counter>(|c| c.value += 41).unwrap();
assert_eq!(returned, Counter { value: 42 });
assert_eq!(registry.read::<Counter>().unwrap(), Counter { value: 42 });
}
#[test]
fn distinct_state_types_are_keyed_independently() {
let registry = StateRegistry::new();
registry.insert(Counter { value: 3 }).unwrap();
registry.insert(Settings { dark_mode: true }).unwrap();
assert_eq!(registry.read::<Counter>().unwrap().value, 3);
assert!(registry.read::<Settings>().unwrap().dark_mode);
}
#[test]
fn duplicate_registration_is_rejected() {
let registry = StateRegistry::new();
registry.insert(Counter { value: 0 }).unwrap();
let err = registry.insert(Counter { value: 9 }).unwrap_err();
assert!(matches!(err, Error::DuplicateRegistration(name) if name == "Counter"));
assert_eq!(registry.read::<Counter>().unwrap().value, 0);
}
#[test]
fn reading_an_unregistered_slice_errors() {
let registry = StateRegistry::new();
let err = registry.read::<Counter>().unwrap_err();
assert!(matches!(err, Error::NotFound(name) if name == "Counter"));
}
#[test]
fn mutating_an_unregistered_slice_errors() {
let registry = StateRegistry::new();
let err = registry.mutate::<Counter>(|c| c.value = 1).unwrap_err();
assert!(matches!(err, Error::NotFound(name) if name == "Counter"));
}
#[test]
fn json_bridge_round_trips_by_name() {
let registry = StateRegistry::new();
registry.insert(Counter { value: 5 }).unwrap();
assert_eq!(registry.get_json("Counter").unwrap(), json!({ "value": 5 }));
registry
.set_json("Counter", json!({ "value": 100 }))
.unwrap();
assert_eq!(registry.read::<Counter>().unwrap().value, 100);
assert_eq!(
registry.get_json("Counter").unwrap(),
json!({ "value": 100 })
);
}
#[test]
fn set_json_with_a_mismatched_shape_errors_and_preserves_state() {
let registry = StateRegistry::new();
registry.insert(Counter { value: 5 }).unwrap();
let err = registry
.set_json("Counter", json!({ "value": "not-an-int" }))
.unwrap_err();
assert!(matches!(err, Error::Deserialize(_)));
assert_eq!(registry.read::<Counter>().unwrap().value, 5);
}
#[test]
fn get_and_set_json_on_an_unknown_name_error() {
let registry = StateRegistry::new();
assert!(matches!(
registry.get_json("Nope").unwrap_err(),
Error::NotFound(_)
));
assert!(matches!(
registry.set_json("Nope", json!({})).unwrap_err(),
Error::NotFound(_)
));
}
#[test]
fn contains_reflects_registration() {
let registry = StateRegistry::new();
assert!(!registry.contains("Counter"));
registry.insert(Counter { value: 0 }).unwrap();
assert!(registry.contains("Counter"));
assert!(!registry.contains("Settings"));
}