Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Resolve actions and rules configuration validation #15551

Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
2538adf
[PromotionBundle] Add PromotionActionValidator class
Wojdylak Nov 20, 2023
161ed14
[PromotionBundle] Add PromotionRuleValidator class
Wojdylak Nov 20, 2023
d243aec
[CoreBundle] Add ChannelCodeCollectionValidator class
Wojdylak Nov 20, 2023
67729d7
[CoreBundle] Add validators
Wojdylak Nov 21, 2023
27bcec5
[PromotionBundle] Add tests of PromotionActionValidator and Promotion…
Wojdylak Nov 21, 2023
9ded51c
[ApiBundle] Add validation for PromotionAction
Wojdylak Nov 21, 2023
c61d53e
[ApiBundle] Add validation for PromotionRule
Wojdylak Nov 21, 2023
f4a3a3e
[CoreBundle] Add ProductCodeExistsValidator class
Wojdylak Nov 21, 2023
6099315
Add contract test for Promotion
Wojdylak Nov 21, 2023
d6349f7
Resolve psalm issues
Wojdylak Nov 21, 2023
173a7e1
Resolve phpstan issues
Wojdylak Nov 21, 2023
10c3308
Add behat tests for Promotion
Wojdylak Nov 21, 2023
fa69b8d
Resolve phpstan issues
Wojdylak Nov 21, 2023
d332213
Change check at PromotionActionGroupValidatorSpec
Wojdylak Nov 21, 2023
d92465d
Add validation filters of PromotionAction
Wojdylak Nov 21, 2023
1e4b146
Change type at PromotionActionValidatorSpec
Wojdylak Nov 21, 2023
77124ac
Resolve phpstan isssues
Wojdylak Nov 22, 2023
af85597
[ApiBundle][Promotion] Enable auto-increment of priority via API when…
Wojdylak Nov 24, 2023
42f6aca
[CoreBundle] Rename no_exist to not_exist
Wojdylak Nov 24, 2023
c756199
[Behat][Api] Change default value to -1
Wojdylak Nov 24, 2023
c5449da
Remove unnecessary comments
Wojdylak Nov 27, 2023
02cc812
[Behat][Promotion] Add setting promotion to the lowest priority scena…
Wojdylak Nov 27, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -11,7 +11,7 @@ Feature: Editing promotion
And I am logged in as an administrator

@api @ui
Scenario: Seeing disabled code field when editing promotion
Scenario: Being unable to change code of promotion
When I want to modify a "Christmas sale" promotion
Then I should not be able to edit its code

Expand Down
Expand Up @@ -61,7 +61,7 @@ Feature: Promotion validation
And I try to save my changes
Then I should be notified that promotion label in "Polish (Poland)" locale is too long

@ui @javascript
@api @ui @javascript
Scenario: Trying to add a new promotion without specifying a order percentage discount
When I want to create a new promotion
And I specify its code as "christmas_sale"
Expand All @@ -71,17 +71,17 @@ Feature: Promotion validation
Then I should be notified that this value should not be blank
And promotion with name "Christmas sale" should not be added

@ui @javascript
@api @ui @javascript
Scenario: Trying to add a new promotion without specifying an item percentage discount
When I want to create a new promotion
And I specify its code as "christmas_sale"
And I name it "Christmas sale"
And I add the "Item percentage discount" action configured without a percentage value
And I add the "Item percentage discount" action configured without a percentage value for "United States" channel
jakubtobiasz marked this conversation as resolved.
Show resolved Hide resolved
And I try to add it
Then I should be notified that this value should not be blank
And promotion with name "Christmas sale" should not be added

@ui @javascript
@api @ui @javascript
Scenario: Trying to add a new promotion with a wrong order percentage discount
When I want to create a new promotion
And I specify its code as "christmas_sale"
Expand All @@ -91,12 +91,12 @@ Feature: Promotion validation
Then I should be notified that a percentage discount value must be between 0% and 100%
And promotion with name "Christmas sale" should not be added

@ui @javascript
@api @ui @javascript
Scenario: Trying to add a new promotion with a wrong item percentage discount
When I want to create a new promotion
And I specify its code as "christmas_sale"
And I name it "Christmas sale"
And I add the "Item percentage discount" action configured with a percentage value of "130%"
And I add the "Item percentage discount" action configured with a percentage value of "130%" for "United States" channel
And I try to add it
Then I should be notified that a percentage discount value must be between 0% and 100%
And promotion with name "Christmas sale" should not be added
Expand Up @@ -8,7 +8,7 @@ Feature: Promotion filters validation
Given the store operates on a single channel in "United States"
And I am logged in as an administrator

@ui @javascript
@api @ui @javascript
Scenario: Adding a promotion with wrong minimum price on price range filter
When I want to create a new promotion
And I specify its code as "10_for_all_products_over_10"
Expand All @@ -19,7 +19,7 @@ Feature: Promotion filters validation
Then I should be notified that a minimum value should be a numeric value
And promotion with name "$10 discount for all products over $10!" should not be added

@ui @javascript
@api @ui @javascript
Scenario: Adding a promotion with wrong maximum price on price range filter
When I want to create a new promotion
And I specify its code as "10_for_all_products_over_10"
Expand Down
10 changes: 0 additions & 10 deletions phpstan-baseline.neon
Wojdylak marked this conversation as resolved.
Show resolved Hide resolved
Expand Up @@ -820,11 +820,6 @@ parameters:
count: 1
path: src/Sylius/Bundle/ApiBundle/DataPersister/ProductVariantDataPersister.php

-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\PromotionDataPersister\\:\\:remove\\(\\) has no return type specified\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/DataPersister/PromotionDataPersister.php

-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\ShippingMethodDataPersister\\:\\:persist\\(\\) has parameter \\$context with no value type specified in iterable type array\\.$#"
count: 1
Expand Down Expand Up @@ -3295,11 +3290,6 @@ parameters:
count: 1
path: src/Sylius/Bundle/CoreBundle/Fixture/Factory/PromotionExampleFactory.php

-
message: "#^Method Sylius\\\\Bundle\\\\CoreBundle\\\\Fixture\\\\Factory\\\\PromotionExampleFactory\\:\\:getLocales\\(\\) return type has no value type specified in iterable type iterable\\.$#"
count: 1
path: src/Sylius/Bundle/CoreBundle/Fixture/Factory/PromotionExampleFactory.php

-
message: "#^Method Sylius\\\\Bundle\\\\CoreBundle\\\\Fixture\\\\Factory\\\\PromotionRuleExampleFactory\\:\\:__construct\\(\\) has parameter \\$promotionRuleFactory with generic interface Sylius\\\\Component\\\\Core\\\\Factory\\\\PromotionRuleFactoryInterface but does not specify its types\\: T$#"
count: 1
Expand Down
Expand Up @@ -120,7 +120,7 @@ public function iMakeItCouponBased(): void
* @When I set its priority to :priority
* @When I remove its priority
*/
public function iRemoveItsPriority(?int $priority = null): void
public function iRemoveItsPriority(int $priority = -1): void
jakubtobiasz marked this conversation as resolved.
Show resolved Hide resolved
{
$this->client->addRequestData('priority', $priority);
}
Expand Down Expand Up @@ -211,6 +211,21 @@ public function iAddTheActionConfiguredWithAPercentageValueForChannel(
);
}

/**
* @When I add the "Item percentage discount" action configured without a percentage value for :channel channel
*/
public function iAddTheActionConfiguredWithoutAPercentageValueForChannel(ChannelInterface $channel): void {

$this->addToRequestAction(
UnitPercentageDiscountPromotionActionCommand::TYPE,
[
$channel->getCode() => [
'percentage' => null,
],
],
);
}

