[Api][Admin] Cover product attributes removing

This commit is contained in:
Jan Goralski 2023-09-04 14:23:19 +02:00 committed by Grzegorz Sadowski
parent 5c5b767929
commit 89cc7a22a4
No known key found for this signature in database
GPG key ID: EF87FF4E6E3BD364
17 changed files with 167 additions and 43 deletions

View file

@ -10,7 +10,7 @@ Feature: Deleting multiple product attributes
And the store has a integer product attribute "Pages"
And I am logged in as an administrator
@ui @javascript
@ui @javascript @no-api
Scenario: Deleting multiple product attributes at once
When I browse product attributes
And I check the "Publisher" product attribute

View file

@ -1,5 +1,5 @@
@managing_product_attributes
Feature:Removing a attribute
Feature: Deleting a product attribute
In order to keep my collection of product attributes not cluttered
As an administrator
I want to be able to remove an attribute that is not assigned to any of the products
@ -8,13 +8,13 @@ Feature:Removing a attribute
Given I am logged in as an administrator
And the store has a product "44 Magnum"
@ui
@ui @api
Scenario: Try deleting a attribute from the registry when product use him
Given this product has a text attribute "Gun caliber" with value "11 mm"
When I delete this product attribute
Then I should be notified that it has been failed deleted "product attribute"
Then I should be notified that it is in use
@ui
@ui @api
Scenario: Deleting a text product attribute when not by used
Given the store has a text product attribute "Gun caliber"
When I delete this product attribute

View file

@ -1,15 +0,0 @@
@managing_product_attributes
Feature: Deleting a text product attribute
In order to remove test, obsolete or incorrect text product attribute
As an Administrator
I want to be able to delete a text product attribute
Background:
Given I am logged in as an administrator
@ui
Scenario: Deleting a text product attribute from the registry
Given the store has a text product attribute "T-Shirt cotton brand"
When I delete this product attribute
Then I should be notified that it has been successfully deleted
And this product attribute should no longer exist in the registry

View file

@ -8,6 +8,7 @@ use Behat\Behat\Context\Context;
use Sylius\Behat\Client\ApiClientInterface;
use Sylius\Behat\Client\ResponseCheckerInterface;
use Sylius\Behat\Context\Api\Resources;
use Sylius\Component\Product\Model\ProductAttributeInterface;
use Webmozart\Assert\Assert;
final class ManagingProductAttributesContext implements Context
@ -26,6 +27,14 @@ final class ManagingProductAttributesContext implements Context
$this->client->index(Resources::PRODUCT_ATTRIBUTES);
}
/**
* @When /^I(?:| try to) delete (this product attribute)$/
*/
public function iDeleteThisProductAttribute(ProductAttributeInterface $attribute): void
{
$this->client->delete(Resources::PRODUCT_ATTRIBUTES, $attribute->getCode());
}
/**
* @Then I should see :count product attributes in the list
*/
@ -46,4 +55,36 @@ final class ManagingProductAttributesContext implements Context
$attributeName,
));
}
/**
* @Then I should be notified that it has been successfully deleted
*/
public function iShouldBeNotifiedThatItHasBeenSuccessfullyDeleted(): void
{
$this->responseChecker->isDeletionSuccessful($this->client->getLastResponse());
}
/**
* @Then /^(this product attribute) should no longer exist in the registry$/
*/
public function thisProductAttributeShouldNoLongerExistInTheRegistry(ProductAttributeInterface $productAttribute): void
{
$response = $this->client->index(Resources::PRODUCT_ATTRIBUTES);
Assert::false(
$this->responseChecker->hasItemWithValue($response, 'code', $productAttribute->getCode()),
sprintf('Product attribute with code %s exists, but should not', $productAttribute->getCode()),
);
}
/**
* @Then I should be notified that it is in use
*/
public function iShouldBeNotifiedThatItIsInUse(): void
{
Assert::contains(
$this->responseChecker->getError($this->client->getLastResponse()),
'Cannot delete, the product attribute is in use.',
);
}
}

View file

@ -99,14 +99,6 @@ final class ManagingPaymentMethodsContext implements Context
$this->indexPage->deleteResourceOnPage(['code' => $paymentMethod->getCode(), 'name' => $paymentMethod->getName()]);
}
/**
* @Then I should be notified that it is in use
*/
public function iShouldBeNotifiedThatItIsInUse()
{
$this->notificationChecker->checkNotification('Cannot delete, the Payment method is in use.', NotificationType::failure());
}
/**
* @Then this payment method :element should be :value
*/

View file

@ -328,7 +328,7 @@ final class ManagingProductAttributesContext implements Context
}
/**
* @When /^I delete (this product attribute)$/
* @When /^I(?:| try to) delete (this product attribute)$/
*/
public function iDeleteThisProductAttribute(ProductAttributeInterface $productAttribute)
{

View file

@ -448,14 +448,6 @@ final class ManagingShippingMethodsContext implements Context
Assert::false($this->indexPage->isSingleResourceOnPage(['code' => $shippingMethod->getCode()]));
}
/**
* @Then I should be notified that it is in use
*/
public function iShouldBeNotifiedThatItIsInUse()
{
$this->notificationChecker->checkNotification('Cannot delete, the Shipping method is in use.', NotificationType::failure());
}
/**
* @Then I should be notified that amount for :channel channel should not be blank
*/

View file

@ -76,14 +76,14 @@ final class NotificationContext implements Context
}
/**
* @Then I should be notified that it has been failed deleted :name
* @Then I should be notified that it is in use
*/
public function iShouldBeNotifiedThatItHasBeenFailedDeleted(string $name): void
public function iShouldBeNotifiedThatItIsInUse(): void
{
$this->testHelper->waitUntilNotificationPopups(
$this->notificationChecker,
NotificationType::failure(),
'Cannot delete, the ' . ucfirst($name) . ' is in use.',
'Cannot delete',
);
}
}

