- A1: scripts/backup-postgres.sh — pg_dump quotidien compressé → Backblaze B2 (rclone), rétention 30j - A2: StatusController retourne HTTP 503 + healthy/alertReason si dernière observation > 6h - A4: Dockerfile installe tippecanoe, GenerateTilesCommand génère 5 tilesets (obs + h6/12/24/48), Caddyfile sert /tiles/* sans fallback SPA, SargassesMap.jsx passe en sources vector tiles statiques - chore: backend/public/assets/ ajouté au .gitignore (build artifacts) - chore: setup vitest frontend + ImpactScoreServiceTest (session précédente) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
72 lines
2.6 KiB
PHP
72 lines
2.6 KiB
PHP
<?php
|
|
|
|
namespace App\Tests\Unit\Service;
|
|
|
|
use App\Service\Forecast\ImpactScoreService;
|
|
use Doctrine\DBAL\Connection;
|
|
use Doctrine\ORM\EntityManagerInterface;
|
|
use PHPUnit\Framework\TestCase;
|
|
use Psr\Log\NullLogger;
|
|
use Symfony\Component\Cache\Adapter\ArrayAdapter;
|
|
use App\Service\Push\PushNotificationService;
|
|
|
|
class ImpactScoreServiceTest extends TestCase
|
|
{
|
|
private ImpactScoreService $service;
|
|
|
|
protected function setUp(): void
|
|
{
|
|
$connection = $this->createStub(Connection::class);
|
|
$em = $this->createStub(EntityManagerInterface::class);
|
|
$cache = new ArrayAdapter();
|
|
$push = $this->createStub(PushNotificationService::class);
|
|
|
|
$this->service = new ImpactScoreService(
|
|
$connection,
|
|
$em,
|
|
$cache,
|
|
new NullLogger(),
|
|
$push,
|
|
);
|
|
}
|
|
|
|
// ── scoreToLevel ──────────────────────────────────────────────────────────
|
|
|
|
#[\PHPUnit\Framework\Attributes\DataProvider('scoreLevelProvider')]
|
|
public function testScoreToLevel(int $score, string $expected): void
|
|
{
|
|
$method = new \ReflectionMethod(ImpactScoreService::class, 'scoreToLevel');
|
|
$result = $method->invoke($this->service, $score);
|
|
|
|
self::assertSame($expected, $result);
|
|
}
|
|
|
|
/** @return array<string, array{int, string}> */
|
|
public static function scoreLevelProvider(): array
|
|
{
|
|
return [
|
|
'score 0 → low' => [0, 'low'],
|
|
'score 30 → low' => [30, 'low'],
|
|
'score 31 → medium' => [31, 'medium'],
|
|
'score 70 → medium' => [70, 'medium'],
|
|
'score 71 → high' => [71, 'high'],
|
|
'score 100 → high' => [100, 'high'],
|
|
];
|
|
}
|
|
|
|
// ── emptyScore ────────────────────────────────────────────────────────────
|
|
|
|
public function testEmptyScoreReturnsCorrectStructure(): void
|
|
{
|
|
$method = new \ReflectionMethod(ImpactScoreService::class, 'emptyScore');
|
|
$result = $method->invoke($this->service);
|
|
|
|
self::assertSame(0, $result['score']);
|
|
self::assertSame('low', $result['level']);
|
|
self::assertNull($result['distance']);
|
|
self::assertSame(0.0, $result['density']);
|
|
self::assertSame('stable', $result['trend']);
|
|
self::assertNull($result['etaHours']);
|
|
}
|
|
}
|