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::{Inventory, ItemStack, ItemType}; use pomomon_garden::features::pom::actions::InteractionAction; use pomomon_garden::prelude::*; fn setup_harvest_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()); // GameConfig app.insert_resource(GameConfig { berry_seeds: vec![BerrySeedConfig { name: "TestSeed".into(), cost: 1, grants: 5, slice: "".into(), growth_stages: 2, }], ..Default::default() }); // Inventory app.init_resource::(); // Grid 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 } #[test] fn test_harvest_fully_grown() { let seed_type = ItemType::BerrySeed { name: "TestSeed".into(), }; let initial_states = vec![( 0, 0, TileState::Occupied { seed: seed_type.clone(), watered: false, growth_stage: 2, // Max withered: false, dry_counter: 0, }, )]; let mut app = setup_harvest_app(1, 1, &initial_states); let _ = app.world_mut().run_system_once( |mut commands: Commands, grid: Res, mut tile_query: Query<&mut TileState>, mut inventory: ResMut, mut item_stack_query: Query<&mut ItemStack>, config: Res| { InteractionAction::Harvest.execute( (0, 0), &grid, &mut tile_query, &mut inventory, &mut item_stack_query, &mut commands, &config, ); }, ); // Check Tile State -> Empty // Wait for commands to apply app.update(); let grid = app.world().resource::(); let tile_entity = grid.get_tile((0, 0)).unwrap(); let tile_state = app.world().entity(tile_entity).get::().unwrap(); assert!(matches!(tile_state, TileState::Empty)); // Check Inventory -> 5 Berries let inventory = app.world().resource::(); assert_eq!(inventory.items.len(), 1); let stack_entity = inventory.items[0]; let stack = app.world().entity(stack_entity).get::().unwrap(); assert_eq!(stack.item_type, ItemType::Berry); assert_eq!(stack.amount, 5); } #[test] fn test_harvest_withered() { let seed_type = ItemType::BerrySeed { name: "TestSeed".into(), }; let initial_states = vec![( 0, 0, TileState::Occupied { seed: seed_type.clone(), watered: false, growth_stage: 1, withered: true, // Withered dry_counter: 0, }, )]; let mut app = setup_harvest_app(1, 1, &initial_states); let _ = app.world_mut().run_system_once( |mut commands: Commands, grid: Res, mut tile_query: Query<&mut TileState>, mut inventory: ResMut, mut item_stack_query: Query<&mut ItemStack>, config: Res| { InteractionAction::Harvest.execute( (0, 0), &grid, &mut tile_query, &mut inventory, &mut item_stack_query, &mut commands, &config, ); }, ); app.update(); // Check Tile State -> Empty let grid = app.world().resource::(); let tile_entity = grid.get_tile((0, 0)).unwrap(); let tile_state = app.world().entity(tile_entity).get::().unwrap(); assert!(matches!(tile_state, TileState::Empty)); // Check Inventory -> Empty (no berries for withered) let inventory = app.world().resource::(); assert!(inventory.items.is_empty()); } #[test] fn test_cannot_harvest_growing() { let seed_type = ItemType::BerrySeed { name: "TestSeed".into(), }; let initial_states = vec![( 0, 0, TileState::Occupied { seed: seed_type.clone(), watered: false, growth_stage: 1, // Growing (Max is 2) withered: false, dry_counter: 0, }, )]; let mut app = setup_harvest_app(1, 1, &initial_states); let _ = app.world_mut().run_system_once( |mut commands: Commands, grid: Res, mut tile_query: Query<&mut TileState>, mut inventory: ResMut, mut item_stack_query: Query<&mut ItemStack>, config: Res| { InteractionAction::Harvest.execute( (0, 0), &grid, &mut tile_query, &mut inventory, &mut item_stack_query, &mut commands, &config, ); }, ); app.update(); // Check Tile State -> Still Occupied let grid = app.world().resource::(); let tile_entity = grid.get_tile((0, 0)).unwrap(); let tile_state = app.world().entity(tile_entity).get::().unwrap(); match tile_state { TileState::Occupied { growth_stage, .. } => { assert_eq!(*growth_stage, 1); } _ => panic!("Should still be occupied"), } // Check Inventory -> Empty let inventory = app.world().resource::(); assert!(inventory.items.is_empty()); }