mirror of
https://github.com/Sylius/Sylius.git
synced 2026-07-14 17:10:53 +00:00
Merge pull request #4364 from TheMadeleine/product-not-softdeletable-implementation
[Product] Remove softdeletable from Product
This commit is contained in:
commit
2a3dff8efd
40 changed files with 906 additions and 245 deletions
43
app/migrations/Version20160309144959.php
Normal file
43
app/migrations/Version20160309144959.php
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Sylius package.
|
||||
*
|
||||
* (c) Paweł Jędrzejewski
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Sylius\Migrations;
|
||||
|
||||
use Doctrine\DBAL\Migrations\AbstractMigration;
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
|
||||
/**
|
||||
* Auto-generated Migration: Please modify to your needs!
|
||||
*/
|
||||
class Version20160309144959 extends AbstractMigration
|
||||
{
|
||||
/**
|
||||
* @param Schema $schema
|
||||
*/
|
||||
public function up(Schema $schema)
|
||||
{
|
||||
// this up() migration is auto-generated, please modify it to your needs
|
||||
$this->abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.');
|
||||
|
||||
$this->addSql('ALTER TABLE sylius_product DROP deleted_at');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Schema $schema
|
||||
*/
|
||||
public function down(Schema $schema)
|
||||
{
|
||||
// this down() migration is auto-generated, please modify it to your needs
|
||||
$this->abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.');
|
||||
|
||||
$this->addSql('ALTER TABLE sylius_product ADD deleted_at DATETIME DEFAULT NULL');
|
||||
}
|
||||
}
|
||||
|
|
@ -41,7 +41,9 @@
|
|||
|
||||
<service id="sylius.behat.context.domain.product" class="%sylius.behat.context.domain.product.class%" scope="scenario">
|
||||
<argument type="service" id="sylius.behat.shared_storage" container="symfony" />
|
||||
<argument type="service" id="sylius.repository.product_variant" container="symfony"/>
|
||||
<argument type="service" id="sylius.repository.product" container="symfony" />
|
||||
<argument type="service" id="sylius.repository.product_variant" container="symfony" />
|
||||
<argument type="service" id="sylius.repository.product_review" container="symfony" />
|
||||
<tag name="sylius.behat.context" />
|
||||
</service>
|
||||
</services>
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
<parameter key="sylius.behat.context.setup.security.class">Sylius\Behat\Context\Setup\SecurityContext</parameter>
|
||||
<parameter key="sylius.behat.context.setup.user.class">Sylius\Behat\Context\Setup\UserContext</parameter>
|
||||
<parameter key="sylius.behat.context.setup.product.class">Sylius\Behat\Context\Setup\ProductContext</parameter>
|
||||
<parameter key="sylius.behat.context.setup.product_review.class">Sylius\Behat\Context\Setup\ProductReviewContext</parameter>
|
||||
<parameter key="sylius.behat.context.setup.promotion.class">Sylius\Behat\Context\Setup\PromotionContext</parameter>
|
||||
<parameter key="sylius.behat.context.setup.shipping.class">Sylius\Behat\Context\Setup\ShippingContext</parameter>
|
||||
<parameter key="sylius.behat.context.setup.zone.class">Sylius\Behat\Context\Setup\ZoneContext</parameter>
|
||||
|
|
@ -88,6 +89,13 @@
|
|||
<tag name="sylius.behat.context" />
|
||||
</service>
|
||||
|
||||
<service id="sylius.behat.context.setup.product_review" class="%sylius.behat.context.setup.product_review.class%" scope="scenario">
|
||||
<argument type="service" id="sylius.behat.shared_storage" container="symfony" />
|
||||
<argument type="service" id="sylius.factory.product_review" container="symfony" />
|
||||
<argument type="service" id="sylius.repository.product_review" container="symfony" />
|
||||
<tag name="sylius.behat.context" />
|
||||
</service>
|
||||
|
||||
<service id="sylius.behat.context.setup.promotion" class="%sylius.behat.context.setup.promotion.class%" scope="scenario">
|
||||
<argument type="service" id="sylius.behat.shared_storage" container="symfony" />
|
||||
<argument type="service" id="sylius.factory.promotion_action" container="symfony" />
|
||||
|
|
|
|||
|
|
@ -70,7 +70,10 @@
|
|||
</service>
|
||||
|
||||
<service id="sylius.behat.context.ui.product" class="%sylius.behat.context.ui.product.class%" scope="scenario">
|
||||
<argument type="service" id="sylius.behat.shared_storage" container="symfony" />
|
||||
<argument type="service" id="sylius.behat.page.product_show" />
|
||||
<argument type="service" id="sylius.behat.page.admin.product_show" />
|
||||
<argument type="service" id="sylius.behat.page.admin.product_index" />
|
||||
<tag name="sylius.behat.context" />
|
||||
</service>
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,9 @@
|
|||
|
||||
<container xmlns="http://symfony.com/schema/dic/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
|
||||
<parameters>
|
||||
<parameter key="sylius.behat.page.admin.product_show.class">Sylius\Behat\Page\Admin\Product\ShowPage</parameter>
|
||||
<parameter key="sylius.behat.page.admin.product_index.class">Sylius\Behat\Page\Admin\Product\IndexPage</parameter>
|
||||
|
||||
<parameter key="sylius.behat.page.cart_summary.class">Sylius\Behat\Page\Cart\CartSummaryPage</parameter>
|
||||
<parameter key="sylius.behat.page.product_show.class">Sylius\Behat\Page\Product\ProductShowPage</parameter>
|
||||
<parameter key="sylius.behat.page.customer_show.class">Sylius\Behat\Page\Customer\CustomerShowPage</parameter>
|
||||
|
|
@ -38,6 +41,11 @@
|
|||
<parameter key="sylius.behat.page.admin.locale.index.class">%sylius.behat.page.admin.crud.index.class%</parameter>
|
||||
</parameters>
|
||||
<services>
|
||||
<service id="sylius.behat.page.admin.product_show" class="%sylius.behat.page.admin.product_show.class%" parent="sylius.behat.symfony_page" scope="scenario" public="false" />
|
||||
<service id="sylius.behat.page.admin.product_index" class="%sylius.behat.page.admin.product_index.class%" parent="sylius.behat.symfony_page" scope="scenario" public="false">
|
||||
<argument type="service" id="sylius.behat.table_manipulator" />
|
||||
</service>
|
||||
|
||||
<service id="sylius.behat.page.cart_summary" class="%sylius.behat.page.cart_summary.class%" parent="sylius.behat.symfony_page" scope="scenario" public="false" />
|
||||
<service id="sylius.behat.page.product_show" class="%sylius.behat.page.product_show.class%" parent="sylius.behat.symfony_page" scope="scenario" public="false" />
|
||||
<service id="sylius.behat.page.customer_show" class="%sylius.behat.page.customer_show.class%" parent="sylius.behat.symfony_page" scope="scenario" public="false" />
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ imports:
|
|||
- suites/ui/theme.yml
|
||||
- suites/ui/user.yml
|
||||
- suites/ui/localization.yml
|
||||
- suites/ui/product.yml
|
||||
|
||||
- suites/domain/order.yml
|
||||
- suites/domain/product.yml
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@ default:
|
|||
- sylius.behat.context.setup.payment
|
||||
- sylius.behat.context.setup.shipping
|
||||
- sylius.behat.context.setup.order
|
||||
- sylius.behat.context.setup.product_review
|
||||
- sylius.behat.context.setup.security
|
||||
|
||||
- sylius.behat.context.domain.product
|
||||
|
||||
|
|
|
|||
25
etc/behat/suites/ui/product.yml
Normal file
25
etc/behat/suites/ui/product.yml
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
# This file is part of the Sylius package.
|
||||
# (c) Paweł Jędrzejewski
|
||||
|
||||
default:
|
||||
suites:
|
||||
ui_product:
|
||||
contexts_as_services:
|
||||
- sylius.behat.context.hook.doctrine_orm
|
||||
|
||||
- sylius.behat.context.transform.zone
|
||||
- sylius.behat.context.transform.lexical
|
||||
- sylius.behat.context.transform.shared_storage
|
||||
- sylius.behat.context.transform.product
|
||||
|
||||
- sylius.behat.context.setup.channel
|
||||
- sylius.behat.context.setup.geographical
|
||||
- sylius.behat.context.setup.product
|
||||
- sylius.behat.context.setup.zone
|
||||
- sylius.behat.context.setup.product_review
|
||||
- sylius.behat.context.setup.security
|
||||
|
||||
- sylius.behat.context.ui.product
|
||||
|
||||
filters:
|
||||
tags: @product && @ui
|
||||
|
|
@ -82,14 +82,6 @@ Feature: Orders management
|
|||
Then I should be on the order index page
|
||||
And I should see "Order has been successfully deleted"
|
||||
|
||||
Scenario: Order integrity is preserved after deleting a product
|
||||
Given I have deleted the product "Mug"
|
||||
And I go to the order index page
|
||||
When I click "Details" near "#000000001"
|
||||
Then I should be viewing order with number "000000001"
|
||||
And I should see "Mug"
|
||||
And I should see "Total: €14.74"
|
||||
|
||||
Scenario: Accessing the order details page from list
|
||||
Given I am on the order index page
|
||||
When I click "Details" near "#000000001"
|
||||
|
|
|
|||
|
|
@ -9,18 +9,19 @@ Feature: Deleting a product
|
|||
And the store has a product "Toyota GT86 model"
|
||||
And this product has "1:43" variant priced at "€15.00"
|
||||
And this product has one review
|
||||
And I am logged in as administrator
|
||||
|
||||
@todo
|
||||
@ui @javascript
|
||||
Scenario: Deleted product disappears from the product catalog
|
||||
When I delete the "Toyota GT86 model" product
|
||||
Then this product should not exist in the product catalog
|
||||
|
||||
@todo
|
||||
@domain
|
||||
Scenario: Deleted product variants disappear from the product catalog
|
||||
When I delete the "Toyota GT86 model" product
|
||||
Then there should be no "1:43" variant of this product in the product catalog
|
||||
Then there should be no variants of this product in the product catalog
|
||||
|
||||
@todo
|
||||
@domain
|
||||
Scenario: Deleted product reviews disappear from the product catalog
|
||||
When I delete the "Toyota GT86 model" product
|
||||
Then there should be no reviews of this product
|
||||
|
|
|
|||
|
|
@ -0,0 +1,20 @@
|
|||
@product
|
||||
Feature: Prevent deletion of purchased product
|
||||
In order to maintain proper order history
|
||||
As an Administrator
|
||||
I want to be prevented from deleting purchased products
|
||||
|
||||
Background:
|
||||
Given the store operates on a single channel in "France"
|
||||
And the store ships everywhere for free
|
||||
And the store allows paying with "Cash on Delivery"
|
||||
And the store has a product "Toyota GT86 model"
|
||||
And the customer "john.doe@gmail.com" placed an order "#00000027"
|
||||
And the customer chose "Free" shipping method to "France" with "Cash on Delivery" payment
|
||||
And the customer bought single "Toyota GT86 model"
|
||||
|
||||
@domain
|
||||
Scenario: Purchased product cannot be deleted
|
||||
When I try to delete the "Toyota GT86 model" product
|
||||
Then I should be notified that this product is in use and cannot be deleted
|
||||
And this product should still exist in the product catalog
|
||||
|
|
@ -13,12 +13,15 @@ namespace Sylius\Behat\Context\Domain;
|
|||
|
||||
use Behat\Behat\Context\Context;
|
||||
use Doctrine\DBAL\DBALException;
|
||||
use Sylius\Component\Core\Model\ProductInterface;
|
||||
use Sylius\Component\Core\Model\ProductVariantInterface;
|
||||
use Sylius\Component\Core\Repository\ProductVariantRepositoryInterface;
|
||||
use Sylius\Component\Core\Test\Services\SharedStorageInterface;
|
||||
use Sylius\Component\Resource\Repository\RepositoryInterface;
|
||||
|
||||
/**
|
||||
* @author Łukasz Chruściel <lukasz.chrusciel@lakion.com>
|
||||
* @author Magdalena Banasiak <magdalena.banasiak@lakion.com>
|
||||
*/
|
||||
final class ProductContext implements Context
|
||||
{
|
||||
|
|
@ -27,21 +30,37 @@ final class ProductContext implements Context
|
|||
*/
|
||||
private $sharedStorage;
|
||||
|
||||
/**
|
||||
* @var RepositoryInterface
|
||||
*/
|
||||
private $productRepository;
|
||||
|
||||
/**
|
||||
* @var ProductVariantRepositoryInterface
|
||||
*/
|
||||
private $productVariantRepository;
|
||||
|
||||
/**
|
||||
* @var RepositoryInterface
|
||||
*/
|
||||
private $reviewRepository;
|
||||
|
||||
/**
|
||||
* @param SharedStorageInterface $sharedStorage
|
||||
* @param RepositoryInterface $productRepository
|
||||
* @param ProductVariantRepositoryInterface $productVariantRepository
|
||||
* @param RepositoryInterface $reviewRepository
|
||||
*/
|
||||
public function __construct(
|
||||
SharedStorageInterface $sharedStorage,
|
||||
ProductVariantRepositoryInterface $productVariantRepository
|
||||
RepositoryInterface $productRepository,
|
||||
ProductVariantRepositoryInterface $productVariantRepository,
|
||||
RepositoryInterface $reviewRepository
|
||||
) {
|
||||
$this->sharedStorage = $sharedStorage;
|
||||
$this->productRepository = $productRepository;
|
||||
$this->productVariantRepository = $productVariantRepository;
|
||||
$this->reviewRepository = $reviewRepository;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -66,9 +85,21 @@ final class ProductContext implements Context
|
|||
}
|
||||
|
||||
/**
|
||||
* @When I should be notified that this variant is in use and cannot be deleted
|
||||
* @When /^I try to delete the ("([^"]+)" product)$/
|
||||
*/
|
||||
public function iShouldBeNotifiedThatThisVariantIsInUseAndCannotBeDeleted()
|
||||
public function iTryToDeleteTheProduct(ProductInterface $product)
|
||||
{
|
||||
try {
|
||||
$this->productRepository->remove($product);
|
||||
} catch (DBALException $exception) {
|
||||
$this->sharedStorage->set('last_exception', $exception);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @When /^I should be notified that this (?:variant|product) is in use and cannot be deleted$/
|
||||
*/
|
||||
public function iShouldBeNotifiedThatThisProductVariantIsInUseAndCannotBeDeleted()
|
||||
{
|
||||
expect($this->sharedStorage->get('last_exception'))->toHaveType(DBALException::class);
|
||||
}
|
||||
|
|
@ -85,7 +116,7 @@ final class ProductContext implements Context
|
|||
}
|
||||
|
||||
/**
|
||||
* @Then /^([^"]+) should still exist in the product catalog$/
|
||||
* @Then /^(this variant) should still exist in the product catalog$/
|
||||
*/
|
||||
public function productVariantShouldExistInTheProductCatalog(ProductVariantInterface $productVariant)
|
||||
{
|
||||
|
|
@ -93,4 +124,43 @@ final class ProductContext implements Context
|
|||
|
||||
expect($productVariant)->toNotBe(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then /^(this product) should still exist in the product catalog$/
|
||||
*/
|
||||
public function productShouldExistInTheProductCatalog(ProductInterface $product)
|
||||
{
|
||||
$product = $this->productRepository->find($product->getId());
|
||||
|
||||
expect($product)->toNotBe(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When /^I delete the ("[^"]+" product)$/
|
||||
*/
|
||||
public function iDeleteTheProduct(ProductInterface $product)
|
||||
{
|
||||
try {
|
||||
$this->sharedStorage->set('deleted_product', $product);
|
||||
$this->productRepository->remove($product);
|
||||
} catch (DBALException $exception) {
|
||||
$this->sharedStorage->set('last_exception', $exception);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then /^there should be no reviews of (this product)$/
|
||||
*/
|
||||
public function thereAreNoProductReviews(ProductInterface $product)
|
||||
{
|
||||
expect($this->reviewRepository->findBy(['reviewSubject' => $product]))->toBe([]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then /^there should be no variants of (this product) in the product catalog$/
|
||||
*/
|
||||
public function thereAreNoVariants(ProductInterface $product)
|
||||
{
|
||||
expect($this->productVariantRepository->findBy(['object' => $product]))->toBe([]);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ use Sylius\Component\Taxation\Model\TaxCategoryInterface;
|
|||
/**
|
||||
* @author Arkadiusz Krakowiak <arkadiusz.krakowiak@lakion.com>
|
||||
* @author Mateusz Zalewski <mateusz.zalewski@lakion.com>
|
||||
* @author Magdalena Banasiak <magdalena.banasiak@lakion.com>
|
||||
*/
|
||||
final class ProductContext implements Context
|
||||
{
|
||||
|
|
@ -80,7 +81,9 @@ final class ProductContext implements Context
|
|||
*/
|
||||
public function storeHasAProductPricedAt($productName, $price = 0)
|
||||
{
|
||||
/** @var ProductInterface $product */
|
||||
$product = $this->productFactory->createNew();
|
||||
|
||||
$product->setName($productName);
|
||||
$product->setPrice($price);
|
||||
$product->setDescription('Awesome '.$productName);
|
||||
|
|
@ -93,6 +96,25 @@ final class ProductContext implements Context
|
|||
$this->sharedStorage->set('product', $product);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Given /^the (product "[^"]+") has "([^"]+)" variant priced at ("[^"]+")$/
|
||||
* @Given /^(this product) has "([^"]+)" variant priced at ("[^"]+")$/
|
||||
*/
|
||||
public function theProductHasVariantPricedAt(ProductInterface $product, $productVariantName, $price)
|
||||
{
|
||||
/** @var ProductVariantInterface $variant */
|
||||
$variant = $this->productVariantFactory->createNew();
|
||||
|
||||
$variant->setPresentation($productVariantName);
|
||||
$variant->setPrice($price);
|
||||
$variant->setProduct($product);
|
||||
$product->addVariant($variant);
|
||||
|
||||
$this->objectManager->flush();
|
||||
|
||||
$this->sharedStorage->set('variant', $variant);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Given /^there is product "([^"]+)" available in ((?:this|that|"[^"]+") channel)$/
|
||||
*/
|
||||
|
|
@ -100,6 +122,7 @@ final class ProductContext implements Context
|
|||
{
|
||||
/** @var ProductInterface $product */
|
||||
$product = $this->productFactory->createNew();
|
||||
|
||||
$product->setName($productName);
|
||||
$product->setPrice(0);
|
||||
$product->setDescription('Awesome ' . $productName);
|
||||
|
|
@ -123,7 +146,9 @@ final class ProductContext implements Context
|
|||
public function itComesInTheFollowingVariations(ProductInterface $product, TableNode $table)
|
||||
{
|
||||
foreach ($table->getHash() as $variantHash) {
|
||||
/** @var ProductVariantInterface $variant */
|
||||
$variant = $this->productVariantFactory->createNew();
|
||||
|
||||
$variant->setPresentation($variantHash['name']);
|
||||
$variant->setPrice($this->getPriceFromString(str_replace(['$', '€', '£'], '', $variantHash['price'])));
|
||||
$variant->setProduct($product);
|
||||
|
|
@ -142,23 +167,6 @@ final class ProductContext implements Context
|
|||
$this->objectManager->flush($productVariant);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Given /^the (product "[^"]+") has "([^"]+)" variant priced at ("[^"]+")$/
|
||||
*/
|
||||
public function theProductHasVariantPricedAt(ProductInterface $product, $productVariantName, $price)
|
||||
{
|
||||
$variant = $this->productVariantFactory->createNew();
|
||||
|
||||
$variant->setPresentation($productVariantName);
|
||||
$variant->setPrice($price);
|
||||
$variant->setProduct($product);
|
||||
$product->addVariant($variant);
|
||||
|
||||
$this->objectManager->flush();
|
||||
|
||||
$this->sharedStorage->set('variant', $variant);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $price
|
||||
*
|
||||
|
|
|
|||
70
src/Sylius/Behat/Context/Setup/ProductReviewContext.php
Normal file
70
src/Sylius/Behat/Context/Setup/ProductReviewContext.php
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Sylius package.
|
||||
*
|
||||
* (c) Paweł Jędrzejewski
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Sylius\Behat\Context\Setup;
|
||||
|
||||
use Behat\Behat\Context\Context;
|
||||
use Doctrine\Common\Persistence\ObjectManager;
|
||||
use Sylius\Component\Core\Model\ProductInterface;
|
||||
use Sylius\Component\Core\Test\Services\SharedStorageInterface;
|
||||
use Sylius\Component\Resource\Factory\FactoryInterface;
|
||||
use Sylius\Component\Resource\Repository\RepositoryInterface;
|
||||
|
||||
/**
|
||||
* @author Magdalena Banasiak <magdalena.banasiak@lakion.com>
|
||||
*/
|
||||
final class ProductReviewContext implements Context
|
||||
{
|
||||
/**
|
||||
* @var SharedStorageInterface
|
||||
*/
|
||||
private $sharedStorage;
|
||||
|
||||
/**
|
||||
* @var FactoryInterface
|
||||
*/
|
||||
private $productReviewFactory;
|
||||
|
||||
/**
|
||||
* @var RepositoryInterface
|
||||
*/
|
||||
private $productReviewRepository;
|
||||
|
||||
/**
|
||||
* @param SharedStorageInterface $sharedStorage
|
||||
* @param FactoryInterface $productReviewFactory
|
||||
* @param RepositoryInterface $productReviewRepository
|
||||
*/
|
||||
public function __construct(
|
||||
SharedStorageInterface $sharedStorage,
|
||||
FactoryInterface $productReviewFactory,
|
||||
RepositoryInterface $productReviewRepository
|
||||
) {
|
||||
$this->sharedStorage = $sharedStorage;
|
||||
$this->productReviewFactory = $productReviewFactory;
|
||||
$this->productReviewRepository = $productReviewRepository;
|
||||
}
|
||||
|
||||
/**
|
||||
* @Given /^(this product) has one review$/
|
||||
*/
|
||||
public function productHasAReview(ProductInterface $product)
|
||||
{
|
||||
$review = $this->productReviewFactory->createNew();
|
||||
$review->setTitle('title');
|
||||
$review->setRating(5);
|
||||
$review->setReviewSubject($product);
|
||||
|
||||
$product->addReview($review);
|
||||
|
||||
$this->productReviewRepository->add($review);
|
||||
}
|
||||
}
|
||||
|
|
@ -12,25 +12,56 @@
|
|||
namespace Sylius\Behat\Context\Ui;
|
||||
|
||||
use Behat\Behat\Context\Context;
|
||||
use Sylius\Behat\Page\Admin\Product\IndexPageInterface;
|
||||
use Sylius\Behat\Page\Admin\Product\ShowPageInterface;
|
||||
use Sylius\Behat\Page\Product\ProductShowPage;
|
||||
use Sylius\Behat\Page\Admin\Product\ShowPage as AdminProductShowPage;
|
||||
use Sylius\Behat\Page\Product\ProductShowPageInterface;
|
||||
use Sylius\Component\Core\Model\ProductInterface;
|
||||
use Sylius\Component\Core\Test\Services\SharedStorageInterface;
|
||||
|
||||
/**
|
||||
* @author Kamil Kokot <kamil.kokot@lakion.com>
|
||||
* @author Magdalena Banasiak <magdalena.banasiak@lakion.com>
|
||||
*/
|
||||
final class ProductContext implements Context
|
||||
{
|
||||
/**
|
||||
* @var ProductShowPageInterface
|
||||
* @var SharedStorageInterface
|
||||
*/
|
||||
private $sharedStorage;
|
||||
|
||||
/**
|
||||
* @var ProductShowPage
|
||||
*/
|
||||
private $productShowPage;
|
||||
|
||||
/**
|
||||
* @param ProductShowPageInterface $productShowPage
|
||||
* @var AdminProductShowPage
|
||||
*/
|
||||
public function __construct(ProductShowPageInterface $productShowPage)
|
||||
{
|
||||
private $adminProductShowPage;
|
||||
|
||||
/**
|
||||
* @var IndexPageInterface
|
||||
*/
|
||||
private $adminProductIndexPage;
|
||||
|
||||
/**
|
||||
* @param SharedStorageInterface $sharedStorage
|
||||
* @param ProductShowPageInterface $productShowPage
|
||||
* @param ShowPageInterface $adminProductShowPage
|
||||
* @param IndexPageInterface $adminProductIndexPage
|
||||
*/
|
||||
public function __construct(
|
||||
SharedStorageInterface $sharedStorage,
|
||||
ProductShowPageInterface $productShowPage,
|
||||
ShowPageInterface $adminProductShowPage,
|
||||
IndexPageInterface $adminProductIndexPage
|
||||
) {
|
||||
$this->sharedStorage = $sharedStorage;
|
||||
$this->productShowPage = $productShowPage;
|
||||
$this->adminProductShowPage = $adminProductShowPage;
|
||||
$this->adminProductIndexPage = $adminProductIndexPage;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -52,4 +83,26 @@ final class ProductContext implements Context
|
|||
|
||||
expect($this->productShowPage->isOpen(['product' => $product]))->toBe(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When I delete the :product product
|
||||
*/
|
||||
public function iDeleteProduct(ProductInterface $product)
|
||||
{
|
||||
$this->adminProductShowPage->open(['id' => $product->getId()]);
|
||||
|
||||
$this->adminProductShowPage->deleteProduct();
|
||||
|
||||
$this->sharedStorage->set('product', $product);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then /^(this product) should not exist in the product catalog$/
|
||||
*/
|
||||
public function productShouldNotExist(ProductInterface $product)
|
||||
{
|
||||
$this->adminProductIndexPage->open();
|
||||
|
||||
expect($this->adminProductIndexPage->isThereProduct($product))->toBe(false);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
67
src/Sylius/Behat/Page/Admin/Product/IndexPage.php
Normal file
67
src/Sylius/Behat/Page/Admin/Product/IndexPage.php
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Sylius package.
|
||||
*
|
||||
* (c) Paweł Jędrzejewski
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Sylius\Behat\Page\Admin\Product;
|
||||
|
||||
use Behat\Mink\Session;
|
||||
use Sylius\Behat\Page\SymfonyPage;
|
||||
use Sylius\Behat\TableManipulatorInterface;
|
||||
use Sylius\Component\Core\Model\ProductInterface;
|
||||
use Symfony\Component\Routing\RouterInterface;
|
||||
|
||||
/**
|
||||
* @author Magdalena Banasiak <magdalena.banasiak@lakion.com>
|
||||
*/
|
||||
class IndexPage extends SymfonyPage implements IndexPageInterface
|
||||
{
|
||||
/**
|
||||
* @var TableManipulatorInterface
|
||||
*/
|
||||
private $tableManipulator;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @param TableManipulatorInterface $tableManipulator
|
||||
*/
|
||||
public function __construct(
|
||||
Session $session,
|
||||
array $parameters,
|
||||
RouterInterface $router,
|
||||
TableManipulatorInterface $tableManipulator
|
||||
) {
|
||||
parent::__construct($session, $parameters, $router);
|
||||
|
||||
$this->tableManipulator = $tableManipulator;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isThereProduct(ProductInterface $product)
|
||||
{
|
||||
if (!$table = $this->getDocument()->find('css', 'table')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$row = $this->tableManipulator->getRowWithFields($table, ['id' => $product->getId()]);
|
||||
|
||||
return null === $row;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getRouteName()
|
||||
{
|
||||
return 'sylius_backend_product_index';
|
||||
}
|
||||
}
|
||||
28
src/Sylius/Behat/Page/Admin/Product/IndexPageInterface.php
Normal file
28
src/Sylius/Behat/Page/Admin/Product/IndexPageInterface.php
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Sylius package.
|
||||
*
|
||||
* (c) Paweł Jędrzejewski
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Sylius\Behat\Page\Admin\Product;
|
||||
|
||||
use Sylius\Behat\Page\PageInterface;
|
||||
use Sylius\Component\Core\Model\ProductInterface;
|
||||
|
||||
/**
|
||||
* @author Magdalena Banasiak <magdalena.banasiak@lakion.com>
|
||||
*/
|
||||
interface IndexPageInterface extends PageInterface
|
||||
{
|
||||
/**
|
||||
* @param ProductInterface $product
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isThereProduct(ProductInterface $product);
|
||||
}
|
||||
40
src/Sylius/Behat/Page/Admin/Product/ShowPage.php
Normal file
40
src/Sylius/Behat/Page/Admin/Product/ShowPage.php
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Sylius package.
|
||||
*
|
||||
* (c) Paweł Jędrzejewski
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Sylius\Behat\Page\Admin\Product;
|
||||
|
||||
use Sylius\Behat\Page\SymfonyPage;
|
||||
|
||||
/**
|
||||
* @author Magdalena Banasiak <magdalena.banasiak@lakion.com>
|
||||
*/
|
||||
class ShowPage extends SymfonyPage implements ShowPageInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function deleteProduct()
|
||||
{
|
||||
$this->getDocument()->pressButton('Delete');
|
||||
|
||||
$confirmationModal = $this->getDocument()->find('css', '#confirmation-modal-confirm');
|
||||
$this->waitForModalToAppear($confirmationModal);
|
||||
$confirmationModal->find('css', 'a:contains("Delete")')->press();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getRouteName()
|
||||
{
|
||||
return 'sylius_backend_product_show';
|
||||
}
|
||||
}
|
||||
26
src/Sylius/Behat/Page/Admin/Product/ShowPageInterface.php
Normal file
26
src/Sylius/Behat/Page/Admin/Product/ShowPageInterface.php
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Sylius package.
|
||||
*
|
||||
* (c) Paweł Jędrzejewski
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Sylius\Behat\Page\Admin\Product;
|
||||
|
||||
use Sylius\Behat\Page\ElementNotFoundException;
|
||||
use Sylius\Behat\Page\PageInterface;
|
||||
|
||||
/**
|
||||
* @author Magdalena Banasiak <magdalena.banasiak@lakion.com>
|
||||
*/
|
||||
interface ShowPageInterface extends PageInterface
|
||||
{
|
||||
/**
|
||||
* @throws ElementNotFoundException
|
||||
*/
|
||||
public function deleteProduct();
|
||||
}
|
||||
|
|
@ -18,20 +18,29 @@ use PhpSpec\Exception\Example\NotEqualException;
|
|||
use PhpSpec\ObjectBehavior;
|
||||
use Prophecy\Argument;
|
||||
use Sylius\Behat\Context\Domain\ProductContext;
|
||||
use Sylius\Component\Core\Model\ProductInterface;
|
||||
use Sylius\Component\Core\Model\ProductVariantInterface;
|
||||
use Sylius\Component\Core\Repository\ProductVariantRepositoryInterface;
|
||||
use Sylius\Component\Core\Test\Services\SharedStorageInterface;
|
||||
use Sylius\Component\Product\Model\VariantInterface;
|
||||
use Sylius\Component\Resource\Repository\RepositoryInterface;
|
||||
use Sylius\Component\Review\Model\ReviewInterface;
|
||||
|
||||
/**
|
||||
* @mixin ProductContext
|
||||
*
|
||||
* @author Łukasz Chruściel <lukasz.chrusciel@lakion.com>
|
||||
* @author Magdalena Banasiak <magdalena.banasiak@lakion.com>
|
||||
*/
|
||||
class ProductContextSpec extends ObjectBehavior
|
||||
{
|
||||
function let(SharedStorageInterface $sharedStorage, ProductVariantRepositoryInterface $productVariantRepository)
|
||||
{
|
||||
$this->beConstructedWith($sharedStorage, $productVariantRepository);
|
||||
function let(
|
||||
SharedStorageInterface $sharedStorage,
|
||||
RepositoryInterface $productRepository,
|
||||
ProductVariantRepositoryInterface $productVariantRepository,
|
||||
RepositoryInterface $reviewRepository
|
||||
) {
|
||||
$this->beConstructedWith($sharedStorage, $productRepository, $productVariantRepository, $reviewRepository);
|
||||
}
|
||||
|
||||
function it_is_initializable()
|
||||
|
|
@ -53,7 +62,7 @@ class ProductContextSpec extends ObjectBehavior
|
|||
$this->iDeleteTheVariantOfProduct($productVariant);
|
||||
}
|
||||
|
||||
function it_tries_to_delete_a_product_variant_that_should_not_be_delted_from_the_repository(
|
||||
function it_tries_to_delete_a_product_variant_that_should_not_be_deleted_from_the_repository(
|
||||
SharedStorageInterface $sharedStorage,
|
||||
ProductVariantRepositoryInterface $productVariantRepository,
|
||||
ProductVariantInterface $productVariant
|
||||
|
|
@ -66,8 +75,10 @@ class ProductContextSpec extends ObjectBehavior
|
|||
|
||||
function it_checks_if_a_product_variant_exists_in_the_repository(
|
||||
SharedStorageInterface $sharedStorage,
|
||||
ProductVariantRepositoryInterface $productVariantRepository
|
||||
ProductVariantRepositoryInterface $productVariantRepository,
|
||||
ProductVariantInterface $productVariant
|
||||
) {
|
||||
$productVariant->getId()->willReturn(1);
|
||||
$sharedStorage->get('product_variant_id')->willReturn(1);
|
||||
$productVariantRepository->find(1)->willReturn(null);
|
||||
|
||||
|
|
@ -79,19 +90,20 @@ class ProductContextSpec extends ObjectBehavior
|
|||
ProductVariantRepositoryInterface $productVariantRepository,
|
||||
ProductVariantInterface $productVariant
|
||||
) {
|
||||
$productVariant->getId()->willReturn(1);
|
||||
$sharedStorage->get('product_variant_id')->willReturn(1);
|
||||
$productVariantRepository->find(1)->willReturn($productVariant);
|
||||
|
||||
$this->shouldThrow(NotEqualException::class)->during('productVariantShouldNotExistInTheProductCatalog', [$productVariant]);
|
||||
$this->shouldThrow(NotEqualException::class)->during('productVariantShouldNotExistInTheProductCatalog');
|
||||
}
|
||||
|
||||
function it_checks_if_a_proper_exception_has_been_thrown_in_the_previous_step(
|
||||
function it_checks_if_a_proper_exception_was_thrown_in_the_previous_step_of_variant_deletion(
|
||||
SharedStorageInterface $sharedStorage,
|
||||
DBALException $exception
|
||||
) {
|
||||
$sharedStorage->get('last_exception')->willReturn($exception);
|
||||
|
||||
$this->iShouldBeNotifiedThatThisVariantIsInUseAndCannotBeDeleted();
|
||||
$this->iShouldBeNotifiedThatThisProductVariantIsInUseAndCannotBeDeleted();
|
||||
}
|
||||
|
||||
function it_throws_an_exception_if_a_wrong_exception_was_passed(
|
||||
|
|
@ -100,18 +112,17 @@ class ProductContextSpec extends ObjectBehavior
|
|||
) {
|
||||
$sharedStorage->get('last_exception')->willReturn($exception);
|
||||
|
||||
$this->shouldThrow(FailureException::class)->during('iShouldBeNotifiedThatThisVariantIsInUseAndCannotBeDeleted', []);
|
||||
$this->shouldThrow(FailureException::class)->during('iShouldBeNotifiedThatThisProductVariantIsInUseAndCannotBeDeleted');
|
||||
}
|
||||
|
||||
function it_throws_an_exception_if_no_exception_was_passed(
|
||||
SharedStorageInterface $sharedStorage
|
||||
) {
|
||||
function it_throws_an_exception_if_no_exception_was_passed(SharedStorageInterface $sharedStorage)
|
||||
{
|
||||
$sharedStorage->get('last_exception')->willThrow(\InvalidArgumentException::class);
|
||||
|
||||
$this->shouldThrow(\InvalidArgumentException::class)->during('iShouldBeNotifiedThatThisVariantIsInUseAndCannotBeDeleted', []);
|
||||
$this->shouldThrow(\InvalidArgumentException::class)->during('iShouldBeNotifiedThatThisProductVariantIsInUseAndCannotBeDeleted');
|
||||
}
|
||||
|
||||
function it_checks_if_product_variant_still_exist_in_a_reposiotry(
|
||||
function it_checks_if_product_variant_still_exist_in_a_repository(
|
||||
ProductVariantRepositoryInterface $productVariantRepository,
|
||||
ProductVariantInterface $productVariant
|
||||
) {
|
||||
|
|
@ -130,4 +141,80 @@ class ProductContextSpec extends ObjectBehavior
|
|||
|
||||
$this->shouldThrow(FailureException::class)->during('productVariantShouldExistInTheProductCatalog', [$productVariant]);
|
||||
}
|
||||
|
||||
function it_deletes_a_product(
|
||||
SharedStorageInterface $sharedStorage,
|
||||
RepositoryInterface $productRepository,
|
||||
ProductInterface $product
|
||||
) {
|
||||
$product->getId()->willReturn(1);
|
||||
$productRepository->find(1)->willReturn($product);
|
||||
|
||||
$sharedStorage->set('deleted_product', $product)->shouldBeCalled();
|
||||
$productRepository->remove($product)->shouldBeCalled();
|
||||
|
||||
$this->iDeleteTheProduct($product);
|
||||
}
|
||||
|
||||
function it_tries_to_delete_a_product_that_does_not_exist(
|
||||
SharedStorageInterface $sharedStorage,
|
||||
RepositoryInterface $productRepository,
|
||||
ProductInterface $product
|
||||
) {
|
||||
$product->getId()->willReturn(1);
|
||||
$productRepository->find(1)->willReturn(null);
|
||||
|
||||
$sharedStorage->set('deleted_product', $product)->shouldBeCalled();
|
||||
$productRepository->remove($product)->willThrow(DBALException::class);
|
||||
|
||||
$sharedStorage->set('last_exception', Argument::type(DBALException::class))->shouldBeCalled();
|
||||
|
||||
$this->iDeleteTheProduct($product);
|
||||
}
|
||||
|
||||
function it_checks_if_there_are_no_reviews(
|
||||
SharedStorageInterface $sharedStorage,
|
||||
RepositoryInterface $reviewRepository,
|
||||
ProductInterface $product
|
||||
) {
|
||||
$sharedStorage->get('deleted_product')->willReturn($product);
|
||||
$reviewRepository->findBy(['reviewSubject' => $product])->willReturn([]);
|
||||
|
||||
$this->thereAreNoProductReviews($product);
|
||||
}
|
||||
|
||||
function it_throws_an_exception_if_reviews_of_the_product_still_exist(
|
||||
SharedStorageInterface $sharedStorage,
|
||||
RepositoryInterface $reviewRepository,
|
||||
ProductInterface $product,
|
||||
ReviewInterface $review
|
||||
) {
|
||||
$sharedStorage->get('deleted_product')->willReturn($product);
|
||||
$reviewRepository->findBy(['reviewSubject' => $product])->willReturn([$review]);
|
||||
|
||||
$this->shouldThrow(FailureException::class)->during('thereAreNoProductReviews', [$product]);
|
||||
}
|
||||
|
||||
function it_checks_if_there_are_no_variants(
|
||||
SharedStorageInterface $sharedStorage,
|
||||
ProductVariantRepositoryInterface $productVariantRepository,
|
||||
ProductInterface $product
|
||||
) {
|
||||
$sharedStorage->get('deleted_product')->willReturn($product);
|
||||
$productVariantRepository->findBy(['object' => $product])->willReturn([]);
|
||||
|
||||
$this->thereAreNoVariants($product);
|
||||
}
|
||||
|
||||
function it_throws_an_exception_if_variants_of_the_product_still_exist(
|
||||
SharedStorageInterface $sharedStorage,
|
||||
ProductVariantRepositoryInterface $productVariantRepository,
|
||||
ProductInterface $product,
|
||||
VariantInterface $variant
|
||||
) {
|
||||
$sharedStorage->get('deleted_product')->willReturn($product);
|
||||
$productVariantRepository->findBy(['object' => $product])->willReturn([$variant]);
|
||||
|
||||
$this->shouldThrow(FailureException::class)->during('thereAreNoVariants', [$product]);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ use Sylius\Component\Core\Repository\ProductRepositoryInterface;
|
|||
use Sylius\Component\Core\Test\Services\SharedStorageInterface;
|
||||
use Sylius\Component\Core\Model\ProductInterface;
|
||||
use Sylius\Component\Resource\Factory\FactoryInterface;
|
||||
use Sylius\Component\Resource\Repository\RepositoryInterface;
|
||||
|
||||
/**
|
||||
* @mixin ProductContext
|
||||
|
|
|
|||
|
|
@ -0,0 +1,67 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Sylius package.
|
||||
*
|
||||
* (c) Paweł Jędrzejewski
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace spec\Sylius\Behat\Context\Setup;
|
||||
|
||||
use Behat\Behat\Context\Context;
|
||||
use Doctrine\Common\Persistence\ObjectManager;
|
||||
use PhpSpec\ObjectBehavior;
|
||||
use Sylius\Component\Core\Model\ProductInterface;
|
||||
use Sylius\Component\Core\Test\Services\SharedStorageInterface;
|
||||
use Sylius\Component\Resource\Factory\FactoryInterface;
|
||||
use Sylius\Component\Resource\Repository\RepositoryInterface;
|
||||
use Sylius\Component\Review\Model\ReviewerInterface;
|
||||
use Sylius\Component\Review\Model\ReviewInterface;
|
||||
|
||||
/**
|
||||
* @author Magdalena Banasiak <magdalena.banasiak@lakion.com>
|
||||
*/
|
||||
class ProductReviewContextSpec extends ObjectBehavior
|
||||
{
|
||||
function let(
|
||||
SharedStorageInterface $sharedStorage,
|
||||
FactoryInterface $reviewFactory,
|
||||
RepositoryInterface $reviewRepository
|
||||
) {
|
||||
$this->beConstructedWith($sharedStorage, $reviewFactory, $reviewRepository);
|
||||
}
|
||||
|
||||
function it_is_initializable()
|
||||
{
|
||||
$this->shouldHaveType('Sylius\Behat\Context\Setup\ProductReviewContext');
|
||||
}
|
||||
|
||||
function it_implements_context_interface()
|
||||
{
|
||||
$this->shouldImplement(Context::class);
|
||||
}
|
||||
|
||||
function it_creates_a_review_for_a_given_product(
|
||||
SharedStorageInterface $sharedStorage,
|
||||
FactoryInterface $reviewFactory,
|
||||
RepositoryInterface $productReviewRepository,
|
||||
ProductInterface $product,
|
||||
ReviewInterface $review
|
||||
) {
|
||||
$sharedStorage->get('product')->willReturn($product);
|
||||
|
||||
$reviewFactory->createNew()->willReturn($review);
|
||||
$review->setTitle('title')->shouldBeCalled();
|
||||
$review->setRating(5)->shouldBeCalled();
|
||||
$review->setReviewSubject($product)->shouldBeCalled();
|
||||
|
||||
$product->addReview($review)->shouldBeCalled();
|
||||
|
||||
$productReviewRepository->add($review);
|
||||
|
||||
$this->productHasAReview($product);
|
||||
}
|
||||
}
|
||||
130
src/Sylius/Behat/spec/Context/Ui/ProductContextSpec.php
Normal file
130
src/Sylius/Behat/spec/Context/Ui/ProductContextSpec.php
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Sylius package.
|
||||
*
|
||||
* (c) Paweł Jędrzejewski
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace spec\Sylius\Behat\Context\Ui;
|
||||
|
||||
use Behat\Behat\Context\Context;
|
||||
use PhpSpec\Exception\Example\NotEqualException;
|
||||
use PhpSpec\ObjectBehavior;
|
||||
use Sylius\Behat\Context\Ui\ProductContext;
|
||||
use Sylius\Behat\Page\Admin\Product\IndexPageInterface;
|
||||
use Sylius\Behat\Page\Admin\Product\ShowPageInterface;
|
||||
use Sylius\Behat\Page\Product\ProductShowPage;
|
||||
use Sylius\Behat\Page\Admin\Product\ShowPage as AdminProductShowPage;
|
||||
use Sylius\Behat\Page\Product\ProductShowPageInterface;
|
||||
use Sylius\Component\Core\Model\ProductInterface;
|
||||
use Sylius\Component\Core\Test\Services\SharedStorage;
|
||||
use Sylius\Component\Core\Test\Services\SharedStorageInterface;
|
||||
|
||||
/**
|
||||
* @mixin ProductContext
|
||||
*
|
||||
* @author Magdalena Banasiak <magdalena.banasiak@lakion.com>
|
||||
*/
|
||||
class ProductContextSpec extends ObjectBehavior
|
||||
{
|
||||
public function let(
|
||||
SharedStorageInterface $sharedStorage,
|
||||
ProductShowPageInterface $productShowPage,
|
||||
ShowPageInterface $adminProductShowPage,
|
||||
IndexPageInterface $adminProductIndexPage
|
||||
) {
|
||||
$this->beConstructedWith($sharedStorage, $productShowPage, $adminProductShowPage, $adminProductIndexPage);
|
||||
}
|
||||
|
||||
function it_is_initializable()
|
||||
{
|
||||
$this->shouldHaveType('Sylius\Behat\Context\Ui\ProductContext');
|
||||
}
|
||||
|
||||
function it_implements_context_interface()
|
||||
{
|
||||
$this->shouldImplement(Context::class);
|
||||
}
|
||||
|
||||
function it_checks_if_i_am_able_to_access_product_page(ProductShowPageInterface $productShowPage, ProductInterface $product)
|
||||
{
|
||||
$productShowPage->tryToOpen(['product' => $product])->shouldBeCalled();
|
||||
$productShowPage->isOpen(['product' => $product])->willReturn(true);
|
||||
|
||||
$this->iShouldBeAbleToAccessProduct($product);
|
||||
}
|
||||
|
||||
function it_throws_an_exception_if_i_am_not_able_to_access_product_page_when_i_should(
|
||||
ProductShowPageInterface $productShowPage,
|
||||
ProductInterface $product
|
||||
) {
|
||||
$productShowPage->tryToOpen(['product' => $product])->shouldBeCalled();
|
||||
$productShowPage->isOpen(['product' => $product])->willReturn(false);
|
||||
|
||||
$this->shouldThrow(NotEqualException::class)->during('iShouldBeAbleToAccessProduct',[$product]);
|
||||
}
|
||||
|
||||
function it_checks_if_i_am_not_able_to_access_product_page(ProductShowPageInterface $productShowPage, ProductInterface $product)
|
||||
{
|
||||
$productShowPage->tryToOpen(['product' => $product])->shouldBeCalled();
|
||||
$productShowPage->isOpen(['product' => $product])->willReturn(false);
|
||||
|
||||
$this->iShouldNotBeAbleToAccessProduct($product);
|
||||
}
|
||||
|
||||
function it_throws_an_exception_if_i_am_able_to_access_product_page_when_i_should_not(
|
||||
ProductShowPageInterface $productShowPage,
|
||||
ProductInterface $product
|
||||
) {
|
||||
$productShowPage->tryToOpen(['product' => $product])->shouldBeCalled();
|
||||
$productShowPage->isOpen(['product' => $product])->willReturn(true);
|
||||
|
||||
$this->shouldThrow(NotEqualException::class)->during('iShouldNotBeAbleToAccessProduct',[$product]);
|
||||
}
|
||||
|
||||
function it_deletes_a_product(
|
||||
ShowPageInterface $adminProductShowPage,
|
||||
SharedStorageInterface $sharedStorage,
|
||||
ProductInterface $product
|
||||
) {
|
||||
$sharedStorage->set('product', $product)->shouldBeCalled();
|
||||
|
||||
$product->getName()->willReturn('Model');
|
||||
$product->getId()->willReturn(1);
|
||||
|
||||
$adminProductShowPage->open(['id' => 1])->shouldBeCalled();
|
||||
$adminProductShowPage->deleteProduct()->shouldBeCalled();
|
||||
|
||||
$this->iDeleteProduct($product);
|
||||
}
|
||||
|
||||
function it_checks_if_a_product_does_not_exist(
|
||||
SharedStorageInterface $sharedStorage,
|
||||
IndexPageInterface $adminProductIndexPage,
|
||||
ProductInterface $product
|
||||
) {
|
||||
$sharedStorage->get('product')->willReturn($product);
|
||||
|
||||
$adminProductIndexPage->open()->shouldBeCalled();
|
||||
$adminProductIndexPage->isThereProduct($product)->willReturn(false);
|
||||
|
||||
$this->productShouldNotExist($product);
|
||||
}
|
||||
|
||||
function it_throws_an_exception_if_a_product_exists_when_it_should_not(
|
||||
SharedStorageInterface $sharedStorage,
|
||||
IndexPageInterface $adminProductIndexPage,
|
||||
ProductInterface $product
|
||||
) {
|
||||
$sharedStorage->get('product')->willReturn($product);
|
||||
|
||||
$adminProductIndexPage->open()->shouldBeCalled();
|
||||
$adminProductIndexPage->isThereProduct($product)->willReturn(true);
|
||||
|
||||
$this->shouldThrow(NotEqualException::class)->during('productShouldNotExist', [$product]);
|
||||
}
|
||||
}
|
||||
46
src/Sylius/Behat/spec/Page/Admin/Product/IndexPageSpec.php
Normal file
46
src/Sylius/Behat/spec/Page/Admin/Product/IndexPageSpec.php
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Sylius package.
|
||||
*
|
||||
* (c) Paweł Jędrzejewski
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace spec\Sylius\Behat\Page\Admin\Product;
|
||||
|
||||
use Behat\Mink\Session;
|
||||
use PhpSpec\ObjectBehavior;
|
||||
use Sylius\Behat\Page\Admin\Product\IndexPageInterface;
|
||||
use Sylius\Behat\Page\Admin\Product\ProductShowPageInterface;
|
||||
use Sylius\Behat\Page\SymfonyPage;
|
||||
use Sylius\Behat\TableManipulatorInterface;
|
||||
use Symfony\Component\Routing\RouterInterface;
|
||||
|
||||
/**
|
||||
* @author Magdalena Banasiak <magdalena.banasiak@lakion.com>
|
||||
*/
|
||||
class IndexPageSpec extends ObjectBehavior
|
||||
{
|
||||
function let(Session $session, RouterInterface $router, TableManipulatorInterface $tableManipulator)
|
||||
{
|
||||
$this->beConstructedWith($session, [], $router, $tableManipulator);
|
||||
}
|
||||
|
||||
function it_is_initializable()
|
||||
{
|
||||
$this->shouldHaveType('Sylius\Behat\Page\Admin\Product\IndexPage');
|
||||
}
|
||||
|
||||
function it_is_symfony_page()
|
||||
{
|
||||
$this->shouldHaveType(SymfonyPage::class);
|
||||
}
|
||||
|
||||
function it_implements_product_index_page_interface()
|
||||
{
|
||||
$this->shouldImplement(IndexPageInterface::class);
|
||||
}
|
||||
}
|
||||
44
src/Sylius/Behat/spec/Page/Admin/Product/ShowPageSpec.php
Normal file
44
src/Sylius/Behat/spec/Page/Admin/Product/ShowPageSpec.php
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Sylius package.
|
||||
*
|
||||
* (c) Paweł Jędrzejewski
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace spec\Sylius\Behat\Page\Admin\Product;
|
||||
|
||||
use Behat\Mink\Session;
|
||||
use PhpSpec\ObjectBehavior;
|
||||
use Sylius\Behat\Page\Admin\Product\ShowPageInterface;
|
||||
use Sylius\Behat\Page\SymfonyPage;
|
||||
use Symfony\Component\Routing\RouterInterface;
|
||||
|
||||
/**
|
||||
* @author Magdalena Banasiak <magdalena.banasiak@lakion.com>
|
||||
*/
|
||||
class ShowPageSpec extends ObjectBehavior
|
||||
{
|
||||
function let(Session $session, RouterInterface $router)
|
||||
{
|
||||
$this->beConstructedWith($session, [], $router);
|
||||
}
|
||||
|
||||
function it_is_initializable()
|
||||
{
|
||||
$this->shouldHaveType('Sylius\Behat\Page\Admin\Product\ShowPage');
|
||||
}
|
||||
|
||||
function it_is_symfony_page()
|
||||
{
|
||||
$this->shouldHaveType(SymfonyPage::class);
|
||||
}
|
||||
|
||||
function it_implements_product_show_page_interface()
|
||||
{
|
||||
$this->shouldImplement(ShowPageInterface::class);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Sylius package.
|
||||
*
|
||||
* (c) Paweł Jędrzejewski
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Sylius\Bundle\CoreBundle\EventListener;
|
||||
|
||||
use Doctrine\ORM\Event\LifecycleEventArgs;
|
||||
use Sylius\Component\Core\Model\ProductInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* @author Mateusz Zalewski <mateusz.zalewski@lakion.com>
|
||||
* @author Grzegorz Sadowski <grzegorz.sadowski@lakion.com>
|
||||
*/
|
||||
class ProductDeleteListener
|
||||
{
|
||||
/**
|
||||
* @var ContainerInterface
|
||||
*/
|
||||
protected $container;
|
||||
|
||||
/**
|
||||
* @param ContainerInterface $container
|
||||
*/
|
||||
public function __construct(ContainerInterface $container)
|
||||
{
|
||||
$this->container = $container;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param LifecycleEventArgs $args
|
||||
*/
|
||||
public function postSoftDelete(LifecycleEventArgs $args)
|
||||
{
|
||||
if (!($product = $args->getEntity()) instanceof ProductInterface) {
|
||||
return;
|
||||
}
|
||||
|
||||
$reviewManager = $this->container->get('sylius.manager.product_review');
|
||||
$reviewRepository = $this->container->get('sylius.repository.product_review');
|
||||
$reviews = $reviewRepository->findBy(['reviewSubject' => $product]);
|
||||
|
||||
foreach ($reviews as $review) {
|
||||
$reviewManager->remove($review);
|
||||
}
|
||||
|
||||
$product->setAverageRating(0);
|
||||
|
||||
$reviewManager->flush();
|
||||
}
|
||||
}
|
||||
|
|
@ -61,7 +61,6 @@
|
|||
<parameter key="sylius.listener.image_upload.class">Sylius\Bundle\CoreBundle\EventListener\ImageUploadListener</parameter>
|
||||
<parameter key="sylius.listener.channel.class">Sylius\Bundle\CoreBundle\EventListener\ChannelDeletionListener</parameter>
|
||||
<parameter key="sylius.listener.customer_aware.class">Sylius\Bundle\CoreBundle\EventListener\CustomerAwareListener</parameter>
|
||||
<parameter key="sylius.listener.product_delete.class">Sylius\Bundle\CoreBundle\EventListener\ProductDeleteListener</parameter>
|
||||
<parameter key="sylius.listener.customer_reviews_delete.class">Sylius\Bundle\CoreBundle\EventListener\CustomerReviewsDeleteListener</parameter>
|
||||
|
||||
<parameter key="sylius.active_promotions_by_channel_provider.class">Sylius\Component\Core\Provider\ActivePromotionsByChannelProvider</parameter>
|
||||
|
|
@ -400,11 +399,6 @@
|
|||
<tag name="kernel.event_listener" event="sylius.taxon.pre_update" method="uploadTaxonImage" />
|
||||
</service>
|
||||
|
||||
<service id="sylius.listener.product_delete" class="%sylius.listener.product_delete.class%">
|
||||
<argument type="service" id="service_container"/>
|
||||
<tag name="doctrine.event_listener" event="postSoftDelete" method="postSoftDelete" />
|
||||
</service>
|
||||
|
||||
<service id="sylius.image_uploader" class="%sylius.image_uploader.class%">
|
||||
<argument type="service">
|
||||
<service class="Gaufrette\Filesystem" factory-service="knp_gaufrette.filesystem_map" factory-method="get">
|
||||
|
|
|
|||
|
|
@ -1,60 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Sylius package.
|
||||
*
|
||||
* (c) Paweł Jędrzejewski
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace spec\Sylius\Bundle\CoreBundle\EventListener;
|
||||
|
||||
use Doctrine\Common\Persistence\ObjectManager;
|
||||
use Doctrine\ORM\Event\LifecycleEventArgs;
|
||||
use PhpSpec\ObjectBehavior;
|
||||
use Sylius\Bundle\ResourceBundle\Doctrine\ORM\EntityRepository;
|
||||
use Sylius\Component\Core\Model\Product;
|
||||
use Sylius\Component\Review\Model\ReviewInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* @author Mateusz Zalewski <mateusz.zalewski@lakion.com>
|
||||
* @author Grzegorz Sadowski <grzegorz.sadowski@lakion.com>
|
||||
*/
|
||||
class ProductDeleteListenerSpec extends ObjectBehavior
|
||||
{
|
||||
function let(ContainerInterface $container)
|
||||
{
|
||||
$this->beConstructedWith($container);
|
||||
}
|
||||
|
||||
function it_is_initializable()
|
||||
{
|
||||
$this->shouldHaveType('Sylius\Bundle\CoreBundle\EventListener\ProductDeleteListener');
|
||||
}
|
||||
|
||||
function it_removes_soft_deleted_product_reviews(
|
||||
$container,
|
||||
EntityRepository $reviewRepository,
|
||||
ObjectManager $reviewManager,
|
||||
LifecycleEventArgs $args,
|
||||
Product $product,
|
||||
ReviewInterface $review
|
||||
) {
|
||||
$args->getEntity()->willReturn($product)->shouldBeCalled();
|
||||
|
||||
$container->get('sylius.manager.product_review')->willReturn($reviewManager)->shouldBeCalled();
|
||||
$container->get('sylius.repository.product_review')->willReturn($reviewRepository)->shouldBeCalled();
|
||||
|
||||
$reviewRepository->findBy(['reviewSubject' => $product])->willReturn([$review])->shouldBeCalled();
|
||||
|
||||
$reviewManager->remove($review)->shouldBeCalled();
|
||||
$reviewManager->flush()->shouldBeCalled();
|
||||
|
||||
$product->setAverageRating(0)->shouldBeCalled();
|
||||
|
||||
$this->postSoftDelete($args);
|
||||
}
|
||||
}
|
||||
|
|
@ -73,10 +73,8 @@
|
|||
<field name="updatedAt" column="updated_at" type="datetime" nullable="true">
|
||||
<gedmo:timestampable on="update"/>
|
||||
</field>
|
||||
<field name="deletedAt" column="deleted_at" type="datetime" nullable="true" />
|
||||
<field name="enabled" column="enabled" type="boolean" />
|
||||
|
||||
<gedmo:soft-deleteable field-name="deletedAt" />
|
||||
<gedmo:loggable />
|
||||
</mapped-superclass>
|
||||
|
||||
|
|
|
|||
|
|
@ -206,8 +206,8 @@ class OrmIndexer implements IndexerInterface
|
|||
->delete(SearchIndex::class, 'u')
|
||||
->where('u.itemId = :item_id')
|
||||
->andWhere('u.entity = :entity_namespace')
|
||||
->setParameter(':item_id', $entity->getId())
|
||||
->setParameter(':entity_namespace', get_class($entity))
|
||||
->setParameter(':item_id', $entity['id'])
|
||||
->setParameter(':entity_namespace', get_class($entity['entity']))
|
||||
;
|
||||
|
||||
$queryBuilder->getQuery()->getResult();
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ class OrmListener implements EventSubscriber
|
|||
{
|
||||
$entity = $args->getEntity();
|
||||
if ($this->ormIndexer->isObjectIndexable($entity)) {
|
||||
$this->scheduledForDeletion[] = $entity;
|
||||
$this->scheduledForDeletion[] = ['id' => $entity->getId(), 'entity' => $entity];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -76,7 +76,6 @@
|
|||
<a href="{{ path('sylius_backend_product_show', {'id': product.id}) }}">
|
||||
<h4 class="name">
|
||||
{{ product.name }}
|
||||
{% if product.deleted %}<span class="label label-danger">{{ 'sylius.deleted'|trans }}</span>{% endif %}
|
||||
</h4>
|
||||
</a>
|
||||
{% if product.hasOptions %}
|
||||
|
|
|
|||
|
|
@ -88,7 +88,6 @@
|
|||
<a href="{{ path('sylius_backend_product_show', {'id': product.id}) }}">
|
||||
<h4 class="name">
|
||||
{{ product.name }}
|
||||
{% if product.deleted %}<span class="label label-danger">{{ 'sylius.deleted'|trans }}</span>{% endif %}
|
||||
</h4>
|
||||
</a>
|
||||
{% if product.hasOptions %}
|
||||
|
|
|
|||
|
|
@ -17,14 +17,12 @@
|
|||
<div class="page-header">
|
||||
<div class="actions-menu">
|
||||
{{ buttons.manage(path('sylius_backend_product_index'), 'sylius.product.manage'|trans) }}
|
||||
{% if not product.deleted %}
|
||||
{{ buttons.edit(path('sylius_backend_product_update', {'id': product.id})) }}
|
||||
{{ buttons.delete(path('sylius_backend_product_delete', {'id': product.id}), null, false, false) }}
|
||||
<a href="{{ path(product) }}" class="btn btn-info">
|
||||
<i class="glyphicon glyphicon-shopping-cart"></i>
|
||||
{{ 'sylius.product.show_in_store'|trans }}
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
<h1><i class="glyphicon glyphicon-calendar"></i> {{ 'sylius.product.show_header'|trans({'%product%': product.name})|raw }}</h1>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -20,11 +20,6 @@
|
|||
</a>
|
||||
{{ buttons.manage(path('sylius_backend_product_option_index'), 'sylius.product_option.manage'|trans) }}
|
||||
{{ buttons.manage(path('sylius_backend_product_attribute_index'), 'sylius.product_attribute.manage'|trans) }}
|
||||
{% if app.request.query.get('deleted') %}
|
||||
<a href="{{ path('sylius_backend_product_index', {'deleted': false}) }}" class="btn btn-danger"><i class="glyphicon glyphicon-trash"></i> {{ 'sylius.hide_deleted'|trans }}</a>
|
||||
{% else %}
|
||||
<a href="{{ path('sylius_backend_product_index', {'deleted': true}) }}" class="btn btn-danger"><i class="glyphicon glyphicon-trash"></i> {{ 'sylius.show_deleted'|trans }}</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
<h1><i class="glyphicon glyphicon-th-list"></i> {{ 'sylius.product.index_header'|trans|raw }}</h1>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -96,12 +96,8 @@
|
|||
<a href="{{ path('sylius_backend_metadata_container_customize', { 'id': product.metadataIdentifier }) }}" class="btn btn-default">
|
||||
<i class="glyphicon glyphicon-file"></i><span>{{ 'sylius.metadata.product.single_customize'|trans }}</span>
|
||||
</a>
|
||||
{% if product.deleted %}
|
||||
{{ buttons.patch(path('sylius_backend_product_delete_restore', {'id': product.id}), 'sylius.restore'|trans, null, 'btn btn-primary') }}
|
||||
{% else %}
|
||||
{{ buttons.edit(path('sylius_backend_product_update', {'id': product.id})) }}
|
||||
{{ buttons.delete(path('sylius_backend_product_delete', {'id': product.id})) }}
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
|
|
|||
|
|
@ -22,19 +22,15 @@
|
|||
{% else %}
|
||||
{{ buttons.enable(path('sylius_backend_product_enable', {'id': product.id})) }}
|
||||
{% endif %}
|
||||
{% if not product.deleted %}
|
||||
<a href="{{ path('sylius_backend_metadata_container_customize', { 'id': product.metadataIdentifier }) }}" class="btn btn-default">
|
||||
<i class="glyphicon glyphicon-file"></i><span>{{ 'sylius.metadata.product.single_customize'|trans }}</span>
|
||||
</a>
|
||||
{{ buttons.edit(path('sylius_backend_product_update', {'id': product.id})) }}
|
||||
{{ buttons.delete(path('sylius_backend_product_delete', {'id': product.id}), null, false, true) }}
|
||||
<a href="{{ path(product) }}" class="btn btn-info">
|
||||
<i class="glyphicon glyphicon-shopping-cart"></i>
|
||||
{{ 'sylius.product.show_in_store'|trans }}
|
||||
</a>
|
||||
{% else %}
|
||||
{{ buttons.patch(path('sylius_backend_product_delete_restore', {'id': product.id}), 'sylius.restore'|trans, null, 'btn btn-primary') }}
|
||||
{% endif %}
|
||||
<a href="{{ path('sylius_backend_metadata_container_customize', { 'id': product.metadataIdentifier }) }}" class="btn btn-default">
|
||||
<i class="glyphicon glyphicon-file"></i><span>{{ 'sylius.metadata.product.single_customize'|trans }}</span>
|
||||
</a>
|
||||
{{ buttons.edit(path('sylius_backend_product_update', {'id': product.id})) }}
|
||||
{{ buttons.delete(path('sylius_backend_product_delete', {'id': product.id}), null, false, true) }}
|
||||
<a href="{{ path(product) }}" class="btn btn-info">
|
||||
<i class="glyphicon glyphicon-shopping-cart"></i>
|
||||
{{ 'sylius.product.show_in_store'|trans }}
|
||||
</a>
|
||||
<a href="{{ path('sylius_backend_product_history', {'id': product.id}) }}" class="btn btn-info">
|
||||
<i class="glyphicon glyphicon-calendar"></i>
|
||||
{{ 'sylius.history.header'|trans }}
|
||||
|
|
@ -42,7 +38,6 @@
|
|||
</div>
|
||||
<h1>
|
||||
<i class="glyphicon glyphicon-info-sign"></i> {{ 'sylius.product.show_header'|trans({'%product%': product.name})|raw }}
|
||||
{% if product.deleted %}<span class="label label-danger">{{ 'sylius.deleted'|trans }}</span>{% endif %}
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
|
|
@ -277,7 +272,6 @@
|
|||
|
||||
<hr>
|
||||
|
||||
{% if not product.deleted %}
|
||||
<div class="well well-sm">
|
||||
{{ buttons.create(path('sylius_backend_product_variant_create', {'productId': product.id}), 'sylius.variant.create'|trans) }}
|
||||
{% if product.hasOptions %}
|
||||
|
|
@ -287,7 +281,6 @@
|
|||
<strong>{{ 'sylius.product.variant_selection_method'|trans }}</strong>: {{ product.variantSelectionMethodLabel }}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{{ list_variants(product.variants) }}
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@ use Doctrine\Common\Collections\ArrayCollection;
|
|||
use Doctrine\Common\Collections\Collection;
|
||||
use Sylius\Component\Archetype\Model\ArchetypeInterface as BaseArchetypeInterface;
|
||||
use Sylius\Component\Attribute\Model\AttributeValueInterface as BaseAttributeValueInterface;
|
||||
use Sylius\Component\Resource\Model\SoftDeletableTrait;
|
||||
use Sylius\Component\Resource\Model\TimestampableTrait;
|
||||
use Sylius\Component\Resource\Model\ToggleableTrait;
|
||||
use Sylius\Component\Resource\Model\TranslatableTrait;
|
||||
|
|
@ -28,7 +27,7 @@ use Sylius\Component\Variation\Model\VariantInterface as BaseVariantInterface;
|
|||
*/
|
||||
class Product implements ProductInterface
|
||||
{
|
||||
use SoftDeletableTrait, TimestampableTrait, ToggleableTrait;
|
||||
use TimestampableTrait, ToggleableTrait;
|
||||
use TranslatableTrait {
|
||||
__construct as private initializeTranslationsCollection;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,7 +26,6 @@ use Sylius\Component\Resource\Model\TranslatableInterface;
|
|||
interface ProductInterface extends
|
||||
ArchetypeSubjectInterface,
|
||||
SlugAwareInterface,
|
||||
SoftDeletableInterface,
|
||||
TimestampableInterface,
|
||||
ToggleableInterface,
|
||||
ProductTranslationInterface,
|
||||
|
|
|
|||
|
|
@ -269,37 +269,6 @@ class ProductSpec extends ObjectBehavior
|
|||
$this->getUpdatedAt()->shouldReturn($date);
|
||||
}
|
||||
|
||||
function it_has_no_deletion_date_by_default()
|
||||
{
|
||||
$this->getDeletedAt()->shouldReturn(null);
|
||||
}
|
||||
|
||||
function it_is_not_be_deleted_by_default()
|
||||
{
|
||||
$this->shouldNotBeDeleted();
|
||||
}
|
||||
|
||||
function its_deletion_date_is_mutable()
|
||||
{
|
||||
$deletedAt = new \DateTime();
|
||||
|
||||
$this->setDeletedAt($deletedAt);
|
||||
$this->getDeletedAt()->shouldReturn($deletedAt);
|
||||
}
|
||||
|
||||
function it_is_deleted_only_if_deletion_date_is_in_past()
|
||||
{
|
||||
$deletedAt = new \DateTime('yesterday');
|
||||
|
||||
$this->setDeletedAt($deletedAt);
|
||||
$this->shouldBeDeleted();
|
||||
|
||||
$deletedAt = new \DateTime('tomorrow');
|
||||
|
||||
$this->setDeletedAt($deletedAt);
|
||||
$this->shouldNotBeDeleted();
|
||||
}
|
||||
|
||||
function it_is_enabled_by_default()
|
||||
{
|
||||
$this->shouldBeEnabled();
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue