MessageQueuerTest::assertFile()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 12
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 7
nc 1
nop 2
dl 0
loc 12
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\MessageQueuer;
13
use Doctrine\ORM\EntityManager;
14
use Ecodev\Felix\Service\MessageRenderer;
15
use Laminas\View\Renderer\RendererInterface;
16
use Money\Money;
17
18
class MessageQueuerTest extends \PHPUnit\Framework\TestCase
19
{
20
    private function createMessageQueuer(): MessageQueuer
21
    {
22
        global $container;
23
24
        $entityManager = $container->get(EntityManager::class);
25
        $viewRenderer = $container->get(RendererInterface::class);
26
        $messageRenderer = new MessageRenderer($viewRenderer, 'my-ichtus.lan');
27
28
        $messageQueuer = new MessageQueuer(
29
            $entityManager,
30
            $messageRenderer,
31
        );
32
33
        return $messageQueuer;
34
    }
35
36
    public function testQueueRegister(): void
37
    {
38
        $user = $this->createMockUserMinimal();
39
        $messageQueuer = $this->createMessageQueuer();
40
        $message = $messageQueuer->queueRegister($user);
41
42
        $this->assertMessage($message, $user, '[email protected]', MessageTypeType::REGISTER, 'Demande de création de compte au Club Nautique Ichtus');
43
    }
44
45
    public function testQueueUnregister(): void
46
    {
47
        $unregisteredUser = $this->createMockUser();
48
        $admin = $this->createMockUserAdmin();
49
        $messageQueuer = $this->createMessageQueuer();
50
        $message = $messageQueuer->queueUnregister($admin, $unregisteredUser);
51
52
        $this->assertMessage($message, $admin, '[email protected]', MessageTypeType::UNREGISTER, 'Démission');
53
    }
54
55
    /**
56
     * @dataProvider providerQueueResetPassword
57
     */
58
    public function testQueueResetPassword(User $user, ?string $expectedEmail): void
59
    {
60
        $messageQueuer = $this->createMessageQueuer();
61
        $message = $messageQueuer->queueResetPassword($user);
62
63
        $this->assertMessage($message, $user, $expectedEmail, MessageTypeType::RESET_PASSWORD, 'Demande de modification de mot de passe');
64
    }
65
66
    public function providerQueueResetPassword(): iterable
67
    {
68
        $userWithEmail = $this->createMockUser();
69
        $userWithFamilyOwner = $this->createMockUserWithFamilyOwner(true);
70
        $userWithFamilyOwnerWithoutEmail = $this->createMockUserWithFamilyOwner(false);
71
        $userWithoutEmail = $this->createMockUserWithoutEmail();
72
73
        return [
74
            'user with email' => [$userWithEmail, '[email protected]'],
75
            'user without email' => [$userWithoutEmail, null],
76
            'user without email but with family owner with email' => [$userWithFamilyOwner, '[email protected]'],
77
            'user without email but with family owner without email' => [$userWithFamilyOwnerWithoutEmail, null],
78
        ];
79
    }
80
81
    public function testQueueBalancePositive(): void
82
    {
83
        $bookables = [];
84
        $bookables[] = $this->createBookable('Cotisation', Money::CHF(9000));
85
        $bookables[] = $this->createBookable('Fonds de réparation interne', Money::CHF(1000));
86
87
        $this->queueBalance($bookables, 'positive');
88
    }
89
90
    public function testQueueBalanceNegative(): void
91
    {
92
        $bookables = [];
93
        $bookables[] = $this->createBookable('Cotisation', Money::CHF(9000));
94
        $bookables[] = $this->createBookable('Fonds de réparation interne', Money::CHF(1000));
95
        $bookables[] = $this->createBookable('Casier 1012', Money::CHF(2000));
96
        $bookables[] = $this->createBookable('Casier 1014', Money::CHF(2000));
97
98
        $this->queueBalance($bookables, 'negative');
99
    }
100
101
    private function queueBalance(array $bookables, string $variant): void
102
    {
103
        $user = new User();
104
        $user->setLogin('john.doe');
105
        $user->setFirstName('John');
106
        $user->setLastName('Doe');
107
        $user->setEmail('[email protected]');
108
109
        $account = new Account();
110
        $account->setBalance(Money::CHF($variant === 'positive' ? 2500 : -4500));
111
        $account->setOwner($user);
112
113
        $messageQueuer = $this->createMessageQueuer();
114
        $message = $messageQueuer->queueBalance($user, $bookables);
115
116
        $this->assertMessage($message, $user, '[email protected]', MessageTypeType::BALANCE, 'Balance de compte', $variant);
117
    }
118
119
    public function testQueueAllBalance(): void
120
    {
121
        $messageQueuer = $this->createMessageQueuer();
122
        $actual = $messageQueuer->queueAllBalance();
123
124
        self::assertsame(2, $actual);
125
    }
126
127
    public function testQueueNegativeBalance(): void
128
    {
129
        $messageQueuer = $this->createMessageQueuer();
130
        $actual = $messageQueuer->queueNegativeBalance();
131
132
        self::assertsame(0, $actual);
133
    }
134
135
    public function testQueueLeaveFamily(): void
136
    {
137
        $messageQueuer = $this->createMessageQueuer();
138
        $user = $this->createMockUser();
139
        $message = $messageQueuer->queueLeaveFamily($user);
140
141
        $this->assertMessage($message, $user, '[email protected]', MessageTypeType::LEAVE_FAMILY, 'Ménage quitté');
142
    }
143
144
    public function testQueueAdminLeaveFamily(): void
145
    {
146
        $messageQueuer = $this->createMessageQueuer();
147
        $user = $this->createMockUser();
148
        $message = $messageQueuer->queueAdminLeaveFamily($user);
149
150
        $this->assertMessage($message, null, '[email protected]', MessageTypeType::ADMIN_LEAVE_FAMILY, 'Ménage quitté');
151
    }
152
153
    public function testQueueRequestUserDeletion(): void
154
    {
155
        $userToDelete = $this->createMockUserWithFamilyOwner(true, true);
156
        $requestingUser = $userToDelete->getOwner();
157
        $messageQueuer = $this->createMessageQueuer();
158
159
        $message = $messageQueuer->queueRequestUserDeletion($requestingUser, $userToDelete);
0 ignored issues
show
Bug introduced by
It seems like $requestingUser can also be of type null; however, parameter $requestingUser of Application\Service\Mess...ueRequestUserDeletion() does only seem to accept Application\Model\User, maybe add an additional type check? ( Ignorable by Annotation )

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

159
        $message = $messageQueuer->queueRequestUserDeletion(/** @scrutinizer ignore-type */ $requestingUser, $userToDelete);
Loading history...
160
161
        $this->assertMessage($message, null, '[email protected]', MessageTypeType::REQUEST_USER_DELETION, 'Demande de suppression de compte');
162
    }
163
164
    private function createMockUser(?User $owner = null, bool $withEmail = true): User
165
    {
166
        $user = $this->createMock(User::class);
167
168
        $user->expects(self::any())
169
            ->method('getId')
170
            ->willReturn(123);
171
172
        $user->expects(self::any())
173
            ->method('getLogin')
174
            ->willReturn('john.doe');
175
176
        $user->expects(self::any())
177
            ->method('getFirstName')
178
            ->willReturn('John');
179
180
        $user->expects(self::any())
181
            ->method('getLastName')
182
            ->willReturn('Doe');
183
184
        $user->expects(self::any())
185
            ->method('getName')
186
            ->willReturn('John Doe');
187
188
        $user->expects(self::any())
189
            ->method('getEmail')
190
            ->willReturn($withEmail ? '[email protected]' : null);
191
192
        $user->expects(self::any())
193
            ->method('createToken')
194
            ->willReturn(str_repeat('X', 32));
195
196
        $user->expects(self::any())
197
            ->method('getOwner')
198
            ->willReturn($owner);
199
200
        return $user;
201
    }
202
203
    private function createMockUserWithFamilyOwner(bool $hasEmail, bool $ownerHasEmail = false): User
204
    {
205
        $owner = $this->createMock(User::class);
206
207
        $owner->expects(self::any())
208
            ->method('getFirstName')
209
            ->willReturn('Family');
210
211
        $owner->expects(self::any())
212
            ->method('getLastName')
213
            ->willReturn('Owner');
214
215
        $owner->expects(self::any())
216
            ->method('getName')
217
            ->willReturn('Family Owner');
218
219
        $owner->expects(self::any())
220
            ->method('getEmail')
221
            ->willReturn($hasEmail ? '[email protected]' : null);
222
223
        $user = $this->createMockUser($owner, $ownerHasEmail);
224
225
        return $user;
226
    }
227
228
    private function createMockUserAdmin(): User
229
    {
230
        $user = $this->createMock(User::class);
231
        $user->expects(self::any())
232
            ->method('getLogin')
233
            ->willReturn('admin');
234
235
        $user->expects(self::any())
236
            ->method('getFirstName')
237
            ->willReturn('Admin');
238
239
        $user->expects(self::any())
240
            ->method('getLastName')
241
            ->willReturn('Istrator');
242
243
        $user->expects(self::any())
244
            ->method('getEmail')
245
            ->willReturn('[email protected]');
246
247
        return $user;
248
    }
249
250
    private function createMockUserMinimal(): User
251
    {
252
        $user = $this->createMock(User::class);
253
        $user->expects(self::any())
254
            ->method('getEmail')
255
            ->willReturn('[email protected]');
256
257
        $user->expects(self::any())
258
            ->method('createToken')
259
            ->willReturn(str_repeat('X', 32));
260
261
        return $user;
262
    }
263
264
    private function createMockUserWithoutEmail(): User
265
    {
266
        $user = $this->createMock(User::class);
267
268
        return $user;
269
    }
270
271
    private function assertMessage(?Message $message, ?User $user, ?string $email, string $type, string $subject, ?string $variant = null): void
272
    {
273
        if (!$email) {
274
            self::assertNull($message);
275
276
            return;
277
        }
278
279
        self::assertSame($type, $message->getType());
0 ignored issues
show
Bug introduced by
The method getType() does not exist on null. ( Ignorable by Annotation )

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

279
        self::assertSame($type, $message->/** @scrutinizer ignore-call */ getType());

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
280
        self::assertSame($email, $message->getEmail());
281
        self::assertSame($user, $message->getRecipient());
282
        self::assertNull($message->getDateSent());
283
        self::assertSame($subject, $message->getSubject());
284
285
        $variant = $variant ? '-' . $variant : $variant;
286
        $expectedBody = 'tests/data/emails/' . str_replace('_', '-', $type . $variant) . '.html';
287
        $this->assertFile($expectedBody, $message->getBody());
288
    }
289
290
    /**
291
     * Custom assert that will not produce gigantic diff.
292
     */
293
    private function assertFile(string $file, string $actual): void
294
    {
295
        // Log actual result for easier comparison with external diff tools
296
        $logFile = 'logs/' . $file;
297
        $dir = dirname($logFile);
298
        @mkdir($dir, 0o777, true);
299
        file_put_contents($logFile, $actual);
300
301
        self::assertFileExists($file, 'Expected file must exist on disk, fix it with: cp ' . $logFile . ' ' . $file);
302
        $expected = file_get_contents($file);
303
304
        self::assertTrue($expected === $actual, 'File content does not match, compare with: meld ' . $file . ' ' . $logFile);
305
    }
306
307
    private function createBookable(string $bookableName, Money $periodicPrice): Bookable
308
    {
309
        $bookable = new Bookable();
310
        $bookable->setName($bookableName);
311
        $bookable->setPeriodicPrice($periodicPrice);
312
313
        return $bookable;
314
    }
315
}
316