Files
galaxy/crates/settings_value/tests/derive_tests.rs
T

165 lines
4.7 KiB
Rust

use serde::{Deserialize, Serialize};
use serde_json::json;
use settings_value::SettingsValue;
// -- struct-level #[serde(default)] -------------------------------------------
#[derive(Debug, Default, PartialEq, Serialize, Deserialize, SettingsValue)]
#[serde(default)]
struct StructWithContainerDefault {
name: String,
count: u32,
}
#[test]
fn container_default_missing_field_uses_default() {
let json = json!({"name": "hello"});
let result = StructWithContainerDefault::from_file_value(&json).unwrap();
assert_eq!(result.name, "hello");
assert_eq!(result.count, 0);
}
#[test]
fn container_default_empty_object_uses_all_defaults() {
let json = json!({});
let result = StructWithContainerDefault::from_file_value(&json).unwrap();
assert_eq!(result, StructWithContainerDefault::default());
}
#[test]
fn container_default_all_fields_present() {
let json = json!({"name": "hello", "count": 42});
let result = StructWithContainerDefault::from_file_value(&json).unwrap();
assert_eq!(result.name, "hello");
assert_eq!(result.count, 42);
}
#[test]
fn container_default_round_trip() {
let val = StructWithContainerDefault {
name: "test".into(),
count: 7,
};
let file_val = val.to_file_value();
let back = StructWithContainerDefault::from_file_value(&file_val).unwrap();
assert_eq!(back, val);
}
// -- struct-level default with non-Default field type -------------------------
/// An enum that does NOT implement Default.
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, SettingsValue)]
enum Mode {
Off,
On,
}
#[derive(Debug, PartialEq, Serialize, Deserialize, SettingsValue)]
enum ModeWithAliases {
#[serde(alias = "LegacyOff")]
Off,
#[serde(alias = "LegacyLabel")]
Label(String),
#[serde(alias = "LegacyPair")]
Pair(String, u32),
#[serde(alias = "LegacyNamed")]
Named { label: String },
}
#[test]
fn enum_aliases_deserialize_from_file_values() {
assert_eq!(
ModeWithAliases::from_file_value(&json!("legacy_off")),
Some(ModeWithAliases::Off)
);
assert_eq!(
ModeWithAliases::from_file_value(&json!({"legacy_label": "hello"})),
Some(ModeWithAliases::Label("hello".to_string()))
);
assert_eq!(
ModeWithAliases::from_file_value(&json!({"legacy_pair": ["hello", 42]})),
Some(ModeWithAliases::Pair("hello".to_string(), 42))
);
assert_eq!(
ModeWithAliases::from_file_value(&json!({"legacy_named": {"label": "hello"}})),
Some(ModeWithAliases::Named {
label: "hello".to_string()
})
);
}
#[test]
fn enum_aliases_do_not_change_serialized_file_values() {
assert_eq!(ModeWithAliases::Off.to_file_value(), json!("off"));
assert_eq!(
ModeWithAliases::Label("hello".to_string()).to_file_value(),
json!({"label": "hello"})
);
assert_eq!(
ModeWithAliases::Pair("hello".to_string(), 42).to_file_value(),
json!({"pair": ["hello", 42]})
);
assert_eq!(
ModeWithAliases::Named {
label: "hello".to_string()
}
.to_file_value(),
json!({"named": {"label": "hello"}})
);
}
#[derive(Debug, PartialEq, Serialize, Deserialize, SettingsValue)]
#[serde(default)]
struct StructWithNonDefaultField {
mode: Mode,
label: String,
}
impl Default for StructWithNonDefaultField {
fn default() -> Self {
Self {
mode: Mode::Off,
label: String::new(),
}
}
}
#[test]
fn container_default_non_default_field_uses_struct_default() {
let json = json!({"label": "hello"});
let result = StructWithNonDefaultField::from_file_value(&json).unwrap();
assert_eq!(result.mode, Mode::Off);
assert_eq!(result.label, "hello");
}
#[test]
fn container_default_non_default_field_present() {
// SettingsValue derive converts variant names to snake_case.
let json = json!({"mode": "on", "label": "hello"});
let result = StructWithNonDefaultField::from_file_value(&json).unwrap();
assert_eq!(result.mode, Mode::On);
assert_eq!(result.label, "hello");
}
// -- without struct-level default, missing fields should fail -----------------
#[derive(Debug, PartialEq, Serialize, Deserialize, SettingsValue)]
struct StructWithoutDefault {
name: String,
count: u32,
}
#[test]
fn no_container_default_missing_field_returns_none() {
let json = json!({"name": "hello"});
assert!(StructWithoutDefault::from_file_value(&json).is_none());
}
#[test]
fn no_container_default_all_present_succeeds() {
let json = json!({"name": "hello", "count": 42});
let result = StructWithoutDefault::from_file_value(&json).unwrap();
assert_eq!(result.name, "hello");
assert_eq!(result.count, 42);
}