use bevy::ecs::system::RunSystemOnce; use pomomon_garden::features::config::components::{BerrySeedConfig, GameConfig}; use pomomon_garden::features::grid::components::{Grid, Tile, TileState}; use pomomon_garden::features::inventory::components::ItemType; use pomomon_garden::features::phase::components::{ CurrentPhase, Phase, SessionTracker, TimerSettings, }; use pomomon_garden::features::phase::handle_continue; use pomomon_garden::features::phase::messages::NextPhaseMessage; use pomomon_garden::prelude::*; fn setup_growth_app( grid_width: u32, grid_height: u32, initial_tile_states: &[(u32, u32, TileState)], ) -> App { let mut app = App::new(); app.add_plugins(MinimalPlugins); app.add_plugins(AssetPlugin::default()); app.init_resource::(); app.init_resource::(); // Initialize phase as Finished(Focus) to trigger growth on continue app.insert_resource(CurrentPhase(Phase::Finished { completed_phase: Box::new(Phase::Focus { duration: 25.0 }), })); // GameConfig with known seeds app.insert_resource(GameConfig { berry_seeds: vec![BerrySeedConfig { name: "FastSeed".into(), cost: 1, grants: 1, slice: "".into(), growth_stages: 2, }], ..Default::default() }); // Grid Setup let mut grid_tiles = Vec::with_capacity(grid_width as usize); for x in 0..grid_width { let mut column = Vec::with_capacity(grid_height as usize); for y in 0..grid_height { let entity = app .world_mut() .spawn((Tile { x, y }, TileState::Unclaimed)) .id(); column.push(entity); } grid_tiles.push(column); } app.insert_resource(Grid { width: grid_width, height: grid_height, tiles: grid_tiles, }); for &(x, y, ref state) in initial_tile_states { if let Ok(entity) = app.world().resource::().get_tile((x, y)) { *app.world_mut().get_mut::(entity).unwrap() = state.clone(); } } app.add_message::(); app } #[test] fn test_crop_growth_logic() { let seed_type = ItemType::BerrySeed { name: "FastSeed".into(), }; // Scenario: // (0,0): Watered, Stage 0 -> Should grow to 1, become unwatered // (1,0): Unwatered, Stage 0 -> Should NOT grow, stay unwatered // (2,0): Watered, Stage 2 (Max) -> Should NOT grow, become unwatered let initial_states = vec![ ( 0, 0, TileState::Occupied { seed: seed_type.clone(), watered: true, growth_stage: 0, withered: false, dry_counter: 0, }, ), ( 1, 0, TileState::Occupied { seed: seed_type.clone(), watered: false, growth_stage: 0, withered: false, dry_counter: 0, }, ), ( 2, 0, TileState::Occupied { seed: seed_type.clone(), watered: true, growth_stage: 2, // Max withered: false, dry_counter: 0, }, ), ]; let mut app = setup_growth_app(3, 1, &initial_states); app.world_mut().write_message(NextPhaseMessage); let _ = app.world_mut().run_system_once(handle_continue); let grid = app.world().resource::(); // Check (0,0) let t1 = grid.get_tile((0, 0)).unwrap(); let s1 = app.world().entity(t1).get::().unwrap(); match s1 { TileState::Occupied { watered, growth_stage, .. } => { assert_eq!(*growth_stage, 1, "(0,0) should grow to stage 1"); assert_eq!(*watered, false, "(0,0) should be unwatered"); } _ => panic!("Invalid state at (0,0)"), } // Check (1,0) let t2 = grid.get_tile((1, 0)).unwrap(); let s2 = app.world().entity(t2).get::().unwrap(); match s2 { TileState::Occupied { watered, growth_stage, .. } => { assert_eq!(*growth_stage, 0, "(1,0) should stay at stage 0"); assert_eq!(*watered, false, "(1,0) should be unwatered"); } _ => panic!("Invalid state at (1,0)"), } // Check (2,0) let t3 = grid.get_tile((2, 0)).unwrap(); let s3 = app.world().entity(t3).get::().unwrap(); match s3 { TileState::Occupied { watered, growth_stage, .. } => { assert_eq!(*growth_stage, 2, "(2,0) should stay at stage 2 (max)"); assert_eq!(*watered, false, "(2,0) should be unwatered"); } _ => panic!("Invalid state at (2,0)"), } }