healthService = $this->createMock(SystemHealthService::class); $this->healthRepository = $this->createMock(SystemHealthRepositoryInterface::class); $this->fixturesDir = sys_get_temp_dir() . '/system-info-test-' . uniqid(); mkdir($this->fixturesDir, 0777, true); } protected function tearDown(): void { $this->removeDir($this->fixturesDir); } public function testBuildPageDataReturnsExpectedStructure(): void { $service = new SystemInfoService($this->healthService, $this->healthRepository, null); $this->healthService->expects($this->once()) ->method('runAll') ->willReturn([ ['status' => 'ok', 'name' => 'DB', 'message' => 'connected'], ]); $this->healthRepository->method('countActivePermissions')->willReturn(10); $this->healthRepository->method('countInactivePermissions')->willReturn(2); $this->healthRepository->method('listAllActivePermissionKeys')->willReturn(['users.view', 'settings.view']); $data = $service->buildPageData(); self::assertArrayHasKey('overview', $data); self::assertArrayHasKey('modules', $data); self::assertArrayHasKey('permissions', $data); self::assertSame(PHP_VERSION, $data['overview']['php_version']); self::assertIsArray($data['overview']['health_checks']); self::assertCount(1, $data['overview']['health_checks']); } public function testModuleInventoryReturnsSortedList(): void { $registry = $this->createRegistryWithModules(); $service = new SystemInfoService($this->healthService, $this->healthRepository, $registry); $this->healthService->method('runAll')->willReturn([]); $this->healthRepository->method('countActivePermissions')->willReturn(0); $this->healthRepository->method('countInactivePermissions')->willReturn(0); $this->healthRepository->method('listAllActivePermissionKeys')->willReturn([]); $data = $service->buildPageData(); self::assertCount(2, $data['modules']); self::assertSame('alpha', $data['modules'][0]['id']); self::assertSame('beta', $data['modules'][1]['id']); self::assertSame('2.0.0', $data['modules'][1]['version']); self::assertSame(['alpha'], $data['modules'][1]['requires']); } public function testPermissionSummaryReturnsCorrectCounts(): void { $service = new SystemInfoService($this->healthService, $this->healthRepository, null); $this->healthService->method('runAll')->willReturn([]); $this->healthRepository->expects($this->once())->method('countActivePermissions')->willReturn(42); $this->healthRepository->expects($this->once())->method('countInactivePermissions')->willReturn(3); $this->healthRepository->expects($this->once())->method('listAllActivePermissionKeys')->willReturn([ 'users.view', 'settings.view', ]); $data = $service->buildPageData(); self::assertSame(42, $data['permissions']['active_count']); self::assertSame(3, $data['permissions']['inactive_count']); self::assertSame(['core' => 2], $data['permissions']['by_source']); } public function testBuildPageDataWorksWithoutModuleRegistry(): void { $service = new SystemInfoService($this->healthService, $this->healthRepository, null); $this->healthService->method('runAll')->willReturn([]); $this->healthRepository->method('countActivePermissions')->willReturn(5); $this->healthRepository->method('countInactivePermissions')->willReturn(0); $this->healthRepository->method('listAllActivePermissionKeys')->willReturn([]); $data = $service->buildPageData(); self::assertSame([], $data['modules']); } private function createRegistryWithModules(): ModuleRegistry { mkdir($this->fixturesDir . '/alpha', 0777, true); file_put_contents( $this->fixturesDir . '/alpha/module.php', ' 'alpha', 'version' => '1.0.0', 'enabled_by_default' => true, ], true) . ';' ); mkdir($this->fixturesDir . '/beta', 0777, true); file_put_contents( $this->fixturesDir . '/beta/module.php', ' 'beta', 'version' => '2.0.0', 'enabled_by_default' => false, 'requires' => ['alpha'], ], true) . ';' ); return ModuleRegistry::boot($this->fixturesDir, ['alpha', 'beta']); } private function removeDir(string $dir): void { if (!is_dir($dir)) { return; } $items = new \RecursiveIteratorIterator( new \RecursiveDirectoryIterator($dir, \FilesystemIterator::SKIP_DOTS), \RecursiveIteratorIterator::CHILD_FIRST ); foreach ($items as $item) { $item->isDir() ? rmdir($item->getPathname()) : unlink($item->getPathname()); } rmdir($dir); } }