1 | <?php |
||||
2 | |||||
3 | declare(strict_types=1); |
||||
4 | |||||
5 | namespace ApplicationTest\Service; |
||||
6 | |||||
7 | use Application\DBAL\Types\MessageTypeType; |
||||
8 | use Application\Enum\PaymentMethod; |
||||
9 | use Application\Enum\ProductType; |
||||
10 | use Application\Model\Country; |
||||
11 | use Application\Model\Message; |
||||
12 | use Application\Model\Order; |
||||
13 | use Application\Model\OrderLine; |
||||
14 | use Application\Model\Product; |
||||
15 | use Application\Model\Subscription; |
||||
16 | use Application\Model\User; |
||||
17 | use Application\Service\MessageQueuer; |
||||
18 | use Doctrine\Common\Collections\ArrayCollection; |
||||
19 | use Doctrine\ORM\EntityManager; |
||||
20 | use Ecodev\Felix\Service\MessageRenderer; |
||||
21 | use Laminas\View\Renderer\RendererInterface; |
||||
22 | use Money\Money; |
||||
23 | use PHPUnit\Framework\TestCase; |
||||
24 | |||||
25 | class MessageQueuerTest extends TestCase |
||||
26 | { |
||||
27 | private function createMockMessageQueuer(): MessageQueuer |
||||
28 | { |
||||
29 | global $container; |
||||
30 | |||||
31 | $entityManager = $container->get(EntityManager::class); |
||||
32 | $viewRenderer = $container->get(RendererInterface::class); |
||||
33 | $messageRenderer = new MessageRenderer($viewRenderer, 'artisans.lan'); |
||||
34 | $config = [ |
||||
35 | 'email' => [ |
||||
36 | 'admins' => [ |
||||
37 | '[email protected]', |
||||
38 | 'jane.doe@@example.com', |
||||
39 | ], |
||||
40 | ], |
||||
41 | ]; |
||||
42 | |||||
43 | $messageQueuer = new MessageQueuer( |
||||
44 | $entityManager, |
||||
45 | $messageRenderer, |
||||
46 | $config, |
||||
47 | ); |
||||
48 | |||||
49 | return $messageQueuer; |
||||
50 | } |
||||
51 | |||||
52 | public function testQueueRegister(): void |
||||
53 | { |
||||
54 | $user = $this->createMockUserMinimal(); |
||||
55 | $messageQueuer = $this->createMockMessageQueuer(); |
||||
56 | $message = $messageQueuer->queueRegister($user); |
||||
57 | |||||
58 | $this->assertMessage($message, $user, '[email protected]', MessageTypeType::REGISTER, 'Demande de création de compte Les artisans de la transition'); |
||||
59 | } |
||||
60 | |||||
61 | public function testQueueConfirmedRegistration(): void |
||||
62 | { |
||||
63 | $registeredUser = $this->createMockUser(); |
||||
64 | $admin = $this->createMockUserAdmin(); |
||||
65 | $messageQueuer = $this->createMockMessageQueuer(); |
||||
66 | $message = $messageQueuer->queueConfirmedRegistration($admin->getEmail(), $registeredUser); |
||||
0 ignored issues
–
show
Bug
introduced
by
![]() |
|||||
67 | |||||
68 | $this->assertMessage($message, null, '[email protected]', MessageTypeType::CONFIRMED_REGISTRATION, 'Nouvel utilisateur'); |
||||
69 | } |
||||
70 | |||||
71 | public function testQueueResetPassword(): void |
||||
72 | { |
||||
73 | $user = $this->createMockUser(); |
||||
74 | $messageQueuer = $this->createMockMessageQueuer(); |
||||
75 | $message = $messageQueuer->queueResetPassword($user, '[email protected]'); |
||||
76 | |||||
77 | $this->assertMessage($message, $user, '[email protected]', MessageTypeType::RESET_PASSWORD, 'Demande de modification de mot de passe'); |
||||
78 | } |
||||
79 | |||||
80 | public function testQueueUpdatedUser(): void |
||||
81 | { |
||||
82 | $updatedUser = $this->createMockUser(); |
||||
83 | $admin = $this->createMockUserAdmin(); |
||||
84 | $messageQueuer = $this->createMockMessageQueuer(); |
||||
85 | |||||
86 | $before = [ |
||||
87 | 'Prénom' => 'John', |
||||
88 | 'Nom de famille ' => 'Doe', |
||||
89 | ]; |
||||
90 | |||||
91 | $after = [ |
||||
92 | 'Prénom' => 'John', |
||||
93 | 'Nom de famille ' => 'Connor', |
||||
94 | ]; |
||||
95 | |||||
96 | $message = $messageQueuer->queueUpdatedUser($admin->getEmail(), $updatedUser, $before, $after); |
||||
0 ignored issues
–
show
It seems like
$admin->getEmail() can also be of type null ; however, parameter $adminEmail of Application\Service\Mess...uer::queueUpdatedUser() does only seem to accept string , 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
![]() |
|||||
97 | |||||
98 | $this->assertMessage($message, null, '[email protected]', MessageTypeType::UPDATED_USER, 'Un utilisateur a modifié ses données personnelles'); |
||||
99 | } |
||||
100 | |||||
101 | public function testQueueUserPendingOrder(): void |
||||
102 | { |
||||
103 | $user = $this->createMockUser(); |
||||
104 | $order = $this->createMockOrder($user); |
||||
105 | $messageQueuer = $this->createMockMessageQueuer(); |
||||
106 | |||||
107 | $message = $messageQueuer->queueUserPendingOrder($order->getOwner(), $order); |
||||
0 ignored issues
–
show
It seems like
$order->getOwner() can also be of type null ; however, parameter $user of Application\Service\Mess...queueUserPendingOrder() 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
![]() |
|||||
108 | |||||
109 | $this->assertMessage($message, $user, '[email protected]', MessageTypeType::USER_PENDING_ORDER, 'Votre commande est en cours de traitement'); |
||||
110 | } |
||||
111 | |||||
112 | public function testQueueUserValidatedOrder(): void |
||||
113 | { |
||||
114 | $user = $this->createMockUser(); |
||||
115 | $order = $this->createMockOrder($user); |
||||
116 | $messageQueuer = $this->createMockMessageQueuer(); |
||||
117 | |||||
118 | $message = $messageQueuer->queueUserValidatedOrder($order->getOwner(), $order); |
||||
0 ignored issues
–
show
It seems like
$order->getOwner() can also be of type null ; however, parameter $user of Application\Service\Mess...eueUserValidatedOrder() 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
![]() |
|||||
119 | |||||
120 | $this->assertMessage($message, $user, '[email protected]', MessageTypeType::USER_VALIDATED_ORDER, 'Votre commande a été validée'); |
||||
121 | } |
||||
122 | |||||
123 | public function testQueueAdminPendingOrder(): void |
||||
124 | { |
||||
125 | $admin = $this->createMockUserAdmin(); |
||||
126 | $user = $this->createMockUser(); |
||||
127 | $order = $this->createMockOrder($user); |
||||
128 | $messageQueuer = $this->createMockMessageQueuer(); |
||||
129 | |||||
130 | $message = $messageQueuer->queueAdminPendingOrder($admin->getEmail(), $order); |
||||
0 ignored issues
–
show
It seems like
$admin->getEmail() can also be of type null ; however, parameter $adminEmail of Application\Service\Mess...ueueAdminPendingOrder() does only seem to accept string , 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
![]() |
|||||
131 | |||||
132 | $this->assertMessage($message, null, '[email protected]', MessageTypeType::ADMIN_PENDING_ORDER, 'Une commande a besoin d\'un BVR'); |
||||
133 | } |
||||
134 | |||||
135 | public function testQueueAdminPendingOrderWithoutSubscription(): void |
||||
136 | { |
||||
137 | $admin = $this->createMockUserAdmin(); |
||||
138 | $user = $this->createMockUser(); |
||||
139 | $order = $this->createMockOrder($user, false); |
||||
140 | $messageQueuer = $this->createMockMessageQueuer(); |
||||
141 | |||||
142 | $message = $messageQueuer->queueAdminPendingOrder($admin->getEmail(), $order); |
||||
0 ignored issues
–
show
It seems like
$admin->getEmail() can also be of type null ; however, parameter $adminEmail of Application\Service\Mess...ueueAdminPendingOrder() does only seem to accept string , 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
![]() |
|||||
143 | |||||
144 | $this->assertMessage($message, null, '[email protected]', MessageTypeType::ADMIN_PENDING_ORDER, 'Une commande a besoin d\'un BVR', 'without-subscription'); |
||||
145 | } |
||||
146 | |||||
147 | public function testQueueAdminValidatedOrder(): void |
||||
148 | { |
||||
149 | $admin = $this->createMockUserAdmin(); |
||||
150 | $user = $this->createMockUser(); |
||||
151 | $order = $this->createMockOrder($user); |
||||
152 | $messageQueuer = $this->createMockMessageQueuer(); |
||||
153 | |||||
154 | $message = $messageQueuer->queueAdminValidatedOrder($admin->getEmail(), $order); |
||||
0 ignored issues
–
show
It seems like
$admin->getEmail() can also be of type null ; however, parameter $email of Application\Service\Mess...ueAdminValidatedOrder() does only seem to accept string , 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
![]() |
|||||
155 | |||||
156 | $this->assertMessage($message, null, '[email protected]', MessageTypeType::ADMIN_VALIDATED_ORDER, 'Commande à comptabiliser'); |
||||
157 | } |
||||
158 | |||||
159 | public function testQueueAdminValidatedOrderWithoutOwner(): void |
||||
160 | { |
||||
161 | $admin = $this->createMockUserAdmin(); |
||||
162 | $order = $this->createMockOrder(null); |
||||
163 | $messageQueuer = $this->createMockMessageQueuer(); |
||||
164 | |||||
165 | $message = $messageQueuer->queueAdminValidatedOrder($admin->getEmail(), $order); |
||||
0 ignored issues
–
show
It seems like
$admin->getEmail() can also be of type null ; however, parameter $email of Application\Service\Mess...ueAdminValidatedOrder() does only seem to accept string , 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
![]() |
|||||
166 | |||||
167 | $this->assertMessage($message, null, '[email protected]', MessageTypeType::ADMIN_VALIDATED_ORDER, 'Commande à comptabiliser', 'without-owner'); |
||||
168 | } |
||||
169 | |||||
170 | public function testQueueRequestMembershipEnd(): void |
||||
171 | { |
||||
172 | $admin = $this->createMockUserAdmin(); |
||||
173 | $user = $this->createMockUser(); |
||||
174 | $messageQueuer = $this->createMockMessageQueuer(); |
||||
175 | |||||
176 | $message = $messageQueuer->queueRequestMembershipEnd($admin->getEmail(), $user); |
||||
0 ignored issues
–
show
It seems like
$admin->getEmail() can also be of type null ; however, parameter $adminEmail of Application\Service\Mess...eRequestMembershipEnd() does only seem to accept string , 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
![]() |
|||||
177 | |||||
178 | $this->assertMessage($message, null, '[email protected]', MessageTypeType::REQUEST_MEMBERSHIP_END, 'Demande d\'arrêt de cotisations'); |
||||
179 | } |
||||
180 | |||||
181 | public function testQueueNewsletterSubscription(): void |
||||
182 | { |
||||
183 | $admin = $this->createMockUserAdmin(); |
||||
184 | $messageQueuer = $this->createMockMessageQueuer(); |
||||
185 | |||||
186 | $message = $messageQueuer->queueNewsletterSubscription($admin->getEmail(), '[email protected]'); |
||||
0 ignored issues
–
show
It seems like
$admin->getEmail() can also be of type null ; however, parameter $adminEmail of Application\Service\Mess...ewsletterSubscription() does only seem to accept string , 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
![]() |
|||||
187 | |||||
188 | $this->assertMessage($message, null, '[email protected]', MessageTypeType::NEWSLETTER_SUBSCRIPTION, 'Demande d\'inscription à la newsletter'); |
||||
189 | } |
||||
190 | |||||
191 | public function testGetEmailsToNotify(): void |
||||
192 | { |
||||
193 | $messageQueuer = $this->createMockMessageQueuer(); |
||||
194 | |||||
195 | $emails = $messageQueuer->getAllEmailsToNotify(); |
||||
196 | |||||
197 | self::assertCount(2, $emails); |
||||
198 | self::assertContains('[email protected]', $emails); |
||||
199 | } |
||||
200 | |||||
201 | private function createMockOrder(?User $owner, bool $withSubscription = true): Order |
||||
202 | { |
||||
203 | $product = $this->createMock(Product::class); |
||||
204 | $product->expects(self::any()) |
||||
205 | ->method('getId') |
||||
206 | ->willReturn(1); |
||||
207 | |||||
208 | $product->expects(self::any()) |
||||
209 | ->method('getCode') |
||||
210 | ->willReturn('xxx-yyy'); |
||||
211 | |||||
212 | $product->expects(self::any()) |
||||
213 | ->method('getName') |
||||
214 | ->willReturn('Article 1'); |
||||
215 | |||||
216 | $productLine = new OrderLine(); |
||||
217 | $productLine->setProduct($product); |
||||
218 | $productLine->setBalanceCHF(Money::CHF(500)); |
||||
219 | $productLine->setBalanceEUR(Money::EUR(0)); |
||||
220 | $productLine->setType(ProductType::Paper); |
||||
221 | |||||
222 | $subscriptionLine = new OrderLine(); |
||||
223 | $subscriptionLine->setSubscription(new Subscription()); |
||||
224 | $subscriptionLine->setName('Abonnement standard papier'); |
||||
225 | $subscriptionLine->setBalanceCHF(Money::CHF(1500)); |
||||
226 | $subscriptionLine->setBalanceEUR(Money::EUR(0)); |
||||
227 | $subscriptionLine->setType(ProductType::Both); |
||||
228 | |||||
229 | $subscriptionLine2 = new OrderLine(); |
||||
230 | $subscriptionLine2->setSubscription(new Subscription()); |
||||
231 | $subscriptionLine2->setName('Abonnement institutionnel numérique'); |
||||
232 | $subscriptionLine2->setAdditionalEmails(['[email protected]', '[email protected]', '[email protected]']); |
||||
233 | $subscriptionLine2->setBalanceCHF(Money::CHF(2500)); |
||||
234 | $subscriptionLine2->setBalanceEUR(Money::EUR(0)); |
||||
235 | $subscriptionLine2->setType(ProductType::Digital); |
||||
236 | |||||
237 | $donationLine = new OrderLine(); |
||||
238 | $donationLine->setName('Don'); |
||||
239 | $donationLine->setBalanceCHF(Money::CHF(3500)); |
||||
240 | $donationLine->setBalanceEUR(Money::EUR(0)); |
||||
241 | $donationLine->setType(ProductType::Other); |
||||
242 | |||||
243 | if ($withSubscription) { |
||||
244 | $lines = new ArrayCollection([$productLine, $subscriptionLine, $subscriptionLine2, $donationLine]); |
||||
245 | } else { |
||||
246 | $lines = new ArrayCollection([$productLine, $donationLine]); |
||||
247 | } |
||||
248 | |||||
249 | $order = $this->createPartialMock(Order::class, ['getId', 'getBalanceCHF', 'getBalanceEUR', 'getOrderLines']); |
||||
250 | $order->setOwner($owner); |
||||
251 | $order->setPaymentMethod(PaymentMethod::Bvr); |
||||
252 | |||||
253 | $order->expects(self::any()) |
||||
254 | ->method('getId') |
||||
255 | ->willReturn(456); |
||||
256 | |||||
257 | $order->expects(self::any()) |
||||
258 | ->method('getBalanceCHF') |
||||
259 | ->willReturn(Money::CHF(3300)); |
||||
260 | |||||
261 | $order->expects(self::any()) |
||||
262 | ->method('getBalanceEUR') |
||||
263 | ->willReturn(Money::EUR(0)); |
||||
264 | |||||
265 | $order->expects(self::any()) |
||||
266 | ->method('getOrderLines') |
||||
267 | ->willReturn($lines); |
||||
268 | |||||
269 | return $order; |
||||
270 | } |
||||
271 | |||||
272 | private function createMockUser(): User |
||||
273 | { |
||||
274 | $user = $this->createMock(User::class); |
||||
275 | |||||
276 | $user->expects(self::any()) |
||||
277 | ->method('getId') |
||||
278 | ->willReturn(123); |
||||
279 | |||||
280 | $user->expects(self::any()) |
||||
281 | ->method('getFirstName') |
||||
282 | ->willReturn('John'); |
||||
283 | |||||
284 | $user->expects(self::any()) |
||||
285 | ->method('getLastName') |
||||
286 | ->willReturn('Doe'); |
||||
287 | |||||
288 | $user->expects(self::any()) |
||||
289 | ->method('getName') |
||||
290 | ->willReturn('John Doe'); |
||||
291 | |||||
292 | $user->expects(self::any()) |
||||
293 | ->method('getStreet') |
||||
294 | ->willReturn('Main street'); |
||||
295 | |||||
296 | $user->expects(self::any()) |
||||
297 | ->method('getPostcode') |
||||
298 | ->willReturn('2020'); |
||||
299 | |||||
300 | $user->expects(self::any()) |
||||
301 | ->method('getLocality') |
||||
302 | ->willReturn('Locality'); |
||||
303 | |||||
304 | $country = new Country(); |
||||
305 | $country->setName('Wookaya'); |
||||
306 | $user->expects(self::any()) |
||||
307 | ->method('getCountry') |
||||
308 | ->willReturn($country); |
||||
309 | |||||
310 | $user->expects(self::any()) |
||||
311 | ->method('getPhone') |
||||
312 | ->willReturn('123 456 87 98'); |
||||
313 | |||||
314 | $user->expects(self::any()) |
||||
315 | ->method('getEmail') |
||||
316 | ->willReturn('[email protected]'); |
||||
317 | |||||
318 | $user->expects(self::any()) |
||||
319 | ->method('createToken') |
||||
320 | ->willReturn(str_repeat('X', 32)); |
||||
321 | |||||
322 | return $user; |
||||
323 | } |
||||
324 | |||||
325 | private function createMockUserAdmin(): User |
||||
326 | { |
||||
327 | $user = $this->createMock(User::class); |
||||
328 | |||||
329 | $user->expects(self::any()) |
||||
330 | ->method('getFirstName') |
||||
331 | ->willReturn('Admin'); |
||||
332 | |||||
333 | $user->expects(self::any()) |
||||
334 | ->method('getLastName') |
||||
335 | ->willReturn('Istrator'); |
||||
336 | |||||
337 | $user->expects(self::any()) |
||||
338 | ->method('getEmail') |
||||
339 | ->willReturn('[email protected]'); |
||||
340 | |||||
341 | return $user; |
||||
342 | } |
||||
343 | |||||
344 | private function createMockUserMinimal(): User |
||||
345 | { |
||||
346 | $user = $this->createMock(User::class); |
||||
347 | $user->expects(self::any()) |
||||
348 | ->method('getEmail') |
||||
349 | ->willReturn('[email protected]'); |
||||
350 | |||||
351 | $user->expects(self::any()) |
||||
352 | ->method('createToken') |
||||
353 | ->willReturn(str_repeat('X', 32)); |
||||
354 | |||||
355 | return $user; |
||||
356 | } |
||||
357 | |||||
358 | private function assertMessage(Message $message, ?User $user, string $email, string $type, string $subject, ?string $variant = null): void |
||||
359 | { |
||||
360 | self::assertSame($type, $message->getType()); |
||||
361 | self::assertSame($email, $message->getEmail()); |
||||
362 | self::assertSame($user, $message->getRecipient()); |
||||
363 | self::assertNull($message->getDateSent()); |
||||
364 | self::assertSame($subject, $message->getSubject()); |
||||
365 | |||||
366 | $variant = $variant ? '-' . $variant : $variant; |
||||
367 | $expectedBody = 'tests/data/emails/' . str_replace('_', '-', $type . $variant) . '.html'; |
||||
368 | $this->assertFile($expectedBody, $message->getBody()); |
||||
369 | } |
||||
370 | |||||
371 | /** |
||||
372 | * Custom assert that will not produce gigantic diff. |
||||
373 | */ |
||||
374 | private function assertFile(string $file, string $actual): void |
||||
375 | { |
||||
376 | // Log actual result for easier comparison with external diff tools |
||||
377 | $logFile = 'logs/' . $file; |
||||
378 | $dir = dirname($logFile); |
||||
379 | @mkdir($dir, 0o777, true); |
||||
380 | file_put_contents($logFile, $actual); |
||||
381 | |||||
382 | self::assertFileExists($file, 'Expected file must exist on disk, fix it with: cp ' . $logFile . ' ' . $file); |
||||
383 | $expected = file_get_contents($file); |
||||
384 | |||||
385 | self::assertTrue($expected === $actual, 'File content does not match, compare with: meld ' . $file . ' ' . $logFile); |
||||
386 | } |
||||
387 | } |
||||
388 |