tempLogDir = sys_get_temp_dir() . '/tkr_test_logs_' . uniqid(); mkdir($this->tempLogDir . '/logs', 0777, true); Log::init($this->tempLogDir . '/logs/tkr.log'); // Set up global config for logging level (DEBUG = 1) global $config; $config = new stdClass(); $config->logLevel = 1; // Allow DEBUG level logs // Create mock PDO and PDOStatement $this->mockStatement = $this->createMock(PDOStatement::class); $this->mockPdo = $this->createMock(PDO::class); // Mock config with feed-relevant properties $this->mockConfig = new ConfigModel($this->mockPdo); $this->mockConfig->itemsPerPage = 10; $this->mockConfig->basePath = '/tkr'; $this->mockConfig->siteTitle = 'Test Site'; $this->mockConfig->siteDescription = 'Test Description'; $this->mockConfig->baseUrl = 'https://test.example.com'; // Mock user $this->mockUser = new UserModel($this->mockPdo); $this->mockUser->displayName = 'Test User'; } protected function tearDown(): void { // Clean up temp directory if (is_dir($this->tempLogDir)) { $this->deleteDirectory($this->tempLogDir); } } private function deleteDirectory(string $dir): void { if (!is_dir($dir)) return; $files = array_diff(scandir($dir), ['.', '..']); foreach ($files as $file) { $path = $dir . '/' . $file; is_dir($path) ? $this->deleteDirectory($path) : unlink($path); } rmdir($dir); } private function setupMockDatabase(array $tickData): void { // Mock PDO prepare method to return our mock statement $this->mockPdo->method('prepare') ->willReturn($this->mockStatement); // Mock statement execute method $this->mockStatement->method('execute') ->willReturn(true); // Mock statement fetchAll to return our test data $this->mockStatement->method('fetchAll') ->willReturn($tickData); } public function testControllerInstantiationWithNoTicks(): void { $this->setupMockDatabase([]); $controller = new FeedController($this->mockPdo, $this->mockConfig, $this->mockUser); // Verify it was created successfully $this->assertInstanceOf(FeedController::class, $controller); // Check logs $logFile = $this->tempLogDir . '/logs/tkr.log'; $this->assertFileExists($logFile); $logContent = file_get_contents($logFile); $this->assertStringContainsString('Loaded 0 ticks for feeds', $logContent); } public function testControllerInstantiationWithTicks(): void { $testTicks = [ ['id' => 1, 'timestamp' => '2025-01-31 12:00:00', 'tick' => 'First tick'], ['id' => 2, 'timestamp' => '2025-01-31 13:00:00', 'tick' => 'Second tick'], ]; $this->setupMockDatabase($testTicks); $controller = new FeedController($this->mockPdo, $this->mockConfig, $this->mockUser); // Verify it was created successfully $this->assertInstanceOf(FeedController::class, $controller); // Check logs $logFile = $this->tempLogDir . '/logs/tkr.log'; $this->assertFileExists($logFile); $logContent = file_get_contents($logFile); $this->assertStringContainsString('Loaded 2 ticks for feeds', $logContent); } public function testControllerCallsDatabaseCorrectly(): void { $this->setupMockDatabase([]); // Verify that PDO prepare is called with the correct SQL for tick loading $this->mockPdo->expects($this->once()) ->method('prepare') ->with('SELECT id, timestamp, tick FROM tick ORDER BY timestamp DESC LIMIT ? OFFSET ?') ->willReturn($this->mockStatement); // Verify that execute is called with correct parameters (page 1, offset 0) $this->mockStatement->expects($this->once()) ->method('execute') ->with([10, 0]); // itemsPerPage=10, page 1 = offset 0 new FeedController($this->mockPdo, $this->mockConfig, $this->mockUser); } public function testRssMethodLogsCorrectly(): void { $testTicks = [ ['id' => 1, 'timestamp' => '2025-01-31 12:00:00', 'tick' => 'Test tick'] ]; $this->setupMockDatabase($testTicks); $controller = new FeedController($this->mockPdo, $this->mockConfig, $this->mockUser); // Capture output to prevent headers/content from affecting test ob_start(); $controller->rss(); ob_end_clean(); // Check logs for RSS generation $logFile = $this->tempLogDir . '/logs/tkr.log'; $logContent = file_get_contents($logFile); $this->assertStringContainsString('Generating RSS feed with 1 ticks', $logContent); } public function testAtomMethodLogsCorrectly(): void { $testTicks = [ ['id' => 1, 'timestamp' => '2025-01-31 12:00:00', 'tick' => 'Test tick'], ['id' => 2, 'timestamp' => '2025-01-31 13:00:00', 'tick' => 'Another tick'] ]; $this->setupMockDatabase($testTicks); $controller = new FeedController($this->mockPdo, $this->mockConfig, $this->mockUser); // Capture output to prevent headers/content from affecting test ob_start(); $controller->atom(); ob_end_clean(); // Check logs for Atom generation $logFile = $this->tempLogDir . '/logs/tkr.log'; $logContent = file_get_contents($logFile); $this->assertStringContainsString('Generating Atom feed with 2 ticks', $logContent); } }