Skip to content

Commit

Permalink
[Cart Operations] Remove item mutation
Browse files Browse the repository at this point in the history
Partial #37
  • Loading branch information
pmclain committed Feb 24, 2019
1 parent 0d0b300 commit 75573a9
Show file tree
Hide file tree
Showing 3 changed files with 310 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

namespace Magento\QuoteGraphQl\Model\Resolver;

use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Framework\GraphQl\Config\Element\Field;
use Magento\Framework\GraphQl\Exception\GraphQlInputException;
use Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException;
use Magento\Framework\GraphQl\Query\ResolverInterface;
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
use Magento\Quote\Api\GuestCartItemRepositoryInterface;
use Magento\Quote\Api\GuestCartRepositoryInterface;
use Magento\QuoteGraphQl\Model\Cart\ExtractDataFromCart;

/**
* @inheritdoc
*/
class RemoveItemFromCartOutput implements ResolverInterface
{
/**
* @var GuestCartItemRepositoryInterface
*/
private $guestCartItemRepository;

/**
* @var GuestCartRepositoryInterface
*/
private $guestCartRepository;

/**
* @var ExtractDataFromCart
*/
private $extractDataFromCart;

public function __construct(
GuestCartItemRepositoryInterface $guestCartItemRepository,
GuestCartRepositoryInterface $guestCartRepository,
ExtractDataFromCart $extractDataFromCart
) {
$this->guestCartItemRepository = $guestCartItemRepository;
$this->guestCartRepository = $guestCartRepository;
$this->extractDataFromCart = $extractDataFromCart;
}

public function resolve(Field $field, $context, ResolveInfo $info, array $value = null, array $args = null)
{
if (!isset($args['input']['cart_id'])) {
throw new GraphQlInputException(__('Required parameter "cart_id" is missing'));
}
if (!isset($args['input']['cart_item_id'])) {
throw new GraphQlInputException(__('Required parameter "cart_item_id" is missing'));
}
$maskedCartId = $args['input']['cart_id'];
$itemId = $args['input']['cart_item_id'];

try {
$this->guestCartItemRepository->deleteById($maskedCartId, $itemId);
} catch (NoSuchEntityException $e) {
throw new GraphQlNoSuchEntityException(__($e->getMessage()));
}

$cart = $this->guestCartRepository->get($maskedCartId);

$cartData = $this->extractDataFromCart->execute($cart);

return ['cart' => array_merge(['cart_id' => $maskedCartId], $cartData)];
}
}
10 changes: 10 additions & 0 deletions app/code/Magento/QuoteGraphQl/etc/schema.graphqls
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ type Mutation {
setShippingAddressesOnCart(input: SetShippingAddressesOnCartInput): SetShippingAddressesOnCartOutput @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\SetShippingAddressesOnCart")
setBillingAddressOnCart(input: SetBillingAddressOnCartInput): SetBillingAddressOnCartOutput @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\SetBillingAddressOnCart")
setShippingMethodsOnCart(input: SetShippingMethodsOnCartInput): SetShippingMethodsOnCartOutput @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\SetShippingMethodsOnCart")
removeItemFromCart(input: RemoveItemFromCartInput): RemoveItemFromCartOutput @resolver(class: "Magento\\QuoteGraphQl\\Model\\Resolver\\RemoveItemFromCartOutput")
}

