[API] Cover DELETE endpoint for product in contract tests

This commit is contained in:
Grzegorz Sadowski 2023-10-02 13:16:06 +02:00
parent 24f56b3d6f
commit 242cdc395f
No known key found for this signature in database
GPG key ID: EF87FF4E6E3BD364
6 changed files with 205 additions and 2 deletions

View file

@ -0,0 +1,48 @@
<?php
/*
* This file is part of the Sylius package.
*
* (c) Sylius Sp. z o.o.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Sylius\Bundle\ApiBundle\DataPersister;
use ApiPlatform\Core\DataPersister\ContextAwareDataPersisterInterface;
use Doctrine\DBAL\Exception\ForeignKeyConstraintViolationException;
use Sylius\Bundle\ApiBundle\Exception\ProductCannotBeRemoved;
use Sylius\Component\Core\Model\ProductInterface;
/** @experimental */
final class ProductDataPersister implements ContextAwareDataPersisterInterface
{
public function __construct(
private ContextAwareDataPersisterInterface $decoratedDataPersister,
) {
}
public function supports($data, array $context = []): bool
{
return $data instanceof ProductInterface;
}
/** @param ProductInterface $data */
public function persist($data, array $context = [])
{
return $this->decoratedDataPersister->persist($data, $context);
}
public function remove($data, array $context = [])
{
try {
return $this->decoratedDataPersister->remove($data, $context);
} catch (ForeignKeyConstraintViolationException) {
throw new ProductCannotBeRemoved();
}
}
}

View file

@ -53,6 +53,11 @@
<tag name="api_platform.data_persister" />
</service>
<service id="Sylius\Bundle\ApiBundle\DataPersister\ProductDataPersister">
<argument type="service" id="api_platform.doctrine.orm.data_persister" />
<tag name="api_platform.data_persister" />
</service>
<service id="Sylius\Bundle\ApiBundle\DataPersister\ProductAttributeDataPersister">
<argument type="service" id="api_platform.doctrine.orm.data_persister" />
<tag name="api_platform.data_persister" />

View file

@ -0,0 +1,72 @@
<?php
/*
* This file is part of the Sylius package.
*
* (c) Sylius Sp. z o.o.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
declare(strict_types=1);
namespace spec\Sylius\Bundle\ApiBundle\DataPersister;
use ApiPlatform\Core\DataPersister\ContextAwareDataPersisterInterface;
use Doctrine\DBAL\Exception\ForeignKeyConstraintViolationException;
use PhpSpec\ObjectBehavior;
use Sylius\Bundle\ApiBundle\Exception\ProductCannotBeRemoved;
use Sylius\Component\Core\Model\ProductInterface;
final class ProductDataPersisterSpec extends ObjectBehavior
{
function let(ContextAwareDataPersisterInterface $persister): void
{
$this->beConstructedWith($persister);
}
function it_is_a_context_aware_persister(): void
{
$this->shouldImplement(ContextAwareDataPersisterInterface::class);
}
function it_supports_only_product(ProductInterface $product): void
{
$this->supports(new \stdClass())->shouldReturn(false);
$this->supports($product)->shouldReturn(true);
}
function it_uses_inner_persister_to_persist_a_product(
ContextAwareDataPersisterInterface $persister,
ProductInterface $product,
): void {
$persister->persist($product, [])->shouldBeCalled();
$this->persist($product, []);
}
function it_throws_cannot_be_removed_exception_if_constraint_fails_on_removal(
ContextAwareDataPersisterInterface $persister,
ProductInterface $product,
): void {
$persister
->remove($product, [])
->willThrow(ForeignKeyConstraintViolationException::class)
;
$this
->shouldThrow(ProductCannotBeRemoved::class)
->during('remove', [$product])
;
}
function it_uses_inner_persister_to_remove_a_product(
ContextAwareDataPersisterInterface $persister,
ProductInterface $product,
): void {
$persister->remove($product, [])->shouldBeCalled();
$this->remove($product, []);
}
}

View file

@ -206,4 +206,52 @@ final class ProductsTest extends JsonApiTestCase
Response::HTTP_OK,
);
}
/** @test */
public function it_deletes_the_product(): void
{
$fixtures = $this->loadFixturesFromFiles([
'authentication/api_administrator.yaml',
'channel.yaml',
'product/product.yaml',
]);
$header = array_merge($this->logInAdminUser('api@example.com'), self::CONTENT_TYPE_HEADER);
/** @var ProductInterface $product */
$product = $fixtures['product_socks'];
$this->client->request(
method: 'DELETE',
uri: sprintf('/api/v2/admin/products/%s', $product->getCode()),
server: $header,
);
$this->assertResponseCode($this->client->getResponse(), Response::HTTP_NO_CONTENT);
}
/** @test */
public function it_does_not_delete_the_product_in_use(): void
{
$fixtures = $this->loadFixturesFromFiles([
'authentication/api_administrator.yaml',
'channel.yaml',
'product/product.yaml',
]);
$header = array_merge($this->logInAdminUser('api@example.com'), self::CONTENT_TYPE_HEADER);
/** @var ProductInterface $product */
$product = $fixtures['product_cap'];
$this->client->request(
method: 'DELETE',
uri: sprintf('/api/v2/admin/products/%s', $product->getCode()),
server: $header,
);
$this->assertResponse(
$this->client->getResponse(),
'admin/product/delete_product_in_use_response',
Response::HTTP_UNPROCESSABLE_ENTITY,
);
}
}

View file

@ -78,6 +78,13 @@ Sylius\Component\Core\Model\ProductVariant:
channelPricings:
WEB: '@channel_pricing_mug_red_web'
MOBILE: '@channel_pricing_mug_red_mobile'
product_variant_cap_red:
code: 'CAP_RED'
product: '@product_cap'
currentLocale: 'en_US'
optionValues: ['@product_option_value_color_red']
channelPricings:
WEB: '@channel_pricing_cap_red_web'
Sylius\Component\Product\Model\ProductVariantTranslation:
product_variant_translation_mug_blue:
@ -104,6 +111,9 @@ Sylius\Component\Core\Model\ChannelPricing:
channel_pricing_mug_red_mobile:
channelCode: 'MOBILE'
price: 2500
channel_pricing_cap_red_web:
channelCode: 'WEB'
price: 2000
Sylius\Component\Product\Model\ProductOption:
product_option_color:
@ -201,6 +211,20 @@ Sylius\Component\Product\Model\ProductAttributeTranslation:
Sylius\Component\Core\Model\ProductImage:
product_mug_thumbnail:
type: "thumbnail"
path: "product.jpg"
type: 'thumbnail'
path: 'product.jpg'
owner: '@product_mug'
Sylius\Component\Core\Model\Order:
cart_with_items:
channel: '@channel_web'
items: ['@order_item']
currencyCode: 'USD'
localeCode: 'en_US'
customer: '@customer'
state: 'cart'
Sylius\Component\Core\Model\OrderItem:
order_item:
variant: '@product_variant_cap_red'
order: '@cart_with_items'

View file

@ -0,0 +1,6 @@
{
"@context": "\/api\/v2\/contexts\/Error",
"@type": "hydra:Error",
"hydra:title": "An error occurred",
"hydra:description": "Cannot delete, the product is in use."
}