Completed
Push — 1.x ( c2f735...1d81a7 )
by Kevin
12s queued 11s
created

disabling_intercept_is_remembered_between_kernel_reboots()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 18
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 10
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 18
rs 9.9332
1
<?php
2
3
namespace Zenstruck\Messenger\Test\Tests;
4
5
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
6
use Symfony\Component\HttpKernel\KernelInterface;
7
use Symfony\Component\Messenger\Envelope;
8
use Symfony\Component\Messenger\MessageBusInterface;
9
use Symfony\Component\Messenger\Stamp\DelayStamp;
10
use Zenstruck\Messenger\Test\InteractsWithMessenger;
11
use Zenstruck\Messenger\Test\TestEnvelope;
12
use Zenstruck\Messenger\Test\Tests\Fixture\Messenger\MessageA;
13
use Zenstruck\Messenger\Test\Tests\Fixture\Messenger\MessageAHandler;
14
use Zenstruck\Messenger\Test\Tests\Fixture\Messenger\MessageB;
15
use Zenstruck\Messenger\Test\Tests\Fixture\Messenger\MessageBHandler;
16
use Zenstruck\Messenger\Test\Tests\Fixture\Messenger\MessageC;
17
use Zenstruck\Messenger\Test\Tests\Fixture\NoBundleKernel;
18
19
/**
20
 * @author Kevin Bond <[email protected]>
21
 */
22
final class InteractsWithMessengerTest extends WebTestCase
23
{
24
    use InteractsWithMessenger;
25
26
    /**
27
     * @test
28
     */
29
    public function can_interact_with_queue(): void
30
    {
31
        self::bootKernel();
32
33
        $this->messenger()->queue()->assertEmpty();
34
        $this->assertEmpty(self::$container->get(MessageAHandler::class)->messages);
35
        $this->assertEmpty(self::$container->get(MessageBHandler::class)->messages);
36
37
        self::$container->get(MessageBusInterface::class)->dispatch(new MessageA());
38
        self::$container->get(MessageBusInterface::class)->dispatch(new MessageB());
39
        self::$container->get(MessageBusInterface::class)->dispatch(new MessageA());
40
41
        $this->messenger()->queue()->assertCount(3);
42
        $this->messenger()->queue()->assertContains(MessageA::class);
43
        $this->messenger()->queue()->assertContains(MessageA::class, 2);
44
        $this->messenger()->queue()->assertContains(MessageB::class);
45
        $this->messenger()->queue()->assertContains(MessageB::class, 1);
46
        $this->messenger()->queue()->assertNotContains(MessageC::class);
47
        $this->assertEmpty(self::$container->get(MessageAHandler::class)->messages);
48
        $this->assertEmpty(self::$container->get(MessageBHandler::class)->messages);
49
50
        $this->messenger()->process(2);
51
52
        $this->messenger()->queue()->assertCount(1);
53
        $this->messenger()->queue()->assertContains(MessageA::class, 1);
54
        $this->messenger()->queue()->assertNotContains(MessageB::class);
55
        $this->assertCount(1, self::$container->get(MessageAHandler::class)->messages);
56
        $this->assertCount(1, self::$container->get(MessageBHandler::class)->messages);
57
58
        $this->messenger()->process();
59
60
        $this->messenger()->queue()->assertEmpty();
61
        $this->messenger()->queue()->assertNotContains(MessageA::class);
62
        $this->messenger()->queue()->assertNotContains(MessageB::class);
63
        $this->assertCount(2, self::$container->get(MessageAHandler::class)->messages);
64
        $this->assertCount(1, self::$container->get(MessageBHandler::class)->messages);
65
    }
66
67
    /**
68
     * @test
69
     */
70
    public function can_disable_intercept(): void
71
    {
72
        self::bootKernel();
73
74
        $this->messenger()->unblock();
75
76
        $this->messenger()->queue()->assertEmpty();
77
        $this->messenger()->acknowledged()->assertEmpty();
78
        $this->messenger()->sent()->assertEmpty();
79
80
        self::$container->get(MessageBusInterface::class)->dispatch(new MessageA());
81
        self::$container->get(MessageBusInterface::class)->dispatch(new MessageB());
82
        self::$container->get(MessageBusInterface::class)->dispatch(new MessageA());
83
84
        $this->messenger()->queue()->assertEmpty();
85
        $this->messenger()->queue()->assertNotContains(MessageA::class);
86
        $this->messenger()->sent()->assertCount(3);
87
        $this->messenger()->sent()->assertContains(MessageA::class, 2);
88
        $this->messenger()->sent()->assertContains(MessageB::class, 1);
89
        $this->messenger()->acknowledged()->assertCount(3);
90
        $this->messenger()->acknowledged()->assertContains(MessageA::class, 2);
91
        $this->messenger()->acknowledged()->assertContains(MessageB::class, 1);
92
        $this->assertCount(2, self::$container->get(MessageAHandler::class)->messages);
93
        $this->assertCount(1, self::$container->get(MessageBHandler::class)->messages);
94
    }
95
96
    /**
97
     * @test
98
     */
99
    public function disabling_intercept_with_items_on_queue_processes_all(): void
100
    {
101
        self::bootKernel();
102
103
        self::$container->get(MessageBusInterface::class)->dispatch(new MessageA());
104
        self::$container->get(MessageBusInterface::class)->dispatch(new MessageB());
105
        self::$container->get(MessageBusInterface::class)->dispatch(new MessageA());
106
107
        $this->messenger()->queue()->assertCount(3);
108
109
        $this->messenger()->process();
110
111
        $this->messenger()->queue()->assertEmpty();
112
        $this->assertCount(2, self::$container->get(MessageAHandler::class)->messages);
113
        $this->assertCount(1, self::$container->get(MessageBHandler::class)->messages);
114
    }
115
116
    /**
117
     * @test
118
     */
119
    public function disabling_intercept_is_remembered_between_kernel_reboots(): void
120
    {
121
        self::bootKernel();
122
123
        $this->messenger()->unblock();
124
125
        self::$container->get(MessageBusInterface::class)->dispatch(new MessageA());
126
127
        $this->messenger()->queue()->assertEmpty();
128
        $this->messenger()->sent()->assertCount(1);
129
130
        self::ensureKernelShutdown();
131
        self::bootKernel();
132
133
        self::$container->get(MessageBusInterface::class)->dispatch(new MessageA());
134
135
        $this->messenger()->queue()->assertEmpty();
136
        $this->messenger()->sent()->assertCount(2);
137
    }
138
139
    /**
140
     * @test
141
     */
142
    public function can_access_envelope_collection_items_via_first(): void
143
    {
144
        self::bootKernel();
145
146
        self::$container->get(MessageBusInterface::class)->dispatch($m1 = new MessageA());
147
        self::$container->get(MessageBusInterface::class)->dispatch($m2 = new MessageB());
148
        self::$container->get(MessageBusInterface::class)->dispatch($m3 = new MessageA(true));
149
150
        $this->messenger()->queue()->assertCount(3);
151
152
        $this->assertSame($m1, $this->messenger()->queue()->first()->getMessage());
0 ignored issues
show
Bug introduced by
The method getMessage() does not exist on Zenstruck\Messenger\Test\TestEnvelope. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

152
        $this->assertSame($m1, $this->messenger()->queue()->first()->/** @scrutinizer ignore-call */ getMessage());
Loading history...
153
        $this->assertSame($m2, $this->messenger()->queue()->first(MessageB::class)->getMessage());
154
        $this->assertSame($m3, $this->messenger()->queue()->first(fn(Envelope $e) => $e->getMessage()->fail)->getMessage());
155
        $this->assertSame($m3, $this->messenger()->queue()->first(fn($e) => $e->getMessage()->fail)->getMessage());
156
        $this->assertSame($m3, $this->messenger()->queue()->first(fn(MessageA $m) => $m->fail)->getMessage());
157
    }
158
159
    /**
160
     * @test
161
     */
162
    public function envelope_collection_first_throws_exception_if_no_match(): void
163
    {
164
        self::bootKernel();
165
166
        $this->expectException(\RuntimeException::class);
167
168
        $this->messenger()->queue()->first();
169
    }
170
171
    /**
172
     * @test
173
     */
174
    public function can_make_stamp_assertions_on_test_envelope(): void
175
    {
176
        self::bootKernel();
177
178
        self::$container->get(MessageBusInterface::class)->dispatch(new MessageA(), [new DelayStamp(1000)]);
179
        self::$container->get(MessageBusInterface::class)->dispatch(new MessageB());
180
181
        $this->messenger()->queue()->first()->assertHasStamp(DelayStamp::class);
182
        $this->messenger()->queue()->first(MessageB::class)->assertNotHasStamp(DelayStamp::class);
183
    }
184
185
    /**
186
     * @test
187
     */
188
    public function cannot_access_queue_if_none_registered(): void
189
    {
190
        self::bootKernel(['environment' => 'test']);
191
192
        $this->expectException(\LogicException::class);
193
        $this->expectExceptionMessage('No transports registered');
194
195
        $this->messenger();
196
    }
197
198
    /**
199
     * @test
200
     */
201
    public function accessing_transport_boots_kernel_if_not_yet_booted(): void
202
    {
203
        $this->messenger()->queue()->assertEmpty();
204
    }
205
206
    /**
207
     * @test
208
     */
209
    public function can_interact_with_multiple_queues(): void
210
    {
211
        self::bootKernel(['environment' => 'multi_transport']);
212
213
        $this->messenger('async1')->queue()->assertEmpty();
214
        $this->messenger('async2')->queue()->assertEmpty();
215
        $this->assertEmpty(self::$container->get(MessageAHandler::class)->messages);
216
        $this->assertEmpty(self::$container->get(MessageBHandler::class)->messages);
217
218
        self::$container->get(MessageBusInterface::class)->dispatch(new MessageA());
219
        self::$container->get(MessageBusInterface::class)->dispatch(new MessageB());
220
        self::$container->get(MessageBusInterface::class)->dispatch(new MessageA());
221
222
        $this->messenger('async1')->queue()->assertCount(2);
223
        $this->messenger('async2')->queue()->assertEmpty();
224
        $this->messenger('async1')->queue()->assertContains(MessageA::class);
225
        $this->messenger('async1')->queue()->assertContains(MessageA::class, 2);
226
        $this->messenger('async2')->queue()->assertNotContains(MessageB::class);
227
        $this->assertEmpty(self::$container->get(MessageAHandler::class)->messages);
228
        $this->assertCount(1, self::$container->get(MessageBHandler::class)->messages);
229
230
        $this->messenger('async1')->process(1);
231
        $this->messenger('async2')->process(1);
232
233
        $this->messenger('async1')->queue()->assertCount(1);
234
        $this->messenger('async1')->queue()->assertContains(MessageA::class, 1);
235
        $this->messenger('async2')->queue()->assertNotContains(MessageB::class);
236
        $this->assertCount(1, self::$container->get(MessageAHandler::class)->messages);
237
        $this->assertCount(1, self::$container->get(MessageBHandler::class)->messages);
238
239
        $this->messenger('async1')->process();
240
        $this->messenger('async2')->process();
241
242
        $this->messenger('async1')->queue()->assertEmpty();
243
        $this->messenger('async2')->queue()->assertEmpty();
244
        $this->assertCount(2, self::$container->get(MessageAHandler::class)->messages);
245
        $this->assertCount(1, self::$container->get(MessageBHandler::class)->messages);
246
    }
247
248
    /**
249
     * @test
250
     */
251
    public function can_enable_intercept(): void
252
    {
253
        self::bootKernel(['environment' => 'multi_transport']);
254
255
        $this->messenger('async2')->intercept();
256
257
        $this->messenger('async2')->queue()->assertEmpty();
258
        $this->assertEmpty(self::$container->get(MessageBHandler::class)->messages);
259
260
        self::$container->get(MessageBusInterface::class)->dispatch(new MessageB());
261
        self::$container->get(MessageBusInterface::class)->dispatch(new MessageB());
262
263
        $this->messenger('async2')->queue()->assertCount(2);
264
    }
265
266
    /**
267
     * @test
268
     */
269
    public function cannot_access_queue_that_does_not_exist(): void
270
    {
271
        self::bootKernel(['environment' => 'multi_transport']);
272
273
        $this->expectException(\InvalidArgumentException::class);
274
        $this->expectExceptionMessage('"invalid" not registered');
275
276
        $this->messenger('invalid');
277
    }
278
279
    /**
280
     * @test
281
     */
282
    public function cannot_access_queue_that_is_not_test_transport(): void
283
    {
284
        self::bootKernel(['environment' => 'multi_transport']);
285
286
        $this->expectException(\LogicException::class);
287
        $this->expectExceptionMessage('Transport "async3" needs to be set to "test://" in your test config to use this feature.');
288
289
        $this->messenger('async3');
290
    }
291
292
    /**
293
     * @test
294
     */
295
    public function queue_name_is_required_if_using_multiple_transports(): void
296
    {
297
        self::bootKernel(['environment' => 'multi_transport']);
298
299
        $this->expectException(\LogicException::class);
300
        $this->expectExceptionMessage('Multiple transports are registered (async1, async2, async3), you must specify a name.');
301
302
        $this->messenger();
303
    }
304
305
    /**
306
     * @test
307
     */
308
    public function can_access_message_objects_on_queue(): void
309
    {
310
        self::bootKernel();
311
312
        self::$container->get(MessageBusInterface::class)->dispatch($m1 = new MessageA());
313
        self::$container->get(MessageBusInterface::class)->dispatch($m2 = new MessageB());
314
        self::$container->get(MessageBusInterface::class)->dispatch($m3 = new MessageA());
315
316
        $this->assertSame([$m1, $m2, $m3], $this->messenger()->queue()->messages());
317
        $this->assertSame([$m1, $m3], $this->messenger()->queue()->messages(MessageA::class));
318
        $this->assertSame([$m2], $this->messenger()->queue()->messages(MessageB::class));
319
    }
320
321
    /**
322
     * @test
323
     */
324
    public function can_access_envelopes_on_envelope_collection(): void
325
    {
326
        self::bootKernel();
327
328
        self::$container->get(MessageBusInterface::class)->dispatch($m1 = new MessageA());
329
        self::$container->get(MessageBusInterface::class)->dispatch($m2 = new MessageB());
330
        self::$container->get(MessageBusInterface::class)->dispatch($m3 = new MessageA());
331
332
        $messages = \array_map(fn(TestEnvelope $envelope) => $envelope->getMessage(), $this->messenger()->queue()->all());
333
        $messagesFromIterator = \array_map(fn(TestEnvelope $envelope) => $envelope->getMessage(), \iterator_to_array($this->messenger()->queue()));
334
335
        $this->assertSame([$m1, $m2, $m3], $messages);
336
        $this->assertSame([$m1, $m2, $m3], $messagesFromIterator);
337
    }
338
339
    /**
340
     * @test
341
     */
342
    public function can_access_sent_acknowledged_and_rejected(): void
343
    {
344
        self::bootKernel();
345
346
        self::$container->get(MessageBusInterface::class)->dispatch($m1 = new MessageA(true));
347
        self::$container->get(MessageBusInterface::class)->dispatch($m2 = new MessageB());
348
349
        $this->assertCount(2, $this->messenger()->queue());
350
        $this->assertCount(2, $this->messenger()->sent());
351
        $this->assertCount(0, $this->messenger()->acknowledged());
352
        $this->assertCount(0, $this->messenger()->rejected());
353
354
        $this->messenger()->process();
355
356
        $this->assertCount(0, $this->messenger()->queue());
357
        $this->assertCount(2, $this->messenger()->sent());
358
        $this->assertCount(1, $this->messenger()->acknowledged());
359
        $this->assertCount(1, $this->messenger()->rejected());
360
    }
361
362
    /**
363
     * @test
364
     */
365
    public function cannot_access_queue_if_bundle_not_enabled(): void
366
    {
367
        self::$class = NoBundleKernel::class;
368
        self::bootKernel(['environment' => 'no_bundle']);
369
        self::$class = null;
370
371
        $this->expectException(\LogicException::class);
372
        $this->expectExceptionMessage('Cannot access transport - is ZenstruckMessengerTestBundle enabled in your test environment?');
373
374
        $this->messenger();
375
    }
376
377
    /**
378
     * @test
379
     */
380
    public function can_configure_throwing_exceptions(): void
381
    {
382
        self::bootKernel();
383
384
        $this->messenger()->throwExceptions();
385
386
        self::$container->get(MessageBusInterface::class)->dispatch(new MessageA(true));
387
388
        $this->expectException(\RuntimeException::class);
389
        $this->expectExceptionMessage('handling failed...');
390
391
        $this->messenger()->process();
392
    }
393
394
    /**
395
     * @test
396
     */
397
    public function can_configure_throwing_exceptions_with_intercept_disabled(): void
398
    {
399
        self::bootKernel();
400
401
        $this->messenger()->throwExceptions()->unblock();
402
403
        $this->expectException(\RuntimeException::class);
404
        $this->expectExceptionMessage('handling failed...');
405
406
        self::$container->get(MessageBusInterface::class)->dispatch(new MessageA(true));
407
    }
408
409
    /**
410
     * @test
411
     */
412
    public function can_disable_exception_catching_in_transport_config(): void
413
    {
414
        self::bootKernel(['environment' => 'multi_transport']);
415
416
        $this->expectException(\RuntimeException::class);
417
        $this->expectExceptionMessage('handling failed...');
418
419
        self::$container->get(MessageBusInterface::class)->dispatch(new MessageB(true));
420
    }
421
422
    /**
423
     * @test
424
     */
425
    public function can_re_enable_exception_catching_if_disabled_in_transport_config(): void
426
    {
427
        self::bootKernel(['environment' => 'multi_transport']);
428
429
        $this->messenger('async2')->catchExceptions();
430
431
        $this->messenger('async2')->rejected()->assertEmpty();
432
433
        self::$container->get(MessageBusInterface::class)->dispatch(new MessageB(true));
434
435
        $this->messenger('async2')->rejected()->assertCount(1);
436
    }
437
438
    /**
439
     * @test
440
     */
441
    public function throwing_exceptions_is_remembered_between_kernel_reboots(): void
442
    {
443
        self::bootKernel();
444
445
        $this->messenger()->throwExceptions();
446
447
        self::ensureKernelShutdown();
448
        self::bootKernel();
449
450
        self::$container->get(MessageBusInterface::class)->dispatch(new MessageA(true));
451
452
        $this->expectException(\RuntimeException::class);
453
        $this->expectErrorMessage('handling failed...');
454
455
        $this->messenger()->process();
456
    }
457
458
    /**
459
     * @test
460
     */
461
    public function transport_data_is_persisted_between_requests_and_kernel_shutdown(): void
462
    {
463
        self::bootKernel();
464
465
        self::$container->get(MessageBusInterface::class)->dispatch(new MessageA());
466
        self::$container->get(MessageBusInterface::class)->dispatch(new MessageA(true));
467
468
        $this->messenger()->queue()->assertCount(2);
469
470
        self::ensureKernelShutdown();
471
        self::bootKernel();
472
473
        $this->messenger()->queue()->assertCount(2);
474
475
        $this->messenger()->process();
476
477
        self::ensureKernelShutdown();
478
        self::bootKernel();
479
480
        $this->messenger()->queue()->assertEmpty();
481
        $this->messenger()->sent()->assertCount(2);
482
        $this->messenger()->acknowledged()->assertCount(1);
483
        $this->messenger()->rejected()->assertCount(1);
484
485
        self::ensureKernelShutdown();
486
487
        $client = self::createClient();
488
489
        $client->request('GET', '/dispatch');
490
491
        $this->messenger()->queue()->assertCount(1);
492
        $this->messenger()->sent()->assertCount(3);
493
        $this->messenger()->acknowledged()->assertCount(1);
494
        $this->messenger()->rejected()->assertCount(1);
495
496
        $client->request('GET', '/dispatch');
497
498
        $this->messenger()->queue()->assertCount(2);
499
        $this->messenger()->sent()->assertCount(4);
500
        $this->messenger()->acknowledged()->assertCount(1);
501
        $this->messenger()->rejected()->assertCount(1);
502
    }
503
504
    /**
505
     * @test
506
     */
507
    public function can_reset_transport_data(): void
508
    {
509
        self::bootKernel();
510
511
        self::$container->get(MessageBusInterface::class)->dispatch(new MessageA());
512
513
        $this->messenger()->queue()->assertNotEmpty();
514
515
        $this->messenger()->reset();
516
517
        $this->messenger()->queue()->assertEmpty();
518
    }
519
520
    protected static function bootKernel(array $options = []): KernelInterface
521
    {
522
        return parent::bootKernel(\array_merge(['environment' => 'single_transport'], $options));
523
    }
524
}
525