View file

@ -10,8 +10,11 @@ default:
- sylius.behat.context.setup.admin_api_security
- sylius.behat.context.setup.channel
- sylius.behat.context.setup.locale
- sylius.behat.context.setup.product
- sylius.behat.context.setup.product_attribute
- sylius.behat.context.transform.shared_storage
- sylius.behat.context.api.admin.managing_product_attributes
filters:

View file

@ -0,0 +1,37 @@
<?php
declare(strict_types=1);
namespace Sylius\Bundle\ApiBundle\DataPersister;
use ApiPlatform\Core\DataPersister\ContextAwareDataPersisterInterface;
use Doctrine\DBAL\Exception\ForeignKeyConstraintViolationException;
use Sylius\Bundle\ApiBundle\Exception\ProductAttributeCannotBeRemoved;
use Sylius\Component\Product\Model\ProductAttributeInterface;
/** @experimental */
final class ProductAttributeDataPersister implements ContextAwareDataPersisterInterface
{
public function __construct(private ContextAwareDataPersisterInterface $decoratedDataPersister)
{
}
public function supports($data, array $context = []): bool
{
return $data instanceof ProductAttributeInterface;
}
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 ProductAttributeCannotBeRemoved();
}
}
}

View file

@ -0,0 +1,14 @@
<?php
declare(strict_types=1);
namespace Sylius\Bundle\ApiBundle\Exception;
/** @experimental */
final class ProductAttributeCannotBeRemoved extends \RuntimeException
{
public function __construct()
{
parent::__construct('Cannot delete, the product attribute is in use.');
}
}

View file

@ -37,6 +37,11 @@
</attribute>
</itemOperation>
<itemOperation name="admin_delete">
<attribute name="method">DELETE</attribute>
<attribute name="path">/admin/product-attributes/{code}</attribute>
</itemOperation>
<itemOperation name="shop_get">
<attribute name="method">GET</attribute>
<attribute name="path">/shop/product-attributes/{code}</attribute>

View file

@ -52,6 +52,7 @@ api_platform:
Sylius\Bundle\ApiBundle\Exception\CannotRemoveCurrentlyLoggedInUser: 422
Sylius\Bundle\ApiBundle\Exception\OrderItemNotFoundException: 422
Sylius\Bundle\ApiBundle\Exception\OrderNoLongerEligibleForPromotion: 422
Sylius\Bundle\ApiBundle\Exception\ProductAttributeCannotBeRemoved: 422
Sylius\Bundle\ApiBundle\Exception\ProductCannotBeRemoved: 422
Sylius\Bundle\ApiBundle\Exception\ProvinceCannotBeRemoved: 422
Sylius\Bundle\ApiBundle\Exception\ShippingMethodCannotBeRemoved: 422

View file

@ -53,6 +53,11 @@
<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" />
</service>
<service id="Sylius\Bundle\ApiBundle\DataPersister\ProductTaxonDataPersister">
<argument type="service" id="api_platform.doctrine.orm.data_persister" />
<argument type="service" id="sylius.event_bus" />

View file

@ -13,6 +13,7 @@ declare(strict_types=1);
namespace Sylius\Tests\Api\Admin;
use Sylius\Component\Product\Model\ProductAttributeInterface;
use Sylius\Tests\Api\JsonApiTestCase;
use Sylius\Tests\Api\Utils\AdminUserLoginTrait;
use Symfony\Component\HttpFoundation\Response;
@ -35,4 +36,24 @@ final class ProductAttributesTest extends JsonApiTestCase
Response::HTTP_OK,
);
}
/** @test */
public function it_deletes_a_product_attribute(): void
{
$fixtures = $this->loadFixturesFromFiles([
'authentication/api_administrator.yaml',
'product/product_attribute.yaml',
]);
$header = array_merge($this->logInAdminUser('api@example.com'), self::CONTENT_TYPE_HEADER);
/** @var ProductAttributeInterface $productAttribute */
$productAttribute = $fixtures['product_attribute_text_delete'];
$this->client->request(
method: 'DELETE',
uri: sprintf('/api/v2/admin/product-attributes/%s', $productAttribute->getCode()),
server: $header,
);
$this->assertResponseCode($this->client->getResponse(), Response::HTTP_NO_CONTENT);
}
}

View file

@ -89,6 +89,15 @@ Sylius\Component\Product\Model\ProductAttribute:
storage_type: 'text'
configuration: []
translatable: true
product_attribute_text_delete:
fallbackLocale: en_US
currentLocale: en_US
code: 'text_delete'
name: 'text delete'
type: 'text'
storage_type: 'text'
configuration: []
translatable: false
Sylius\Component\Product\Model\ProductAttributeTranslation:
product_attribute_translation_checkbox:

View file

@ -173,7 +173,26 @@
}
},
"type": "text"
},
{
"@id": "\/api\/v2\/admin\/product-attributes/text_delete",
"@type": "ProductAttribute",
"code": "text_delete",
"configuration": [],
"position": 8,
"storageType": "text",
"translatable": false,
"translations": {
"en_US": {
"@id": "\/api\/v2\/admin\/product-attribute-translations\/@integer@",
"@type": "ProductAttributeTranslation",
"id": "@integer@",
"name": "text delete",
"locale": "en_US"
}
},
"type": "text"
}
],
"hydra:totalItems": 8
"hydra:totalItems": 9
}