*/ class TestLoggerTest extends LoggerInterfaceTest { private TestLogger $logger; public function getLogger(): TestLogger { if (!isset($this->logger)) { $this->logger = new TestLogger(); } return $this->logger; } public function getLogs(): array { $logs = array(); foreach ($this->getLogger()->records as $record) { // Interpolate context $message = preg_replace_callback( '!\{([^\}\s]*)\}!', fn (array $matches): string => $record['context'][$matches[1] ?? null] ?? $matches[0], $record['message'] ); $logs[] = $record['level'] . ' ' . $message; } return $logs; } public function testThrowsOnInvalidLevel(): void { self::markTestSkipped('TestLogger from psr/log 1.1 does not throw on invalid level.'); } /** * @dataProvider getLogLevels */ public function testHasRecord(string $level): void { $levelMethod = 'has' . ucfirst($level); $logger = $this->getLogger(); $this->assertFalse(call_user_func([$logger, $levelMethod . 'Records'])); $logger->log($level, $level . ' Message', ['foo' => 'bar']); $logger->log($level, $level . ' Hello'); $this->assertTrue(call_user_func([$logger, $levelMethod . 'Records'])); $record = $level . ' Message'; $this->assertTrue($logger->hasRecord($record, $level), 'hasRecord without context'); $this->assertTrue(call_user_func([$logger, $levelMethod], $record), $levelMethod . ' without context'); $record = ['message' => $level . ' Message']; $this->assertTrue($logger->hasRecord($record, $level), 'hasRecord without context'); $this->assertTrue(call_user_func([$logger, $levelMethod], $record), $levelMethod . ' without context'); $record = ['message' => $level . ' Message', ['foo' => 'bar']]; $this->assertTrue($logger->hasRecord($record, $level), 'hasRecord with context'); $this->assertTrue(call_user_func([$logger, $levelMethod], $record), $levelMethod . ' with context'); $this->assertTrue( call_user_func([$logger, $levelMethod . 'ThatContains'], 'Message'), $levelMethod . 'ThatContains' ); $this->assertTrue( call_user_func([$logger, $levelMethod . 'ThatMatches'], '/^[a-z]+ Message$/i'), $levelMethod . 'ThatMatches' ); $passesCallback = fn (array $record) => $record['message'] === $level . ' Message'; $this->assertTrue( call_user_func([$logger, $levelMethod . 'ThatPasses'], $passesCallback), $levelMethod . 'ThatPasses' ); } public static function getLogLevels(): array { return [ ['debug'], ['info'], ['notice'], ['warning'], ['error'], ['critical'], ['alert'], ['emergency'], ]; } public function testFalseHasRecord(): void { $logger = $this->getLogger(); $logger->debug('debug message'); $logger->debug('log message'); $logger->debug('log message with context', ['debug' => true]); $logger->debug('log message with context', ['debug' => false]); $logger->warning('log message'); $logger->warning('warning message'); $this->assertFalse($logger->hasAlert('my message')); $this->assertFalse($logger->hasAlert(['message' => 'my message'])); $this->assertFalse($logger->hasAlertRecords()); $this->assertFalse($logger->hasAlertThatContains('my message')); $this->assertFalse($logger->hasAlertThatMatches('/my message/')); $this->assertFalse($logger->hasAlertThatPasses(fn (array $record) => true)); $this->assertFalse($logger->hasDebug('warning message')); $this->assertFalse($logger->hasDebug(['message' => 'warning message'])); $this->assertFalse($logger->hasDebugThatContains('warning message')); $this->assertFalse($logger->hasDebugThatMatches('/warning message/')); $this->assertFalse($logger->hasDebugThatPasses(fn (array $record) => 'warning message' === $record['message'])); } public function testPlaceholderInterpolation() : void { $logger = new TestLogger(true); $message = 'User {username} created'; $logger->debug($message, ['username' => 'bolivar']); $this->assertTrue($logger->hasDebugThatContains('User bolivar created')); } }