tkr/tests/Controller/FeedController/FeedControllerTest.php
Greg Sarjeant 9593a43cc0
Some checks are pending
Run unit tests / run-unit-tests (push) Waiting to run
make-homepage-testable (#42)
Add logging and tests for the homepage and settings page. Make both support dependency injection.

Reviewed-on: https://gitea.subcultureofone.org/greg/tkr/pulls/42
Co-authored-by: Greg Sarjeant <greg@subcultureofone.org>
Co-committed-by: Greg Sarjeant <greg@subcultureofone.org>
2025-08-02 01:43:48 +00:00

175 lines
6.3 KiB
PHP

<?php
use PHPUnit\Framework\TestCase;
class FeedControllerTest extends TestCase
{
private PDO $mockPdo;
private PDOStatement $mockStatement;
private ConfigModel $mockConfig;
private UserModel $mockUser;
private string $tempLogDir;
protected function setUp(): void
{
// Set up temporary logging
$this->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);
}
}