mirror of
https://github.com/Sylius/Sylius.git
synced 2026-07-14 17:10:53 +00:00
[API] Cover DELETE endpoint for product in contract tests
This commit is contained in:
parent
24f56b3d6f
commit
242cdc395f
6 changed files with 205 additions and 2 deletions
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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" />
|
||||
|
|
|
|||
|
|
@ -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, []);
|
||||
}
|
||||
}
|
||||
|
|
@ -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,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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'
|
||||
|
|
|
|||
|
|
@ -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."
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue