• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

api-platform / core / 14648308077

24 Apr 2025 05:54PM UTC coverage: 7.021%. First build
14648308077

Pull #6904

github

web-flow
Merge e57e10524 into 7c796de0d
Pull Request #6904: feat(graphql): added support for graphql subscriptions to work for actions

55 of 188 new or added lines in 9 files covered. (29.26%)

11165 of 159026 relevant lines covered (7.02%)

6.23 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/Symfony/Tests/Doctrine/EventListener/PublishMercureUpdatesListenerTest.php
1
<?php
2

3
/*
4
 * This file is part of the API Platform project.
5
 *
6
 * (c) Kévin Dunglas <dunglas@gmail.com>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11

12
declare(strict_types=1);
13

14
namespace ApiPlatform\Symfony\Tests\Doctrine\EventListener;
15

16
use ApiPlatform\GraphQl\Subscription\MercureSubscriptionIriGeneratorInterface as GraphQlMercureSubscriptionIriGeneratorInterface;
17
use ApiPlatform\GraphQl\Subscription\SubscriptionManagerInterface as GraphQlSubscriptionManagerInterface;
18
use ApiPlatform\Metadata\ApiResource;
19
use ApiPlatform\Metadata\Get;
20
use ApiPlatform\Metadata\IriConverterInterface;
21
use ApiPlatform\Metadata\Operations;
22
use ApiPlatform\Metadata\Post;
23
use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface;
24
use ApiPlatform\Metadata\Resource\ResourceMetadataCollection;
25
use ApiPlatform\Metadata\ResourceClassResolverInterface;
26
use ApiPlatform\Metadata\UrlGeneratorInterface;
27
use ApiPlatform\Symfony\Doctrine\EventListener\PublishMercureUpdatesListener;
28
use ApiPlatform\Symfony\Tests\Fixtures\NotAResource;
29
use ApiPlatform\Symfony\Tests\Fixtures\TestBundle\Entity\Dummy;
30
use ApiPlatform\Symfony\Tests\Fixtures\TestBundle\Entity\DummyCar;
31
use ApiPlatform\Symfony\Tests\Fixtures\TestBundle\Entity\DummyFriend;
32
use ApiPlatform\Symfony\Tests\Fixtures\TestBundle\Entity\DummyMercure;
33
use ApiPlatform\Symfony\Tests\Fixtures\TestBundle\Entity\DummyOffer;
34
use ApiPlatform\Symfony\Tests\Fixtures\TestBundle\Entity\MercureWithTopicsAndGetOperation;
35
use Doctrine\ORM\EntityManagerInterface;
36
use Doctrine\ORM\Event\OnFlushEventArgs;
37
use Doctrine\ORM\UnitOfWork;
38
use PHPUnit\Framework\TestCase;
39
use Prophecy\Argument;
40
use Prophecy\PhpUnit\ProphecyTrait;
41
use Symfony\Component\Mercure\HubInterface;
42
use Symfony\Component\Mercure\HubRegistry;
43
use Symfony\Component\Mercure\Jwt\StaticTokenProvider;
44
use Symfony\Component\Mercure\MockHub;
45
use Symfony\Component\Mercure\Update;
46
use Symfony\Component\Serializer\SerializerInterface;
47

48
/**
49
 * @author Kévin Dunglas <dunglas@gmail.com>
50
 */
