Merge branch '2.0' into bootstrap-shop

* 2.0: (115 commits)
  [Admin] Rename parameter
  [Admin] Change command handlers and console command ids to dotted notation
  [Core] Change command handlers and console command ids to dotted notation
  [Core] Use new services
  [Core] Rename Message to Command
  [Admin] Rename Message to Command
  [Promotion] Remove deprecated commands
  [Ui] Remove deprecated commands
  [User] Remove deprecated commands
  [Admin] Configure and use anonymous view in store component
  [Admin] Add missing order notes information
  [Behat] Use test attribute to retrieve order notes
  [Admin] Render pagination and enabled filter test attributes
  [Behat] Enable scenarios and improve implementation for filtered pages redirections
  [Admin] Render view in store button in the variant edit page
  [CS][DX] Refactor
  [Behat] Improve view product in store action
  [Behat] Enable viewing product in store from variant edit page scenarios
  [Behat] Enable deleting multiple product variants scenario
  [Behat] Enable remaining managing users scenario
  ...
This commit is contained in:
Grzegorz Sadowski 2024-08-05 14:20:57 +02:00
commit f27e03497a
No known key found for this signature in database
GPG key ID: EF87FF4E6E3BD364
600 changed files with 3480 additions and 3427 deletions

View file

@ -1,4 +1,4 @@
name: Continuous Integration 1.12 (Full)
name: Continuous Integration 1.14 (Full)
on:
schedule:
@ -17,7 +17,7 @@ jobs:
static-checks:
strategy:
matrix:
branch: [ "1.12" ]
branch: [ "1.14" ]
name: "[${{ matrix.branch }}] Static checks"
uses: ./.github/workflows/ci_static-checks.yaml
with:
@ -26,7 +26,7 @@ jobs:
e2e-mariadb:
strategy:
matrix:
branch: [ "1.12" ]
branch: [ "1.14" ]
name: "[${{ matrix.branch }}] End-to-end tests (MariaDB)"
needs: static-checks
uses: ./.github/workflows/ci_e2e-mariadb.yaml
@ -36,7 +36,7 @@ jobs:
e2e-mysql:
strategy:
matrix:
branch: [ "1.12" ]
branch: [ "1.14" ]
name: "[${{ matrix.branch }}] End-to-end tests (MySQL)"
needs: static-checks
uses: ./.github/workflows/ci_e2e-mysql.yaml
@ -46,7 +46,7 @@ jobs:
e2e-pgsql:
strategy:
matrix:
branch: [ "1.12" ]
branch: [ "1.14" ]
name: "[${{ matrix.branch }}] End-to-end tests (PostgreSQL)"
needs: static-checks
uses: ./.github/workflows/ci_e2e-pgsql.yaml
@ -56,7 +56,7 @@ jobs:
e2e-custom:
strategy:
matrix:
branch: [ "1.12" ]
branch: [ "1.14" ]
name: "[${{ matrix.branch }}] End-to-end tests (Custom)"
needs: static-checks
uses: ./.github/workflows/ci_e2e-custom.yaml
@ -72,7 +72,7 @@ jobs:
packages:
strategy:
matrix:
branch: [ "1.12" ]
branch: [ "1.14" ]
name: "[${{ matrix.branch }}] Packages"
needs: static-checks
uses: ./.github/workflows/ci_packages.yaml

View file

@ -24,8 +24,17 @@ jobs:
outputs:
matrix: ${{ steps.matrix.outputs.prop }}
steps:
- uses: actions/checkout@v4
- name: "Get matrix"
- name: "Checkout (With Branch)"
if: "${{ inputs.branch != '' }}"
uses: actions/checkout@v4
with:
ref: ${{ inputs.branch }}
- name: "Checkout"
uses: actions/checkout@v4
if: "${{ inputs.branch == '' }}"
-
name: "Get matrix"
id: matrix
uses: notiz-dev/github-action-json-property@release
with:

View file

@ -43,6 +43,10 @@
* `sylius.mongodb_odm.repository.class`
* `sylius.phpcr_odm.repository.class`
* The following parameters were renamed:
* `sylius.message.admin_user_create.validation_groups` to `sylius_admin.command_handler.create_admin_user.validation_groups`
* The following configuration options were removed:

View file

@ -12,7 +12,7 @@ Feature: Being redirected to previous filtered page
And the store has a product "Znicz Pruszków T-Shirt"
And I am logged in as an administrator
@todo @ui @no-api
@no-api @ui
Scenario: Being redirected to previous filtered page after deleting a product
When I browse products
And I choose enabled filter
@ -20,7 +20,7 @@ Feature: Being redirected to previous filtered page
And I delete the "FC Barcelona T-Shirt" product on filtered page
Then I should be redirected to the previous page of only enabled products
@todo @ui @no-api
@no-api @ui
Scenario: Being redirected to previous filtered page after cancelling editing a product
When I browse products
And I choose enabled filter
@ -29,7 +29,7 @@ Feature: Being redirected to previous filtered page
And I cancel my changes
Then I should be redirected to the previous page of only enabled products
@todo @ui @no-api
@no-api @ui
Scenario: Being redirected to previous filtered page with pagination after cancelling editing a product
When I browse products
And I choose enabled filter
@ -39,7 +39,7 @@ Feature: Being redirected to previous filtered page
And I cancel my changes
Then I should be redirected to the 2nd page of only enabled products
@todo @ui @no-api
@no-api @ui
Scenario: Being redirected to previous filtered page after cancelling creating a new product
When I browse products
And I choose enabled filter

View file

@ -19,7 +19,7 @@ Feature: Editing product options
Then I should be notified that it has been successfully edited
And this product option name should be "T-Shirt color"
@todo @ui @api
@api @ui
Scenario: Not being able to edit code of an existing product option
When I want to modify the "T-Shirt size" product option
Then I should not be able to edit its code

View file

@ -0,0 +1,22 @@
@managing_product_variants
Feature: Accessing product variants generation
In order to avoid making mistakes when generating product variants
As an Administrator
I want to be able to access the product variants generation page only for products with configured options
Background:
Given the store operates on a single channel in "United States"
And the store has a "Yerba Mate" configurable product
And I am logged in as an administrator
@no-api @ui
Scenario: Being unable to go to the generate variants page for a product without options
When I want to see the list of variants of the "Yerba Mate" product
Then I should not be able to go to the generate variants page
@no-api @ui
Scenario: Being able to go to the generate variants page for a product with options
Given this product has option "Taste" with values "Orange" and "Melon"
When I want to see the list of variants of the "Yerba Mate" product
And I go to generate variants page
Then I should be on the "Yerba Mate" product generate variants page

View file

@ -20,7 +20,7 @@ Feature: Adding a new product variant
And I add it
Then I should be notified that it has been successfully created
And the "VODKA_WYBOROWA_PREMIUM" variant of the "Wyborowa Vodka" product should appear in the store
# And the variant with code "VODKA_WYBOROWA_PREMIUM" should be priced at "$100.00" for channel "United States"
And the variant with code "VODKA_WYBOROWA_PREMIUM" should be priced at "$100.00" for channel "United States"
@api @ui
Scenario: Adding a new product variant with name
@ -34,9 +34,9 @@ Feature: Adding a new product variant
And I add it
Then I should be notified that it has been successfully created
And the "VODKA_WYBOROWA_PREMIUM" variant of the "Wyborowa Vodka" product should appear in the store
# And the variant with code "VODKA_WYBOROWA_PREMIUM" should be priced at "$100.00" for channel "United States"
# And the variant with code "VODKA_WYBOROWA_PREMIUM" should be named "Vodka Wyborowa Premium" in "English (United States)" locale
# And the variant with code "VODKA_WYBOROWA_PREMIUM" should be named "Wódka Wyborowa Premium" in "Polish (Poland)" locale
And the variant with code "VODKA_WYBOROWA_PREMIUM" should be priced at "$100.00" for channel "United States"
And the variant with code "VODKA_WYBOROWA_PREMIUM" should be named "Vodka Wyborowa Premium" in "English (United States)" locale
And the variant with code "VODKA_WYBOROWA_PREMIUM" should be named "Wódka Wyborowa Premium" in "Polish (Poland)" locale
@api @ui
Scenario: Adding a new product variant with specific option's value
@ -69,8 +69,8 @@ Feature: Adding a new product variant
And I add it
Then I should be notified that it has been successfully created
And the "VODKA_WYBOROWA_EXQUISITE" variant of the "Wyborowa Vodka" product should appear in the store
# And the variant with code "VODKA_WYBOROWA_EXQUISITE" should be priced at "$100.00" for channel "United States"
# And the variant with code "VODKA_WYBOROWA_EXQUISITE" should have an original price of "$120.00" for channel "United States"
And the variant with code "VODKA_WYBOROWA_EXQUISITE" should be priced at "$100.00" for channel "United States"
And the variant with code "VODKA_WYBOROWA_EXQUISITE" should have an original price of "$120.00" for channel "United States"
@api @ui
Scenario: Adding a new product variant without shipping required
@ -81,9 +81,9 @@ Feature: Adding a new product variant
And I set its "Taste" option to "Orange"
And I add it
Then I should be notified that it has been successfully created
# And the variant with code "VODKA_WYBOROWA_PREMIUM" should not have shipping required
And the variant with code "VODKA_WYBOROWA_PREMIUM" should not have shipping required
And the "VODKA_WYBOROWA_PREMIUM" variant of the "Wyborowa Vodka" product should appear in the store
# And the variant with code "VODKA_WYBOROWA_PREMIUM" should be priced at "$100.00" for channel "United States"
And the variant with code "VODKA_WYBOROWA_PREMIUM" should be priced at "$100.00" for channel "United States"
@api @ui
Scenario: Adding a new free product variant
@ -94,7 +94,7 @@ Feature: Adding a new product variant
And I add it
Then I should be notified that it has been successfully created
And the "VODKA_WYBOROWA_PREMIUM" variant of the "Wyborowa Vodka" product should appear in the store
# And the variant with code "VODKA_WYBOROWA_PREMIUM" should be priced at "$0.00" for channel "United States"
And the variant with code "VODKA_WYBOROWA_PREMIUM" should be priced at "$0.00" for channel "United States"
@api @ui
Scenario: Adding a new product variant with minimum price
@ -106,5 +106,5 @@ Feature: Adding a new product variant
And I add it
Then I should be notified that it has been successfully created
And the "VODKA_WYBOROWA" variant of the "Wyborowa Vodka" product should appear in the store
# And the variant with code "VODKA_WYBOROWA" should be priced at "$100.00" for channel "United States"
# And the variant with code "VODKA_WYBOROWA" should have minimum price "$50.00" for channel "United States"
And the variant with code "VODKA_WYBOROWA" should be priced at "$100.00" for channel "United States"
And the variant with code "VODKA_WYBOROWA" should have minimum price "$50.00" for channel "United States"

View file

@ -18,4 +18,4 @@ Feature: Adding a product variant with only original price
And I add it
Then I should be notified that it has been successfully created
And the "VODKA_WYBOROWA_DELUX" variant of the "Wyborowa Vodka" product should appear in the store
# And the variant with code "VODKA_WYBOROWA_DELUX" should be originally priced at "$100.00" for channel "United States"
And the variant with code "VODKA_WYBOROWA_DELUX" should be originally priced at "$100.00" for channel "United States"

View file

@ -10,22 +10,22 @@ In order to check a product in shop in all channels it is available in
And the store has a product "Bugatti" available in "United States" channel
And I am logged in as an administrator
@todo @ui @no-api
@no-api @ui
Scenario: Accessing product show page in shop from the product variant edit page where product is available in more than one channel
Given this product is also available in the "Europe" channel
And this product has "Red" variant priced at "$220,000.00" in "Europe" channel
When I want to modify the "Bugatti" product variant
And I choose to show this product in the "Europe" channel
And I choose to show this product in the channel "Europe"
Then I should see this product in the "Europe" channel in the shop
@todo @ui @no-api
@no-api @ui
Scenario: Accessing product show page in shop from the product variant edit page where product is available in one channel
Given this product has "Red" variant priced at "$220,000.00" in "United States" channel
When I want to modify the "Bugatti" product variant
And I choose to show this product in this channel
Then I should see this product in the "United States" channel in the shop
@todo @ui @no-api
@no-api @ui
Scenario: Being unable to access product show page in shop when the product is disabled
Given this product has been disabled
When I want to modify the "Bugatti" product variant

View file

@ -10,7 +10,7 @@ Feature: Deleting multiple product variants
And this product has "Small PHP Mug", "Medium PHP Mug" and "Big PHP Mug" variants
And I am logged in as an administrator
@todo @ui @mink:chromedriver @no-api
@no-api @ui @mink:chromedriver
Scenario: Deleting multiple product variants at once
When I browse variants of this product
And I check the "Small PHP Mug" product variant

View file

@ -15,7 +15,7 @@ Feature: Generating product variant generation
When I want to generate new variants for this product
And I specify that the 1st variant is identified by "WYBOROWA_ORANGE" code
And I try to generate it
Then I should be notified that prices in all channels must be defined for the 1st variant
Then I should be notified that price for the 1st variant in "United States" channel must be defined
And I should not see any variants in the list
@ui @no-api
@ -33,7 +33,7 @@ Feature: Generating product variant generation
And I specify that the 1st variant costs "$90.00" in "United States" channel
And I try to generate it
Then I should be notified that code is required for the 2nd variant
Then I should be notified that prices in all channels must be defined for the 2nd variant
And I should be notified that price for the 2nd variant in "United States" channel must be defined
And I should not see any variants in the list
@ui @no-api
@ -54,9 +54,9 @@ Feature: Generating product variant generation
And I do not specify any information about variants
And I try to generate it
Then I should be notified that code is required for the 1st variant
And I should be notified that prices in all channels must be defined for the 1st variant
And I should be notified that price for the 1st variant in "United States" channel must be defined
And I should be notified that code is required for the 2nd variant
And I should be notified that prices in all channels must be defined for the 2nd variant
And I should be notified that price for the 2nd variant in "United States" channel must be defined
And I should not see any variants in the list
@ui @no-api

View file

@ -15,7 +15,7 @@ Feature: Product variant validation
And I specify its code as "VODKA_WYBOROWA_PREMIUM"
But I do not set its price
And I try to add it
Then I should be notified that prices in all channels must be defined
Then I should be notified that prices in "United States" channel must be defined
And the "VODKA_WYBOROWA_PREMIUM" variant of the "Wyborowa Vodka" product should not appear in the store
@no-ui @api

View file

@ -7,7 +7,6 @@ Feature: Accessing the variants management from the product edit page
Background:
Given the store operates on a single channel in "United States"
And the store has a "Audi" configurable product
And this product has option "Model" with values "RS6" and "RS7"
And I am logged in as an administrator
@no-api @ui
@ -24,6 +23,12 @@ Feature: Accessing the variants management from the product edit page
@no-api @ui
Scenario: Being able to access the variant generation page
Given this product has option "Model" with values "RS6" and "RS7"
When I modify the "Audi" product
And I go to the variant generation page
Then I should be on the variant generation page for this product
@no-api @ui
Scenario: Being unable to go to the generate variants page for a product without options
When I want to modify the "Audi" product
Then I should not be able to go to the generate variants page

View file

@ -31,7 +31,7 @@ Feature: Adding product with prices for multiple channels
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
Then I should be notified that price must be defined for "Web-US" channel
@no-api @ui
Scenario: Require prices only for chosen channels
@ -55,7 +55,7 @@ Feature: Adding product with prices for multiple channels
And I set its price to "$10.00" for "Web-US" channel
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
Then I should be notified that price must be defined for "Web-GB" channel
@no-api @ui
Scenario: Do not specify price while adding a new simple product

View file

@ -85,7 +85,7 @@ Feature: Products validation
And I name it "Dice Brewing" in "English (United States)" locale
And I set its slug to "dice-brewing"
And I try to add it
Then I should be notified that price must be defined for every channel
Then I should be notified that price must be defined for "Web-GB" channel
And product with code "BOARD_DICE_BREWING" should not be added
@ui @api

View file

@ -1,25 +0,0 @@
@accessing_edit_page_from_product_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
Background:
Given the store operates on a single channel in "United States"
And the store has a "Iron shield" configurable product
And the product "Iron shield" has "Iron shield - very big" variant with code "123456789-xl"
And the product "Iron shield" has "Iron shield - very small" variant with code "123456789-xs"
And I am logged in as an administrator
And I am browsing products
@todo @ui @no-api
Scenario: Accessing to product edit page from product show page
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
And I go to edit page of "Iron shield - very big" variant
Then I should be on "Iron shield - very big" variant edit page

View file

@ -11,20 +11,20 @@ Feature: Checking products in the shop while viewing them
And I am logged in as an administrator
And I am browsing products
@ui @no-api
@no-api @ui
Scenario: Accessing product show page in shop from the product show page where product is available in more than one channel
Given this product is available in the "Europe" channel
When I access the "Bugatti" product
And I show this product in the "Europe" channel
Then I should see this product in the "Europe" channel in the shop
@ui @no-api
@no-api @ui
Scenario: Accessing product show page in shop from the product show page where product is available in one channel
When I access the "Bugatti" product
And I show this product in this channel
Then I should see this product in the "Europe" channel in the shop
@ui @no-api
@no-api @ui
Scenario: Being unable to access product show page in shop when the product is disabled
Given this product has been disabled
When I access the "Bugatti" product

View file

@ -0,0 +1,53 @@
@navigating_between_product_show_and_edit_pages
Feature: Navigating between product show and edit pages
In order to navigate between product show and edit pages
As an Administrator
I want to be able to move to edit page directly from product show page and vice versa
Background:
Given the store operates on a single channel in "United States"
And the store has a "Iron sword" product
And the store has a "Iron shield" configurable product
And the product "Iron shield" has "Iron shield - very big" variant with code "123456789-xl"
And the product "Iron shield" has "Iron shield - very small" variant with code "123456789-xs"
And I am logged in as an administrator
@no-api @ui
Scenario: Accessing to product edit page from simple product show page
When I access the "Iron sword" product
And I go to edit page
Then I should be on "Iron sword" product edit page
@no-api @ui
Scenario: Accessing to product edit page from configurable product show page
When I access the "Iron shield" product
And I go to edit page
Then I should be on "Iron shield" product edit page
@no-api @ui
Scenario: Accessing to variant edit page from product show page
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
@no-api @ui
Scenario: Accessing to product show page from simple product edit page
When I want to modify the "Iron sword" product
And I go to show page
Then I should be on "Iron sword" product show page
@no-api @ui
Scenario: Accessing to product show page from configurable product edit page
When I want to modify the "Iron shield" product
And I go to show page
Then I should be on "Iron shield" product show page
@no-api @ui
Scenario: Not being able to access product show page from simple product create page
When I want to create a new simple product
Then I should not be able to open the product show page
@no-api @ui
Scenario: Not being able to access product show page from configurable product create page
When I want to create a new configurable product
Then I should not be able to open the product show page

View file

@ -15,7 +15,7 @@ Feature: Seeing applied catalog promotions details for a simple product
And I am logged in as an administrator
And I am browsing products
@todo @ui @no-api
@no-api @ui
Scenario: Seeing applied catalog promotion details on a simple product
When I access "Ursus C-355" product
Then this product price should be decreased by catalog promotion "Company bankruptcy sale" in "United States" channel

View file

@ -22,7 +22,7 @@ Feature: Seeing applied catalog promotions details within variant
And I am logged in as an administrator
And I am browsing products
@todo @ui @no-api
@no-api @ui
Scenario: Seeing applied catalog promotion details within variant
When I access "Wyborowa Vodka" product
Then "Wyborowa Vodka Exquisite" variant price should be decreased by catalog promotion "Winter sale" in "United States" channel

View file

@ -17,13 +17,13 @@ Feature: Viewing details of a product with variants
And I am logged in as an administrator
And I am browsing products
@todo @ui @no-api
@no-api @ui
Scenario: Viewing a configurable product
When I access the "Iron Shield" product
Then I should see product show page with variants
And I should see product name "Iron Shield"
@todo @ui @api
@api @ui
Scenario: Viewing taxonomies
Given the store classifies its products as "Shield" and "Equipment"
And the product "Iron Shield" has a main taxon "Equipment"
@ -32,32 +32,32 @@ Feature: Viewing details of a product with variants
Then I should see main taxon is "Equipment"
And I should see product taxon "Shield"
@todo @ui @api
@api @ui
Scenario: Viewing options
When I access the "Iron Shield" product
Then I should see option "Shield size"
@todo @ui @api
@api @ui
Scenario: Viewing variants
When I access the "Iron Shield" product
Then I should see 2 variants
And I should see the "Iron Shield - very big" variant
And I should see the "Iron Shield - very small" variant
@todo @ui @no-api
@no-api @ui
Scenario: Viewing variants' details
When I access the "Iron Shield" product
Then I should see 2 variants
And I should see "Iron Shield - very big" variant with code "123456789-xl", priced "$25.00" and current stock 5 and in "United States" channel
And I should see "Iron Shield - very small" variant with code "123456789-xs", priced "$15.00" and current stock 12 and in "United States" channel
@todo @ui @javascript @api
@api @ui @mink:chromedriver
Scenario: Viewing media
Given the "Iron Shield" product has an image "mugs.jpg" with "main" type
When I access the "Iron Shield" product
Then I should see an image related to this product
@todo @ui @api
@api @ui
Scenario: Viewing more details
Given the product "Iron Shield" has the slug "iron-shield"
And the description of product "Iron Shield" is "Shield created by dwarf"
@ -70,14 +70,14 @@ Feature: Viewing details of a product with variants
And I should see product's meta keywords is "shield"
And I should see product's short description is "good shield"
@todo @ui @api
@api @ui
Scenario: Viewing association types
Given the store has a "Glass shield" product
And the product "Iron Shield" has an association "Similar" with product "Glass shield"
When I access the "Iron Shield" product
Then I should see product association type "Similar"
@todo @ui @no-api
@no-api @ui
Scenario: Viewing associations
Given the store has a "Glass shield" product
And the product "Iron Shield" has an association "Similar" with product "Glass shield"

View file

@ -11,21 +11,21 @@ Feature: Viewing details of a simple product
And I am logged in as an administrator
And I am browsing products
@todo @ui @no-api
@no-api @ui
Scenario: Viewing a simple product show page
When I access the "Iron Shield" product
Then I should see product show page without variants
And I should see product name "Iron Shield"
And I should see product breadcrumb "Iron Shield"
@todo @ui @no-api
@no-api @ui
Scenario: Viewing pricing block
Given the product "Iron Shield" has original price "$25.00"
When I access the "Iron Shield" product
Then I should see price "$20.00" for channel "United States"
And I should see original price "$25.00" for channel "United States"
@todo @ui @no-api
@no-api @ui
Scenario: Viewing price block without channel enable
Given this product is unavailable in "United States" channel
When I access the "Iron Shield" product
@ -33,7 +33,7 @@ Feature: Viewing details of a simple product
And I should see the product in neither channel
And I should not see price for channel "United States"
@todo @ui @no-api
@no-api @ui
Scenario: Viewing details block
Given the store has a tax category "No tax" with a code "nt"
And product's "Iron Shield" code is "123456789"
@ -45,7 +45,7 @@ Feature: Viewing details of a simple product
And I should see 4 as a current stock of this product
And I should see product's tax category is "No tax"
@todo @ui @no-api
@no-api @ui
Scenario: Viewing taxonomy block
Given this product belongs to "Shield"
And the product "Iron Shield" has a main taxon "Equipment"
@ -53,7 +53,7 @@ Feature: Viewing details of a simple product
Then I should see main taxon is "Equipment"
And I should see product taxon "Shield"
@todo @ui @no-api
@no-api @ui
Scenario: Viewing shipping block
Given the store has "Over sized" and "Standard" shipping category
And the product "Iron Shield" has height "10.0", width "15.0", depth "20.0", weight "25.0"
@ -65,13 +65,13 @@ Feature: Viewing details of a simple product
And I should see product's depth is 20
And I should see product's weight is 25
@todo @ui @javascript @api
@api @ui @mink:chromedriver
Scenario: Viewing media block
Given the "Iron Shield" product has an image "mugs.jpg" with "main" type
When I access the "Iron Shield" product
Then I should see an image related to this product
@todo @ui @no-api
@no-api @ui
Scenario: Viewing "more details" block
Given the product "Iron Shield" has the slug "iron-shield"
And the description of product "Iron Shield" is "Shield created by dwarf"
@ -84,7 +84,7 @@ Feature: Viewing details of a simple product
And I should see product's meta keywords is "shield"
And I should see product's short description is "good shield"
@todo @ui @no-api
@no-api @ui
Scenario: Viewing associations block
Given the store has "Similar" and "Dwarf equipment" product association types
And the store has a "Glass Shield" product

View file

@ -10,13 +10,13 @@ Feature: Seeing the lowest price before the discount for a simple product
And I am logged in as an administrator
And I am browsing products
@ui @no-api
@no-api @ui
Scenario: Seeing price block with lowest price before the discount
Given this product's price changed to "$21.00" and original price changed to "$37.00"
When I access the "Bizon Z056" product
Then I should see "$42.00" as its lowest price before the discount in "United States" channel
@ui @no-api
@no-api @ui
Scenario: Seeing price block without lowest price before the discount
When I access the "Bizon Z056" product
Then I should not see the lowest price before the discount in "United States" channel

View file

@ -13,7 +13,7 @@ Feature: Seeing the lowest price before the discount within variant
And I am logged in as an administrator
And I am browsing products
@ui @no-api
@no-api @ui
Scenario: Seeing price block with lowest price before the discount within variant
When I access the "Wyborowa Vodka" product
Then I should not see the lowest price before the discount for "Wyborowa Vodka Rye" variant in "United States" channel

View file

@ -14,7 +14,7 @@ Feature: Viewing product's non translatable attributes
And I am logged in as an administrator
And I am browsing products
@todo @ui @api
@api @ui
Scenario: Viewing product's non translatable attributes along with default ones
When I access the "Iron Pickaxe" product
Then I should see non-translatable attribute "crit chance" with value 10%

View file

@ -15,7 +15,7 @@ Feature: Viewing product's attributes in different locales
And I am logged in as an administrator
And I am browsing products
@todo @ui @api
@api @ui
Scenario: Viewing product's attributes defined in different locales
When I access the "Iron Shield" product
Then I should see attribute "material" with value "oak wood" in "English (United States)" locale

View file

@ -8,7 +8,7 @@ Feature: Adding a new shipping category
Given the store operates on a single channel in "United States"
And I am logged in as an administrator
@todo @ui @api
@api @ui
Scenario: Adding a new shipping category with detailed information
When I want to create a new shipping category
And I specify its code as "OVER_SIZED"

View file

@ -9,7 +9,7 @@ Feature: Browsing shipping categories
And the store has "Over sized" and "Standard" shipping category
And I am logged in as an administrator
@todo @ui @api
@api @ui
Scenario: Browsing defined shipping categories
When I browse shipping categories
Then I should see 2 shipping categories in the list

View file

@ -9,7 +9,7 @@ Feature: Deleting multiple shipping categories
And the store has "Big" and "Small" shipping category
And I am logged in as an administrator
@todo @ui @mink:chromedriver @no-api
@no-api @ui @mink:chromedriver
Scenario: Deleting multiple shipping categories at once
When I browse shipping categories
And I check the "Big" shipping category

View file

@ -9,7 +9,7 @@ Feature: Deleting a shipping category
And the store has "Standard" shipping category
And I am logged in as an administrator
@todo @ui @api
@api @ui
Scenario: Deleted shipping category should disappear from the registry
When I delete shipping category "Standard"
Then I should be notified that it has been successfully deleted

View file

@ -9,12 +9,12 @@ Feature: Editing shipping method
And the store has "Standard" shipping category
And I am logged in as an administrator
@todo @ui @api
@api @ui
Scenario: Seeing disabled code field when editing shipping category
When I modify a shipping category "Standard"
Then I should not be able to edit its code
@todo @ui @api
@api @ui
Scenario: Renaming the shipping category
When I want to modify a shipping category "Standard"
And I rename it to "Normal"

View file

@ -9,7 +9,7 @@ Feature: Shipping category unique code validation
And the store has "Standard" shipping category identified by "STANDARD"
And I am logged in as an administrator
@todo @ui @api
@api @ui
Scenario: Trying to add shipping category with taken code
When I want to create a new shipping category
And I specify its code as "STANDARD"

View file

@ -8,7 +8,7 @@ Feature: Shipping category validation
Given the store operates on a single channel in "United States"
And I am logged in as an administrator
@todo @ui @api
@api @ui
Scenario: Trying to add a new shipping category without specifying its code
When I want to create a new shipping category
And I name it "Standard"
@ -17,7 +17,7 @@ Feature: Shipping category validation
Then I should be notified that code is required
And shipping category with name "Standard" should not be added
@todo @ui @api
@api @ui
Scenario: Trying to add a new shipping category with a too long code
When I want to create a new shipping category
And I name it "Standard"
@ -25,7 +25,7 @@ Feature: Shipping category validation
And I try to add it
Then I should be notified that code is too long
@todo @ui @api
@api @ui
Scenario: Trying to add a new shipping category without specifying its name
When I want to create a new shipping category
And I specify its code as "STANDARD"

View file

@ -12,7 +12,7 @@ Feature: Customer group validation
When I want to create a new customer group
And I try to add it
Then I should be notified that name is required
# And I should be informed that this form contains errors #TODO: Uncomment when flash messages are brought back
And I should be informed that this form contains errors
@api @ui
Scenario: Trying to remove name from an existing customer group
@ -21,7 +21,7 @@ Feature: Customer group validation
And I remove its name
And I try to save my changes
Then I should be notified that name is required
# And I should be informed that this form contains errors #TODO: Uncomment when flash messages are brought back
And I should be informed that this form contains errors
And this customer group should still be named "Retail"
@api @ui

View file

@ -9,7 +9,7 @@ Feature: Changing shop user's password
And there is a user "kibsoon@example.com" identified by "goodGuy"
And I am logged in as an administrator
@api @todo @ui
@api @ui
Scenario: Changing a password of a shop user
When I change the password of user "kibsoon@example.com" to "veryGoodGuy"
Then I should be notified that it has been successfully edited

View file

@ -13,7 +13,7 @@ Feature: Leaving additional request notes on my order during checkout
And there is a customer account "customer@example.com" identified by "sylius"
And I am logged in as "customer@example.com"
@todo @ui @api
@api @ui
Scenario: Adding note on the checkout summary step
Given I have product "PHP T-Shirt" in the cart
And I specified the billing address as "Ankh Morpork", "Frost Alley", "90210", "United States" for "Jon Snow"

View file

@ -16,7 +16,7 @@ Feature: Placing an order on a single channel store
And there is a customer account "customer@example.com" identified by "sylius"
And I am logged in as "customer@example.com"
@todo @ui
@api @ui
Scenario: Placing an order in a channels base currency
Given I have product "PHP T-Shirt" in the cart
And I specified the billing address as "Ankh Morpork", "Frost Alley", "90210", "United States" for "Jon Snow"
@ -24,7 +24,7 @@ Feature: Placing an order on a single channel store
And I confirm my order
Then the administrator should see that order placed by "customer@example.com" has "USD" currency
@todo @ui @no-api
@no-api @ui
Scenario: Placing an order in a channels base currency displaying prices in other currency
Given that channel also allows to shop using the "CAD" currency
And I had product "PHP T-Shirt" in the cart

View file

@ -17,7 +17,7 @@ Feature: Placing an order on multiple channels with different currency
And there is a customer account "customer@example.com" identified by "sylius"
And I am logged in as "customer@example.com"
@todo @ui @api
@api @ui
Scenario: Placing an order in a channels base currency
Given I changed my current channel to "United States"
And I have product "PHP T-Shirt" in the cart
@ -26,7 +26,7 @@ Feature: Placing an order on multiple channels with different currency
And I confirm my order
Then the administrator should see that order placed by "customer@example.com" has "USD" currency
@todo @ui @api
@api @ui
Scenario: Placing an order on a different channel with same currency
Given I changed my current channel to "Colombia"
And I had product "PHP T-Shirt" in the cart

View file

@ -17,7 +17,7 @@ Feature: Placing an order on multiple channels with same currency
And there is a customer account "customer@example.com" identified by "sylius"
And I am logged in as "customer@example.com"
@todo @ui
@api @ui
Scenario: Placing an order in a channels base currency
Given I changed my current channel to "Web"
And I have product "PHP T-Shirt" in the cart
@ -26,7 +26,7 @@ Feature: Placing an order on multiple channels with same currency
And I confirm my order
Then the administrator should see that order placed by "customer@example.com" has "USD" currency
@todo @ui
@api @ui
Scenario: Placing an order on a different channel with same currency
Given I changed my current channel to "Mobile"
And I had product "PHP T-Shirt" in the cart

View file

@ -9,13 +9,13 @@ Feature: Applying catalog promotions for product created in catalog promotions s
And the store classifies its products as "Clothes" and "Dishes"
And I am logged in as an administrator
@todo @ui @mink:chromedriver @no-api
@no-api @ui @mink:chromedriver
Scenario: Applying catalog promotion on newly created simple product
Given there is a catalog promotion "Clothes sale" that reduces price by "30%" and applies on "Clothes" taxon
When I create a new simple product "T-Shirt" priced at "$20.00" with "Clothes" taxon in the "United States" channel
Then the visitor should see "$14.00" as the price of the "T-Shirt" product in the "United States" channel
@api @todo @ui
@api @ui
Scenario: Applying catalog promotion on newly created product variant
Given there is a catalog promotion "Clothes sale" that reduces price by "30%" and applies on "Clothes" taxon
And the store has a "T-Shirt" configurable product
@ -23,7 +23,7 @@ Feature: Applying catalog promotions for product created in catalog promotions s
When I create a new "PHP T-Shirt" variant priced at "$20.00" for "T-Shirt" product in the "United States" channel
Then the visitor should see "$14.00" as the price of the "T-Shirt" product in the "United States" channel
@api @todo @ui
@api @ui
Scenario: Not applying catalog promotion on newly created product variant if it's not eligible
Given there is a catalog promotion "Clothes sale" that reduces price by "30%" and applies on "Clothes" taxon
And the store has a "Plate" configurable product

View file

@ -14,12 +14,12 @@ Feature: Not reapplying catalog promotions on variant once its prices changes
And there is disabled catalog promotion "Surprise sale" between "2021-07-01" and "2022-05-04" available in "Web-US" channel that reduces price by "90%" and applies on "PHP T-Shirt" variant
And I am logged in as an administrator
@api @todo @ui
@api @ui
Scenario: Changing the price of the variant
When I change the price of the "PHP T-Shirt" product variant to "$50.00" in "Web-US" channel
Then the visitor should see "$50.00" as the price of the "T-Shirt" product in the "Web-US" channel
@api @todo @ui
@api @ui
Scenario: Changing the original price of the variant
When I change the original price of the "PHP T-Shirt" product variant to "$105.00" in "Web-US" channel
Then the visitor should see "$100.00" as the price of the "T-Shirt" product in the "Web-US" channel

View file

@ -16,14 +16,14 @@ Feature: Not reapplying catalog promotions on variants once the products taxo
And there is disabled catalog promotion "Surprise sale" between "2021-07-01" and "2022-05-04" available in "Web-US" channel that reduces price by "90%" and applies on "Dishes" taxon
And I am logged in as an administrator
@api @todo @ui
@api @ui @mink:chromedriver
Scenario: Changing products taxon to taxon with scheduled catalog promotion
When I change that the "T-Shirt" product does not belong to the "Clothes" taxon
And I add "Shirts" taxon to the "T-Shirt" product
Then the visitor should see that the "PHP T-Shirt" variant is not discounted
And the visitor should still see "$100.00" as the price of the "T-Shirt" product in the "Web-US" channel
@api @todo @ui
@api @ui @mink:chromedriver
Scenario: Changing products taxon to taxon with disabled catalog promotion
When I change that the "T-Shirt" product does not belong to the "Clothes" taxon
And I add "Dishes" taxon to the "T-Shirt" product

View file

