195 lines
5.7 KiB
C#
195 lines
5.7 KiB
C#
using FluentAssertions;
|
|
using Game.Blackjack;
|
|
using OECS;
|
|
using Xunit;
|
|
|
|
namespace Game.Blackjack.Tests;
|
|
|
|
public class GameFlowTests
|
|
{
|
|
[Fact]
|
|
public void NewGame_StartsInBettingPhase()
|
|
{
|
|
var (world, _) = TestHelpers.SetupGame();
|
|
|
|
var state = world.ReadSingleton<GameState>();
|
|
state.Phase.Should().Be(GamePhase.Betting);
|
|
state.Chips.Should().Be(100);
|
|
state.RoundNumber.Should().Be(1);
|
|
}
|
|
|
|
[Fact]
|
|
public void PlaceBet_AdvancesToDealing()
|
|
{
|
|
var (world, group) = TestHelpers.SetupGame();
|
|
|
|
world.Commands.Enqueue(new PlaceBetCommand { Amount = 10 });
|
|
group.RunLogical();
|
|
|
|
var state = world.ReadSingleton<GameState>();
|
|
state.Phase.Should().Be(GamePhase.PlayerTurn);
|
|
state.CurrentBet.Should().Be(10);
|
|
state.Chips.Should().Be(90);
|
|
}
|
|
|
|
[Fact]
|
|
public void PlaceBet_RejectsInsufficientChips()
|
|
{
|
|
var (world, group) = TestHelpers.SetupGame();
|
|
|
|
world.Commands.Enqueue(new PlaceBetCommand { Amount = 200 });
|
|
group.RunLogical();
|
|
|
|
var state = world.ReadSingleton<GameState>();
|
|
state.Phase.Should().Be(GamePhase.Betting);
|
|
state.Chips.Should().Be(100);
|
|
}
|
|
|
|
[Fact]
|
|
public void PlaceBet_RejectsZeroOrNegative()
|
|
{
|
|
var (world, group) = TestHelpers.SetupGame();
|
|
|
|
world.Commands.Enqueue(new PlaceBetCommand { Amount = 0 });
|
|
group.RunLogical();
|
|
world.ReadSingleton<GameState>().Phase.Should().Be(GamePhase.Betting);
|
|
|
|
world.Commands.Enqueue(new PlaceBetCommand { Amount = -5 });
|
|
group.RunLogical();
|
|
world.ReadSingleton<GameState>().Phase.Should().Be(GamePhase.Betting);
|
|
}
|
|
|
|
[Fact]
|
|
public void Dealing_CreatesDeckAndHands()
|
|
{
|
|
var (world, group) = TestHelpers.SetupGame();
|
|
|
|
world.Commands.Enqueue(new PlaceBetCommand { Amount = 10 });
|
|
group.RunLogical();
|
|
|
|
TestHelpers.FindEntity<Deck>(world).Should().NotBe(Entity.Null);
|
|
TestHelpers.FindEntity<PlayerHand>(world).Should().NotBe(Entity.Null);
|
|
TestHelpers.FindEntity<DealerHand>(world).Should().NotBe(Entity.Null);
|
|
}
|
|
|
|
[Fact]
|
|
public void Dealing_DealsTwoCardsToEach()
|
|
{
|
|
var (world, group) = TestHelpers.SetupGame();
|
|
|
|
world.Commands.Enqueue(new PlaceBetCommand { Amount = 10 });
|
|
group.RunLogical();
|
|
|
|
var playerHand = TestHelpers.FindEntity<PlayerHand>(world);
|
|
var dealerHand = TestHelpers.FindEntity<DealerHand>(world);
|
|
|
|
TestHelpers.CountCardsInHand(world, playerHand).Should().Be(2);
|
|
TestHelpers.CountCardsInHand(world, dealerHand).Should().Be(2);
|
|
}
|
|
|
|
[Fact]
|
|
public void Hit_DrawsOneCard()
|
|
{
|
|
var (world, group) = TestHelpers.SetupGame();
|
|
|
|
world.Commands.Enqueue(new PlaceBetCommand { Amount = 10 });
|
|
group.RunLogical();
|
|
|
|
var playerHand = TestHelpers.FindEntity<PlayerHand>(world);
|
|
var before = TestHelpers.CountCardsInHand(world, playerHand);
|
|
|
|
world.Commands.Enqueue(new HitCommand());
|
|
group.RunLogical();
|
|
|
|
var after = TestHelpers.CountCardsInHand(world, playerHand);
|
|
after.Should().Be(before + 1);
|
|
}
|
|
|
|
[Fact]
|
|
public void Stand_AdvancesToDealerTurn()
|
|
{
|
|
var (world, group) = TestHelpers.SetupGame();
|
|
|
|
world.Commands.Enqueue(new PlaceBetCommand { Amount = 10 });
|
|
group.RunLogical();
|
|
|
|
world.Commands.Enqueue(new StandCommand());
|
|
group.RunLogical();
|
|
|
|
var state = world.ReadSingleton<GameState>();
|
|
state.Phase.Should().Be(GamePhase.RoundOver);
|
|
}
|
|
|
|
[Fact]
|
|
public void NewRound_ResetsPhase()
|
|
{
|
|
var (world, group) = TestHelpers.SetupGame();
|
|
|
|
world.Commands.Enqueue(new PlaceBetCommand { Amount = 10 });
|
|
group.RunLogical();
|
|
world.Commands.Enqueue(new StandCommand());
|
|
group.RunLogical();
|
|
|
|
world.Commands.Enqueue(new NewRoundCommand());
|
|
group.RunLogical();
|
|
|
|
var state = world.ReadSingleton<GameState>();
|
|
state.Phase.Should().Be(GamePhase.Betting);
|
|
state.Result.Should().Be(RoundResult.None);
|
|
}
|
|
|
|
[Fact]
|
|
public void DeterministicSeed_ProducesSameDeal()
|
|
{
|
|
var (world1, group1) = TestHelpers.SetupGame(seed: 42);
|
|
world1.Commands.Enqueue(new PlaceBetCommand { Amount = 10 });
|
|
group1.RunLogical();
|
|
var cards1 = TestHelpers.GetAllCards(world1);
|
|
|
|
var (world2, group2) = TestHelpers.SetupGame(seed: 42);
|
|
world2.Commands.Enqueue(new PlaceBetCommand { Amount = 10 });
|
|
group2.RunLogical();
|
|
var cards2 = TestHelpers.GetAllCards(world2);
|
|
|
|
cards1.Should().Equal(cards2);
|
|
}
|
|
|
|
[Fact]
|
|
public void PlayerBust_LosesBet()
|
|
{
|
|
var (world, group) = TestHelpers.SetupGame(seed: 12345);
|
|
|
|
world.Commands.Enqueue(new PlaceBetCommand { Amount = 10 });
|
|
group.RunLogical();
|
|
|
|
while (world.ReadSingleton<GameState>().Phase == GamePhase.PlayerTurn)
|
|
{
|
|
world.Commands.Enqueue(new HitCommand());
|
|
group.RunLogical();
|
|
}
|
|
|
|
var state = world.ReadSingleton<GameState>();
|
|
state.Phase.Should().Be(GamePhase.RoundOver);
|
|
}
|
|
|
|
[Fact]
|
|
public void Serialization_RoundTrips()
|
|
{
|
|
var (world, group) = TestHelpers.SetupGame(seed: 42);
|
|
|
|
world.Commands.Enqueue(new PlaceBetCommand { Amount = 10 });
|
|
group.RunLogical();
|
|
|
|
using var stream = new MemoryStream();
|
|
WorldSerializer.Save(world, stream);
|
|
stream.Position = 0;
|
|
|
|
var world2 = new World();
|
|
WorldSerializer.Load(world2, stream);
|
|
|
|
var state = world2.ReadSingleton<GameState>();
|
|
state.Chips.Should().Be(90);
|
|
state.CurrentBet.Should().Be(10);
|
|
state.RoundNumber.Should().Be(1);
|
|
}
|
|
} |