51
class PublishMercureUpdatesListenerTest extends TestCase
52
{
53
    use ProphecyTrait;
54

55
    public function testPublishUpdate(): void
56
    {
57
        $toInsert = new Dummy();
×
58
        $toInsert->setId(1);
×
59
        $toInsertNotResource = new NotAResource('foo', 'bar');
×
60

61
        $toUpdate = new Dummy();
×
62
        $toUpdate->setId(2);
×
63
        $toUpdateNoMercureAttribute = new DummyCar();
×
64
        $toUpdateMercureOptions = new DummyOffer();
×
65
        $toUpdateMercureTopicOptions = new DummyMercure();
×
66

67
        $toDelete = new Dummy();
×
68
        $toDelete->setId(3);
×
69
        $toDeleteExpressionLanguage = new DummyFriend();
×
70
        $toDeleteExpressionLanguage->setId(4);
×
71
        $toDeleteMercureOptions = new DummyOffer();
×
72

73
        $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class);
×
74
        $resourceClassResolverProphecy->getResourceClass(Argument::type(Dummy::class))->willReturn(Dummy::class);
×
75
        $resourceClassResolverProphecy->getResourceClass(Argument::type(DummyCar::class))->willReturn(DummyCar::class);
×
76
        $resourceClassResolverProphecy->getResourceClass(Argument::type(DummyFriend::class))->willReturn(DummyFriend::class);
×
77
        $resourceClassResolverProphecy->getResourceClass(Argument::type(DummyOffer::class))->willReturn(DummyOffer::class);
×
78
        $resourceClassResolverProphecy->getResourceClass(Argument::type(DummyMercure::class))->willReturn(DummyMercure::class);
×
79
        $resourceClassResolverProphecy->isResourceClass(Dummy::class)->willReturn(true);
×
80
        $resourceClassResolverProphecy->isResourceClass(NotAResource::class)->willReturn(false);
×
81
        $resourceClassResolverProphecy->isResourceClass(DummyCar::class)->willReturn(true);
×
82
        $resourceClassResolverProphecy->isResourceClass(DummyFriend::class)->willReturn(true);
×
83
        $resourceClassResolverProphecy->isResourceClass(DummyOffer::class)->willReturn(true);
×
84
        $resourceClassResolverProphecy->isResourceClass(DummyMercure::class)->willReturn(true);
×
85

86
        $iriConverterProphecy = $this->prophesize(IriConverterInterface::class);
×
87
        $iriConverterProphecy->getIriFromResource($toInsert, UrlGeneratorInterface::ABS_URL)->willReturn('http://example.com/dummies/1')->shouldBeCalled();
×
88
        $iriConverterProphecy->getIriFromResource($toUpdate, UrlGeneratorInterface::ABS_URL)->willReturn('http://example.com/dummies/2')->shouldBeCalled();
×
89
        $iriConverterProphecy->getIriFromResource($toDelete, UrlGeneratorInterface::ABS_URL)->willReturn('http://example.com/dummies/3')->shouldBeCalled();
×
90
        $iriConverterProphecy->getIriFromResource($toDelete)->willReturn('/dummies/3')->shouldBeCalled();
×
91
        $iriConverterProphecy->getIriFromResource($toDeleteExpressionLanguage)->willReturn('/dummy_friends/4')->shouldBeCalled();
×
92
        $iriConverterProphecy->getIriFromResource($toDeleteExpressionLanguage, UrlGeneratorInterface::ABS_URL)->willReturn('http://example.com/dummy_friends/4')->shouldBeCalled();
×
93
        $iriConverterProphecy->getIriFromResource($toDeleteMercureOptions)->willReturn('/dummy_offers/5')->shouldBeCalled();
×
94
        $iriConverterProphecy->getIriFromResource($toDeleteMercureOptions, UrlGeneratorInterface::ABS_URL)->willReturn('http://example.com/dummy_offers/5')->shouldBeCalled();
×
95

96
        $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class);
×
97

98
        $resourceMetadataFactoryProphecy->create(DummyMercure::class)->willReturn(new ResourceMetadataCollection(Dummy::class, [(new ApiResource())->withOperations(new Operations([
×
99
            'get' => (new Get())->withMercure([]),
×
100
        ]))]));
×
101

102
        $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadataCollection(Dummy::class, [(new ApiResource())->withOperations(new Operations([
×
103
            'get' => (new Get())->withShortName('Dummy')->withMercure(['hub' => 'managed', 'enable_async_update' => false])->withNormalizationContext(['groups' => ['foo', 'bar']]),
×
104
        ]))]));
×
105
        $resourceMetadataFactoryProphecy->create(DummyCar::class)->willReturn(new ResourceMetadataCollection(DummyCar::class, [(new ApiResource())->withOperations(new Operations([
×
106
            'get' => new Get(),
×
107
        ]))]));
×
108
        $resourceMetadataFactoryProphecy->create(DummyFriend::class)->willReturn(new ResourceMetadataCollection(DummyFriend::class, [(new ApiResource())->withOperations(new Operations([
×
109
            'get' => (new Get())->withTypes('https://schema.org/Person')->withShortName('DummyFriend')->withMercure(['private' => true, 'retry' => 10, 'hub' => 'managed', 'enable_async_update' => false]),
×
110
        ]))]));
×
111
        $resourceMetadataFactoryProphecy->create(DummyOffer::class)->willReturn(new ResourceMetadataCollection(DummyOffer::class, [(new ApiResource())->withOperations(new Operations([
×
112
            'get' => (new Get())->withShortName('DummyOffer')->withMercure(['topics' => 'http://example.com/custom_topics/1', 'data' => 'mercure_custom_data', 'hub' => 'managed', 'enable_async_update' => false])->withNormalizationContext(['groups' => ['baz']]),
×
113
        ]))]));