/**
* @When /^I add the "([^"]+)" action configured with a percentage value of ("[^"]+")$/
* @When I add the :actionType action configured without a percentage value
Expand Down Expand Up @@ -255,7 +270,7 @@ public function iEditPromotionToHaveDiscount(PromotionInterface $promotion, floa
/**
* @When /^I specify that on ("[^"]+" channel) this action should be applied to items with price greater than "(?:€|£|\$)([^"]+)"$/
*/
public function iAddAMinPriceFilterRangeForChannel(ChannelInterface $channel, int $minimum): void
public function iAddAMinPriceFilterRangeForChannel(ChannelInterface $channel, int|string $minimum): void
jakubtobiasz marked this conversation as resolved.
Show resolved Hide resolved
{
$actions = $this->getActions();
$actions[0]['configuration'][$channel->getCode()]['filters']['price_range_filter']['min'] = $minimum;
Expand All @@ -266,7 +281,7 @@ public function iAddAMinPriceFilterRangeForChannel(ChannelInterface $channel, in
/**
* @When /^I specify that on ("[^"]+" channel) this action should be applied to items with price lesser than "(?:€|£|\$)([^"]+)"$/
*/
public function iAddAMaxPriceFilterRangeForChannel(ChannelInterface $channel, int $maximum): void
public function iAddAMaxPriceFilterRangeForChannel(ChannelInterface $channel, int|string $maximum): void
{
$actions = $this->getActions();
$actions[0]['configuration'][$channel->getCode()]['filters']['price_range_filter']['max'] = $maximum;
Expand Down Expand Up @@ -751,6 +766,42 @@ public function iShouldBeNotifiedThatThisValueShouldNotBeBlank(): void
'This value should not be blank.',
);
}

/**
* @Then I should be notified that a percentage discount value must be between 0% and 100%
* @Then I should be notified that a percentage discount value must be at least 0%
* @Then I should be notified that the maximum value of a percentage discount is 100%
*/
public function iShouldBeNotifiedThatPercentageDiscountShouldBeBetween(): void
{
Assert::contains(
$this->responseChecker->getError($this->client->getLastResponse()),
'The percentage discount must be between 0% and 100%.',
);
}

/**
* @Then I should be notified that a minimum value should be a numeric value
*/
public function iShouldBeNotifiedThatAMinimalValueShouldBeNumeric(): void
{
Assert::contains(
$this->responseChecker->getError($this->client->getLastResponse()),
'[min]: This value should be of type numeric.',
);
}

/**
* @Then I should be notified that a maximum value should be a numeric value
*/
public function iShouldBeNotifiedThatAMaximumValueShouldBeNumeric(): void
{
Assert::contains(
$this->responseChecker->getError($this->client->getLastResponse()),
'[max]: This value should be of type numeric.',
);
}

/**
* @Then I should see :count promotions on the list
* @Then I should see a single promotion on the list
Expand Down
11 changes: 11 additions & 0 deletions src/Sylius/Behat/Context/Ui/Admin/ManagingPromotionsContext.php
Expand Up @@ -229,6 +229,17 @@ public function iAddTheActionConfiguredWithAPercentageValueForChannel(
$this->createPage->fillActionOptionForChannel($channel->getCode(), 'Percentage', $percentage);
}

/**
* @When I add the :actionType action configured without a percentage value for :channel channel
*/
public function iAddTheActionConfiguredWithoutAPercentageValueForChannel(
string $actionType,
ChannelInterface $channel
): void {
$this->createPage->addAction($actionType);
$this->createPage->fillActionOptionForChannel($channel->getCode(), 'Percentage', '');
}

/**
* @When /^I add the "([^"]+)" action configured with a percentage value of "(?:|-)([^"]+)%"$/
* @When I add the :actionType action configured without a percentage value
Expand Down
Expand Up @@ -25,23 +25,23 @@ public function __construct(private ContextAwareDataPersisterInterface $decorate
{
}

/** @param array<mixed> $context */
/** @param array<string, mixed> $context */
public function supports($data, array $context = []): bool
{
return $data instanceof PromotionInterface;
}

/** @param array<mixed> $context */
/** @param array<string, mixed> $context */
public function persist($data, array $context = [])
{
return $this->decoratedDataPersister->persist($data, $context);
}

/** @param array<mixed> $context */
public function remove($data, array $context = [])
/** @param array<string, mixed> $context */
public function remove($data, array $context = []): void
{
try {
return $this->decoratedDataPersister->remove($data, $context);
$this->decoratedDataPersister->remove($data, $context);
} catch (ForeignKeyConstraintViolationException) {
throw new PromotionCannotBeRemoved();
}
Expand Down
Expand Up @@ -19,6 +19,9 @@
/** @experimental */
final class PromotionDocumentationModifier implements DocumentationModifierInterface
{
const ROUTE_ADMIN_PROMOTIONS = '/admin/promotions';
const ROUTE_ADMIN_PROMOTION = '/admin/promotions/{code}';

/**
* @param string[] $actionTypes
* @param string[] $ruleTypes
Expand All @@ -34,8 +37,8 @@ public function modify(OpenApi $docs): OpenApi
{
$paths = $docs->getPaths();

$this->addDescription($paths, sprintf('%s/admin/promotions', $this->apiRoute), 'Post');
$this->addDescription($paths, sprintf('%s/admin/promotions/{code}', $this->apiRoute), 'Put');
$this->addDescription($paths, sprintf('%s%s', $this->apiRoute, self::ROUTE_ADMIN_PROMOTIONS), 'Post');
$this->addDescription($paths, sprintf('%s%s', $this->apiRoute, self::ROUTE_ADMIN_PROMOTION), 'Put');
Wojdylak marked this conversation as resolved.
Show resolved Hide resolved

return $docs->withPaths($paths);
}
Expand Down
Expand Up @@ -18,7 +18,10 @@
<resource class="%sylius.model.promotion.class%" shortName="Promotion">
<attribute name="route_prefix">admin</attribute>

<attribute name="validation_groups">sylius</attribute>
<attribute name="validation_groups">
<attribute>sylius</attribute>
<attribute>sylius_api</attribute>
</attribute>

<attribute name="order">
<attribute name="priority">DESC</attribute>
Expand Down
Expand Up @@ -45,9 +45,6 @@
<group>admin:promotion:read</group>
<group>admin:promotion:create</group>
<group>admin:promotion:update</group>
<denormalization_context>
<entry name="disable_type_enforcement">true</entry>
</denormalization_context>
</attribute>

<attribute name="exclusive">
Expand Down
Expand Up @@ -188,5 +188,13 @@
<argument type="service" id="Sylius\Bundle\ApiBundle\Validator\CatalogPromotion\ForVariantsScopeValidator.inner" />
<argument type="service" id="Sylius\Bundle\CoreBundle\SectionResolver\SectionProviderInterface" />
</service>

<service id="Sylius\Bundle\ApiBundle\Validator\Constraints\PromotionActionGroupValidator">
<tag name="validator.constraint_validator" alias="sylius_promotion_action_group" />
</service>

<service id="Sylius\Bundle\ApiBundle\Validator\Constraints\PromotionRuleGroupValidator">
<tag name="validator.constraint_validator" alias="sylius_promotion_rule_group" />
</service>
</services>
</container>