fix: enforce executable movement state
This commit is contained in:
@@ -7,8 +7,10 @@ namespace BattleForge\Tests\Unit\Domain;
|
||||
use BattleForge\Domain\Battlefield;
|
||||
use BattleForge\Domain\MatchState;
|
||||
use BattleForge\Domain\Position;
|
||||
use BattleForge\Domain\Terrain;
|
||||
use BattleForge\Domain\UnitState;
|
||||
use InvalidArgumentException;
|
||||
use PHPUnit\Framework\Attributes\DataProvider;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
final class MatchStateTest extends TestCase
|
||||
@@ -24,6 +26,67 @@ final class MatchStateTest extends TestCase
|
||||
);
|
||||
}
|
||||
|
||||
public function testItRejectsAUnitOutsideTheBattlefield(): void
|
||||
{
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
$this->expectExceptionMessage('Unit alpha-1 is outside the battlefield.');
|
||||
|
||||
new MatchState(
|
||||
new Battlefield(8, 8),
|
||||
[$this->unit('alpha-1', 'alpha', new Position(8, 0))],
|
||||
'alpha',
|
||||
);
|
||||
}
|
||||
|
||||
#[DataProvider('impassableTerrainProvider')]
|
||||
public function testItRejectsALivingUnitOnImpassableTerrain(Terrain $terrain): void
|
||||
{
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
$this->expectExceptionMessage('Living unit alpha-1 must stand on passable terrain.');
|
||||
|
||||
new MatchState(
|
||||
new Battlefield(8, 8, ['0:0' => $terrain]),
|
||||
[$this->unit('alpha-1', 'alpha')],
|
||||
'alpha',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return iterable<string, array{Terrain}>
|
||||
*/
|
||||
public static function impassableTerrainProvider(): iterable
|
||||
{
|
||||
yield 'water' => [Terrain::Water];
|
||||
yield 'blocking' => [Terrain::Blocking];
|
||||
}
|
||||
|
||||
public function testItRejectsLivingUnitsAtTheSamePosition(): void
|
||||
{
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
$this->expectExceptionMessage('Living units cannot share position 0:0.');
|
||||
|
||||
new MatchState(
|
||||
new Battlefield(8, 8),
|
||||
[$this->unit('alpha-1', 'alpha'), $this->unit('bravo-1', 'bravo')],
|
||||
'alpha',
|
||||
);
|
||||
}
|
||||
|
||||
public function testItAcceptsLivingAndDefeatedUnitsAtTheSamePosition(): void
|
||||
{
|
||||
$match = new MatchState(
|
||||
new Battlefield(8, 8),
|
||||
[
|
||||
$this->unit('alpha-1', 'alpha'),
|
||||
$this->unit('bravo-1', 'bravo', health: 0),
|
||||
],
|
||||
'alpha',
|
||||
);
|
||||
|
||||
self::assertSame('0:0', $match->unit('alpha-1')->position->key());
|
||||
self::assertSame('0:0', $match->unit('bravo-1')->position->key());
|
||||
}
|
||||
|
||||
public function testItRejectsAnUnknownUnitLookup(): void
|
||||
{
|
||||
$match = $this->match();
|
||||
@@ -169,14 +232,21 @@ final class MatchStateTest extends TestCase
|
||||
{
|
||||
return new MatchState(
|
||||
new Battlefield(8, 8),
|
||||
[$this->unit('alpha-1', 'alpha'), $this->unit('bravo-1', 'bravo')],
|
||||
[
|
||||
$this->unit('alpha-1', 'alpha'),
|
||||
$this->unit('bravo-1', 'bravo', new Position(7, 7)),
|
||||
],
|
||||
'alpha',
|
||||
actionLog: $actionLog,
|
||||
);
|
||||
}
|
||||
|
||||
private function unit(string $id, string $teamId): UnitState
|
||||
{
|
||||
return new UnitState($id, $teamId, new Position(0, 0), 10, 10, 4, 2, 4, 2);
|
||||
private function unit(
|
||||
string $id,
|
||||
string $teamId,
|
||||
?Position $position = null,
|
||||
int $health = 10,
|
||||
): UnitState {
|
||||
return new UnitState($id, $teamId, $position ?? new Position(0, 0), 10, $health, 4, 2, 4, 2);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user