[Admin][ProductOption] Added validation product option feature

This commit is contained in:
Grzegorz Sadowski 2016-04-22 11:17:54 +02:00
parent a6a3aba9b9
commit 38dd2cbd54
13 changed files with 347 additions and 16 deletions

View file

@ -97,6 +97,11 @@
<tag name="sylius.behat.context" />
</service>
<service id="sylius.behat.context.transform.product_option" class="%sylius.behat.context.transform.product_option.class%" scope="scenario">
<argument type="service" id="sylius.repository.product_option" container="symfony" />
<tag name="sylius.behat.context" />
</service>
<service id="sylius.behat.context.transform.product_variant" class="%sylius.behat.context.transform.product_variant.class%" scope="scenario">
<argument type="service" id="sylius.repository.product" container="symfony" />
<argument type="service" id="sylius.repository.product_variant" container="symfony" />

View file

@ -59,7 +59,7 @@
<parameter key="sylius.behat.page.admin.product_attribute.index.class">%sylius.behat.page.admin.crud.index.class%</parameter>
<parameter key="sylius.behat.page.admin.product_attribute.update.class">Sylius\Behat\Page\Admin\Product\Attribute\UpdatePage</parameter>
<parameter key="sylius.behat.page.admin.product_option.create.class">Sylius\Behat\Page\Admin\ProductOption\CreatePage</parameter>
<parameter key="sylius.behat.page.admin.product_option.update.class">%sylius.behat.page.admin.crud.update.class%</parameter>
<parameter key="sylius.behat.page.admin.product_option.update.class">Sylius\Behat\Page\Admin\ProductOption\UpdatePage</parameter>
<parameter key="sylius.behat.page.admin.product_option.index.class">%sylius.behat.page.admin.crud.index.class%</parameter>
<parameter key="sylius.behat.page.admin.promotion.create.class">Sylius\Behat\Page\Admin\Promotion\CreatePage</parameter>
<parameter key="sylius.behat.page.admin.promotion.update.class">Sylius\Behat\Page\Admin\Promotion\UpdatePage</parameter>

View file

@ -8,6 +8,7 @@ default:
- sylius.behat.context.hook.doctrine_orm
- sylius.behat.context.transform.locale
- sylius.behat.context.transform.product_option
- sylius.behat.context.transform.shared_storage
- sylius.behat.context.setup.channel

View file

@ -0,0 +1,21 @@
@managing_product_options
Feature: Product option unique code validation
In order to uniquely identify product options
As an Administrator
I want to be prevented from adding two product options with the same code
Background:
Given the store operates on a single channel in "France"
And the store has a product option "T-Shirt size" with a code "t_shirt_size"
And I am logged in as an administrator
@ui @javascript
Scenario: Trying to add product option with a taken code
Given I want to create a new product option
When I name it "T-Shirt color" in "English (United States)"
And I specify its code as "t_shirt_size"
And I add the option value with code "OV1" and value "S"
And I add the option value with code "OV2" and value "M"
And I try to add it
Then I should be notified that product option with this code already exists
And there should still be only one product option with code "t_shirt_size"

View file

@ -0,0 +1,65 @@
@managing_product_options
Feature: Product option validation
In order to avoid making mistakes when managing a product option
As an Administrator
I want to be prevented from adding it without specifying required fields
Background:
Given the store operates on a single channel in "France"
And the store has a product option "T-Shirt color" with a code "t_shirt_color"
And I am logged in as an administrator
@ui @javascript
Scenario: Trying to add a new product option without specifying its code
Given I want to create a new product option
When I name it "T-Shirt size" in "English (United States)"
But I do not specify its code
And I add the option value with code "OV1" and value "S"
And I add the option value with code "OV2" and value "M"
And I try to add it
Then I should be notified that code is required
And the product option with name "T-Shirt size" should not be added
@ui @javascript
Scenario: Trying to add a new product option without specifying its name
Given I want to create a new product option
When I specify its code as "t_shirt_size"
But I do not name it
And I add the option value with code "OV1" and value "S"
And I add the option value with code "OV2" and value "M"
And I try to add it
Then I should be notified that name is required
And the product option with code "t_shirt_size" should not be added
@ui
Scenario: Trying to remove name from an existing product option
Given I want to modify the "T-Shirt color" product option
When I remove its name from "English (United States)" translation
And I try to save my changes
Then I should be notified that name is required
And this product option should still be named "T-Shirt color"
@ui
Scenario: Seeing disabled code field when editing product option
Given I want to modify the "T-Shirt color" product option
Then the code field should be disabled
@ui
Scenario: Trying to add a new product option without any option values
Given I want to create a new product option
When I name it "T-Shirt size" in "English (United States)"
And I specify its code as "t_shirt_size"
But I do not add an option value
And I try to add it
Then I should be notified that at least two option values are required
And the product option with name "T-Shirt size" should not be added
@ui @javascript
Scenario: Trying to add a new product option with one option value
Given I want to create a new product option
When I name it "T-Shirt size" in "English (United States)"
And I specify its code as "t_shirt_size"
And I add the option value with code "OV1" and value "S"
And I try to add it
Then I should be notified that at least two option values are required
And the product option with name "T-Shirt size" should not be added