×
114
        $resourceMetadataFactoryProphecy->create(DummyMercure::class)->willReturn(new ResourceMetadataCollection(DummyMercure::class, [(new ApiResource())->withOperations(new Operations([
×
115
            'get' => (new Get())->withMercure(['topics' => ['/dummies/1', '/users/3'], 'hub' => 'managed', 'enable_async_update' => false])->withNormalizationContext(['groups' => ['baz']]),
×
116
        ]))]));
×
117

118
        $serializerProphecy = $this->prophesize(SerializerInterface::class);
×
119
        $serializerProphecy->serialize($toInsert, 'jsonld', ['groups' => ['foo', 'bar']])->willReturn('1');
×
120
        $serializerProphecy->serialize($toUpdate, 'jsonld', ['groups' => ['foo', 'bar']])->willReturn('2');
×
121
        $serializerProphecy->serialize($toUpdateMercureOptions, 'jsonld', ['groups' => ['baz']])->willReturn('mercure_options');
×
122
        $serializerProphecy->serialize($toUpdateMercureTopicOptions, 'jsonld', ['groups' => ['baz']])->willReturn('mercure_options');
×
123

124
        $formats = ['jsonld' => ['application/ld+json'], 'jsonhal' => ['application/hal+json']];
×
125

126
        $topics = [];
×
127
        $private = [];
×
128
        $retry = [];
×
129
        $data = [];
×
130

131
        $managedHub = $this->createMockHub(function (Update $update) use (&$topics, &$private, &$retry, &$data): string {
×
132
            $topics = array_merge($topics, $update->getTopics());
×
133
            $private[] = $update->isPrivate();
×
134
            $retry[] = $update->getRetry();
×
135
            $data[] = $update->getData();
×
136

137
            return 'id';
×
138
        });
×
139

140
        $listener = new PublishMercureUpdatesListener(
×
141
            $resourceClassResolverProphecy->reveal(),
×
142
            $iriConverterProphecy->reveal(),
×
143
            $resourceMetadataFactoryProphecy->reveal(),
×
144
            $serializerProphecy->reveal(),
×
145
            $formats,
×
146
            null,
×
147
            new HubRegistry($this->createMock(HubInterface::class), [
×
148
                'managed' => $managedHub,
×
149
            ]),
×
150
            null,
×
151
            null,
×
152
            null,
×
153
            true,
×
154
        );
×
155

156
        $uowProphecy = $this->prophesize(UnitOfWork::class);
×
157
        $uowProphecy->getScheduledEntityInsertions()->willReturn([$toInsert, $toInsertNotResource])->shouldBeCalled();
×
158
        $uowProphecy->getScheduledEntityUpdates()->willReturn([$toUpdate, $toUpdateNoMercureAttribute, $toUpdateMercureOptions, $toUpdateMercureTopicOptions])->shouldBeCalled();
×
159
        $uowProphecy->getScheduledEntityDeletions()->willReturn([$toDelete, $toDeleteExpressionLanguage, $toDeleteMercureOptions])->shouldBeCalled();
×
160

161
        $emProphecy = $this->prophesize(EntityManagerInterface::class);
×
162
        $emProphecy->getUnitOfWork()->willReturn($uowProphecy->reveal())->shouldBeCalled();
×
163
        $eventArgs = new OnFlushEventArgs($emProphecy->reveal());
×
164

165
        $listener->onFlush($eventArgs);
×
166
        $listener->postFlush();
×
167

168
        $this->assertEquals(['1', '2', 'mercure_custom_data', 'mercure_options', '{"@id":"\/dummies\/3","@type":"Dummy"}', '{"@id":"\/dummy_friends\/4","@type":"https:\/\/schema.org\/Person"}', '{"@id":"\/dummy_offers\/5","@type":"DummyOffer"}'], $data);
×
169
        $this->assertEquals(['http://example.com/dummies/1', 'http://example.com/dummies/2', 'http://example.com/custom_topics/1', '/dummies/1', '/users/3', 'http://example.com/dummies/3', 'http://example.com/dummy_friends/4', 'http://example.com/custom_topics/1'], $topics);
×
170
        $this->assertEquals([false, false, false, false, false, true, false], $private);
×
171
        $this->assertEquals([null, null, null, null, null, 10, null], $retry);
×
172
    }
173

174
    public function testPublishUpdateMultipleTopicsUsingExpressionLanguage(): void