@ -100,36 +100,6 @@ parameters:
count: 1
path: src/Sylius/Bundle/AdminBundle/EventListener/ResourceDeleteSubscriber.php
-
message: "#^Method Sylius\\\\Bundle\\\\AdminBundle\\\\Form\\\\Extension\\\\CatalogPromotionActionTypeExtension\\:\\:__construct\\(\\) has parameter \\$actionConfigurationTypes with no value type specified in iterable type iterable\\.$#"
count: 1
path: src/Sylius/Bundle/AdminBundle/Form/Extension/CatalogPromotionActionTypeExtension.php
-
message: "#^Property Sylius\\\\Bundle\\\\AdminBundle\\\\Form\\\\Extension\\\\CatalogPromotionActionTypeExtension\\:\\:\\$actionConfigurationTypes type has no value type specified in iterable type array\\.$#"
count: 1
path: src/Sylius/Bundle/AdminBundle/Form/Extension/CatalogPromotionActionTypeExtension.php
-
message: "#^Property Sylius\\\\Bundle\\\\AdminBundle\\\\Form\\\\Extension\\\\CatalogPromotionActionTypeExtension\\:\\:\\$actionTypes type has no value type specified in iterable type array\\.$#"
count: 1
path: src/Sylius/Bundle/AdminBundle/Form/Extension/CatalogPromotionActionTypeExtension.php
-
message: "#^Method Sylius\\\\Bundle\\\\AdminBundle\\\\Form\\\\Extension\\\\CatalogPromotionScopeTypeExtension\\:\\:__construct\\(\\) has parameter \\$scopeConfigurationTypes with no value type specified in iterable type iterable\\.$#"
count: 1
path: src/Sylius/Bundle/AdminBundle/Form/Extension/CatalogPromotionScopeTypeExtension.php
-
message: "#^Property Sylius\\\\Bundle\\\\AdminBundle\\\\Form\\\\Extension\\\\CatalogPromotionScopeTypeExtension\\:\\:\\$scopeConfigurationTypes type has no value type specified in iterable type array\\.$#"
count: 1
path: src/Sylius/Bundle/AdminBundle/Form/Extension/CatalogPromotionScopeTypeExtension.php
-
message: "#^Property Sylius\\\\Bundle\\\\AdminBundle\\\\Form\\\\Extension\\\\CatalogPromotionScopeTypeExtension\\:\\:\\$scopeTypes type has no value type specified in iterable type array\\.$#"
count: 1
path: src/Sylius/Bundle/AdminBundle/Form/Extension/CatalogPromotionScopeTypeExtension.php
-
message: "#^Method Sylius\\\\Bundle\\\\AdminBundle\\\\Form\\\\RequestPasswordResetType\\:\\:__construct\\(\\) has parameter \\$validationGroups with no value type specified in iterable type array\\.$#"
count: 1
@ -170,11 +140,6 @@ parameters:
count: 1
path: src/Sylius/Bundle/AdminBundle/Menu/ProductVariantFormMenuBuilder.php
-
message: "#^Method Sylius\\\\Bundle\\\\AdminBundle\\\\Menu\\\\PromotionUpdateMenuBuilder\\:\\:createMenu\\(\\) has parameter \\$options with no value type specified in iterable type array\\.$#"
count: 1
path: src/Sylius/Bundle/AdminBundle/Menu/PromotionUpdateMenuBuilder.php
-
message: "#^Method Sylius\\\\Bundle\\\\AdminBundle\\\\Twig\\\\ChannelNameExtension\\:\\:__construct\\(\\) has parameter \\$channelRepository with generic interface Sylius\\\\Component\\\\Channel\\\\Repository\\\\ChannelRepositoryInterface but does not specify its types\\: T$#"
count: 1
@ -595,11 +560,6 @@ parameters:
count: 1
path: src/Sylius/Bundle/ApiBundle/DataPersister/AddressDataPersister.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\AddressDataPersister\\:\\:persist\\(\\) has parameter \\$data with no type specified\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/DataPersister/AddressDataPersister.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\AddressDataPersister\\:\\:remove\\(\\) has no return type specified\\.$#"
count: 1
@ -610,31 +570,16 @@ parameters:
count: 1
path: src/Sylius/Bundle/ApiBundle/DataPersister/AddressDataPersister.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\AddressDataPersister\\:\\:remove\\(\\) has parameter \\$data with no type specified\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/DataPersister/AddressDataPersister.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\AddressDataPersister\\:\\:supports\\(\\) has parameter \\$context with no value type specified in iterable type array\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/DataPersister/AddressDataPersister.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\AddressDataPersister\\:\\:supports\\(\\) has parameter \\$data with no type specified\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/DataPersister/AddressDataPersister.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\AdminUserDataPersister\\:\\:persist\\(\\) has parameter \\$context with no value type specified in iterable type array\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/DataPersister/AdminUserDataPersister.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\AdminUserDataPersister\\:\\:persist\\(\\) has parameter \\$data with no type specified\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/DataPersister/AdminUserDataPersister.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\AdminUserDataPersister\\:\\:remove\\(\\) has no return type specified\\.$#"
count: 1
@ -645,46 +590,16 @@ parameters:
count: 1
path: src/Sylius/Bundle/ApiBundle/DataPersister/AdminUserDataPersister.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\AdminUserDataPersister\\:\\:remove\\(\\) has parameter \\$data with no type specified\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/DataPersister/AdminUserDataPersister.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\AdminUserDataPersister\\:\\:supports\\(\\) has parameter \\$context with no value type specified in iterable type array\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/DataPersister/AdminUserDataPersister.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\AdminUserDataPersister\\:\\:supports\\(\\) has parameter \\$data with no type specified\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/DataPersister/AdminUserDataPersister.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\ChannelDataPersister\\:\\:persist\\(\\) has parameter \\$data with no type specified\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/DataPersister/ChannelDataPersister.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\ChannelDataPersister\\:\\:remove\\(\\) has parameter \\$data with no type specified\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/DataPersister/ChannelDataPersister.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\ChannelDataPersister\\:\\:supports\\(\\) has parameter \\$data with no type specified\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/DataPersister/ChannelDataPersister.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\CountryDataPersister\\:\\:persist\\(\\) has parameter \\$context with no value type specified in iterable type array\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/DataPersister/CountryDataPersister.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\CountryDataPersister\\:\\:persist\\(\\) has parameter \\$data with no type specified\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/DataPersister/CountryDataPersister.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\CountryDataPersister\\:\\:remove\\(\\) has no return type specified\\.$#"
count: 1
@ -695,51 +610,16 @@ parameters:
count: 1
path: src/Sylius/Bundle/ApiBundle/DataPersister/CountryDataPersister.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\CountryDataPersister\\:\\:remove\\(\\) has parameter \\$data with no type specified\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/DataPersister/CountryDataPersister.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\CountryDataPersister\\:\\:supports\\(\\) has parameter \\$context with no value type specified in iterable type array\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/DataPersister/CountryDataPersister.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\CountryDataPersister\\:\\:supports\\(\\) has parameter \\$data with no type specified\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/DataPersister/CountryDataPersister.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\CustomerDataPersister\\:\\:remove\\(\\) has parameter \\$data with no type specified\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/DataPersister/CustomerDataPersister.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\CustomerDataPersister\\:\\:supports\\(\\) has parameter \\$data with no type specified\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/DataPersister/CustomerDataPersister.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\LocaleDataPersister\\:\\:persist\\(\\) has parameter \\$data with no type specified\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/DataPersister/LocaleDataPersister.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\LocaleDataPersister\\:\\:supports\\(\\) has parameter \\$data with no type specified\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/DataPersister/LocaleDataPersister.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\MessengerDataPersister\\:\\:persist\\(\\) has parameter \\$context with no value type specified in iterable type array\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/DataPersister/MessengerDataPersister.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\MessengerDataPersister\\:\\:persist\\(\\) has parameter \\$data with no type specified\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/DataPersister/MessengerDataPersister.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\MessengerDataPersister\\:\\:remove\\(\\) has no return type specified\\.$#"
count: 1
@ -750,36 +630,11 @@ parameters:
count: 1
path: src/Sylius/Bundle/ApiBundle/DataPersister/MessengerDataPersister.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\MessengerDataPersister\\:\\:remove\\(\\) has parameter \\$data with no type specified\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/DataPersister/MessengerDataPersister.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\MessengerDataPersister\\:\\:supports\\(\\) has parameter \\$context with no value type specified in iterable type array\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/DataPersister/MessengerDataPersister.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\MessengerDataPersister\\:\\:supports\\(\\) has parameter \\$data with no type specified\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/DataPersister/MessengerDataPersister.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\PaymentMethodDataPersister\\:\\:persist\\(\\) has parameter \\$data with no type specified\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/DataPersister/PaymentMethodDataPersister.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\PaymentMethodDataPersister\\:\\:remove\\(\\) has parameter \\$data with no type specified\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/DataPersister/PaymentMethodDataPersister.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\PaymentMethodDataPersister\\:\\:supports\\(\\) has parameter \\$data with no type specified\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/DataPersister/PaymentMethodDataPersister.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\ProductAttributeDataPersister\\:\\:persist\\(\\) has parameter \\$context with no value type specified in iterable type array\\.$#"
count: 1
@ -795,51 +650,21 @@ parameters:
count: 1
path: src/Sylius/Bundle/ApiBundle/DataPersister/ProductAttributeDataPersister.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\ProductAttributeDataPersister\\:\\:remove\\(\\) has parameter \\$data with no type specified\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/DataPersister/ProductAttributeDataPersister.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\ProductAttributeDataPersister\\:\\:supports\\(\\) has parameter \\$context with no value type specified in iterable type array\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/DataPersister/ProductAttributeDataPersister.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\ProductAttributeDataPersister\\:\\:supports\\(\\) has parameter \\$data with no type specified\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/DataPersister/ProductAttributeDataPersister.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\ProductDataPersister\\:\\:persist\\(\\) has parameter \\$data with no type specified\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/DataPersister/ProductDataPersister.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\ProductDataPersister\\:\\:remove\\(\\) has no return type specified\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/DataPersister/ProductDataPersister.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\ProductDataPersister\\:\\:remove\\(\\) has parameter \\$data with no type specified\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/DataPersister/ProductDataPersister.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\ProductDataPersister\\:\\:supports\\(\\) has parameter \\$data with no type specified\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/DataPersister/ProductDataPersister.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\ProductTaxonDataPersister\\:\\:persist\\(\\) has parameter \\$context with no value type specified in iterable type array\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/DataPersister/ProductTaxonDataPersister.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\ProductTaxonDataPersister\\:\\:persist\\(\\) has parameter \\$data with no type specified\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/DataPersister/ProductTaxonDataPersister.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\ProductTaxonDataPersister\\:\\:remove\\(\\) has no return type specified\\.$#"
count: 1
@ -855,71 +680,16 @@ parameters:
count: 1
path: src/Sylius/Bundle/ApiBundle/DataPersister/ProductTaxonDataPersister.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\ProductTaxonDataPersister\\:\\:supports\\(\\) has parameter \\$data with no type specified\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/DataPersister/ProductTaxonDataPersister.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\ProductVariantDataPersister\\:\\:persist\\(\\) has parameter \\$data with no type specified\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/DataPersister/ProductVariantDataPersister.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\ProductVariantDataPersister\\:\\:remove\\(\\) has no return type specified\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/DataPersister/ProductVariantDataPersister.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\ProductVariantDataPersister\\:\\:remove\\(\\) has parameter \\$data with no type specified\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/DataPersister/ProductVariantDataPersister.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\ProductVariantDataPersister\\:\\:supports\\(\\) has parameter \\$data with no type specified\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/DataPersister/ProductVariantDataPersister.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\PromotionCouponDataPersister\\:\\:persist\\(\\) has parameter \\$data with no type specified\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/DataPersister/PromotionCouponDataPersister.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\PromotionCouponDataPersister\\:\\:remove\\(\\) has parameter \\$data with no type specified\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/DataPersister/PromotionCouponDataPersister.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\PromotionCouponDataPersister\\:\\:supports\\(\\) has parameter \\$data with no type specified\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/DataPersister/PromotionCouponDataPersister.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\PromotionDataPersister\\:\\:persist\\(\\) has parameter \\$data with no type specified\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/DataPersister/PromotionDataPersister.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\PromotionDataPersister\\:\\:remove\\(\\) has parameter \\$data with no type specified\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/DataPersister/PromotionDataPersister.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\PromotionDataPersister\\:\\:supports\\(\\) has parameter \\$data with no type specified\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/DataPersister/PromotionDataPersister.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\ShippingMethodDataPersister\\:\\:persist\\(\\) has parameter \\$context with no value type specified in iterable type array\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/DataPersister/ShippingMethodDataPersister.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\ShippingMethodDataPersister\\:\\:persist\\(\\) has parameter \\$data with no type specified\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/DataPersister/ShippingMethodDataPersister.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\ShippingMethodDataPersister\\:\\:remove\\(\\) has no return type specified\\.$#"
count: 1
@ -930,36 +700,16 @@ parameters:
count: 1
path: src/Sylius/Bundle/ApiBundle/DataPersister/ShippingMethodDataPersister.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\ShippingMethodDataPersister\\:\\:remove\\(\\) has parameter \\$data with no type specified\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/DataPersister/ShippingMethodDataPersister.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\ShippingMethodDataPersister\\:\\:supports\\(\\) has parameter \\$context with no value type specified in iterable type array\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/DataPersister/ShippingMethodDataPersister.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\ShippingMethodDataPersister\\:\\:supports\\(\\) has parameter \\$data with no type specified\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/DataPersister/ShippingMethodDataPersister.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\TranslatableDataPersister\\:\\:supports\\(\\) has parameter \\$data with no type specified\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/DataPersister/TranslatableDataPersister.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\ZoneDataPersister\\:\\:persist\\(\\) has parameter \\$context with no value type specified in iterable type array\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/DataPersister/ZoneDataPersister.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\ZoneDataPersister\\:\\:persist\\(\\) has parameter \\$data with no type specified\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/DataPersister/ZoneDataPersister.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\ZoneDataPersister\\:\\:remove\\(\\) has no return type specified\\.$#"
count: 1
@ -970,21 +720,11 @@ parameters:
count: 1
path: src/Sylius/Bundle/ApiBundle/DataPersister/ZoneDataPersister.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\ZoneDataPersister\\:\\:remove\\(\\) has parameter \\$data with no type specified\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/DataPersister/ZoneDataPersister.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\ZoneDataPersister\\:\\:supports\\(\\) has parameter \\$context with no value type specified in iterable type array\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/DataPersister/ZoneDataPersister.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\ZoneDataPersister\\:\\:supports\\(\\) has parameter \\$data with no type specified\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/DataPersister/ZoneDataPersister.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataProvider\\\\AccountResetPasswordItemDataProvider\\:\\:getItem\\(\\) has parameter \\$context with no value type specified in iterable type array\\.$#"
count: 1
@ -1705,11 +1445,6 @@ parameters:
count: 1
path: src/Sylius/Bundle/ApiBundle/Filter/Doctrine/ChannelsAwareChannelFilter.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\Filter\\\\Doctrine\\\\ChannelsAwareChannelFilter\\:\\:filterProperty\\(\\) has parameter \\$value with no type specified\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/Filter/Doctrine/ChannelsAwareChannelFilter.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\Filter\\\\Doctrine\\\\ChannelsAwareChannelFilter\\:\\:getDescription\\(\\) return type has no value type specified in iterable type array\\.$#"
count: 1
@ -1720,11 +1455,6 @@ parameters:
count: 1
path: src/Sylius/Bundle/ApiBundle/Filter/Doctrine/ExchangeRateFilter.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\Filter\\\\Doctrine\\\\ExchangeRateFilter\\:\\:filterProperty\\(\\) has parameter \\$value with no type specified\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/Filter/Doctrine/ExchangeRateFilter.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\Filter\\\\Doctrine\\\\ExchangeRateFilter\\:\\:getDescription\\(\\) return type has no value type specified in iterable type array\\.$#"
count: 1
@ -1735,11 +1465,6 @@ parameters:
count: 1
path: src/Sylius/Bundle/ApiBundle/Filter/Doctrine/ProductPriceOrderFilter.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\Filter\\\\Doctrine\\\\ProductPriceOrderFilter\\:\\:filterProperty\\(\\) has parameter \\$value with no type specified\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/Filter/Doctrine/ProductPriceOrderFilter.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\Filter\\\\Doctrine\\\\ProductPriceOrderFilter\\:\\:getDescription\\(\\) return type has no value type specified in iterable type array\\.$#"
count: 1
@ -1750,11 +1475,6 @@ parameters:
count: 1
path: src/Sylius/Bundle/ApiBundle/Filter/Doctrine/ProductVariantCatalogPromotionFilter.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\Filter\\\\Doctrine\\\\ProductVariantCatalogPromotionFilter\\:\\:filterProperty\\(\\) has parameter \\$value with no type specified\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/Filter/Doctrine/ProductVariantCatalogPromotionFilter.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\Filter\\\\Doctrine\\\\ProductVariantCatalogPromotionFilter\\:\\:getDescription\\(\\) return type has no value type specified in iterable type array\\.$#"
count: 1
@ -1765,21 +1485,11 @@ parameters:
count: 1
path: src/Sylius/Bundle/ApiBundle/Filter/Doctrine/ProductVariantOptionValueFilter.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\Filter\\\\Doctrine\\\\ProductVariantOptionValueFilter\\:\\:filterProperty\\(\\) has parameter \\$value with no type specified\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/Filter/Doctrine/ProductVariantOptionValueFilter.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\Filter\\\\Doctrine\\\\ProductVariantOptionValueFilter\\:\\:getDescription\\(\\) return type has no value type specified in iterable type array\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/Filter/Doctrine/ProductVariantOptionValueFilter.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\Filter\\\\Doctrine\\\\PromotionCouponPromotionFilter\\:\\:filterProperty\\(\\) has parameter \\$value with no type specified\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/Filter/Doctrine/PromotionCouponPromotionFilter.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\Filter\\\\Doctrine\\\\TaxonFilter\\:\\:filterProperty\\(\\) has no return type specified\\.$#"
count: 1
@ -1790,21 +1500,11 @@ parameters:
count: 1
path: src/Sylius/Bundle/ApiBundle/Filter/Doctrine/TaxonFilter.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\Filter\\\\Doctrine\\\\TaxonFilter\\:\\:filterProperty\\(\\) has parameter \\$value with no type specified\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/Filter/Doctrine/TaxonFilter.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\Filter\\\\Doctrine\\\\TaxonFilter\\:\\:getDescription\\(\\) return type has no value type specified in iterable type array\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/Filter/Doctrine/TaxonFilter.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\Filter\\\\Doctrine\\\\TranslationOrderNameAndLocaleFilter\\:\\:filterProperty\\(\\) has parameter \\$value with no type specified\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/Filter/Doctrine/TranslationOrderNameAndLocaleFilter.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\Filter\\\\Doctrine\\\\TranslationOrderNameAndLocaleFilter\\:\\:getDescription\\(\\) return type has no value type specified in iterable type array\\.$#"
count: 1
@ -1850,46 +1550,6 @@ parameters:
count: 1
path: src/Sylius/Bundle/ApiBundle/Provider/CompositePaymentConfigurationProviderInterface.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\Provider\\\\LiipProductImageFilterProvider\\:\\:__construct\\(\\) has parameter \\$filters with no value type specified in iterable type array\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/Provider/LiipProductImageFilterProvider.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\Provider\\\\LiipProductImageFilterProvider\\:\\:provideAllFilters\\(\\) return type has no value type specified in iterable type array\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/Provider/LiipProductImageFilterProvider.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\Provider\\\\LiipProductImageFilterProvider\\:\\:provideShopFilters\\(\\) return type has no value type specified in iterable type array\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/Provider/LiipProductImageFilterProvider.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\Provider\\\\LiipProductImageFilterProvider\\:\\:removeAdminFilters\\(\\) has parameter \\$filters with no value type specified in iterable type array\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/Provider/LiipProductImageFilterProvider.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\Provider\\\\LiipProductImageFilterProvider\\:\\:removeAdminFilters\\(\\) return type has no value type specified in iterable type array\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/Provider/LiipProductImageFilterProvider.php
-
message: "#^Property Sylius\\\\Bundle\\\\ApiBundle\\\\Provider\\\\LiipProductImageFilterProvider\\:\\:\\$filters type has no value type specified in iterable type array\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/Provider/LiipProductImageFilterProvider.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\Provider\\\\ProductImageFilterProviderInterface\\:\\:provideAllFilters\\(\\) return type has no value type specified in iterable type array\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/Provider/ProductImageFilterProviderInterface.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\Provider\\\\ProductImageFilterProviderInterface\\:\\:provideShopFilters\\(\\) return type has no value type specified in iterable type array\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/Provider/ProductImageFilterProviderInterface.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\Serializer\\\\ChannelPriceHistoryConfigDenormalizer\\:\\:__construct\\(\\) has parameter \\$channelPriceHistoryConfigFactory with generic interface Sylius\\\\Component\\\\Resource\\\\Factory\\\\FactoryInterface but does not specify its types\\: T$#"
count: 1
@ -1915,16 +1575,6 @@ parameters:
count: 1
path: src/Sylius/Bundle/ApiBundle/Serializer/ProductAttributeValueNormalizer.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\Serializer\\\\ProductImageNormalizer\\:\\:resolvePath\\(\\) has parameter \\$data with no type specified\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/Serializer/ProductImageNormalizer.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\Serializer\\\\ProductImageNormalizer\\:\\:resolvePath\\(\\) return type has no value type specified in iterable type array\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/Serializer/ProductImageNormalizer.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\Serializer\\\\ProductNormalizer\\:\\:isShopOperation\\(\\) has parameter \\$context with no value type specified in iterable type array\\.$#"
count: 1
@ -2455,61 +2105,6 @@ parameters:
count: 1
path: src/Sylius/Bundle/CoreBundle/Collector/SyliusCollector.php
-
message: "#^If condition is always false\\.$#"
count: 1
path: src/Sylius/Bundle/CoreBundle/Command/CancelUnpaidOrdersCommand.php
-
message: "#^If condition is always false\\.$#"
count: 1
path: src/Sylius/Bundle/CoreBundle/Command/CheckRequirementsCommand.php
-
message: "#^If condition is always false\\.$#"
count: 1
path: src/Sylius/Bundle/CoreBundle/Command/InformAboutGUSCommand.php
-
message: "#^If condition is always false\\.$#"
count: 1
path: src/Sylius/Bundle/CoreBundle/Command/InstallAssetsCommand.php
-
message: "#^If condition is always false\\.$#"
count: 1
path: src/Sylius/Bundle/CoreBundle/Command/InstallCommand.php
-
message: "#^If condition is always false\\.$#"
count: 1
path: src/Sylius/Bundle/CoreBundle/Command/InstallDatabaseCommand.php
-
message: "#^If condition is always false\\.$#"
count: 1
path: src/Sylius/Bundle/CoreBundle/Command/InstallSampleDataCommand.php
-
message: "#^If condition is always false\\.$#"
count: 1
path: src/Sylius/Bundle/CoreBundle/Command/JwtConfigurationCommand.php
-
message: "#^If condition is always false\\.$#"
count: 1
path: src/Sylius/Bundle/CoreBundle/Command/Model/PluginInfo.php
-
message: "#^If condition is always false\\.$#"
count: 1
path: src/Sylius/Bundle/CoreBundle/Command/SetupCommand.php
-
message: "#^If condition is always false\\.$#"
count: 1
path: src/Sylius/Bundle/CoreBundle/Command/ShowAvailablePluginsCommand.php
-
message: "#^Method Sylius\\\\Bundle\\\\CoreBundle\\\\Context\\\\CustomerAndChannelBasedCartContext\\:\\:__construct\\(\\) has parameter \\$orderRepository with generic interface Sylius\\\\Component\\\\Core\\\\Repository\\\\OrderRepositoryInterface but does not specify its types\\: T$#"
count: 1
@ -3820,16 +3415,6 @@ parameters:
count: 1
path: src/Sylius/Bundle/CoreBundle/Installer/Setup/LocaleSetup.php
-
message: "#^Method Sylius\\\\Bundle\\\\CoreBundle\\\\MessageHandler\\\\Admin\\\\Account\\\\RequestResetPasswordEmailHandler\\:\\:__construct\\(\\) has parameter \\$userRepository with generic interface Sylius\\\\Component\\\\User\\\\Repository\\\\UserRepositoryInterface but does not specify its types\\: T$#"
count: 1
path: src/Sylius/Bundle/CoreBundle/MessageHandler/Admin/Account/RequestResetPasswordEmailHandler.php
-
message: "#^Method Sylius\\\\Bundle\\\\CoreBundle\\\\MessageHandler\\\\Admin\\\\Account\\\\RequestResetPasswordEmailHandler\\:\\:__invoke\\(\\) has no return type specified\\.$#"
count: 1
path: src/Sylius/Bundle/CoreBundle/MessageHandler/Admin/Account/RequestResetPasswordEmailHandler.php
-
message: "#^Method Sylius\\\\Bundle\\\\CoreBundle\\\\Migrations\\\\Version20171003103916\\:\\:getProductAttributes\\(\\) return type has no value type specified in iterable type array\\.$#"
count: 1
@ -4410,21 +3995,6 @@ parameters:
count: 1
path: src/Sylius/Bundle/ProductBundle/Form/DataTransformer/ProductsToProductAssociationsTransformer.php
-
message: "#^Method Sylius\\\\Bundle\\\\ProductBundle\\\\Form\\\\DataTransformer\\\\ProductsToProductAssociationsTransformer\\:\\:__construct\\(\\) has parameter \\$productAssociationFactory with generic interface Sylius\\\\Component\\\\Resource\\\\Factory\\\\FactoryInterface but does not specify its types\\: T$#"
count: 1
path: src/Sylius/Bundle/ProductBundle/Form/DataTransformer/ProductsToProductAssociationsTransformer.php
-
message: "#^Method Sylius\\\\Bundle\\\\ProductBundle\\\\Form\\\\DataTransformer\\\\ProductsToProductAssociationsTransformer\\:\\:__construct\\(\\) has parameter \\$productAssociationTypeRepository with generic interface Sylius\\\\Component\\\\Resource\\\\Repository\\\\RepositoryInterface but does not specify its types\\: T$#"
count: 1
path: src/Sylius/Bundle/ProductBundle/Form/DataTransformer/ProductsToProductAssociationsTransformer.php
-
message: "#^Method Sylius\\\\Bundle\\\\ProductBundle\\\\Form\\\\DataTransformer\\\\ProductsToProductAssociationsTransformer\\:\\:__construct\\(\\) has parameter \\$productRepository with generic interface Sylius\\\\Component\\\\Product\\\\Repository\\\\ProductRepositoryInterface but does not specify its types\\: T$#"
count: 1
path: src/Sylius/Bundle/ProductBundle/Form/DataTransformer/ProductsToProductAssociationsTransformer.php
-
message: "#^Method Sylius\\\\Bundle\\\\ProductBundle\\\\Form\\\\DataTransformer\\\\ProductsToProductAssociationsTransformer\\:\\:reverseTransform\\(\\) return type with generic interface Doctrine\\\\Common\\\\Collections\\\\Collection does not specify its types\\: TKey, T$#"
count: 1
@ -4445,16 +4015,6 @@ parameters:
count: 1
path: src/Sylius/Bundle/ProductBundle/Form/Type/ProductAssociationTypeChoiceType.php
-
message: "#^Method Sylius\\\\Bundle\\\\ProductBundle\\\\Form\\\\Type\\\\ProductAssociationsType\\:\\:__construct\\(\\) has parameter \\$productAssociationTypeRepository with generic interface Sylius\\\\Component\\\\Resource\\\\Repository\\\\RepositoryInterface but does not specify its types\\: T$#"
count: 1
path: src/Sylius/Bundle/ProductBundle/Form/Type/ProductAssociationsType.php
-
message: "#^Method Sylius\\\\Bundle\\\\ProductBundle\\\\Form\\\\Type\\\\ProductAssociationsType\\:\\:__construct\\(\\) has parameter \\$productsToProductAssociationsTransformer with generic interface Symfony\\\\Component\\\\Form\\\\DataTransformerInterface but does not specify its types\\: T, R$#"
count: 1
path: src/Sylius/Bundle/ProductBundle/Form/Type/ProductAssociationsType.php
-
message: "#^Method Sylius\\\\Bundle\\\\ProductBundle\\\\Form\\\\Type\\\\ProductChoiceType\\:\\:__construct\\(\\) has parameter \\$productRepository with generic interface Sylius\\\\Component\\\\Resource\\\\Repository\\\\RepositoryInterface but does not specify its types\\: T$#"
count: 1
@ -4490,11 +4050,6 @@ parameters:
count: 1
path: src/Sylius/Bundle/ProductBundle/Validator/UniqueSimpleProductCodeValidator.php
-
message: "#^If condition is always false\\.$#"
count: 1
path: src/Sylius/Bundle/PromotionBundle/Command/GenerateCouponsCommand.php
-
message: "#^Method Sylius\\\\Bundle\\\\PromotionBundle\\\\DiscountApplicationCriteria\\\\DiscountApplicationCriteriaInterface\\:\\:isApplicable\\(\\) has parameter \\$context with no value type specified in iterable type array\\.$#"
count: 1
@ -4845,11 +4400,6 @@ parameters:
count: 1
path: src/Sylius/Bundle/TaxonomyBundle/SyliusTaxonomyBundle.php
-
message: "#^If condition is always false\\.$#"
count: 1
path: src/Sylius/Bundle/UiBundle/Command/DebugTemplateEventCommand.php
-
message: "#^Method Sylius\\\\Bundle\\\\UiBundle\\\\ContextProvider\\\\ContextProviderInterface\\:\\:provide\\(\\) has parameter \\$templateContext with no value type specified in iterable type array\\.$#"
count: 1
@ -4950,21 +4500,6 @@ parameters:
count: 1
path: src/Sylius/Bundle/UiBundle/Twig/TemplateEventExtension.php
-
message: "#^If condition is always false\\.$#"
count: 1
path: src/Sylius/Bundle/UserBundle/Command/AbstractRoleCommand.php
-
message: "#^If condition is always false\\.$#"
count: 1
path: src/Sylius/Bundle/UserBundle/Command/DemoteUserCommand.php
-
message: "#^If condition is always false\\.$#"
count: 1
path: src/Sylius/Bundle/UserBundle/Command/PromoteUserCommand.php
-
message: "#^Method Sylius\\\\Bundle\\\\UserBundle\\\\Console\\\\Command\\\\AbstractRoleCommand\\:\\:getUserRepository\\(\\) return type with generic interface Sylius\\\\Component\\\\User\\\\Repository\\\\UserRepositoryInterface does not specify its types\\: T$#"
count: 1