View file

@ -20,13 +20,14 @@ use Sylius\Component\Core\Model\ProductVariantInterface;
use Sylius\Component\Core\Repository\ProductRepositoryInterface;
use Sylius\Component\Core\Test\Services\SharedStorageInterface;
use Sylius\Component\Resource\Factory\FactoryInterface;
use Sylius\Component\Resource\Repository\RepositoryInterface;
use Sylius\Component\Taxation\Model\TaxCategoryInterface;
use Sylius\Component\Variation\Repository\OptionRepositoryInterface;
/**
* @author Arkadiusz Krakowiak <arkadiusz.krakowiak@lakion.com>
* @author Mateusz Zalewski <mateusz.zalewski@lakion.com>
* @author Magdalena Banasiak <magdalena.banasiak@lakion.com>
* @author Grzegorz Sadowski <grzegorz.sadowski@lakion.com>
*/
final class ProductContext implements Context
{
@ -56,7 +57,7 @@ final class ProductContext implements Context
private $productOptionFactory;
/**
* @var RepositoryInterface
* @var OptionRepositoryInterface
*/
private $productOptionRepository;
@ -71,7 +72,7 @@ final class ProductContext implements Context
* @param FactoryInterface $productFactory
* @param FactoryInterface $productVariantFactory
* @param FactoryInterface $productOptionFactory
* @param RepositoryInterface $productOptionRepository
* @param OptionRepositoryInterface $productOptionRepository
* @param ObjectManager $objectManager
*/
public function __construct(
@ -80,7 +81,7 @@ final class ProductContext implements Context
FactoryInterface $productFactory,
FactoryInterface $productVariantFactory,
FactoryInterface $productOptionFactory,
RepositoryInterface $productOptionRepository,
OptionRepositoryInterface $productOptionRepository,
ObjectManager $objectManager
) {
$this->sharedStorage = $sharedStorage;
@ -186,6 +187,19 @@ final class ProductContext implements Context
$this->objectManager->flush($productVariant);
}
/**
* @Given the store has a product option :productOptionName with a code :productOptionCode
*/
public function theStoreHasAProductOptionWithACode($productOptionName, $productOptionCode)
{
$productOption = $this->productOptionFactory->createNew();
$productOption->setCode($productOptionCode);
$productOption->setName($productOptionName);
$this->sharedStorage->set('product_option', $productOption);
$this->productOptionRepository->add($productOption);
}
/**
* @param string $price
*

View file

@ -12,9 +12,7 @@
namespace Sylius\Behat\Context\Transform;
use Behat\Behat\Context\Context;
use Sylius\Component\Core\Repository\ProductRepositoryInterface;
use Sylius\Component\Core\Repository\ProductVariantRepositoryInterface;
use Sylius\Component\Resource\Repository\RepositoryInterface;
use Sylius\Component\Variation\Repository\OptionRepositoryInterface;
use Webmozart\Assert\Assert;
/**
@ -23,14 +21,14 @@ use Webmozart\Assert\Assert;
final class ProductOptionContext implements Context
{
/**
* @var RepositoryInterface
* @var OptionRepositoryInterface
*/
private $productOptionRepository;
/**
* @param RepositoryInterface $productOptionRepository
* @param OptionRepositoryInterface $productOptionRepository
*/
public function __construct(RepositoryInterface $productOptionRepository)
public function __construct(OptionRepositoryInterface $productOptionRepository)
{
$this->productOptionRepository = $productOptionRepository;
}
@ -41,7 +39,7 @@ final class ProductOptionContext implements Context
*/
public function getProductOptionByName($productOptionName)
{
$productOption = $this->productOptionRepository->findOneBy(['name' => $productOptionName]);
$productOption = $this->productOptionRepository->findOneByName($productOptionName);
Assert::notNull(
$productOption,
sprintf('Product option with name "%s" does not exist in the product option repository.', $productOptionName)

View file

@ -14,9 +14,10 @@ namespace Sylius\Behat\Context\Ui\Admin;
use Behat\Behat\Context\Context;
use Sylius\Behat\Page\Admin\Crud\IndexPageInterface;
use Sylius\Behat\Page\Admin\ProductOption\CreatePageInterface;
use Sylius\Behat\Page\Admin\Crud\UpdatePageInterface;
use Sylius\Behat\Page\Admin\ProductOption\UpdatePageInterface;
use Sylius\Behat\Service\CurrentPageResolverInterface;
use Sylius\Behat\Service\NotificationCheckerInterface;
use Sylius\Component\Product\Model\OptionInterface;
use Webmozart\Assert\Assert;
/**
@ -80,6 +81,14 @@ final class ManagingProductOptionsContext implements Context
$this->createPage->open();
}
/**
* @Given I want to modify the :productOption product option
*/
public function iWantToModifyAPaymentMethod(OptionInterface $productOption)
{
$this->updatePage->open(['id' => $productOption->getId()]);
}
/**
* @When I browse product options
*/
@ -108,16 +117,26 @@ final class ManagingProductOptionsContext implements Context
/**
* @When I name it :name in :language
* @When I remove its name from :language translation
*/
public function iNameItInLanguage($name, $language)
public function iNameItInLanguage($name = null, $language)
{
$this->createPage->nameItIn($name, $language);
}
/**
* @When I specify its code as :code
* @When I do not name it
*/
public function iSpecifyItsCodeAs($code)
public function iDoNotNameIt()
{
// Intentionally left blank to fulfill context expectation
}
/**
* @When I specify its code as :code
* @When I do not specify its code
*/
public function iSpecifyItsCodeAs($code = null)
{
$this->createPage->specifyCode($code);
}
@ -150,4 +169,107 @@ final class ManagingProductOptionsContext implements Context
sprintf('The shipping method with name %s has not been found.', $productOptionName)
);
}
/**
* @Then I should be notified that product option with this code already exists
*/
public function iShouldBeNotifiedThatProductOptionWithThisCodeAlreadyExists()
{
Assert::true(
$this->createPage->checkValidationMessageFor('code', 'The option with given code already exists.'),
'Unique code violation message should appear on page, but it does not.'
);
}
/**
* @Then there should still be only one product option with :element :value
*/
public function thereShouldStillBeOnlyOneProductOptionWith($element, $value)
{
$this->iBrowseProductOptions();
Assert::true(
$this->indexPage->isResourceOnPage([$element => $value]),
sprintf('Product option with %s %s cannot be found.', $element, $value)
);
}
/**
* @Then I should be notified that :element is required
*/
public function iShouldBeNotifiedThatElementIsRequired($element)
{
$this->assertFieldValidationMessage($element, sprintf('Please enter option %s.', $element));
}
/**
* @Then the product option with :element :value should not be added
*/
public function theProductoptionWithElementValueShouldNotBeAdded($element, $value)
{
$this->iBrowseProductOptions();
Assert::false(
$this->indexPage->isResourceOnPage([$element => $value]),
sprintf('Product option with %s %s was created, but it should not.', $element, $value)
);
}
/**
* @param string $element
* @param string $expectedMessage
*/
private function assertFieldValidationMessage($element, $expectedMessage)
{
Assert::true(
$this->createPage->checkValidationMessageFor($element, $expectedMessage),
sprintf('Product option %s should be required.', $element)
);
}
/**
* @Then /^(this product option) should still be named "([^"]+)"$/
*/
public function thisProductOptionNameShouldStillBe(OptionInterface $productOption, $productOptionName)
{
$this->iBrowseProductOptions();
Assert::true(
$this->indexPage->isResourceOnPage([
'code' => $productOption->getCode(),
'name' => $productOptionName,
]),
sprintf('Product option name %s has not been assigned properly.', $productOptionName)
);
}
/**
* @Then the code field should be disabled
*/
public function theCodeFieldShouldBeDisabled()
{
Assert::true(
$this->updatePage->isCodeDisabled(),
'Code field should be disabled but it is not'
);
}
/**
* @When I do not add an option value
*/
public function iDoNotAddAnOptionValue()
{
// Intentionally left blank to fulfill context expectation
}
/**
* @Then I should be notified that at least two option values are required
*/
public function iShouldBeNotifiedThatAtLeastTwoOptionValuesAreRequired()
{
Assert::true(
$this->createPage->checkValidationMessageForOptionValues('Please add at least 2 option values.'),
'I should be notified that product option needs at least two option values.'
);
}
}

View file

@ -12,6 +12,7 @@
namespace Sylius\Behat\Page\Admin\ProductOption;
use Behat\Mink\Element\Element;
use Behat\Mink\Exception\ElementNotFoundException;
use Sylius\Behat\Behaviour\SpecifiesItsCode;
use Sylius\Behat\Page\Admin\Crud\CreatePage as BaseCreatePage;
@ -45,6 +46,19 @@ class CreatePage extends BaseCreatePage implements CreatePageInterface
$optionValueForm->fillField('Value', $code);
}
/**
* {@inheritdoc}
*/
public function checkValidationMessageForOptionValues($message)
{
$optionValuesValidationElement = $this->getElement('ui_segment')->find('css', '.ui.pointing');
if (null === $optionValuesValidationElement) {
throw new ElementNotFoundException($this->getDriver(), 'product option validation box', 'css', '.ui.pointing');
}
return $optionValuesValidationElement->getText() === $message;
}
/**
* {@inheritdoc}
*/
@ -54,6 +68,7 @@ class CreatePage extends BaseCreatePage implements CreatePageInterface
'code' => '#sylius_product_option_code',
'name' => '#sylius_product_option_translations_en_US_name',
'values' => '#sylius_product_option_values',
'ui_segment' => '.ui.segment',
]);
}

View file

@ -34,4 +34,9 @@ interface CreatePageInterface extends BaseCreatePageInterface
* @param string $value
*/
public function addOptionValue($code, $value);
/**
* @param string $message
*/
public function checkValidationMessageForOptionValues($message);
}

View file

@ -0,0 +1,53 @@
<?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\ProductOption;
use Sylius\Behat\Behaviour\ChecksCodeImmutability;
use Sylius\Behat\Page\Admin\Crud\UpdatePage as BaseUpdatePage;
/**
* @author Grzegorz Sadowski <grzegorz.sadowski@lakion.com>
*/
class UpdatePage extends BaseUpdatePage implements UpdatePageInterface
{
use ChecksCodeImmutability;
/**
* {@inheritdoc}
*/
public function nameItIn($name, $language)
{
$this->getDocument()->fillField(
sprintf('sylius_product_option_translations_%s_name', $language), $name
);
}
/**
* {@inheritdoc}
*/
protected function getCodeElement()
{
return $this->getElement('code');
}
/**
* {@inheritdoc}
*/
protected function getDefinedElements()
{
return array_merge(parent::getDefinedElements(), [
'code' => '#sylius_product_option_code',
'name' => '#sylius_product_option_translations_en_US_name',
'values' => '#sylius_product_option_values',
]);
}
}

View file

@ -0,0 +1,31 @@
<?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\ProductOption;
use Sylius\Behat\Page\Admin\Crud\UpdatePageInterface as BaseUpdatePageInterface;
/**
* @author Grzegorz Sadowski <grzegorz.sadowski@lakion.com>
*/
interface UpdatePageInterface extends BaseUpdatePageInterface
{
/**
* @return bool
*/
public function isCodeDisabled();
/**
* @param string $name
* @param string $languageCode
*/
public function nameItIn($name, $languageCode);
}

View file

@ -36,6 +36,7 @@ sylius:
edit_currency: Edit currency
edit_customer: Edit customer
edit_payment_method: Edit payment method
edit_product_option: Edit product option
edit_promotion: Edit promotion
edit_tax_category: Edit tax category
edit_tax_rate: Edit tax rate