Skip to content

Commit 79fdef6

Browse files
committed
Add tests for scheduler macro
1 parent acc8e2d commit 79fdef6

File tree

3 files changed

+131
-17
lines changed

3 files changed

+131
-17
lines changed

test/Sentry/Features/ConsoleIntegrationTest.php

Lines changed: 76 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,31 +2,95 @@
22

33
namespace Sentry\Features;
44

5+
use Illuminate\Console\Scheduling\Schedule;
6+
use RuntimeException;
7+
use Sentry\CheckInStatus;
58
use Sentry\Laravel\Tests\TestCase;
69
use Illuminate\Console\Scheduling\Event;
710

811
class ConsoleIntegrationTest extends TestCase
912
{
10-
public function setUp(): void
13+
public function testScheduleMacro(): void
1114
{
12-
if (!method_exists(Event::class, 'flushMacros')) {
13-
$this->markTestSkipped('Macroable::flushMacros() is not available in this Laravel version.');
14-
}
15+
/** @var Event $scheduledEvent */
16+
$scheduledEvent = $this->getScheduler()->call(function () {})->sentryMonitor('test-monitor');
17+
18+
$scheduledEvent->run($this->app);
19+
20+
// We expect a total of 2 events to be sent to Sentry:
21+
// 1. The start check-in event
22+
// 2. The finish check-in event
23+
$this->assertEquals(2, $this->getEventsCount());
24+
25+
$finishCheckInEvent = $this->getLastEvent();
26+
27+
$this->assertNotNull($finishCheckInEvent->getCheckIn());
28+
$this->assertEquals('test-monitor', $finishCheckInEvent->getCheckIn()->getMonitorSlug());
29+
$this->assertEquals(CheckInStatus::ok(), $finishCheckInEvent->getCheckIn()->getStatus());
30+
}
31+
32+
public function testScheduleMacroAutomaticSlug(): void
33+
{
34+
/** @var Event $scheduledEvent */
35+
$scheduledEvent = $this->getScheduler()->command('inspire')->sentryMonitor();
1536

16-
parent::setUp(); // TODO: Change the autogenerated stub
37+
$scheduledEvent->run($this->app);
38+
39+
// We expect a total of 2 events to be sent to Sentry:
40+
// 1. The start check-in event
41+
// 2. The finish check-in event
42+
$this->assertEquals(2, $this->getEventsCount());
43+
44+
$finishCheckInEvent = $this->getLastEvent();
45+
46+
$this->assertNotNull($finishCheckInEvent->getCheckIn());
47+
$this->assertEquals('scheduled_artisan-inspire', $finishCheckInEvent->getCheckIn()->getMonitorSlug());
48+
}
49+
50+
public function testScheduleMacroWithoutSlugOrCommandName(): void
51+
{
52+
$this->expectException(RuntimeException::class);
53+
54+
$this->getScheduler()->call(function () {})->sentryMonitor();
1755
}
1856

19-
public function testArtisanCommandIsRegistered(): void
57+
public function testScheduleMacroWithoutDsnSet(): void
2058
{
59+
$this->resetApplicationWithConfig([
60+
'sentry.dsn' => null,
61+
]);
62+
63+
/** @var Event $scheduledEvent */
64+
$scheduledEvent = $this->getScheduler()->call('inspire')->sentryMonitor('test-monitor');
65+
66+
$scheduledEvent->callBeforeCallbacks($this->app);
67+
68+
$this->assertEquals(0, $this->getEventsCount());
69+
70+
$scheduledEvent->finish($this->app, 0);
71+
72+
$this->assertEquals(0, $this->getEventsCount());
73+
}
74+
75+
public function testScheduleMacroIsRegistered(): void
76+
{
77+
if (!method_exists(Event::class, 'flushMacros')) {
78+
$this->markTestSkipped('Macroable::flushMacros() is not available in this Laravel version.');
79+
}
80+
2181
Event::flushMacros();
2282

2383
$this->refreshApplication();
2484

2585
$this->assertTrue(Event::hasMacro('sentryMonitor'));
2686
}
2787

28-
public function testArtisanCommandIsRegisteredWithoutDsnSet(): void
88+
public function testScheduleMacroIsRegisteredWithoutDsnSet(): void
2989
{
90+
if (!method_exists(Event::class, 'flushMacros')) {
91+
$this->markTestSkipped('Macroable::flushMacros() is not available in this Laravel version.');
92+
}
93+
3094
Event::flushMacros();
3195

3296
$this->resetApplicationWithConfig([
@@ -35,4 +99,9 @@ public function testArtisanCommandIsRegisteredWithoutDsnSet(): void
3599

36100
$this->assertTrue(Event::hasMacro('sentryMonitor'));
37101
}
102+
103+
private function getScheduler(): Schedule
104+
{
105+
return $this->app->make(Schedule::class);
106+
}
38107
}

test/Sentry/IntegrationTest.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -153,9 +153,9 @@ public function testExceptionReportedUsingReportHelperIsNotMarkedAsUnhandled():
153153

154154
report($testException);
155155

156-
$this->assertCount(1, $this->lastSentryEvents);
156+
$this->assertEquals(1, $this->getEventsCount());
157157

158-
[, $hint] = $this->lastSentryEvents[0];
158+
$hint = $this->getLastEventHint();
159159

160160
$this->assertEquals($testException, $hint->exception);
161161
$this->assertNotNull($hint->mechanism);
@@ -168,9 +168,9 @@ public function testExceptionIsNotMarkedAsUnhandled(): void
168168

169169
Integration::captureUnhandledException($testException);
170170

171-
$this->assertCount(1, $this->lastSentryEvents);
171+
$this->assertEquals(1, $this->getEventsCount());
172172

173-
[, $hint] = $this->lastSentryEvents[0];
173+
$hint = $this->getLastEventHint();
174174

175175
$this->assertEquals($testException, $hint->exception);
176176
$this->assertNotNull($hint->mechanism);

test/Sentry/TestCase.php

Lines changed: 51 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use Sentry\ClientInterface;
99
use Sentry\Event;
1010
use Sentry\EventHint;
11+
use Sentry\EventType;
1112
use Sentry\State\Scope;
1213
use ReflectionProperty;
1314
use Sentry\Laravel\Tracing;
@@ -17,20 +18,30 @@
1718

1819
abstract class TestCase extends LaravelTestCase
1920
{
21+
private static $hasSetupGlobalEventProcessor = false;
22+
2023
protected $setupConfig = [
2124
// Set config here before refreshing the app to set it in the container before Sentry is loaded
2225
// or use the `$this->resetApplicationWithConfig([ /* config */ ]);` helper method
2326
];
2427

2528
/** @var array<int, array{0: Event, 1: EventHint|null}> */
26-
protected $lastSentryEvents = [];
29+
protected static $lastSentryEvents = [];
2730

2831
protected function getEnvironmentSetUp($app): void
2932
{
30-
$this->lastSentryEvents = [];
33+
self::$lastSentryEvents = [];
34+
35+
$this->setupGlobalEventProcessor();
3136

32-
$app['config']->set('sentry.before_send', function (Event $event, ?EventHint $hint) {
33-
$this->lastSentryEvents[] = [$event, $hint];
37+
$app['config']->set('sentry.before_send', static function (Event $event, ?EventHint $hint) {
38+
self::$lastSentryEvents[] = [$event, $hint];
39+
40+
return null;
41+
});
42+
43+
$app['config']->set('sentry.before_send_transaction', static function (Event $event, ?EventHint $hint) {
44+
self::$lastSentryEvents[] = [$event, $hint];
3445

3546
return null;
3647
});
@@ -110,10 +121,44 @@ protected function getLastBreadcrumb(): ?Breadcrumb
110121

111122
protected function getLastEvent(): ?Event
112123
{
113-
if (empty($this->lastSentryEvents)) {
124+
if (empty(self::$lastSentryEvents)) {
114125
return null;
115126
}
116127

117-
return end($this->lastSentryEvents)[0];
128+
return end(self::$lastSentryEvents)[0];
129+
}
130+
131+
protected function getLastEventHint(): ?EventHint
132+
{
133+
if (empty(self::$lastSentryEvents)) {
134+
return null;
135+
}
136+
137+
return end(self::$lastSentryEvents)[1];
138+
}
139+
140+
protected function getEventsCount(): int
141+
{
142+
return count(self::$lastSentryEvents);
143+
}
144+
145+
private function setupGlobalEventProcessor(): void
146+
{
147+
if (self::$hasSetupGlobalEventProcessor) {
148+
return;
149+
}
150+
151+
Scope::addGlobalEventProcessor(static function (Event $event, ?EventHint $hint) {
152+
// Regular events and transactions are handled by the `before_send` and `before_send_transaction` callbacks
153+
if (in_array($event->getType(), [EventType::event(), EventType::transaction()], true)) {
154+
return $event;
155+
}
156+
157+
self::$lastSentryEvents[] = [$event, $hint];
158+
159+
return null;
160+
});
161+
162+
self::$hasSetupGlobalEventProcessor = true;
118163
}
119164
}

0 commit comments

Comments
 (0)