mirror of
https://github.com/Sylius/Sylius.git
synced 2026-07-05 20:57:12 +00:00
Merge 3b3242e0c5 into cbb32838fb
This commit is contained in:
commit
057651da11
7 changed files with 122 additions and 9 deletions
|
|
@ -52,6 +52,16 @@ Feature: Maintaining cart after authorization
|
|||
Then there should be one item in my cart
|
||||
And this item should have name "Stark T-Shirt"
|
||||
|
||||
@api @ui @mink:chromedriver
|
||||
Scenario: Having cart maintained after logging in when the guest has addressed the cart with a typo email and then corrected it
|
||||
When I add "Stark T-Shirt" product to the cart
|
||||
And I addressed the cart with email "robb@strak.com"
|
||||
And I addressed the cart with email "robb@stark.com"
|
||||
And I log in as "robb@stark.com" with "KingInTheNorth" password
|
||||
And I see the summary of my cart
|
||||
Then there should be one item in my cart
|
||||
And this item should have name "Stark T-Shirt"
|
||||
|
||||
@api @ui @mink:chromedriver
|
||||
Scenario: Having cart maintained after registration
|
||||
When I add product "Stark T-Shirt" to the cart
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ final readonly class BlameCartHandler
|
|||
throw new UnprocessableCartException();
|
||||
}
|
||||
|
||||
if (null !== $cart->getCustomer()) {
|
||||
if (!$cart->isCreatedByGuest()) {
|
||||
throw new ConflictHttpException('There is an assigned customer to this cart');
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -65,14 +65,14 @@ final class BlameCartHandlerTest extends TestCase
|
|||
->method('findCartByTokenValue')
|
||||
->with('TOKEN')
|
||||
->willReturn($this->cart);
|
||||
$this->cart->expects(self::once())->method('getCustomer')->willReturn(null);
|
||||
$this->cart->expects(self::once())->method('isCreatedByGuest')->willReturn(true);
|
||||
$this->user->expects(self::once())->method('getCustomer')->willReturn($this->customerMock);
|
||||
$this->cart->expects(self::once())->method('setCustomerWithAuthorization')->with($this->customerMock);
|
||||
$this->orderProcessor->expects(self::once())->method('process')->with($this->cart);
|
||||
$this->handler->__invoke(new BlameCart('sylius@example.com', 'TOKEN'));
|
||||
}
|
||||
|
||||
public function testThrowsAnExceptionIfCartIsOccupied(): void
|
||||
public function testThrowsAnExceptionIfCartIsNotCreatedByGuest(): void
|
||||
{
|
||||
$this->shopUserRepository->expects(self::once())
|
||||
->method('findOneByEmail')
|
||||
|
|
@ -81,7 +81,7 @@ final class BlameCartHandlerTest extends TestCase
|
|||
$this->orderRepository->expects(self::once())
|
||||
->method('findCartByTokenValue')
|
||||
->with('TOKEN')->willReturn($this->cart);
|
||||
$this->cart->expects(self::once())->method('getCustomer')->willReturn($this->customerMock);
|
||||
$this->cart->expects(self::once())->method('isCreatedByGuest')->willReturn(false);
|
||||
self::expectException(ConflictHttpException::class);
|
||||
$this->handler->__invoke(new BlameCart('sylius@example.com', 'TOKEN'));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -233,12 +233,20 @@ class OrderRepository extends BaseOrderRepository implements OrderRepositoryInte
|
|||
ChannelInterface $channel,
|
||||
CustomerInterface $customer,
|
||||
): ?OrderInterface {
|
||||
$completedCheckoutsQueryBuilder = $this->createQueryBuilder('completedOrder')
|
||||
->select('completedOrder.id')
|
||||
->andWhere('completedOrder.channel = :channel')
|
||||
->andWhere('completedOrder.customer = :customer')
|
||||
->andWhere('completedOrder.checkoutCompletedAt > o.createdAt')
|
||||
;
|
||||
|
||||
return $this->createQueryBuilder('o')
|
||||
->andWhere('o.state = :state')
|
||||
->andWhere('o.channel = :channel')
|
||||
->andWhere('o.customer = :customer')
|
||||
->andWhere('o.items IS NOT EMPTY')
|
||||
->andWhere('o.createdByGuest = :createdByGuest')
|
||||
->andWhere(sprintf('NOT EXISTS (%s)', $completedCheckoutsQueryBuilder->getDQL()))
|
||||
->setParameter('state', OrderInterface::STATE_CART)
|
||||
->setParameter('channel', $channel)
|
||||
->setParameter('customer', $customer)
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ final class ShopCartBlamerListener
|
|||
private function blame(ShopUserInterface $user): void
|
||||
{
|
||||
$cart = $this->getCart();
|
||||
if (null === $cart || null !== $cart->getCustomer()) {
|
||||
if (null === $cart || !$cart->isCreatedByGuest()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ final class ShopCartBlamerListenerTest extends TestCase
|
|||
|
||||
$this->sectionResolver->expects($this->once())->method('getSection')->willReturn($shopSection);
|
||||
$this->cartContext->expects($this->once())->method('getCart')->willReturn($cart);
|
||||
$cart->expects($this->once())->method('getCustomer')->willReturn(null);
|
||||
$cart->expects($this->once())->method('isCreatedByGuest')->willReturn(true);
|
||||
$userEvent->expects($this->once())->method('getUser')->willReturn($user);
|
||||
$user->expects($this->once())->method('getCustomer')->willReturn($customer);
|
||||
$cart->expects($this->once())->method('setCustomerWithAuthorization')->with($customer);
|
||||
|
|
@ -128,7 +128,7 @@ final class ShopCartBlamerListenerTest extends TestCase
|
|||
|
||||
$this->sectionResolver->expects($this->once())->method('getSection')->willReturn($shopSection);
|
||||
$this->cartContext->expects($this->once())->method('getCart')->willReturn($cart);
|
||||
$cart->expects($this->once())->method('getCustomer')->willReturn(null);
|
||||
$cart->expects($this->once())->method('isCreatedByGuest')->willReturn(true);
|
||||
$token->expects($this->once())->method('getUser')->willReturn($user);
|
||||
$user->expects($this->once())->method('getCustomer')->willReturn($customer);
|
||||
$cart->expects($this->once())->method('setCustomerWithAuthorization')->with($customer);
|
||||
|
|
@ -137,6 +137,28 @@ final class ShopCartBlamerListenerTest extends TestCase
|
|||
}
|
||||
|
||||
public function testDoesNothingIfGivenCartHasBeenBlamedInPast(): void
|
||||
{
|
||||
/** @var OrderInterface&MockObject $cart */
|
||||
$cart = $this->createMock(OrderInterface::class);
|
||||
/** @var Request&MockObject $request */
|
||||
$request = $this->createMock(Request::class);
|
||||
/** @var TokenInterface&MockObject $token */
|
||||
$token = $this->createMock(TokenInterface::class);
|
||||
/** @var ShopUserInterface&MockObject $user */
|
||||
$user = $this->createMock(ShopUserInterface::class);
|
||||
/** @var ShopSection&MockObject $shopSection */
|
||||
$shopSection = $this->createMock(ShopSection::class);
|
||||
|
||||
$this->sectionResolver->expects($this->once())->method('getSection')->willReturn($shopSection);
|
||||
$this->cartContext->expects($this->once())->method('getCart')->willReturn($cart);
|
||||
$cart->expects($this->once())->method('isCreatedByGuest')->willReturn(false);
|
||||
$token->expects($this->once())->method('getUser')->willReturn($user);
|
||||
$cart->expects($this->never())->method('setCustomerWithAuthorization');
|
||||
|
||||
$this->shopCartBlamerListener->onInteractiveLogin(new InteractiveLoginEvent($request, $token));
|
||||
}
|
||||
|
||||
public function testBlamesCartWhenGuestCartAlreadyHasCustomerButIsStillGuestCart(): void
|
||||
{
|
||||
/** @var OrderInterface&MockObject $cart */
|
||||
$cart = $this->createMock(OrderInterface::class);
|
||||
|
|
@ -153,9 +175,10 @@ final class ShopCartBlamerListenerTest extends TestCase
|
|||
|
||||
$this->sectionResolver->expects($this->once())->method('getSection')->willReturn($shopSection);
|
||||
$this->cartContext->expects($this->once())->method('getCart')->willReturn($cart);
|
||||
$cart->expects($this->once())->method('getCustomer')->willReturn($customer);
|
||||
$cart->expects($this->once())->method('isCreatedByGuest')->willReturn(true);
|
||||
$token->expects($this->once())->method('getUser')->willReturn($user);
|
||||
$cart->expects($this->never())->method('setCustomerWithAuthorization');
|
||||
$user->expects($this->once())->method('getCustomer')->willReturn($customer);
|
||||
$cart->expects($this->once())->method('setCustomerWithAuthorization')->with($customer);
|
||||
|
||||
$this->shopCartBlamerListener->onInteractiveLogin(new InteractiveLoginEvent($request, $token));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -110,6 +110,78 @@ final class CartTest extends JsonApiTestCase
|
|||
self::assertSame([], $response['items']);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function it_does_not_return_a_cart_abandoned_before_the_customer_last_completed_checkout(): void
|
||||
{
|
||||
$this->setUpDefaultPostHeaders();
|
||||
$this->setUpShopUserContext();
|
||||
|
||||
$this->loadFixturesFromFiles([
|
||||
'authentication/shop_user.yaml',
|
||||
'channel/channel.yaml',
|
||||
'cart.yaml',
|
||||
'country.yaml',
|
||||
'shipping_method.yaml',
|
||||
'payment_method.yaml',
|
||||
]);
|
||||
|
||||
$this->placeOrder(
|
||||
tokenValue: 'placedOrderToken',
|
||||
email: 'shop@example.com',
|
||||
checkoutCompletedAt: new \DateTimeImmutable(),
|
||||
);
|
||||
|
||||
$abandonedCartToken = $this->pickUpCart(tokenValue: 'abandonedCartToken', email: 'shop@example.com');
|
||||
$this->addItemToCart('MUG_BLUE', 3, $abandonedCartToken);
|
||||
|
||||
$abandonedCart = $this->orderRepository->findCartByTokenValue($abandonedCartToken);
|
||||
$abandonedCart->setCreatedAt(new \DateTime('-1 hour'));
|
||||
$this->get('doctrine.orm.entity_manager')->flush();
|
||||
|
||||
$this->requestPost(uri: '/api/v2/shop/orders', body: []);
|
||||
|
||||
$this->assertResponseCode($this->client->getResponse(), Response::HTTP_CREATED);
|
||||
|
||||
$response = json_decode($this->client->getResponse()->getContent(), true, flags: \JSON_THROW_ON_ERROR);
|
||||
|
||||
self::assertNotSame($abandonedCartToken, $response['tokenValue']);
|
||||
self::assertSame([], $response['items']);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function it_returns_the_customer_cart_created_after_the_last_completed_checkout(): void
|
||||
{
|
||||
$this->setUpDefaultPostHeaders();
|
||||
$this->setUpShopUserContext();
|
||||
|
||||
$this->loadFixturesFromFiles([
|
||||
'authentication/shop_user.yaml',
|
||||
'channel/channel.yaml',
|
||||
'cart.yaml',
|
||||
'country.yaml',
|
||||
'shipping_method.yaml',
|
||||
'payment_method.yaml',
|
||||
]);
|
||||
|
||||
$this->placeOrder(
|
||||
tokenValue: 'placedOrderToken',
|
||||
email: 'shop@example.com',
|
||||
checkoutCompletedAt: new \DateTimeImmutable('-1 hour'),
|
||||
);
|
||||
|
||||
$newCartToken = $this->pickUpCart(tokenValue: 'newCartToken', email: 'shop@example.com');
|
||||
$this->addItemToCart('MUG_BLUE', 3, $newCartToken);
|
||||
|
||||
$this->requestPost(uri: '/api/v2/shop/orders', body: []);
|
||||
|
||||
$this->assertResponseCode($this->client->getResponse(), Response::HTTP_CREATED);
|
||||
|
||||
$response = json_decode($this->client->getResponse()->getContent(), true, flags: \JSON_THROW_ON_ERROR);
|
||||
|
||||
self::assertSame($newCartToken, $response['tokenValue']);
|
||||
self::assertCount(1, $response['items']);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function it_gets_an_empty_cart_as_guest(): void
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue