Files
myep/tests/Service/BookingNewsletterOptInTest.php
T

222 lines
7.7 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Tests\Service;
use App\BusProNet\Model\Travel;
use App\Enum\NewsletterOptInContext;
use App\Exception\NewsletterProviderException;
use App\Form\Model\BookingDto;
use App\Form\Model\ParticipantDto;
use App\Service\BookingNewsletterOptIn;
use App\Service\NewsletterManager;
use PHPUnit\Framework\TestCase;
use Psr\Log\NullLogger;
class BookingNewsletterOptInTest extends TestCase
{
public function testChildrenAreNotOfferedACompanionOptIn(): void
{
$bookingDto = $this->createBookingDto([
['[email protected]', 30],
['[email protected]', 12],
]);
$companions = $this->createService($this->createStub(NewsletterManager::class))
->resolveCompanions($bookingDto, '[email protected]');
self::assertSame([], $companions);
}
public function testApplicantAddressIsNotOfferedAsACompanion(): void
{
$bookingDto = $this->createBookingDto([
['[email protected]', 30],
['[email protected] ', 25],
]);
$companions = $this->createService($this->createStub(NewsletterManager::class))
->resolveCompanions($bookingDto, '[email protected]');
self::assertSame([], $companions);
}
public function testDuplicateAndInvalidCompanionAddressesAreCollapsed(): void
{
$bookingDto = $this->createBookingDto([
['[email protected]', 30],
['[email protected]', 25],
['[email protected]', 26],
['not-an-email', 27],
[null, 28],
]);
$companions = $this->createService($this->createStub(NewsletterManager::class))
->resolveCompanions($bookingDto, '[email protected]');
self::assertCount(1, $companions);
self::assertSame('[email protected]', $companions[0]->email);
}
public function testConfirmedAndPendingCompanionsAreSkipped(): void
{
$companions = $this->createCompanions([
'[email protected]',
'[email protected]',
'[email protected]',
]);
$newsletterManager = $this->createMock(NewsletterManager::class);
$newsletterManager
->method('hasConfirmedOptIn')
->willReturnCallback(static fn (string $email): bool => '[email protected]' === $email);
$newsletterManager
->method('hasPendingConfirmation')
->willReturnCallback(static fn (string $email): bool => '[email protected]' === $email);
$newsletterManager
->expects(self::once())
->method('requestConfirmation')
->with('[email protected]', 'Tim', 'Teiler', NewsletterOptInContext::Companion, 'Mia Muster');
$this->createService($newsletterManager)->subscribeCompanions($companions, 'Mia Muster');
}
public function testOneFailingCompanionDoesNotStopTheOthers(): void
{
$companions = $this->createCompanions([
'[email protected]',
'[email protected]',
]);
$newsletterManager = $this->createMock(NewsletterManager::class);
$newsletterManager->method('hasConfirmedOptIn')->willReturn(false);
$newsletterManager->method('hasPendingConfirmation')->willReturn(false);
$requestedEmails = [];
$newsletterManager
->expects(self::exactly(2))
->method('requestConfirmation')
->willReturnCallback(static function (string $email) use (&$requestedEmails): void {
$requestedEmails[] = $email;
if ('[email protected]' === $email) {
throw new NewsletterProviderException('Mailer down.');
}
});
$this->createService($newsletterManager)->subscribeCompanions($companions, 'Mia Muster');
self::assertSame(['[email protected]', '[email protected]'], $requestedEmails);
}
public function testAFailingConsentLookupDoesNotEscapeToTheCaller(): void
{
$companions = $this->createCompanions([
'[email protected]',
'[email protected]',
]);
$newsletterManager = $this->createMock(NewsletterManager::class);
$newsletterManager
->method('hasConfirmedOptIn')
->willReturnCallback(static function (string $email): bool {
if ('[email protected]' === $email) {
throw new \RuntimeException('Database gone.');
}
return false;
});
$newsletterManager->method('hasPendingConfirmation')->willReturn(false);
$newsletterManager
->expects(self::once())
->method('requestConfirmation')
->with('[email protected]');
$this->createService($newsletterManager)->subscribeCompanions($companions, 'Mia Muster');
}
public function testApplicantOptInFailureDoesNotEscapeToTheCaller(): void
{
$newsletterManager = $this->createStub(NewsletterManager::class);
$newsletterManager
->method('requestConfirmation')
->willThrowException(new \RuntimeException('Database gone.'));
$this->createService($newsletterManager)->subscribeApplicant('[email protected]', null);
$this->expectNotToPerformAssertions();
}
public function testApplicantOptInUsesTheOwnWording(): void
{
$bookingDto = $this->createBookingDto([['[email protected]', 30]]);
$applicant = $bookingDto->participants[0];
$newsletterManager = $this->createMock(NewsletterManager::class);
$newsletterManager
->expects(self::once())
->method('requestConfirmation')
->with('[email protected]', 'Mia', 'Muster');
$this->createService($newsletterManager)->subscribeApplicant('[email protected]', $applicant);
}
public function testRequestedByNameIsTheApplicantsFullName(): void
{
$bookingDto = $this->createBookingDto([['[email protected]', 30]]);
self::assertSame(
'Mia Muster',
$this->createService($this->createStub(NewsletterManager::class))->resolveRequestedByName($bookingDto)
);
}
private function createService(NewsletterManager $newsletterManager): BookingNewsletterOptIn
{
return new BookingNewsletterOptIn($newsletterManager, new NullLogger());
}
/**
* @param list<array{0: string|null, 1: int}> $participants email and age, applicant first
*/
private function createBookingDto(array $participants): BookingDto
{
$bookingDto = new BookingDto(new Travel(), 1);
foreach ($participants as $index => [$email, $age]) {
$participant = new ParticipantDto();
$participant->index = $index;
$participant->firstName = 0 === $index ? 'Mia' : 'Tim';
$participant->lastName = 0 === $index ? 'Muster' : 'Teiler';
$participant->email = $email;
$participant->dateOfBirth = new \DateTimeImmutable(sprintf('-%d years', $age));
$bookingDto->participants[] = $participant;
}
return $bookingDto;
}
/**
* @param list<string> $emails
*
* @return list<ParticipantDto>
*/
private function createCompanions(array $emails): array
{
$companions = [];
foreach ($emails as $offset => $email) {
$participant = new ParticipantDto();
$participant->index = $offset + 1;
$participant->firstName = 'Tim';
$participant->lastName = 'Teiler';
$participant->email = $email;
$participant->dateOfBirth = new \DateTimeImmutable('-25 years');
$companions[] = $participant;
}
return $companions;
}
}