Completed
Push — master ( 419f51...37bf86 )
by Michał
08:39
created

MockRavenClient   A

Complexity

Total Complexity 1

Size/Duplication

Total Lines 12
Duplicated Lines 0 %

Coupling/Cohesion

Dependencies 1

Importance

Changes 0
Metric Value
wmc 1
cbo 1
dl 0
loc 12
rs 10
c 0
b 0
f 0

1 Method

Rating   Name   Duplication   Size   Complexity  
A capture() 0 6 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Dziki\MonologSentryBundle\Tests\Unit\Handler;
6
7
use Dziki\MonologSentryBundle\Handler\Raven;
8
use Monolog\Formatter\FormatterInterface;
9
use Monolog\Formatter\LineFormatter;
10
use Monolog\Logger;
11
use PHPUnit\Framework\TestCase;
12
use Raven_Client;
13
14
class RavenTest extends TestCase
15
{
16
    public function setUp()
17
    {
18
        if (!class_exists('Raven_Client')) {
19
            $this->markTestSkipped('sentry/sentry not installed');
20
        }
21
    }
22
23
    public function testConstruct()
24
    {
25
        $handler = new Raven($this->getRavenClient());
26
        $this->assertInstanceOf(Raven::class, $handler);
27
    }
28
29
    protected function getRavenClient()
30
    {
31
        $dsn = 'http://43f6017361224d098402974103bfc53d:[email protected]:9000/1';
32
33
        return new MockRavenClient($dsn);
34
    }
35
36 View Code Duplication
    public function testDebug()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
37
    {
38
        $ravenClient = $this->getRavenClient();
39
        $handler = $this->getHandler($ravenClient);
40
41
        $record = $this->getRecord(Logger::DEBUG, 'A test debug message');
42
        $handler->handle($record);
43
44
        $this->assertEquals($ravenClient::DEBUG, $ravenClient->lastData['level']);
45
        $this->assertContains($record['message'], $ravenClient->lastData['message']);
46
    }
47
48
    protected function getHandler($ravenClient)
49
    {
50
        $handler = new Raven($ravenClient);
51
52
        return $handler;
53
    }
54
55
    /**
56
     * @param int $level
57
     * @param string $message
58
     * @param array $context
59
     * @return array Record
60
     */
61
    protected function getRecord($level = Logger::WARNING, $message = 'test', array $context = []): array
62
    {
63
        return [
64
            'message' => (string)$message,
65
            'context' => $context,
66
            'level' => $level,
67
            'level_name' => Logger::getLevelName($level),
68
            'channel' => 'test',
69
            'datetime' => new \DateTimeImmutable(),
70
            'extra' => [],
71
        ];
72
    }
73
74 View Code Duplication
    public function testWarning()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
75
    {
76
        $ravenClient = $this->getRavenClient();
77
        $handler = $this->getHandler($ravenClient);
78
79
        $record = $this->getRecord(Logger::WARNING, 'A test warning message');
80
        $handler->handle($record);
81
82
        $this->assertEquals($ravenClient::WARNING, $ravenClient->lastData['level']);
83
        $this->assertContains($record['message'], $ravenClient->lastData['message']);
84
    }
85
86 View Code Duplication
    public function testTag()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
87
    {
88
        $ravenClient = $this->getRavenClient();
89
        $handler = $this->getHandler($ravenClient);
90
91
        $tags = [1, 2, 'foo'];
92
        $record = $this->getRecord(Logger::INFO, 'test', ['tags' => $tags]);
93
        $handler->handle($record);
94
95
        $this->assertEquals($tags, $ravenClient->lastData['tags']);
96
    }
97
98
    public function testExtraParameters()
99
    {
100
        $ravenClient = $this->getRavenClient();
101
        $handler = $this->getHandler($ravenClient);
102
103
        $checksum = '098f6bcd4621d373cade4e832627b4f6';
104
        $release = '05a671c66aefea124cc08b76ea6d30bb';
105
        $eventId = '31423';
106
        $record = $this->getRecord(
107
            Logger::INFO,
108
            'test',
109
            ['checksum' => $checksum, 'release' => $release, 'event_id' => $eventId]
110
        );
111
        $handler->handle($record);
112
113
        $this->assertEquals($checksum, $ravenClient->lastData['checksum']);
114
        $this->assertEquals($release, $ravenClient->lastData['release']);
115
        $this->assertEquals($eventId, $ravenClient->lastData['event_id']);
116
    }
117
118 View Code Duplication
    public function testFingerprint()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
119
    {
120
        $ravenClient = $this->getRavenClient();
121
        $handler = $this->getHandler($ravenClient);
122
123
        $fingerprint = ['{{ default }}', 'other value'];
124
        $record = $this->getRecord(Logger::INFO, 'test', ['fingerprint' => $fingerprint]);
125
        $handler->handle($record);
126
127
        $this->assertEquals($fingerprint, $ravenClient->lastData['fingerprint']);
128
    }
129
130
    public function testUserContext()
131
    {
132
        $ravenClient = $this->getRavenClient();
133
        $handler = $this->getHandler($ravenClient);
134
135
        $recordWithNoContext = $this->getRecord(Logger::INFO, 'test with default user context');
136
        // set user context 'externally'
137
138
        $user = [
139
            'id' => '123',
140
            'email' => '[email protected]',
141
        ];
142
143
        $recordWithContext = $this->getRecord(Logger::INFO, 'test', ['user' => $user]);
144
145
        // handle with null context
146
        $ravenClient->user_context(null);
0 ignored issues
show
Documentation introduced by
null is of type null, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
147
        $handler->handle($recordWithContext);
148
        $this->assertEquals($user, $ravenClient->lastData['user']);
149
150
        $ravenClient->user_context(['id' => 'test_user_id']);
151
        // handle context
152
        $handler->handle($recordWithContext);
153
        $this->assertEquals($user, $ravenClient->lastData['user']);
154
155
        // check to see if its reset
156
        $handler->handle($recordWithNoContext);
157
        $this->assertInternalType('array', $ravenClient->context->user);
158
        $this->assertSame('test_user_id', $ravenClient->context->user['id']);
159
    }
160
161
    public function testException()
162
    {
163
        $ravenClient = $this->getRavenClient();
164
        $handler = $this->getHandler($ravenClient);
165
166
        try {
167
            $this->methodThatThrowsAnException();
168
        } catch (\Exception $e) {
169
            $record = $this->getRecord(Logger::ERROR, $e->getMessage(), ['context' => ['exception' => $e]]);
170
            $handler->handle($record);
171
        }
172
173
        $this->assertEquals('[test] ' . $record['message'], $ravenClient->lastData['message']);
174
    }
175
176
    private function methodThatThrowsAnException()
177
    {
178
        throw new \Exception('This is an exception');
179
    }
180
181
    public function testHandleBatch()
182
    {
183
        $records = $this->getMultipleRecords();
184
        $records[] = $this->getRecord(Logger::WARNING, 'warning');
185
        $records[] = $this->getRecord(Logger::WARNING, 'warning');
186
187
        $logFormatter = $this->createMock('Monolog\\Formatter\\FormatterInterface');
188
189
        $formatter = $this->createMock('Monolog\\Formatter\\FormatterInterface');
190
        $formatter->expects($this->once())->method('format')->with(
191
            $this->callback(
192
                function ($record) {
193
                    return $record['level'] == 400;
194
                }
195
            )
196
        )
197
        ;
198
199
        $handler = $this->getHandler($this->getRavenClient());
200
        $handler->setBatchFormatter($logFormatter);
201
        $handler->setFormatter($formatter);
202
        $handler->handleBatch($records);
203
204
        $handler->handleBatch([]);
205
    }
206
207
    protected function getMultipleRecords(): array
208
    {
209
        return [
210
            $this->getRecord(Logger::DEBUG, 'debug message 1'),
211
            $this->getRecord(Logger::DEBUG, 'debug message 2'),
212
            $this->getRecord(Logger::INFO, 'information'),
213
            $this->getRecord(Logger::WARNING, 'warning'),
214
            $this->getRecord(Logger::ERROR, 'error'),
215
        ];
216
    }
217
218
    /**
219
     * @test
220
     */
221
    public function doNothingOnEmptyBatch(): void
222
    {
223
        $logFormatter = $this->createMock(FormatterInterface::class);
224
        $logFormatter->expects($this->never())
225
                     ->method('format');
226
227
        $logFormatter->expects($this->never())
228
                     ->method('formatBatch');
229
230
        $handler = $this->getHandler($this->getRavenClient());
231
        $handler->setBatchFormatter($logFormatter);
232
        $handler->setFormatter($logFormatter);
233
        $handler->handleBatch([]);
234
    }
235
236
    /**
237
     * @test
238
     */
239
    public function addContextsIfProvided(): void
240
    {
241
        $logFormatter = $this->createMock(FormatterInterface::class);
242
        $logFormatter->expects($this->once())
243
                     ->method('format')
244
                     ->willReturnArgument(0);
245
246
        $ravenClient = $this->getRavenClient();
247
248
        $handler = $this->getHandler($ravenClient);
249
        $handler->setBatchFormatter($logFormatter);
250
        $handler->setFormatter($logFormatter);
251
252
        $record = $this->getRecord();
253
        $record['contexts'] = ['browser_context'];
254
        $handler->handle($record);
255
256
        $this->assertSame(['browser_context'], $ravenClient->lastData['contexts']);
257
    }
258
259
    public function testHandleBatchDoNothingIfRecordsAreBelowLevel()
260
    {
261
        $records = [
262
            $this->getRecord(Logger::DEBUG, 'debug message 1'),
263
            $this->getRecord(Logger::DEBUG, 'debug message 2'),
264
            $this->getRecord(Logger::INFO, 'information'),
265
        ];
266
267
        $handler = $this->getMockBuilder('Monolog\Handler\RavenHandler')
268
                        ->setMethods(['handle'])
269
                        ->setConstructorArgs([$this->getRavenClient()])
270
                        ->getMock()
271
        ;
272
        $handler->expects($this->never())->method('handle');
273
        $handler->setLevel(Logger::ERROR);
274
        $handler->handleBatch($records);
275
    }
276
277
    public function testHandleBatchPicksProperMessage()
278
    {
279
        $records = [
280
            $this->getRecord(Logger::DEBUG, 'debug message 1'),
281
            $this->getRecord(Logger::DEBUG, 'debug message 2'),
282
            $this->getRecord(Logger::INFO, 'information 1'),
283
            $this->getRecord(Logger::ERROR, 'error 1'),
284
            $this->getRecord(Logger::WARNING, 'warning'),
285
            $this->getRecord(Logger::ERROR, 'error 2'),
286
            $this->getRecord(Logger::INFO, 'information 2'),
287
        ];
288
289
        $logFormatter = $this->createMock('Monolog\\Formatter\\FormatterInterface');
290
291
        $formatter = $this->createMock('Monolog\\Formatter\\FormatterInterface');
292
        $formatter->expects($this->once())->method('format')->with(
293
            $this->callback(
294
                function ($record) use ($records) {
295
                    return $record['message'] == 'error 1';
296
                }
297
            )
298
        )
299
        ;
300
301
        $handler = $this->getHandler($this->getRavenClient());
302
        $handler->setBatchFormatter($logFormatter);
303
        $handler->setFormatter($formatter);
304
        $handler->handleBatch($records);
305
    }
306
307
    public function testGetSetBatchFormatter()
308
    {
309
        $ravenClient = $this->getRavenClient();
310
        $handler = $this->getHandler($ravenClient);
311
312
        $handler->setBatchFormatter($formatter = new LineFormatter());
313
        $this->assertSame($formatter, $handler->getBatchFormatter());
314
    }
315
316
    public function testRelease()
317
    {
318
        $ravenClient = $this->getRavenClient();
319
        $handler = $this->getHandler($ravenClient);
320
        $release = 'v42.42.42';
321
        $handler->setRelease($release);
322
        $record = $this->getRecord(Logger::INFO, 'test');
323
        $handler->handle($record);
324
325
        $this->assertEquals($release, $ravenClient->lastData['release']);
326
327
        $localRelease = 'v41.41.41';
328
        $record = $this->getRecord(Logger::INFO, 'test', ['release' => $localRelease]);
329
        $handler->handle($record);
330
        $this->assertEquals($localRelease, $ravenClient->lastData['release']);
331
    }
332
333
    protected function getIdentityFormatter(): FormatterInterface
334
    {
335
        $formatter = $this->createMock(FormatterInterface::class);
336
        $formatter->expects($this->any())
337
                  ->method('format')
338
                  ->will(
339
                      $this->returnCallback(
340
                          function ($record) {
341
                              return $record['message'];
342
                          }
343
                      )
344
                  )
345
        ;
346
347
        return $formatter;
348
    }
349
}
350
351
class MockRavenClient extends Raven_Client
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
352
{
353
    public $lastData;
354
    public $lastStack;
355
356
    public function capture($data, $stack = null, $vars = null)
357
    {
358
        $data = array_merge($this->get_user_data(), $data);
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $data. This often makes code more readable.
Loading history...
359
        $this->lastData = $data;
360
        $this->lastStack = $stack;
361
    }
362
}
363