175
    {
176
        $mercure = [
×
177
            'topics' => [
×
178
                '@=iri(object)',
×
179
                '@=iri(object, '.UrlGeneratorInterface::ABS_PATH.')',
×
180
                '@=iri(object, '.UrlGeneratorInterface::ABS_URL.', get_operation(object, "/custom_resource/mercure_with_topics_and_get_operations/{id}{._format}"))',
×
181
            ],
×
182
        ];
×
183

184
        $toInsert = new MercureWithTopicsAndGetOperation();
×
185
        $toInsert->id = 1;
×
186
        $toInsert->name = 'Hello World!';
×
187

188
        $toUpdate = new MercureWithTopicsAndGetOperation();
×
189
        $toUpdate->id = 2;
×
190
        $toUpdate->name = 'Hello World!';
×
191

192
        $toDelete = new MercureWithTopicsAndGetOperation();
×
193
        $toDelete->id = 3;
×
194
        $toDelete->name = 'Hello World!';
×
195

196
        // Even if it's the Post operation which sends Updates to Mercure,
197
        // the `mercure` configuration is retrieved from the first operation
198
        // of the resource because the Doctrine Listener doesn't have a
199
        // reference to the operation.
200
        $getOperation = (new Get())->withMercure($mercure)->withShortName('MercureWithTopicsAndGetOperation');
×
201
        $customGetOperation = (new Get(uriTemplate: '/custom_resource/mercure_with_topics_and_get_operations/{id}{._format}'));
×
202
        $postOperation = (new Post());
×
203

204
        $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class);
×
205
        $resourceClassResolverProphecy->getResourceClass(Argument::type(MercureWithTopicsAndGetOperation::class))->willReturn(MercureWithTopicsAndGetOperation::class);
×
206
        $resourceClassResolverProphecy->isResourceClass(MercureWithTopicsAndGetOperation::class)->willReturn(true);
×
207

208
        $iriConverterProphecy = $this->prophesize(IriConverterInterface::class);
×
209

210
        $iriConverterProphecy->getIriFromResource($toInsert, UrlGeneratorInterface::ABS_URL, null)->willReturn('http://example.com/mercure_with_topics_and_get_operations/1')->shouldBeCalled();
×
211
        $iriConverterProphecy->getIriFromResource($toInsert, UrlGeneratorInterface::ABS_PATH, null)->willReturn('/mercure_with_topics_and_get_operations/1')->shouldBeCalled();
×
212
        $iriConverterProphecy->getIriFromResource($toInsert, UrlGeneratorInterface::ABS_URL, Argument::exact($customGetOperation))->willReturn('http://example.com/custom_resource/mercure_with_topics_and_get_operations/1')->shouldBeCalled();
×
213

214
        $iriConverterProphecy->getIriFromResource($toUpdate, UrlGeneratorInterface::ABS_URL, null)->willReturn('http://example.com/mercure_with_topics_and_get_operations/2')->shouldBeCalled();
×
215
        $iriConverterProphecy->getIriFromResource($toUpdate, UrlGeneratorInterface::ABS_PATH, null)->willReturn('/mercure_with_topics_and_get_operations/2')->shouldBeCalled();
×
216
        $iriConverterProphecy->getIriFromResource($toUpdate, UrlGeneratorInterface::ABS_URL, Argument::exact($customGetOperation))->willReturn('http://example.com/custom_resource/mercure_with_topics_and_get_operations/2')->shouldBeCalled();
×
217

218
        $iriConverterProphecy->getIriFromResource($toDelete)->willReturn('/mercure_with_topics_and_get_operations/3')->shouldBeCalled();
×
219
        $iriConverterProphecy->getIriFromResource($toDelete, UrlGeneratorInterface::ABS_URL, null)->willReturn('http://example.com/mercure_with_topics_and_get_operations/3')->shouldBeCalled();
×
220
        $iriConverterProphecy->getIriFromResource($toDelete, UrlGeneratorInterface::ABS_PATH, null)->willReturn('/mercure_with_topics_and_get_operations/3')->shouldBeCalled();
×
221
        $iriConverterProphecy->getIriFromResource($toDelete, UrlGeneratorInterface::ABS_URL, Argument::exact($customGetOperation))->willReturn('http://example.com/custom_resource/mercure_with_topics_and_get_operations/3')->shouldBeCalled();
×
222

223
        $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class);
×
224

225
        $resourceMetadataFactoryProphecy->create(MercureWithTopicsAndGetOperation::class)->willReturn(new ResourceMetadataCollection(MercureWithTopicsAndGetOperation::class, [
×
226
            (new ApiResource())->withOperations(new Operations([
×
227
                'get' => $getOperation,
×
228
                'custom_get' => $customGetOperation,
×
229
                'post' => $postOperation,
×
230
            ])),
×
231
        ]))->shouldBeCalled();
×
232

233
        $serializerProphecy = $this->prophesize(SerializerInterface::class);
×
234
        $serializerProphecy->serialize($toInsert, 'jsonld', [])->willReturn('{"@type":"MercureWithTopicsAndGetOperation","@id":"/mercure_with_topics_and_get_operations/1","id":1,"name":"Hello World!"}')->shouldBeCalled();
×
235
        $serializerProphecy->serialize($toUpdate, 'jsonld', [])->willReturn('{"@type":"MercureWithTopicsAndGetOperation","@id":"/mercure_with_topics_and_get_operations/2","id":2,"name":"Hello World!"}')->shouldBeCalled();
×
236

237
        $formats = ['jsonld' => ['application/ld+json'], 'jsonhal' => ['application/hal+json']];
×
238

239
        $topics = [];
×
240
        $private = [];
×
241
        $retry = [];
×
242
        $data = [];
×
243

244
        $defaultHub = $this->createMockHub(function (Update $update) use (&$topics, &$private, &$retry, &$data): string {
×
245
            $topics = array_merge($topics, $update->getTopics());
×
246
            $private[] = $update->isPrivate();
×
247
            $retry[] = $update->getRetry();
×
248
            $data[] = $update->getData();
×
249

250
            return 'id';
×
251
        });
×
252

253
        $listener = new PublishMercureUpdatesListener(
×
254
            $resourceClassResolverProphecy->reveal(),
×
255
            $iriConverterProphecy->reveal(),
×
256
            $resourceMetadataFactoryProphecy->reveal(),
×
257
            $serializerProphecy->reveal(),
×
258
            $formats,
×
259
            null,
×
260
            new HubRegistry($defaultHub, ['default' => $defaultHub]),
×
261
            null,
×
262
            null,
×
263
            null,
×
264
            true,
×
265
        );
×
266

267
        $uowProphecy = $this->prophesize(UnitOfWork::class);
×
268
        $uowProphecy->getScheduledEntityInsertions()->willReturn([$toInsert])->shouldBeCalled();
×
269
        $uowProphecy->getScheduledEntityUpdates()->willReturn([$toUpdate])->shouldBeCalled();
×
270
        $uowProphecy->getScheduledEntityDeletions()->willReturn([$toDelete])->shouldBeCalled();
×
271

272
        $emProphecy = $this->prophesize(EntityManagerInterface::class);
×
273
        $emProphecy->getUnitOfWork()->willReturn($uowProphecy->reveal())->shouldBeCalled();
×
274
        $eventArgs = new OnFlushEventArgs($emProphecy->reveal());
×
275

276
        $listener->onFlush($eventArgs);
×
277
        $listener->postFlush();
×
278

279
        $this->assertEquals([
×
280
            '{"@type":"MercureWithTopicsAndGetOperation","@id":"/mercure_with_topics_and_get_operations/1","id":1,"name":"Hello World!"}',
×
281
            '{"@type":"MercureWithTopicsAndGetOperation","@id":"/mercure_with_topics_and_get_operations/2","id":2,"name":"Hello World!"}',
×
282
            '{"@id":"\/mercure_with_topics_and_get_operations\/3","@type":"MercureWithTopicsAndGetOperation"}',
×
283
        ], $data);
×
284
        $this->assertEquals([
×
285
            'http://example.com/mercure_with_topics_and_get_operations/1', '/mercure_with_topics_and_get_operations/1', 'http://example.com/custom_resource/mercure_with_topics_and_get_operations/1',
×
286
            'http://example.com/mercure_with_topics_and_get_operations/2', '/mercure_with_topics_and_get_operations/2', 'http://example.com/custom_resource/mercure_with_topics_and_get_operations/2',
×
287
            'http://example.com/mercure_with_topics_and_get_operations/3', '/mercure_with_topics_and_get_operations/3', 'http://example.com/custom_resource/mercure_with_topics_and_get_operations/3',
×
288
        ], $topics);
×
289
    }
290

291
    public function testPublishGraphQlUpdates(): void
292
    {
293
        $toUpdate = new Dummy();
×
294
        $toUpdate->setId(2);
×
295

296
        $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class);
