mod application; mod commands; mod domain; mod errors; mod events; pub use application::*; pub use commands::*; pub use domain::*; pub use errors::*; pub use events::*; #[cfg(test)] mod tests { use super::*; use module_inventory::{InventoryEquipmentSlot, InventoryItemRarity, InventoryItemSourceKind}; #[test] fn build_treasure_record_snapshot_accepts_minimal_contract() { let snapshot = build_treasure_record_snapshot(TreasureResolveInput { treasure_record_id: "treasure_001".to_string(), runtime_session_id: "runtime_001".to_string(), story_session_id: "storysess_001".to_string(), actor_user_id: "user_001".to_string(), encounter_id: "enc_001".to_string(), encounter_name: "旧钟楼暗格".to_string(), scene_id: Some("scene_001".to_string()), scene_name: Some("旧钟楼".to_string()), action: TreasureInteractionAction::Inspect, reward_items: vec![RuntimeItemRewardItemSnapshot { item_id: "item_001".to_string(), category: "遗物".to_string(), item_name: "铜钥残片".to_string(), description: Some("带着旧钟楼铜锈味的钥片。".to_string()), quantity: 1, rarity: RuntimeItemRewardItemRarity::Rare, tags: vec!["钥片".to_string(), "钟楼".to_string()], stackable: false, stack_key: String::new(), equipment_slot_id: None, }], reward_hp: 3, reward_mana: 2, reward_currency: 10, story_hint: Some("发现了旧机关的回响。".to_string()), created_at_micros: 10, updated_at_micros: 10, }) .expect("minimal treasure snapshot should succeed"); assert_eq!(snapshot.treasure_record_id, "treasure_001"); assert_eq!(snapshot.reward_items.len(), 1); } #[test] fn build_inventory_item_snapshot_from_reward_item_keeps_inventory_fields() { let item = build_inventory_item_snapshot_from_reward_item( "treasure_001", RuntimeItemRewardItemSnapshot { item_id: "item_001".to_string(), category: "遗物".to_string(), item_name: "铜钥残片".to_string(), description: Some("带着旧钟楼铜锈味的钥片。".to_string()), quantity: 1, rarity: RuntimeItemRewardItemRarity::Rare, tags: vec!["钥片".to_string(), "钟楼".to_string()], stackable: false, stack_key: String::new(), equipment_slot_id: Some(RuntimeItemEquipmentSlot::Relic), }, ) .expect("reward item should convert into inventory item"); assert_eq!(item.item_id, "item_001"); assert_eq!(item.category, "遗物"); assert_eq!(item.name, "铜钥残片"); assert_eq!(item.rarity, InventoryItemRarity::Rare); assert_eq!(item.stack_key, "item_001"); assert_eq!(item.equipment_slot_id, Some(InventoryEquipmentSlot::Relic)); assert_eq!(item.source_kind, InventoryItemSourceKind::TreasureReward); assert_eq!(item.source_reference_id, Some("treasure_001".to_string())); } #[test] fn normalize_reward_item_snapshot_trims_and_fills_stack_key() { let item = normalize_reward_item_snapshot(RuntimeItemRewardItemSnapshot { item_id: " item_001 ".to_string(), category: " 遗物 ".to_string(), item_name: " 铜钥残片 ".to_string(), description: Some(" 带着旧钟楼铜锈味的钥片。 ".to_string()), quantity: 1, rarity: RuntimeItemRewardItemRarity::Rare, tags: vec![" 钥片 ".to_string(), "".to_string(), "钟楼".to_string()], stackable: false, stack_key: String::new(), equipment_slot_id: None, }) .expect("reward item should normalize"); assert_eq!(item.item_id, "item_001"); assert_eq!(item.category, "遗物"); assert_eq!(item.item_name, "铜钥残片"); assert_eq!( item.description.as_deref(), Some("带着旧钟楼铜锈味的钥片。") ); assert_eq!(item.tags, vec!["钥片".to_string(), "钟楼".to_string()]); assert_eq!(item.stack_key, "item_001"); } }