View file

@ -847,9 +847,7 @@ final readonly class ManagingPaymentMethodsContext implements Context
return null;
}
/**
* @return string[]
*/
/** @return string[] */
private function getPaymentMethodNamesFromCollection(): array
{
$paymentMethods = $this->responseChecker->getCollection($this->client->index(Resources::PAYMENT_METHODS));

View file

@ -567,13 +567,13 @@ final class ManagingProductVariantsContext implements Context
}
/**
* @Then I should be notified that prices in all channels must be defined
* @Then I should be notified that prices in :channel channel must be defined
*/
public function iShouldBeNotifiedThatPricesInAllChannelsMustBeDefined(): void
public function iShouldBeNotifiedThatPricesInAllChannelsMustBeDefined(ChannelInterface $channel): void
{
Assert::contains(
$this->responseChecker->getError($this->client->getLastResponse()),
'You must define price for every enabled channel.',
sprintf('channelPricings[%s].price: You must define price.', $channel->getCode()),
);
}

View file

@ -14,8 +14,8 @@ declare(strict_types=1);
namespace Sylius\Behat\Context\Cli;
use Behat\Behat\Context\Context;
use Sylius\Bundle\CoreBundle\Command\InstallSampleDataCommand;
use Sylius\Bundle\CoreBundle\Command\SetupCommand;
use Sylius\Bundle\CoreBundle\Console\Command\InstallSampleDataCommand;
use Sylius\Bundle\CoreBundle\Console\Command\SetupCommand;
use Symfony\Bundle\FrameworkBundle\Console\Application;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Tester\CommandTester;

View file

@ -14,7 +14,7 @@ declare(strict_types=1);
namespace Sylius\Behat\Context\Cli;
use Behat\Behat\Context\Context;
use Sylius\Bundle\CoreBundle\Command\SetupCommand;
use Sylius\Bundle\CoreBundle\Console\Command\SetupCommand;
use Symfony\Bundle\FrameworkBundle\Console\Application;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Tester\CommandTester;

View file

@ -1,46 +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\Context\Ui\Admin;
use Behat\Behat\Context\Context;
use Sylius\Behat\Page\Admin\Product\UpdateSimpleProductPageInterface;
use Sylius\Behat\Page\Admin\ProductVariant\UpdatePageInterface;
use Sylius\Component\Core\Model\ProductInterface;
use Sylius\Component\Core\Model\ProductVariantInterface;
use Webmozart\Assert\Assert;
final class AccessingEditPageFromProductShowPageContext implements Context
{
public function __construct(
private UpdateSimpleProductPageInterface $updateSimpleProductPage,
private UpdatePageInterface $updateVariantProductPage,
) {
}
/**
* @Then I should be on :product product edit page
*/
public function iShouldBeOnProductEditPage(ProductInterface $product): void
{
Assert::true($this->updateSimpleProductPage->isOpen(['id' => $product->getId()]));
}
/**
* @Then I should be on :variant variant edit page
*/
public function iShouldBeOnVariantEditPage(ProductVariantInterface $variant): void
{
Assert::true($this->updateVariantProductPage->isOpen(['productId' => $variant->getProduct()->getId(), 'id' => $variant->getId()]));
}
}

View file

@ -0,0 +1,39 @@
<?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\Context\Ui\Admin\Helper;
trait NavigationTrait
{
public function hasShowPageButton(): bool
{
return $this->hasElement('show_' . $this->getResourceName() . '_button');
}
public function switchToShowPage(): void
{
$this->getElement('show_' . $this->getResourceName() . '_button')->click();
}
public function hasEditPageButton(): bool
{
return $this->hasElement('edit_' . $this->getResourceName() . '_button');
}
public function switchToEditPage(): void
{
$this->getElement('edit_' . $this->getResourceName() . '_button')->click();
}
abstract protected function getResourceName(): string;
}

View file

@ -0,0 +1,20 @@
<?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\Context\Ui\Admin\Helper;
enum ProductTypeEnum: string
{
case simple = 'simple';
case configurable = 'configurable';
}

View file

