serviceRepository = $this->createStub(ServiceRepository::class); $this->em = $this->createStub(EntityManagerInterface::class); $this->httpClient = $this->createStub(HttpClientInterface::class); } private function execute(?EntityManagerInterface $em = null): CommandTester { $command = new CheckServicesCommand( $this->serviceRepository, $em ?? $this->em, $this->httpClient, ); $tester = new CommandTester($command); $tester->execute([]); return $tester; } private function createService(string $name, string $url, string $status = 'up', ?string $externalType = null): Service { $category = new ServiceCategory('Test', 'test'); $service = new Service($name, strtolower(str_replace(' ', '-', $name)), $category); $service->setUrl($url); $service->setStatus($status); if (null !== $externalType) { $service->setExternalType($externalType); $service->setIsExternal(true); } return $service; } private function mockQueryReturning(array $services): void { $query = $this->createStub(Query::class); $query->method('getResult')->willReturn($services); $qb = $this->createStub(QueryBuilder::class); $qb->method('where')->willReturnSelf(); $qb->method('andWhere')->willReturnSelf(); $qb->method('setParameter')->willReturnSelf(); $qb->method('getQuery')->willReturn($query); $this->serviceRepository->method('createQueryBuilder')->willReturn($qb); } private function mockResponse(int $statusCode, array $json = []): ResponseInterface { $response = $this->createStub(ResponseInterface::class); $response->method('getStatusCode')->willReturn($statusCode); $response->method('toArray')->willReturn($json); return $response; } public function testNoServicesToCheck(): void { $this->mockQueryReturning([]); $tester = $this->execute(); $this->assertSame(0, $tester->getStatusCode()); $this->assertStringContainsString('Aucun service', $tester->getDisplay()); } public function testServiceUpViaHttp(): void { $service = $this->createService('Web App', 'https://example.com'); $this->mockQueryReturning([$service]); $this->httpClient->method('request')->willReturn($this->mockResponse(200)); $tester = $this->execute(); $this->assertSame(0, $tester->getStatusCode()); $this->assertStringContainsString('1 service(s) verifie(s), 0 changement(s)', $tester->getDisplay()); } public function testServiceDownViaHttp(): void { $service = $this->createService('Web App', 'https://example.com'); $this->mockQueryReturning([$service]); $this->httpClient->method('request')->willReturn($this->mockResponse(500)); $tester = $this->execute(); $this->assertSame(0, $tester->getStatusCode()); $this->assertStringContainsString('1 service(s) verifie(s), 1 changement(s)', $tester->getDisplay()); $this->assertSame(Service::STATUS_DOWN, $service->getStatus()); } public function testServiceDegradedViaHttp(): void { $service = $this->createService('Web App', 'https://example.com'); $this->mockQueryReturning([$service]); $this->httpClient->method('request')->willReturn($this->mockResponse(403)); $this->execute(); $this->assertSame(Service::STATUS_DEGRADED, $service->getStatus()); } public function testHttpExceptionMarksDown(): void { $service = $this->createService('Web App', 'https://example.com'); $this->mockQueryReturning([$service]); $this->httpClient->method('request')->willThrowException(new \RuntimeException('timeout')); $this->execute(); $this->assertSame(Service::STATUS_DOWN, $service->getStatus()); } public function testSkipsSoonStatus(): void { $service = $this->createService('Future', 'https://example.com', Service::STATUS_SOON); $this->mockQueryReturning([$service]); $tester = $this->execute(); $this->assertSame(0, $tester->getStatusCode()); $this->assertStringContainsString('Skip', $tester->getDisplay()); $this->assertStringContainsString('0 service(s) verifie(s)', $tester->getDisplay()); } public function testSkipsMaintenanceStatus(): void { $service = $this->createService('Maint', 'https://example.com', Service::STATUS_MAINTENANCE); $this->mockQueryReturning([$service]); $tester = $this->execute(); $this->assertStringContainsString('Skip', $tester->getDisplay()); } public function testDocuSealCheckUp(): void { $service = $this->createService('DocuSeal', 'https://docuseal.example.com', 'up', 'docuseal'); $this->mockQueryReturning([$service]); $this->httpClient->method('request')->willReturn($this->mockResponse(200)); $this->execute(); $this->assertSame(Service::STATUS_UP, $service->getStatus()); } public function testDocuSealCheckDown(): void { $service = $this->createService('DocuSeal', 'https://docuseal.example.com', 'up', 'docuseal'); $this->mockQueryReturning([$service]); $this->httpClient->method('request')->willReturn($this->mockResponse(503)); $this->execute(); $this->assertSame(Service::STATUS_DOWN, $service->getStatus()); } public function testDocuSealCheckException(): void { $service = $this->createService('DocuSeal', 'https://docuseal.example.com', 'up', 'docuseal'); $this->mockQueryReturning([$service]); $this->httpClient->method('request')->willThrowException(new \RuntimeException('fail')); $this->execute(); $this->assertSame(Service::STATUS_DOWN, $service->getStatus()); } public function testVaultCheckUp(): void { $service = $this->createService('Vault', 'https://vault.example.com', 'up', 'vault'); $this->mockQueryReturning([$service]); $this->httpClient->method('request')->willReturn($this->mockResponse(200)); $this->execute(); $this->assertSame(Service::STATUS_UP, $service->getStatus()); } public function testVaultCheckDegraded(): void { $service = $this->createService('Vault', 'https://vault.example.com', 'up', 'vault'); $this->mockQueryReturning([$service]); $this->httpClient->method('request')->willReturn($this->mockResponse(429)); $this->execute(); $this->assertSame(Service::STATUS_DEGRADED, $service->getStatus()); } public function testVaultCheckDown(): void { $service = $this->createService('Vault', 'https://vault.example.com', 'up', 'vault'); $this->mockQueryReturning([$service]); $this->httpClient->method('request')->willReturn($this->mockResponse(503)); $this->execute(); $this->assertSame(Service::STATUS_DOWN, $service->getStatus()); } public function testVaultCheckException(): void { $service = $this->createService('Vault', 'https://vault.example.com', 'up', 'vault'); $this->mockQueryReturning([$service]); $this->httpClient->method('request')->willThrowException(new \RuntimeException('fail')); $this->execute(); $this->assertSame(Service::STATUS_DOWN, $service->getStatus()); } public function testMinioCheckUp(): void { $service = $this->createService('Minio', 'https://minio.example.com', 'up', 'minio'); $this->mockQueryReturning([$service]); $this->httpClient->method('request')->willReturn($this->mockResponse(200)); $this->execute(); $this->assertSame(Service::STATUS_UP, $service->getStatus()); } public function testMinioCheckDown(): void { $service = $this->createService('Minio', 'https://minio.example.com', 'up', 'minio'); $this->mockQueryReturning([$service]); $this->httpClient->method('request')->willReturn($this->mockResponse(503)); $this->execute(); $this->assertSame(Service::STATUS_DOWN, $service->getStatus()); } public function testMinioCheckException(): void { $service = $this->createService('Minio', 'https://minio.example.com', 'up', 'minio'); $this->mockQueryReturning([$service]); $this->httpClient->method('request')->willThrowException(new \RuntimeException('fail')); $this->execute(); $this->assertSame(Service::STATUS_DOWN, $service->getStatus()); } public function testStripeCheckUpdatesStatus(): void { $service = $this->createService('Stripe', 'https://stripe.com', 'up', 'stripe'); $this->mockQueryReturning([$service]); $this->httpClient->method('request')->willReturnCallback(function (string $method, string $url) { if (str_contains($url, 'status.stripe.com')) { return $this->mockResponse(200, [ 'status' => ['indicator' => 'major', 'description' => 'Major outage'], ]); } return $this->mockResponse(200); }); $this->execute(); $this->assertSame(Service::STATUS_DOWN, $service->getStatus()); } public function testStripeCheckMinor(): void { $service = $this->createService('Stripe', 'https://stripe.com', 'up', 'stripe'); $this->mockQueryReturning([$service]); $this->httpClient->method('request')->willReturnCallback(function (string $method, string $url) { if (str_contains($url, 'status.stripe.com')) { return $this->mockResponse(200, [ 'status' => ['indicator' => 'minor', 'description' => 'Minor issue'], ]); } return $this->mockResponse(200); }); $this->execute(); $this->assertSame(Service::STATUS_DEGRADED, $service->getStatus()); } public function testStripeCheckNone(): void { $service = $this->createService('Stripe', 'https://stripe.com', 'up', 'stripe'); $this->mockQueryReturning([$service]); $this->httpClient->method('request')->willReturnCallback(function (string $method, string $url) { if (str_contains($url, 'status.stripe.com')) { return $this->mockResponse(200, [ 'status' => ['indicator' => 'none', 'description' => 'All good'], ]); } return $this->mockResponse(200); }); $this->execute(); $this->assertSame(Service::STATUS_UP, $service->getStatus()); } public function testStripeCheckCritical(): void { $service = $this->createService('Stripe', 'https://stripe.com', 'up', 'stripe'); $this->mockQueryReturning([$service]); $this->httpClient->method('request')->willReturnCallback(function (string $method, string $url) { if (str_contains($url, 'status.stripe.com')) { return $this->mockResponse(200, [ 'status' => ['indicator' => 'critical', 'description' => 'Critical outage'], ]); } return $this->mockResponse(200); }); $this->execute(); $this->assertSame(Service::STATUS_DOWN, $service->getStatus()); } public function testStripeCheckUnknownIndicator(): void { $service = $this->createService('Stripe', 'https://stripe.com', 'up', 'stripe'); $this->mockQueryReturning([$service]); $this->httpClient->method('request')->willReturnCallback(function (string $method, string $url) { if (str_contains($url, 'status.stripe.com')) { return $this->mockResponse(200, [ 'status' => ['indicator' => 'unknown_value', 'description' => 'Unknown'], ]); } return $this->mockResponse(200); }); $this->execute(); $this->assertSame(Service::STATUS_UP, $service->getStatus()); } public function testStripeCheckException(): void { $service = $this->createService('Stripe', 'https://stripe.com', 'up', 'stripe'); $this->mockQueryReturning([$service]); $this->httpClient->method('request')->willThrowException(new \RuntimeException('network error')); $tester = $this->execute(); $this->assertStringContainsString('Impossible de verifier', $tester->getDisplay()); } public function testFlushCalledAfterChecks(): void { $service = $this->createService('Web App', 'https://example.com'); $this->mockQueryReturning([$service]); $this->httpClient->method('request')->willReturn($this->mockResponse(200)); $em = $this->createMock(EntityManagerInterface::class); $em->expects($this->once())->method('flush'); $this->execute($em); } public function testServiceStatusChangeMessage(): void { $service = $this->createService('API', 'https://api.example.com'); $this->mockQueryReturning([$service]); $this->httpClient->method('request')->willReturn($this->mockResponse(500)); $tester = $this->execute(); $this->assertStringContainsString('Auto-detection', $tester->getDisplay()); $this->assertStringContainsString('up -> down', $tester->getDisplay()); } public function testHttpRedirect3xx(): void { $service = $this->createService('Redirect', 'https://example.com'); $this->mockQueryReturning([$service]); $this->httpClient->method('request')->willReturn($this->mockResponse(301)); $this->execute(); $this->assertSame(Service::STATUS_UP, $service->getStatus()); } }