mirror of
https://github.com/Sylius/Sylius.git
synced 2026-07-15 09:30:58 +00:00
Merge branch '2.0' into api-platform-3
* 2.0: (30 commits) [CS][DX] Refactor [CS][DX] Refactor Fix taxon tree dropdown [Behat] Remove unnecessary step [Behat][Product] Fix and enable adding product with multiple attributes scenario [Admin][Product] Various scenarios fixes More fixes Minor fixes [Admin] Add validation for ratio value [Admin] Twig hooks, refactor [Admin] Refactor context [Admin] Enable behats [ProductOption][Behat] Use product option from sharedStorage Fix behats step Remove unnecessary lines [ProductOption][Behat] minor improvements [Admin][ProductOption][Behat] Change localeCode to locale_code [Admin][ProductOption] Add behat's test for "apply to all" functionality [Admin][Product] Change using live action to new way [Admin][ProductOption] Add apply to all button ...
This commit is contained in:
commit
8ad643977d
94 changed files with 637 additions and 611 deletions
|
|
@ -8,12 +8,12 @@ Feature: Adding a new exchange rate
|
|||
Given the store has currency "US Dollar" and "British Pound"
|
||||
And I am logged in as an administrator
|
||||
|
||||
@todo @ui @api
|
||||
@api @ui
|
||||
Scenario: Adding a new exchange rate
|
||||
When I want to add a new exchange rate
|
||||
And I specify its ratio as 1.20
|
||||
And I specify its ratio as 1.2
|
||||
And I choose "US Dollar" as the source currency
|
||||
And I choose "British Pound" as the target currency
|
||||
And I add it
|
||||
Then I should be notified that it has been successfully created
|
||||
And the exchange rate with ratio 1.20000 between "US Dollar" and "British Pound" should appear in the store
|
||||
And the exchange rate with ratio 1.2 between "US Dollar" and "British Pound" should appear in the store
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ Feature: Browsing exchange rates
|
|||
And the exchange rate of "British Pound" to "Bhutanese Ngultrum" is 2.37
|
||||
And I am logged in as an administrator
|
||||
|
||||
@todo @ui @api
|
||||
@api @ui
|
||||
Scenario: Browsing store's exchange rates
|
||||
When I am browsing exchange rates of the store
|
||||
Then I should see 2 exchange rates on the list
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ Feature: Deleting exchange rates
|
|||
Given the store has currency "US Dollar", "British Pound" and "Bhutanese Ngultrum"
|
||||
And I am logged in as an administrator
|
||||
|
||||
@todo @ui @api
|
||||
@api @ui
|
||||
Scenario: Deleted exchange rate should disappear from the list
|
||||
Given the exchange rate of "US Dollar" to "British Pound" is 1.2
|
||||
When I delete the exchange rate between "US Dollar" and "British Pound"
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ Feature: Deleting multiple exchange rates
|
|||
And the exchange rate of "Polish Zloty" to "Euro" is 0.22
|
||||
And I am logged in as an administrator
|
||||
|
||||
@todo @ui @mink:chromedriver @no-api
|
||||
@no-api @ui @mink:chromedriver
|
||||
Scenario: Deleting multiple exchange rates at once
|
||||
When I browse exchange rates
|
||||
And I check the exchange rate between "Euro" and "British Pound"
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ Feature: Editing exchange rate
|
|||
Given the store has currency "US Dollar" and "British Pound"
|
||||
And I am logged in as an administrator
|
||||
|
||||
@todo @ui @api
|
||||
@api @ui
|
||||
Scenario: Change exchange rate's ratio
|
||||
Given the exchange rate of "US Dollar" to "British Pound" is 1.30
|
||||
And I am editing this exchange rate
|
||||
|
|
@ -17,7 +17,7 @@ Feature: Editing exchange rate
|
|||
Then I should be notified that it has been successfully edited
|
||||
And it should have a ratio of 3.21
|
||||
|
||||
@todo @ui @api
|
||||
@api @ui
|
||||
Scenario: Being unable to change currencies
|
||||
Given the exchange rate of "US Dollar" to "British Pound" is 1.30
|
||||
When I want to edit this exchange rate
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ Feature: Exchange rate validation
|
|||
Given the store has currency "US Dollar" and "British Pound"
|
||||
And I am logged in as an administrator
|
||||
|
||||
@todo @ui @api
|
||||
@api @ui
|
||||
Scenario: Trying to add a new exchange rate without ratio
|
||||
When I want to add a new exchange rate
|
||||
And I choose "US Dollar" as the source currency
|
||||
|
|
@ -18,7 +18,7 @@ Feature: Exchange rate validation
|
|||
Then I should be notified that ratio is required
|
||||
And the exchange rate between "US Dollar" and "British Pound" should not be added
|
||||
|
||||
@todo @ui @api
|
||||
@api @ui
|
||||
Scenario: Trying to add a new exchange rate with negative ratio
|
||||
When I want to add a new exchange rate
|
||||
And I choose "US Dollar" as the source currency
|
||||
|
|
@ -28,7 +28,27 @@ Feature: Exchange rate validation
|
|||
Then I should be notified that the ratio must be greater than zero
|
||||
And the exchange rate between "US Dollar" and "British Pound" should not be added
|
||||
|
||||
@todo @ui @api
|
||||
@api @ui
|
||||
Scenario: Trying to add a new exchange rate with an excessively high ratio
|
||||
When I want to add a new exchange rate
|
||||
And I choose "US Dollar" as the source currency
|
||||
And I choose "British Pound" as the target currency
|
||||
And I specify its ratio as 123450000
|
||||
And I try to add it
|
||||
Then I should be notified that the ratio must be less than 100000
|
||||
And the exchange rate between "US Dollar" and "British Pound" should not be added
|
||||
|
||||
@api @ui
|
||||
Scenario: Trying to add a new exchange rate with an zero ratio
|
||||
When I want to add a new exchange rate
|
||||
And I choose "US Dollar" as the source currency
|
||||
And I choose "British Pound" as the target currency
|
||||
And I specify its ratio as 0
|
||||
And I try to add it
|
||||
Then I should be notified that the ratio must be greater than zero
|
||||
And the exchange rate between "US Dollar" and "British Pound" should not be added
|
||||
|
||||
@api @ui
|
||||
Scenario: Trying to add a new exchange rate with same target currency as source
|
||||
When I want to add a new exchange rate
|
||||
And I specify its ratio as 1.23
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ Feature: Filtering exchange rates by a currency
|
|||
And the exchange rate of "Polish Zloty" to "Euro" is 0.22
|
||||
And I am logged in as an administrator
|
||||
|
||||
@todo @ui @api
|
||||
@api @ui
|
||||
Scenario: Filtering exchange rates by a chosen currency
|
||||
When I browse exchange rates of the store
|
||||
And I choose "Euro" as a currency filter
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ Feature: Inability of adding exchange rates with the same currency pair
|
|||
And the exchange rate of "Euro" to "British Pound" is 1.2
|
||||
And I am logged in as an administrator
|
||||
|
||||
@todo @ui @api
|
||||
@api @ui
|
||||
Scenario: Being prevented from adding an exchange rate for the same currency pair
|
||||
When I want to add a new exchange rate
|
||||
And I specify its ratio as 3.20
|
||||
|
|
@ -20,7 +20,7 @@ Feature: Inability of adding exchange rates with the same currency pair
|
|||
And I should still see one exchange rate on the list
|
||||
And this exchange rate should have a ratio of 1.2
|
||||
|
||||
@todo @ui @api
|
||||
@api @ui
|
||||
Scenario: Being prevented from adding an exchange rate for a reversed currency pair
|
||||
When I want to add a new exchange rate
|
||||
And I specify its ratio as 3.20
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ Feature: Adding a new product option
|
|||
Given the store is available in "English (United States)"
|
||||
And I am logged in as an administrator
|
||||
|
||||
@ui @javascript @todo-api
|
||||
@todo-api @ui @javascript
|
||||
Scenario: Adding a new product option with two required option values
|
||||
When I want to create a new product option
|
||||
And I name it "T-Shirt size" in "English (United States)"
|
||||
|
|
@ -21,7 +21,7 @@ Feature: Adding a new product option
|
|||
And product option "T-Shirt size" should have the "S" option value
|
||||
And product option "T-Shirt size" should have the "M" option value
|
||||
|
||||
@ui @api
|
||||
@api @ui
|
||||
Scenario: Adding a new product option without any option values
|
||||
When I want to create a new product option
|
||||
And I name it "T-Shirt size" in "English (United States)"
|
||||
|
|
@ -31,7 +31,7 @@ Feature: Adding a new product option
|
|||
Then I should be notified that it has been successfully created
|
||||
And the product option "T-Shirt size" should appear in the registry
|
||||
|
||||
@ui @javascript @todo-api
|
||||
@todo-api @ui @javascript
|
||||
Scenario: Adding a new product option with one option value
|
||||
When I want to create a new product option
|
||||
And I name it "T-Shirt size" in "English (United States)"
|
||||
|
|
@ -41,3 +41,20 @@ Feature: Adding a new product option
|
|||
Then I should be notified that it has been successfully created
|
||||
And the product option "T-Shirt size" should appear in the registry
|
||||
And product option "T-Shirt size" should have the "S" option value
|
||||
|
||||
@no-api @ui @javascript
|
||||
Scenario: Adding a new product option with applying option value to all option values
|
||||
Given the store is also available in "Polish (Poland)"
|
||||
When I want to create a new product option
|
||||
And I name it "T-Shirt size" in "English (United States)"
|
||||
And I specify its code as "t_shirt_size"
|
||||
And I add the "S" option value identified by "OV1" in "English (United States)"
|
||||
And I apply the option value identified by 'OV1' in 'English (United States)' to all option values.
|
||||
And I add the "M" option value identified by "OV2" in "English (United States)"
|
||||
And I add it
|
||||
Then I should be notified that it has been successfully created
|
||||
And the product option "T-Shirt size" should appear in the registry
|
||||
And this product option should have the "S" option value in "English (United States)" locale
|
||||
And this product option should have the "S" option value in "Polish (Poland)" locale
|
||||
And this product option should have the "M" option value in "English (United States)" locale
|
||||
But this product option should not have the "M" option value in "Polish (Poland)" locale
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ Feature: Browsing product options
|
|||
As an Administrator
|
||||
I want to be able to browse product options
|
||||
|
||||
@ui @api
|
||||
@api @ui
|
||||
Scenario: Browsing defined product options
|
||||
Given I am logged in as an administrator
|
||||
And the store has a product option "T-Shirt size" with a code "t_shirt_size"
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ Feature: Deleting multiple product options
|
|||
And the store has also a product option "T-Shirt brand"
|
||||
And I am logged in as an administrator
|
||||
|
||||
@ui @mink:chromedriver @no-api
|
||||
@no-api @ui @mink:chromedriver
|
||||
Scenario: Deleting multiple product options at once
|
||||
When I browse product options
|
||||
And I check the "T-Shirt size" product option
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ Feature: Editing product options
|
|||
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 @todo-api
|
||||
@todo-api @ui
|
||||
Scenario: Renaming the product option
|
||||
Given this product option has the "S" option value with code "t_shirt_size_s"
|
||||
And this product option has also the "M" option value with code "t_shirt_size_m"
|
||||
|
|
|
|||
|
|
@ -11,14 +11,14 @@ Feature: Filtering product options
|
|||
And I am logged in as an administrator
|
||||
And I am browsing product options
|
||||
|
||||
@ui @todo-api
|
||||
@todo-api @ui
|
||||
Scenario: Filtering product options by name
|
||||
When I search for product options with "T-Shirt"
|
||||
Then I should see 2 product options in the list
|
||||
And the product option "T-Shirt size" should be in the registry
|
||||
And the product option "T-Shirt color" should be in the registry
|
||||
|
||||
@ui @todo-api
|
||||
@todo-api @ui
|
||||
Scenario: Filtering product options by code
|
||||
When I search for product options with "xyz"
|
||||
Then I should see 2 product options in the list
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ Feature: Managing option values of a product option
|
|||
And this product option has also the "M" option value with code "OV2"
|
||||
And I am logged in as an administrator
|
||||
|
||||
@ui @mink:chromedriver @todo-api
|
||||
@todo-api @ui @javascript
|
||||
Scenario: Adding an option value to an existing product option
|
||||
When I want to modify the "T-Shirt size" product option
|
||||
And I add the "L" option value identified by "OV3"
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ Feature: Product option unique code validation
|
|||
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 @api
|
||||
@api @ui
|
||||
Scenario: Trying to add product option with a taken code
|
||||
When I want to create a new product option
|
||||
And I name it "T-Shirt color" in "English (United States)"
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ Feature: Product option validation
|
|||
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 @api
|
||||
@api @ui
|
||||
Scenario: Trying to add a new product option without specifying its code
|
||||
When I want to create a new product option
|
||||
And I name it "T-Shirt size" in "English (United States)"
|
||||
|
|
@ -18,14 +18,14 @@ Feature: Product option validation
|
|||
Then I should be notified that code is required
|
||||
And the product option with name "T-Shirt size" should not be added
|
||||
|
||||
@no-ui @api
|
||||
@api @no-ui
|
||||
Scenario: Trying to add a new product option translation in unexsting locale
|
||||
When I want to modify the "T-Shirt color" product option
|
||||
And I name it "T-Shirt color" in "French (France)"
|
||||
And I try to save my changes
|
||||
Then I should be notified that the locale is not available
|
||||
|
||||
@ui @api
|
||||
@api @ui
|
||||
Scenario: Trying to add a new product option with a too long code
|
||||
When I want to create a new product option
|
||||
And I name it "T-Shirt size" in "English (United States)"
|
||||
|
|
@ -33,7 +33,7 @@ Feature: Product option validation
|
|||
And I try to add it
|
||||
Then I should be notified that code is too long
|
||||
|
||||
@ui @api
|
||||
@api @ui
|
||||
Scenario: Trying to add a new product option without specifying its name
|
||||
When I want to create a new product option
|
||||
And I specify its code as "t_shirt_size"
|
||||
|
|
@ -42,7 +42,7 @@ Feature: Product option validation
|
|||
Then I should be notified that name is required
|
||||
And the product option with code "t_shirt_size" should not be added
|
||||
|
||||
@ui @api
|
||||
@api @ui
|
||||
Scenario: Trying to remove name from an existing product option
|
||||
When I want to modify the "T-Shirt color" product option
|
||||
And I remove its name from "English (United States)" translation
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ Feature: Product option values translation validation
|
|||
And this product option has also the "M" option value with code "OV2"
|
||||
And I am logged in as an administrator
|
||||
|
||||
@no-ui @api
|
||||
@api @no-ui
|
||||
Scenario: Trying to add product option value translation in unexisting locale
|
||||
When I want to modify the "T-Shirt size" product option
|
||||
And I add the "X" option value identified by "OV3" in "French (France)"
|
||||
|
|
|
|||
|
|
@ -10,20 +10,20 @@ Feature: Sorting listed product options by position
|
|||
And the store has also a product option "Mug type" at position 1
|
||||
And I am logged in as an administrator
|
||||
|
||||
@ui @api
|
||||
@api @ui
|
||||
Scenario: Product options are sorted by position in ascending order by default
|
||||
When I browse product options
|
||||
Then I should see 3 product options in the list
|
||||
And the first product option in the list should have name "Mug size"
|
||||
And the last product option in the list should have name "Mug color"
|
||||
|
||||
@ui @api
|
||||
@api @ui
|
||||
Scenario: Product option added at no position is added as the last one
|
||||
Given the store has a product option "Mug shape"
|
||||
When I browse product options
|
||||
Then the last product option in the list should have name "Mug shape"
|
||||
|
||||
@ui @api
|
||||
@api @ui
|
||||
Scenario: Product option added at position 0 is added as the first one
|
||||
Given the store has a product option "Mug shape" at position 0
|
||||
When I browse product options
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ Feature: Accessing a store's product page
|
|||
And I am logged in as an administrator
|
||||
And I am using "Polish (Poland)" locale for my panel
|
||||
|
||||
@todo @ui @no-api
|
||||
@no-api @ui
|
||||
Scenario: Accessing the product shop page from the admin panel when the product has a translation with a defined slug in the administrator's chosen language
|
||||
Given the locale "Polish (Poland)" is enabled
|
||||
And this product is named "Bulldog francuski T-Shirt" in the "Polish (Poland)" locale
|
||||
|
|
@ -18,7 +18,7 @@ Feature: Accessing a store's product page
|
|||
Then the show product's page button should be enabled
|
||||
And it should be leading to the product's page in the "Polish (Poland)" locale
|
||||
|
||||
@todo @ui @no-api
|
||||
@no-api @ui
|
||||
Scenario: Accessing the product shop page from the admin panel when the product has a translation with a defined slug in the default channel's language
|
||||
Given the locale "French (France)" is enabled
|
||||
And this product is named "Tee-shirt bouledogue français" in the "French (France)" locale
|
||||
|
|
@ -26,7 +26,7 @@ Feature: Accessing a store's product page
|
|||
Then the show product's page button should be enabled
|
||||
And it should be leading to the product's page in the "German (Germany)" locale
|
||||
|
||||
@todo @ui @no-api
|
||||
@no-api @ui
|
||||
Scenario: Accessing the product shop page from the admin panel with using first available locale with slug and enabled in the channel
|
||||
Given the locale "French (France)" is enabled
|
||||
And the store also operates in "French (France)" locale
|
||||
|
|
@ -36,7 +36,7 @@ Feature: Accessing a store's product page
|
|||
Then the show product's page button should be enabled
|
||||
And it should be leading to the product's page in the "French (France)" locale
|
||||
|
||||
@todo @ui @no-api
|
||||
@no-api @ui
|
||||
Scenario: Not being able to access the product shop page from the admin panel when the product has no translations meeting the criteria
|
||||
Given this product has no translations with a defined slug
|
||||
When I want to edit this product
|
||||
|
|
|
|||
|
|
@ -10,19 +10,19 @@ Feature: Accessing the variants management from the product edit page
|
|||
And this product has option "Model" with values "RS6" and "RS7"
|
||||
And I am logged in as an administrator
|
||||
|
||||
@todo @ui @no-api
|
||||
@no-api @ui
|
||||
Scenario: Being able to access the variants list page
|
||||
When I modify the "Audi" product
|
||||
And I go to the variants list
|
||||
Then I should be on the list of this product's variants
|
||||
|
||||
@todo @ui @no-api
|
||||
@no-api @ui
|
||||
Scenario: Being able to access the variant creation page
|
||||
When I modify the "Audi" product
|
||||
And I go to the variant creation page
|
||||
Then I should be on the variant creation page for this product
|
||||
|
||||
@todo @ui @no-api
|
||||
@no-api @ui
|
||||
Scenario: Being able to access the variant generation page
|
||||
When I modify the "Audi" product
|
||||
And I go to the variant generation page
|
||||
|
|
|
|||
|
|
@ -10,11 +10,14 @@ Feature: Adding a new integer product attribute
|
|||
And the store has a non-translatable text product attribute "ISBN"
|
||||
And I am logged in as an administrator
|
||||
|
||||
@todo @ui @javascript @api
|
||||
@api @ui @mink:chromedriver
|
||||
Scenario: Adding two text attributes to a product
|
||||
When I want to create a new configurable product
|
||||
And I specify its code as "HARRY_POTTER_1"
|
||||
And I name it "Harry Potter and the Sorcerer's Stone" in "English (United States)"
|
||||
And I name it "Harry Potter and the Sorcerer's Stone" in "English (United States)" locale
|
||||
And I generate its slug in "English (United States)" locale
|
||||
And I add the "Author" attribute
|
||||
And I add the "ISBN" attribute
|
||||
And I set its non-translatable "Author" attribute to "J.K. Rowling"
|
||||
And I set its non-translatable "ISBN" attribute to "978-1338878929"
|
||||
And I add it
|
||||
|
|
|
|||
|
|
@ -8,12 +8,12 @@ Feature: Adding a product with only original price
|
|||
Given the store operates on a single channel in "United States"
|
||||
And I am logged in as an administrator
|
||||
|
||||
@todo @ui @no-api
|
||||
@no-api @ui
|
||||
Scenario: Adding a new simple product without price
|
||||
When I want to create a new simple product
|
||||
And I specify its code as "BOARD_DICE_BREWING"
|
||||
And I name it "Dice Brewing" in "English (United States)"
|
||||
And I set its slug to "games/Dice-brewing" in "English (United States)"
|
||||
And I name it "Dice Brewing" in "English (United States)" locale
|
||||
And I set its slug to "games/Dice-brewing" in "English (United States)" locale
|
||||
And I set its original price to "$100.00" for "United States" channel
|
||||
And I add it
|
||||
Then I should be notified that it has been successfully created
|
||||
|
|
|
|||
|
|
@ -10,11 +10,11 @@ Feature: Adding product with prices for multiple channels
|
|||
And the store operates on another channel named "Web-GB" in "GBP" currency
|
||||
And I am logged in as an administrator
|
||||
|
||||
@todo @ui @no-api
|
||||
@no-api @ui
|
||||
Scenario: Configure prices for each channel and currency while adding a new simple product
|
||||
When I want to create a new simple product
|
||||
And I specify its code as "BOARD_DICE_BREWING"
|
||||
And I name it "Dice Brewing" in "English (United States)"
|
||||
And I name it "Dice Brewing" in "English (United States)" locale
|
||||
And I set its price to "$10.00" for "Web-US" channel
|
||||
And I set its price to "£5.00" for "Web-GB" channel
|
||||
And I set its slug to "dice-brewing"
|
||||
|
|
@ -23,21 +23,21 @@ Feature: Adding product with prices for multiple channels
|
|||
And product "Dice Brewing" should be priced at $10.00 for channel "Web-US"
|
||||
And product "Dice Brewing" should be priced at £5.00 for channel "Web-GB"
|
||||
|
||||
@todo @ui @no-api
|
||||
@no-api @ui
|
||||
Scenario: Configure prices for each channel while adding a new simple product
|
||||
When I want to create a new simple product
|
||||
And I specify its code as "BOARD_DICE_BREWING"
|
||||
And I name it "Dice Brewing" in "English (United States)"
|
||||
And I name it "Dice Brewing" in "English (United States)" locale
|
||||
And I make it available in channel "Web-US"
|
||||
And I set its slug to "dice-brewing"
|
||||
And I add it
|
||||
Then I should be notified that price must be defined for every channel
|
||||
|
||||
@todo @ui @no-api
|
||||
@no-api @ui
|
||||
Scenario: Require prices only for chosen channels
|
||||
When I want to create a new simple product
|
||||
And I specify its code as "BOARD_DICE_BREWING"
|
||||
And I name it "Dice Brewing" in "English (United States)"
|
||||
And I name it "Dice Brewing" in "English (United States)" locale
|
||||
And I make it available in channel "Web-US"
|
||||
And I set its price to "$10.00" for "Web-US" channel
|
||||
And I set its slug to "dice-brewing"
|
||||
|
|
@ -45,11 +45,11 @@ Feature: Adding product with prices for multiple channels
|
|||
Then I should be notified that it has been successfully created
|
||||
And product "Dice Brewing" should be priced at $10.00 for channel "Web-US"
|
||||
|
||||
@todo @ui @no-api
|
||||
@no-api @ui
|
||||
Scenario: Require prices for all chosen channels
|
||||
When I want to create a new simple product
|
||||
And I specify its code as "BOARD_DICE_BREWING"
|
||||
And I name it "Dice Brewing" in "English (United States)"
|
||||
And I name it "Dice Brewing" in "English (United States)" locale
|
||||
And I make it available in channel "Web-US"
|
||||
And I make it available in channel "Web-GB"
|
||||
And I set its price to "$10.00" for "Web-US" channel
|
||||
|
|
@ -57,11 +57,11 @@ Feature: Adding product with prices for multiple channels
|
|||
And I add it
|
||||
Then I should be notified that price must be defined for every channel
|
||||
|
||||
@todo @ui @no-api
|
||||
@no-api @ui
|
||||
Scenario: Do not specify price while adding a new simple product
|
||||
When I want to create a new simple product
|
||||
And I specify its code as "BOARD_DICE_BREWING"
|
||||
And I name it "Dice Brewing" in "English (United States)"
|
||||
And I name it "Dice Brewing" in "English (United States)" locale
|
||||
And I set its slug to "dice-brewing"
|
||||
And I add it
|
||||
Then I should be notified that it has been successfully created
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ Feature: Deleting multiple products
|
|||
Given the store has "Audi RS5 model", "Audi RS6 model" and "Audi RS7 model" products
|
||||
And I am logged in as an administrator
|
||||
|
||||
@todo @ui @mink:chromedriver @no-api
|
||||
@no-api @ui @mink:chromedriver
|
||||
Scenario: Deleting multiple products at once
|
||||
When I browse products
|
||||
And I check the "Audi RS5 model" product
|
||||
|
|
|
|||
|
|
@ -10,12 +10,12 @@ Feature: Preventing a potential XSS attack while adding a new product
|
|||
And the store has "No XSS" taxonomy
|
||||
And I am logged in as an administrator
|
||||
|
||||
@ui @mink:chromedriver @no-api
|
||||
@no-api @ui @mink:chromedriver
|
||||
Scenario: Preventing a potential XSS attack while adding new product
|
||||
When I want to create a new simple product
|
||||
Then I should be able to name it "No XSS" in "English (United States)" locale
|
||||
|
||||
@todo @ui @javascript @no-api
|
||||
@no-api @ui @mink:chromedriver
|
||||
Scenario: Preventing a potential XSS attack while choosing main taxon for a new product
|
||||
When I want to create a new simple product
|
||||
Then I should be able to choose main taxon "No XSS"
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ Feature: Removing a product's price after channel deletion
|
|||
And this product is also priced at "£5.00" in "Web-GB" channel
|
||||
And I am logged in as an administrator
|
||||
|
||||
@todo @ui @no-api
|
||||
@no-api @ui
|
||||
Scenario: Removing a product's price after corresponding channel deletion
|
||||
When channel "Web-GB" has been deleted
|
||||
Then product "Dice Brewing" should be priced at $10.00 for channel "Web-US"
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ Feature: Removing a product's price from the channel where it is not available i
|
|||
And this product is disabled in "Web-GB" channel
|
||||
And I am logged in as an administrator
|
||||
|
||||
@todo @ui @no-api
|
||||
@no-api @ui
|
||||
Scenario: Removing a product's price from disabled channel
|
||||
Given the channel "Web-GB" has been disabled
|
||||
When I want to modify the "Dice Brewing" product
|
||||
|
|
@ -22,7 +22,7 @@ Feature: Removing a product's price from the channel where it is not available i
|
|||
Then I should not have configured price for "Web-GB" channel
|
||||
But I should have original price equal to "£70.00" in "Web-GB" channel
|
||||
|
||||
@todo @ui @no-api
|
||||
@no-api @ui
|
||||
Scenario: Removing a product's price from obsolete channel
|
||||
Given this product is disabled in "Web-GB" channel
|
||||
When I want to modify the "Dice Brewing" product
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ Feature: Toggling the inventory tracking
|
|||
Given the store has a product "Dice Brewing"
|
||||
And I am logged in as an administrator
|
||||
|
||||
@todo @ui @no-api
|
||||
@no-api @ui
|
||||
Scenario: Disabling inventory for a simple product
|
||||
Given the "Dice Brewing" product is tracked by the inventory
|
||||
When I want to modify the "Dice Brewing" product
|
||||
|
|
@ -17,7 +17,7 @@ Feature: Toggling the inventory tracking
|
|||
Then I should be notified that it has been successfully edited
|
||||
And inventory of this product should not be tracked
|
||||
|
||||
@todo @ui @no-api
|
||||
@no-api @ui
|
||||
Scenario: Enabling inventory for a simple product
|
||||
When I want to modify the "Dice Brewing" product
|
||||
And I enable its inventory tracking
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
@accessing_edit_page_from_product_show_page
|
||||
Feature: Accessing to product edit page from show page
|
||||
Feature: Accessing the product edit page from the show page
|
||||
In order to edit product in the simple way
|
||||
As an Administrator
|
||||
I want to be able to move to edit page directly from product show page
|
||||
|
|
@ -14,12 +14,12 @@ Feature: Accessing to product edit page from show page
|
|||
|
||||
@todo @ui @no-api
|
||||
Scenario: Accessing to product edit page from product show page
|
||||
When I access the "Iron Shield" product
|
||||
When I access the "Iron shield" product
|
||||
And I go to edit page
|
||||
Then I should be on "Iron shield" product edit page
|
||||
|
||||
@todo @ui @no-api
|
||||
Scenario: Accessing to variant edit page from product show page
|
||||
When I access the "Iron Shield" product
|
||||
When I access the "Iron shield" product
|
||||
And I go to edit page of "Iron shield - very big" variant
|
||||
Then I should be on "Iron shield - very big" variant edit page
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Sylius package.
|
||||
*
|
||||
* (c) Sylius Sp. z o.o.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sylius\Behat\Behaviour;
|
||||
|
||||
trait ChoosesName
|
||||
{
|
||||
use DocumentAccessor;
|
||||
|
||||
public function chooseName(string $name): void
|
||||
{
|
||||
$this->getDocument()->selectFieldOption('Name', $name);
|
||||
}
|
||||
}
|
||||
|
|
@ -22,7 +22,7 @@ use Sylius\Component\Currency\Model\CurrencyInterface;
|
|||
use Sylius\Component\Currency\Model\ExchangeRateInterface;
|
||||
use Webmozart\Assert\Assert;
|
||||
|
||||
final class ManagingExchangeRatesContext implements Context
|
||||
final readonly class ManagingExchangeRatesContext implements Context
|
||||
{
|
||||
public function __construct(
|
||||
private ApiClientInterface $client,
|
||||
|
|
@ -278,6 +278,17 @@ final class ManagingExchangeRatesContext implements Context
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then I should be notified that the ratio must be less than :value
|
||||
*/
|
||||
public function iShouldBeNotifiedThatRatioMustBeLessThan(string $value): void
|
||||
{
|
||||
Assert::contains(
|
||||
$this->responseChecker->getError($this->client->getLastResponse()),
|
||||
sprintf('The ratio must be less than %s.', $value),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then I should be notified that source and target currencies must differ
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -102,19 +102,9 @@ final class ManagingProductOptionsContext implements Context
|
|||
|
||||
/**
|
||||
* @When I add the :value option value identified by :code
|
||||
*/
|
||||
public function iAddTheOptionValueWithCodeAndValue(string $value, string $code): void
|
||||
{
|
||||
$this->client->addSubResourceData(
|
||||
'values',
|
||||
['code' => $code, 'translations' => ['en_US' => ['value' => $value]]],
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When I add the :value option value identified by :code in :localeCode
|
||||
*/
|
||||
public function iAddTheOptionValueWithCodeAndValueInLocale(string $value, string $code, string $localeCode): void
|
||||
public function iAddTheOptionValueWithCodeAndValue(string $value, string $code, string $localeCode = 'en_US'): void
|
||||
{
|
||||
$this->client->addSubResourceData(
|
||||
'values',
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ final readonly class ManagingCustomerGroupsContext implements Context
|
|||
* @When I specify its name as :name
|
||||
* @When I remove its name
|
||||
*/
|
||||
public function iSpecifyItsNameAs(string $name = null): void
|
||||
public function iSpecifyItsNameAs(?string $name = null): void
|
||||
{
|
||||
$this->createPage->nameIt($name ?? '');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,26 +14,28 @@ declare(strict_types=1);
|
|||
namespace Sylius\Behat\Context\Ui\Admin;
|
||||
|
||||
use Behat\Behat\Context\Context;
|
||||
use Sylius\Behat\Page\Admin\ExchangeRate\CreatePageInterface;
|
||||
use Sylius\Behat\Element\Admin\ExchangeRate\FormElementInterface;
|
||||
use Sylius\Behat\Page\Admin\Crud\CreatePageInterface;
|
||||
use Sylius\Behat\Page\Admin\Crud\UpdatePageInterface;
|
||||
use Sylius\Behat\Page\Admin\ExchangeRate\IndexPageInterface;
|
||||
use Sylius\Behat\Page\Admin\ExchangeRate\UpdatePageInterface;
|
||||
use Sylius\Component\Currency\Model\CurrencyInterface;
|
||||
use Sylius\Component\Currency\Model\ExchangeRateInterface;
|
||||
use Webmozart\Assert\Assert;
|
||||
|
||||
final class ManagingExchangeRatesContext implements Context
|
||||
final readonly class ManagingExchangeRatesContext implements Context
|
||||
{
|
||||
public function __construct(
|
||||
private CreatePageInterface $createPage,
|
||||
private IndexPageInterface $indexPage,
|
||||
private UpdatePageInterface $updatePage,
|
||||
private FormElementInterface $formElement,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @When I want to add a new exchange rate
|
||||
*/
|
||||
public function iWantToAddNewExchangeRate()
|
||||
public function iWantToAddNewExchangeRate(): void
|
||||
{
|
||||
$this->createPage->open();
|
||||
}
|
||||
|
|
@ -42,7 +44,7 @@ final class ManagingExchangeRatesContext implements Context
|
|||
* @When /^I want to edit (this exchange rate)$/
|
||||
* @When /^I am editing (this exchange rate)$/
|
||||
*/
|
||||
public function iWantToEditThisExchangeRate(ExchangeRateInterface $exchangeRate)
|
||||
public function iWantToEditThisExchangeRate(ExchangeRateInterface $exchangeRate): void
|
||||
{
|
||||
$this->updatePage->open(['id' => $exchangeRate->getId()]);
|
||||
}
|
||||
|
|
@ -52,7 +54,7 @@ final class ManagingExchangeRatesContext implements Context
|
|||
* @When I browse exchange rates
|
||||
* @When I browse exchange rates of the store
|
||||
*/
|
||||
public function iWantToBrowseExchangeRatesOfTheStore()
|
||||
public function iWantToBrowseExchangeRatesOfTheStore(): void
|
||||
{
|
||||
$this->indexPage->open();
|
||||
}
|
||||
|
|
@ -61,31 +63,31 @@ final class ManagingExchangeRatesContext implements Context
|
|||
* @When /^I specify its ratio as (-?[0-9\.]+)$/
|
||||
* @When I don't specify its ratio
|
||||
*/
|
||||
public function iSpecifyItsRatioAs($ratio = null)
|
||||
public function iSpecifyItsRatioAs(?string $ratio = null): void
|
||||
{
|
||||
$this->createPage->specifyRatio($ratio ?? '');
|
||||
$this->formElement->specifyRatio($ratio ?? '');
|
||||
}
|
||||
|
||||
/**
|
||||
* @When I choose :currencyCode as the source currency
|
||||
*/
|
||||
public function iChooseAsSourceCurrency($currencyCode)
|
||||
public function iChooseAsSourceCurrency(string $currencyCode): void
|
||||
{
|
||||
$this->createPage->chooseSourceCurrency($currencyCode);
|
||||
$this->formElement->specifySourceCurrency($currencyCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When I choose :currencyCode as the target currency
|
||||
*/
|
||||
public function iChooseAsTargetCurrency($currencyCode)
|
||||
public function iChooseAsTargetCurrency(string $currencyCode): void
|
||||
{
|
||||
$this->createPage->chooseTargetCurrency($currencyCode);
|
||||
$this->formElement->specifyTargetCurrency($currencyCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When I( try to) add it
|
||||
*/
|
||||
public function iAddIt()
|
||||
public function iAddIt(): void
|
||||
{
|
||||
$this->createPage->create();
|
||||
}
|
||||
|
|
@ -93,15 +95,15 @@ final class ManagingExchangeRatesContext implements Context
|
|||
/**
|
||||
* @When I change ratio to :ratio
|
||||
*/
|
||||
public function iChangeRatioTo($ratio)
|
||||
public function iChangeRatioTo(string $ratio): void
|
||||
{
|
||||
$this->updatePage->changeRatio($ratio);
|
||||
$this->formElement->specifyRatio($ratio);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When I save my changes
|
||||
*/
|
||||
public function iSaveMyChanges()
|
||||
public function iSaveMyChanges(): void
|
||||
{
|
||||
$this->updatePage->saveChanges();
|
||||
}
|
||||
|
|
@ -109,7 +111,7 @@ final class ManagingExchangeRatesContext implements Context
|
|||
/**
|
||||
* @When I delete the exchange rate between :sourceCurrencyName and :targetCurrencyName
|
||||
*/
|
||||
public function iDeleteTheExchangeRateBetweenAnd($sourceCurrencyName, $targetCurrencyName)
|
||||
public function iDeleteTheExchangeRateBetweenAnd(string $sourceCurrencyName, string $targetCurrencyName): void
|
||||
{
|
||||
$this->indexPage->open();
|
||||
|
||||
|
|
@ -122,7 +124,7 @@ final class ManagingExchangeRatesContext implements Context
|
|||
/**
|
||||
* @When I choose :currencyName as a currency filter
|
||||
*/
|
||||
public function iChooseCurrencyAsACurrencyFilter($currencyName)
|
||||
public function iChooseCurrencyAsACurrencyFilter(string $currencyName): void
|
||||
{
|
||||
$this->indexPage->chooseCurrencyFilter($currencyName);
|
||||
}
|
||||
|
|
@ -130,7 +132,7 @@ final class ManagingExchangeRatesContext implements Context
|
|||
/**
|
||||
* @When I filter
|
||||
*/
|
||||
public function iFilter()
|
||||
public function iFilter(): void
|
||||
{
|
||||
$this->indexPage->filter();
|
||||
}
|
||||
|
|
@ -157,7 +159,7 @@ final class ManagingExchangeRatesContext implements Context
|
|||
/**
|
||||
* @Then I should see :count exchange rates on the list
|
||||
*/
|
||||
public function iShouldSeeExchangeRatesOnTheList($count = 0)
|
||||
public function iShouldSeeExchangeRatesOnTheList(int $count): void
|
||||
{
|
||||
$this->assertCountOfExchangeRatesOnTheList($count);
|
||||
}
|
||||
|
|
@ -166,7 +168,7 @@ final class ManagingExchangeRatesContext implements Context
|
|||
* @Then I should see a single exchange rate in the list
|
||||
* @Then I should( still) see one exchange rate on the list
|
||||
*/
|
||||
public function iShouldSeeOneExchangeRateOnTheList()
|
||||
public function iShouldSeeOneExchangeRateOnTheList(): void
|
||||
{
|
||||
$this->indexPage->open();
|
||||
|
||||
|
|
@ -176,11 +178,14 @@ final class ManagingExchangeRatesContext implements Context
|
|||
/**
|
||||
* @Then the exchange rate with ratio :ratio between :sourceCurrency and :targetCurrency should appear in the store
|
||||
*/
|
||||
public function theExchangeRateBetweenAndShouldAppearInTheStore($ratio, CurrencyInterface $sourceCurrency, CurrencyInterface $targetCurrency)
|
||||
{
|
||||
public function theExchangeRateBetweenAndShouldAppearInTheStore(
|
||||
string $ratio,
|
||||
CurrencyInterface $sourceCurrency,
|
||||
CurrencyInterface $targetCurrency,
|
||||
): void {
|
||||
$this->indexPage->open();
|
||||
|
||||
$this->assertExchangeRateWithRatioIsOnTheList((float) $ratio, $sourceCurrency->getName(), $targetCurrency->getName());
|
||||
$this->assertExchangeRateWithRatioIsOnTheList($ratio, $sourceCurrency->getName(), $targetCurrency->getName());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -200,15 +205,15 @@ final class ManagingExchangeRatesContext implements Context
|
|||
/**
|
||||
* @Then it should have a ratio of :ratio
|
||||
*/
|
||||
public function thisExchangeRateShouldHaveRatioOf($ratio)
|
||||
public function thisExchangeRateShouldHaveRatioOf(string $ratio): void
|
||||
{
|
||||
Assert::eq($this->updatePage->getRatio(), $ratio);
|
||||
Assert::eq($this->formElement->getRatio(), $ratio);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then /^(this exchange rate) should no longer be on the list$/
|
||||
*/
|
||||
public function thisExchangeRateShouldNoLongerBeOnTheList(ExchangeRateInterface $exchangeRate)
|
||||
public function thisExchangeRateShouldNoLongerBeOnTheList(ExchangeRateInterface $exchangeRate): void
|
||||
{
|
||||
$this->assertExchangeRateIsNotOnTheList(
|
||||
$exchangeRate->getSourceCurrency()->getName(),
|
||||
|
|
@ -219,7 +224,7 @@ final class ManagingExchangeRatesContext implements Context
|
|||
/**
|
||||
* @Then the exchange rate between :sourceCurrencyName and :targetCurrencyName should not be added
|
||||
*/
|
||||
public function theExchangeRateBetweenAndShouldNotBeAdded($sourceCurrencyName, $targetCurrencyName)
|
||||
public function theExchangeRateBetweenAndShouldNotBeAdded(string $sourceCurrencyName, string $targetCurrencyName): void
|
||||
{
|
||||
$this->indexPage->open();
|
||||
|
||||
|
|
@ -229,7 +234,7 @@ final class ManagingExchangeRatesContext implements Context
|
|||
/**
|
||||
* @Then /^(this exchange rate) should have a ratio of ([0-9\.]+)$/
|
||||
*/
|
||||
public function thisExchangeRateShouldHaveARatioOf(ExchangeRateInterface $exchangeRate, $ratio)
|
||||
public function thisExchangeRateShouldHaveARatioOf(ExchangeRateInterface $exchangeRate, string $ratio): void
|
||||
{
|
||||
$sourceCurrencyName = $exchangeRate->getSourceCurrency()->getName();
|
||||
$targetCurrencyName = $exchangeRate->getTargetCurrency()->getName();
|
||||
|
|
@ -242,7 +247,7 @@ final class ManagingExchangeRatesContext implements Context
|
|||
*/
|
||||
public function iShouldNotBeAbleToEditItsSourceCurrency(): void
|
||||
{
|
||||
Assert::true($this->updatePage->isSourceCurrencyDisabled());
|
||||
Assert::true($this->formElement->isFieldDisabled('source_currency'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -250,16 +255,16 @@ final class ManagingExchangeRatesContext implements Context
|
|||
*/
|
||||
public function iShouldNotBeAbleToEditItsTargetCurrency(): void
|
||||
{
|
||||
Assert::true($this->updatePage->isTargetCurrencyDisabled());
|
||||
Assert::true($this->formElement->isFieldDisabled('target_currency'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then /^I should be notified that ([^"]+) is required$/
|
||||
*/
|
||||
public function iShouldBeNotifiedThatIsRequired($element)
|
||||
public function iShouldBeNotifiedThatIsRequired(string $element): void
|
||||
{
|
||||
Assert::same(
|
||||
$this->createPage->getValidationMessage($element),
|
||||
$this->formElement->getValidationMessage($element),
|
||||
sprintf('Please enter exchange rate %s.', $element),
|
||||
);
|
||||
}
|
||||
|
|
@ -267,15 +272,23 @@ final class ManagingExchangeRatesContext implements Context
|
|||
/**
|
||||
* @Then I should be notified that the ratio must be greater than zero
|
||||
*/
|
||||
public function iShouldBeNotifiedThatRatioMustBeGreaterThanZero()
|
||||
public function iShouldBeNotifiedThatRatioMustBeGreaterThanZero(): void
|
||||
{
|
||||
Assert::same($this->createPage->getValidationMessage('ratio'), 'The ratio must be greater than 0.');
|
||||
Assert::same($this->formElement->getValidationMessage('ratio'), 'The ratio must be greater than 0.');
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then I should be notified that the ratio must be less than :value
|
||||
*/
|
||||
public function iShouldBeNotifiedThatRatioMustBeLessThan(string $value): void
|
||||
{
|
||||
Assert::same($this->formElement->getValidationMessage('ratio'), sprintf('The ratio must be less than %s.', $value));
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then I should be notified that source and target currencies must differ
|
||||
*/
|
||||
public function iShouldBeNotifiedThatSourceAndTargetCurrenciesMustDiffer()
|
||||
public function iShouldBeNotifiedThatSourceAndTargetCurrenciesMustDiffer(): void
|
||||
{
|
||||
$this->assertFormHasValidationMessage('The source and target currencies must differ.');
|
||||
}
|
||||
|
|
@ -283,23 +296,22 @@ final class ManagingExchangeRatesContext implements Context
|
|||
/**
|
||||
* @Then I should be notified that the currency pair must be unique
|
||||
*/
|
||||
public function iShouldBeNotifiedThatTheCurrencyPairMustBeUnique()
|
||||
public function iShouldBeNotifiedThatTheCurrencyPairMustBeUnique(): void
|
||||
{
|
||||
$this->assertFormHasValidationMessage('The currency pair must be unique.');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param float $ratio
|
||||
* @param string $sourceCurrencyName
|
||||
* @param string $targetCurrencyName
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
private function assertExchangeRateWithRatioIsOnTheList($ratio, $sourceCurrencyName, $targetCurrencyName)
|
||||
{
|
||||
private function assertExchangeRateWithRatioIsOnTheList(
|
||||
string $ratio,
|
||||
string $sourceCurrencyName,
|
||||
string $targetCurrencyName,
|
||||
): void {
|
||||
Assert::true(
|
||||
$this->indexPage->isSingleResourceOnPage([
|
||||
'ratio' => (string) $ratio,
|
||||
'ratio' => $ratio,
|
||||
'sourceCurrency' => $sourceCurrencyName,
|
||||
'targetCurrency' => $targetCurrencyName,
|
||||
]),
|
||||
|
|
@ -313,12 +325,9 @@ final class ManagingExchangeRatesContext implements Context
|
|||
}
|
||||
|
||||
/**
|
||||
* @param string $sourceCurrencyName
|
||||
* @param string $targetCurrencyName
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
private function assertExchangeRateIsNotOnTheList($sourceCurrencyName, $targetCurrencyName)
|
||||
private function assertExchangeRateIsNotOnTheList(string $sourceCurrencyName, string $targetCurrencyName): void
|
||||
{
|
||||
Assert::false(
|
||||
$this->indexPage->isSingleResourceOnPage([
|
||||
|
|
@ -334,28 +343,24 @@ final class ManagingExchangeRatesContext implements Context
|
|||
}
|
||||
|
||||
/**
|
||||
* @param int $count
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
private function assertCountOfExchangeRatesOnTheList($count)
|
||||
private function assertCountOfExchangeRatesOnTheList(int $count): void
|
||||
{
|
||||
Assert::same(
|
||||
$this->indexPage->countItems(),
|
||||
(int) $count,
|
||||
$count,
|
||||
'Expected %2$d exchange rates to be on the list, but found %d instead.',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $expectedMessage
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
private function assertFormHasValidationMessage($expectedMessage)
|
||||
private function assertFormHasValidationMessage(string $expectedMessage): void
|
||||
{
|
||||
Assert::true(
|
||||
$this->createPage->hasFormValidationError($expectedMessage),
|
||||
$this->formElement->hasFormValidationError($expectedMessage),
|
||||
sprintf(
|
||||
'The validation message "%s" was not found on the page.',
|
||||
$expectedMessage,
|
||||
|
|
|
|||
|
|
@ -18,24 +18,26 @@ use Sylius\Behat\Element\Admin\ProductOption\FormElementInterface;
|
|||
use Sylius\Behat\Page\Admin\Crud\CreatePageInterface;
|
||||
use Sylius\Behat\Page\Admin\Crud\IndexPageInterface;
|
||||
use Sylius\Behat\Page\Admin\Crud\UpdatePageInterface;
|
||||
use Sylius\Behat\Service\SharedStorageInterface;
|
||||
use Sylius\Component\Core\Formatter\StringInflector;
|
||||
use Sylius\Component\Product\Model\ProductOptionInterface;
|
||||
use Webmozart\Assert\Assert;
|
||||
|
||||
final class ManagingProductOptionsContext implements Context
|
||||
final readonly class ManagingProductOptionsContext implements Context
|
||||
{
|
||||
public function __construct(
|
||||
private IndexPageInterface $indexPage,
|
||||
private CreatePageInterface $createPage,
|
||||
private UpdatePageInterface $updatePage,
|
||||
private FormElementInterface $formElement,
|
||||
private SharedStorageInterface $sharedStorage,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @When I want to create a new product option
|
||||
*/
|
||||
public function iWantToCreateANewProductOption()
|
||||
public function iWantToCreateANewProductOption(): void
|
||||
{
|
||||
$this->createPage->open();
|
||||
}
|
||||
|
|
@ -43,9 +45,11 @@ final class ManagingProductOptionsContext implements Context
|
|||
/**
|
||||
* @When I want to modify the :productOption product option
|
||||
*/
|
||||
public function iWantToModifyAProductOption(ProductOptionInterface $productOption)
|
||||
public function iWantToModifyAProductOption(ProductOptionInterface $productOption): void
|
||||
{
|
||||
$this->updatePage->open(['id' => $productOption->getId()]);
|
||||
if (!$this->updatePage->isOpen(['id' => $productOption->getId()])) {
|
||||
$this->updatePage->open(['id' => $productOption->getId()]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -60,7 +64,7 @@ final class ManagingProductOptionsContext implements Context
|
|||
* @Given I am browsing product options
|
||||
* @When I browse product options
|
||||
*/
|
||||
public function iBrowseProductOptions()
|
||||
public function iBrowseProductOptions(): void
|
||||
{
|
||||
$this->indexPage->open();
|
||||
}
|
||||
|
|
@ -69,7 +73,7 @@ final class ManagingProductOptionsContext implements Context
|
|||
* @When I add it
|
||||
* @When I try to add it
|
||||
*/
|
||||
public function iAddIt()
|
||||
public function iAddIt(): void
|
||||
{
|
||||
$this->createPage->create();
|
||||
}
|
||||
|
|
@ -78,7 +82,7 @@ final class ManagingProductOptionsContext implements Context
|
|||
* @When I save my changes
|
||||
* @When I try to save my changes
|
||||
*/
|
||||
public function iSaveMyChanges()
|
||||
public function iSaveMyChanges(): void
|
||||
{
|
||||
$this->updatePage->saveChanges();
|
||||
}
|
||||
|
|
@ -86,9 +90,9 @@ final class ManagingProductOptionsContext implements Context
|
|||
/**
|
||||
* @When I name it :name in :language
|
||||
*/
|
||||
public function iNameItInLanguage($name, $language)
|
||||
public function iNameItInLanguage($name, $language): void
|
||||
{
|
||||
$this->formElement->nameItIn($name, $language);
|
||||
$this->formElement->setName($name, $language);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -97,13 +101,13 @@ final class ManagingProductOptionsContext implements Context
|
|||
*/
|
||||
public function iRenameItToInLanguage(string $language, ?string $name = null): void
|
||||
{
|
||||
$this->formElement->nameItIn($name ?? '', $language);
|
||||
$this->formElement->setName($name ?? '', $language);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When I do not name it
|
||||
*/
|
||||
public function iDoNotNameIt()
|
||||
public function iDoNotNameIt(): void
|
||||
{
|
||||
// Intentionally left blank to fulfill context expectation
|
||||
}
|
||||
|
|
@ -119,10 +123,19 @@ final class ManagingProductOptionsContext implements Context
|
|||
|
||||
/**
|
||||
* @When I add the :value option value identified by :code
|
||||
* @When I add the :value option value identified by :code in :localeCode
|
||||
*/
|
||||
public function iAddTheOptionValueWithCodeAndValue(string $value, string $code): void
|
||||
public function iAddTheOptionValueWithCodeAndValue(string $value, string $code, string $localeCode = 'en_US'): void
|
||||
{
|
||||
$this->formElement->addOptionValue($code, $value);
|
||||
$this->formElement->addOptionValue($code, $localeCode, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When I apply the option value identified by :code in :localeCode to all option values.
|
||||
*/
|
||||
public function iApplyToAllTheOptionValueIdentifiedBy(string $code, string $localeCode): void
|
||||
{
|
||||
$this->formElement->applyToAllOptionValues($code, $localeCode);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -130,7 +143,7 @@ final class ManagingProductOptionsContext implements Context
|
|||
*/
|
||||
public function iDeleteTheOptionValueWithCodeAndValue(string $value): void
|
||||
{
|
||||
$this->formElement->removeOptionValue($value);
|
||||
// TODO: Implement deleting option value
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -150,21 +163,22 @@ final class ManagingProductOptionsContext implements Context
|
|||
}
|
||||
|
||||
/**
|
||||
* @Then I should see the product option :productOptionName in the list
|
||||
* @Then the product option :productOptionName should appear in the registry
|
||||
* @Then the product option :productOptionName should be in the registry
|
||||
* @Then I should see the product option :productOption in the list
|
||||
* @Then the product option :productOption should appear in the registry
|
||||
* @Then the product option :productOption should be in the registry
|
||||
*/
|
||||
public function theProductOptionShouldAppearInTheRegistry(string $productOptionName): void
|
||||
public function theProductOptionShouldAppearInTheRegistry(ProductOptionInterface $productOption): void
|
||||
{
|
||||
$this->sharedStorage->set('product_option', $productOption);
|
||||
$this->iBrowseProductOptions();
|
||||
|
||||
Assert::true($this->indexPage->isSingleResourceOnPage(['name' => $productOptionName]));
|
||||
Assert::true($this->indexPage->isSingleResourceOnPage(['name' => $productOption->getName()]));
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then I should be notified that product option with this code already exists
|
||||
*/
|
||||
public function iShouldBeNotifiedThatProductOptionWithThisCodeAlreadyExists()
|
||||
public function iShouldBeNotifiedThatProductOptionWithThisCodeAlreadyExists(): void
|
||||
{
|
||||
Assert::same($this->formElement->getValidationMessage('code'), 'The option with given code already exists.');
|
||||
}
|
||||
|
|
@ -172,7 +186,7 @@ final class ManagingProductOptionsContext implements Context
|
|||
/**
|
||||
* @Then there should still be only one product option with :element :value
|
||||
*/
|
||||
public function thereShouldStillBeOnlyOneProductOptionWith($element, $value)
|
||||
public function thereShouldStillBeOnlyOneProductOptionWith(string $element, string $value): void
|
||||
{
|
||||
$this->iBrowseProductOptions();
|
||||
|
||||
|
|
@ -182,15 +196,15 @@ final class ManagingProductOptionsContext implements Context
|
|||
/**
|
||||
* @Then I should be notified that :element is required
|
||||
*/
|
||||
public function iShouldBeNotifiedThatElementIsRequired($element)
|
||||
public function iShouldBeNotifiedThatElementIsRequired(string $element): void
|
||||
{
|
||||
Assert::same($this->formElement->getValidationMessage($element, ['%localeCode%' => 'en_US']), sprintf('Please enter option %s.', $element));
|
||||
Assert::same($this->formElement->getValidationMessage($element, ['%locale_code%' => 'en_US']), sprintf('Please enter option %s.', $element));
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then the product option with :element :value should not be added
|
||||
*/
|
||||
public function theProductOptionWithElementValueShouldNotBeAdded($element, $value)
|
||||
public function theProductOptionWithElementValueShouldNotBeAdded(string $element, string $value): void
|
||||
{
|
||||
$this->iBrowseProductOptions();
|
||||
|
||||
|
|
@ -201,7 +215,7 @@ final class ManagingProductOptionsContext implements Context
|
|||
* @Then /^(this product option) should still be named "([^"]+)"$/
|
||||
* @Then /^(this product option) name should be "([^"]+)"$/
|
||||
*/
|
||||
public function thisProductOptionNameShouldStillBe(ProductOptionInterface $productOption, $productOptionName)
|
||||
public function thisProductOptionNameShouldStillBe(ProductOptionInterface $productOption, string $productOptionName): void
|
||||
{
|
||||
$this->iBrowseProductOptions();
|
||||
|
||||
|
|
@ -227,14 +241,6 @@ final class ManagingProductOptionsContext implements Context
|
|||
// 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.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then I should see a single product option in the list
|
||||
* @Then I should see :amount product options in the list
|
||||
|
|
@ -247,28 +253,36 @@ final class ManagingProductOptionsContext implements Context
|
|||
/**
|
||||
* @Then /^(this product option) should have the "([^"]*)" option value$/
|
||||
* @Then /^(product option "[^"]+") should have the "([^"]*)" option value$/
|
||||
* @Then /^(this product option) should have the "([^"]*)" option value in ("([^"]+)" locale)$/
|
||||
*/
|
||||
public function thisProductOptionShouldHaveTheOptionValue(ProductOptionInterface $productOption, $optionValue)
|
||||
{
|
||||
public function thisProductOptionShouldHaveTheOptionValue(
|
||||
ProductOptionInterface $productOption,
|
||||
string $optionValue,
|
||||
string $localeCode = 'en_US',
|
||||
): void {
|
||||
$this->iWantToModifyAProductOption($productOption);
|
||||
|
||||
Assert::true($this->formElement->isThereOptionValue($optionValue));
|
||||
Assert::true($this->formElement->hasOptionValue($optionValue, $localeCode));
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then /^(this product option) should not have the "([^"]*)" option value$/
|
||||
* @Then /^(this product option) should not have the "([^"]*)" option value in ("([^"]+)" locale)$/
|
||||
*/
|
||||
public function thisProductOptionShouldNotHaveTheOptionValue(ProductOptionInterface $productOption, string $optionValue): void
|
||||
{
|
||||
public function thisProductOptionShouldNotHaveTheOptionValue(
|
||||
ProductOptionInterface $productOption,
|
||||
string $optionValue,
|
||||
string $localeCode = 'en_US',
|
||||
): void {
|
||||
$this->iWantToModifyAProductOption($productOption);
|
||||
|
||||
Assert::false($this->formElement->isThereOptionValue($optionValue));
|
||||
Assert::false($this->formElement->hasOptionValue($optionValue, $localeCode));
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then the first product option in the list should have :field :value
|
||||
*/
|
||||
public function theFirstProductOptionInTheListShouldHave($field, $value)
|
||||
public function theFirstProductOptionInTheListShouldHave(string $field, string $value): void
|
||||
{
|
||||
Assert::same($this->indexPage->getColumnFields($field)[0], $value);
|
||||
}
|
||||
|
|
@ -276,7 +290,7 @@ final class ManagingProductOptionsContext implements Context
|
|||
/**
|
||||
* @Then the last product option in the list should have :field :value
|
||||
*/
|
||||
public function theLastProductOptionInTheListShouldHave($field, $value)
|
||||
public function theLastProductOptionInTheListShouldHave(string $field, string $value): void
|
||||
{
|
||||
$values = $this->indexPage->getColumnFields($field);
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@ use Webmozart\Assert\Assert;
|
|||
|
||||
final readonly class ManagingTaxCategoriesContext implements Context
|
||||
{
|
||||
|
||||
public function __construct(
|
||||
private IndexPageInterface $indexPage,
|
||||
private CreatePageInterface $createPage,
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ final readonly class ManagingTranslatableEntitiesContext implements Context
|
|||
{
|
||||
Assert::throws(
|
||||
fn () => $this->taxonFormElement->describeItAs('Description', $localeCode),
|
||||
ElementNotFoundException::class
|
||||
ElementNotFoundException::class,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,12 +57,9 @@ class FormElement extends Element implements FormElementInterface
|
|||
*/
|
||||
protected function getDefinedElements(): array
|
||||
{
|
||||
return array_merge(
|
||||
parent::getDefinedElements(),
|
||||
[
|
||||
return array_merge(parent::getDefinedElements(), [
|
||||
'form' => 'form',
|
||||
],
|
||||
);
|
||||
]);
|
||||
}
|
||||
|
||||
protected function waitForFormUpdate(): void
|
||||
|
|
|
|||
|
|
@ -60,5 +60,4 @@ final class FormElement extends BaseFormElement implements FormElementInterface
|
|||
'code' => '[data-test-code]',
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
58
src/Sylius/Behat/Element/Admin/ExchangeRate/FormElement.php
Normal file
58
src/Sylius/Behat/Element/Admin/ExchangeRate/FormElement.php
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Sylius package.
|
||||
*
|
||||
* (c) Sylius Sp. z o.o.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sylius\Behat\Element\Admin\ExchangeRate;
|
||||
|
||||
use Sylius\Behat\Element\Admin\Crud\FormElement as BaseFormElement;
|
||||
|
||||
final class FormElement extends BaseFormElement implements FormElementInterface
|
||||
{
|
||||
public function isFieldDisabled(string $fieldName): bool
|
||||
{
|
||||
return null !== $this->getElement($fieldName)->getAttribute('disabled');
|
||||
}
|
||||
|
||||
public function getRatio(): string
|
||||
{
|
||||
return $this->getElement('ratio')->getValue();
|
||||
}
|
||||
|
||||
public function hasFormValidationError(string $expectedMessage): bool
|
||||
{
|
||||
return $expectedMessage === $this->getValidationErrors();
|
||||
}
|
||||
|
||||
public function specifyRatio(string $ratio): void
|
||||
{
|
||||
$this->getElement('ratio')->setValue($ratio);
|
||||
}
|
||||
|
||||
public function specifySourceCurrency(string $sourceCurrency): void
|
||||
{
|
||||
$this->getElement('source_currency')->setValue($sourceCurrency);
|
||||
}
|
||||
|
||||
public function specifyTargetCurrency(string $targetCurrency): void
|
||||
{
|
||||
$this->getElement('target_currency')->setValue($targetCurrency);
|
||||
}
|
||||
|
||||
protected function getDefinedElements(): array
|
||||
{
|
||||
return array_merge(parent::getDefinedElements(), [
|
||||
'ratio' => '[data-test-ratio]',
|
||||
'source_currency' => '[data-test-source-currency]',
|
||||
'target_currency' => '[data-test-target-currency]',
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Sylius package.
|
||||
*
|
||||
* (c) Sylius Sp. z o.o.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sylius\Behat\Element\Admin\ExchangeRate;
|
||||
|
||||
use Sylius\Behat\Element\Admin\Crud\FormElementInterface as BaseFormElementInterface;
|
||||
|
||||
interface FormElementInterface extends BaseFormElementInterface
|
||||
{
|
||||
public function isFieldDisabled(string $fieldName): bool;
|
||||
|
||||
public function getRatio(): string;
|
||||
|
||||
public function hasFormValidationError(string $expectedMessage): bool;
|
||||
|
||||
public function specifyRatio(string $ratio): void;
|
||||
|
||||
public function specifySourceCurrency(string $sourceCurrency): void;
|
||||
|
||||
public function specifyTargetCurrency(string $targetCurrency): void;
|
||||
}
|
||||
|
|
@ -60,5 +60,4 @@ final class FormElement extends BaseFormElement implements FormElementInterface
|
|||
'code' => '[data-test-code]',
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@ declare(strict_types=1);
|
|||
namespace Sylius\Behat\Element\Admin\Locale;
|
||||
|
||||
use Sylius\Behat\Element\Admin\Crud\FormElementInterface as BaseFormElementInterface;
|
||||
use Sylius\Component\Core\Model\TaxonInterface;
|
||||
|
||||
interface FormElementInterface extends BaseFormElementInterface
|
||||
{
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ final class AttributesFormElement extends BaseFormElement implements AttributesF
|
|||
{
|
||||
$this->changeTab();
|
||||
$this->selectAttributeToBeAdded($attributeName);
|
||||
$this->clickButton('Add');
|
||||
$this->getElement('attribute_add_button')->click();
|
||||
|
||||
$this->waitForFormUpdate();
|
||||
}
|
||||
|
|
@ -40,7 +40,8 @@ final class AttributesFormElement extends BaseFormElement implements AttributesF
|
|||
public function addSelectedAttributes(): void
|
||||
{
|
||||
$this->changeTab();
|
||||
$this->clickButton('Add');
|
||||
$this->getElement('attribute_add_button')->click();
|
||||
|
||||
$this->waitForFormUpdate();
|
||||
}
|
||||
|
||||
|
|
@ -131,9 +132,7 @@ final class AttributesFormElement extends BaseFormElement implements AttributesF
|
|||
|
||||
protected function getDefinedElements(): array
|
||||
{
|
||||
return array_merge(
|
||||
parent::getDefinedElements(),
|
||||
[
|
||||
return array_merge(parent::getDefinedElements(), [
|
||||
'attribute_add_button' => '[data-test-attribute-add-button]',
|
||||
'attribute_autocomplete' => '[data-test-attribute-autocomplete] input[name="product_attributes"]',
|
||||
'attribute_delete_button' => '[data-test-attribute-delete-button="%attribute_name%"]',
|
||||
|
|
@ -141,8 +140,7 @@ final class AttributesFormElement extends BaseFormElement implements AttributesF
|
|||
'attribute_tab' => '[data-test-attribute-tab="%name%"]',
|
||||
'attribute_value' => '[data-test-attribute-value][data-test-locale-code="%locale_code%"][data-test-attribute-name="%attribute_name%"]',
|
||||
'side_navigation_tab' => '[data-test-side-navigation-tab="%name%"]',
|
||||
],
|
||||
);
|
||||
]);
|
||||
}
|
||||
|
||||
private function selectAttributeToBeAdded(string $attributeName): void
|
||||
|
|
@ -162,11 +160,6 @@ final class AttributesFormElement extends BaseFormElement implements AttributesF
|
|||
}
|
||||
}
|
||||
|
||||
private function clickButton(string $locator): void
|
||||
{
|
||||
$this->getElement('attribute_add_button')->click();
|
||||
}
|
||||
|
||||
private function changeTab(): void
|
||||
{
|
||||
if (DriverHelper::isNotJavascript($this->getDriver())) {
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ final class ChannelPricingsFormElement extends BaseFormElement implements Channe
|
|||
|
||||
public function hasNoPriceForChannel(string $channelName): bool
|
||||
{
|
||||
return !str_contains($this->getElement('prices')->getHtml(), $channelName);
|
||||
return !str_contains($this->getElement('channels')->getText(), $channelName);
|
||||
}
|
||||
|
||||
public function getChannelPricingValidationMessage(): string
|
||||
|
|
@ -55,9 +55,7 @@ final class ChannelPricingsFormElement extends BaseFormElement implements Channe
|
|||
|
||||
protected function getDefinedElements(): array
|
||||
{
|
||||
return array_merge(
|
||||
parent::getDefinedElements(),
|
||||
[
|
||||
return array_merge(parent::getDefinedElements(), [
|
||||
'channel' => '[data-test-channel-code="%channel_code%"]',
|
||||
'channel_tab' => '[data-test-channel-tab="%channel_code%"]',
|
||||
'channels' => '[data-test-channels]',
|
||||
|
|
@ -65,8 +63,7 @@ final class ChannelPricingsFormElement extends BaseFormElement implements Channe
|
|||
'price' => '[data-test-price-in-channel="%channel_code%"]',
|
||||
'prices_validation_message' => '[data-test-missing-channel-price]',
|
||||
'side_navigation_tab' => '[data-test-side-navigation-tab="%name%"]',
|
||||
],
|
||||
);
|
||||
]);
|
||||
}
|
||||
|
||||
private function changeChannelTab(string $channelCode): void
|
||||
|
|
|
|||
|
|
@ -14,92 +14,57 @@ declare(strict_types=1);
|
|||
namespace Sylius\Behat\Element\Admin\ProductOption;
|
||||
|
||||
use Behat\Mink\Element\NodeElement;
|
||||
use Behat\Mink\Exception\ElementNotFoundException;
|
||||
use Sylius\Behat\Behaviour\ChecksCodeImmutability;
|
||||
use Sylius\Behat\Behaviour\NamesIt;
|
||||
use Sylius\Behat\Behaviour\SpecifiesItsField;
|
||||
use Sylius\Behat\Element\Admin\Crud\FormElement as BaseFormElement;
|
||||
use Webmozart\Assert\Assert;
|
||||
|
||||
class FormElement extends BaseFormElement implements FormElementInterface
|
||||
{
|
||||
use NamesIt;
|
||||
use SpecifiesItsField;
|
||||
use ChecksCodeImmutability;
|
||||
|
||||
public function addOptionValue(string $code, string $value): void
|
||||
public function setName(string $name, string $localeCode): void
|
||||
{
|
||||
$count = count($this->getProductOptionValues());
|
||||
|
||||
$this->getElement('add_value')->click();
|
||||
$this->getDocument()->waitFor(5, fn () => $count + 1 === count($this->getProductOptionValues()));
|
||||
|
||||
$optionValueForm = $this->getLastOptionValueElement();
|
||||
|
||||
$optionValueForm->fillField('Code', $code);
|
||||
|
||||
$optionValueForm->find('css', '[data-test-option-value-translation]')->setValue($value);
|
||||
$this->getElement('name', ['%locale_code%' => $localeCode])->setValue($name);
|
||||
}
|
||||
|
||||
public function removeOptionValue(string $optionValue): void
|
||||
public function addOptionValue(string $code, string $localeCode, string $value): void
|
||||
{
|
||||
$count = count($this->getProductOptionValues());
|
||||
$this->getElement('add_option_value')->press();
|
||||
$this->waitForFormUpdate();
|
||||
|
||||
$optionValues = $this->getProductOptionValues();
|
||||
|
||||
foreach ($optionValues as $optionValueElement) {
|
||||
if ($optionValueElement->has('css', sprintf('input[value="%s"]', $optionValue))) {
|
||||
$optionValueElement->find('css', '[data-test-delete-value]')->click();
|
||||
|
||||
$this->getDocument()->waitFor(5, fn () => $count - 1 === count($this->getProductOptionValues()));
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
throw new ElementNotFoundException($this->getSession(), 'option value', 'css', sprintf('input[value="%s"]', $optionValue));
|
||||
$lastValue = $this->getElement('last_option_value');
|
||||
$lastValue->find('css', '[data-test-code]')->setValue($code);
|
||||
$lastValue->find('css', sprintf('[id$="_translations_%s_value"]', $localeCode))->setValue($value);
|
||||
$this->waitForFormUpdate();
|
||||
}
|
||||
|
||||
public function nameItIn(string $name, string $localeCode): void
|
||||
public function hasOptionValue(string $optionValue, string $localeCode): bool
|
||||
{
|
||||
$this->getElement('name', ['%localeCode%' => $localeCode])->setValue($name);
|
||||
return $this->hasElement('option_value', ['%option_value%' => $optionValue, '%locale_code%' => $localeCode]);
|
||||
}
|
||||
|
||||
public function isThereOptionValue(string $optionValue): bool
|
||||
public function applyToAllOptionValues(string $code, string $localeCode): void
|
||||
{
|
||||
$optionValues = $this->getElement('values');
|
||||
$this->getElement('apply_to_all', ['%value_code%' => $code, '%locale_code%' => $localeCode])->click();
|
||||
$this->waitForFormUpdate();
|
||||
}
|
||||
|
||||
return $optionValues->has('css', sprintf('input[value="%s"]', $optionValue));
|
||||
protected function getDefinedElements(): array
|
||||
{
|
||||
return array_merge(parent::getDefinedElements(), [
|
||||
'add_option_value' => '[data-test-add-option-value]',
|
||||
'apply_to_all' => '[data-test-option-value="%value_code%"] [data-test-option-value-locale="%locale_code%"] [data-test-apply-to-all]',
|
||||
'code' => '[data-test-code]',
|
||||
'form' => '[data-live-name-value="sylius_admin:product_option:form"]',
|
||||
'last_option_value' => '[data-test-option-values] [data-test-option-value]:last-child',
|
||||
'name' => '#sylius_admin_product_option_translations_%locale_code%_name',
|
||||
'option_value' => '[data-test-option-values] input[id$="_translations_%locale_code%_value"][value="%option_value%"]',
|
||||
]);
|
||||
}
|
||||
|
||||
protected function getCodeElement(): NodeElement
|
||||
{
|
||||
return $this->getElement('code');
|
||||
}
|
||||
|
||||
protected function getDefinedElements(): array
|
||||
{
|
||||
return array_merge(parent::getDefinedElements(), [
|
||||
'add_value' => '[data-test-add-value]',
|
||||
'code' => '[data-test-code]',
|
||||
'name' => '#sylius_admin_product_option_translations_%localeCode%_name',
|
||||
'product_option_value' => '[data-test-product-option-value]',
|
||||
'values' => '[data-test-values]',
|
||||
]);
|
||||
}
|
||||
|
||||
private function getLastOptionValueElement(): NodeElement
|
||||
{
|
||||
$values = $this->getProductOptionValues();
|
||||
|
||||
return end($values);
|
||||
}
|
||||
|
||||
private function getProductOptionValues(): array
|
||||
{
|
||||
$items = $this->getElement('values')->findAll('css', '[data-test-product-option-value]');
|
||||
Assert::isArray($items);
|
||||
|
||||
return $items;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,15 +17,15 @@ use Sylius\Behat\Element\Admin\Crud\FormElementInterface as BaseFormElementInter
|
|||
|
||||
interface FormElementInterface extends BaseFormElementInterface
|
||||
{
|
||||
public function specifyCode(string $code): void;
|
||||
|
||||
public function isCodeDisabled(): bool;
|
||||
|
||||
public function nameItIn(string $name, string $localeCode): void;
|
||||
public function setName(string $name, string $localeCode): void;
|
||||
|
||||
public function isThereOptionValue(string $optionValue): bool;
|
||||
public function addOptionValue(string $code, string $localeCode, string $value): void;
|
||||
|
||||
public function addOptionValue(string $code, string $value): void;
|
||||
public function hasOptionValue(string $optionValue, string $localeCode): bool;
|
||||
|
||||
public function removeOptionValue(string $optionValue): void;
|
||||
|
||||
public function specifyCode(string $code): void;
|
||||
public function applyToAllOptionValues(string $code, string $localeCode): void;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,35 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Sylius package.
|
||||
*
|
||||
* (c) Sylius Sp. z o.o.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sylius\Behat\Page\Admin\Currency;
|
||||
|
||||
use Sylius\Behat\Behaviour\ChoosesName;
|
||||
use Sylius\Behat\Page\Admin\Crud\CreatePage as BaseCreatePage;
|
||||
|
||||
class CreatePage extends BaseCreatePage implements CreatePageInterface
|
||||
{
|
||||
use ChoosesName;
|
||||
|
||||
public function specifyExchangeRate(float $exchangeRate): void
|
||||
{
|
||||
$this->getDocument()->fillField('Exchange rate', $exchangeRate);
|
||||
}
|
||||
|
||||
protected function getDefinedElements(): array
|
||||
{
|
||||
return array_merge(parent::getDefinedElements(), [
|
||||
'code' => '#sylius_admin_currency_code',
|
||||
'exchangeRate' => '#sylius_admin_currency_exchangeRate',
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Sylius package.
|
||||
*
|
||||
* (c) Sylius Sp. z o.o.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sylius\Behat\Page\Admin\Currency;
|
||||
|
||||
use Sylius\Behat\Page\Admin\Crud\CreatePageInterface as BaseCreatePageInterface;
|
||||
|
||||
interface CreatePageInterface extends BaseCreatePageInterface
|
||||
{
|
||||
public function chooseName(string $name): void;
|
||||
|
||||
public function specifyExchangeRate(float $exchangeRate): void;
|
||||
}
|
||||
|
|
@ -1,53 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Sylius package.
|
||||
*
|
||||
* (c) Sylius Sp. z o.o.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sylius\Behat\Page\Admin\ExchangeRate;
|
||||
|
||||
use Sylius\Behat\Page\Admin\Crud\CreatePage as BaseCreatePage;
|
||||
|
||||
class CreatePage extends BaseCreatePage implements CreatePageInterface
|
||||
{
|
||||
public function specifyRatio(string $ratio): void
|
||||
{
|
||||
$this->getDocument()->fillField('Ratio', $ratio);
|
||||
}
|
||||
|
||||
public function chooseSourceCurrency(string $currency): void
|
||||
{
|
||||
$this->getDocument()->selectFieldOption('Source currency', $currency);
|
||||
}
|
||||
|
||||
public function chooseTargetCurrency(string $currency): void
|
||||
{
|
||||
$this->getDocument()->selectFieldOption('Target currency', $currency);
|
||||
}
|
||||
|
||||
public function hasFormValidationError(string $expectedMessage): bool
|
||||
{
|
||||
$formValidationErrors = $this->getDocument()->find('css', 'form > div.ui.red.label.sylius-validation-error');
|
||||
if (null === $formValidationErrors) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $expectedMessage === $formValidationErrors->getText();
|
||||
}
|
||||
|
||||
protected function getDefinedElements(): array
|
||||
{
|
||||
return array_merge(parent::getDefinedElements(), [
|
||||
'source currency' => '#sylius_admin_exchange_rate_sourceCurrency',
|
||||
'target currency' => '#sylius_admin_exchange_rate_targetCurrency',
|
||||
'ratio' => '#sylius_admin_exchange_rate_ratio',
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Sylius package.
|
||||
*
|
||||
* (c) Sylius Sp. z o.o.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sylius\Behat\Page\Admin\ExchangeRate;
|
||||
|
||||
use Sylius\Behat\Page\Admin\Crud\CreatePageInterface as BaseCreatePage;
|
||||
|
||||
interface CreatePageInterface extends BaseCreatePage
|
||||
{
|
||||
public function specifyRatio(string $ratio): void;
|
||||
|
||||
public function chooseSourceCurrency(string $currency): void;
|
||||
|
||||
public function chooseTargetCurrency(string $currency): void;
|
||||
|
||||
public function hasFormValidationError(string $expectedMessage): bool;
|
||||
}
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Sylius package.
|
||||
*
|
||||
* (c) Sylius Sp. z o.o.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sylius\Behat\Page\Admin\ExchangeRate;
|
||||
|
||||
use Sylius\Behat\Page\Admin\Crud\UpdatePage as BaseUpdatePage;
|
||||
|
||||
class UpdatePage extends BaseUpdatePage implements UpdatePageInterface
|
||||
{
|
||||
public function getRatio(): string
|
||||
{
|
||||
return $this->getElement('ratio')->getValue();
|
||||
}
|
||||
|
||||
public function changeRatio(string $ratio): void
|
||||
{
|
||||
$this->getElement('ratio')->setValue($ratio);
|
||||
}
|
||||
|
||||
public function isSourceCurrencyDisabled(): bool
|
||||
{
|
||||
return null !== $this->getElement('sourceCurrency')->getAttribute('disabled');
|
||||
}
|
||||
|
||||
public function isTargetCurrencyDisabled(): bool
|
||||
{
|
||||
return null !== $this->getElement('targetCurrency')->getAttribute('disabled');
|
||||
}
|
||||
|
||||
protected function getDefinedElements(): array
|
||||
{
|
||||
return array_merge(parent::getDefinedElements(), [
|
||||
'ratio' => '#sylius_admin_exchange_rate_ratio',
|
||||
'sourceCurrency' => '#sylius_admin_exchange_rate_sourceCurrency',
|
||||
'targetCurrency' => '#sylius_admin_exchange_rate_targetCurrency',
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Sylius package.
|
||||
*
|
||||
* (c) Sylius Sp. z o.o.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sylius\Behat\Page\Admin\ExchangeRate;
|
||||
|
||||
use Sylius\Behat\Page\Admin\Crud\UpdatePageInterface as BaseUpdatePageInterface;
|
||||
|
||||
interface UpdatePageInterface extends BaseUpdatePageInterface
|
||||
{
|
||||
public function getRatio(): string;
|
||||
|
||||
public function changeRatio(string $ratio): void;
|
||||
|
||||
public function isSourceCurrencyDisabled(): bool;
|
||||
|
||||
public function isTargetCurrencyDisabled(): bool;
|
||||
}
|
||||
|
|
@ -142,17 +142,15 @@ class UpdateSimpleProductPage extends BaseUpdatePage implements UpdateSimpleProd
|
|||
|
||||
protected function getDefinedElements(): array
|
||||
{
|
||||
return array_merge(
|
||||
parent::getDefinedElements(),
|
||||
[
|
||||
'code' => '[data-test-code]',
|
||||
'enabled' => '[data-test-enabled]',
|
||||
'field_shipping_category' => '[name="sylius_admin_product[variant][shippingCategory]"]',
|
||||
'field_shipping_required' => '[name="sylius_admin_product[variant][shippingRequired]"]',
|
||||
'product_translation_accordion' => '[data-test-product-translations-accordion="%localeCode%"]',
|
||||
'show_product_button' => '[data-test-view-in-store]',
|
||||
'side_navigation_tab' => '[data-test-side-navigation-tab="%name%"]',
|
||||
],
|
||||
);
|
||||
return array_merge(parent::getDefinedElements(), [
|
||||
'code' => '[data-test-code]',
|
||||
'enabled' => '[data-test-enabled]',
|
||||
'field_shipping_category' => '[name="sylius_admin_product[variant][shippingCategory]"]',
|
||||
'field_shipping_required' => '[name="sylius_admin_product[variant][shippingRequired]"]',
|
||||
'product_translation_accordion' => '[data-test-product-translations-accordion="%localeCode%"]',
|
||||
'show_product_button' => '[data-test-view-in-store]',
|
||||
'side_navigation_tab' => '[data-test-side-navigation-tab="%name%"]',
|
||||
'tracked' => '[name="sylius_admin_product[variant][tracked]"]',
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -322,7 +322,7 @@ class ShowPage extends SymfonyPage implements ShowPageInterface
|
|||
} while (!$isOpen && microtime(true) < $end);
|
||||
|
||||
if (!$isOpen) {
|
||||
throw new UnexpectedPageException();
|
||||
throw new UnexpectedPageException('Is not open: ' . $e->getMessage() . ' ' . json_encode($urlParameters));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -116,6 +116,7 @@
|
|||
<argument type="service" id="sylius.behat.page.admin.exchange_rate.create" />
|
||||
<argument type="service" id="sylius.behat.page.admin.exchange_rate.index" />
|
||||
<argument type="service" id="sylius.behat.page.admin.exchange_rate.update" />
|
||||
<argument type="service" id="sylius.behat.element.admin.exchange_rate.form" />
|
||||
</service>
|
||||
|
||||
<service id="sylius.behat.context.ui.admin.managing_inventory" class="Sylius\Behat\Context\Ui\Admin\ManagingInventoryContext">
|
||||
|
|
@ -228,6 +229,7 @@
|
|||
<argument type="service" id="sylius.behat.page.admin.product_option.create" />
|
||||
<argument type="service" id="sylius.behat.page.admin.product_option.update" />
|
||||
<argument type="service" id="sylius.behat.element.admin.product_option.form" />
|
||||
<argument type="service" id="sylius.behat.shared_storage" />
|
||||
</service>
|
||||
|
||||
<service id="sylius.behat.context.ui.admin.managing_product_reviews" class="Sylius\Behat\Context\Ui\Admin\ManagingProductReviewsContext">
|
||||
|
|
|
|||
|
|
@ -137,5 +137,12 @@
|
|||
>
|
||||
<argument type="service" id="Sylius\Behat\Service\Helper\AutocompleteHelperInterface" />
|
||||
</service>
|
||||
|
||||
<service
|
||||
id="sylius.behat.element.admin.exchange_rate.form"
|
||||
class="Sylius\Behat\Element\Admin\ExchangeRate\FormElement"
|
||||
parent="sylius.behat.element.admin.crud.form"
|
||||
>
|
||||
</service>
|
||||
</services>
|
||||
</container>
|
||||
|
|
|
|||
|
|
@ -12,16 +12,20 @@
|
|||
-->
|
||||
|
||||
<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.exchange_rate.create.class">%sylius.behat.page.admin.crud.create.class%</parameter>
|
||||
<parameter key="sylius.behat.page.admin.exchange_rate.update.class">%sylius.behat.page.admin.crud.update.class%</parameter>
|
||||
</parameters>
|
||||
<services>
|
||||
<defaults public="true" />
|
||||
|
||||
<service id="sylius.behat.page.admin.exchange_rate.create" class="Sylius\Behat\Page\Admin\ExchangeRate\CreatePage" parent="sylius.behat.page.admin.crud.create" public="false">
|
||||
<service id="sylius.behat.page.admin.exchange_rate.create" class="%sylius.behat.page.admin.exchange_rate.create.class%" parent="sylius.behat.page.admin.crud.create" public="false">
|
||||
<argument type="string">sylius_admin_exchange_rate_create</argument>
|
||||
</service>
|
||||
<service id="sylius.behat.page.admin.exchange_rate.index" class="Sylius\Behat\Page\Admin\ExchangeRate\IndexPage" parent="sylius.behat.page.admin.crud.index" public="false">
|
||||
<argument type="string">sylius_admin_exchange_rate_index</argument>
|
||||
</service>
|
||||
<service id="sylius.behat.page.admin.exchange_rate.update" class="Sylius\Behat\Page\Admin\ExchangeRate\UpdatePage" parent="sylius.behat.page.admin.crud.update" public="false">
|
||||
<service id="sylius.behat.page.admin.exchange_rate.update" class="%sylius.behat.page.admin.exchange_rate.update.class%" parent="sylius.behat.page.admin.crud.update" public="false">
|
||||
<argument type="string">sylius_admin_exchange_rate_update</argument>
|
||||
</service>
|
||||
</services>
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
default:
|
||||
suites:
|
||||
ui_viewing_products:
|
||||
ui_accessing_edit_page_from_product_show_page:
|
||||
contexts:
|
||||
- sylius.behat.context.hook.doctrine_orm
|
||||
- sylius.behat.context.hook.session
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ final class LocaleType extends AbstractType
|
|||
$locale = $event->getData();
|
||||
if ($locale instanceof LocaleInterface && null !== $locale->getCode()) {
|
||||
$options['disabled'] = true;
|
||||
$options['choices'] = [ Locales::getName($locale->getCode()) => $locale->getCode()];
|
||||
$options['choices'] = [Locales::getName($locale->getCode()) => $locale->getCode()];
|
||||
} else {
|
||||
$options['choices'] = array_flip($this->getAvailableLocales());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,14 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Sylius package.
|
||||
*
|
||||
* (c) Sylius Sp. z o.o.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sylius\Bundle\AdminBundle\Provider;
|
||||
|
|
|
|||
|
|
@ -38,3 +38,7 @@ textarea.form-control {
|
|||
border-left-width: 2px;
|
||||
border-left-color: #ff0017;
|
||||
}
|
||||
|
||||
.form-select:disabled {
|
||||
color: var(--tblr-gray-500);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,21 +22,20 @@ twig_hooks:
|
|||
|
||||
'sylius_admin.dashboard.index.content.header':
|
||||
breadcrumbs:
|
||||
template: '@SyliusAdmin/dashboard/index/content/header/breadcrumbs.html.twig'
|
||||
enabled: false
|
||||
title_block:
|
||||
template: '@SyliusAdmin/dashboard/index/content/header/title_block/title.html.twig'
|
||||
channel_selector:
|
||||
component: 'sylius_admin:dashboard:channel_selector'
|
||||
props:
|
||||
channelCode: '@=_context.channel_code'
|
||||
template: '@SyliusAdmin/shared/crud/common/content/header/title_block.html.twig'
|
||||
|
||||
'sylius_admin.dashboard.index.content.header.title_block':
|
||||
title:
|
||||
template: '@SyliusAdmin/shared/crud/common/content/header/title_block/title.html.twig'
|
||||
configuration:
|
||||
title: sylius.ui.dashboard
|
||||
sylius_test_html_attribute: 'dashboard-header'
|
||||
actions:
|
||||
enabled: false
|
||||
component: 'sylius_admin:dashboard:channel_selector'
|
||||
props:
|
||||
channelCode: '@=_context.channel_code'
|
||||
|
||||
'sylius_admin.dashboard.index.content.statistics':
|
||||
statistics_grid:
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
twig_hooks:
|
||||
hooks:
|
||||
'sylius_admin.exchange_rate.create.content':
|
||||
form:
|
||||
template: '@SyliusAdmin/shared/crud/common/content/form.html.twig'
|
||||
configuration:
|
||||
render_rest: false
|
||||
|
||||
'sylius_admin.exchange_rate.create.content.form':
|
||||
sections:
|
||||
template: '@SyliusAdmin/exchange_rate/form/sections.html.twig'
|
||||
|
||||
'sylius_admin.exchange_rate.create.content.form.sections':
|
||||
general:
|
||||
template: '@SyliusAdmin/exchange_rate/form/sections/general.html.twig'
|
||||
|
||||
'sylius_admin.exchange_rate.create.content.form.sections.general':
|
||||
ratio:
|
||||
template: '@SyliusAdmin/exchange_rate/form/sections/general/ratio.html.twig'
|
||||
source_currency:
|
||||
template: '@SyliusAdmin/exchange_rate/form/sections/general/source_currency.html.twig'
|
||||
target_currency:
|
||||
template: '@SyliusAdmin/exchange_rate/form/sections/general/target_currency.html.twig'
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
twig_hooks:
|
||||
hooks:
|
||||
'sylius_admin.exchange_rate.update.content':
|
||||
form:
|
||||
template: '@SyliusAdmin/shared/crud/common/content/form.html.twig'
|
||||
configuration:
|
||||
render_rest: false
|
||||
|
||||
'sylius_admin.exchange_rate.update.content.form':
|
||||
sections:
|
||||
template: '@SyliusAdmin/exchange_rate/form/sections.html.twig'
|
||||
|
||||
'sylius_admin.exchange_rate.update.content.form.sections':
|
||||
general:
|
||||
template: '@SyliusAdmin/exchange_rate/form/sections/general.html.twig'
|
||||
|
||||
'sylius_admin.exchange_rate.update.content.form.sections.general':
|
||||
ratio:
|
||||
template: '@SyliusAdmin/exchange_rate/form/sections/general/ratio.html.twig'
|
||||
source_currency:
|
||||
template: '@SyliusAdmin/exchange_rate/form/sections/general/source_currency.html.twig'
|
||||
target_currency:
|
||||
template: '@SyliusAdmin/exchange_rate/form/sections/general/target_currency.html.twig'
|
||||
|
|
@ -12,11 +12,22 @@ twig_hooks:
|
|||
isSimple: '@=_context.resource.isSimple()'
|
||||
configuration:
|
||||
method: 'PUT'
|
||||
|
||||
|
||||
'sylius_admin.product.update.content.header.title_block.actions':
|
||||
view_in_store:
|
||||
template: '@SyliusAdmin/product/common/header/title_block/actions/view_in_store.html.twig'
|
||||
priority: 32
|
||||
priority: 0
|
||||
manage_variants:
|
||||
template: '@SyliusAdmin/product/common/header/title_block/actions/manage_variants.html.twig'
|
||||
priority: 300
|
||||
|
||||
'sylius_admin.product.update.content.header.title_block.actions.manage_variants':
|
||||
list:
|
||||
template: '@SyliusAdmin/product/common/header/title_block/actions/manage_variants/list.html.twig'
|
||||
create:
|
||||
template: '@SyliusAdmin/product/common/header/title_block/actions/manage_variants/create.html.twig'
|
||||
generate:
|
||||
template: '@SyliusAdmin/product/common/header/title_block/actions/manage_variants/generate.html.twig'
|
||||
|
||||
'sylius_admin.product.update.content.form':
|
||||
side_navigation:
|
||||
|
|
|
|||
|
|
@ -14,9 +14,11 @@ sylius_grid:
|
|||
sortable: ~
|
||||
sourceCurrency:
|
||||
type: string
|
||||
path: sourceCurrency.name
|
||||
label: sylius.ui.source_currency
|
||||
targetCurrency:
|
||||
type: string
|
||||
path: targetCurrency.name
|
||||
label: sylius.ui.target_currency
|
||||
ratio:
|
||||
type: string
|
||||
|
|
|
|||
|
|
@ -9,11 +9,4 @@ sylius_admin_exchange_rate:
|
|||
form:
|
||||
type: Sylius\Bundle\AdminBundle\Form\Type\ExchangeRateType
|
||||
permission: true
|
||||
vars:
|
||||
all:
|
||||
subheader: sylius.ui.manage_exchange_rates
|
||||
templates:
|
||||
form: "@SyliusAdmin/ExchangeRate/_form.html.twig"
|
||||
index:
|
||||
icon: sliders
|
||||
type: sylius.resource
|
||||
|
|
|
|||
|
|
@ -18,6 +18,8 @@ use Sylius\TwigHooks\LiveComponent\HookableLiveComponentTrait;
|
|||
use Symfony\Component\Form\FormFactoryInterface;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\UX\LiveComponent\Attribute\AsLiveComponent;
|
||||
use Symfony\UX\LiveComponent\Attribute\LiveAction;
|
||||
use Symfony\UX\LiveComponent\Attribute\LiveArg;
|
||||
use Symfony\UX\LiveComponent\Attribute\LiveProp;
|
||||
use Symfony\UX\LiveComponent\DefaultActionTrait;
|
||||
use Symfony\UX\LiveComponent\LiveCollectionTrait;
|
||||
|
|
@ -43,4 +45,14 @@ class FormComponent
|
|||
{
|
||||
return $this->formFactory->create($this->formClass, $this->resource);
|
||||
}
|
||||
|
||||
#[LiveAction]
|
||||
public function applyToAll(#[LiveArg] string $valueKey, #[LiveArg] string $translationKey): void
|
||||
{
|
||||
$value = $this->formValues['values'][$valueKey]['translations'][$translationKey]['value'];
|
||||
|
||||
foreach ($this->formValues['values'][$valueKey]['translations'] as &$translation) {
|
||||
$translation['value'] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
|||
final class LoggedInAdminUserProviderSpec extends ObjectBehavior
|
||||
{
|
||||
private const SECURITY_SESSION_KEY = '_security_admin';
|
||||
|
||||
private const SERIALIZED_TOKEN = 'O:74:"Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken":3:{i:0;N;i:1;s:5:"admin";i:2;a:5:{i:0;O:37:"Sylius\Component\Core\Model\AdminUser":8:{i:0;s:38:"sylius{x33enl1y0askgkgw8k0skocc4ko0kg}";i:1;s:30:"x33enl1y0askgkgw8k0skocc4ko0kg";i:2;s:6:"sylius";i:3;s:6:"sylius";i:4;b:0;i:5;b:1;i:6;i:404;i:7;s:9:"plaintext";}i:1;b:1;i:2;N;i:3;a:0:{}i:4;a:1:{i:0;s:26:"ROLE_ADMINISTRATION_ACCESS";}}}';
|
||||
|
||||
function let(
|
||||
|
|
|
|||
|
|
@ -1,13 +1,12 @@
|
|||
{# Rendered with \Sylius\Bundle\AdminBundle\Twig\Component\Dashboard\ChannelSelectorComponent #}
|
||||
|
||||
{% if channels|length > 1 %}
|
||||
<div class="d-flex justify-content-end" {{ attributes }}>
|
||||
<div class="col-12 col-md-auto ms-auto d-print-none" {{ attributes }}>
|
||||
<div class="dropdown">
|
||||
<a class="btn btn-secondary dropdown-toggle" href="#" role="button" id="dropdownMenuLink" data-bs-toggle="dropdown" aria-expanded="false" {{ sylius_test_html_attribute('choose-channel-button') }}>
|
||||
{{ channel_name }}
|
||||
</a>
|
||||
|
||||
<ul class="dropdown-menu" aria-labelledby="dropdownMenuLink" {{ sylius_test_html_attribute('choose-channel-list') }}>
|
||||
<ul class="dropdown-menu dropdown-menu-end" aria-labelledby="dropdownMenuLink" {{ sylius_test_html_attribute('choose-channel-list') }}>
|
||||
{% for channel in channels %}
|
||||
<li>
|
||||
<a
|
||||
|
|
|
|||
|
|
@ -1,5 +0,0 @@
|
|||
{% import '@SyliusAdmin/shared/helper/breadcrumbs.html.twig' as _breadcrumbs %}
|
||||
|
||||
{{ _breadcrumbs.default([
|
||||
{ 'name': 'Dashboard', 'active': true },
|
||||
]) }}
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
{% import '@SyliusAdmin/shared/helper/header.html.twig' as _header %}
|
||||
|
||||
<div class="col-12 col-md-6 mb-3 mt-3">
|
||||
<div class="d-md-flex gap-2 align-items-center" {{ sylius_test_html_attribute('dashboard-header') }}>
|
||||
{{ _header.h1('sylius.ui.dashboard'|trans) }}
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -10,29 +10,11 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="d-flex justify-content-end">
|
||||
<div class="d-flex justify-content-end gap-5 mb-3">
|
||||
<div class="btn-group" role="group">
|
||||
<button
|
||||
type="button"
|
||||
class="btn navigation navigation-prev"
|
||||
data-action="live#action"
|
||||
data-live-action-param="prevent|getPreviousPeriod"
|
||||
{{ sylius_test_html_attribute('previous-period') }}
|
||||
>
|
||||
{{ icon({ icon: 'arrow-left', class: 'icon dropdown-item-icon icon-tabler' }) }}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn navigation navigation-prev"
|
||||
data-action="live#action"
|
||||
data-live-action-param="prevent|getNextPeriod"
|
||||
{{ sylius_test_html_attribute('next-period') }}
|
||||
>
|
||||
{{ icon({ icon: 'arrow-right', class: 'icon dropdown-item-icon icon-tabler' }) }}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn {% if period == '2 weeks' %}btn-secondary{% else %}btn-outline-secondary{% endif %}"
|
||||
class="btn {% if period == '2 weeks' %}btn-light border{% endif %}"
|
||||
data-action="live#action"
|
||||
data-live-action-param="prevent|changeRange"
|
||||
data-live-period-param="2 weeks"
|
||||
|
|
@ -42,7 +24,7 @@
|
|||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn {% if period == 'month' %}btn-secondary{% else %}btn-outline-secondary{% endif %}"
|
||||
class="btn {% if period == 'month' %}btn-light border{% endif %}"
|
||||
data-action="live#action"
|
||||
data-live-action-param="prevent|changeRange"
|
||||
data-live-period-param="month"
|
||||
|
|
@ -52,7 +34,7 @@
|
|||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn {% if period == 'year' %}btn-secondary{% else %}btn-outline-secondary{% endif %}"
|
||||
class="btn {% if period == 'year' %}btn-light border{% endif %}"
|
||||
data-action="live#action"
|
||||
data-live-action-param="prevent|changeRange"
|
||||
data-live-period-param="year"
|
||||
|
|
@ -62,6 +44,26 @@
|
|||
{{ 'sylius.ui.statistics.year'|trans }}
|
||||
</button>
|
||||
</div>
|
||||
<div class="btn-group" role="group">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-icon navigation navigation-prev"
|
||||
data-action="live#action"
|
||||
data-live-action-param="prevent|getPreviousPeriod"
|
||||
{{ sylius_test_html_attribute('previous-period') }}
|
||||
>
|
||||
{{ icon({ icon: 'arrow-left', class: 'icon dropdown-item-icon icon-tabler' }) }}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-icon navigation navigation-prev"
|
||||
data-action="live#action"
|
||||
data-live-action-param="prevent|getNextPeriod"
|
||||
{{ sylius_test_html_attribute('next-period') }}
|
||||
>
|
||||
{{ icon({ icon: 'arrow-right', class: 'icon dropdown-item-icon icon-tabler' }) }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="statistics-chart" class="chart-lg" data-intervals="{{ statistics_data.sales_summary.intervals|json_encode }}" data-sales="{{ statistics_data.sales_summary.sales|json_encode }}" data-currency="{{ statistics_data.currency_symbol }}"></div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
<div class="row">
|
||||
{% hook 'sections' %}
|
||||
</div>
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
<div class="col-12 p-2">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<div class="card-title">
|
||||
{{ 'sylius.ui.general'|trans }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row align-items-center">
|
||||
{% hook 'general' %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
<div class="mb-3">
|
||||
{{ form_row(hookable_metadata.context.form.ratio, sylius_test_form_attribute('ratio')) }}
|
||||
</div>
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
<div class="mb-3">
|
||||
{{ form_row(hookable_metadata.context.form.sourceCurrency, sylius_test_form_attribute('source-currency')) }}
|
||||
</div>
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
<div class="mb-3">
|
||||
{{ form_row(hookable_metadata.context.form.targetCurrency, sylius_test_form_attribute('target-currency')) }}
|
||||
</div>
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
<div class="dropdown">
|
||||
<button class="btn dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
{{ 'sylius.ui.manage_variants'|trans }}
|
||||
</button>
|
||||
<ul class="dropdown-menu" {{ sylius_test_html_attribute('manage-variants') }}>
|
||||
{% hook 'manage_variants' %}
|
||||
</ul>
|
||||
</div>
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
{% from '@SyliusAdmin/shared/helper/icon.html.twig' import icon %}
|
||||
|
||||
{% set product = hookable_metadata.context.resource %}
|
||||
|
||||
<li>
|
||||
<a class="dropdown-item" href="{{ path('sylius_admin_product_variant_create', {'productId': product.id}) }}">
|
||||
{{ icon({ icon: 'plus', class: 'icon dropdown-item-icon icon-tabler' }) }}
|
||||
{{ 'sylius.ui.create'|trans }}
|
||||
</a>
|
||||
</li>
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
{% from '@SyliusAdmin/shared/helper/icon.html.twig' import icon %}
|
||||
|
||||
{% set product = hookable_metadata.context.resource %}
|
||||
|
||||
<li>
|
||||
<a class="dropdown-item" href="{{ path('sylius_admin_product_variant_generate', {'productId': product.id}) }}">
|
||||
{{ icon({ icon: 'arrows-split', class: 'icon dropdown-item-icon icon-tabler' }) }}
|
||||
{{ 'sylius.ui.generate'|trans }}
|
||||
</a>
|
||||
</li>
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
{% from '@SyliusAdmin/shared/helper/icon.html.twig' import icon %}
|
||||
|
||||
{% set product = hookable_metadata.context.resource %}
|
||||
|
||||
<li>
|
||||
<a class="dropdown-item" href="{{ path('sylius_admin_product_variant_index', {'productId': product.id}) }}">
|
||||
{{ icon({ icon: 'list-details', class: 'icon dropdown-item-icon icon-tabler' }) }}
|
||||
{{ 'sylius.ui.list_variants'|trans }}
|
||||
</a>
|
||||
</li>
|
||||
|
|
@ -41,7 +41,7 @@
|
|||
{% set url = sylius_channel_url(path('sylius_shop_product_show', {'slug': product_translation.slug, '_locale': product_translation.locale}), channel) %}
|
||||
{% endif %}
|
||||
|
||||
<a class="btn" href="{{ (url is not defined) ? '#' : url|raw }}" target="_blank" {{ sylius_test_html_attribute('view-in-store') }}>
|
||||
<a class="btn {% if url is not defined %}disabled{% endif %}" href="{{ (url is not defined) ? '#' : url|raw }}" target="_blank" {{ sylius_test_html_attribute('view-in-store') }}>
|
||||
{{ _icon({ icon: 'arrow-up-right', class: 'icon icon-tabler' }) }}
|
||||
{{ 'sylius.ui.view_in_store'|trans }}
|
||||
</a>
|
||||
|
|
|
|||
|
|
@ -78,9 +78,12 @@
|
|||
{{ form_label(product_attribute_value.value, null, {label_attr: {class: required_class}}) }}
|
||||
{% if locale_code is not null %}
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-secondary btn-sm"
|
||||
data-action="live#action"
|
||||
data-live-action-param="prevent|applyToAll(attributeCode={{ product_attribute_code }},localeCode={{ product_attribute_value.vars.data.localeCode }})"
|
||||
data-live-action-param="applyToAll"
|
||||
data-live-attribute-code-param="{{ product_attribute_code }}"
|
||||
data-live-locale-code-param="{{ product_attribute_value.vars.data.localeCode }}"
|
||||
>
|
||||
{{ 'sylius.ui.apply_to_all'|trans }}
|
||||
</button>
|
||||
|
|
|
|||
|
|
@ -3,14 +3,13 @@
|
|||
<div class="card-title">{{ 'sylius.ui.values'|trans }}</div>
|
||||
</div>
|
||||
<div class="card-body" >
|
||||
<div class="row" {{ sylius_test_html_attribute('values') }}>
|
||||
<div class="row" {{ sylius_test_html_attribute('option-values') }}>
|
||||
{{ form_errors(hookable_metadata.context.form.values) }}
|
||||
|
||||
{% for value_form in hookable_metadata.context.form.values %}
|
||||
{% hook 'values' with { value_form } %}
|
||||
{% for value_form_key, value_form in hookable_metadata.context.form.values %}
|
||||
{% hook 'values' with { value_form, value_form_key } %}
|
||||
{% endfor %}
|
||||
|
||||
{{ form_row(hookable_metadata.context.form.values.vars.button_add, sylius_test_form_attribute('add-value')) }}
|
||||
</div>
|
||||
{{ form_row(hookable_metadata.context.form.values.vars.button_add, sylius_test_form_attribute('add-option-value')) }}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,9 +1,7 @@
|
|||
<div class="card mb-3">
|
||||
<div class="card-body" {{ sylius_test_html_attribute('product-option-value') }}>
|
||||
<div class="row align-items-end" >
|
||||
<div class="col">
|
||||
{% hook 'value' with { form: hookable_metadata.context.value_form } %}
|
||||
</div>
|
||||
<div class="col-12 col-md-6" {{ sylius_test_html_attribute('option-value', hookable_metadata.context.value_form.code.vars.value) }}>
|
||||
<div class="card mb-3">
|
||||
<div class="card-body">
|
||||
{% hook 'value' with { form: hookable_metadata.context.value_form } %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,25 +1,34 @@
|
|||
{% for translation_form in hookable_metadata.context.value_form.translations %}
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
{% if translation_form.vars.name is not null %}
|
||||
{% from '@SyliusAdmin/shared/helper/icon.html.twig' import icon %}
|
||||
|
||||
{% for translation_form_key, translation_form in hookable_metadata.context.value_form.translations %}
|
||||
<div class="row" {{ sylius_test_html_attribute('option-value-locale', translation_form_key) }}>
|
||||
<div class="col-3">
|
||||
{% if translation_form.vars.name is not null %}
|
||||
<div class="d-flex">
|
||||
<span class="flag flag-sm flag-country-{{ translation_form.vars.name|lower|split('_')|last }} me-2 mt-3"></span>
|
||||
<div class="me-3 mt-1">{{ form_label(translation_form, translation_form.vars.name|sylius_locale_name) }}</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<span class="flag flag-sm flag-country-eu me-3"></span>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<span class="flag flag-sm flag-country-eu me-3"></span>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="col-9">
|
||||
<div class="d-flex">
|
||||
<div class="p-2 w-100">
|
||||
{{ form_widget(
|
||||
translation_form.value,
|
||||
sylius_test_form_attribute('option-value-translation')
|
||||
) }}
|
||||
|
||||
{{ form_errors(translation_form.value) }}
|
||||
</div>
|
||||
<div class="input-group">
|
||||
{{ form_widget(translation_form.value) }}
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-icon"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{{ 'sylius.ui.apply_to_all'|trans }}"
|
||||
data-action="live#action:prevent"
|
||||
data-live-action-param="applyToAll"
|
||||
data-live-value-key-param="{{ hookable_metadata.context.value_form_key }}"
|
||||
data-live-translation-key-param="{{ translation_form_key }}"
|
||||
{{ sylius_test_html_attribute('apply-to-all') }}
|
||||
>
|
||||
{{ icon({ icon: 'duplicate', class: 'icon icon-tabler' }) }}
|
||||
</button>
|
||||
{{ form_errors(translation_form.value) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -7,8 +7,9 @@
|
|||
{% set header = hookable_metadata.configuration.title %}
|
||||
{% endif %}
|
||||
|
||||
{% set test_attribute = hookable_metadata.configuration.sylius_test_html_attribute is defined ? sylius_test_html_attribute(hookable_metadata.configuration.sylius_test_html_attribute) : null %}
|
||||
|
||||
<div class="col-12 col-md">
|
||||
<div class="col-12 col-md" {{ test_attribute }}>
|
||||
<div class="d-md-flex gap-2 align-items-center">
|
||||
{{ _header.h1(header|trans) }}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -371,5 +371,14 @@
|
|||
<path d="M17 17m-2 0a2 2 0 1 0 4 0a2 2 0 1 0 -4 0" />
|
||||
<path d="M5 17h-2v-11a1 1 0 0 1 1 -1h9v12m-4 0h6m4 0h2v-6h-8m0 -5h5l3 5" />
|
||||
{% endif %}
|
||||
|
||||
{% if icon == 'duplicate' %}
|
||||
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
|
||||
<path stroke="none" d="M0 0h24v24H0z"></path>
|
||||
<path d="M7 9.667a2.667 2.667 0 0 1 2.667 -2.667h8.666a2.667 2.667 0 0 1 2.667 2.667v8.666a2.667 2.667 0 0 1 -2.667 2.667h-8.666a2.667 2.667 0 0 1 -2.667 -2.667z"></path>
|
||||
<path d="M4.012 16.737a2 2 0 0 1 -1.012 -1.737v-10c0 -1.1 .9 -2 2 -2h10c.75 0 1.158 .385 1.5 1"></path>
|
||||
<path d="M11 14h6"></path>
|
||||
<path d="M14 11v6"></path>
|
||||
{% endif %}
|
||||
</svg>
|
||||
{% endmacro %}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{% from '@SyliusAdmin/shared/helper/icon.html.twig' import icon %}
|
||||
|
||||
<div class="dropdown">
|
||||
<button class="btn btn-icon btn-sm" type="button" data-bs-toggle="dropdown" {{ sylius_test_html_attribute('actions') }}>
|
||||
<button class="btn btn-icon btn-sm" type="button" data-bs-toggle="dropdown" data-bs-popper-config='{"strategy":"fixed"}' {{ sylius_test_html_attribute('actions') }}>
|
||||
{{ icon({ icon: 'dots', class: 'icon' }) }}
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
|
|
|
|||
|
|
@ -29,6 +29,11 @@
|
|||
<option name="message">sylius.exchange_rate.ratio.greater_than</option>
|
||||
<option name="groups">sylius</option>
|
||||
</constraint>
|
||||
<constraint name="LessThan">
|
||||
<option name="value">100000</option>
|
||||
<option name="groups">sylius</option>
|
||||
<option name="message">sylius.exchange_rate.ratio.less_than</option>
|
||||
</constraint>
|
||||
</property>
|
||||
<property name="sourceCurrency">
|
||||
<constraint name="NotBlank">
|
||||
|
|
|
|||
|
|
@ -8,7 +8,8 @@ sylius:
|
|||
not_blank: Please enter exchange rate.
|
||||
exchange_rate:
|
||||
ratio:
|
||||
greater_than: The ratio must be greater than 0.
|
||||
greater_than: The ratio must be greater than {{ compared_value }}.
|
||||
less_than: The ratio must be less than {{ compared_value }}.
|
||||
invalid: The ratio must be a number.
|
||||
not_blank: Please enter exchange rate ratio.
|
||||
source_currency:
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ final readonly class ErrorTemplateFinder implements ErrorTemplateFinderInterface
|
|||
{
|
||||
public function __construct(
|
||||
private SectionProviderInterface $sectionProvider,
|
||||
private Environment $twig
|
||||
private Environment $twig,
|
||||
) {
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue