[Shop][Checkout] Prevent starting checkout with empty cart

This commit is contained in:
Arminek 2016-09-14 01:48:01 +02:00
parent a63e26058c
commit 5210baf7d5
6 changed files with 97 additions and 10 deletions

View file

@ -0,0 +1,17 @@
@checkout
Feature: Prevent starting checkout with empty cart
In order to get back to shop after starting checkout with empty cart
As a Customer
I want to be able to add something to cart before entering checkout
Background:
Given the store operates on a single channel in "United States"
And the store has a product "PHP T-Shirt" priced at "$19.99"
And the store ships everywhere for free
And the store allows paying offline
And I am a logged in customer
@ui
Scenario: Being on shop home page after starting checkout with empty cart
Given I have tried to open checkout addressing page
Then I should be redirected to the homepage

View file

@ -169,6 +169,14 @@ final class CheckoutContext implements Context
$this->addressPage->open();
}
/**
* @Given I have tried to open checkout addressing page
*/
public function iHaveTriedToOpenCheckoutAddressingPage()
{
$this->addressPage->tryToOpen();
}
/**
* @Given /^(this user) bought this product$/
*/

View file

@ -83,6 +83,11 @@ final class CheckoutResolver implements EventSubscriberInterface
/** @var OrderInterface $order */
$order = $this->cartContext->getCart();
if ($order->isEmpty()) {
$event->setResponse(new RedirectResponse($this->urlGenerator->generate('sylius_shop_homepage')));
}
$stateMachine = $this->stateMachineFactory->get($order, OrderCheckoutTransitions::GRAPH);
if ($stateMachine->can($this->getRequestedTransition($request))) {
@ -95,7 +100,7 @@ final class CheckoutResolver implements EventSubscriberInterface
return;
}
$event->setResponse(new RedirectResponse($this->urlGenerator->generate($order->getCheckoutState())));
$event->setResponse(new RedirectResponse($this->urlGenerator->generateForOrderCheckoutState($order)));
}
/**

View file

@ -11,15 +11,15 @@
namespace Sylius\Bundle\CoreBundle\Checkout;
use Sylius\Component\Core\Model\OrderInterface;
use Symfony\Component\Routing\Exception\RouteNotFoundException;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Routing\RequestContext;
use Symfony\Component\Routing\RouterInterface;
/**
* @author Arkadiusz Krakowiak <arkadiusz.krakowiak@lakion.com>
*/
final class CheckoutStateUrlGenerator implements UrlGeneratorInterface
final class CheckoutStateUrlGenerator implements CheckoutStateUrlGeneratorInterface
{
/**
* @var RouterInterface
@ -44,13 +44,21 @@ final class CheckoutStateUrlGenerator implements UrlGeneratorInterface
/**
* {@inheritdoc}
*/
public function generate($name, $parameters = array(), $referenceType = self::ABSOLUTE_PATH)
public function generate($name, $parameters = [], $referenceType = self::ABSOLUTE_PATH)
{
if (!isset($this->routeCollection[$name]['route'])) {
return $this->router->generate($name, $parameters, $referenceType);
}
/**
* {@inheritdoc}
*/
public function generateForOrderCheckoutState(OrderInterface $order, $parameters = [], $referenceType = self::ABSOLUTE_PATH)
{
if (!isset($this->routeCollection[$order->getCheckoutState()]['route'])) {
throw new RouteNotFoundException();
}
return $this->router->generate($this->routeCollection[$name]['route'], $parameters, $referenceType);
return $this->router->generate($this->routeCollection[$order->getCheckoutState()]['route'], $parameters, $referenceType);
}
/**

View file

@ -0,0 +1,30 @@
<?php
/*
* This file is part of the Sylius package.
*
* (c) Paweł Jędrzejewski
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sylius\Bundle\CoreBundle\Checkout;
use Sylius\Component\Core\Model\OrderInterface;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
/**
* @author Arkadiusz Krakowiak <arkadiusz.krakowiak@lakion.com>
*/
interface CheckoutStateUrlGeneratorInterface extends UrlGeneratorInterface
{
/**
* @param OrderInterface $order
* @param array $parameters
* @param int $referenceType
*
* @return string
*/
public function generateForOrderCheckoutState(OrderInterface $order, $parameters = [], $referenceType = self::ABSOLUTE_PATH);
}

View file

@ -14,6 +14,8 @@ namespace spec\Sylius\Bundle\CoreBundle\Checkout;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use Sylius\Bundle\CoreBundle\Checkout\CheckoutStateUrlGenerator;
use Sylius\Bundle\CoreBundle\Checkout\CheckoutStateUrlGeneratorInterface;
use Sylius\Component\Core\Model\OrderInterface;
use Symfony\Component\Routing\Exception\RouteNotFoundException;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Routing\RouterInterface;
@ -46,19 +48,36 @@ final class CheckoutStateUrlGeneratorSpec extends ObjectBehavior
$this->shouldImplement(UrlGeneratorInterface::class);
}
function it_generates_state_url(RouterInterface $router)
function it_is_a_checkout_state_url_generator()
{
$this->shouldImplement(CheckoutStateUrlGeneratorInterface::class);
}
function it_generates_state_url(RouterInterface $router, OrderInterface $order)
{
$order->getCheckoutState()->willReturn('addressed');
$router->generate('sylius_shop_checkout_select_shipping', [], UrlGeneratorInterface::ABSOLUTE_PATH)
->willReturn('/checkout/address')
;
$this->generate('addressed')->shouldReturn('/checkout/address');
$this->generateForOrderCheckoutState($order)->shouldReturn('/checkout/address');
}
function it_throws_route_not_found_exception_if_there_is_no_route_for_given_state(RouterInterface $router)
function it_is_a_regular_url_generator(RouterInterface $router)
{
$router->generate('route_name', [], UrlGeneratorInterface::ABSOLUTE_PATH)->willReturn('/some-route');
$this->generate('route_name')->shouldReturn('/some-route');
}
function it_throws_route_not_found_exception_if_there_is_no_route_for_given_state(
RouterInterface $router,
OrderInterface $order
) {
$order->getCheckoutState()->willReturn('shipping_selected');
$router->generate(Argument::any())->shouldNotBeCalled();
$this->shouldThrow(RouteNotFoundException::class)->during('generate', ['shipping_selected']);
$this->shouldThrow(RouteNotFoundException::class)->during('generateForOrderCheckoutState', [$order]);
}
}