Completed
Push — master ( eeedf4...3b415d )
by Alejandro
02:34
created

test/Service/MailServiceAbstractFactoryTest.php (5 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
namespace AcMailerTest\Service;
3
4
use AcMailer\Event\MailEvent;
5
use AcMailer\Options\MailOptions;
6
use AcMailer\Service\Factory\MailServiceAbstractFactory;
7
use AcMailer\Service\Factory\MailServiceFactory;
8
use AcMailerTest\Event\MailListenerMock;
9
use AcMailerTest\ServiceManager\ServiceManagerMock;
10
use Zend\EventManager\EventManagerAwareInterface;
11
use Zend\Mail\Transport\File;
12
use Zend\Mail\Transport\Sendmail;
13
use Zend\Mail\Transport\Smtp;
14
use Zend\ServiceManager\ServiceLocatorInterface;
15
use Zend\Stdlib\ArrayUtils;
16
use Zend\View\Renderer\PhpRenderer;
17
use Zend\View\Resolver\TemplatePathStack;
18
use PHPUnit_Framework_TestCase as TestCase;
19
20
/**
21
 * Class MailServiceFactoryTest
22
 * @author Alejandro Celaya Alastrué
23
 * @link http://www.alejandrocelaya.com
24
 */
25
class MailServiceAbstractFactoryTest extends TestCase
26
{
27
    /**
28
     * @var MailServiceAbstractFactory
29
     */
30
    private $mailServiceFactory;
31
    /**
32
     * @var ServiceLocatorInterface
33
     */
34
    private $serviceLocator;
35
36
    public function setUp()
37
    {
38
        $this->mailServiceFactory = new MailServiceAbstractFactory();
39
    }
40
41
    public function testMessageData()
42
    {
43
        $options = [
44
            'message_options' => [
45
                'from'          => '[email protected]',
46
                'from_name'     => 'Alejandro Celaya',
47
                'reply_to'      => '[email protected]',
48
                'reply_to_name' => 'Alejandro Celaya',
49
                'to'            => ['[email protected]', '[email protected]'],
50
                'cc'            => ['[email protected]'],
51
                'bcc'           => ['[email protected]'],
52
                'subject'       => 'The subject',
53
                'body'          => ['content' => 'The body'],
54
            ]
55
        ];
56
        $this->initServiceLocator($options);
57
        $mailService = $this->mailServiceFactory->createServiceWithName(
58
            $this->serviceLocator,
59
            'acmailer.mailservice.default',
60
            ''
61
        );
62
63
        $this->assertInstanceOf('AcMailer\Service\MailService', $mailService);
64
        $this->assertEquals(
65
            $options['message_options']['from_name'],
66
            $mailService->getMessage()->getFrom()->get($options['message_options']['from'])->getName()
67
        );
68
        $this->assertEquals(
69
            $options['message_options']['reply_to_name'],
70
            $mailService->getMessage()->getReplyTo()->get($options['message_options']['reply_to'])->getName()
71
        );
72
        $toArray = array_keys(ArrayUtils::iteratorToArray($mailService->getMessage()->getTo()));
73
        $ccArray = array_keys(ArrayUtils::iteratorToArray($mailService->getMessage()->getCc()));
74
        $bccArray = array_keys(ArrayUtils::iteratorToArray($mailService->getMessage()->getBcc()));
75
        $this->assertEquals($options['message_options']['to'], $toArray);
76
        $this->assertEquals($options['message_options']['cc'], $ccArray);
77
        $this->assertEquals($options['message_options']['bcc'], $bccArray);
78
        $this->assertEquals($options['message_options']['subject'], $mailService->getMessage()->getSubject());
79
        $this->assertInstanceof('Zend\Mime\Message', $mailService->getMessage()->getBody());
80
    }
81
82
    public function testSmtpAdapter()
83
    {
84
        $options = [
85
            'mail_adapter' => 'Zend\Mail\Transport\Smtp',
86
            'smtp_options' => [
87
                'host'  => 'the.host',
88
                'port'  => 465,
89
                'connection_config' => [
90
                    'username'  => 'alejandro',
91
                    'password'  => '1234',
92
                    'ssl'       => 'ssl',
93
                ]
94
            ]
95
        ];
96
        $this->initServiceLocator($options);
97
        $mailService = $this->mailServiceFactory->createServiceWithName(
98
            $this->serviceLocator,
99
            'acmailer.mailservice.default',
100
            ''
101
        );
102
103
        /* @var Smtp $transport */
104
        $transport = $mailService->getTransport();
105
        $this->assertInstanceOf($options['mail_adapter'], $transport);
106
        $connConfig = $transport->getOptions()->getConnectionConfig();
107
        $this->assertEquals($options['smtp_options']['connection_config']['username'], $connConfig['username']);
108
        $this->assertEquals($options['smtp_options']['connection_config']['password'], $connConfig['password']);
109
        $this->assertEquals($options['smtp_options']['connection_config']['ssl'], $connConfig['ssl']);
110
        $this->assertEquals($options['smtp_options']['host'], $transport->getOptions()->getHost());
111
        $this->assertEquals($options['smtp_options']['port'], $transport->getOptions()->getPort());
112
    }
113
114
    public function testFileAdapter()
115
    {
116
        $options = [
117
            'mail_adapter'  => 'file',
118
            'file_options' => [
119
                'path'     => __DIR__,
120
                'callback' => function ($transport) {
121
                    return get_class($transport);
122
                }
123
            ]
124
        ];
125
        $this->initServiceLocator($options);
126
        $mailService = $this->mailServiceFactory->createServiceWithName(
127
            $this->serviceLocator,
128
            'acmailer.mailservice.default',
129
            ''
130
        );
131
132
        /* @var File $transport */
133
        $transport = $mailService->getTransport();
134
        $this->assertInstanceOf('Zend\Mail\Transport\File', $transport);
135
        $this->assertEquals($options['file_options']['path'], $transport->getOptions()->getPath());
136
        $this->assertEquals($options['file_options']['callback'], $transport->getOptions()->getCallback());
137
    }
138
139 View Code Duplication
    public function testAdapterAsService()
140
    {
141
        $this->initServiceLocator([
142
            'mail_adapter' => 'my_transport_service'
143
        ]);
144
        $transport = new Sendmail();
145
        $this->serviceLocator->set('my_transport_service', $transport);
146
        $mailService = $this->mailServiceFactory->createServiceWithName(
147
            $this->serviceLocator,
148
            'acmailer.mailservice.default',
149
            ''
150
        );
151
        $this->assertSame($transport, $mailService->getTransport());
152
    }
153
154
    /**
155
     * @expectedException \AcMailer\Exception\InvalidArgumentException
156
     */
157
    public function testAdapterAsInvalidService()
158
    {
159
        $this->initServiceLocator([
160
            'mail_adapter' => 'my_transport_service'
161
        ]);
162
        $this->mailServiceFactory->createServiceWithName(
163
            $this->serviceLocator,
164
            'acmailer.mailservice.default',
165
            ''
166
        );
167
    }
168
169
    /**
170
     * @expectedException \AcMailer\Exception\InvalidArgumentException
171
     */
172
    public function testAdapterAsAserviceNotReturningTransport()
173
    {
174
        $this->initServiceLocator([
175
            'mail_adapter' => 'my_transport_service'
176
        ]);
177
        $this->serviceLocator->set('my_transport_service', new \stdClass());
178
        $this->mailServiceFactory->createServiceWithName(
179
            $this->serviceLocator,
180
            'acmailer.mailservice.default',
181
            ''
182
        );
183
    }
184
185 View Code Duplication
    public function testAdapterAsInstance()
186
    {
187
        $expected = new Sendmail();
188
        $this->initServiceLocator([
189
            'mail_adapter' => $expected
190
        ]);
191
        $mailService = $this->mailServiceFactory->createServiceWithName(
192
            $this->serviceLocator,
193
            'acmailer.mailservice.default',
194
            ''
195
        );
196
        $this->assertSame($expected, $mailService->getTransport());
197
    }
198
199
    public function testViewRendererService()
200
    {
201
        $this->initServiceLocator();
202
        // Create the service with default configuration
203
        $mailService = $this->mailServiceFactory->createServiceWithName(
204
            $this->serviceLocator,
205
            'acmailer.mailservice.default',
206
            ''
207
        );
208
        /** @var PhpRenderer $renderer */
209
        $renderer = $mailService->getRenderer();
210
        $this->assertInstanceOf('Zend\View\Renderer\PhpRenderer', $renderer);
211
        $this->assertInstanceOf('Zend\View\Resolver\TemplatePathStack', $renderer->resolver());
212
213
        // Set a template_map and unset the template_path_stack
214
        $config = $this->serviceLocator->get('Config');
215
        unset($config['view_manager']['template_path_stack']);
216
        $config['view_manager']['template_map'] = [];
217
        $this->serviceLocator->set('Config', $config);
0 ignored issues
show
It seems like you code against a concrete implementation and not the interface Zend\ServiceManager\ServiceLocatorInterface as the method set() does only exist in the following implementations of said interface: AcMailerTest\ServiceManager\ServiceManagerMock.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
218
        $mailService = $this->mailServiceFactory->createServiceWithName(
219
            $this->serviceLocator,
220
            'acmailer.mailservice.default',
221
            ''
222
        );
223
        /** @var PhpRenderer $renderer */
224
        $renderer = $mailService->getRenderer();
225
        $this->assertInstanceOf('Zend\View\Renderer\PhpRenderer', $renderer);
226
        $this->assertInstanceOf('Zend\View\Resolver\TemplateMapResolver', $renderer->resolver());
227
228
        // Set both a template_map and a template_path_stack
229
        $this->initServiceLocator();
230
        $config = $this->serviceLocator->get('Config');
231
        $config['view_manager']['template_map'] = [];
232
        $this->serviceLocator->set('Config', $config);
0 ignored issues
show
It seems like you code against a concrete implementation and not the interface Zend\ServiceManager\ServiceLocatorInterface as the method set() does only exist in the following implementations of said interface: AcMailerTest\ServiceManager\ServiceManagerMock.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
233
        $mailService = $this->mailServiceFactory->createServiceWithName(
234
            $this->serviceLocator,
235
            'acmailer.mailservice.default',
236
            ''
237
        );
238
        /** @var PhpRenderer $renderer */
239
        $renderer = $mailService->getRenderer();
240
        $this->assertInstanceOf('Zend\View\Renderer\PhpRenderer', $renderer);
241
        $this->assertInstanceOf('Zend\View\Resolver\AggregateResolver', $renderer->resolver());
242
243
        // Set a viewrenderer service and see if it is used
244
        $renderer = new PhpRenderer();
245
        $this->serviceLocator->set('mailviewrenderer', $renderer);
0 ignored issues
show
It seems like you code against a concrete implementation and not the interface Zend\ServiceManager\ServiceLocatorInterface as the method set() does only exist in the following implementations of said interface: AcMailerTest\ServiceManager\ServiceManagerMock.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
246
        $mailService = $this->mailServiceFactory->createServiceWithName(
247
            $this->serviceLocator,
248
            'acmailer.mailservice.default',
249
            ''
250
        );
251
        $this->assertSame($renderer, $mailService->getRenderer());
252
    }
253
254
    public function testTemplateBody()
255
    {
256
        $options = [
257
            'message_options' => [
258
                'body' => [
259
                    'content' => 'This body is not going to be used',
260
                    'use_template'  => true,
261
                    'template' => [
262
                        'path'          => 'ac-mailer/mail-templates/layout',
263
                        'children'      => [
264
                            'content'   => [
265
                                'path'   => 'ac-mailer/mail-templates/mail',
266
                            ]
267
                        ]
268
                    ],
269
                ]
270
            ]
271
        ];
272
        $this->initServiceLocator($options);
273
274
        $resolver = new TemplatePathStack();
275
        $resolver->addPath(__DIR__ . '/../../view');
276
        $renderer = new PhpRenderer();
277
        $renderer->setResolver($resolver);
278
        $this->serviceLocator->set('mailviewrenderer', $renderer);
0 ignored issues
show
It seems like you code against a concrete implementation and not the interface Zend\ServiceManager\ServiceLocatorInterface as the method set() does only exist in the following implementations of said interface: AcMailerTest\ServiceManager\ServiceManagerMock.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
279
        $mailService = $this->mailServiceFactory->createServiceWithName(
280
            $this->serviceLocator,
281
            'acmailer.mailservice.default',
282
            ''
283
        );
284
285
        $this->assertNotEquals($options ['message_options']['body']['content'], $mailService->getMessage()->getBody());
286
        $this->assertInstanceOf('Zend\Mime\Message', $mailService->getMessage()->getBody());
287
    }
288
289
    public function testWithDefaultLayout()
290
    {
291
        $options = [
292
            'message_options' => [
293
                'body' => [
294
                    'use_template'  => true,
295
                    'template' => [
296
                        'path'          => 'ac-mailer/mail-templates/mail',
297
                        'default_layout' => [
298
                            'path' => 'ac-mailer/mail-templates/layout',
299
                        ]
300
                    ],
301
                ]
302
            ]
303
        ];
304
        $this->initServiceLocator($options);
305
306
        $resolver = new TemplatePathStack();
307
        $resolver->addPath(__DIR__ . '/../../view');
308
        $renderer = new PhpRenderer();
309
        $renderer->setResolver($resolver);
310
        $this->serviceLocator->set('mailviewrenderer', $renderer);
0 ignored issues
show
It seems like you code against a concrete implementation and not the interface Zend\ServiceManager\ServiceLocatorInterface as the method set() does only exist in the following implementations of said interface: AcMailerTest\ServiceManager\ServiceManagerMock.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
311
        $mailService = $this->mailServiceFactory->createServiceWithName(
312
            $this->serviceLocator,
313
            'acmailer.mailservice.default',
314
            ''
315
        );
316
        $this->assertInstanceOf('Zend\Mime\Message', $mailService->getMessage()->getBody());
317
    }
318
319
    public function testFileAttachments()
320
    {
321
        $cwd = getcwd();
322
        chdir(dirname(__DIR__));
323
        $options = [
324
            'message_options' => [
325
                'attachments' => [
326
                    'files' => [
327
                        'attachments/file1',
328
                        'attachments/file2',
329
                    ],
330
                    'dir' => [
331
                        'iterate'   => true,
332
                        'path'      => 'attachments/dir',
333
                        'recursive' => true,
334
                    ],
335
                ],
336
            ]
337
        ];
338
        $this->initServiceLocator($options);
339
        $mailService = $this->mailServiceFactory->createServiceWithName(
340
            $this->serviceLocator,
341
            'acmailer.mailservice.default',
342
            ''
343
        );
344
345
        $this->assertCount(4, $mailService->getAttachments());
346
        chdir($cwd);
347
    }
348
349
    public function testListeners()
350
    {
351
        $options = [
352
            'mail_listeners' => [
353
                new MailListenerMock(),
354
                'mail_listener_service',
355
                'AcMailerTest\Event\MailListenerMock'
356
            ]
357
        ];
358
        $this->initServiceLocator($options);
359
        $this->serviceLocator->set('mail_listener_service', new MailListenerMock());
360
361
        /** @var EventManagerAwareInterface $mailService */
362
        $mailService = $this->mailServiceFactory->createServiceWithName(
363
            $this->serviceLocator,
364
            'acmailer.mailservice.default',
365
            ''
366
        );
367
        $this->assertCount(3, $mailService->getEventManager()->getListeners(MailEvent::EVENT_MAIL_PRE_SEND));
368
    }
369
370
    /**
371
     * @expectedException \AcMailer\Exception\InvalidArgumentException
372
     */
373
    public function testInvalidListenersThrowException()
374
    {
375
        $options = [
376
            'mail_listeners' => [
377
                new \stdClass(),
378
                'invalid_service',
379
                '\Nonsens\Foo'
380
            ]
381
        ];
382
        $this->initServiceLocator($options);
383
        $this->mailServiceFactory->createServiceWithName(
384
            $this->serviceLocator,
385
            'acmailer.mailservice.default',
386
            ''
387
        );
388
    }
389
390
    private function initServiceLocator(array $mailOptions = [])
391
    {
392
        $this->serviceLocator = new ServiceManagerMock([
393
            'acmailer.mailoptions.default' => new MailOptions($mailOptions),
394
            'Config' => include __DIR__ . '/../../config/module.config.php'
395
        ]);
396
    }
397
}
398