Failed Conditions
Push — master ( 5c622e...91b182 )
by Adrien
07:46
created

MailerTest::createBookable()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 4
nc 1
nop 2
dl 0
loc 7
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace ApplicationTest\Service;
6
7
use Application\DBAL\Types\MessageTypeType;
8
use Application\Model\Account;
9
use Application\Model\Bookable;
10
use Application\Model\Message;
11
use Application\Model\User;
12
use Application\Service\Mailer;
13
use Doctrine\ORM\EntityManager;
14
use Prophecy\Argument;
15
use Zend\Mail\Transport\InMemory;
16
use Zend\View\Renderer\RendererInterface;
17
18
class MailerTest extends \PHPUnit\Framework\TestCase
19
{
20
    private function createMockMailer(): Mailer
21
    {
22
        global $container;
23
24
        $entityManager = $this->createMock(EntityManager::class);
25
        $renderer = $container->get(RendererInterface::class);
26
        $transport = new InMemory();
27
28
        $mailer = new Mailer(
29
            $entityManager,
30
            $transport,
31
            $renderer,
32
            'my-ichtus.lan',
33
            null,
34
            '[email protected]',
35
            '/user/bin/php'
36
        );
37
38
        return $mailer;
39
    }
40
41
    public function testQueueRegister(): void
42
    {
43
        $user = $this->createMockUserMinimal();
44
        $mailer = $this->createMockMailer();
45
        $message = $mailer->queueRegister($user);
46
47
        $this->assertMessage($message, $user, '[email protected]', MessageTypeType::REGISTER, 'Demande de création de compte au Club Nautique Ichtus');
48
    }
49
50
    public function testQueueUnregister(): void
51
    {
52
        $unregisteredUser = $this->createMockUser();
53
        $admin = $this->createMockUserAdmin();
54
        $mailer = $this->createMockMailer();
55
        $message = $mailer->queueUnregister($admin, $unregisteredUser);
56
57
        $this->assertMessage($message, $admin, '[email protected]', MessageTypeType::UNREGISTER, 'Démission');
58
    }
59
60
    public function testQueueResetPassword(): void
61
    {
62
        $user = $this->createMockUser();
63
        $mailer = $this->createMockMailer();
64
        $message = $mailer->queueResetPassword($user, '[email protected]');
65
66
        $this->assertMessage($message, $user, '[email protected]', MessageTypeType::RESET_PASSWORD, 'Demande de modification de mot de passe');
67
    }
68
69
    public function testQueueBalancePositive(): void
70
    {
71
        $bookables = [];
72
        $bookables[] = $this->createBookable('Cotisation', '90.00');
73
        $bookables[] = $this->createBookable('Fonds de réparation interne', '10.00');
74
75
        $this->queueBalance($bookables, 'positive');
76
    }
77
78
    public function testQueueBalanceNegative(): void
79
    {
80
        $bookables = [];
81
        $bookables[] = $this->createBookable('Cotisation', '90.00');
82
        $bookables[] = $this->createBookable('Fonds de réparation interne', '10.00');
83
        $bookables[] = $this->createBookable('Casier 1012', '20.00');
84
        $bookables[] = $this->createBookable('Casier 1014', '20.00');
85
86
        $this->queueBalance($bookables, 'negative');
87
    }
88
89
    private function queueBalance(array $bookables, string $variant): void
90
    {
91
        $user = new User();
92
        $user->setLogin('john.doe');
93
        $user->setFirstName('John');
94
        $user->setLastName('Doe');
95
        $user->setEmail('[email protected]');
96
97
        $account = new Account();
98
        $account->setBalance($variant === 'positive' ? '25.00' : '-45.00');
99
        $account->setOwner($user);
100
101
        $mailer = $this->createMockMailer();
102
        $message = $mailer->queueBalance($user, $bookables);
103
104
        $this->assertMessage($message, $user, '[email protected]', MessageTypeType::BALANCE, 'Balance de compte', $variant);
105
    }
106
107
    public function testSendMessage(): void
108
    {
109
        $mailer = $this->createMockMailer();
110
        $message = new Message();
111
        $message->setEmail('[email protected]');
112
113
        $this->expectOutputRegex('~email sent to: john\.doe@example\.com~');
114
        $mailer->sendMessage($message);
115
        self::assertNotNull($message->getDateSent());
116
    }
117
118
    private function createMockUser(): User
119
    {
120
        $prophecy = $this->prophesize(User::class);
121
        $prophecy->getId()->willReturn(123);
122
        $prophecy->getLogin()->willReturn('john.doe');
123
        $prophecy->getFirstName()->willReturn('John');
124
        $prophecy->getLastName()->willReturn('Doe');
125
        $prophecy->getName()->willReturn('John Doe');
126
        $prophecy->getEmail()->willReturn('[email protected]');
127
        $prophecy->createToken()->willReturn(str_repeat('X', 32));
128
        $prophecy->messageAdded(Argument::type(Message::class));
129
130
        $user = $prophecy->reveal();
131
132
        return $user;
133
    }
134
135
    private function createMockUserAdmin(): User
136
    {
137
        $prophecy = $this->prophesize(User::class);
138
        $prophecy->getLogin()->willReturn('admin');
139
        $prophecy->getFirstName()->willReturn('Admin');
140
        $prophecy->getLastName()->willReturn('Istrator');
141
        $prophecy->getEmail()->willReturn('[email protected]');
142
        $prophecy->messageAdded(Argument::type(Message::class));
143
144
        $user = $prophecy->reveal();
145
146
        return $user;
147
    }
148
149
    private function createMockUserMinimal(): User
150
    {
151
        $prophecy = $this->prophesize(User::class);
152
        $prophecy->getLogin();
153
        $prophecy->getFirstName();
154
        $prophecy->getLastName();
155
        $prophecy->getEmail()->willReturn('[email protected]');
156
        $prophecy->createToken()->willReturn(str_repeat('X', 32));
157
        $prophecy->messageAdded(Argument::type(Message::class));
158
        $user = $prophecy->reveal();
159
160
        return $user;
161
    }
162
163
    private function assertMessage(Message $message, ?User $user, string $email, string $type, string $subject, ?string $variant = null): void
164
    {
165
        self::assertSame($type, $message->getType());
166
        self::assertSame($email, $message->getEmail());
167
        self::assertSame($user, $message->getRecipient());
168
        self::assertNull($message->getDateSent());
169
        self::assertSame($subject, $message->getSubject());
170
171
        $variant = $variant ? '-' . $variant : $variant;
172
        $expectedBody = 'tests/data/emails/' . str_replace('_', '-', $type . $variant) . '.html';
173
        $this->assertFile($expectedBody, $message->getBody());
174
    }
175
176
    /**
177
     * Custom assert that will not produce gigantic diff
178
     *
179
     * @param string $file
180
     * @param string $actual
181
     */
182
    private function assertFile(string $file, string $actual): void
183
    {
184
        // Log actual result for easier comparison with external diff tools
185
        $logFile = 'logs/' . $file;
186
        $dir = dirname($logFile);
187
        @mkdir($dir, 0777, true);
1 ignored issue
show
Security Best Practice introduced by
It seems like you do not handle an error condition for mkdir(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

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

187
        /** @scrutinizer ignore-unhandled */ @mkdir($dir, 0777, true);

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
188
        file_put_contents($logFile, $actual);
189
190
        self::assertFileExists($file, 'Expected file must exist on disk, fix it with: cp ' . $logFile . ' ' . $file);
191
        $expected = file_get_contents($file);
192
193
        self::assertTrue($expected === $actual, 'File content does not match, compare with: meld ' . $file . ' ' . $logFile);
194
    }
195
196
    private function createBookable(string $bookableName, string $periodicPrice): Bookable
197
    {
198
        $bookable = new Bookable();
199
        $bookable->setName($bookableName);
200
        $bookable->setPeriodicPrice($periodicPrice);
201
202
        return $bookable;
203
    }
204
}
205