@ -14,24 +14,20 @@ declare(strict_types=1);
namespace Sylius\Behat\Context\Ui\Admin;
use Behat\Behat\Context\Context;
use FriendsOfBehat\PageObjectExtension\Page\SymfonyPageInterface;
use Sylius\Behat\Context\Ui\Admin\Helper\ValidationTrait;
use Sylius\Behat\Element\Admin\CustomerGroup\FormElementInterface;
use Sylius\Behat\Page\Admin\Crud\CreatePageInterface;
use Sylius\Behat\Page\Admin\Crud\IndexPageInterface;
use Sylius\Behat\Page\Admin\CustomerGroup\CreatePageInterface;
use Sylius\Behat\Page\Admin\CustomerGroup\UpdatePageInterface;
use Sylius\Behat\Service\Resolver\CurrentPageResolverInterface;
use Sylius\Behat\Page\Admin\Crud\UpdatePageInterface;
use Sylius\Component\Customer\Model\CustomerGroupInterface;
use Webmozart\Assert\Assert;
final readonly class ManagingCustomerGroupsContext implements Context
{
use ValidationTrait;
public function __construct(
private CreatePageInterface $createPage,
private IndexPageInterface $indexPage,
private CurrentPageResolverInterface $currentPageResolver,
private UpdatePageInterface $updatePage,
private FormElementInterface $formElement,
) {
}
@ -49,7 +45,15 @@ final readonly class ManagingCustomerGroupsContext implements Context
*/
public function iSpecifyItsCodeAs(?string $code = null): void
{
$this->createPage->specifyCode($code ?? '');
$this->formElement->fillElement($code ?? '', 'code');
}
/**
* @When I specify a too long code
*/
public function iSpecifyATooLongCode(): void
{
$this->formElement->fillElement(str_repeat('a', 256), 'code');
}
/**
@ -58,7 +62,7 @@ final readonly class ManagingCustomerGroupsContext implements Context
*/
public function iSpecifyItsNameAs(?string $name = null): void
{
$this->createPage->nameIt($name ?? '');
$this->formElement->fillElement($name ?? '', 'name');
}
/**
@ -198,7 +202,7 @@ final readonly class ManagingCustomerGroupsContext implements Context
public function iShouldBeNotifiedThatNameIsRequired(): void
{
Assert::same(
$this->updatePage->getValidationMessage('name'),
$this->formElement->getValidationMessage('name'),
'Please enter a customer group name.',
);
}
@ -208,7 +212,18 @@ final readonly class ManagingCustomerGroupsContext implements Context
*/
public function iShouldBeNotifiedThatCustomerGroupWithThisCodeAlreadyExists(): void
{
Assert::same($this->createPage->getValidationMessage('code'), 'Customer group code has to be unique.');
Assert::same($this->formElement->getValidationMessage('code'), 'Customer group code has to be unique.');
}
/**
* @Then I should be notified that code is too long
*/
public function iShouldBeNotifiedThatCodeIsTooLong(): void
{
Assert::contains(
$this->formElement->getValidationMessage('code'),
'must not be longer than 255 characters.',
);
}
/**
@ -216,10 +231,7 @@ final readonly class ManagingCustomerGroupsContext implements Context
*/
public function iShouldBeInformedThatThisFormContainsErrors(): void
{
/** @var CreatePageInterface|UpdatePageInterface $currentPage */
$currentPage = $this->currentPageResolver->getCurrentPageWithForm([$this->createPage, $this->updatePage]);
Assert::contains($currentPage->getMessageInvalidForm(), 'This form contains errors');
Assert::true($this->formElement->hasFormErrorAlert());
}
/**
@ -227,7 +239,7 @@ final readonly class ManagingCustomerGroupsContext implements Context
*/
public function iShouldNotBeAbleToEditItsCode(): void
{
Assert::true($this->updatePage->isCodeDisabled());
Assert::true($this->formElement->isCodeDisabled());
}
/**
@ -253,9 +265,4 @@ final readonly class ManagingCustomerGroupsContext implements Context
),
);
}
protected function resolveCurrentPage(): SymfonyPageInterface
{
return $this->currentPageResolver->getCurrentPageWithForm([$this->createPage, $this->updatePage]);
}
}

View file

@ -230,7 +230,7 @@ final readonly class ManagingProductOptionsContext implements Context
*/
public function iShouldNotBeAbleToEditItsCode(): void
{
Assert::true($this->updatePage->isCodeDisabled());
Assert::true($this->formElement->isCodeDisabled());
}
/**
@ -258,7 +258,7 @@ final readonly class ManagingProductOptionsContext implements Context
public function thisProductOptionShouldHaveTheOptionValue(
ProductOptionInterface $productOption,
string $optionValue,
string $localeCode = 'en_US'
string $localeCode = 'en_US',
): void {
$this->iWantToModifyAProductOption($productOption);
@ -272,7 +272,7 @@ final readonly class ManagingProductOptionsContext implements Context
public function thisProductOptionShouldNotHaveTheOptionValue(
ProductOptionInterface $productOption,
string $optionValue,
string $localeCode = 'en_US'
string $localeCode = 'en_US',
): void {
$this->iWantToModifyAProductOption($productOption);

View file

@ -15,14 +15,17 @@ namespace Sylius\Behat\Context\Ui\Admin;
use Behat\Behat\Context\Context;
use Sylius\Behat\Element\Admin\Product\TaxonomyFormElementInterface;
use Sylius\Behat\Page\Admin\Product\UpdateSimpleProductPageInterface;
use Sylius\Component\Core\Model\ProductInterface;
use Sylius\Component\Core\Model\TaxonInterface;
use Webmozart\Assert\Assert;
final class ManagingProductTaxonsContext implements Context
final readonly class ManagingProductTaxonsContext implements Context
{
public function __construct(private TaxonomyFormElementInterface $taxonomyFormElement)
{
public function __construct(
private UpdateSimpleProductPageInterface $updateSimpleProductPage,
private TaxonomyFormElementInterface $taxonomyFormElement,
) {
}
/**
@ -41,6 +44,10 @@ final class ManagingProductTaxonsContext implements Context
ProductInterface $product,
TaxonInterface $taxon,
): void {
if (!$this->updateSimpleProductPage->isOpen(['id' => $product->getId()])) {
$this->updateSimpleProductPage->open(['id' => $product->getId()]);
}
$this->taxonomyFormElement->uncheckProductTaxon($taxon);
}

View file

@ -277,11 +277,11 @@ final class ManagingProductVariantsContext implements Context
}
/**
* @When I choose to show this product in the :channelName channel
* @When /^I choose to show this product in the (channel "([^"]+)")$/
*/
public function iChooseToShowThisProductInTheChannel(string $channelName): void
public function iChooseToShowThisProductInTheChannel(ChannelInterface $channel): void
{
$this->updatePage->showProductInChannel($channelName);
$this->updatePage->showProductInChannel($channel);
}
/**
@ -404,6 +404,30 @@ final class ManagingProductVariantsContext implements Context
$this->updatePage->specifyPrice($price, $channel);
}
/**
* @When I want to see the list of variants of the :product product
*/
public function iWantToSeeTheListOfVariantsOfTheProduct(ProductInterface $product): void
{
$this->indexPage->open(['productId' => $product->getId()]);
}
/**
* @When I go to generate variants page
*/
public function iGoToGenerateVariantsPage(): void
{
$this->indexPage->goToVariantGeneration();
}
/**
* @Then I should be on the :product product generate variants page
*/
public function iShouldBeOnTheProductGenerateVariantsPage(ProductInterface $product): void
{
$this->generatePage->verify(['productId' => $product->getId()]);
}
/**
* @Then /^the (variant with code "[^"]+") should be priced at (?:€|£|\$)([^"]+) for (channel "([^"]+)")$/
* @Then /^the (variant with code "[^"]+") should be priced at "(?:|£|\$)([^"]+)" for (channel "([^"]+)")$/
@ -557,19 +581,21 @@ final class ManagingProductVariantsContext implements Context
public function iShouldBeNotifiedThatCodeIsRequiredForVariant($position)
{
Assert::same(
$this->generatePage->getValidationMessage('code', $position - 1),
$this->generatePage->getValidationMessage('code', ['%position%' => $position - 1]),
'Please enter the code.',
);
}
/**
* @Then /^I should be notified that prices in all channels must be defined for the (\d)(?:st|nd|rd|th) variant$/
* @Then /^I should be notified that price for the (\d+)(?:|st|nd|rd|th) variant in ("([^"]+)" channel) must be defined$/
*/
public function iShouldBeNotifiedThatPricesInAllChannelsMustBeDefinedForTheVariant($position): void
{
public function iShouldBeNotifiedThatPriceForTheVariantInChannelMustBeDefined(
int $position,
ChannelInterface $channel,
): void {
Assert::same(
$this->generatePage->getValidationMessage('channel_pricings', $position - 1),
'You must define price for every enabled channel.',
$this->generatePage->getValidationMessage('price', ['%channel_code%' => $channel->getCode(), '%position%' => $position - 1]),
'You must define price.',
);
}
@ -579,19 +605,19 @@ final class ManagingProductVariantsContext implements Context
public function iShouldBeNotifiedThatVariantCodeMustBeUniqueWithinThisProductForYheVariant($position)
{
Assert::same(
$this->generatePage->getValidationMessage('code', $position - 1),
$this->generatePage->getValidationMessage('code', ['%position%' => $position - 1]),
'This code must be unique within this product.',
);
}
/**
* @Then I should be notified that prices in all channels must be defined
* @Then I should be notified that prices in :channel channel must be defined
*/
public function iShouldBeNotifiedThatPricesInAllChannelsMustBeDefined()
public function iShouldBeNotifiedThatPricesInAllChannelsMustBeDefined(ChannelInterface $channel): void
{
Assert::contains(
$this->createPage->getPricesValidationMessage(),
'You must define price for every enabled channel.',
$this->createPage->getValidationMessage('price', ['%channel_code%' => $channel->getCode()]),
'You must define price',
);
}
@ -767,6 +793,14 @@ final class ManagingProductVariantsContext implements Context
Assert::true($this->generatePage->isProductVariantRemovable($nthVariant - 1));
}
/**
* @Then I should not be able to go to the generate variants page
*/
public function iShouldNotBeAbleToGoToTheGenerateVariantsPage(): void
{
Assert::false($this->indexPage->hasGenerateVariantsButton(), 'Generate variants button should not be visible');
}
/**
* @param string $element
* @param string $message

View file

@ -208,7 +208,7 @@ final readonly class ManagingProductsContext implements Context
/**
* @When I choose to show this product in the :channel channel
*/
public function iChooseToShowThisProductInTheChannel(string $channel): void
public function iChooseToShowThisProductInTheChannel(ChannelInterface $channel): void
{
$this->updateSimpleProductPage->showProductInChannel($channel);
}
@ -1102,13 +1102,13 @@ final readonly class ManagingProductsContext implements Context
}
/**
* @Then I should be notified that price must be defined for every channel
* @Then I should be notified that price must be defined for :channel channel
*/
public function iShouldBeNotifiedThatPriceMustBeDefinedForEveryChannel(): void
public function iShouldBeNotifiedThatPriceMustBeDefinedForChannel(ChannelInterface $channel): void
{
Assert::same(
$this->channelPricingsFormElement->getChannelPricingValidationMessage(),
'You must define price for every enabled channel.',
$this->channelPricingsFormElement->getValidationMessage('price', ['%channel_code%' => $channel->getCode()]),
'You must define price.',
);
}
@ -1428,6 +1428,14 @@ final readonly class ManagingProductsContext implements Context
Assert::true($this->attributesFormElement->hasAttributeError($attributeName, $localeCode));
}
/**
* @Then I should not be able to go to the generate variants page
*/
public function iShouldNotBeAbleToGoToTheGenerateVariantsPage(): void
{
Assert::false($this->updateSimpleProductPage->hasGenerateVariantsButton(), 'Generate variants button should not be visible');
}
private function assertValidationMessage(string $element, string $message): void
{
/** @var CreatePageInterface|UpdatePageInterface $currentPage */

View file

@ -36,7 +36,7 @@ class ManagingShippingCategoriesContext implements Context
/**
* @When I want to create a new shipping category
*/
public function iWantToCreateANewShippingCategory()
public function iWantToCreateANewShippingCategory(): void
{
$this->createPage->open();
}
@ -44,7 +44,7 @@ class ManagingShippingCategoriesContext implements Context
/**
* @When /^I browse shipping categories$/
*/
public function iWantToBrowseShippingCategories()
public function iWantToBrowseShippingCategories(): void
{
$this->indexPage->open();
}
@ -61,7 +61,7 @@ class ManagingShippingCategoriesContext implements Context
/**
* @When I specify its description as :shippingCategoryDescription
*/
public function iSpecifyItsDescriptionAs($shippingCategoryDescription)
public function iSpecifyItsDescriptionAs(string $shippingCategoryDescription): void
{
$this->createPage->specifyDescription($shippingCategoryDescription);
}
@ -70,7 +70,7 @@ class ManagingShippingCategoriesContext implements Context
* @When I add it
* @When I try to add it
*/
public function iAddIt()
public function iAddIt(): void
{
$this->createPage->create();
}
@ -78,7 +78,7 @@ class ManagingShippingCategoriesContext implements Context
/**
* @Then I should be notified that :element is required
*/
public function iShouldBeNotifiedThatCodeIsRequired($element)
public function iShouldBeNotifiedThatCodeIsRequired(string $element): void
{
Assert::same(
$this->updatePage->getValidationMessage($element),
@ -99,7 +99,7 @@ class ManagingShippingCategoriesContext implements Context
* @When I name it :shippingCategoryName
* @When I do not specify its name
*/
public function iNameIt($shippingCategoryName = null)
public function iNameIt($shippingCategoryName = null): void
{
$this->createPage->nameIt($shippingCategoryName ?? '');
}
@ -116,7 +116,7 @@ class ManagingShippingCategoriesContext implements Context
* @Then /^the (shipping category "([^"]+)") should be in the registry$/
* @Then /^the (shipping category "([^"]+)") should appear in the registry$/
*/
public function theShippingCategoryShouldAppearInTheRegistry(ShippingCategoryInterface $shippingCategory)
public function theShippingCategoryShouldAppearInTheRegistry(ShippingCategoryInterface $shippingCategory): void
{
$this->iWantToBrowseShippingCategories();
@ -126,7 +126,7 @@ class ManagingShippingCategoriesContext implements Context
/**
* @When I delete shipping category :shippingCategoryName
*/
public function iDeleteShippingCategory($shippingCategoryName)
public function iDeleteShippingCategory(string $shippingCategoryName): void
{
$this->iWantToBrowseShippingCategories();
$this->indexPage->deleteResourceOnPage(['name' => $shippingCategoryName]);
@ -143,7 +143,7 @@ class ManagingShippingCategoriesContext implements Context
/**
* @Then shipping category with name :shippingCategoryName should not be added
*/
public function shippingCategoryWithNameShouldNotBeAdded($shippingCategoryName)
public function shippingCategoryWithNameShouldNotBeAdded(string $shippingCategoryName): void
{
Assert::false($this->indexPage->isSingleResourceOnPage(['name' => $shippingCategoryName]));
}
@ -152,7 +152,7 @@ class ManagingShippingCategoriesContext implements Context
* @When /^I modify a (shipping category "([^"]+)")$/
* @When /^I want to modify a (shipping category "([^"]+)")$/
*/
public function iWantToModifyAShippingCategory(ShippingCategoryInterface $shippingCategory)
public function iWantToModifyAShippingCategory(ShippingCategoryInterface $shippingCategory): void
{
$this->updatePage->open(['id' => $shippingCategory->getId()]);
}
@ -160,7 +160,7 @@ class ManagingShippingCategoriesContext implements Context
/**
* @When I rename it to :name
*/
public function iNameItIn($name)
public function iNameItIn(string $name): void
{
$this->createPage->nameIt($name ?? '');
}
@ -168,7 +168,7 @@ class ManagingShippingCategoriesContext implements Context
/**
* @When I save my changes
*/
public function iSaveMyChanges()
public function iSaveMyChanges(): void
{
$this->updatePage->saveChanges();
}
@ -200,7 +200,7 @@ class ManagingShippingCategoriesContext implements Context
/**
* @Then this shipping category name should be :shippingCategoryName
*/
public function thisShippingCategoryNameShouldBe($shippingCategoryName)
public function thisShippingCategoryNameShouldBe(string $shippingCategoryName): void
{
Assert::true($this->updatePage->hasResourceValues(['name' => $shippingCategoryName]));
}
@ -208,7 +208,7 @@ class ManagingShippingCategoriesContext implements Context
/**
* @Then I should be notified that shipping category with this code already exists
*/
public function iShouldBeNotifiedThatShippingCategoryWithThisCodeAlreadyExists()
public function iShouldBeNotifiedThatShippingCategoryWithThisCodeAlreadyExists(): void
{
Assert::same(
$this->createPage->getValidationMessage('code'),
@ -219,7 +219,7 @@ class ManagingShippingCategoriesContext implements Context
/**
* @Then there should still be only one shipping category with code :code
*/
public function thereShouldStillBeOnlyOneShippingCategoryWith($code)
public function thereShouldStillBeOnlyOneShippingCategoryWith(string $code): void
{
$this->iWantToBrowseShippingCategories();

View file

@ -0,0 +1,129 @@
<?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\Context\Ui\Admin;
use Behat\Behat\Context\Context;
use Sylius\Behat\Context\Ui\Admin\Helper\ProductTypeEnum;
use Sylius\Behat\Page\Admin\Product\CreateConfigurableProductPageInterface;
use Sylius\Behat\Page\Admin\Product\CreateSimpleProductPageInterface;
use Sylius\Behat\Page\Admin\Product\ShowPageInterface;
use Sylius\Behat\Page\Admin\Product\UpdateSimpleProductPageInterface;
use Sylius\Behat\Page\Admin\ProductVariant\UpdatePageInterface;
use Sylius\Component\Core\Model\ProductInterface;
use Sylius\Component\Core\Model\ProductVariantInterface;
use Webmozart\Assert\Assert;
final class NavigatingBetweenProductShowAndEditPagesContext implements Context
{
private ProductTypeEnum $currentProductType;
public function __construct(
private readonly UpdateSimpleProductPageInterface $updateSimpleProductPage,
private readonly UpdatePageInterface $updateVariantProductPage,
private readonly ShowPageInterface $productShowPage,
private readonly CreateSimpleProductPageInterface $createSimpleProductPage,
private readonly CreateConfigurableProductPageInterface $createConfigurableProductPage,
) {
}
/**
* @When I access the :product product
*/
public function iAccessTheProduct(ProductInterface $product): void
{
$this->productShowPage->open(['id' => $product->getId()]);
}
/**
* @When I go to edit page
*/
public function iGoToEditPage(): void
{
$this->productShowPage->switchToEditPage();
}
/**
* @When I go to show page
*/
public function iGoToShowPage(): void
{
$this->updateSimpleProductPage->switchToShowPage();
}
/**
* @When I go to edit page of :variant variant
*/
public function iGoToEditPageOfVariant(ProductVariantInterface $variant): void
{
$this->productShowPage->showVariantEditPage($variant);
}
/**
* @When /^I want to create a new (simple|configurable) product$/
*/
public function iWantToCreateANewProduct(string $productType): void
{
$productType = ProductTypeEnum::from($productType);
match ($productType) {
ProductTypeEnum::simple => $this->createSimpleProductPage->open(),
ProductTypeEnum::configurable => $this->createConfigurableProductPage->open(),
};
$this->currentProductType = $productType;
}
/**
* @When I want to modify the :product product
*/
public function iWantToModifyAProduct(ProductInterface $product): void
{
$this->updateSimpleProductPage->open(['id' => $product->getId()]);
}
/**
* @Then I should be on :product product edit page
*/
public function iShouldBeOnProductEditPage(ProductInterface $product): void
{
Assert::true($this->updateSimpleProductPage->isOpen(['id' => $product->getId()]));
}
/**
* @Then I should be on :variant variant edit page
*/
public function iShouldBeOnVariantEditPage(ProductVariantInterface $variant): void
{
Assert::true($this->updateVariantProductPage->isOpen(['productId' => $variant->getProduct()->getId(), 'id' => $variant->getId()]));
}
/**
* @Then I should be on :product product show page
*/
public function iShouldBeOnProductShowPage(ProductInterface $product): void
{
Assert::true($this->productShowPage->isOpen(['id' => $product->getId()]));
}
/**
* @Then I should not be able to open the product show page
*/
public function iShouldNotBeAbleToAccessTheProductShowPage(): void
{
match (ProductTypeEnum::from($this->currentProductType->value)) {
ProductTypeEnum::simple => Assert::false($this->updateSimpleProductPage->hasShowPageButton()),
ProductTypeEnum::configurable => Assert::false($this->createConfigurableProductPage->hasShowPageButton()),
};
}
}

View file

@ -52,7 +52,7 @@ final readonly class ProductCreationContext implements Context
$this->productChannelPricingsFormElement->specifyPrice($channel, $price);
$this->createPage->checkChannel($channel->getCode());
$this->productTaxonomyFormElement->selectMainTaxon($taxon);
$this->productTaxonomyFormElement->selectMainTaxon($taxon->getName());
$this->productTaxonomyFormElement->checkProductTaxon($taxon);
$this->createPage->create();

View file

@ -18,11 +18,11 @@ use Sylius\Behat\Element\Product\ShowPage\AssociationsElementInterface;
use Sylius\Behat\Element\Product\ShowPage\AttributesElementInterface;
use Sylius\Behat\Element\Product\ShowPage\DetailsElementInterface;
use Sylius\Behat\Element\Product\ShowPage\MediaElementInterface;
use Sylius\Behat\Element\Product\ShowPage\MoreDetailsElementInterface;
use Sylius\Behat\Element\Product\ShowPage\OptionsElementInterface;
use Sylius\Behat\Element\Product\ShowPage\PricingElementInterface;
use Sylius\Behat\Element\Product\ShowPage\ShippingElementInterface;
use Sylius\Behat\Element\Product\ShowPage\TaxonomyElementInterface;
use Sylius\Behat\Element\Product\ShowPage\TranslationsElementInterface;
use Sylius\Behat\Element\Product\ShowPage\VariantsElementInterface;
use Sylius\Behat\Page\Admin\Product\IndexPageInterface;
use Sylius\Behat\Page\Admin\Product\ShowPageInterface;
@ -30,10 +30,11 @@ use Sylius\Component\Core\Model\CatalogPromotionInterface;
use Sylius\Component\Core\Model\ChannelInterface;
use Sylius\Component\Core\Model\ProductInterface;
use Sylius\Component\Core\Model\ProductVariantInterface;
use Sylius\Component\Locale\Model\LocaleInterface;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Webmozart\Assert\Assert;
final class ProductShowPageContext implements Context
final readonly class ProductShowPageContext implements Context
{
public function __construct(
private IndexPageInterface $indexPage,
@ -42,7 +43,7 @@ final class ProductShowPageContext implements Context
private AttributesElementInterface $attributesElement,
private DetailsElementInterface $detailsElement,
private MediaElementInterface $mediaElement,
private MoreDetailsElementInterface $moreDetailsElement,
private TranslationsElementInterface $translationsElement,
private PricingElementInterface $pricingElement,
private ShippingElementInterface $shippingElement,
private TaxonomyElementInterface $taxonomyElement,
@ -93,14 +94,6 @@ final class ProductShowPageContext implements Context
$this->productShowPage->showProductInSingleChannel();
}
/**
* @When I go to edit page
*/
public function iGoToEditPage(): void
{
$this->productShowPage->showProductEditPage();
}
/**
* @When I access :product product
*/
@ -109,14 +102,6 @@ final class ProductShowPageContext implements Context
$this->productShowPage->open(['id' => $product->getId()]);
}
/**
* @When I go to edit page of :variant variant
*/
public function iGoToEditPageOfVariant(ProductVariantInterface $variant): void
{
$this->productShowPage->showVariantEditPage($variant);
}
/**
* @When I access the price history of a simple product for :channel channel
*/
@ -172,15 +157,15 @@ final class ProductShowPageContext implements Context
*/
public function iShouldSeeBreadcrumb(string $breadcrumb): void
{
Assert::same($breadcrumb, $this->productShowPage->getBreadcrumb());
Assert::contains($this->productShowPage->getBreadcrumb(), $breadcrumb);
}
/**
* @Then I should see price :price for channel :channelName
* @Then I should see price :price for channel :channel
*/
public function iShouldSeePriceForChannel(string $price, string $channelName): void
public function iShouldSeePriceForChannel(string $price, ChannelInterface $channel): void
{
Assert::same($this->pricingElement->getPriceForChannel($channelName), $price);
Assert::same($this->pricingElement->getPriceForChannel($channel->getCode()), $price);
}
/**
@ -239,11 +224,11 @@ final class ProductShowPageContext implements Context
}
/**
* @Then I should see original price :price for channel :channelName
* @Then I should see original price :price for channel :channel
*/
public function iShouldSeeOriginalPriceForChannel(string $originalPrice, string $channelName): void
public function iShouldSeeOriginalPriceForChannel(string $originalPrice, ChannelInterface $channel): void
{
Assert::same($this->pricingElement->getOriginalPriceForChannel($channelName), $originalPrice);
Assert::same($this->pricingElement->getOriginalPriceForChannel($channel->getCode()), $originalPrice);
}
/**
@ -257,9 +242,9 @@ final class ProductShowPageContext implements Context
/**
* @Then I should see the product is enabled for channel :channel
*/
public function iShouldSeeProductIsEnabledForChannels(string $channel): void
public function iShouldSeeProductIsEnabledForChannels(ChannelInterface $channel): void
{
Assert::true($this->detailsElement->hasChannel($channel));
Assert::true($this->detailsElement->hasChannel($channel->getCode()));
}
/**
@ -299,7 +284,7 @@ final class ProductShowPageContext implements Context
*/
public function iShouldSeeProductTaxon(string $taxonName): void
{
Assert::true($this->taxonomyElement->hasProductTaxon($taxonName));
Assert::contains($this->taxonomyElement->getProductTaxons(), $taxonName);
}
/**
@ -355,7 +340,7 @@ final class ProductShowPageContext implements Context
*/
public function iShouldSeeProductNameIs(string $name): void
{
Assert::same($this->moreDetailsElement->getName(), $name);
Assert::same($this->translationsElement->getName(), $name);
}
/**
@ -363,7 +348,7 @@ final class ProductShowPageContext implements Context
*/
public function iShouldSeeProductSlugIs(string $slug): void
{
Assert::same($this->moreDetailsElement->getSlug(), $slug);
Assert::same($this->translationsElement->getSlug(), $slug);
}
/**
@ -371,7 +356,7 @@ final class ProductShowPageContext implements Context
*/
public function iShouldSeeProductSDescriptionIs(string $description): void
{
Assert::same($this->moreDetailsElement->getDescription(), $description);
Assert::same($this->translationsElement->getDescription(), $description);
}
/**
@ -379,7 +364,7 @@ final class ProductShowPageContext implements Context
*/
public function iShouldSeeProductMetaKeywordsAre(string $metaKeywords): void
{
Assert::same($this->moreDetailsElement->getProductMetaKeywords(), $metaKeywords);
Assert::same($this->translationsElement->getProductMetaKeywords(), $metaKeywords);
}
/**
@ -387,7 +372,7 @@ final class ProductShowPageContext implements Context
*/
public function iShouldSeeProductShortDescriptionIs(string $shortDescription): void
{
Assert::same($this->moreDetailsElement->getShortDescription(), $shortDescription);
Assert::same($this->translationsElement->getShortDescription(), $shortDescription);
}
/**
@ -430,31 +415,31 @@ final class ProductShowPageContext implements Context
string $code,
string $price,
string $currentStock,
string $channel,
ChannelInterface $channel,
): void {
Assert::true($this->variantsElement->hasProductVariantWithCodePriceAndCurrentStock(
$variantName,
$code,
$price,
$currentStock,
$channel,
$channel->getCode(),
));
}
/**
* @Then I should see the :variantName variant
* @Then I should see the :variant variant
*/
public function iShouldSeeTheVariant(string $variantName): void
public function iShouldSeeTheVariant(ProductVariantInterface $variant): void
{
Assert::true($this->variantsElement->hasProductVariant($variantName));
Assert::true($this->variantsElement->hasProductVariant($variant->getCode()));
}
/**
* @Then I should see attribute :attribute with value :value in :nameOfLocale locale
* @Then I should see attribute :attribute with value :value in :locale locale
*/
public function iShouldSeeAttributeWithValueInLocale(string $attribute, string $value, string $nameOfLocale): void
public function iShouldSeeAttributeWithValueInLocale(string $attribute, string $value, LocaleInterface $locale): void
{
Assert::true($this->attributesElement->hasAttributeInLocale($attribute, $nameOfLocale, $value));
Assert::true($this->attributesElement->hasAttributeInLocale($attribute, $locale->getCode(), $value));
}
/**
@ -462,7 +447,7 @@ final class ProductShowPageContext implements Context
*/
public function iShouldSeeNonTranslatableAttributeWithValue(string $attribute, string $value): void
{
Assert::true($this->attributesElement->hasNonTranslatableAttribute($attribute, $value));
Assert::true($this->attributesElement->hasNonTranslatableAttribute($attribute, (float) $value / 100));
}
/**
@ -474,19 +459,19 @@ final class ProductShowPageContext implements Context
}
/**
* @Then this product price should be decreased by catalog promotion :catalogPromotion in :channelName channel
* @Then this product price should be decreased by catalog promotion :catalogPromotion in :channel channel
*/
public function thisProductPriceShouldBeDecreasedByCatalogPromotion(
CatalogPromotionInterface $catalogPromotion,
string $channelName,
ChannelInterface $channel,
): void {
Assert::inArray(
$catalogPromotion->getName(),
$this->pricingElement->getCatalogPromotionsNamesForChannel($channelName),
$this->pricingElement->getCatalogPromotionsNamesForChannel($channel->getCode()),
);
$url = $this->urlGenerator->generate('sylius_admin_catalog_promotion_show', ['id' => $catalogPromotion->getId()]);
Assert::inArray($url, $this->pricingElement->getCatalogPromotionLinksForChannel($channelName));
Assert::inArray($url, $this->pricingElement->getCatalogPromotionLinksForChannel($channel->getCode()));
}
/**

View file

@ -44,14 +44,19 @@ class FormElement extends Element implements FormElementInterface
public function getValidationErrors(): string
{
$validationMessage = $this->getDocument()->find('css', '.sylius-validation-error, .alert.alert-danger');
$validationMessage = $this->getDocument()->find('css', 'form .alert.alert-danger');
if (null === $validationMessage) {
throw new ElementNotFoundException($this->getSession(), 'Validation message', 'css', '.sylius-validation-error, .alert.alert-danger');
throw new ElementNotFoundException($this->getSession(), 'Validation message', 'css', 'form .alert.alert-danger');
}
return $validationMessage->getText();
}
public function hasFormErrorAlert(): bool
{
return $this->hasElement('form_error_alert');
}
/**
* @return array<string, string>
*/
@ -59,6 +64,7 @@ class FormElement extends Element implements FormElementInterface
{
return array_merge(parent::getDefinedElements(), [
'form' => 'form',
'form_error_alert' => '[data-test-form-error-alert]',
]);
}

View file

@ -31,4 +31,6 @@ interface FormElementInterface
* @throws ElementNotFoundException
*/
public function getValidationErrors(): string;
public function hasFormErrorAlert(): bool;
}

View file

@ -11,31 +11,26 @@
declare(strict_types=1);
namespace Sylius\Behat\Page\Admin\CustomerGroup;
namespace Sylius\Behat\Element\Admin\CustomerGroup;
use Behat\Mink\Element\NodeElement;
use Sylius\Behat\Behaviour\ChecksCodeImmutability;
use Sylius\Behat\Page\Admin\Crud\UpdatePage as BaseUpdatePage;
use Sylius\Behat\Element\Admin\Crud\FormElement as BaseFormElement;
class UpdatePage extends BaseUpdatePage implements UpdatePageInterface
final class FormElement extends BaseFormElement implements FormElementInterface
{
use ChecksCodeImmutability;
public function nameIt(string $name): void
protected function getDefinedElements(): array
{
$this->getElement('name')->setValue($name);
return array_merge(parent::getDefinedElements(), [
'code' => '[data-test-code]',
'name' => '[data-test-name]',
]);
}
protected function getCodeElement(): NodeElement
{
return $this->getElement('code');
}
protected function getDefinedElements(): array
{
return array_merge(parent::getDefinedElements(), [
'code' => '#sylius_admin_customer_group_code',
'name' => '#sylius_admin_customer_group_name',
]);
}
}

View file

@ -11,13 +11,11 @@
declare(strict_types=1);
namespace Sylius\Behat\Page\Admin\CustomerGroup;
namespace Sylius\Behat\Element\Admin\CustomerGroup;
use Sylius\Behat\Page\Admin\Crud\UpdatePageInterface as BaseUpdatePageInterface;
use Sylius\Behat\Element\Admin\Crud\FormElementInterface as BaseFormElementInterface;
interface UpdatePageInterface extends BaseUpdatePageInterface
interface FormElementInterface extends BaseFormElementInterface
{
public function nameIt(string $name): void;
public function isCodeDisabled(): bool;
}

View file

@ -13,7 +13,6 @@ declare(strict_types=1);
namespace Sylius\Behat\Element\Admin\ExchangeRate;
use Sylius\Behat\Behaviour\SpecifiesItsField;
use Sylius\Behat\Element\Admin\Crud\FormElement as BaseFormElement;
final class FormElement extends BaseFormElement implements FormElementInterface

View file

@ -48,11 +48,6 @@ final class ChannelPricingsFormElement extends BaseFormElement implements Channe
return !str_contains($this->getElement('channels')->getText(), $channelName);
}
public function getChannelPricingValidationMessage(): string
{
return $this->getElement('prices_validation_message')->getText();
}
protected function getDefinedElements(): array
{
return array_merge(parent::getDefinedElements(), [
@ -61,7 +56,6 @@ final class ChannelPricingsFormElement extends BaseFormElement implements Channe
'channels' => '[data-test-channels]',
'original_price' => '[data-test-original-price-in-channel="%channel_code%"]',
'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%"]',
]);
}

View file

@ -13,9 +13,10 @@ declare(strict_types=1);
namespace Sylius\Behat\Element\Admin\Product;
use Sylius\Behat\Element\Admin\Crud\FormElementInterface as BaseFormElementInterface;
use Sylius\Component\Core\Model\ChannelInterface;
interface ChannelPricingsFormElementInterface
interface ChannelPricingsFormElementInterface extends BaseFormElementInterface
{
public function specifyPrice(ChannelInterface $channel, string $price): void;
@ -26,6 +27,4 @@ interface ChannelPricingsFormElementInterface
public function getOriginalPriceForChannel(ChannelInterface $channel): string;
public function hasNoPriceForChannel(string $channelName): bool;
public function getChannelPricingValidationMessage(): string;
}

View file

@ -40,7 +40,7 @@ final class AssociationsElement extends Element implements AssociationsElementIn
protected function getDefinedElements(): array
{
return array_merge(parent::getDefinedElements(), [
'associations' => '#associations',
'associations' => '[data-test-associations]',
]);
}

View file

@ -17,27 +17,30 @@ use FriendsOfBehat\PageObjectExtension\Element\Element;
final class AttributesElement extends Element implements AttributesElementInterface
{
public function hasAttributeInLocale(string $attribute, string $locale, string $value): bool
public function hasAttributeInLocale(string $attribute, string $localeCode, string $value): bool
{
$values = $this->getDocument()->find('css', sprintf('#attributes .tab.segment[data-tab="%s"]', $locale));
$attributeValue = $this->getElement('attribute_with_locale', ['%locale_code%' => $localeCode]);
$attributeValue = $values->find('css', sprintf('tr:contains("%s") td:nth-child(2)', $attribute))->getText();
return $attributeValue === $value;
return str_contains($attributeValue->getText(), $value) && str_contains($attributeValue->getText(), $attribute);
}
public function hasNonTranslatableAttribute(string $attribute, string $value): bool
public function hasNonTranslatableAttribute(string $attribute, float|string $value): bool
{
$attributeValue = $this->getDocument()->find('css', sprintf('.ui.segment[data-tab="non-translatable"] tr:contains("%s") td:nth-child(2)', $attribute))->getText();
$attributeElement = $this->getElement('non_translatable-attribute');
$hasName = $attributeElement->has('css', sprintf('[data-test-non-translatable-attribute-name="%s"]', $attribute));
$hasValue = $attributeElement->has('css', sprintf('[data-test-non-translatable-attribute-value="%s"]', $value));
return str_contains($attributeValue, $value);
return $hasName && $hasValue;
}
protected function getDefinedElements(): array
{
return array_merge(parent::getDefinedElements(), [
'attribute_value_in_locale' => '.attributes:contains("%locale%") ~ table tr:contains("%attribute%") td:nth-child(2)',
'attributes_in_locale' => '#attributes :contains("%locale%")',
'attribute_name' => '[data-test-attribute-name="%name%"]',
'attribute_value' => '[data-test-attribute-value]',
'attribute_with_locale' => '[data-test-attribute-with-locale="%locale_code%"]',
'attribute_without_locale' => '[data-test-attribute-without-locale]',
'non_translatable-attribute' => '[data-test-non-translatable-attribute]',
]);
}
}

View file

@ -15,7 +15,7 @@ namespace Sylius\Behat\Element\Product\ShowPage;
interface AttributesElementInterface
{
public function hasAttributeInLocale(string $attribute, string $locale, string $value): bool;
public function hasAttributeInLocale(string $attribute, string $localeCode, string $value): bool;
public function hasNonTranslatableAttribute(string $attribute, string $value): bool;
public function hasNonTranslatableAttribute(string $attribute, float|string $value): bool;
}

View file

@ -13,7 +13,6 @@ declare(strict_types=1);
namespace Sylius\Behat\Element\Product\ShowPage;
use Behat\Mink\Element\NodeElement;
use FriendsOfBehat\PageObjectExtension\Element\Element;
final class DetailsElement extends Element implements DetailsElementInterface
@ -23,15 +22,10 @@ final class DetailsElement extends Element implements DetailsElementInterface
return $this->getElement('product_code')->getText();
}
public function hasChannel(string $channelName): bool
public function hasChannel(string $channelCode): bool
{
$channels = $this->getElement('channels');
/** @var NodeElement $channel */
foreach ($channels->findAll('css', 'span') as $channel) {
if ($channel->getText() === $channelName) {
return true;
}
if ($this->hasElement('channel', ['%channel_code%' => $channelCode])) {
return true;
}
return false;
@ -39,11 +33,11 @@ final class DetailsElement extends Element implements DetailsElementInterface
public function countChannels(): int
{
if (!$this->hasElement('channels')) {
if (!$this->hasElement('channel')) {
return 0;
}
$channels = $this->getElement('channels')->findAll('css', 'span.channel-name');
$channels = $this->getDocument()->findAll('css', ['data-test-channel']);
return \count($channels);
}
@ -61,10 +55,10 @@ final class DetailsElement extends Element implements DetailsElementInterface
protected function getDefinedElements(): array
{
return array_merge(parent::getDefinedElements(), [
'channels' => '#details tr:contains("Channels") td:nth-child(2)',
'current_stock' => '#details tr:contains("Current stock") td:nth-child(2)',
'product_code' => '#details tr:contains("Code") td:nth-child(2)',
'tax_category' => '#details tr:contains("Tax category") td:nth-child(2)',
'channel' => '[data-test-channel="%channel_code%"]',
'current_stock' => '[data-test-current-stock]',
'product_code' => '[data-test-product-code]',
'tax_category' => '[data-test-tax-category]',
]);
}
}

View file

@ -17,7 +17,7 @@ interface DetailsElementInterface
{
public function getProductCode(): string;
public function hasChannel(string $channelName): bool;
public function hasChannel(string $channelCode): bool;
public function countChannels(): int;

View file

@ -19,7 +19,7 @@ final class MediaElement extends Element implements MediaElementInterface
{
public function isImageDisplayed(): bool
{
$imageElement = $this->getDocument()->find('css', '#media a img');
$imageElement = $this->getDocument()->find('css', '[data-test-media] img');
if ($imageElement === null) {
return false;
}

View file

@ -21,20 +21,13 @@ final class OptionsElement extends Element implements OptionsElementInterface
{
$options = $this->getElement('options');
/** @var NodeElement $option */
foreach ($options->findAll('css', 'li') as $option) {
if ($option->getText() === $optionName) {
return true;
}
}
return false;
return $options->has('css', sprintf('div:contains("%s")', $optionName));
}
protected function getDefinedElements(): array
{
return array_merge(parent::getDefinedElements(), [
'options' => '#options ul',
'options' => '[data-test-options]',
]);
}
}

View file

@ -14,43 +14,44 @@ declare(strict_types=1);
namespace Sylius\Behat\Element\Product\ShowPage;
use Behat\Mink\Element\NodeElement;
use Behat\Mink\Exception\ElementNotFoundException;
use FriendsOfBehat\PageObjectExtension\Element\Element;
final class PricingElement extends Element implements PricingElementInterface
{
public function getPriceForChannel(string $channelName): string
public function getPriceForChannel(string $channelCode): string
{
$channelPriceRow = $this->getChannelPriceRow($channelName);
$channelPriceRow = $this->getChannelPriceRow($channelCode);
if (null === $channelPriceRow) {
return '';
}
$priceForChannel = $channelPriceRow->find('css', 'td:nth-child(2)');
$priceForChannel = $channelPriceRow->find('css', '[data-test-price]');
return $priceForChannel->getText();
}
public function getOriginalPriceForChannel(string $channelName): string
public function getOriginalPriceForChannel(string $channelCode): string
{
$channelPriceRow = $this->getChannelPriceRow($channelName);
$channelPriceRow = $this->getChannelPriceRow($channelCode);
$priceForChannel = $channelPriceRow->find('css', 'td:nth-child(3)');
$priceForChannel = $channelPriceRow->find('css', '[data-test-original-price]');
return $priceForChannel->getText();
}
public function getCatalogPromotionsNamesForChannel(string $channelName): array
public function getCatalogPromotionsNamesForChannel(string $channelCode): array
{
/** @var NodeElement[] $appliedPromotions */
$appliedPromotions = $this->getAppliedPromotionsForChannel($channelName);
$appliedPromotions = $this->getAppliedPromotionsForChannel($channelCode);
return array_map(fn (NodeElement $element): string => $element->getText(), $appliedPromotions);
}
public function getCatalogPromotionLinksForChannel(string $channelName): array
public function getCatalogPromotionLinksForChannel(string $channelCode): array
{
$appliedPromotions = $this->getAppliedPromotionsForChannel($channelName);
$appliedPromotions = $this->getAppliedPromotionsForChannel($channelCode);
return array_map(fn (NodeElement $element): string => $element->getAttribute('href'), $appliedPromotions);
}
@ -70,35 +71,40 @@ final class PricingElement extends Element implements PricingElementInterface
public function getSimpleProductPricingRowForChannel(string $channelCode): NodeElement
{
return $this->getElement('simple_product_pricing_row', ['%channelCode%' => $channelCode]);
return $this->getElement('simple_product_pricing_row', ['%channel_code%' => $channelCode]);
}
public function getVariantPricingRowForChannel(string $variantCode, string $channelCode): NodeElement
{
return $this->getElement('variant_pricing_row', [
'%variantCode%' => $variantCode,
'%channelCode%' => $channelCode,
'%variant_code%' => $variantCode,
'%channel_code%' => $channelCode,
]);
}
protected function getDefinedElements(): array
{
return array_merge(parent::getDefinedElements(), [
'simple_product_pricing_row' => '[data-test-simple-product="%channelCode%"]',
'variant_pricing_row' => '[data-test-variant-pricing="%channelCode%.%variantCode%"]',
'price_row' => '[data-test-pricing="%channel_code%"]',
'simple_product_pricing_row' => '[data-test-simple-product="%channel_code%"]',
'variant_pricing_row' => '[data-test-variant-pricing="%channel_code%.%variant_code%"]',
]);
}
private function getAppliedPromotionsForChannel(string $channelName): array
private function getAppliedPromotionsForChannel(string $channelCode): array
{
/** @var NodeElement $channelPriceRow */
$channelPriceRow = $this->getChannelPriceRow($channelName);
$channelPriceRow = $this->getChannelPriceRow($channelCode);
return $channelPriceRow->findAll('css', '.applied-promotion');
return $channelPriceRow->findAll('css', '[data-test-applied-promotion]');
}
private function getChannelPriceRow(string $channelName): ?NodeElement
private function getChannelPriceRow(string $channelCode): ?NodeElement
{
return $this->getDocument()->find('css', sprintf('#pricing tr:contains("%s")', $channelName));
try {
return $this->getElement('price_row', ['%channel_code%' => $channelCode]);
} catch (ElementNotFoundException) {
return null;
}
}
}

View file

@ -17,13 +17,13 @@ use Behat\Mink\Element\NodeElement;
interface PricingElementInterface
{
public function getPriceForChannel(string $channelName): string;
public function getPriceForChannel(string $channelCode): string;
public function getOriginalPriceForChannel(string $channelName): string;
public function getOriginalPriceForChannel(string $channelCode): string;
public function getCatalogPromotionsNamesForChannel(string $channelName): array;
public function getCatalogPromotionsNamesForChannel(string $channelCode): array;
public function getCatalogPromotionLinksForChannel(string $channelName): array;
public function getCatalogPromotionLinksForChannel(string $channelCode): array;
public function getLowestPriceBeforeDiscountForChannel(string $channelCode): string;

View file

@ -45,11 +45,11 @@ final class ShippingElement extends Element implements ShippingElementInterface
protected function getDefinedElements(): array
{
return array_merge(parent::getDefinedElements(), [
'product_depth' => '#shipping tr:contains("Depth") td:nth-child(2)',
'product_height' => '#shipping tr:contains("Height") td:nth-child(2)',
'product_weight' => '#shipping tr:contains("Weight") td:nth-child(2)',
'product_width' => '#shipping tr:contains("Width") td:nth-child(2)',
'shipping_category' => '#shipping tr:contains("Shipping category") td:nth-child(2)',
'product_depth' => '[data-test-depth]',
'product_height' => '[data-test-height]',
'product_weight' => '[data-test-weight]',
'product_width' => '[data-test-width]',
'shipping_category' => '[data-test-shipping-category]',
]);
}
}

View file

@ -13,7 +13,6 @@ declare(strict_types=1);
namespace Sylius\Behat\Element\Product\ShowPage;
use Behat\Mink\Element\NodeElement;
use FriendsOfBehat\PageObjectExtension\Element\Element;
final class TaxonomyElement extends Element implements TaxonomyElementInterface
@ -23,25 +22,16 @@ final class TaxonomyElement extends Element implements TaxonomyElementInterface
return $this->getElement('main_taxon')->getText();
}
public function hasProductTaxon(string $taxonName): bool
public function getProductTaxons(): string
{
$taxons = $this->getElement('product_taxon');
/** @var NodeElement $taxon */
foreach ($taxons->findAll('css', 'li') as $taxon) {
if ($taxon->getText() === $taxonName) {
return true;
}
}
return false;
return $this->getElement('product_taxons')->getText();
}
protected function getDefinedElements(): array
{
return array_merge(parent::getDefinedElements(), [
'main_taxon' => '#taxonomy tr:contains("Main taxon") td:nth-child(2)',
'product_taxon' => '#taxonomy tr:contains("Product taxon") td:nth-child(2)',
'main_taxon' => '[data-test-main-taxon]',
'product_taxons' => '[data-test-product-taxons]',
]);
}
}

View file

@ -17,5 +17,5 @@ interface TaxonomyElementInterface
{
public function getProductMainTaxon(): string;
public function hasProductTaxon(string $taxonName): bool;
public function getProductTaxons(): string;
}

View file

@ -15,7 +15,7 @@ namespace Sylius\Behat\Element\Product\ShowPage;
use FriendsOfBehat\PageObjectExtension\Element\Element;
final class MoreDetailsElement extends Element implements MoreDetailsElementInterface
final class TranslationsElement extends Element implements TranslationsElementInterface
{
public function getDescription(): string
{
@ -50,12 +50,12 @@ final class MoreDetailsElement extends Element implements MoreDetailsElementInte
protected function getDefinedElements(): array
{
return array_merge(parent::getDefinedElements(), [
'description' => '#more-details tr:contains("Description") td:nth-child(2)',
'meta_description' => '#more-details tr:contains("Meta description") td:nth-child(2)',
'meta_keywords' => '#more-details tr:contains("Meta keywords") td:nth-child(2)',
'name' => '#more-details tr:contains("Name") td:nth-child(2)',
'short_description' => '#more-details tr:contains("Short description") td:nth-child(2)',
'slug' => '#more-details tr:contains("Slug") td:nth-child(2)',
'description' => '#product-translations [data-test-description]',
'meta_description' => '#product-translations [data-test-meta-description]',
'meta_keywords' => '#product-translations [data-test-meta-keywords]',
'name' => '#product-translations [data-test-product-name]',
'short_description' => '#product-translations [data-test-short-description]',
'slug' => '#product-translations [data-test-slug]',
]);
}
}

View file

@ -13,7 +13,7 @@ declare(strict_types=1);
namespace Sylius\Behat\Element\Product\ShowPage;
interface MoreDetailsElementInterface
interface TranslationsElementInterface
{
public function getName(): string;

View file

@ -21,23 +21,14 @@ final class VariantsElement extends Element implements VariantsElementInterface
public function countVariantsOnPage(): int
{
/** @var NodeElement $variants|array */
$variants = $this->getDocument()->findAll('css', '#variants .item');
$variants = $this->getDocument()->findAll('css', '[data-test-variant]');
return \count($variants);
}
public function hasProductVariant(string $name): bool
public function hasProductVariant(string $code): bool
{
$variantRows = $this->getDocument()->findAll('css', '#variants .variants-accordion__title');
/** @var NodeElement $variant */
foreach ($variantRows as $variant) {
if ($variant->find('css', '.content .variant-name')->getText() === $name) {
return true;
}
}
return false;
return $this->hasElement('variant', ['%code%' => $code]);
}
public function hasProductVariantWithCodePriceAndCurrentStock(
@ -45,10 +36,10 @@ final class VariantsElement extends Element implements VariantsElementInterface
string $code,
string $price,
string $currentStock,
string $channel,
string $channelCode,
): bool {
/** @var NodeElement $variantRow */
$variantRows = $this->getDocument()->findAll('css', '#variants .variants-accordion__title');
$variantRows = $this->getDocument()->findAll('css', '[data-test-variant]');
/** @var NodeElement $variant */
foreach ($variantRows as $variant) {
@ -59,7 +50,7 @@ final class VariantsElement extends Element implements VariantsElementInterface
$code,
$price,
$currentStock,
$channel,
$channelCode,
)
) {
return true;
@ -84,33 +75,34 @@ final class VariantsElement extends Element implements VariantsElementInterface
return false;
}
protected function getDefinedElements(): array
{
return array_merge(parent::getDefinedElements(), [
'variant' => '[data-test-variant="%code%"]',
'variant_pricing_row' => '[data-test-variant-pricing="%channel_code%.%variant_code%"]',
]);
}
private function hasProductWithGivenNameCodePriceAndCurrentStock(
NodeElement $variant,
string $name,
string $code,
string $price,
string $currentStock,
string $channel,
string $channelCode,
): bool {
$variantContent = $variant->getParent()->find(
'css',
sprintf('.variants-accordion__content.%s', $this->getItemIndexClass($variant)),
);
if (
$variant->find('css', '.content .variant-name')->getText() === $name &&
$variant->find('css', '.content .variant-code')->getText() === $code &&
$variantContent->find('css', sprintf('tr.pricing:contains("%s") td:nth-child(2)', $channel))->getText() === $price &&
$variant->find('css', '.current-stock')->getText() === $currentStock
$variant->find('css', '[data-test-product-variant-code]')->getText() === $code &&
$variant->find('css', '[data-test-product-variant-name]')->getText() === $name &&
$this->getElement('variant_pricing_row', [
'%channel_code%' => $channelCode,
'%variant_code%' => $code,
])->find('css', '[data-test-price]')->getText() === $price &&
$variant->find('css', '[data-test-current-stock]')->getText() === $currentStock
) {
return true;
}
return false;
}
private function getItemIndexClass(NodeElement $variant): string
{
return explode(' ', $variant->getAttribute('class'))[1];
}
}

View file

@ -17,14 +17,14 @@ interface VariantsElementInterface
{
public function countVariantsOnPage(): int;
public function hasProductVariant(string $name): bool;
public function hasProductVariant(string $code): bool;
public function hasProductVariantWithCodePriceAndCurrentStock(
string $name,
string $code,
string $price,
string $currentStock,
string $channel,
string $channelCode,
): bool;
public function hasProductVariantWithLowestPriceBeforeDiscountInChannel(

View file

@ -28,7 +28,7 @@ class CreatePage extends SymfonyPage implements CreatePageInterface
Session $session,
$minkParameters,
RouterInterface $router,
private string $routeName,
private readonly string $routeName,
) {
parent::__construct($session, $minkParameters, $router);
}
@ -41,9 +41,9 @@ class CreatePage extends SymfonyPage implements CreatePageInterface
$this->getDocument()->pressButton('Create');
}
public function getValidationMessage(string $element): string
public function getValidationMessage(string $element, array $parameters = []): string
{
$foundElement = $this->getFieldElement($element);
$foundElement = $this->getFieldElement($element, $parameters);
if (null === $foundElement) {
throw new ElementNotFoundException($this->getSession(), 'Field element');
}
@ -61,17 +61,25 @@ class CreatePage extends SymfonyPage implements CreatePageInterface
return $this->routeName;
}
public function cancelChanges(): void
{
$this->getElement('cancel_button')->click();
}
public function getMessageInvalidForm(): string
{
return $this->getDocument()->find('css', '.ui.icon.negative.message')->getText();
}
/**
* @return array<string, string>
*/
protected function getDefinedElements(): array
{
return array_merge(
parent::getDefinedElements(),
['form' => 'form'],
);
return array_merge(parent::getDefinedElements(), [
'form' => 'form',
'cancel_button' => '[data-test-cancel-changes-button]',
]);
}
protected function waitForFormUpdate(): void
@ -104,9 +112,9 @@ class CreatePage extends SymfonyPage implements CreatePageInterface
/**
* @throws ElementNotFoundException
*/
private function getFieldElement(string $element): ?NodeElement
private function getFieldElement(string $element, array $parameters = []): ?NodeElement
{
$element = $this->getElement($element);
$element = $this->getElement($element, $parameters);
while (null !== $element && !$element->hasClass('field')) {
$element = $element->getParent();
}

View file

@ -21,7 +21,7 @@ interface CreatePageInterface extends SymfonyPageInterface
/**
* @throws ElementNotFoundException
*/
public function getValidationMessage(string $element): string;
public function getValidationMessage(string $element, array $parameters = []): string;
/**
* @throws ElementNotFoundException

View file

@ -27,8 +27,8 @@ class IndexPage extends SymfonyPage implements IndexPageInterface
Session $session,
$minkParameters,
RouterInterface $router,
private TableAccessorInterface $tableAccessor,
private string $routeName,
private readonly TableAccessorInterface $tableAccessor,
private readonly string $routeName,
) {
parent::__construct($session, $minkParameters, $router);
}
@ -165,6 +165,16 @@ class IndexPage extends SymfonyPage implements IndexPageInterface
return $this->routeName;
}
public function goToPage(int $page): void
{
$this->getElement('page_button', ['%page%' => $page])->click();
}
public function getPageNumber(): int
{
return (int) $this->getElement('current_page')->getText();
}
protected function getTableAccessor(): TableAccessorInterface
{
return $this->tableAccessor;
@ -200,10 +210,12 @@ class IndexPage extends SymfonyPage implements IndexPageInterface
return array_merge(parent::getDefinedElements(), [
'bulk_actions' => '.sylius-grid-nav__bulk',
'bulk_delete_confirm_button' => '[data-test-modal="bulk-delete"] [data-test-confirm-button]',
'enabled_filter' => '#criteria_enabled',
'current_page' => '[data-test-current-page]',
'enabled_filter' => '[data-test-criterion-enabled]',
'filter' => '[data-test-filter]',
'filters_form' => '[data-test-filters-form]',
'filters_toggle' => '.accordion-button',
'page_button' => '[data-test-page="%page%"]',
'table' => '.table',
]);
}

View file

@ -1,32 +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\CustomerGroup;
use Sylius\Behat\Behaviour\NamesIt;
use Sylius\Behat\Behaviour\SpecifiesItsField;
use Sylius\Behat\Page\Admin\Crud\CreatePage as BaseCreatePage;
class CreatePage extends BaseCreatePage implements CreatePageInterface
{
use SpecifiesItsField;
use NamesIt;
protected function getDefinedElements(): array
{
return array_merge(parent::getDefinedElements(), [
'code' => '#sylius_admin_customer_group_code',
'name' => '#sylius_admin_customer_group_name',
]);
}
}

View file

@ -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\CustomerGroup;
use Sylius\Behat\Page\Admin\Crud\CreatePageInterface as BaseCreatePageInterface;
interface CreatePageInterface extends BaseCreatePageInterface
{
public function specifyCode(string $code): void;
public function nameIt(string $name): void;
}

View file

@ -0,0 +1,21 @@
<?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;
use FriendsOfBehat\PageObjectExtension\Page\SymfonyPageInterface;
interface EditToShowPageSwitcherInterface extends SymfonyPageInterface
{
public function switchToShowPage(): void;
}

View file

@ -27,7 +27,7 @@ class ShowPage extends SymfonyPage implements ShowPageInterface
Session $session,
$minkParameters,
RouterInterface $router,
private TableAccessorInterface $tableAccessor,
private readonly TableAccessorInterface $tableAccessor,
) {
parent::__construct($session, $minkParameters, $router);
}
@ -314,9 +314,9 @@ class ShowPage extends SymfonyPage implements ShowPageInterface
public function hasNote(string $note): bool
{
$orderNotesElement = $this->getElement('order_notes');
$notes = $this->getElement('notes');
return $orderNotesElement->getText() === $note;
return $notes->getText() === $note;
}
public function hasShippingProvinceName(string $provinceName): bool
@ -388,32 +388,35 @@ class ShowPage extends SymfonyPage implements ShowPageInterface
return $this->getElement('shipment_shipped_at_date')->getText();
}
/**
* @return array<string, string>
*/
protected function getDefinedElements(): array
{
return array_merge(parent::getDefinedElements(), [
'billing_address' => '[data-test-billing-address]',
'cancel_order' => '[data-test-cancel-order]',
'currency' => '#sylius-order-currency',
'currency' => '[data-test-currency]',
'customer_email' => '[data-test-customer] [data-test-email]',
'ip_address' => '#ipAddress',
'item' => '[data-test-item="%name%"]',
'items_total' => '[data-test-items-total]',
'order_notes' => '#sylius-order-notes',
'notes' => '[data-test-notes]',
'order_payment_state' => '[data-test-order-payment-state]',
'order_shipping_state' => '[data-test-order-shipping-state]',
'order_state' => '[data-test-order-state]',
'order_total' => '[data-test-order-total]',
'payments' => '[data-test-payments]',
'payment_complete' => '[data-test-complete-payment="%paymentId%"]',
'payment_refund' => '[data-test-refund-payment="%paymentId%"]',
'payments' => '[data-test-payments]',
'promotion' => '[data-test-promotion="%name%"]',
'promotion_total' => '[data-test-promotion-total]',
'resend_order_confirmation_email' => '[data-test-resend-order-confirmation-email]',
'resend_shipment_confirmation_email' => '[data-test-resend-shipment-confirmation-email]',
'shipment_shipped_at_date' => '[data-test-shipments] [data-test-shipped-at-date]',
'shipments' => '[data-test-shipments]',
'shipment_tracking' => '[data-test-shipment-tracking]',
'shipment_ship_button' => '[data-test-shipment-ship-button]',
'shipment_shipped_at_date' => '[data-test-shipments] [data-test-shipped-at-date]',
'shipment_tracking' => '[data-test-shipment-tracking]',
'shipments' => '[data-test-shipments]',
'shipping' => '[data-test-shipping="%name%"]',
'shipping_address' => '[data-test-shipping-address]',
'shipping_adjustment_name' => '#shipping-adjustment-label',
@ -426,11 +429,6 @@ class ShowPage extends SymfonyPage implements ShowPageInterface
]);
}
protected function getTableAccessor(): TableAccessorInterface
{
return $this->tableAccessor;
}
protected function hasAddress(string $elementText, string $customerName, string $street, string $postcode, string $city, string $countryName): bool
{
return

View file

@ -33,11 +33,6 @@ class CreatePage extends BaseCreatePage implements CreatePageInterface
);
}
public function cancelChanges(): void
{
$this->getElement('cancel_button')->click();
}
public function checkChannel(string $channelName): void
{
$this->getDocument()->checkField($channelName);
@ -105,7 +100,6 @@ class CreatePage extends BaseCreatePage implements CreatePageInterface
protected function getDefinedElements(): array
{
return array_merge(parent::getDefinedElements(), [
'cancel_button' => '[data-test-cancel-changes-button]',
'code' => '#sylius_admin_payment_method_code',
'enabled' => '#sylius_admin_payment_method_enabled',
'gateway_name' => '#sylius_admin_payment_method_gatewayConfig_gatewayName',

View file

@ -15,6 +15,7 @@ namespace Sylius\Behat\Page\Admin\Product;
use Behat\Mink\Element\NodeElement;
use Behat\Mink\Session;
use Sylius\Behat\Context\Ui\Admin\Helper\NavigationTrait;
use Sylius\Behat\Page\Admin\Crud\CreatePage as BaseCreatePage;
use Sylius\Behat\Service\DriverHelper;
use Sylius\Behat\Service\Helper\AutocompleteHelperInterface;
@ -22,6 +23,14 @@ use Symfony\Component\Routing\RouterInterface;
class CreateConfigurableProductPage extends BaseCreatePage implements CreateConfigurableProductPageInterface
{
use NavigationTrait;
/**
* @template TKey of array-key
* @template TValue
*
* @param array<TKey, TValue>|\ArrayAccess<TKey, TValue> $minkParameters
*/
public function __construct(
Session $session,
$minkParameters,
@ -32,6 +41,11 @@ class CreateConfigurableProductPage extends BaseCreatePage implements CreateConf
parent::__construct($session, $minkParameters, $router, $routeName);
}
public function getResourceName(): string
{
return 'product';
}
public function create(): void
{
$this->waitForFormUpdate();
@ -57,9 +71,7 @@ class CreateConfigurableProductPage extends BaseCreatePage implements CreateConf
$this->autocompleteHelper->selectByName($this->getDriver(), $productOptionsAutocomplete->getXpath(), $optionName);
}
/**
* @return string[]
*/
/** @return array<string, string> */
protected function getDefinedElements(): array
{
return array_merge(
@ -71,6 +83,7 @@ class CreateConfigurableProductPage extends BaseCreatePage implements CreateConf
'code' => '[data-test-code]',
'enabled' => '[data-test-enabled]',
'product_options_autocomplete' => '[data-test-product-options-autocomplete]',
'show_product_button' => '[data-test-show-product]',
'side_navigation_tab' => '[data-test-side-navigation-tab="%name%"]',
],
);

View file

@ -14,8 +14,9 @@ declare(strict_types=1);
namespace Sylius\Behat\Page\Admin\Product;
use Sylius\Behat\Page\Admin\Crud\CreatePageInterface as BaseCreatePageInterface;
use Sylius\Behat\Page\Admin\ShowPageButtonCheckerInterface;
interface CreateConfigurableProductPageInterface extends BaseCreatePageInterface
interface CreateConfigurableProductPageInterface extends BaseCreatePageInterface, ShowPageButtonCheckerInterface
{
public function selectOption(string $optionName): void;

View file

@ -15,6 +15,7 @@ namespace Sylius\Behat\Page\Admin\Product;
use Behat\Mink\Element\NodeElement;
use Behat\Mink\Session;
use Sylius\Behat\Context\Ui\Admin\Helper\NavigationTrait;
use Sylius\Behat\Page\Admin\Crud\CreatePage as BaseCreatePage;
use Sylius\Behat\Service\DriverHelper;
use Sylius\Behat\Service\Helper\AutocompleteHelperInterface;
@ -22,6 +23,14 @@ use Symfony\Component\Routing\RouterInterface;
class CreateSimpleProductPage extends BaseCreatePage implements CreateSimpleProductPageInterface
{
use NavigationTrait;
/**
* @template TKey of array-key
* @template TValue
*
* @param array<TKey, TValue>|\ArrayAccess<TKey, TValue> $minkParameters
*/
public function __construct(
Session $session,
$minkParameters,
@ -32,6 +41,11 @@ class CreateSimpleProductPage extends BaseCreatePage implements CreateSimpleProd
parent::__construct($session, $minkParameters, $router, $routeName);
}
public function getResourceName(): string
{
return 'product';
}
public function getRouteName(): string
{
return parent::getRouteName() . '_simple';
@ -51,11 +65,6 @@ class CreateSimpleProductPage extends BaseCreatePage implements CreateSimpleProd
$this->getElement('channel', ['%channel_code%' => $channelCode])->check();
}
public function cancelChanges(): void
{
$this->getElement('cancel_button')->click();
}
private function changeTab(string $tabName): void
{
if (DriverHelper::isNotJavascript($this->getDriver())) {
@ -110,6 +119,7 @@ class CreateSimpleProductPage extends BaseCreatePage implements CreateSimpleProd
return parent::getElement($name, $parameters);
}
/** @return array<string, string> */
protected function getDefinedElements(): array
{
return array_merge(
@ -121,6 +131,7 @@ class CreateSimpleProductPage extends BaseCreatePage implements CreateSimpleProd
'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-show-product]',
'side_navigation_tab' => '[data-test-side-navigation-tab="%name%"]',
],
);

View file

@ -14,8 +14,9 @@ declare(strict_types=1);
namespace Sylius\Behat\Page\Admin\Product;
use Sylius\Behat\Page\Admin\Crud\CreatePageInterface as BaseCreatePageInterface;
use Sylius\Behat\Page\Admin\ShowPageButtonCheckerInterface;
interface CreateSimpleProductPageInterface extends BaseCreatePageInterface
interface CreateSimpleProductPageInterface extends BaseCreatePageInterface, ShowPageButtonCheckerInterface
{
public function checkChannel(string $channelCode): void;

View file

@ -80,12 +80,8 @@ class IndexPage extends CrudIndexPage implements IndexPageInterface
$table = $this->getElement('table');
$row = $tableAccessor->getRowWithFields($table, ['name' => $productName]);
$field = $tableAccessor->getFieldFromRow($table, $row, 'actions');
$field->clickLink('details');
}
public function goToPage(int $page): void
{
$this->getElement('pagination_button', ['%page%' => $page])->click();
$field->find('css', '[data-test-show-action="Details"]')->click();
}
public function checkFirstProductHasDataAttribute(string $attributeName): bool
@ -98,11 +94,7 @@ class IndexPage extends CrudIndexPage implements IndexPageInterface
return $this->getElement('last_product')->find('css', sprintf('[%s]', $attributeName)) !== null;
}
public function getPageNumber(): int
{
return (int) $this->getElement('page_number')->getText();
}
/** @return array<string, string> */
protected function getDefinedElements(): array
{
return array_merge(parent::getDefinedElements(), [
@ -111,9 +103,6 @@ class IndexPage extends CrudIndexPage implements IndexPageInterface
'first_product' => '.table > tbody > tr:first-child',
'last_product' => '.table > tbody > tr:last-child',
'main_taxon_filter' => '#criteria_main_taxon',
'page_number' => '.sylius-grid-nav__pagination .active',
'pagination_button' => '.sylius-grid-nav__pagination a.item:contains("%page%")',
'pagination_buttons' => '.sylius-grid-nav__pagination',
'taxon_filter' => '#criteria_taxon',
]);
}

View file

@ -58,6 +58,7 @@ class IndexPerTaxonPage extends CrudIndexPage implements IndexPerTaxonPageInterf
$this->getDocument()->waitFor(5, fn () => null === $saveConfigurationButton->find('css', '.loading'));
}
/** @return array<string, string> */
protected function getDefinedElements(): array
{
return array_merge(parent::getDefinedElements(), [

View file

@ -14,11 +14,32 @@ declare(strict_types=1);
namespace Sylius\Behat\Page\Admin\Product;
use Behat\Mink\Element\NodeElement;
use Behat\Mink\Session;
use FriendsOfBehat\PageObjectExtension\Page\SymfonyPage;
use Sylius\Behat\Context\Ui\Admin\Helper\NavigationTrait;
use Sylius\Component\Core\Model\ProductVariantInterface;
use Symfony\Component\Routing\RouterInterface;
class ShowPage extends SymfonyPage implements ShowPageInterface
{
use NavigationTrait;
/**
* @template TKey of array-key
* @template TValue
*
* @param array<TKey, TValue>|\ArrayAccess<TKey, TValue> $minkParameters
*/
public function __construct(Session $session, $minkParameters, RouterInterface $router)
{
parent::__construct($session, $minkParameters, $router);
}
public function getResourceName(): string
{
return 'product';
}
public function isSimpleProductPage(): bool
{
return !$this->hasElement('variants');
@ -29,6 +50,7 @@ class ShowPage extends SymfonyPage implements ShowPageInterface
return $this->getElement('show_product_button')->hasClass('disabled');
}
/** @return string[] */
public function getAppliedCatalogPromotionsLinks(string $variantName, string $channelName): array
{
$appliedPromotions = $this->getAppliedCatalogPromotions($variantName, $channelName);
@ -36,6 +58,7 @@ class ShowPage extends SymfonyPage implements ShowPageInterface
return array_map(fn (NodeElement $element): string => $element->getAttribute('href'), $appliedPromotions);
}
/** @return string[] */
public function getAppliedCatalogPromotionsNames(string $variantName, string $channelName): array
{
$appliedPromotions = $this->getAppliedCatalogPromotions($variantName, $channelName);
@ -68,28 +91,25 @@ class ShowPage extends SymfonyPage implements ShowPageInterface
$this->getElement('show_product_button')->click();
}
public function showProductEditPage(): void
{
$this->getElement('edit_product_button')->click();
}
public function showVariantEditPage(ProductVariantInterface $variant): void
{
$this->getElement('edit_variant_button', ['%variantCode%' => $variant->getCode()])->click();
$this->getElement('edit_variant_button', ['%variant_code%' => $variant->getCode()])->click();
}
/** @return array<string, string> */
protected function getDefinedElements(): array
{
return array_merge(parent::getDefinedElements(), [
'breadcrumb' => '.breadcrumb > div',
'edit_product_button' => '#edit-product',
'edit_variant_button' => '#variants .variants-accordion__title:contains("%variantCode%") .edit-variant',
'product_name' => '#header h1 .content > span',
'breadcrumb' => '.breadcrumb',
'edit_product_button' => '[data-test-edit-product]',
'edit_variant_button' => '[data-test-edit-variant="%variant_code%"]',
'product_name' => '[data-test-product-name]',
'show_product_button' => '[data-test-view-in-store]',
'variants' => '#variants',
'variants' => '[data-test-variant-pricing]',
]);
}
/** @return NodeElement[] */
private function getAppliedCatalogPromotions(string $variantName, string $channelName): array
{
$pricingElement = $this->getPricingRow($variantName, $channelName);

View file

@ -14,12 +14,15 @@ declare(strict_types=1);
namespace Sylius\Behat\Page\Admin\Product;
use FriendsOfBehat\PageObjectExtension\Page\SymfonyPageInterface;
use Sylius\Behat\Page\Admin\ShowToEditPageSwitcherInterface;
use Sylius\Component\Core\Model\ProductVariantInterface;
interface ShowPageInterface extends SymfonyPageInterface
interface ShowPageInterface extends SymfonyPageInterface, ShowToEditPageSwitcherInterface
{
/** @return string[] */
public function getAppliedCatalogPromotionsLinks(string $variantName, string $channelName): array;
/** @return string[] */
public function getAppliedCatalogPromotionsNames(string $variantName, string $channelName): array;
public function getName(): string;
@ -34,7 +37,5 @@ interface ShowPageInterface extends SymfonyPageInterface
public function showProductInSingleChannel(): void;
public function showProductEditPage(): void;
public function showVariantEditPage(ProductVariantInterface $variant): void;
}

View file

@ -16,6 +16,7 @@ namespace Sylius\Behat\Page\Admin\Product;
use Behat\Mink\Element\NodeElement;
use Behat\Mink\Session;
use Sylius\Behat\Behaviour\ChecksCodeImmutability;
use Sylius\Behat\Context\Ui\Admin\Helper\NavigationTrait;
use Sylius\Behat\Page\Admin\Crud\UpdatePage as BaseUpdatePage;
use Sylius\Behat\Service\AutocompleteHelper;
use Sylius\Behat\Service\Helper\AutocompleteHelperInterface;
@ -24,6 +25,7 @@ use Symfony\Component\Routing\RouterInterface;
class UpdateConfigurableProductPage extends BaseUpdatePage implements UpdateConfigurableProductPageInterface
{
use ChecksCodeImmutability;
use NavigationTrait;
/**
* @param array<array-key, string> $minkParameters
@ -38,6 +40,11 @@ class UpdateConfigurableProductPage extends BaseUpdatePage implements UpdateConf
parent::__construct($session, $minkParameters, $router, $routeName);
}
protected function getResourceName(): string
{
return 'product';
}
public function saveChanges(): void
{
$this->waitForFormUpdate();
@ -105,9 +112,7 @@ class UpdateConfigurableProductPage extends BaseUpdatePage implements UpdateConf
return $this->getElement('code');
}
/**
* @return string[]
*/
/** @return array<string, string> */
protected function getDefinedElements(): array
{
return array_merge(
@ -120,6 +125,7 @@ class UpdateConfigurableProductPage extends BaseUpdatePage implements UpdateConf
'enabled' => '[data-test-enabled]',
'options' => '[data-test-options]',
'product_options_autocomplete' => '[data-test-product-options-autocomplete]',
'show_product_button' => '[data-test-show-product]',
'side_navigation_tab' => '[data-test-side-navigation-tab="%name%"]',
],
);

View file

@ -14,8 +14,13 @@ declare(strict_types=1);
namespace Sylius\Behat\Page\Admin\Product;
use Sylius\Behat\Page\Admin\Crud\UpdatePageInterface;
use Sylius\Behat\Page\Admin\EditToShowPageSwitcherInterface;
use Sylius\Behat\Page\Admin\ShowPageButtonCheckerInterface;
interface UpdateConfigurableProductPageInterface extends UpdatePageInterface
interface UpdateConfigurableProductPageInterface extends
UpdatePageInterface,
EditToShowPageSwitcherInterface,
ShowPageButtonCheckerInterface
{
public function isCodeDisabled(): bool;

Some files were not shown because too many files have changed in this diff Show more