From 6d3ce08e8c58082bb20fc512a139a176bd56c5f9 Mon Sep 17 00:00:00 2001 From: Ricardo Machado <89906313+rmachado-studocu@users.noreply.github.com> Date: Mon, 20 May 2024 00:48:25 +0200 Subject: [PATCH] Adds `shareContext` to `LogFake` (#45) --- readme.md | 42 ++++++++++++++++++++++++++++++++ src/LogFake.php | 42 +++++++++++++++++++++++++++++++- tests/AssertionTest.php | 23 ++++++++++++++++++ tests/LogFakeApiTest.php | 52 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 158 insertions(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 7169edf..733cd22 100644 --- a/readme.md +++ b/readme.md @@ -398,6 +398,48 @@ Log::assertCurrentContext( ); // ❌ the 'env' key is set to "production" ``` +### assertHasSharedContext() + +Assert that the Log manager currently has the given shared context. It is possible to provide the expected context as an array or alternatively you can provide a truth-test closure to check the current context. + +#### Can be called on + +- [x] Facade base (default channel) +- [ ] Channels +- [ ] Stacks + +#### Example tests + +```php +/* + * implementation... + */ + +Log::shareContext([ + 'invocation-id' => '54', +]); + +/* + * assertions... + */ + +Log::assertHasSharedContext([ + 'invocation-id' => '54', +]); // ✅ + +Log::assertCurrentContext( + fn (array $context) => $context['invocation-id'] === '54') +); // ✅ + +Log::assertCurrentContext([ + 'invocation-id' => '99', +]); // ❌ wrong invocation ID + +Log::assertCurrentContext( + fn (array $context) => $context['invocation-id'] === '99') +); // ❌ wrong invocation ID +``` + ## Inspection Sometimes when debugging tests it's useful to be able to take a peek at the messages that have been logged. There are a couple of helpers to assist with this. diff --git a/src/LogFake.php b/src/LogFake.php index 3914cf3..0c506bf 100644 --- a/src/LogFake.php +++ b/src/LogFake.php @@ -30,6 +30,13 @@ class LogFake implements LoggerInterface */ private array $stacks = []; + /** + * The context shared across channels and stacks. + * + * @var array + */ + protected $sharedContext = []; + /** * @link https://github.com/timacdonald/log-fake#basic-usage Documentation */ @@ -84,6 +91,25 @@ public function assertChannelIsCurrentlyForgotten(string $name, ?string $message return $this; } + /** + * @link ... Documentation + * + * @param (Closure(array): bool)|array $callback + */ + public function assertHasSharedContext(Closure|array $callback, ?string $message = null): LogFake + { + $callback = is_array($callback) + ? fn ($context) => $context === $callback + : $callback; + + PHPUnit::assertTrue( + $callback($this->sharedContext), + $message ?? 'Expected shared context was not found.' + ); + + return $this; + } + /** * @see LogManager::build() * @@ -127,7 +153,7 @@ public function driver(?string $driver = null): ChannelFake $channel = $this->channels[$name] ??= new ChannelFake($name); - return $channel->remember(); + return $channel->remember()->withContext($this->sharedContext); } /** @@ -225,4 +251,18 @@ private static function parseStackDriver(array $channels, ?string $channel): str { return 'stack::'.($channel ?? 'unnamed').':'.Collection::make($channels)->sort()->implode(','); } + + /** + * @param array $context + */ + public function shareContext(array $context): LogFake + { + foreach ($this->channels as $channel) { + $channel->withContext($context); + } + + $this->sharedContext = array_merge($this->sharedContext, $context); + + return $this; + } } diff --git a/tests/AssertionTest.php b/tests/AssertionTest.php index 1281ade..f0e8175 100644 --- a/tests/AssertionTest.php +++ b/tests/AssertionTest.php @@ -540,4 +540,27 @@ public function testAssertLoggedFuncWithNonBoolReturnedFromClosure(): void 'Expected log was not created in the [stack] channel.' ); } + + public function testAssertHasSharedContext(): void + { + $log = new LogFake(); + $log->shareContext(['shared' => 'context']); + + $log->assertHasSharedContext(fn ($context) => $context === ['shared' => 'context']); + self::assertFailsWithMessage( + fn () => $log->assertHasSharedContext(fn ($context) => false), + 'Expected shared context was not found.' + ); + } + + public function testItCanProvideCustomMessageWithAssertHasSharedContext(): void + { + $log = new LogFake(); + $log->shareContext(['shared' => 'context']); + + self::assertFailsWithMessage( + fn () => $log->assertHasSharedContext(fn ($context) => false, 'Whoops!'), + 'Whoops!' + ); + } } diff --git a/tests/LogFakeApiTest.php b/tests/LogFakeApiTest.php index 4ae2404..f85ab3d 100644 --- a/tests/LogFakeApiTest.php +++ b/tests/LogFakeApiTest.php @@ -632,4 +632,56 @@ public function testItClearsContextWhenAChannelIsForgotten(): void $log->channel('channel')->assertLogged(fn (LogEntry $log) => $log->context === []); } + + public function testItSupportsSharedContextForAlreadyBuiltDrivers(): void + { + $log = new LogFake(); + $channel = $log->channel('channel'); + $log->shareContext([ + 'shared' => 'context', + ]); + $channel->info('expected message', [ + 'local' => 'context', + ]); + + $log->channel('channel')->assertLogged(fn (LogEntry $log) => $log->context === [ + 'shared' => 'context', + 'local' => 'context', + ]); + } + + public function testItSupportsSharedContextForNewlyBuiltDrivers(): void + { + $log = new LogFake(); + $log->shareContext([ + 'shared' => 'context', + ]); + + $log->channel('channel')->info('expected message', [ + 'local' => 'context', + ]); + + $log->channel('channel')->assertLogged(fn (LogEntry $log) => $log->context === [ + 'shared' => 'context', + 'local' => 'context', + ]); + } + + public function testItMergesSharedContext(): void + { + $log = new LogFake(); + $log->shareContext([ + 'shared' => 'first', + 'more' => 'context', + ])->shareContext([ + 'shared' => 'second', + ]); + + $log->channel('channel')->info('expected message'); + + $log->channel('channel')->assertLogged(fn (LogEntry $log) => $log->context === [ + 'shared' => 'second', + 'more' => 'context', + ]); + } }