input AddSimpleProductsToCartInput {
Expand Down Expand Up @@ -206,6 +207,15 @@ type AddVirtualProductsToCartOutput {
cart: Cart!
}

input RemoveItemFromCartInput {
cart_id: String!
cart_item_id: String!
}

type RemoveItemFromCartOutput {
cart: Cart!
}

type SimpleCartItem implements CartItemInterface @doc(description: "Simple Cart Item") {
customizable_options: [SelectedCustomizableOption] @resolver(class: "Magento\\QuoteGraphQl\\Model\\Resolver\\CustomizableOptions")
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

namespace Magento\GraphQl\Quote;

use Magento\Catalog\Api\ProductRepositoryInterface;
use Magento\Integration\Api\CustomerTokenServiceInterface;
use Magento\Quote\Api\Data\CartInterface;
use Magento\Quote\Api\GuestCartRepositoryInterface;
use Magento\Quote\Model\Quote;
use Magento\Quote\Model\QuoteIdToMaskedQuoteIdInterface;
use Magento\Quote\Model\ResourceModel\Quote as QuoteResource;
use Magento\TestFramework\Helper\Bootstrap;
use Magento\TestFramework\TestCase\GraphQlAbstract;
use Magento\TestFramework\ObjectManager;

/**
* Test for empty cart creation mutation
*/
class RemoveItemFromCartTest extends GraphQlAbstract
{
/**
* @var QuoteResource
*/
private $quoteResource;

/**
* @var Quote
*/
private $quote;

/**
* @var QuoteIdToMaskedQuoteIdInterface
*/
private $quoteIdToMaskedId;

/**
* @var ProductRepositoryInterface
*/
private $productRepository;

/**
* @var GuestCartRepositoryInterface
*/
private $guestCartRepository;

protected function setUp()
{
$objectManager = Bootstrap::getObjectManager();
$this->quoteResource = $objectManager->create(QuoteResource::class);
$this->quote = $objectManager->create(Quote::class);
$this->quoteIdToMaskedId = $objectManager->create(QuoteIdToMaskedQuoteIdInterface::class);
$this->productRepository = $objectManager->create(ProductRepositoryInterface::class);
$this->guestCartRepository = $objectManager->create(GuestCartRepositoryInterface::class);
}

/**
* @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php
*/
public function testGuestRemoveItemFromCart()
{
$this->quoteResource->load(
$this->quote,
'test_order_with_simple_product_without_address',
'reserved_order_id'
);
$maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId());
$itemId = $this->quote->getItemByProduct($this->productRepository->get('simple'))->getId();

$query = <<<QUERY
mutation {
removeItemFromCart(
input: {
cart_id: "$maskedQuoteId"
cart_item_id: "$itemId"
}
) {
cart {
cart_id
items {
id
qty
}
}
}
}
QUERY;
$response = $this->graphQlQuery($query);

$this->assertArrayHasKey('removeItemFromCart', $response);
$this->assertArrayHasKey('cart', $response['removeItemFromCart']);

$responseCart = $response['removeItemFromCart']['cart'];

$this->assertCount(0, $responseCart['items']);
}

/**
* @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php
* @magentoApiDataFixture Magento/Customer/_files/customer.php
*/
public function testRemoveItemFromCart()
{
$this->quoteResource->load(
$this->quote,
'test_order_with_simple_product_without_address',
'reserved_order_id'
);
$maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId());
$itemId = $this->quote->getItemByProduct($this->productRepository->get('simple'))->getId();

$this->quote->setCustomerId(1);
$this->quoteResource->save($this->quote);

$headerMap = $this->getHeaderMap();

$query = <<<QUERY
mutation {
removeItemFromCart(
input: {
cart_id: "$maskedQuoteId"
cart_item_id: "$itemId"
}
) {
cart {
cart_id
items {
id
qty
}
}
}
}
QUERY;

$response = $this->graphQlQuery($query, [], '', $headerMap);

$this->assertArrayHasKey('removeItemFromCart', $response);
$this->assertArrayHasKey('cart', $response['removeItemFromCart']);

$responseCart = $response['removeItemFromCart']['cart'];

$this->assertCount(0, $responseCart['items']);
}

public function testRemoveItemFromCartNoSuchCartIdException()
{
$maskedCartId = 'nada';

$this->expectExceptionMessage('No such entity with cartId');

$query = <<<QUERY
mutation {
removeItemFromCart(
input: {
cart_id: "$maskedCartId"
cart_item_id: "nononono"
}
) {
cart {
cart_id
items {
id
qty
}
}
}
}
QUERY;
$this->graphQlQuery($query);
}

/**
* @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php
*/
public function testRemoveItemFromCartNoSuchCartItem()
{
$this->quoteResource->load(
$this->quote,
'test_order_with_simple_product_without_address',
'reserved_order_id'
);
$maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId());
$itemId = 'nononono';

$this->expectExceptionMessage(sprintf('Cart doesn\'t contain the %s item.', $itemId));

$query = <<<QUERY
mutation {
removeItemFromCart(
input: {
cart_id: "$maskedQuoteId"
cart_item_id: "$itemId"
}
) {
cart {
cart_id
items {
id
qty
}
}
}
}
QUERY;
$this->graphQlQuery($query);
}

/**
* @param string $username
* @return array
*/
private function getHeaderMap(string $username = 'customer@example.com'): array
{
$password = 'password';
/** @var CustomerTokenServiceInterface $customerTokenService */
$customerTokenService = ObjectManager::getInstance()
->get(CustomerTokenServiceInterface::class);
$customerToken = $customerTokenService->createCustomerAccessToken($username, $password);
$headerMap = ['Authorization' => 'Bearer ' . $customerToken];
return $headerMap;
}
}

0 comments on commit 75573a9

Please sign in to comment.