Passed
Pull Request — 1.x (#6)
by Kevin
06:51
created

can_access_envelopes_on_queue()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 6
nc 1
nop 0
dl 0
loc 11
rs 10
c 0
b 0
f 0
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 can_access_envelope_collection_items_via_first(): void
120
    {
121
        self::bootKernel();
122
123
        self::$container->get(MessageBusInterface::class)->dispatch($m1 = new MessageA());
124
        self::$container->get(MessageBusInterface::class)->dispatch($m2 = new MessageB());
125
        self::$container->get(MessageBusInterface::class)->dispatch($m3 = new MessageA(true));
126
127
        $this->messenger()->queue()->assertCount(3);
128
129
        $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

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