makeDb(); $logger = new AuditLogger($pdo); $logger->record('UPDATE', 'worker', 1, ['n' => 1], ['n' => 2]); $logger->record('CREATE', 'worker', 2, null, ['n' => 1]); $logger->record('UPDATE', 'sprint', 3, ['n' => 1], ['n' => 2]); $repo = new AuditRepository($pdo); $this->assertSame(['CREATE', 'UPDATE'], $repo->distinctActions()); } public function testDistinctEntityTypesReturnsSortedUniqueValues(): void { $pdo = $this->makeDb(); $logger = new AuditLogger($pdo); $logger->record('UPDATE', 'worker', 1, ['n' => 1], ['n' => 2]); $logger->record('UPDATE', 'sprint', 2, ['n' => 1], ['n' => 2]); $logger->record('UPDATE', 'worker', 3, ['n' => 1], ['n' => 2]); $repo = new AuditRepository($pdo); $this->assertSame(['sprint', 'worker'], $repo->distinctEntityTypes()); } public function testDistinctColumnRejectsUnknownColumnViaReflection(): void { $pdo = $this->makeDb(); $repo = new AuditRepository($pdo); $rm = new \ReflectionMethod($repo, 'distinctColumn'); $rm->setAccessible(true); $this->expectException(InvalidArgumentException::class); $rm->invoke($repo, 'user_email'); } public function testDistinctColumnRejectsInjectionAttemptViaReflection(): void { $pdo = $this->makeDb(); $repo = new AuditRepository($pdo); $rm = new \ReflectionMethod($repo, 'distinctColumn'); $rm->setAccessible(true); $this->expectException(InvalidArgumentException::class); $rm->invoke($repo, 'action; DROP TABLE audit_log; --'); } }