use bevy::prelude::*; use pomomon_garden::features::config::components::{BerrySeedConfig, GameConfig}; use pomomon_garden::features::core::states::AppState; use pomomon_garden::features::grid::components::{Grid, Tile, TileState}; use pomomon_garden::features::inventory::components::ItemType; use pomomon_garden::features::phase::components::{CurrentPhase, Phase, TimerSettings}; use pomomon_garden::features::wonderevent::components::{Position, WonderEventMessage}; use pomomon_garden::features::wonderevent::{ RequestWonderEvent, WonderEventPlugin, WonderEventSender, }; #[test] fn test_wonder_event_triggers() { let mut app = App::new(); app.add_plugins(MinimalPlugins); app.add_plugins(bevy::state::app::StatesPlugin); app.add_plugins(WonderEventPlugin); app.insert_resource(GameConfig::default()); app.insert_resource(TimerSettings { focus_duration: 60, // 60 seconds short_break_duration: 5, long_break_duration: 15, long_break_interval: 4, }); app.insert_resource(Grid { width: 10, height: 10, tiles: vec![], }); app.init_state::(); let mut next_state = app.world_mut().resource_mut::>(); next_state.set(AppState::GameScreen); app.insert_resource(CurrentPhase(Phase::Focus { duration: 60.0 })); // 1. Full Duration (60.0). No trigger. app.update(); verify_event_count(&mut app, 0); // 2. Half Duration (30.0). Trigger! *app.world_mut().resource_mut::() = CurrentPhase(Phase::Focus { duration: 30.0 }); app.update(); verify_event_count(&mut app, 1); // 3. Less than half (29.0). Already triggered. No new trigger. *app.world_mut().resource_mut::() = CurrentPhase(Phase::Focus { duration: 29.0 }); app.update(); verify_event_count(&mut app, 0); // New events should be 0 // 4. Pause (Focus). Logic should NOT reset trigger. let prev = Box::new(Phase::Focus { duration: 29.0 }); *app.world_mut().resource_mut::() = CurrentPhase(Phase::Paused { previous_phase: prev, }); app.update(); verify_event_count(&mut app, 0); // 5. Resume Focus. Logic should remember it was triggered. *app.world_mut().resource_mut::() = CurrentPhase(Phase::Focus { duration: 29.0 }); app.update(); verify_event_count(&mut app, 0); // 6. Break. Logic should reset trigger. *app.world_mut().resource_mut::() = CurrentPhase(Phase::Break { duration: 5.0 }); app.update(); verify_event_count(&mut app, 0); // 7. New Focus (Half Duration). Logic should trigger again. *app.world_mut().resource_mut::() = CurrentPhase(Phase::Focus { duration: 30.0 }); app.update(); verify_event_count(&mut app, 1); } fn verify_event_count(app: &mut App, expected: usize) { let count = app .world_mut() .resource_mut::>() .drain() .count(); assert_eq!( count, expected, "Expected {} events, found {}", expected, count ); } #[test] fn test_wonder_response_handling() { let mut app = App::new(); app.add_plugins(MinimalPlugins); app.add_plugins(bevy::state::app::StatesPlugin); app.add_plugins(WonderEventPlugin); app.insert_resource(GameConfig { berry_seeds: vec![BerrySeedConfig { name: "TestSeed".to_string(), cost: 1, grants: 1, slice: "Seed1".to_string(), growth_stages: 5, }], ..Default::default() }); app.insert_resource(CurrentPhase(Phase::Focus { duration: 60.0 })); // Setup Grid with an occupied tile let mut tiles = Vec::new(); let column = vec![ app.world_mut() .spawn(( Tile { x: 0, y: 0 }, TileState::Occupied { seed: ItemType::BerrySeed { name: "TestSeed".to_string(), }, watered: true, growth_stage: 1, withered: false, dry_counter: 0, }, )) .id(), ]; tiles.push(column); app.insert_resource(Grid { width: 1, height: 1, tiles, }); app.insert_resource(TimerSettings::default()); // Init State app.init_state::(); let mut next_state = app.world_mut().resource_mut::>(); next_state.set(AppState::GameScreen); // Run update to enter state app.update(); // Send WonderEventMessage directly to the channel let sender = app.world().resource::().0.clone(); sender .send(WonderEventMessage::WonderGranted { position: Position { x: 0, y: 0 }, }) .expect("Failed to send WonderEventMessage"); // Run update to process message app.update(); // Verify Tile State (growth should increase from 1 to 2) let grid = app.world().resource::(); let tile_entity = grid.get_tile((0, 0)).unwrap(); let tile_state = app.world().get::(tile_entity).unwrap(); if let TileState::Occupied { growth_stage, .. } = tile_state { assert_eq!(*growth_stage, 2, "Growth stage should increase to 2"); } else { panic!("Tile state should be Occupied"); } // Verify Floating Text Spawned let mut text_query = app.world_mut().query::<&Text2d>(); assert_eq!( text_query.iter(app.world()).count(), 1, "Should spawn one floating text" ); }