mirror of
https://github.com/Xevion/Pac-Man.git
synced 2025-12-06 03:15:48 -06:00
227 lines
8.0 KiB
Rust
227 lines
8.0 KiB
Rust
use bevy_ecs::entity::Entity;
|
|
use pacman::{
|
|
events::CollisionTrigger,
|
|
systems::{EntityType, GhostState, Position, ScoreResource},
|
|
};
|
|
use speculoos::prelude::*;
|
|
|
|
mod common;
|
|
|
|
#[test]
|
|
fn test_calculate_score_for_item() {
|
|
assert_that(&(EntityType::Pellet.score_value() < EntityType::PowerPellet.score_value())).is_true();
|
|
assert_that(&EntityType::Pellet.score_value().is_some()).is_true();
|
|
assert_that(&EntityType::PowerPellet.score_value().is_some()).is_true();
|
|
assert_that(&EntityType::Player.score_value().is_none()).is_true();
|
|
assert_that(&EntityType::Ghost.score_value().is_none()).is_true();
|
|
}
|
|
|
|
#[test]
|
|
fn test_is_collectible_item() {
|
|
// Collectible
|
|
assert_that(&EntityType::Pellet.is_collectible()).is_true();
|
|
assert_that(&EntityType::PowerPellet.is_collectible()).is_true();
|
|
|
|
// Non-collectible
|
|
assert_that(&EntityType::Player.is_collectible()).is_false();
|
|
assert_that(&EntityType::Ghost.is_collectible()).is_false();
|
|
}
|
|
|
|
#[test]
|
|
fn test_item_system_pellet_collection() {
|
|
let (mut world, mut _schedule) = common::create_test_world();
|
|
let pellet = common::spawn_test_item(&mut world, 1, EntityType::Pellet);
|
|
|
|
// Send collision event
|
|
common::trigger_collision(&mut world, CollisionTrigger::ItemCollision { item: pellet });
|
|
|
|
world.flush();
|
|
|
|
// Check that score was updated
|
|
let score = world.resource_mut::<ScoreResource>();
|
|
assert_that(&score.0).is_equal_to(10);
|
|
|
|
// Check that the pellet was despawned (query should return empty)
|
|
let item_count = world
|
|
.query::<&EntityType>()
|
|
.iter(&world)
|
|
.filter(|&entity_type| matches!(entity_type, EntityType::Pellet))
|
|
.count();
|
|
assert_that(&item_count).is_equal_to(0);
|
|
}
|
|
|
|
#[test]
|
|
fn test_item_system_power_pellet_collection() {
|
|
let (mut world, mut _schedule) = common::create_test_world();
|
|
let power_pellet = common::spawn_test_item(&mut world, 1, EntityType::PowerPellet);
|
|
|
|
common::trigger_collision(&mut world, CollisionTrigger::ItemCollision { item: power_pellet });
|
|
|
|
world.flush();
|
|
|
|
// Check that score was updated with power pellet value
|
|
let score = world.resource::<ScoreResource>();
|
|
assert_that(&score.0).is_equal_to(50);
|
|
|
|
// Check that the power pellet was despawned (query should return empty)
|
|
let item_count = world
|
|
.query::<&EntityType>()
|
|
.iter(&world)
|
|
.filter(|&entity_type| matches!(entity_type, EntityType::PowerPellet))
|
|
.count();
|
|
assert_that(&item_count).is_equal_to(0);
|
|
}
|
|
|
|
#[test]
|
|
fn test_item_system_multiple_collections() {
|
|
let (mut world, mut _schedule) = common::create_test_world();
|
|
let pellet1 = common::spawn_test_item(&mut world, 1, EntityType::Pellet);
|
|
let pellet2 = common::spawn_test_item(&mut world, 2, EntityType::Pellet);
|
|
let power_pellet = common::spawn_test_item(&mut world, 3, EntityType::PowerPellet);
|
|
|
|
// Send multiple collision events
|
|
common::trigger_collision(&mut world, CollisionTrigger::ItemCollision { item: pellet1 });
|
|
common::trigger_collision(&mut world, CollisionTrigger::ItemCollision { item: pellet2 });
|
|
common::trigger_collision(&mut world, CollisionTrigger::ItemCollision { item: power_pellet });
|
|
|
|
world.flush();
|
|
|
|
// Check final score: 2 pellets (20) + 1 power pellet (50) = 70
|
|
let score = world.resource::<ScoreResource>();
|
|
assert_that(&score.0).is_equal_to(70);
|
|
|
|
// Check that all items were despawned
|
|
let pellet_count = world
|
|
.query::<&EntityType>()
|
|
.iter(&world)
|
|
.filter(|&entity_type| matches!(entity_type, EntityType::Pellet))
|
|
.count();
|
|
let power_pellet_count = world
|
|
.query::<&EntityType>()
|
|
.iter(&world)
|
|
.filter(|&entity_type| matches!(entity_type, EntityType::PowerPellet))
|
|
.count();
|
|
assert_that(&pellet_count).is_equal_to(0);
|
|
assert_that(&power_pellet_count).is_equal_to(0);
|
|
}
|
|
|
|
#[test]
|
|
fn test_item_system_ignores_non_item_collisions() {
|
|
let (mut world, mut _schedule) = common::create_test_world();
|
|
|
|
// Create a ghost entity (not an item)
|
|
let ghost = world.spawn((Position::Stopped { node: 2 }, EntityType::Ghost)).id();
|
|
|
|
// Initial score
|
|
let initial_score = world.resource::<ScoreResource>().0;
|
|
|
|
// Send collision event between pacman and ghost
|
|
common::trigger_collision(&mut world, CollisionTrigger::ItemCollision { item: ghost });
|
|
|
|
world.flush();
|
|
|
|
// Score should remain unchanged
|
|
let score = world.resource::<ScoreResource>();
|
|
assert_that(&score.0).is_equal_to(initial_score);
|
|
|
|
// Ghost should still exist (not despawned)
|
|
let ghost_count = world
|
|
.query::<&EntityType>()
|
|
.iter(&world)
|
|
.filter(|&entity_type| matches!(entity_type, EntityType::Ghost))
|
|
.count();
|
|
assert_that(&ghost_count).is_equal_to(1);
|
|
}
|
|
|
|
#[test]
|
|
fn test_item_system_no_collision_events() {
|
|
let (mut world, mut _schedule) = common::create_test_world();
|
|
let _pacman = common::spawn_test_pacman(&mut world, 0);
|
|
let _pellet = common::spawn_test_item(&mut world, 1, EntityType::Pellet);
|
|
|
|
let initial_score = world.resource::<ScoreResource>().0;
|
|
|
|
// Run system without any collision events
|
|
world.flush();
|
|
|
|
// Nothing should change
|
|
let score = world.resource::<ScoreResource>();
|
|
assert_that(&score.0).is_equal_to(initial_score);
|
|
let pellet_count = world
|
|
.query::<&EntityType>()
|
|
.iter(&world)
|
|
.filter(|&entity_type| matches!(entity_type, EntityType::Pellet))
|
|
.count();
|
|
assert_that(&pellet_count).is_equal_to(1);
|
|
}
|
|
|
|
#[test]
|
|
fn test_item_system_collision_with_missing_entity() {
|
|
let (mut world, mut _schedule) = common::create_test_world();
|
|
|
|
// Create a fake entity ID that doesn't exist
|
|
let fake_entity = Entity::from_raw(999);
|
|
|
|
common::trigger_collision(&mut world, CollisionTrigger::ItemCollision { item: fake_entity });
|
|
|
|
// System should handle gracefully and not crash
|
|
world.flush();
|
|
// Score should remain unchanged
|
|
let score = world.resource::<ScoreResource>();
|
|
assert_that(&score.0).is_equal_to(0);
|
|
}
|
|
|
|
#[test]
|
|
fn test_item_system_preserves_existing_score() {
|
|
let (mut world, mut _schedule) = common::create_test_world();
|
|
|
|
// Set initial score
|
|
world.insert_resource(ScoreResource(100));
|
|
|
|
let pellet = common::spawn_test_item(&mut world, 1, EntityType::Pellet);
|
|
|
|
common::trigger_collision(&mut world, CollisionTrigger::ItemCollision { item: pellet });
|
|
|
|
world.flush();
|
|
|
|
// Score should be initial + pellet value
|
|
let score = world.resource::<ScoreResource>();
|
|
assert_that(&score.0).is_equal_to(110);
|
|
}
|
|
|
|
#[test]
|
|
fn test_power_pellet_does_not_affect_ghosts_in_eyes_state() {
|
|
let (mut world, mut _schedule) = common::create_test_world();
|
|
let power_pellet = common::spawn_test_item(&mut world, 1, EntityType::PowerPellet);
|
|
|
|
// Spawn a ghost in Eyes state (returning to ghost house)
|
|
let eyes_ghost = common::spawn_test_ghost(&mut world, 2, GhostState::Eyes);
|
|
|
|
// Spawn a ghost in Normal state
|
|
let normal_ghost = common::spawn_test_ghost(&mut world, 3, GhostState::Normal);
|
|
|
|
common::trigger_collision(&mut world, CollisionTrigger::ItemCollision { item: power_pellet });
|
|
|
|
world.flush();
|
|
|
|
// Check that the power pellet was collected and score updated
|
|
let score = world.resource::<ScoreResource>();
|
|
assert_that(&score.0).is_equal_to(50);
|
|
|
|
// Check that the power pellet was despawned
|
|
let power_pellet_count = world
|
|
.query::<&EntityType>()
|
|
.iter(&world)
|
|
.filter(|&entity_type| matches!(entity_type, EntityType::PowerPellet))
|
|
.count();
|
|
assert_that(&power_pellet_count).is_equal_to(0);
|
|
|
|
// Check that the Eyes ghost state was not changed
|
|
let eyes_ghost_state = world.entity(eyes_ghost).get::<GhostState>().unwrap();
|
|
assert_that(&matches!(*eyes_ghost_state, GhostState::Eyes)).is_true();
|
|
|
|
// Check that the Normal ghost state was changed to Frightened
|
|
let normal_ghost_state = world.entity(normal_ghost).get::<GhostState>().unwrap();
|
|
assert_that(&matches!(*normal_ghost_state, GhostState::Frightened { .. })).is_true();
|
|
}
|