Chessistics/chessistics-tests/Simulation/UndoTests.cs

121 lines
3.4 KiB
C#
Raw Normal View History

using Chessistics.Engine.Commands;
using Chessistics.Engine.Events;
using Chessistics.Engine.Model;
using Chessistics.Tests.Helpers;
using Xunit;
namespace Chessistics.Tests.Simulation;
public class UndoTests
{
private SimHelper CreateSim()
{
var level = new BoardBuilder(4, 4)
.WithProduction(0, 0, "Scierie", CargoType.Wood, amount: 1)
.WithDemand(3, 0, "Depot", CargoType.Wood, 3, 30)
.WithStock(PieceKind.Rook, 3)
.Build();
return SimHelper.FromLevel(level);
}
[Fact]
public void Undo_EmptyStack_ReturnsNoEvents()
{
var sim = CreateSim();
Assert.False(sim.Sim.CanUndo);
Assert.Empty(sim.Sim.Undo());
}
[Fact]
public void Undo_AfterPlace_RestoresPreviousState()
{
var sim = CreateSim();
Assert.False(sim.Sim.CanUndo);
sim.Place(PieceKind.Rook, (0, 0), (1, 0));
Assert.Single(sim.Snapshot.Pieces);
Assert.True(sim.Sim.CanUndo);
var events = sim.Sim.Undo();
Assert.Single(events);
Assert.IsType<StateRestoredEvent>(events[0]);
Assert.Empty(sim.Snapshot.Pieces);
Assert.Equal(3, sim.Snapshot.RemainingStock[PieceKind.Rook]);
Assert.False(sim.Sim.CanUndo);
}
[Fact]
public void Undo_AfterRemove_RestoresPiece()
{
var sim = CreateSim();
sim.Place(PieceKind.Rook, (0, 0), (1, 0));
var pieceId = sim.Snapshot.Pieces[0].Id;
sim.Remove(pieceId);
Assert.Empty(sim.Snapshot.Pieces);
sim.Sim.Undo();
Assert.Single(sim.Snapshot.Pieces);
Assert.Equal(pieceId, sim.Snapshot.Pieces[0].Id);
}
[Fact]
public void Undo_MultipleMutations_UndoneInReverseOrder()
{
var sim = CreateSim();
sim.Place(PieceKind.Rook, (0, 0), (1, 0));
sim.Place(PieceKind.Rook, (0, 1), (1, 1));
sim.Place(PieceKind.Rook, (0, 2), (1, 2));
Assert.Equal(3, sim.Snapshot.Pieces.Count);
sim.Sim.Undo();
Assert.Equal(2, sim.Snapshot.Pieces.Count);
sim.Sim.Undo();
Assert.Single(sim.Snapshot.Pieces);
sim.Sim.Undo();
Assert.Empty(sim.Snapshot.Pieces);
Assert.False(sim.Sim.CanUndo);
}
[Fact]
public void Undo_RejectedPlacement_DoesNotCheckpoint()
{
var sim = CreateSim();
// Invalid placement (off the board) — should be rejected and not undoable
sim.Place(PieceKind.Rook, (99, 99), (100, 100));
Assert.False(sim.Sim.CanUndo);
}
[Fact]
public void Undo_AfterSimulationStep_RewindsTurnsToo()
{
// Placing then stepping means the sim advanced. Undo of the placement
// should restore the pre-placement state — which also means turn 0.
var sim = CreateSim();
sim.Place(PieceKind.Rook, (0, 0), (1, 0));
sim.Step();
sim.Step();
Assert.Equal(2, sim.Snapshot.TurnNumber);
sim.Sim.Undo();
Assert.Equal(0, sim.Snapshot.TurnNumber);
Assert.Empty(sim.Snapshot.Pieces);
}
[Fact]
public void QuickLoad_ClearsUndoStack()
{
var sim = CreateSim();
sim.Place(PieceKind.Rook, (0, 0), (1, 0));
sim.Sim.QuickSave();
sim.Place(PieceKind.Rook, (0, 1), (1, 1));
// Two undoable mutations so far — load clears the stack
sim.Sim.QuickLoad();
Assert.False(sim.Sim.CanUndo);
}
}