126 lines
4.8 KiB
PHP
126 lines
4.8 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Tests\Controller\Voucher;
|
|
|
|
use App\BusProNet\Model\VoucherPaymentMethod;
|
|
use App\BusProNet\Model\VoucherTemplate;
|
|
use App\BusProNet\Model\VoucherTemplates;
|
|
use App\Controller\Voucher\IndexController;
|
|
use App\Exception\VoucherShopUnavailableException;
|
|
use App\Form\Model\VoucherPurchaseDto;
|
|
use App\Model\PurchaseFlow;
|
|
use App\Service\PurchaseFlowResolver;
|
|
use App\Service\VoucherPurchaseSessionManager;
|
|
use App\Service\VoucherTemplateProvider;
|
|
use PHPUnit\Framework\TestCase;
|
|
use Symfony\Component\HttpFoundation\RedirectResponse;
|
|
use Symfony\Component\HttpFoundation\Request;
|
|
use Symfony\Component\HttpFoundation\Session\Session;
|
|
use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage;
|
|
|
|
class IndexControllerTest extends TestCase
|
|
{
|
|
private VoucherPurchaseSessionManager $sessionManager;
|
|
private PurchaseFlowResolver $purchaseFlowResolver;
|
|
|
|
protected function setUp(): void
|
|
{
|
|
$this->sessionManager = new VoucherPurchaseSessionManager();
|
|
$this->purchaseFlowResolver = new PurchaseFlowResolver();
|
|
}
|
|
|
|
public function testStartsAFreshPurchaseAndSendsTheVisitorToTheLogin(): void
|
|
{
|
|
$request = $this->createRequest();
|
|
$template = new VoucherTemplate(3, 'K', 'Allgemein');
|
|
|
|
$templateProvider = $this->createStub(VoucherTemplateProvider::class);
|
|
$templateProvider->method('getTemplates')->willReturn(new VoucherTemplates(10, 5000, [$template]));
|
|
$templateProvider->method('getPaymentMethod')->willReturn(new VoucherPaymentMethod(2, 'Überweisung', 'UEBERW'));
|
|
|
|
$response = $this->createController($templateProvider)->index($request, 'https://www.ep-reisen.de/gutscheine');
|
|
|
|
self::assertInstanceOf(RedirectResponse::class, $response);
|
|
self::assertSame('/app_login', $response->getTargetUrl());
|
|
$dto = $this->sessionManager->find($request);
|
|
self::assertSame(10, $dto?->minAmount);
|
|
self::assertSame(5000, $dto->maxAmount);
|
|
self::assertSame($template, $dto->template);
|
|
self::assertSame('https://www.ep-reisen.de/gutscheine', $this->sessionManager->getReturnUrl($request));
|
|
self::assertSame(PurchaseFlow::Voucher, $this->purchaseFlowResolver->resolvePending($request));
|
|
}
|
|
|
|
/**
|
|
* Idempotent so that a speculative fetch in the visitor's own browser cannot wipe their draft.
|
|
*/
|
|
public function testResumesAnUnfinishedPurchaseAndOnlyUpdatesTheReturnUrl(): void
|
|
{
|
|
$request = $this->createRequest();
|
|
$draft = new VoucherPurchaseDto();
|
|
$draft->currentStep = 2;
|
|
$draft->amount = 111;
|
|
$this->sessionManager->save($request, $draft);
|
|
|
|
$templateProvider = $this->createMock(VoucherTemplateProvider::class);
|
|
$templateProvider->expects(self::never())->method('getTemplates');
|
|
|
|
$response = $this->createController($templateProvider)->index($request, 'https://www.snowzone.net/');
|
|
|
|
self::assertSame('/app_login', $response->getTargetUrl());
|
|
self::assertSame($draft, $this->sessionManager->find($request));
|
|
self::assertSame(2, $draft->currentStep);
|
|
self::assertSame('https://www.snowzone.net/', $this->sessionManager->getReturnUrl($request));
|
|
}
|
|
|
|
public function testAnUnavailableShopShowsTheErrorPage(): void
|
|
{
|
|
$request = $this->createRequest();
|
|
|
|
$templateProvider = $this->createStub(VoucherTemplateProvider::class);
|
|
$templateProvider->method('getTemplates')->willThrowException(new VoucherShopUnavailableException());
|
|
|
|
$controller = $this->createController($templateProvider);
|
|
$response = $controller->index($request);
|
|
|
|
self::assertSame('/app_voucher_error', $response->getTargetUrl());
|
|
self::assertNull($this->sessionManager->find($request));
|
|
self::assertSame('error', $controller->flashes[0][0] ?? null);
|
|
}
|
|
|
|
private function createRequest(): Request
|
|
{
|
|
$request = Request::create('/gutschein');
|
|
$request->setSession(new Session(new MockArraySessionStorage()));
|
|
|
|
return $request;
|
|
}
|
|
|
|
private function createController(VoucherTemplateProvider $templateProvider): TestableIndexController
|
|
{
|
|
return new TestableIndexController($this->sessionManager, $templateProvider, $this->purchaseFlowResolver);
|
|
}
|
|
}
|
|
|
|
final class TestableIndexController extends IndexController
|
|
{
|
|
/**
|
|
* @var list<array{string, mixed}>
|
|
*/
|
|
public array $flashes = [];
|
|
|
|
protected function addFlash(string $type, mixed $message): void
|
|
{
|
|
$this->flashes[] = [$type, $message];
|
|
}
|
|
|
|
/**
|
|
* @param array<string, mixed> $parameters
|
|
*/
|
|
protected function redirectToRoute(string $route, array $parameters = [], int $status = 302): RedirectResponse
|
|
{
|
|
return new RedirectResponse('/'.$route, $status);
|
|
}
|
|
}
|