163 lines
5.3 KiB
PHP
163 lines
5.3 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace BattleForge\Tests\Integration;
|
|
|
|
use BattleForge\Http\Handlers\GetBundledScenario;
|
|
use BattleForge\Http\Request;
|
|
use PHPUnit\Framework\TestCase;
|
|
|
|
final class GetBundledScenarioTest extends TestCase
|
|
{
|
|
private string $tmpDir;
|
|
|
|
protected function setUp(): void
|
|
{
|
|
$this->tmpDir = sys_get_temp_dir() . '/bf-bundled-one-' . bin2hex(random_bytes(4));
|
|
mkdir($this->tmpDir, 0700, true);
|
|
file_put_contents(
|
|
$this->tmpDir . '/manifest.json',
|
|
json_encode(['valid' => ['name' => 'Valid', 'summary' => 'OK']], JSON_THROW_ON_ERROR),
|
|
);
|
|
$this->writeValidFixture();
|
|
}
|
|
|
|
protected function tearDown(): void
|
|
{
|
|
if (is_dir($this->tmpDir)) {
|
|
foreach (glob($this->tmpDir . '/*') ?: [] as $file) {
|
|
unlink($file);
|
|
}
|
|
rmdir($this->tmpDir);
|
|
}
|
|
}
|
|
|
|
public function testReturnsTheScenarioJsonForAKnownId(): void
|
|
{
|
|
$handler = new GetBundledScenario($this->tmpDir);
|
|
$response = $handler->handle(
|
|
new Request([], [], [], [], [], '', 'GET', '/scenarios/bundled/valid', null, ''),
|
|
['id' => 'valid'],
|
|
);
|
|
|
|
self::assertSame(200, $response->status);
|
|
$body = json_decode($response->body, true);
|
|
self::assertSame('valid', $body['id'] ?? null);
|
|
self::assertSame('Valid', $body['name'] ?? null);
|
|
self::assertSame(8, $body['battlefield']['width'] ?? null);
|
|
}
|
|
|
|
public function testReturns404ForAnUnknownId(): void
|
|
{
|
|
$handler = new GetBundledScenario($this->tmpDir);
|
|
$response = $handler->handle(
|
|
new Request([], [], [], [], [], '', 'GET', '/scenarios/bundled/unknown', null, ''),
|
|
['id' => 'unknown'],
|
|
);
|
|
|
|
self::assertSame(404, $response->status);
|
|
}
|
|
|
|
public function testReturns404ForAnIdThatFailsTheRegex(): void
|
|
{
|
|
$handler = new GetBundledScenario($this->tmpDir);
|
|
$response = $handler->handle(
|
|
new Request([], [], [], [], [], '', 'GET', '/scenarios/bundled/..', null, ''),
|
|
['id' => '..'],
|
|
);
|
|
|
|
self::assertSame(404, $response->status);
|
|
}
|
|
|
|
public function testReturns500WhenTheFixtureFailsValidation(): void
|
|
{
|
|
$bad = [
|
|
'id' => 'broken',
|
|
'name' => 'Broken',
|
|
'battlefield' => ['width' => 8, 'height' => 8, 'terrain' => []],
|
|
'units' => [],
|
|
'deploymentZones' => [],
|
|
'objectives' => [],
|
|
'victoryCondition' => 'eliminate_all',
|
|
'holdRoundsRequired' => 1,
|
|
];
|
|
file_put_contents($this->tmpDir . '/broken.json', json_encode($bad, JSON_THROW_ON_ERROR));
|
|
file_put_contents(
|
|
$this->tmpDir . '/manifest.json',
|
|
json_encode([
|
|
'valid' => ['name' => 'Valid', 'summary' => 'OK'],
|
|
'broken' => ['name' => 'Broken', 'summary' => 'Bad'],
|
|
], JSON_THROW_ON_ERROR),
|
|
);
|
|
|
|
$handler = new GetBundledScenario($this->tmpDir);
|
|
$response = $handler->handle(
|
|
new Request([], [], [], [], [], '', 'GET', '/scenarios/bundled/broken', null, ''),
|
|
['id' => 'broken'],
|
|
);
|
|
|
|
self::assertSame(500, $response->status);
|
|
$body = json_decode($response->body, true);
|
|
self::assertSame('fixture invalid', $body['error'] ?? null);
|
|
self::assertIsArray($body['details'] ?? null);
|
|
self::assertNotEmpty($body['details']);
|
|
}
|
|
|
|
private function writeValidFixture(): void
|
|
{
|
|
$fixture = [
|
|
'id' => 'valid',
|
|
'name' => 'Valid',
|
|
'battlefield' => ['width' => 8, 'height' => 8, 'terrain' => []],
|
|
'units' => [
|
|
$this->unit('a1', 'alpha', 0, 0),
|
|
$this->unit('a2', 'alpha', 1, 0),
|
|
$this->unit('a3', 'alpha', 2, 0),
|
|
$this->unit('b1', 'bravo', 7, 7),
|
|
$this->unit('b2', 'bravo', 6, 7),
|
|
$this->unit('b3', 'bravo', 5, 7),
|
|
],
|
|
'deploymentZones' => [
|
|
'alpha' => $this->deploymentZone('alpha', [[0, 0], [1, 0], [2, 0]]),
|
|
'bravo' => $this->deploymentZone('bravo', [[7, 7], [6, 7], [5, 7]]),
|
|
],
|
|
'objectives' => [],
|
|
'victoryCondition' => 'eliminate_all',
|
|
'holdRoundsRequired' => 1,
|
|
];
|
|
file_put_contents($this->tmpDir . '/valid.json', json_encode($fixture, JSON_THROW_ON_ERROR));
|
|
}
|
|
|
|
/** @return array<string, mixed> */
|
|
private function unit(string $id, string $teamId, int $x, int $y): array
|
|
{
|
|
return [
|
|
'id' => $id,
|
|
'teamId' => $teamId,
|
|
'position' => ['x' => $x, 'y' => $y],
|
|
'maxHealth' => 10,
|
|
'health' => 10,
|
|
'attack' => 3,
|
|
'defense' => 3,
|
|
'speed' => 2,
|
|
'archetype' => 'defender',
|
|
'abilities' => [],
|
|
];
|
|
}
|
|
|
|
/**
|
|
* @param list<array{0: int, 1: int}> $coords
|
|
* @return array<string, mixed>
|
|
*/
|
|
private function deploymentZone(string $teamId, array $coords): array
|
|
{
|
|
$positions = [];
|
|
foreach ($coords as $coord) {
|
|
$positions[] = ['x' => $coord[0], 'y' => $coord[1]];
|
|
}
|
|
|
|
return ['teamId' => $teamId, 'positions' => $positions];
|
|
}
|
|
}
|