Skip to content

Commit e3d7769

Browse files
committed
test(channels): Add tests for exception reporting functionality
- Implement tests for various channels including Dump, Log, Mail, Notify, and Stack. - Ensure consistency in exception reporting across all channels by using 'testing' exception. - Improve testing coverage of the exception notification system.
1 parent dd725be commit e3d7769

19 files changed

+207
-308
lines changed

rector.php

Lines changed: 11 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@
3737
use Rector\CodingStyle\Rector\FuncCall\ArraySpreadInsteadOfArrayMergeRector;
3838
use Rector\CodingStyle\Rector\Stmt\NewlineAfterStatementRector;
3939
use Rector\Config\RectorConfig;
40-
use Rector\Contract\Rector\ConfigurableRectorInterface;
4140
use Rector\DeadCode\Rector\ClassLike\RemoveAnnotationRector;
4241
use Rector\DowngradePhp81\Rector\Array_\DowngradeArraySpreadStringKeyRector;
4342
use Rector\EarlyReturn\Rector\Return_\ReturnBinaryOrToEarlyReturnRector;
@@ -86,10 +85,6 @@
8685
'**/__snapshots__/*',
8786
'**/Fixtures/*',
8887
__DIR__.'/src/Channels/Channel.php',
89-
__DIR__.'/tests/Channels/LogChannelTest.php',
90-
__DIR__.'/tests/ExceptionNotifyManagerTest.php',
91-
__DIR__.'/tests/FeatureTest.php',
92-
__DIR__.'/tests/Fixtures/',
9388
__FILE__,
9489
])
9590
->withCache(__DIR__.'/.build/rector/')
@@ -121,11 +116,11 @@
121116
LaravelSetList::LARAVEL_90,
122117
...collect((new ReflectionClass(LaravelSetList::class))->getConstants(ReflectionClassConstant::IS_PUBLIC))
123118
->reject(
124-
static fn (
125-
string $constant,
126-
string $name
127-
): bool => \in_array($name, ['LARAVEL_STATIC_TO_INJECTION', 'LARAVEL_'], true)
128-
|| preg_match('/^LARAVEL_\d{2,3}$/', $name)
119+
static fn (string $constant, string $name): bool => \in_array(
120+
$name,
121+
['LARAVEL_STATIC_TO_INJECTION', 'LARAVEL_'],
122+
true
123+
) || preg_match('/^LARAVEL_\d{2,3}$/', $name)
129124
)
130125
// ->dd()
131126
->values()
@@ -141,7 +136,6 @@
141136
...$classes
142137
->filter(static fn (string $class): bool => str_starts_with($class, 'RectorLaravel\Rector'))
143138
->filter(static fn (string $class): bool => (new ReflectionClass($class))->isInstantiable())
144-
// ->filter(static fn (string $class): bool => is_subclass_of($class, ConfigurableRectorInterface::class))
145139
->values()
146140
// ->dd()
147141
->all(),
@@ -169,19 +163,12 @@
169163
->map(static fn (string $class) => collect((new ReflectionClass($class))->getConstants(ReflectionClassConstant::IS_PUBLIC))
170164
->reduce(
171165
static function (array $carry, mixed $value, string $name) use ($class): array {
166+
$classConstFetch = new ClassConstFetch(new FullyQualified($class), new Identifier($name));
167+
172168
$scalarValueToConstFetch = match (true) {
173-
\is_string($value) => new ScalarValueToConstFetch(
174-
new String_($value),
175-
new ClassConstFetch(new FullyQualified($class), new Identifier($name))
176-
),
177-
\is_int($value) => new ScalarValueToConstFetch(
178-
new Int_($value),
179-
new ClassConstFetch(new FullyQualified($class), new Identifier($name))
180-
),
181-
\is_float($value) => new ScalarValueToConstFetch(
182-
new Float_($value),
183-
new ClassConstFetch(new FullyQualified($class), new Identifier($name))
184-
),
169+
\is_string($value) => new ScalarValueToConstFetch(new String_($value), $classConstFetch),
170+
\is_int($value) => new ScalarValueToConstFetch(new Int_($value), $classConstFetch),
171+
\is_float($value) => new ScalarValueToConstFetch(new Float_($value), $classConstFetch),
185172
default => null,
186173
};
187174

@@ -222,7 +209,7 @@ static function (array $carry, mixed $value, string $name) use ($class): array {
222209
->withConfiguredRule(
223210
RenameFunctionRector::class,
224211
[
225-
// 'faker' => 'fake',
212+
'faker' => 'fake',
226213
'Guanguans\LaravelExceptionNotify\Support\rescue' => 'rescue',
227214
'Guanguans\Notify\Foundation\Support\rescue' => 'rescue',
228215
'Pest\Faker\fake' => 'fake',

src/Channels/StackChannel.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
namespace Guanguans\LaravelExceptionNotify\Channels;
1515

1616
use Guanguans\LaravelExceptionNotify\Facades\ExceptionNotify;
17-
use function Guanguans\LaravelExceptionNotify\Support\rescue;
1817

1918
/**
2019
* @see \Illuminate\Log\LogManager::createStackDriver()

src/Collectors/AbstractCollector.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ public function name(): string
2424

2525
public static function fallbackName(): string
2626
{
27-
return (string) str(class_basename(static::class))
28-
->beforeLast(str(class_basename(self::class))->replace('Abstract', ''))
29-
->snake(' ');
27+
return ucwords((string) str(class_basename(static::class))
28+
->beforeLast(str(class_basename(self::class))->remove('Abstract'))
29+
->snake(' '));
3030
}
3131
}

src/ExceptionNotifyManager.php

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -91,10 +91,6 @@ private function createOriginalDriver(string $driver): ChannelContract
9191

9292
$studlyName = Str::studly($configRepository->get('driver', $driver));
9393

94-
if (method_exists($this, $method = "create{$studlyName}Driver")) {
95-
return $this->{$method}($configRepository);
96-
}
97-
9894
if (class_exists($class = "\\Guanguans\\LaravelExceptionNotify\\Channels\\{$studlyName}Channel")) {
9995
return new $class($configRepository);
10096
}

src/Support/helpers.php

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515

1616
use Guanguans\LaravelExceptionNotify\Exceptions\InvalidArgumentException;
1717
use Illuminate\Support\Arr;
18-
use Illuminate\Support\Facades\Log;
1918

2019
if (!\function_exists('Guanguans\LaravelExceptionNotify\Support\make')) {
2120
/**
@@ -73,27 +72,6 @@ function env_explode(string $key, mixed $default = null, string $delimiter = ','
7372
}
7473
}
7574

76-
if (!\function_exists('Guanguans\LaravelExceptionNotify\Support\rescue')) {
77-
/**
78-
* @param null|\Closure $rescue
79-
* @param bool|\Closure $log
80-
*
81-
* @see rescue()
82-
*/
83-
function rescue(callable $callback, mixed $rescue = null, mixed $log = true): mixed
84-
{
85-
try {
86-
return $callback();
87-
} catch (\Throwable $throwable) {
88-
if (value($log, $throwable)) {
89-
Log::error($throwable->getMessage(), ['exception' => $throwable]);
90-
}
91-
92-
return value($rescue, $throwable);
93-
}
94-
}
95-
}
96-
9775
if (!\function_exists('Guanguans\LaravelExceptionNotify\Support\json_pretty_encode')) {
9876
/**
9977
* @throws \JsonException

tests/Channels/ChannelTest.php

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
<?php
2+
3+
/** @noinspection DebugFunctionUsageInspection */
4+
/** @noinspection ForgottenDebugOutputInspection */
5+
/** @noinspection AnonymousFunctionStaticInspection */
6+
/** @noinspection StaticClosureCanBeUsedInspection */
7+
8+
declare(strict_types=1);
9+
10+
/**
11+
* Copyright (c) 2021-2025 guanguans<ityaozm@gmail.com>
12+
*
13+
* For the full copyright and license information, please view
14+
* the LICENSE file that was distributed with this source code.
15+
*
16+
* @see https://github.com/guanguans/laravel-exception-notify
17+
*/
18+
19+
use Guanguans\LaravelExceptionNotify\Events\ReportedEvent;
20+
use Guanguans\LaravelExceptionNotify\Events\ReportingEvent;
21+
use Guanguans\LaravelExceptionNotify\ExceptionNotifyManager;
22+
use Guanguans\LaravelExceptionNotify\Facades\ExceptionNotify;
23+
24+
it('can listen reporting and reported event', function (): void {
25+
ExceptionNotify::reporting(function (ReportingEvent $reportingEvent): void {
26+
dump($reportingEvent::class);
27+
});
28+
29+
ExceptionNotify::reported(function (ReportedEvent $reportedEvent): void {
30+
dump($reportedEvent::class);
31+
});
32+
33+
expect($this->app->make(ExceptionNotifyManager::class))
34+
->report(new Exception('testing'))
35+
->toBeNull();
36+
})->group(__DIR__, __FILE__);
37+
38+
it('can attempt Exception', function (): void {
39+
config()->set('exception-notify.rate_limiter.max_attempts', 3);
40+
expect(fn () => $this->attempt(new Exception(microtime())))
41+
->call($logChannel = app(ExceptionNotifyManager::class)->channel('log'))->toBeTrue()
42+
->call($logChannel)->toBeTrue()
43+
->call($logChannel)->toBeTrue()
44+
->call($logChannel)->toBeFalse();
45+
})->group(__DIR__, __FILE__);
46+
47+
it('are same fingerprints for exceptions of throw in the same position', function (): void {
48+
collect(range(1, 10))
49+
->map(fn (): string => (fn () => $this->fingerprintFor(new Exception(microtime())))->call(ExceptionNotify::driver('log')))
50+
->reduce(static function (?string $previousFingerprint, string $fingerprint): string {
51+
$previousFingerprint and expect($previousFingerprint)->toBe($fingerprint);
52+
53+
return $fingerprint;
54+
});
55+
})->group(__DIR__, __FILE__);

tests/Channels/DumpChannelTest.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
/** @noinspection AnonymousFunctionStaticInspection */
4+
/** @noinspection StaticClosureCanBeUsedInspection */
5+
6+
declare(strict_types=1);
7+
8+
/**
9+
* Copyright (c) 2021-2025 guanguans<ityaozm@gmail.com>
10+
*
11+
* For the full copyright and license information, please view
12+
* the LICENSE file that was distributed with this source code.
13+
*
14+
* @see https://github.com/guanguans/laravel-exception-notify
15+
*/
16+
17+
use Guanguans\LaravelExceptionNotify\ExceptionNotifyManager;
18+
19+
it('can report', function (): void {
20+
expect($this->app->make(ExceptionNotifyManager::class)->driver('dump'))
21+
->report(new Exception('testing'))
22+
->toBeNull();
23+
})->group(__DIR__, __FILE__);

tests/Channels/LogChannelTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,6 @@
1818

1919
it('can report', function (): void {
2020
expect($this->app->make(ExceptionNotifyManager::class)->driver('log'))
21-
->report(new Exception('test'))
21+
->report(new Exception('testing'))
2222
->toBeNull();
2323
})->group(__DIR__, __FILE__);

tests/Channels/MailChannelTest.php

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,22 +15,17 @@
1515
*/
1616

1717
use Guanguans\LaravelExceptionNotify\ExceptionNotifyManager;
18-
use Guanguans\LaravelExceptionNotify\Exceptions\InvalidArgumentException;
1918
use Guanguans\LaravelExceptionNotify\Mail\ReportExceptionMail;
19+
use Guanguans\LaravelExceptionNotifyTests\Fixtures\MailableExtender;
2020
use Illuminate\Support\Facades\Mail;
2121

22-
it('will throw `InvalidArgumentException`', function (): void {
23-
config()->set('exception-notify.channels.mail.extender');
24-
$this->app->make(ExceptionNotifyManager::class)->driver('mail');
25-
})->group(__DIR__, __FILE__)->throws(InvalidArgumentException::class)->skip();
26-
27-
it('will throw `TransportException`', function (): void {
28-
config()->set(
29-
'exception-notify.channels.mail.extender',
30-
static fn (object $mailerOrPendingMail): object => $mailerOrPendingMail
31-
);
22+
it('can report', function (): void {
23+
config(['exception-notify.channels.mail.render' => 'value']);
24+
config(['exception-notify.channels.mail.extender' => MailableExtender::class]);
3225

3326
Mail::fake();
34-
$this->app->make(ExceptionNotifyManager::class)->driver('mail')->reportContent('content');
27+
expect($this->app->make(ExceptionNotifyManager::class)->driver('mail'))
28+
->report(new Exception('testing'))
29+
->toBeNull();
3530
Mail::assertSent(ReportExceptionMail::class);
36-
})->group(__DIR__, __FILE__)->skip();
31+
})->group(__DIR__, __FILE__);

tests/Channels/NotifyChannelTest.php

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -14,23 +14,10 @@
1414
* @see https://github.com/guanguans/laravel-exception-notify
1515
*/
1616

17-
use Guanguans\LaravelExceptionNotify\Channels\NotifyChannel;
1817
use Guanguans\LaravelExceptionNotify\ExceptionNotifyManager;
19-
use Guanguans\LaravelExceptionNotify\Exceptions\InvalidArgumentException;
20-
use Illuminate\Config\Repository;
21-
use Psr\Http\Message\ResponseInterface;
22-
23-
it('will throw `InvalidArgumentException`', function (): void {
24-
new NotifyChannel(new Repository([
25-
'__channel' => 'null',
26-
'client' => [
27-
'extender' => null,
28-
],
29-
]));
30-
})->group(__DIR__, __FILE__)->throws(InvalidArgumentException::class);
3118

3219
it('can report', function (): void {
33-
expect(app(ExceptionNotifyManager::class)->driver('bark'))
34-
->reportContent('content')
35-
->toBeInstanceOf(ResponseInterface::class);
20+
expect($this->app->make(ExceptionNotifyManager::class)->driver('bark'))
21+
->report(new Exception('testing'))
22+
->toBeNull();
3623
})->group(__DIR__, __FILE__);

0 commit comments

Comments
 (0)