wip: guest account registration (self-service and booking create flow)
This commit is contained in:
1 parent
e4430ac5c5
commit
d74888f64b
43 files changed
+2736
-144
No files matched your search
@@ -0,0 +1,113 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Tests\Controller\Account;
|
||||
|
||||
use App\Entity\User;
|
||||
use App\Exception\GuestAccountActivationExpiredException;
|
||||
use App\Service\BookingGuestAccountManager;
|
||||
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
|
||||
use Symfony\Bundle\SecurityBundle\Security;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
class GuestAccountActivationControllerTest extends WebTestCase
|
||||
{
|
||||
public function testExpiredActivationLinkShowsResendPageInsteadOf404(): void
|
||||
{
|
||||
$client = self::createClient([], ['HTTPS' => 'on']);
|
||||
$client->disableReboot();
|
||||
|
||||
$guestAccountManager = $this->createMock(BookingGuestAccountManager::class);
|
||||
$guestAccountManager
|
||||
->expects(self::once())
|
||||
->method('validateActivationRequest')
|
||||
->with(self::isInstanceOf(Request::class))
|
||||
->willThrowException(new GuestAccountActivationExpiredException());
|
||||
$guestAccountManager->expects(self::never())->method('consumeActivation');
|
||||
$guestAccountManager->expects(self::never())->method('validateActivationUrlForResend');
|
||||
$guestAccountManager->expects(self::never())->method('resendWelcomeEmail');
|
||||
|
||||
$security = $this->createMock(Security::class);
|
||||
$security->expects(self::never())->method('login');
|
||||
|
||||
self::getContainer()->set(BookingGuestAccountManager::class, $guestAccountManager);
|
||||
self::getContainer()->set(Security::class, $security);
|
||||
|
||||
$client->request('GET', '/welcome/[email protected]&nonce=current-nonce&expires=9999999999&_hash=signature');
|
||||
|
||||
self::assertResponseIsSuccessful();
|
||||
self::assertStringContainsString('Link', $client->getResponse()->getContent());
|
||||
self::assertStringContainsString('Willkommens-E-Mail erneut senden', $client->getResponse()->getContent());
|
||||
}
|
||||
|
||||
public function testResendActionResendsWelcomeMailAndRedirectsToLogin(): void
|
||||
{
|
||||
$client = self::createClient([], ['HTTPS' => 'on']);
|
||||
$client->disableReboot();
|
||||
|
||||
$user = new User('[email protected]');
|
||||
$user->setWelcomeActivationNonce('current-nonce');
|
||||
|
||||
$guestAccountManager = $this->createMock(BookingGuestAccountManager::class);
|
||||
$guestAccountManager
|
||||
->expects(self::once())
|
||||
->method('validateActivationRequest')
|
||||
->with(self::isInstanceOf(Request::class))
|
||||
->willThrowException(new GuestAccountActivationExpiredException());
|
||||
$guestAccountManager
|
||||
->expects(self::once())
|
||||
->method('validateActivationUrlForResend')
|
||||
->with(self::callback(static function (string $activationUrl): bool {
|
||||
return str_contains($activationUrl, 'email=customer%40example.com')
|
||||
|| str_contains($activationUrl, '[email protected]');
|
||||
}))
|
||||
->willReturn($user);
|
||||
$guestAccountManager
|
||||
->expects(self::once())
|
||||
->method('resendWelcomeEmail')
|
||||
->with($user);
|
||||
|
||||
$security = $this->createMock(Security::class);
|
||||
$security->expects(self::never())->method('login');
|
||||
|
||||
self::getContainer()->set(BookingGuestAccountManager::class, $guestAccountManager);
|
||||
self::getContainer()->set(Security::class, $security);
|
||||
|
||||
$crawler = $client->request('GET', '/welcome/[email protected]&nonce=current-nonce&expires=9999999999&_hash=signature');
|
||||
self::assertResponseIsSuccessful();
|
||||
|
||||
$form = $crawler->selectButton('Willkommens-E-Mail erneut senden')->form();
|
||||
$client->submit($form);
|
||||
|
||||
self::assertResponseRedirects('/');
|
||||
$client->followRedirect();
|
||||
|
||||
self::assertStringContainsString('Wir haben dir die Willkommens-E-Mail erneut gesendet.', $client->getResponse()->getContent());
|
||||
}
|
||||
|
||||
public function testTamperedActivationLinkStillReturns404(): void
|
||||
{
|
||||
$client = self::createClient([], ['HTTPS' => 'on']);
|
||||
$client->disableReboot();
|
||||
|
||||
$guestAccountManager = $this->createMock(BookingGuestAccountManager::class);
|
||||
$guestAccountManager
|
||||
->expects(self::once())
|
||||
->method('validateActivationRequest')
|
||||
->with(self::isInstanceOf(Request::class))
|
||||
->willThrowException(new NotFoundHttpException());
|
||||
$guestAccountManager->expects(self::never())->method('consumeActivation');
|
||||
|
||||
$security = $this->createMock(Security::class);
|
||||
$security->expects(self::never())->method('login');
|
||||
|
||||
self::getContainer()->set(BookingGuestAccountManager::class, $guestAccountManager);
|
||||
self::getContainer()->set(Security::class, $security);
|
||||
|
||||
$client->request('GET', '/welcome/[email protected]&nonce=current-nonce&expires=9999999999&_hash=invalid');
|
||||
|
||||
self::assertResponseStatusCodeSame(404);
|
||||
}
|
||||
}
|
||||
@@ -256,6 +256,59 @@ class PersonalDataControllerTest extends TestCase
|
||||
], $controller->flashes);
|
||||
}
|
||||
|
||||
public function testIndexConsumesWelcomeActivationAfterForcedPasswordChangeSucceeds(): void
|
||||
{
|
||||
$personalData = $this->createCompletePersonalData();
|
||||
$controller = $this->createController(true, true, $this->validator(), 'NewPassw0rd!');
|
||||
$controller->user->markWelcomeActivationPending('current-nonce', new \DateTimeImmutable('+30 minutes'));
|
||||
|
||||
$controller->apiClient
|
||||
->expects(self::once())
|
||||
->method('getPersonalData')
|
||||
->with('[email protected]', null, null)
|
||||
->willReturn($personalData);
|
||||
$controller->apiClient
|
||||
->expects(self::once())
|
||||
->method('updatePersonalData')
|
||||
->with('[email protected]', $personalData)
|
||||
->willReturn($personalData);
|
||||
$controller->newsletterManager
|
||||
->expects(self::once())
|
||||
->method('hasConfirmedOptIn')
|
||||
->with('[email protected]')
|
||||
->willReturn(false);
|
||||
$controller->newsletterManager
|
||||
->expects(self::once())
|
||||
->method('hasPendingConfirmation')
|
||||
->with('[email protected]')
|
||||
->willReturn(false);
|
||||
$controller->dataLoader
|
||||
->expects(self::once())
|
||||
->method('invalidateUserBookingCaches')
|
||||
->with($controller->user);
|
||||
$controller->entityManager
|
||||
->expects(self::once())
|
||||
->method('flush');
|
||||
$controller->passwordHasher
|
||||
->expects(self::once())
|
||||
->method('hashPassword')
|
||||
->with($controller->user, 'NewPassw0rd!')
|
||||
->willReturn('new-local-hash');
|
||||
|
||||
$request = Request::create('/personal-data', 'POST');
|
||||
$request->setSession(new Session(new MockArraySessionStorage()));
|
||||
$request->getSession()->set(PersonalDataController::SESSION_FORCE_PASSWORD_CHANGE_KEY, true);
|
||||
|
||||
$response = $controller->index($request);
|
||||
|
||||
self::assertSame(302, $response->getStatusCode());
|
||||
self::assertSame('new-local-hash', $controller->user->getPassword());
|
||||
self::assertNull($controller->user->getWelcomeActivationNonce());
|
||||
self::assertNull($controller->user->getWelcomeActivationExpiresAt());
|
||||
self::assertNotNull($controller->user->getWelcomeActivatedAt());
|
||||
self::assertFalse($request->getSession()->has(PersonalDataController::SESSION_FORCE_PASSWORD_CHANGE_KEY));
|
||||
}
|
||||
|
||||
public function testIndexDoesNotPersistInvalidFormSubmission(): void
|
||||
{
|
||||
$controller = $this->createController(true, false, $this->validator(), 'NewPassw0rd!');
|
||||
|
||||
@@ -0,0 +1,151 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Tests\Controller\Account;
|
||||
|
||||
use App\Service\BookingGuestAccountManager;
|
||||
use App\Service\PublicFormRateLimiter;
|
||||
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
class PortalAccessRequestControllerTest extends WebTestCase
|
||||
{
|
||||
public function testPortalAccessRequestRedirectsToLoginAfterSendingActivationMail(): void
|
||||
{
|
||||
$client = self::createClient([], ['HTTPS' => 'on']);
|
||||
$client->disableReboot();
|
||||
|
||||
$rateLimiter = $this->createMock(PublicFormRateLimiter::class);
|
||||
$rateLimiter
|
||||
->expects(self::once())
|
||||
->method('isPortalAccessAllowed')
|
||||
->with('[email protected]', self::isInstanceOf(Request::class))
|
||||
->willReturn(true);
|
||||
|
||||
$guestAccountManager = $this->createMock(BookingGuestAccountManager::class);
|
||||
$guestAccountManager
|
||||
->expects(self::once())
|
||||
->method('requestPortalAccess')
|
||||
->with('[email protected]', 123)
|
||||
->willReturn(BookingGuestAccountManager::PORTAL_ACCESS_SENT);
|
||||
|
||||
self::getContainer()->set(PublicFormRateLimiter::class, $rateLimiter);
|
||||
self::getContainer()->set(BookingGuestAccountManager::class, $guestAccountManager);
|
||||
|
||||
$crawler = $client->request('GET', '/');
|
||||
$token = $crawler->filter('input[name="_token"]')->attr('value');
|
||||
$client->request('POST', '/portal-access/request', [
|
||||
'email' => '[email protected]',
|
||||
'bookingNumber' => '123',
|
||||
'_token' => $token,
|
||||
]);
|
||||
|
||||
self::assertResponseRedirects('/');
|
||||
$client->followRedirect();
|
||||
|
||||
self::assertStringContainsString('Wenn zu deiner Buchung ein Portalzugang möglich ist, haben wir dir eine E-Mail gesendet.', $client->getResponse()->getContent());
|
||||
}
|
||||
|
||||
public function testPortalAccessRequestRejectsMismatchedBookingGenerically(): void
|
||||
{
|
||||
$client = self::createClient([], ['HTTPS' => 'on']);
|
||||
$client->disableReboot();
|
||||
|
||||
$rateLimiter = $this->createMock(PublicFormRateLimiter::class);
|
||||
$rateLimiter
|
||||
->expects(self::once())
|
||||
->method('isPortalAccessAllowed')
|
||||
->with('[email protected]', self::isInstanceOf(Request::class))
|
||||
->willReturn(true);
|
||||
|
||||
$guestAccountManager = $this->createMock(BookingGuestAccountManager::class);
|
||||
$guestAccountManager
|
||||
->expects(self::once())
|
||||
->method('requestPortalAccess')
|
||||
->with('[email protected]', 123)
|
||||
->willReturn(BookingGuestAccountManager::PORTAL_ACCESS_NOT_SENT);
|
||||
|
||||
self::getContainer()->set(PublicFormRateLimiter::class, $rateLimiter);
|
||||
self::getContainer()->set(BookingGuestAccountManager::class, $guestAccountManager);
|
||||
|
||||
$crawler = $client->request('GET', '/');
|
||||
$token = $crawler->filter('input[name="_token"]')->attr('value');
|
||||
$client->request('POST', '/portal-access/request', [
|
||||
'email' => '[email protected]',
|
||||
'bookingNumber' => '123',
|
||||
'_token' => $token,
|
||||
]);
|
||||
|
||||
self::assertResponseRedirects('/');
|
||||
$client->followRedirect();
|
||||
|
||||
self::assertStringContainsString('Wenn zu deiner Buchung ein Portalzugang möglich ist, haben wir dir eine E-Mail gesendet.', $client->getResponse()->getContent());
|
||||
}
|
||||
|
||||
public function testPortalAccessRequestShowsLoginHintForAlreadyActiveAccount(): void
|
||||
{
|
||||
$client = self::createClient([], ['HTTPS' => 'on']);
|
||||
$client->disableReboot();
|
||||
|
||||
$rateLimiter = $this->createMock(PublicFormRateLimiter::class);
|
||||
$rateLimiter
|
||||
->expects(self::once())
|
||||
->method('isPortalAccessAllowed')
|
||||
->with('[email protected]', self::isInstanceOf(Request::class))
|
||||
->willReturn(true);
|
||||
|
||||
$guestAccountManager = $this->createMock(BookingGuestAccountManager::class);
|
||||
$guestAccountManager
|
||||
->expects(self::once())
|
||||
->method('requestPortalAccess')
|
||||
->with('[email protected]', 123)
|
||||
->willReturn(BookingGuestAccountManager::PORTAL_ACCESS_ALREADY_ACTIVE);
|
||||
|
||||
self::getContainer()->set(PublicFormRateLimiter::class, $rateLimiter);
|
||||
self::getContainer()->set(BookingGuestAccountManager::class, $guestAccountManager);
|
||||
|
||||
$crawler = $client->request('GET', '/');
|
||||
$token = $crawler->filter('input[name="_token"]')->attr('value');
|
||||
$client->request('POST', '/portal-access/request', [
|
||||
'email' => '[email protected]',
|
||||
'bookingNumber' => '123',
|
||||
'_token' => $token,
|
||||
]);
|
||||
|
||||
self::assertResponseRedirects('/');
|
||||
$client->followRedirect();
|
||||
|
||||
self::assertStringContainsString('Für diese E-Mail-Adresse besteht bereits ein aktiver Portalzugang.', $client->getResponse()->getContent());
|
||||
}
|
||||
|
||||
public function testPortalAccessRequestReturns429WhenThrottled(): void
|
||||
{
|
||||
$client = self::createClient([], ['HTTPS' => 'on']);
|
||||
$client->disableReboot();
|
||||
|
||||
$rateLimiter = $this->createMock(PublicFormRateLimiter::class);
|
||||
$rateLimiter
|
||||
->expects(self::once())
|
||||
->method('isPortalAccessAllowed')
|
||||
->with('[email protected]', self::isInstanceOf(Request::class))
|
||||
->willReturn(false);
|
||||
|
||||
$guestAccountManager = $this->createMock(BookingGuestAccountManager::class);
|
||||
$guestAccountManager->expects(self::never())->method('requestPortalAccess');
|
||||
|
||||
self::getContainer()->set(PublicFormRateLimiter::class, $rateLimiter);
|
||||
self::getContainer()->set(BookingGuestAccountManager::class, $guestAccountManager);
|
||||
|
||||
$crawler = $client->request('GET', '/');
|
||||
$token = $crawler->filter('input[name="_token"]')->attr('value');
|
||||
$client->request('POST', '/portal-access/request', [
|
||||
'email' => '[email protected]',
|
||||
'bookingNumber' => '123',
|
||||
'_token' => $token,
|
||||
]);
|
||||
|
||||
self::assertResponseStatusCodeSame(429);
|
||||
self::assertStringContainsString(PublicFormRateLimiter::THROTTLED_MESSAGE, $client->getResponse()->getContent());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,293 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Tests\Controller\Booking\Create;
|
||||
|
||||
use App\BusProNet\ApiClient;
|
||||
use App\BusProNet\Constants;
|
||||
use App\BusProNet\Model\BookingResponse;
|
||||
use App\BusProNet\Model\Hotel;
|
||||
use App\BusProNet\Model\Travel;
|
||||
use App\Entity\User;
|
||||
use App\Form\Model\BookingCreateContext;
|
||||
use App\Form\Model\BookingDto;
|
||||
use App\Form\Model\BookingSummaryDto;
|
||||
use App\Form\Model\BookingSummaryPricingDto;
|
||||
use App\Form\Model\BookingSummaryVoucherDto;
|
||||
use App\Form\Model\ParticipantDto;
|
||||
use App\Form\Model\RoomGroupsDto;
|
||||
use App\Repository\UserRepository;
|
||||
use App\Service\BookingConfigurator;
|
||||
use App\Service\BookingCreateContextFactory;
|
||||
use App\Service\BookingGuestAccountManager;
|
||||
use App\Service\BookingSessionManager;
|
||||
use App\Service\NewsletterManager;
|
||||
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
|
||||
use Symfony\Bundle\SecurityBundle\Security;
|
||||
|
||||
class Step4ControllerTest extends WebTestCase
|
||||
{
|
||||
protected function tearDown(): void
|
||||
{
|
||||
self::ensureKernelShutdown();
|
||||
parent::tearDown();
|
||||
}
|
||||
|
||||
public function testStep4RendersCheckboxAndProvisionsGuestAccountAfterSuccessfulBooking(): void
|
||||
{
|
||||
$client = self::createClient([], ['HTTPS' => 'on']);
|
||||
$client->disableReboot();
|
||||
|
||||
$bookingDto = $this->createBookingDto();
|
||||
$context = $this->createBookingContext($bookingDto);
|
||||
|
||||
$bookingSessionManager = $this->createMock(BookingSessionManager::class);
|
||||
$bookingSessionManager
|
||||
->expects(self::exactly(2))
|
||||
->method('getOrCreateBookingCreateDto')
|
||||
->willReturn($bookingDto);
|
||||
|
||||
$contextFactory = $this->createMock(BookingCreateContextFactory::class);
|
||||
$contextFactory
|
||||
->expects(self::exactly(2))
|
||||
->method('createWithParticipantPrices')
|
||||
->with($bookingDto)
|
||||
->willReturn($context);
|
||||
|
||||
$userRepository = $this->createMock(UserRepository::class);
|
||||
$userRepository
|
||||
->expects(self::exactly(2))
|
||||
->method('findOneByNormalizedEmail')
|
||||
->with('[email protected]')
|
||||
->willReturn(null);
|
||||
|
||||
$guestAccountManager = $this->createMock(BookingGuestAccountManager::class);
|
||||
$guestAccountManager
|
||||
->expects(self::once())
|
||||
->method('provisionGuestAccountForBooking')
|
||||
->with('[email protected]', 123, 'Alice', 'Example')
|
||||
->willReturn(true);
|
||||
|
||||
$bookingConfigurator = $this->createMock(BookingConfigurator::class);
|
||||
$bookingConfigurator
|
||||
->expects(self::once())
|
||||
->method('applyCreateBookingStatusRules');
|
||||
|
||||
$apiClient = $this->createMock(ApiClient::class);
|
||||
$apiClient
|
||||
->expects(self::once())
|
||||
->method('createBooking')
|
||||
->with($bookingDto)
|
||||
->willReturn(new BookingResponse(BookingResponse::BOOKING_PROCESSED, 123));
|
||||
|
||||
$newsletterManager = $this->createMock(NewsletterManager::class);
|
||||
$newsletterManager->expects(self::never())->method('requestConfirmation');
|
||||
|
||||
self::getContainer()->set(BookingSessionManager::class, $bookingSessionManager);
|
||||
self::getContainer()->set(BookingCreateContextFactory::class, $contextFactory);
|
||||
self::getContainer()->set(UserRepository::class, $userRepository);
|
||||
self::getContainer()->set(BookingGuestAccountManager::class, $guestAccountManager);
|
||||
self::getContainer()->set(BookingConfigurator::class, $bookingConfigurator);
|
||||
self::getContainer()->set(ApiClient::class, $apiClient);
|
||||
self::getContainer()->set(NewsletterManager::class, $newsletterManager);
|
||||
|
||||
$crawler = $client->request('GET', '/bookings/create/confirmation');
|
||||
self::assertResponseIsSuccessful();
|
||||
self::assertStringContainsString('Benutzeraccount in MyE&P anlegen', $client->getResponse()->getContent());
|
||||
|
||||
$form = $crawler->selectButton('Verbindlich buchen')->form([
|
||||
'booking_create_step4[confirmationAccepted]' => '1',
|
||||
'booking_create_step4[termsAccepted]' => '1',
|
||||
'booking_create_step4[guestAccountOptIn]' => '1',
|
||||
]);
|
||||
$client->submit($form);
|
||||
|
||||
self::assertResponseRedirects('/bookings/create/success');
|
||||
}
|
||||
|
||||
public function testStep4HidesGuestAccountCheckboxForAuthenticatedUsers(): void
|
||||
{
|
||||
$bookingDto = $this->createBookingDto();
|
||||
$userRepository = $this->createMock(UserRepository::class);
|
||||
$userRepository->expects(self::never())->method('findOneByNormalizedEmail');
|
||||
|
||||
$controller = $this->createAuthenticatedController(
|
||||
user: new User('[email protected]'),
|
||||
userRepository: $userRepository,
|
||||
);
|
||||
|
||||
self::assertNull($controller->exposeGuestAccountTargetEmail($bookingDto));
|
||||
}
|
||||
|
||||
public function testStep4HidesGuestAccountCheckboxWhenLocalUserAlreadyExists(): void
|
||||
{
|
||||
$client = self::createClient([], ['HTTPS' => 'on']);
|
||||
$client->disableReboot();
|
||||
|
||||
$bookingDto = $this->createBookingDto();
|
||||
$context = $this->createBookingContext($bookingDto);
|
||||
|
||||
$bookingSessionManager = $this->createMock(BookingSessionManager::class);
|
||||
$bookingSessionManager
|
||||
->expects(self::once())
|
||||
->method('getOrCreateBookingCreateDto')
|
||||
->willReturn($bookingDto);
|
||||
|
||||
$contextFactory = $this->createMock(BookingCreateContextFactory::class);
|
||||
$contextFactory
|
||||
->expects(self::once())
|
||||
->method('createWithParticipantPrices')
|
||||
->with($bookingDto)
|
||||
->willReturn($context);
|
||||
|
||||
$userRepository = $this->createMock(UserRepository::class);
|
||||
$userRepository
|
||||
->expects(self::once())
|
||||
->method('findOneByNormalizedEmail')
|
||||
->with('[email protected]')
|
||||
->willReturn(new User('[email protected]'));
|
||||
|
||||
$guestAccountManager = $this->createMock(BookingGuestAccountManager::class);
|
||||
$guestAccountManager->expects(self::never())->method('provisionGuestAccount');
|
||||
|
||||
self::getContainer()->set(BookingSessionManager::class, $bookingSessionManager);
|
||||
self::getContainer()->set(BookingCreateContextFactory::class, $contextFactory);
|
||||
self::getContainer()->set(UserRepository::class, $userRepository);
|
||||
self::getContainer()->set(BookingGuestAccountManager::class, $guestAccountManager);
|
||||
|
||||
$client->request('GET', '/bookings/create/confirmation');
|
||||
|
||||
self::assertResponseIsSuccessful();
|
||||
self::assertStringNotContainsString('Benutzeraccount in MyE&P anlegen', $client->getResponse()->getContent());
|
||||
}
|
||||
|
||||
public function testGuestAccountActivationRedirectsToPersonalDataAndForcesPasswordChange(): void
|
||||
{
|
||||
$client = self::createClient([], ['HTTPS' => 'on']);
|
||||
$client->disableReboot();
|
||||
|
||||
$guestAccountManager = $this->createMock(BookingGuestAccountManager::class);
|
||||
$guestAccountManager
|
||||
->expects(self::once())
|
||||
->method('validateActivationRequest')
|
||||
->with(self::isInstanceOf(\Symfony\Component\HttpFoundation\Request::class))
|
||||
->willReturn(new User('[email protected]'));
|
||||
$guestAccountManager
|
||||
->expects(self::never())
|
||||
->method('consumeActivation');
|
||||
|
||||
$security = $this->createMock(Security::class);
|
||||
$security
|
||||
->expects(self::once())
|
||||
->method('login')
|
||||
->with(self::isInstanceOf(User::class), null, 'main')
|
||||
->willReturn(null);
|
||||
|
||||
self::getContainer()->set(BookingGuestAccountManager::class, $guestAccountManager);
|
||||
self::getContainer()->set(Security::class, $security);
|
||||
|
||||
$client->request('GET', '/welcome/[email protected]&nonce=current-nonce&expires=9999999999&_hash=signature');
|
||||
|
||||
self::assertResponseRedirects('/personal-data');
|
||||
self::assertTrue($client->getRequest()->getSession()->get(\App\Controller\Account\PersonalDataController::SESSION_FORCE_PASSWORD_CHANGE_KEY));
|
||||
}
|
||||
|
||||
private function createBookingDto(): BookingDto
|
||||
{
|
||||
$travel = new Travel();
|
||||
$travel->id = 123;
|
||||
$travel->label = 'Winterreise';
|
||||
$travel->productCode = 'PROD-1';
|
||||
$travel->dateFrom = new \DateTimeImmutable('2026-01-01');
|
||||
$travel->dateTo = new \DateTimeImmutable('2026-01-08');
|
||||
$hotel = new Hotel();
|
||||
$hotel->name = 'Hotel Test';
|
||||
$travel->hotel = $hotel;
|
||||
|
||||
$bookingDto = new BookingDto($travel, 77);
|
||||
$bookingDto->currentStep = 4;
|
||||
$bookingDto->bookingStatus = 'F';
|
||||
$bookingDto->paymentMethod = Constants::PAYMENT_METHOD_TRANSFER;
|
||||
|
||||
$participant = new ParticipantDto();
|
||||
$participant->index = 0;
|
||||
$participant->firstName = 'Alice';
|
||||
$participant->lastName = 'Example';
|
||||
$participant->email = '[email protected]';
|
||||
$participant->gender = 'M';
|
||||
$participant->nationality = 'DE';
|
||||
$participant->dateOfBirth = new \DateTimeImmutable('1990-01-01');
|
||||
$bookingDto->participants = [$participant];
|
||||
|
||||
return $bookingDto;
|
||||
}
|
||||
|
||||
private function createBookingContext(BookingDto $bookingDto): BookingCreateContext
|
||||
{
|
||||
$pricing = new BookingSummaryPricingDto([], [], null, [], 0.0);
|
||||
$vouchers = new BookingSummaryVoucherDto(null, 0.0);
|
||||
$summary = new BookingSummaryDto([], 1, $pricing, $vouchers, null);
|
||||
|
||||
return new BookingCreateContext(
|
||||
bookingDto: $bookingDto,
|
||||
summaryData: $summary,
|
||||
groupedRooms: new RoomGroupsDto([], []),
|
||||
participantPrices: [0.0],
|
||||
);
|
||||
}
|
||||
|
||||
private function createAuthenticatedController(User $user, UserRepository $userRepository): TestableStep4Controller
|
||||
{
|
||||
return new TestableStep4Controller(
|
||||
$this->createMock(BookingConfigurator::class),
|
||||
$this->createMock(BookingSessionManager::class),
|
||||
$this->createMock(BookingCreateContextFactory::class),
|
||||
$this->createMock(BookingGuestAccountManager::class),
|
||||
$this->createMock(ApiClient::class),
|
||||
$this->createMock(\Symfony\Contracts\Cache\CacheInterface::class),
|
||||
$this->createMock(NewsletterManager::class),
|
||||
$userRepository,
|
||||
$this->createMock(\Psr\Log\LoggerInterface::class),
|
||||
$user,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
final class TestableStep4Controller extends \App\Controller\Booking\Create\Step4Controller
|
||||
{
|
||||
public function __construct(
|
||||
BookingConfigurator $bookingService,
|
||||
BookingSessionManager $bookingSessionService,
|
||||
BookingCreateContextFactory $createContextFactory,
|
||||
BookingGuestAccountManager $guestAccountManager,
|
||||
ApiClient $apiClient,
|
||||
\Symfony\Contracts\Cache\CacheInterface $cache,
|
||||
NewsletterManager $doubleOptInService,
|
||||
UserRepository $userRepository,
|
||||
\Psr\Log\LoggerInterface $logger,
|
||||
private readonly User $user,
|
||||
) {
|
||||
parent::__construct(
|
||||
$bookingService,
|
||||
$bookingSessionService,
|
||||
$createContextFactory,
|
||||
$guestAccountManager,
|
||||
$apiClient,
|
||||
$cache,
|
||||
$doubleOptInService,
|
||||
$userRepository,
|
||||
$logger,
|
||||
);
|
||||
}
|
||||
|
||||
public function exposeGuestAccountTargetEmail(BookingDto $bookingDto): ?string
|
||||
{
|
||||
return $this->resolveGuestAccountTargetEmail($bookingDto);
|
||||
}
|
||||
|
||||
protected function getUser(): \Symfony\Component\Security\Core\User\UserInterface|null
|
||||
{
|
||||
return $this->user;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user