[ShopBundle][ApiBundle] Fix ShopCartBlamerListener to allow reassigning guest cart on login

This commit is contained in:
Mateusz 2026-06-12 15:01:24 +02:00
parent f8a27841f2
commit 4d35ae1d75
5 changed files with 42 additions and 9 deletions

View file

@ -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

View file

@ -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');
}

View file

@ -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'));
}

View file

@ -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;
}

View file

@ -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));
}