recursiveLoopOnExtendsThrowsException()   B
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 32
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 32
c 0
b 0
f 0
rs 8.8571
cc 1
eloc 20
nc 1
nop 0
1
<?php
2
declare(strict_types=1);
3
4
namespace AcMailerTest\Service\Factory;
5
6
use AcMailer\Attachment\AttachmentParserManager;
7
use AcMailer\Event\MailListenerInterface;
8
use AcMailer\Exception;
9
use AcMailer\Model\EmailBuilder;
10
use AcMailer\Model\EmailBuilderInterface;
11
use AcMailer\Service\Factory\MailServiceAbstractFactory;
12
use AcMailer\Service\MailService;
13
use AcMailer\View\MailViewRendererFactory;
14
use Interop\Container\ContainerInterface;
15
use PHPUnit\Framework\TestCase;
16
use Prophecy\Prophecy\ObjectProphecy;
17
use Zend\Expressive\Template\TemplateRendererInterface;
18
use Zend\Mail\Transport\Sendmail;
19
use Zend\Mail\Transport\Smtp;
20
use Zend\Mail\Transport\TransportInterface;
21
use Zend\View\Renderer\RendererInterface;
22
23
class MailServiceAbstractFactoryTest extends TestCase
24
{
25
    /**
26
     * @var MailServiceAbstractFactory
27
     */
28
    private $factory;
29
    /**
30
     * @var ObjectProphecy
31
     */
32
    private $container;
33
34
    public function setUp()
35
    {
36
        $this->factory = new MailServiceAbstractFactory();
37
        $this->container = $this->prophesize(ContainerInterface::class);
38
    }
39
40
    /**
41
     * @test
42
     * @dataProvider provideServiceNames
43
     * @param string $requestedName
44
     * @param bool $expected
45
     */
46
    public function canCreateReturnsProperResult(string $requestedName, bool $expected)
47
    {
48
        $this->container->get('config')->willReturn([
49
            'acmailer_options' => [
50
                'mail_services' => [
51
                    'default' => [],
52
                ],
53
            ],
54
        ]);
55
56
        $result = $this->factory->canCreate($this->container->reveal(), $requestedName);
57
        $this->assertEquals($expected, $result);
58
    }
59
60
    public function provideServiceNames(): array
61
    {
62
        return [
63
            ['invalid', false],
64
            ['acmailer.mailservice', false],
65
            ['foo.mailservice.invalid', false],
66
            ['acmailer.foo.bar', false],
67
            ['foo.bar.baz', false],
68
            ['acmailer.mailservice.invalid', false],
69
            ['acmailer.mailservice.default', true],
70
        ];
71
    }
72
73
    /**
74
     * @test
75
     */
76
    public function exceptionIsThrownIfRequestedConfigIsNotFound()
77
    {
78
        $this->container->get('config')->willReturn([
79
            'acmailer_options' => [
80
                'mail_services' => [
81
                    'default' => [],
82
                ],
83
            ],
84
        ]);
85
86
        $this->expectException(Exception\ServiceNotCreatedException::class);
87
        $this->factory->__invoke($this->container->reveal(), 'acmailer.mailservice.invalid');
88
    }
89
90
    /**
91
     * @test
92
     * @dataProvider provideValidServiceConfig
93
     * @param array $config
94
     */
95
    public function serviceIsCreatedIfConfigIsCorrect(array $config)
96
    {
97
        $this->container->get('config')->willReturn([
98
            'acmailer_options' => [
99
                'mail_services' => [
100
                    'default' => $config,
101
                ],
102
            ],
103
        ]);
104
        $this->container->has(Sendmail::class)->willReturn(false);
105
        $this->container->get(MailViewRendererFactory::SERVICE_NAME)->willReturn(
106
            $this->prophesize(TemplateRendererInterface::class)->reveal()
107
        );
108
        $this->container->get('my_renderer')->willReturn(
109
            $this->prophesize(TemplateRendererInterface::class)->reveal()
110
        );
111
        $this->container->get(EmailBuilder::class)->willReturn(
112
            $this->prophesize(EmailBuilderInterface::class)->reveal()
113
        );
114
        $this->container->get(AttachmentParserManager::class)->willReturn(
115
            $this->prophesize(AttachmentParserManager::class)->reveal()
116
        );
117
118
        $result = $this->factory->__invoke($this->container->reveal(), 'acmailer.mailservice.default');
119
120
        $this->assertInstanceOf(MailService::class, $result);
121
    }
122
123
    public function provideValidServiceConfig()
124
    {
125
        return [
126
            [[
127
                'transport' => 'sendmail',
128
            ]],
129
            [[
130
                'transport' => new Smtp(),
131
            ]],
132
            [[
133
                'transport' => new Smtp(),
134
                'renderer' => 'my_renderer',
135
            ]],
136
        ];
137
    }
138
139
    /**
140
     * @test
141
     * @dataProvider provideInvalidTransports
142
     * @param $transport
143
     * @param bool $inContainer
144
     */
145
    public function exceptionIsThrownIfConfiguredTransportHasAnInvalidValue($transport, bool $inContainer)
146
    {
147
        $this->container->get('config')->willReturn([
148
            'acmailer_options' => [
149
                'mail_services' => [
150
                    'default' => [
151
                        'transport' => $transport,
152
                    ],
153
                ],
154
            ],
155
        ]);
156
        $this->container->has($transport)->willReturn($inContainer);
157
        if ($inContainer) {
158
            $this->container->get($transport)->willReturn(new \stdClass());
159
        }
160
161
        $this->expectException(Exception\InvalidArgumentException::class);
162
        $this->factory->__invoke($this->container->reveal(), 'acmailer.mailservice.default');
163
    }
164
165
    public function provideInvalidTransports(): array
166
    {
167
        return [
168
            [new \stdClass(), false],
169
            [800, false],
170
            ['my_transport', true],
171
            ['my_transport', false],
172
        ];
173
    }
174
175
    /**
176
     * @test
177
     */
178
    public function wrongCustomRendererThrowsException()
179
    {
180
        $this->container->get('config')->willReturn([
181
            'acmailer_options' => [
182
                'mail_services' => [
183
                    'default' => [
184
                        'transport' => 'sendmail',
185
                        'renderer' => 'foo_renderer',
186
                    ],
187
                ],
188
            ],
189
        ]);
190
        $this->container->has(Sendmail::class)->willReturn(false);
191
        $this->container->get('foo_renderer')->willReturn(new \stdClass());
192
193
        $this->expectException(Exception\InvalidArgumentException::class);
194
        $this->expectExceptionMessage(\sprintf(
195
            'Defined renderer of type "%s" is not valid. The renderer must resolve to a "%s" instance',
196
            \stdClass::class,
197
            TemplateRendererInterface::class
198
        ));
199
        $this->factory->__invoke($this->container->reveal(), 'acmailer.mailservice.default');
200
    }
201
202
    /**
203
     * @test
204
     */
205
    public function recursiveLoopOnExtendsThrowsException()
206
    {
207
        $this->container->get('config')->willReturn([
208
            'acmailer_options' => [
209
                'mail_services' => [
210
                    'default' => [
211
                        'transport' => 'sendmail',
212
                        'extends' => 'another',
213
                    ],
214
                    'another' => [
215
                        'extends' => 'foo',
216
                    ],
217
                    'foo' => [
218
                        'extends' => 'default',
219
                    ],
220
                ],
221
            ],
222
        ]);
223
        $this->container->has(Sendmail::class)->willReturn(false);
224
        $this->container->get(MailViewRendererFactory::SERVICE_NAME)->willReturn(
225
            $this->prophesize(RendererInterface::class)->reveal()
226
        );
227
        $this->container->get(EmailBuilder::class)->willReturn(
228
            $this->prophesize(EmailBuilderInterface::class)->reveal()
229
        );
230
231
        $this->expectException(Exception\ServiceNotCreatedException::class);
232
        $this->expectExceptionMessage(
233
            'It wasn\'t possible to create a mail service due to circular inheritance. Review "extends".'
234
        );
235
        $this->factory->__invoke($this->container->reveal(), 'acmailer.mailservice.default');
236
    }
237
238
    /**
239
     * @test
240
     */
241
    public function extendFromInvalidServiceThrowsException()
242
    {
243
        $this->container->get('config')->willReturn([
244
            'acmailer_options' => [
245
                'mail_services' => [
246
                    'default' => [
247
                        'transport' => 'sendmail',
248
                        'extends' => 'invalid',
249
                    ],
250
                ],
251
            ],
252
        ]);
253
        $this->container->has(Sendmail::class)->willReturn(false);
254
        $this->container->get(MailViewRendererFactory::SERVICE_NAME)->willReturn(
255
            $this->prophesize(RendererInterface::class)->reveal()
256
        );
257
        $this->container->get(EmailBuilder::class)->willReturn(
258
            $this->prophesize(EmailBuilderInterface::class)->reveal()
259
        );
260
261
        $this->expectException(Exception\InvalidArgumentException::class);
262
        $this->expectExceptionMessage(
263
            'Provided service "invalid" to extend from is not configured inside acmailer_options.mail_services'
264
        );
265
        $this->factory->__invoke($this->container->reveal(), 'acmailer.mailservice.default');
266
    }
267
268
    /**
269
     * @test
270
     */
271
    public function extendedConfigIsProperlyApplied()
272
    {
273
        $this->container->get('config')->willReturn([
274
            'acmailer_options' => [
275
                'mail_services' => [
276
                    'default' => [
277
                        'extends' => 'another',
278
                    ],
279
                    'another' => [
280
                        'extends' => 'foo',
281
                        'renderer' => 'my_renderer',
282
                    ],
283
                    'foo' => [
284
                        'transport' => 'my_transport',
285
                    ],
286
                ],
287
            ],
288
        ]);
289
        $this->container->has('my_transport')->willReturn(true)->shouldBeCalled();
290
        $this->container->get('my_transport')->willReturn(
291
            $this->prophesize(TransportInterface::class)->reveal()
292
        )->shouldBeCalled();
293
        $this->container->get('my_renderer')->willReturn(
294
            $this->prophesize(TemplateRendererInterface::class)->reveal()
295
        )->shouldBeCalled();
296
        $this->container->get(EmailBuilder::class)->willReturn(
297
            $this->prophesize(EmailBuilderInterface::class)->reveal()
298
        );
299
        $this->container->get(AttachmentParserManager::class)->willReturn(
300
            $this->prophesize(AttachmentParserManager::class)->reveal()
301
        );
302
303
        $result = $this->factory->__invoke($this->container->reveal(), 'acmailer.mailservice.default');
304
305
        $this->assertInstanceOf(MailService::class, $result);
306
    }
307
308
    /**
309
     * @test
310
     */
311
    public function listenersAreAttached()
312
    {
313
        $this->container->get('config')->willReturn([
314
            'acmailer_options' => [
315
                'mail_services' => [
316
                    'default' => [
317
                        'transport' => 'sendmail',
318
                        'mail_listeners' => [
319
                            $this->prophesize(MailListenerInterface::class)->reveal(),
320
                            'my_lazy_listener',
321
                            [
322
                                'listener' => 'another_lazy_listener',
323
                                'priority' => 3,
324
                            ],
325
                        ],
326
                    ],
327
                ],
328
            ],
329
        ]);
330
        $this->container->has(Sendmail::class)->willReturn(false);
331
        $this->container->get(MailViewRendererFactory::SERVICE_NAME)->willReturn(
332
            $this->prophesize(TemplateRendererInterface::class)->reveal()
333
        );
334
        $this->container->get(EmailBuilder::class)->willReturn(
335
            $this->prophesize(EmailBuilderInterface::class)->reveal()
336
        );
337
        $this->container->get(AttachmentParserManager::class)->willReturn(
338
            $this->prophesize(AttachmentParserManager::class)->reveal()
339
        );
340
341
        $result = $this->factory->__invoke($this->container->reveal(), 'acmailer.mailservice.default');
342
343
        $this->assertInstanceOf(MailService::class, $result);
344
345
        $ref = new \ReflectionObject($result->getEventManager());
346
        $prop = $ref->getProperty('events');
347
        $prop->setAccessible(true);
348
        $this->assertCount(3, $prop->getValue($result->getEventManager()));
349
    }
350
}
351