×
297
        $resourceClassResolverProphecy->getResourceClass(Argument::type(Dummy::class))->willReturn(Dummy::class);
×
298
        $resourceClassResolverProphecy->isResourceClass(Dummy::class)->willReturn(true);
×
299

300
        $iriConverterProphecy = $this->prophesize(IriConverterInterface::class);
×
301
        $iriConverterProphecy->getIriFromResource($toUpdate, UrlGeneratorInterface::ABS_URL)->willReturn('http://example.com/dummies/2');
×
302

303
        $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class);
×
304
        $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadataCollection(Dummy::class, [(new ApiResource())->withOperations(new Operations([
×
305
            'get' => (new Get())->withMercure(['enable_async_update' => false])->withNormalizationContext(['groups' => ['foo', 'bar']]),
×
306
        ]))]));
×
307

308
        $serializerProphecy = $this->prophesize(SerializerInterface::class);
×
309
        $serializerProphecy->serialize($toUpdate, 'jsonld', ['groups' => ['foo', 'bar']])->willReturn('2');
×
310

311
        $formats = ['jsonld' => ['application/ld+json'], 'jsonhal' => ['application/hal+json']];
×
312

313
        $topics = [];
×
314
        $private = [];
×
315
        $retry = [];
×
316
        $data = [];
×
317

318
        $defaultHub = $this->createMockHub(function (Update $update) use (&$topics, &$private, &$retry, &$data): string {
×
319
            $topics = array_merge($topics, $update->getTopics());
×
320
            $private[] = $update->isPrivate();
×
321
            $retry[] = $update->getRetry();
×
322
            $data[] = $update->getData();
×
323

324
            return 'id';
×
325
        });
×
326

327
        $graphQlSubscriptionManagerProphecy = $this->prophesize(GraphQlSubscriptionManagerInterface::class);
×
328
        $graphQlSubscriptionId = 'subscription-id';
×
329
        $graphQlSubscriptionData = ['data'];
×
NEW
330
        $graphQlSubscriptionManagerProphecy->getPushPayloads($toUpdate, 'update')->willReturn([[$graphQlSubscriptionId, $graphQlSubscriptionData]]);
×
331
        $graphQlMercureSubscriptionIriGenerator = $this->prophesize(GraphQlMercureSubscriptionIriGeneratorInterface::class);
×
332
        $topicIri = 'subscription-topic-iri';
×
333
        $graphQlMercureSubscriptionIriGenerator->generateTopicIri($graphQlSubscriptionId)->willReturn($topicIri);
×
334

335
        $listener = new PublishMercureUpdatesListener(
×
336
            $resourceClassResolverProphecy->reveal(),
×
337
            $iriConverterProphecy->reveal(),
×
338
            $resourceMetadataFactoryProphecy->reveal(),
×
339
            $serializerProphecy->reveal(),
×
340
            $formats,
×
341
            null,
×
342
            new HubRegistry($defaultHub, ['default' => $defaultHub]),
×
343
            $graphQlSubscriptionManagerProphecy->reveal(),
×
344
            $graphQlMercureSubscriptionIriGenerator->reveal(),
×
345
            null,
×
346
            true,
×
347
        );
×
348

349
        $uowProphecy = $this->prophesize(UnitOfWork::class);
×
350
        $uowProphecy->getScheduledEntityInsertions()->willReturn([])->shouldBeCalled();
×
351
        $uowProphecy->getScheduledEntityUpdates()->willReturn([$toUpdate])->shouldBeCalled();
×
352
        $uowProphecy->getScheduledEntityDeletions()->willReturn([])->shouldBeCalled();
×
353

354
        $emProphecy = $this->prophesize(EntityManagerInterface::class);
×
355
        $emProphecy->getUnitOfWork()->willReturn($uowProphecy->reveal())->shouldBeCalled();
×
356
        $eventArgs = new OnFlushEventArgs($emProphecy->reveal());
×
357

358
        $listener->onFlush($eventArgs);
×
359
        $listener->postFlush();
×
360

361
        $this->assertEquals(['http://example.com/dummies/2', 'subscription-topic-iri'], $topics);
×
362
        $this->assertEquals([false, false], $private);
×
363
        $this->assertEquals([null, null], $retry);
×
364
        $this->assertEquals(['2', '["data"]'], $data);
×
365
    }
366

367
    private function createMockHub(callable $callable): HubInterface
368
    {
369
        return new MockHub('https://mercure.demo/.well-known/mercure', new StaticTokenProvider('x'), $callable);
×
370
    }
371
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc