From 37dc341f9634ee40c5126e951112a2f8da3fb5c9 Mon Sep 17 00:00:00 2001 From: Dominik Pfaffenbauer Date: Thu, 9 Apr 2020 11:55:44 +0200 Subject: [PATCH 01/12] [3.0] add tests for cart with units and quantity price rules --- features/domain/cart/cart_units.feature | 4 +- .../domain/cart/cart_units_precision.feature | 4 +- .../cart_units_precision_and_vouchers.feature | 4 +- ...units_precision_and_vouchers_gross.feature | 4 +- .../cart/cart_units_taxation_gross.feature | 16 ++--- .../cart/cart_units_taxation_net.feature | 16 ++--- features/domain/product/product_unit.feature | 4 +- ..._to_cart_with_quantity_price_rules.feature | 65 +++++++++++++++++++ .../adding_product_to_cart_with_unit.feature | 31 +++++++++ .../product/view_product_with_units.feature | 4 +- .../Behat/Context/Setup/ProductContext.php | 12 ++-- .../Setup/ProductQuantityPriceRuleContext.php | 65 ++++++++++++++----- .../Behat/Context/Ui/Frontend/CartContext.php | 65 ++++++++++++++++++- src/CoreShop/Behat/Page/Frontend/CartPage.php | 41 +++++++++++- .../Behat/Page/Frontend/CartPageInterface.php | 10 ++- .../views/Cart/Summary/_item.html.twig | 8 ++- 16 files changed, 295 insertions(+), 58 deletions(-) create mode 100644 features/ui/cart/adding_product_to_cart_with_quantity_price_rules.feature create mode 100644 features/ui/cart/adding_product_to_cart_with_unit.feature diff --git a/features/domain/cart/cart_units.feature b/features/domain/cart/cart_units.feature index 4abde9f0c1..8769a4daf3 100644 --- a/features/domain/cart/cart_units.feature +++ b/features/domain/cart/cart_units.feature @@ -17,8 +17,8 @@ Feature: Create a new cart And the site has a product-unit "Carton" And the site has a product-unit "Palette" And the product has the default unit "Pieces" - And the product has and additional unit "Carton" with conversion rate "24" - And the product has and additional unit "Palette" with conversion rate "200" + And the product has an additional unit "Carton" with conversion rate "24" + And the product has an additional unit "Palette" with conversion rate "200" Scenario: Create a new cart and add a product Given I add the product "T-Shirt" with unit "Pieces" to my cart diff --git a/features/domain/cart/cart_units_precision.feature b/features/domain/cart/cart_units_precision.feature index 4c850a9727..b87bdd1296 100644 --- a/features/domain/cart/cart_units_precision.feature +++ b/features/domain/cart/cart_units_precision.feature @@ -15,8 +15,8 @@ Feature: Create a new cart And the site has a product "Shoes" priced at 1000 And the product has the tax rule group "AT" And the product has the default unit "Pieces" - And the product has and additional unit "Carton" with conversion rate "24" and price 2000 and precision 2 - And the product has and additional unit "Palette" with conversion rate "200" and price 150000 and precision 4 + And the product has an additional unit "Carton" with conversion rate "24" and price 2000 and precision 2 + And the product has an additional unit "Palette" with conversion rate "200" and price 150000 and precision 4 Scenario: Create a new cart and add a product and calculate totals Given I add the product "Shoes" with unit "Carton" in quantity 1.5 to my cart diff --git a/features/domain/cart/cart_units_precision_and_vouchers.feature b/features/domain/cart/cart_units_precision_and_vouchers.feature index c2bdb85b35..4283630992 100644 --- a/features/domain/cart/cart_units_precision_and_vouchers.feature +++ b/features/domain/cart/cart_units_precision_and_vouchers.feature @@ -15,8 +15,8 @@ Feature: Create a new cart And the site has a product "Shoes" priced at 1000 And the product has the tax rule group "AT" And the product has the default unit "Pieces" - And the product has and additional unit "Carton" with conversion rate "24" and price 2000 and precision 2 - And the product has and additional unit "Palette" with conversion rate "200" and price 150000 and precision 4 + And the product has an additional unit "Carton" with conversion rate "24" and price 2000 and precision 2 + And the product has an additional unit "Palette" with conversion rate "200" and price 150000 and precision 4 And adding a cart price rule named "discount" And the cart rule is active And the cart rule is a voucher rule with code "asdf" diff --git a/features/domain/cart/cart_units_precision_and_vouchers_gross.feature b/features/domain/cart/cart_units_precision_and_vouchers_gross.feature index 6868dccc73..fc3081fd96 100644 --- a/features/domain/cart/cart_units_precision_and_vouchers_gross.feature +++ b/features/domain/cart/cart_units_precision_and_vouchers_gross.feature @@ -15,8 +15,8 @@ Feature: Create a new cart And the site has a product "Shoes" priced at 1000 And the product has the tax rule group "AT" And the product has the default unit "Pieces" - And the product has and additional unit "Carton" with conversion rate "24" and price 2000 and precision 2 - And the product has and additional unit "Palette" with conversion rate "200" and price 150000 and precision 4 + And the product has an additional unit "Carton" with conversion rate "24" and price 2000 and precision 2 + And the product has an additional unit "Palette" with conversion rate "200" and price 150000 and precision 4 And adding a cart price rule named "discount" And the cart rule is active And the cart rule is a voucher rule with code "asdf" diff --git a/features/domain/cart/cart_units_taxation_gross.feature b/features/domain/cart/cart_units_taxation_gross.feature index aa57e46d74..c18e5b8780 100644 --- a/features/domain/cart/cart_units_taxation_gross.feature +++ b/features/domain/cart/cart_units_taxation_gross.feature @@ -17,23 +17,23 @@ Feature: Create a new cart where store uses gross values And the site has a product "Shoes" priced at 1000 And the product has the tax rule group "AT" And the product has the default unit "Pieces" - And the product has and additional unit "Carton" with conversion rate "24" and price 2000 - And the product has and additional unit "Palette" with conversion rate "200" and price 150000 + And the product has an additional unit "Carton" with conversion rate "24" and price 2000 + And the product has an additional unit "Palette" with conversion rate "200" and price 150000 And the site has a product "T-Shirt" priced at 2000 And the product has the tax rule group "AT" And the product has the default unit "Pieces" - And the product has and additional unit "Carton" with conversion rate "24" and price 4000 - And the product has and additional unit "Palette" with conversion rate "200" and price 300000 + And the product has an additional unit "Carton" with conversion rate "24" and price 4000 + And the product has an additional unit "Palette" with conversion rate "200" and price 300000 And the site has a product "Shorts" priced at 3000 And the product has the tax rule group "AT" And the product has the default unit "Pieces" - And the product has and additional unit "Carton" with conversion rate "24" and price 3000 - And the product has and additional unit "Palette" with conversion rate "200" and price 450000 + And the product has an additional unit "Carton" with conversion rate "24" and price 3000 + And the product has an additional unit "Palette" with conversion rate "200" and price 450000 And the site has a product "CH T-Shirt" priced at 1590 And the product has the tax rule group "CH" And the product has the default unit "Pieces" - And the product has and additional unit "Carton" with conversion rate "24" and price 35000 - And the product has and additional unit "Palette" with conversion rate "200" and price 250000 + And the product has an additional unit "Carton" with conversion rate "24" and price 35000 + And the product has an additional unit "Palette" with conversion rate "200" and price 250000 Scenario: Create a new cart and add a product and calculate totals Given I add the product "T-Shirt" with unit "Carton" to my cart diff --git a/features/domain/cart/cart_units_taxation_net.feature b/features/domain/cart/cart_units_taxation_net.feature index 7bd95a687d..5b3409ee38 100644 --- a/features/domain/cart/cart_units_taxation_net.feature +++ b/features/domain/cart/cart_units_taxation_net.feature @@ -17,23 +17,23 @@ Feature: Create a new cart where store uses gross values And the site has a product "Shoes" priced at 1000 And the product has the tax rule group "AT" And the product has the default unit "Pieces" - And the product has and additional unit "Carton" with conversion rate "24" and price 2000 - And the product has and additional unit "Palette" with conversion rate "200" and price 150000 + And the product has an additional unit "Carton" with conversion rate "24" and price 2000 + And the product has an additional unit "Palette" with conversion rate "200" and price 150000 And the site has a product "T-Shirt" priced at 2000 And the product has the tax rule group "AT" And the product has the default unit "Pieces" - And the product has and additional unit "Carton" with conversion rate "24" and price 4000 - And the product has and additional unit "Palette" with conversion rate "200" and price 300000 + And the product has an additional unit "Carton" with conversion rate "24" and price 4000 + And the product has an additional unit "Palette" with conversion rate "200" and price 300000 And the site has a product "Shorts" priced at 3000 And the product has the tax rule group "AT" And the product has the default unit "Pieces" - And the product has and additional unit "Carton" with conversion rate "24" and price 3000 - And the product has and additional unit "Palette" with conversion rate "200" and price 450000 + And the product has an additional unit "Carton" with conversion rate "24" and price 3000 + And the product has an additional unit "Palette" with conversion rate "200" and price 450000 And the site has a product "CH T-Shirt" priced at 1590 And the product has the tax rule group "CH" And the product has the default unit "Pieces" - And the product has and additional unit "Carton" with conversion rate "24" and price 35000 - And the product has and additional unit "Palette" with conversion rate "200" and price 250000 + And the product has an additional unit "Carton" with conversion rate "24" and price 35000 + And the product has an additional unit "Palette" with conversion rate "200" and price 250000 Scenario: Create a new cart and add a product and calculate totals Given I add the product "T-Shirt" with unit "Carton" to my cart diff --git a/features/domain/product/product_unit.feature b/features/domain/product/product_unit.feature index 0aca6dcde2..9a1fec4139 100644 --- a/features/domain/product/product_unit.feature +++ b/features/domain/product/product_unit.feature @@ -21,7 +21,7 @@ Feature: Adding a new Product And the site has a product-unit "Palette" And the site has a product "Shoe 2" priced at 200 And the product has the default unit "Pieces" - And the product has and additional unit "Carton" with conversion rate "24" - And the product has and additional unit "Palette" with conversion rate "200" + And the product has an additional unit "Carton" with conversion rate "24" + And the product has an additional unit "Palette" with conversion rate "200" Then the product should have and additional unit "Carton" with conversion rate "24" Then the product should have and additional unit "Palette" with conversion rate "200" diff --git a/features/ui/cart/adding_product_to_cart_with_quantity_price_rules.feature b/features/ui/cart/adding_product_to_cart_with_quantity_price_rules.feature new file mode 100644 index 0000000000..c2661128d4 --- /dev/null +++ b/features/ui/cart/adding_product_to_cart_with_quantity_price_rules.feature @@ -0,0 +1,65 @@ +@ui @cart @wip +Feature: Adding a product of given quantity to the cart + + Background: + Given the site operates on a store in "Austria" + And the store "Austria" is the default store + And the site has a product "TShirt" priced at 10000 + And the product is active and published and available for store "Austria" + + Scenario: Adding product with quantity price rule of type percentage-decrease in quantity 1 to cart + Given adding a quantity price rule to this product named "default-product-quantity-price-rule" with calculation-behaviour "volume" + And the quantity price rule is active + And the quantity price rule has a range starting from 5 with behaviour percentage-decrease of 10% + When I add this product to the cart + Then I should be on the cart summary page + And I should be notified that the product has been successfully added + And I should see "TShirt" with unit price "€100.00" in my cart + + Scenario: Adding product with quantity price rule of type percentage-decrease in quantity 5 to cart + Given adding a quantity price rule to this product named "default-product-quantity-price-rule" with calculation-behaviour "volume" + And the quantity price rule is active + And the quantity price rule has a range starting from 5 with behaviour percentage-decrease of 10% + When I add 5 of this product to the cart + Then I should be on the cart summary page + And I should be notified that the product has been successfully added + And I should see "TShirt" with unit price "€90.00" in my cart + And I should see "TShirt" with total price "€450.00" in my cart + + Scenario: Adding product with quantity price rule of type amount-decrease in quantity 1 to cart + Given adding a quantity price rule to this product named "default-product-quantity-price-rule" with calculation-behaviour "volume" + And the quantity price rule is active + And the quantity price rule has a range starting from 5 with behaviour amount-decrease of 2000 in currency "EUR" + When I add this product to the cart + Then I should be on the cart summary page + And I should be notified that the product has been successfully added + And I should see "TShirt" with unit price "€100.00" in my cart + + Scenario: Adding product with quantity price rule of type percentage-decrease in quantity 5 to cart + Given adding a quantity price rule to this product named "default-product-quantity-price-rule" with calculation-behaviour "volume" + And the quantity price rule is active + And the quantity price rule has a range starting from 5 with behaviour amount-decrease of 2000 in currency "EUR" + When I add 5 of this product to the cart + Then I should be on the cart summary page + And I should be notified that the product has been successfully added + And I should see "TShirt" with unit price "€80.00" in my cart + And I should see "TShirt" with total price "€400.00" in my cart + + Scenario: Adding product with quantity price rule of type fixed price in quantity 1 to cart + Given adding a quantity price rule to this product named "default-product-quantity-price-rule" with calculation-behaviour "volume" + And the quantity price rule is active + And the quantity price rule has a range starting from 5 with behaviour fixed of 7000 in currency "EUR" + When I add this product to the cart + Then I should be on the cart summary page + And I should be notified that the product has been successfully added + And I should see "TShirt" with unit price "€100.00" in my cart + + Scenario: Adding product with quantity price rule of type fixed price in quantity 5 to cart + Given adding a quantity price rule to this product named "default-product-quantity-price-rule" with calculation-behaviour "volume" + And the quantity price rule is active + And the quantity price rule has a range starting from 5 with behaviour fixed of 7000 in currency "EUR" + When I add 5 of this product to the cart + Then I should be on the cart summary page + And I should be notified that the product has been successfully added + And I should see "TShirt" with unit price "€70.00" in my cart + And I should see "TShirt" with total price "€350.00" in my cart diff --git a/features/ui/cart/adding_product_to_cart_with_unit.feature b/features/ui/cart/adding_product_to_cart_with_unit.feature new file mode 100644 index 0000000000..5450582d71 --- /dev/null +++ b/features/ui/cart/adding_product_to_cart_with_unit.feature @@ -0,0 +1,31 @@ +@ui @cart @wip +Feature: Adding a product of given quantity to the cart + + Background: + Given the site operates on a store in "Austria" + And the store "Austria" is the default store + And the site has a product "TShirt" priced at 10000 + And the product is active and published and available for store "Austria" + And the site has a product-unit "Pieces" + And the site has a product-unit "Carton" + And the site has a product-unit "Palette" + And the product has the default unit "Pieces" + And the product has an additional unit "Carton" with conversion rate "24" and price 200000 + And the product has an additional unit "Palette" with conversion rate "200" and price 1800000 + + Scenario: Adding product with one unit to the cart + When I add this product in unit "Pieces" to the cart + Then I should be on the cart summary page + And I should be notified that the product has been successfully added + And I should see product "TShirt" with unit "Pieces" in my cart + And I should see product "TShirt" in unit "Pieces" with unit price "€100.00" in my cart + + Scenario: Adding products with two units to the cart + When I add this product in unit "Carton" to the cart + When I add this product in unit "Palette" to the cart + Then I should be on the cart summary page + And I should be notified that the product has been successfully added + And I should see product "TShirt" with unit "Carton" in my cart + And I should see product "TShirt" with unit "Palette" in my cart + And I should see product "TShirt" in unit "Carton" with unit price "€2,000.00" in my cart + And I should see product "TShirt" in unit "Palette" with unit price "€18,000.00" in my cart diff --git a/features/ui/product/view_product_with_units.feature b/features/ui/product/view_product_with_units.feature index 58926a8e00..187523d3bd 100644 --- a/features/ui/product/view_product_with_units.feature +++ b/features/ui/product/view_product_with_units.feature @@ -12,8 +12,8 @@ Feature: Viewing product details with units Given the site has a product "T-Shirt" priced at 10000 And the product is active and published and available for store "Austria" And the product has the default unit "Pieces" - And the product has and additional unit "Carton" with conversion rate "24" and price 200000 - And the product has and additional unit "Palette" with conversion rate "200" and price 1500000 + And the product has an additional unit "Carton" with conversion rate "24" and price 200000 + And the product has an additional unit "Palette" with conversion rate "200" and price 1500000 When I open the product's detail page Then I should see the price "€100.00" Then I should see the price "€2,000.00" for unit "carton" diff --git a/src/CoreShop/Behat/Context/Setup/ProductContext.php b/src/CoreShop/Behat/Context/Setup/ProductContext.php index a9e2e5cca8..05669721af 100644 --- a/src/CoreShop/Behat/Context/Setup/ProductContext.php +++ b/src/CoreShop/Behat/Context/Setup/ProductContext.php @@ -344,12 +344,12 @@ public function theProductHasTheDefaultUnit(ProductInterface $product, ProductUn } /** - * @Given /^the (product) has and additional (unit "[^"]+") with conversion rate ("\d++")$/ - * @Given /^the (product "[^"]+") has and additional (unit "[^"]+") with conversion rate ("\d+")$/ - * @Given /^the (product) has and additional (unit "[^"]+") with conversion rate ("[^"]+") and price (\d+)$/ - * @Given /^the (product) has and additional (unit "[^"]+") with conversion rate ("\d+") and price (\d+) and precision (\d+)$/ - * @Given /^the (product "[^"]+") has and additional (unit "[^"]+") with conversion rate ("\d+") and price (\d+)$/ - * @Given /^the (product "[^"]+") has and additional (unit "[^"]+") with conversion rate ("\d+") and price (\d+) and precision (\d+)$/ + * @Given /^the (product) has an additional (unit "[^"]+") with conversion rate ("\d+")$/ + * @Given /^the (product "[^"]+") has an additional (unit "[^"]+") with conversion rate ("\d+")$/ + * @Given /^the (product) has an additional (unit "[^"]+") with conversion rate ("[^"]+") and price (\d+)$/ + * @Given /^the (product) has an additional (unit "[^"]+") with conversion rate ("\d+") and price (\d+) and precision (\d+)$/ + * @Given /^the (product "[^"]+") has an additional (unit "[^"]+") with conversion rate ("\d+") and price (\d+)$/ + * @Given /^the (product "[^"]+") has an additional (unit "[^"]+") with conversion rate ("\d+") and price (\d+) and precision (\d+)$/ */ public function theProductHasAnAdditionalUnit( ProductInterface $product, diff --git a/src/CoreShop/Behat/Context/Setup/ProductQuantityPriceRuleContext.php b/src/CoreShop/Behat/Context/Setup/ProductQuantityPriceRuleContext.php index 801ee5d8f5..97e2650510 100644 --- a/src/CoreShop/Behat/Context/Setup/ProductQuantityPriceRuleContext.php +++ b/src/CoreShop/Behat/Context/Setup/ProductQuantityPriceRuleContext.php @@ -115,7 +115,11 @@ public function theProductQuantityPriceRuleIsInActive(ProductQuantityPriceRuleIn * @Given /^the (quantity price rule "[^"]+") has a range starting from ([^"]+) with behaviour percentage-decrease of ([^"]+)%$/ * @Given /^the (quantity price rule) has a range starting from ([^"]+) with behaviour percentage-decrease of ([^"]+)%$/ */ - public function theProductQuantityPriceRuleHasRangePercentageDecrease(ProductQuantityPriceRuleInterface $rule, int $from, float $percentage) + public function theProductQuantityPriceRuleHasRangePercentageDecrease( + ProductQuantityPriceRuleInterface $rule, + int $from, + float $percentage + ) { /** * @var QuantityRangeInterface $range @@ -132,7 +136,11 @@ public function theProductQuantityPriceRuleHasRangePercentageDecrease(ProductQua * @Given /^the (quantity price rule "[^"]+") has a range starting from to ([^"]+) with behaviour percentage-increase of ([^"]+)%$/ * @Given /^the (quantity price rule) has a range starting from ([^"]+) with behaviour percentage-increase of ([^"]+)%$/ */ - public function theProductQuantityPriceRuleHasRangePercentageIncrease(ProductQuantityPriceRuleInterface $rule, int $from, float $percentage) + public function theProductQuantityPriceRuleHasRangePercentageIncrease( + ProductQuantityPriceRuleInterface $rule, + int $from, + float $percentage + ) { /** * @var QuantityRangeInterface $range @@ -146,13 +154,13 @@ public function theProductQuantityPriceRuleHasRangePercentageIncrease(ProductQua } /** - * @Given /^the (quantity price rule "[^"]+") has a range starting from ([^"]+) with behaviour amount-decrease of ([^"]+) in (currency "[^"]+")$/ - * @Given /^the (quantity price rule) has a range starting from ([^"]+) with behaviour amount-decrease of ([^"]+) in (currency "[^"]+")$/ + * @Given /^the (quantity price rule "[^"]+") has a range starting from ([^"]+) with behaviour amount-decrease of (\d+) in (currency "[^"]+")$/ + * @Given /^the (quantity price rule) has a range starting from ([^"]+) with behaviour amount-decrease of (\d+) in (currency "[^"]+")$/ */ public function theProductQuantityPriceRuleHasRangeAmountDecrease( ProductQuantityPriceRuleInterface $rule, int $from, - $amount, + int $amount, CurrencyInterface $currency ) { /** @@ -168,13 +176,13 @@ public function theProductQuantityPriceRuleHasRangeAmountDecrease( } /** - * @Given /^the (quantity price rule "[^"]+") has a range starting from ([^"]+) with behaviour amount-increase of ([^"]+) in (currency "[^"]+")$/ - * @Given /^the (quantity price rule) has a range starting from ([^"]+) with behaviour amount-increase of ([^"]+) in (currency "[^"]+")$/ + * @Given /^the (quantity price rule "[^"]+") has a range starting from ([^"]+) with behaviour amount-increase of (\d+) in (currency "[^"]+")$/ + * @Given /^the (quantity price rule) has a range starting from ([^"]+) with behaviour amount-increase of (\d+) in (currency "[^"]+")$/ */ public function theProductQuantityPriceRuleHasRangeAmountIncrease( ProductQuantityPriceRuleInterface $rule, int $from, - $amount, + int $amount, CurrencyInterface $currency ) { /** @@ -190,10 +198,15 @@ public function theProductQuantityPriceRuleHasRangeAmountIncrease( } /** - * @Given /^the (quantity price rule "[^"]+") has a range starting from ([^"]+) with behaviour fixed of ([^"]+) in (currency "[^"]+")$/ - * @Given /^the (quantity price rule) has a range starting from ([^"]+) with behaviour fixed of ([^"]+) in (currency "[^"]+")$/ + * @Given /^the (quantity price rule "[^"]+") has a range starting from ([^"]+) with behaviour fixed of (\d+) in (currency "[^"]+")$/ + * @Given /^the (quantity price rule) has a range starting from ([^"]+) with behaviour fixed of (\d+) in (currency "[^"]+")$/ */ - public function theProductQuantityPriceRuleHasRangeFixed(ProductQuantityPriceRuleInterface $rule, int $from, $amount, CurrencyInterface $currency) + public function theProductQuantityPriceRuleHasRangeFixed( + ProductQuantityPriceRuleInterface $rule, + int $from, + int $amount, + CurrencyInterface $currency + ) { /** * @var QuantityRangeInterface $range @@ -211,7 +224,10 @@ public function theProductQuantityPriceRuleHasRangeFixed(ProductQuantityPriceRul * @Given /^the (quantity price rule "[^"]+") has a condition countries with (country "[^"]+")$/ * @Given /^the (quantity price rule) has a condition countries with (country "[^"]+")$/ */ - public function theProductQuantityPriceRuleHasACountriesCondition(ProductQuantityPriceRuleInterface $rule, CountryInterface $country) + public function theProductQuantityPriceRuleHasACountriesCondition( + ProductQuantityPriceRuleInterface $rule, + CountryInterface $country + ) { $this->assertConditionForm(CountriesConfigurationType::class, 'countries'); @@ -226,7 +242,10 @@ public function theProductQuantityPriceRuleHasACountriesCondition(ProductQuantit * @Given /^the (quantity price rule "[^"]+") has a condition customers with (customer "[^"]+")$/ * @Given /^the (quantity price rule) has a condition customers with (customer "[^"]+")$/ */ - public function theProductQuantityPriceRuleHasACustomerCondition(ProductQuantityPriceRuleInterface $rule, CustomerInterface $customer) + public function theProductQuantityPriceRuleHasACustomerCondition( + ProductQuantityPriceRuleInterface $rule, + CustomerInterface $customer + ) { $this->assertConditionForm(CustomersConfigurationType::class, 'customers'); @@ -258,7 +277,10 @@ public function theProductQuantityPriceRuleHasATimeSpanCondition(ProductQuantity * @Given /^the (quantity price rule "[^"]+") has a condition customer-groups with (customer-group "[^"]+")$/ * @Given /^the (quantity price rule) has a condition customer-groups with (customer-group "[^"]+")$/ */ - public function theProductQuantityPriceRuleHasACustomerGroupCondition(ProductQuantityPriceRuleInterface $rule, CustomerGroupInterface $group) + public function theProductQuantityPriceRuleHasACustomerGroupCondition( + ProductQuantityPriceRuleInterface $rule, + CustomerGroupInterface $group + ) { $this->assertConditionForm(CustomerGroupsConfigurationType::class, 'customerGroups'); @@ -273,7 +295,10 @@ public function theProductQuantityPriceRuleHasACustomerGroupCondition(ProductQua * @Given /^the (quantity price rule "[^"]+") has a condition stores with (store "[^"]+")$/ * @Given /^the (quantity price rule) has a condition stores with (store "[^"]+")$/ */ - public function theProductQuantityPriceRuleHasAStoreCondition(ProductQuantityPriceRuleInterface $rule, StoreInterface $store) + public function theProductQuantityPriceRuleHasAStoreCondition( + ProductQuantityPriceRuleInterface $rule, + StoreInterface $store + ) { $this->assertConditionForm(StoresConfigurationType::class, 'stores'); @@ -288,7 +313,10 @@ public function theProductQuantityPriceRuleHasAStoreCondition(ProductQuantityPri * @Given /^the (quantity price rule "[^"]+") has a condition zones with (zone "[^"]+")$/ * @Given /^the (quantity price rule) has a condition zones with (zone "[^"]+")$/ */ - public function theProductQuantityPriceRuleHasAZoneCondition(ProductQuantityPriceRuleInterface $rule, ZoneInterface $zone) + public function theProductQuantityPriceRuleHasAZoneCondition( + ProductQuantityPriceRuleInterface $rule, + ZoneInterface $zone + ) { $this->assertConditionForm(ZonesConfigurationType::class, 'zones'); @@ -303,7 +331,10 @@ public function theProductQuantityPriceRuleHasAZoneCondition(ProductQuantityPric * @Given /^the (quantity price rule "[^"]+") has a condition currencies with (currency "[^"]+")$/ * @Given /^the (quantity price rule) has a condition currencies with (currency "[^"]+")$/ */ - public function theProductsQuantityPriceRuleHasACurrencyCondition(ProductQuantityPriceRuleInterface $rule, CurrencyInterface $currency) + public function theProductsQuantityPriceRuleHasACurrencyCondition( + ProductQuantityPriceRuleInterface $rule, + CurrencyInterface $currency + ) { $this->assertConditionForm(CurrenciesConfigurationType::class, 'currencies'); diff --git a/src/CoreShop/Behat/Context/Ui/Frontend/CartContext.php b/src/CoreShop/Behat/Context/Ui/Frontend/CartContext.php index 46036e7fa9..4bbe5cb9bb 100644 --- a/src/CoreShop/Behat/Context/Ui/Frontend/CartContext.php +++ b/src/CoreShop/Behat/Context/Ui/Frontend/CartContext.php @@ -23,6 +23,8 @@ use CoreShop\Behat\Service\SharedStorageInterface; use CoreShop\Component\Core\Model\ProductInterface; use CoreShop\Component\Pimcore\Routing\LinkGeneratorInterface; +use CoreShop\Component\Product\Model\ProductUnitDefinitionInterface; +use CoreShop\Component\Product\Model\ProductUnitInterface; use Webmozart\Assert\Assert; final class CartContext implements Context @@ -79,6 +81,20 @@ public function iAddProductToTheCart(ProductInterface $product): void $this->sharedStorage->set('product', $product); } + /** + * @Given /^I add this (product) in (unit "[^"]+") to the cart$/ + * @Given /^I add (product "[^"]+") in (unit "[^"]+") to the cart$/ + */ + public function iAddProductInUnitToTheCart(ProductInterface $product, ProductUnitInterface $unit): void + { + $unitDefinition = $this->findUnitDefinition($product, $unit); + + $this->productPage->tryToOpenWithUri($this->linkGenerator->generate($product, null, ['_locale' => 'en'])); + $this->productPage->addToCartInUnit($unitDefinition); + + $this->sharedStorage->set('product', $product); + } + /** * @Given I removed product :productName from the cart * @When I remove product :productName from the cart @@ -138,7 +154,36 @@ public function iShouldSeeProductWithUnitPriceInMyCart($productName, $unitPrice) Assert::same($this->cartPage->getItemUnitPrice($productName), $unitPrice); } - /** + /** + * @Then /^I should see "([^"]+)" with total price "([^"]+)" in my cart$/ + */ + public function iShouldSeeProductWithTotalPriceInMyCart($productName, $unitPrice) + { + Assert::same($this->cartPage->getItemTotalPrice($productName), $unitPrice); + } + + /** + * @Then /^I should see (product "[^"]+") in (unit "[^"]+") with unit price "([^"]+)" in my cart$/ + */ + public function iShouldSeeProductInUnitWithUnitPriceInMyCart(ProductInterface $product, ProductUnitInterface $unit, $unitPrice) + { + $unitDefinition = $this->findUnitDefinition($product, $unit); + + Assert::same($this->cartPage->getItemUnitPriceWithUnit($product->getName(), $unitDefinition), $unitPrice); + } + + /** + * @Then /^I should see this (product) with (unit "[^"]+") in my cart$/ + * @Then /^I should see (product "[^"]+") with (unit "[^"]+") in my cart$/ + */ + public function iShouldSeeProductWithUnitInMyCart(ProductInterface $product, ProductUnitInterface $unit) + { + $unitDefinition = $this->findUnitDefinition($product, $unit); + + Assert::true($this->cartPage->hasProductInUnit($product->getName(), $unitDefinition)); + } + + /** * @Then /^I should see "([^"]+)" with quantity (\d+) in my cart$/ */ public function iShouldSeeWithQuantityInMyCart($productName, $quantity) @@ -164,4 +209,22 @@ public function myCartsTotalShouldBe($total) Assert::same($this->cartPage->getTotal(), $total); } + + protected function findUnitDefinition(ProductInterface $product, ProductUnitInterface $unit) + { + $unitDefinition = null; + + Assert::notNull($product->getUnitDefinitions()); + + foreach ($product->getUnitDefinitions()->getUnitDefinitions() as $definition) { + if ($definition->getUnit()->getId() === $unit->getId()) { + $unitDefinition = $definition; + break; + } + } + + Assert::notNull($unitDefinition); + + return $unitDefinition; + } } diff --git a/src/CoreShop/Behat/Page/Frontend/CartPage.php b/src/CoreShop/Behat/Page/Frontend/CartPage.php index 342d6f1f20..73a8de35dc 100644 --- a/src/CoreShop/Behat/Page/Frontend/CartPage.php +++ b/src/CoreShop/Behat/Page/Frontend/CartPage.php @@ -15,6 +15,8 @@ namespace CoreShop\Behat\Page\Frontend; use Behat\Mink\Exception\ElementNotFoundException; +use CoreShop\Component\Core\Model\ProductInterface; +use CoreShop\Component\Product\Model\ProductUnitDefinitionInterface; class CartPage extends AbstractFrontendPage implements CartPageInterface { @@ -40,6 +42,16 @@ public function hasItemNamed(string $name): bool return $this->hasItemWith($name, '[data-test-cart-item-name]'); } + public function hasProductInUnit(string $name, ProductUnitDefinitionInterface $unitDefinition): bool + { + return null !== $this->getElement('cart_item_unit', + [ + '%unitId%' => $unitDefinition->getId(), + '%name%' => $name, + ] + ); + } + public function getItemUnitPrice(string $name): string { $unitPrice = $this->getElement('item_unit_price', ['%name%' => $name]); @@ -47,9 +59,30 @@ public function getItemUnitPrice(string $name): string return trim($unitPrice->getText()); } + public function getItemUnitPriceWithUnit(string $name, ProductUnitDefinitionInterface $unitDefinition): string + { + $unitPrice = $this->getElement('item_unit_price_unit', ['%name%' => $name, '%unitId%' => $unitDefinition->getId()]); + + return trim($unitPrice->getText()); + } + + public function getItemTotalPrice(string $productName): string + { + $unitPrice = $this->getElement('item_total_price', ['%name%' => $productName]); + + return trim($unitPrice->getText()); + } + + public function getItemTotalPriceWithUnit(string $name, ProductUnitDefinitionInterface $unitDefinition): string + { + $unitPrice = $this->getElement('item_total_price_unit', ['%name%' => $name, '%unitId%' => $unitDefinition->getId()]); + + return trim($unitPrice->getText()); + } + public function getQuantity(string $productName): int { - return (int) $this->getElement('item_quantity_input', ['%name%' => $productName])->getValue(); + return (int)$this->getElement('item_quantity_input', ['%name%' => $productName])->getValue(); } public function changeQuantity(string $productName, string $quantity): void @@ -94,7 +127,7 @@ private function hasItemWith(string $attributeName, $selector): bool private function getPriceFromString(string $price): int { - return (int) round((float) str_replace(['€', '£', '$'], '', $price) * 100, 2); + return (int)round((float)str_replace(['€', '£', '$'], '', $price) * 100, 2); } protected function getDefinedElements(): array @@ -103,10 +136,14 @@ protected function getDefinedElements(): array 'cart_empty' => '[data-test-cart-empty]', 'cart_items' => '[data-test-cart-items]', 'item_unit_price' => '[data-test-cart-item-row="%name%"] [data-test-cart-item-unit-price]', + 'item_unit_price_unit' => '[data-test-cart-item-row-unit-%unitId%="%name%"] [data-test-cart-item-unit-price]', + 'item_total_price' => '[data-test-cart-item-row="%name%"] [data-test-cart-item-total-price]', + 'item_total_price_unit' => '[data-test-cart-item-row-unit-%unitId%="%name%"] [data-test-cart-item-total-price]', 'item_quantity_input' => '[data-test-cart-item-quantity-input="%name%"]', 'update_cart_button' => '[data-test-update-cart-button]', 'delete_button' => '[data-test-cart-remove-button="%name%"]', 'cart_total' => '[data-test-cart-total]', + 'cart_item_unit' => '[data-test-cart-item-unit-%unitId%="%name%"]', ]); } } diff --git a/src/CoreShop/Behat/Page/Frontend/CartPageInterface.php b/src/CoreShop/Behat/Page/Frontend/CartPageInterface.php index dcf5f3de00..1b1db64ea9 100644 --- a/src/CoreShop/Behat/Page/Frontend/CartPageInterface.php +++ b/src/CoreShop/Behat/Page/Frontend/CartPageInterface.php @@ -14,7 +14,7 @@ namespace CoreShop\Behat\Page\Frontend; -use CoreShop\Component\Core\Model\ProductInterface; +use CoreShop\Component\Product\Model\ProductUnitDefinitionInterface; interface CartPageInterface extends FrontendPageInterface { @@ -24,8 +24,16 @@ public function isSingleItemOnPage(): bool; public function hasItemNamed(string $name): bool; + public function hasProductInUnit(string $name, ProductUnitDefinitionInterface $unitDefinition): bool; + + public function getItemUnitPriceWithUnit(string $name, ProductUnitDefinitionInterface $unitDefinition): string; + public function getItemUnitPrice(string $productName): string; + public function getItemTotalPrice(string $productName): string; + + public function getItemTotalPriceWithUnit(string $name, ProductUnitDefinitionInterface $unitDefinition): string; + public function getQuantity(string $productName): int; public function changeQuantity(string $productName, string $quantity): void; diff --git a/src/CoreShop/Bundle/FrontendBundle/Resources/views/Cart/Summary/_item.html.twig b/src/CoreShop/Bundle/FrontendBundle/Resources/views/Cart/Summary/_item.html.twig index da6b8c55ea..15fe378fce 100644 --- a/src/CoreShop/Bundle/FrontendBundle/Resources/views/Cart/Summary/_item.html.twig +++ b/src/CoreShop/Bundle/FrontendBundle/Resources/views/Cart/Summary/_item.html.twig @@ -3,7 +3,7 @@ {% set productUrl = coreshop_path(item.product, 'coreshop_product_detail') %} - + {% if item.product and item.product.image is asset_image %} @@ -30,7 +30,9 @@ {{ form_widget(form.quantity, coreshop_test_form_attribute('cart-item-quantity-input', item.name)) }} {% if item.hasUnitDefinition %}
- {{ item.unitDefinition.unit.name }} + + {{ item.unitDefinition.unit.name }} +
{% endif %} @@ -54,7 +56,7 @@ {% endif %} {% endif %} - + {{ currency.convertAndFormat(item.total) }} From 9d4245eeb8fb825506aa7a08cb90e6065af02571 Mon Sep 17 00:00:00 2001 From: Dominik Pfaffenbauer Date: Thu, 9 Apr 2020 12:19:53 +0200 Subject: [PATCH 02/12] [3.0] add product view tests for quantity price rule with units --- ...with_quantity_price_rules_and_unit.feature | 60 +++++++++++++++++++ .../product/view_product_with_units.feature | 2 +- .../Setup/ProductQuantityPriceRuleContext.php | 57 +++++++++++++++++- .../ProductQuantityPriceRuleContext.php | 15 ++++- .../Context/Ui/Frontend/ProductContext.php | 49 +++++++++++++++ .../Behat/Page/Frontend/ProductPage.php | 46 +++++++++----- .../Page/Frontend/ProductPageInterface.php | 3 + .../config/services/contexts/setup.yml | 1 + .../quantity_price_ranges_volume.html.twig | 8 ++- 9 files changed, 222 insertions(+), 19 deletions(-) create mode 100644 features/ui/product/view_product_with_quantity_price_rules_and_unit.feature diff --git a/features/ui/product/view_product_with_quantity_price_rules_and_unit.feature b/features/ui/product/view_product_with_quantity_price_rules_and_unit.feature new file mode 100644 index 0000000000..3cc9eb2b98 --- /dev/null +++ b/features/ui/product/view_product_with_quantity_price_rules_and_unit.feature @@ -0,0 +1,60 @@ +@ui @product +Feature: Viewing product details with quantity price rules + + Background: + Given the site operates on a store in "Austria" + And the store "Austria" is the default store + And the site has a product-unit "Pieces" + And the site has a product-unit "Carton" + And the site has a product-unit "Palette" + And the site has a product "T-Shirt" priced at 10000 + And the product is active and published and available for store "Austria" + And the product has the default unit "Pieces" + And the product has an additional unit "Carton" with conversion rate "24" and price 200000 + And the product has an additional unit "Palette" with conversion rate "200" and price 1500000 + And adding a quantity price rule to this product named "default-product-quantity-price-rule" with calculation-behaviour "volume" + And the quantity price rule is active + + Scenario: View product with quantity price rule + Given the quantity price rule has a range starting from 5 with behaviour percentage-decrease of 10% + And the price range is only valid for unit "Pieces" + When I open the product's detail page + Then I should see the price "€100.00" + And I should see one quantity price rule with price "€90.00" for unit "Pieces" + And I should see the quantity price rule 1 starting from "5" for unit "Pieces" + + Scenario: View product with quantity price rules having multiple ranges + Given the quantity price rule has a range starting from 5 with behaviour percentage-decrease of 10% + And the price range is only valid for unit "Pieces" + And the quantity price rule has a range starting from 10 with behaviour percentage-decrease of 20% + And the price range is only valid for unit "Pieces" + When I open the product's detail page + Then I should see the price "€100.00" + And I should see the quantity price rule 1 starting from "5" for unit "Pieces" + And I should see the quantity price rule 2 starting from "10" for unit "Pieces" + And I should see the quantity price rule 2 with price "€80.00" for unit "Pieces" + + Scenario: View product with quantity price rules having multiple ranges for multiple units + Given the quantity price rule has a range starting from 5 with behaviour percentage-decrease of 10% + And the price range is only valid for unit "Pieces" + And the quantity price rule has a range starting from 10 with behaviour percentage-decrease of 20% + And the price range is only valid for unit "Pieces" + And the quantity price rule has a range starting from 20 with behaviour percentage-decrease of 10% + And the price range is only valid for unit "Carton" + And the quantity price rule has a range starting from 40 with behaviour percentage-decrease of 20% + And the price range is only valid for unit "Carton" + And the quantity price rule has a range starting from 100 with behaviour percentage-decrease of 10% + And the price range is only valid for unit "Palette" + And the quantity price rule has a range starting from 200 with behaviour percentage-decrease of 20% + And the price range is only valid for unit "Palette" + When I open the product's detail page + Then I should see the price "€100.00" + And I should see the quantity price rule 1 starting from "5" for unit "Pieces" + And I should see the quantity price rule 2 starting from "10" for unit "Pieces" + And I should see the quantity price rule 2 with price "€80.00" for unit "Pieces" + And I should see the quantity price rule 1 starting from "20" for unit "Carton" + And I should see the quantity price rule 2 starting from "40" for unit "Carton" + And I should see the quantity price rule 2 with price "€1,600.00" for unit "Carton" + And I should see the quantity price rule 1 starting from "100" for unit "Palette" + And I should see the quantity price rule 2 starting from "200" for unit "Palette" + And I should see the quantity price rule 2 with price "€12,000.00" for unit "Palette" diff --git a/features/ui/product/view_product_with_units.feature b/features/ui/product/view_product_with_units.feature index 187523d3bd..02b18c8a5f 100644 --- a/features/ui/product/view_product_with_units.feature +++ b/features/ui/product/view_product_with_units.feature @@ -4,7 +4,7 @@ Feature: Viewing product details with units Background: Given the site operates on a store in "Austria" And the store "Austria" is the default store - Given the site has a product-unit "Pieces" + And the site has a product-unit "Pieces" And the site has a product-unit "Carton" And the site has a product-unit "Palette" diff --git a/src/CoreShop/Behat/Context/Setup/ProductQuantityPriceRuleContext.php b/src/CoreShop/Behat/Context/Setup/ProductQuantityPriceRuleContext.php index 97e2650510..5c859c4798 100644 --- a/src/CoreShop/Behat/Context/Setup/ProductQuantityPriceRuleContext.php +++ b/src/CoreShop/Behat/Context/Setup/ProductQuantityPriceRuleContext.php @@ -33,12 +33,15 @@ use CoreShop\Component\Core\Model\ProductInterface; use CoreShop\Component\Core\Model\QuantityRangeInterface; use CoreShop\Component\Core\Model\StoreInterface; +use CoreShop\Component\Core\Repository\ProductRepositoryInterface; use CoreShop\Component\Customer\Model\CustomerGroupInterface; +use CoreShop\Component\Product\Model\ProductUnitInterface; use CoreShop\Component\Resource\Factory\FactoryInterface; use CoreShop\Component\Rule\Model\ConditionInterface; use CoreShop\Component\ProductQuantityPriceRules\Model\ProductQuantityPriceRuleInterface; use Doctrine\Common\Persistence\ObjectManager; use Symfony\Component\Form\FormFactoryInterface; +use Webmozart\Assert\Assert; final class ProductQuantityPriceRuleContext implements Context { @@ -50,6 +53,7 @@ final class ProductQuantityPriceRuleContext implements Context private $formFactory; private $conditionFormTypeRegistry; private $productQuantityPriceRuleFactory; + private $productRepository; public function __construct( SharedStorageInterface $sharedStorage, @@ -57,7 +61,8 @@ public function __construct( FactoryInterface $rangeFactory, FormFactoryInterface $formFactory, FormTypeRegistryInterface $conditionFormTypeRegistry, - FactoryInterface $productQuantityPriceRuleFactory + FactoryInterface $productQuantityPriceRuleFactory, + ProductRepositoryInterface $productRepository ) { $this->sharedStorage = $sharedStorage; $this->objectManager = $objectManager; @@ -65,6 +70,7 @@ public function __construct( $this->formFactory = $formFactory; $this->conditionFormTypeRegistry = $conditionFormTypeRegistry; $this->productQuantityPriceRuleFactory = $productQuantityPriceRuleFactory; + $this->productRepository = $productRepository; } /** @@ -130,6 +136,8 @@ public function theProductQuantityPriceRuleHasRangePercentageDecrease( $range->setRangeStartingFrom($from); $this->addRange($rule, $range); + + $this->sharedStorage->set('quantity-price-rule-range', $range); } /** @@ -151,6 +159,8 @@ public function theProductQuantityPriceRuleHasRangePercentageIncrease( $range->setRangeStartingFrom($from); $this->addRange($rule, $range); + + $this->sharedStorage->set('quantity-price-rule-range', $range); } /** @@ -173,6 +183,8 @@ public function theProductQuantityPriceRuleHasRangeAmountDecrease( $range->setCurrency($currency); $this->addRange($rule, $range); + + $this->sharedStorage->set('quantity-price-rule-range', $range); } /** @@ -195,6 +207,8 @@ public function theProductQuantityPriceRuleHasRangeAmountIncrease( $range->setCurrency($currency); $this->addRange($rule, $range); + + $this->sharedStorage->set('quantity-price-rule-range', $range); } /** @@ -218,6 +232,29 @@ public function theProductQuantityPriceRuleHasRangeFixed( $range->setCurrency($currency); $this->addRange($rule, $range); + + $this->sharedStorage->set('quantity-price-rule-range', $range); + } + + /** + * @Given /^the (price range) is only valid for (unit "[^"]+")$/ + */ + public function theQuantityPriceRangeIsValidForUnit(QuantityRangeInterface $range, ProductUnitInterface $unit) + { + $productId = $range->getRule()->getProduct(); + /** + * @var ProductInterface $product + */ + $product = $this->productRepository->find($productId); + + Assert::notNull($product); + + $unitDefinition = $this->findUnitDefinition($product, $unit); + + $range->setUnitDefinition($unitDefinition); + + $this->objectManager->persist($range); + $this->objectManager->flush(); } /** @@ -439,6 +476,24 @@ private function addRange(ProductQuantityPriceRuleInterface $rule, QuantityRange $this->objectManager->flush(); } + protected function findUnitDefinition(ProductInterface $product, ProductUnitInterface $unit) + { + $unitDefinition = null; + + Assert::notNull($product->getUnitDefinitions()); + + foreach ($product->getUnitDefinitions()->getUnitDefinitions() as $definition) { + if ($definition->getUnit()->getId() === $unit->getId()) { + $unitDefinition = $definition; + break; + } + } + + Assert::notNull($unitDefinition); + + return $unitDefinition; + } + /** * {@inheritdoc} */ diff --git a/src/CoreShop/Behat/Context/Transform/ProductQuantityPriceRuleContext.php b/src/CoreShop/Behat/Context/Transform/ProductQuantityPriceRuleContext.php index 17c80ea48c..edbd4af0d9 100644 --- a/src/CoreShop/Behat/Context/Transform/ProductQuantityPriceRuleContext.php +++ b/src/CoreShop/Behat/Context/Transform/ProductQuantityPriceRuleContext.php @@ -16,6 +16,7 @@ use Behat\Behat\Context\Context; use CoreShop\Behat\Service\SharedStorageInterface; +use CoreShop\Component\Core\Model\QuantityRangeInterface; use CoreShop\Component\ProductQuantityPriceRules\Model\ProductQuantityPriceRuleInterface; use CoreShop\Component\ProductQuantityPriceRules\Repository\ProductQuantityPriceRuleRepositoryInterface; use Webmozart\Assert\Assert; @@ -50,10 +51,22 @@ public function getProductQuantityPriceRuleByProductAndName($ruleName) */ public function getLatestSpecificProductQuantityPriceRule() { - $resource = $this->sharedStorage->getLatestResource(); + $resource = $this->sharedStorage->get('product-quantity-price-rule'); Assert::isInstanceOf($resource, ProductQuantityPriceRuleInterface::class); return $resource; } + + /** + * @Transform /^(price range)$/ + */ + public function getPriceRange() + { + $resource = $this->sharedStorage->get('quantity-price-rule-range'); + + Assert::isInstanceOf($resource, QuantityRangeInterface::class); + + return $resource; + } } diff --git a/src/CoreShop/Behat/Context/Ui/Frontend/ProductContext.php b/src/CoreShop/Behat/Context/Ui/Frontend/ProductContext.php index 87e0ed3a1a..74054d32aa 100644 --- a/src/CoreShop/Behat/Context/Ui/Frontend/ProductContext.php +++ b/src/CoreShop/Behat/Context/Ui/Frontend/ProductContext.php @@ -20,6 +20,7 @@ use CoreShop\Behat\Service\SharedStorageInterface; use CoreShop\Component\Core\Model\ProductInterface; use CoreShop\Component\Pimcore\Routing\LinkGeneratorInterface; +use CoreShop\Component\Product\Model\ProductUnitInterface; use Webmozart\Assert\Assert; final class ProductContext implements Context @@ -167,4 +168,52 @@ public function iShouldSeeTheQuantityPriceRuleStartingFrom(int $number, $startin Assert::greaterThan($priceRules, $number+1); Assert::contains($priceRules[$number]['startingFrom'], $startingFrom); } + + + /** + * @Then /^I should see one quantity price rule with price "([^"]+)" for (unit "[^"]+")$/ + */ + public function iShouldSeeOneQuantityPiceRuleForUnitWithPrice($price, ProductUnitInterface $unit) + { + $priceRules = $this->productPage->getQuantityPriceRulesForUnit($unit); + + Assert::count($priceRules, 1); + Assert::contains($priceRules[0]['price'], $price); + } + + /** + * @Then /^I should see the quantity price rule (\d+) with price "([^"]+)" for (unit "[^"]+")$/ + */ + public function iShouldSeeTheQuantityPriceRuleForUnitWithPrice(int $number, $price, ProductUnitInterface $unit) + { + $number--; + $priceRules = $this->productPage->getQuantityPriceRulesForUnit($unit); + + Assert::greaterThan($priceRules, $number+1); + Assert::contains($priceRules[$number]['price'], $price); + } + + /** + * @Then /^I should see the quantity price rule (\d+) with excl price "([^"]+)" for (unit "[^"]+")$/ + */ + public function iShouldSeeTheQuantityPriceRuleForUnitWithInclPrice(int $number, $price, ProductUnitInterface $unit) + { + $number--; + $priceRules = $this->productPage->getQuantityPriceRulesForUnit($unit); + + Assert::greaterThan($priceRules, $number+1); + Assert::contains($priceRules[$number]['priceExcl'], $price); + } + + /** + * @Then /^I should see the quantity price rule (\d+) starting from "(\d+)" for (unit "[^"]+")$/ + */ + public function iShouldSeeTheQuantityPriceRuleForUnitStartingFrom(int $number, $startingFrom, ProductUnitInterface $unit) + { + $number--; + $priceRules = $this->productPage->getQuantityPriceRulesForUnit($unit); + + Assert::greaterThan($priceRules, $number+1); + Assert::contains($priceRules[$number]['startingFrom'], $startingFrom); + } } diff --git a/src/CoreShop/Behat/Page/Frontend/ProductPage.php b/src/CoreShop/Behat/Page/Frontend/ProductPage.php index 2940597168..02fb6b3131 100644 --- a/src/CoreShop/Behat/Page/Frontend/ProductPage.php +++ b/src/CoreShop/Behat/Page/Frontend/ProductPage.php @@ -16,6 +16,7 @@ use Behat\Mink\Element\NodeElement; use CoreShop\Component\Product\Model\ProductUnitDefinitionInterface; +use CoreShop\Component\Product\Model\ProductUnitInterface; class ProductPage extends AbstractFrontendPage implements ProductPageInterface { @@ -66,22 +67,16 @@ public function getTax(): string public function getQuantityPriceRules(): array { - $element = $this->getElement('product_quantity_price_rules'); - - return array_map( - static function(NodeElement $element) { - $startFromElement = $element->find('css', '[data-test-product-quantity-price-rule-start]'); - $priceElement = $element->find('css', '[data-test-product-quantity-price-rule-price-inc]'); - $priceExcElement = $element->find('css', '[data-test-product-quantity-price-rule-price-exc]'); + return $this->processQuantityPriceRuleElement('[data-test-product-quantity-price-rule]'); + } - return [ - 'text' => $element->getText(), - 'startingFrom' => $startFromElement->getText(), - 'price' => $priceElement->getText(), - 'priceExcl' => $priceExcElement->getText(), - ]; - }, - $element->findAll('css', '[data-test-product-quantity-price-rule]') + public function getQuantityPriceRulesForUnit(ProductUnitInterface $unit): array + { + return $this->processQuantityPriceRuleElement( + sprintf( + '[data-test-product-quantity-price-rule-unit-%s]', + $unit->getId() + ) ); } @@ -109,6 +104,27 @@ public function addToCartInUnitWithQuantity(ProductUnitDefinitionInterface $unit $this->getElement('add_to_cart')->click(); } + protected function processQuantityPriceRuleElement(string $selector) + { + $element = $this->getElement('product_quantity_price_rules'); + + return array_map( + static function(NodeElement $element) { + $startFromElement = $element->find('css', '[data-test-product-quantity-price-rule-start]'); + $priceElement = $element->find('css', '[data-test-product-quantity-price-rule-price-inc]'); + $priceExcElement = $element->find('css', '[data-test-product-quantity-price-rule-price-exc]'); + + return [ + 'text' => $element->getText(), + 'startingFrom' => $startFromElement->getText(), + 'price' => $priceElement->getText(), + 'priceExcl' => $priceExcElement->getText(), + ]; + }, + $element->findAll('css', $selector) + ); + } + protected function getDefinedElements(): array { return array_merge(parent::getDefinedElements(), [ diff --git a/src/CoreShop/Behat/Page/Frontend/ProductPageInterface.php b/src/CoreShop/Behat/Page/Frontend/ProductPageInterface.php index 17bc335200..61204c28af 100644 --- a/src/CoreShop/Behat/Page/Frontend/ProductPageInterface.php +++ b/src/CoreShop/Behat/Page/Frontend/ProductPageInterface.php @@ -16,6 +16,7 @@ use Behat\Mink\Exception\ElementNotFoundException; use CoreShop\Component\Product\Model\ProductUnitDefinitionInterface; +use CoreShop\Component\Product\Model\ProductUnitInterface; interface ProductPageInterface extends FrontendPageInterface { @@ -37,6 +38,8 @@ public function getTax(): string; public function getQuantityPriceRules(): array; + public function getQuantityPriceRulesForUnit(ProductUnitInterface $unit): array; + /** * @throws ElementNotFoundException */ diff --git a/src/CoreShop/Behat/Resources/config/services/contexts/setup.yml b/src/CoreShop/Behat/Resources/config/services/contexts/setup.yml index 807b121ec0..773f8f62aa 100644 --- a/src/CoreShop/Behat/Resources/config/services/contexts/setup.yml +++ b/src/CoreShop/Behat/Resources/config/services/contexts/setup.yml @@ -291,6 +291,7 @@ services: - '@form.factory' - '@coreshop.form_registry.product_quantity_price_rules.conditions' - '@coreshop.factory.product_quantity_price_rule' + - '@coreshop.repository.product' tags: - { name: fob.context_service } diff --git a/src/CoreShop/Bundle/FrontendBundle/Resources/views/ProductQuantityPriceRanges/quantity_price_ranges_volume.html.twig b/src/CoreShop/Bundle/FrontendBundle/Resources/views/ProductQuantityPriceRanges/quantity_price_ranges_volume.html.twig index 32870aed64..a321025634 100644 --- a/src/CoreShop/Bundle/FrontendBundle/Resources/views/ProductQuantityPriceRanges/quantity_price_ranges_volume.html.twig +++ b/src/CoreShop/Bundle/FrontendBundle/Resources/views/ProductQuantityPriceRanges/quantity_price_ranges_volume.html.twig @@ -51,7 +51,13 @@ {% endif %} {% for range in sorted_unit_range.ranges %} - + {{ 'coreshop.ui.product_quantity_price_rules.starting_from'|trans }} From 6b2b24d48b653767b40ad9fdfc09c59efcbfc9a7 Mon Sep 17 00:00:00 2001 From: Dominik Pfaffenbauer Date: Thu, 9 Apr 2020 12:29:41 +0200 Subject: [PATCH 03/12] [3.0] add tests for add-to-cart with quantity price rules and units --- ...with_quantity_price_rules_and_unit.feature | 51 +++++++++++++++++++ .../adding_product_to_cart_with_unit.feature | 6 +-- .../Behat/Context/Ui/Frontend/CartContext.php | 46 +++++++++++++---- 3 files changed, 88 insertions(+), 15 deletions(-) create mode 100644 features/ui/cart/adding_product_to_cart_with_quantity_price_rules_and_unit.feature diff --git a/features/ui/cart/adding_product_to_cart_with_quantity_price_rules_and_unit.feature b/features/ui/cart/adding_product_to_cart_with_quantity_price_rules_and_unit.feature new file mode 100644 index 0000000000..c684372581 --- /dev/null +++ b/features/ui/cart/adding_product_to_cart_with_quantity_price_rules_and_unit.feature @@ -0,0 +1,51 @@ +@ui @cart @wip +Feature: Adding a product of given quantity to the cart + + Background: + Given the site operates on a store in "Austria" + And the store "Austria" is the default store + And the site has a product-unit "Pieces" + And the site has a product-unit "Carton" + And the site has a product-unit "Palette" + And the site has a product "TShirt" priced at 10000 + And the product is active and published and available for store "Austria" + And the product has the default unit "Pieces" + And the product has an additional unit "Carton" with conversion rate "24" and price 200000 + And the product has an additional unit "Palette" with conversion rate "200" and price 1500000 + And adding a quantity price rule to this product named "default-product-quantity-price-rule" with calculation-behaviour "volume" + And the quantity price rule is active + And the quantity price rule has a range starting from 5 with behaviour percentage-decrease of 10% + And the price range is only valid for unit "Pieces" + And the quantity price rule has a range starting from 10 with behaviour percentage-decrease of 20% + And the price range is only valid for unit "Pieces" + And the quantity price rule has a range starting from 20 with behaviour percentage-decrease of 10% + And the price range is only valid for unit "Carton" + And the quantity price rule has a range starting from 40 with behaviour percentage-decrease of 20% + And the price range is only valid for unit "Carton" + And the quantity price rule has a range starting from 100 with behaviour percentage-decrease of 10% + And the price range is only valid for unit "Palette" + And the quantity price rule has a range starting from 200 with behaviour percentage-decrease of 20% + And the price range is only valid for unit "Palette" + + Scenario: Adding product with quantity price rule and unit + Given the quantity price rule has a range starting from 5 with behaviour percentage-decrease of 10% + And the price range is only valid for unit "Pieces" + When I add this product in unit "Pieces" to the cart + Then I should be on the cart summary page + And I should be notified that the product has been successfully added + And I should see product "TShirt" with unit "Pieces" in my cart + And I should see product "TShirt" in unit "Pieces" with unit price "€100.00" in my cart + + Scenario: Adding product with quantity price rule and unit in quantity 5 + When I add 5 of this product in unit "Carton" to the cart + Then I should be on the cart summary page + And I should be notified that the product has been successfully added + And I should see product "TShirt" in unit "Carton" with unit price "€2,000.00" in my cart + And I should see product "TShirt" in unit "Carton" with total price "€10,000.00" in my cart + + Scenario: Adding product with quantity price rule and unit in quantity 20 + When I add 20 of this product in unit "Carton" to the cart + Then I should be on the cart summary page + And I should be notified that the product has been successfully added + And I should see product "TShirt" in unit "Carton" with unit price "€1,800.00" in my cart + And I should see product "TShirt" in unit "Carton" with total price "€36,000.00" in my cart diff --git a/features/ui/cart/adding_product_to_cart_with_unit.feature b/features/ui/cart/adding_product_to_cart_with_unit.feature index 5450582d71..fb1c641ffa 100644 --- a/features/ui/cart/adding_product_to_cart_with_unit.feature +++ b/features/ui/cart/adding_product_to_cart_with_unit.feature @@ -22,10 +22,8 @@ Feature: Adding a product of given quantity to the cart Scenario: Adding products with two units to the cart When I add this product in unit "Carton" to the cart - When I add this product in unit "Palette" to the cart - Then I should be on the cart summary page - And I should be notified that the product has been successfully added - And I should see product "TShirt" with unit "Carton" in my cart + And I add this product in unit "Palette" to the cart + Then I should see product "TShirt" with unit "Carton" in my cart And I should see product "TShirt" with unit "Palette" in my cart And I should see product "TShirt" in unit "Carton" with unit price "€2,000.00" in my cart And I should see product "TShirt" in unit "Palette" with unit price "€18,000.00" in my cart diff --git a/src/CoreShop/Behat/Context/Ui/Frontend/CartContext.php b/src/CoreShop/Behat/Context/Ui/Frontend/CartContext.php index 4bbe5cb9bb..ffa74d6ce1 100644 --- a/src/CoreShop/Behat/Context/Ui/Frontend/CartContext.php +++ b/src/CoreShop/Behat/Context/Ui/Frontend/CartContext.php @@ -81,6 +81,15 @@ public function iAddProductToTheCart(ProductInterface $product): void $this->sharedStorage->set('product', $product); } + /** + * @Given /^I add (\d+) of this (product) to the cart$/ + */ + public function iAddQuantityProductToTheCart($quantity, ProductInterface $product) + { + $this->productPage->tryToOpenWithUri($this->linkGenerator->generate($product, null, ['_locale' => 'en'])); + $this->productPage->addToCartWithQuantity($quantity); + } + /** * @Given /^I add this (product) in (unit "[^"]+") to the cart$/ * @Given /^I add (product "[^"]+") in (unit "[^"]+") to the cart$/ @@ -96,22 +105,27 @@ public function iAddProductInUnitToTheCart(ProductInterface $product, ProductUni } /** - * @Given I removed product :productName from the cart - * @When I remove product :productName from the cart + * @Given /^I add (\d+) of this (product) in (unit "[^"]+") to the cart$/ + * @Given /^I add (\d+) of (product "[^"]+") in (unit "[^"]+") to the cart$/ */ - public function iRemoveProductFromTheCart(string $productName): void + public function iAddQuantityProductInUnitToTheCart($quantity, ProductInterface $product, ProductUnitInterface $unit) { - $this->cartPage->open(); - $this->cartPage->removeProduct($productName); + $unitDefinition = $this->findUnitDefinition($product, $unit); + + $this->productPage->tryToOpenWithUri($this->linkGenerator->generate($product, null, ['_locale' => 'en'])); + $this->productPage->addToCartInUnitWithQuantity($unitDefinition, $quantity); + + $this->sharedStorage->set('product', $product); } /** - * @Given /^I add (\d+) of this (product) to the cart$/ + * @Given I removed product :productName from the cart + * @When I remove product :productName from the cart */ - public function iAddQuantityProductToTheCart($quantity, ProductInterface $product) + public function iRemoveProductFromTheCart(string $productName): void { - $this->productPage->tryToOpenWithUri($this->linkGenerator->generate($product, null, ['_locale' => 'en'])); - $this->productPage->addToCartWithQuantity($quantity); + $this->cartPage->open(); + $this->cartPage->removeProduct($productName); } /** @@ -157,9 +171,9 @@ public function iShouldSeeProductWithUnitPriceInMyCart($productName, $unitPrice) /** * @Then /^I should see "([^"]+)" with total price "([^"]+)" in my cart$/ */ - public function iShouldSeeProductWithTotalPriceInMyCart($productName, $unitPrice) + public function iShouldSeeProductWithTotalPriceInMyCart($productName, $totalPrice) { - Assert::same($this->cartPage->getItemTotalPrice($productName), $unitPrice); + Assert::same($this->cartPage->getItemTotalPrice($productName), $totalPrice); } /** @@ -172,6 +186,16 @@ public function iShouldSeeProductInUnitWithUnitPriceInMyCart(ProductInterface $p Assert::same($this->cartPage->getItemUnitPriceWithUnit($product->getName(), $unitDefinition), $unitPrice); } + /** + * @Then /^I should see (product "[^"]+") in (unit "[^"]+") with total price "([^"]+)" in my cart$/ + */ + public function iShouldSeeProductInUnitWithTotalPriceInMyCart(ProductInterface $product, ProductUnitInterface $unit, $totalPrice) + { + $unitDefinition = $this->findUnitDefinition($product, $unit); + + Assert::same($this->cartPage->getItemTotalPriceWithUnit($product->getName(), $unitDefinition), $totalPrice); + } + /** * @Then /^I should see this (product) with (unit "[^"]+") in my cart$/ * @Then /^I should see (product "[^"]+") with (unit "[^"]+") in my cart$/ From 52c2658cf8495352285080e932c6f084341e0a4a Mon Sep 17 00:00:00 2001 From: Dominik Pfaffenbauer Date: Thu, 9 Apr 2020 15:38:40 +0200 Subject: [PATCH 04/12] [3.0] add tests for min/max qty to order --- ...g_product_to_cart_with_maximum_qty.feature | 31 +++++++++++++++++++ ...g_product_to_cart_with_minimum_qty.feature | 31 +++++++++++++++++++ ..._to_cart_with_quantity_price_rules.feature | 2 +- ...with_quantity_price_rules_and_unit.feature | 2 +- ...g_product_to_cart_with_store_price.feature | 3 +- .../adding_product_to_cart_with_unit.feature | 2 +- .../ui/cart/remove_product_from_cart.feature | 1 + .../Behat/Context/Setup/ProductContext.php | 10 ++++++ .../Behat/Context/Ui/Frontend/CartContext.php | 24 +++++++++++++- .../Behat/Service/NotificationChecker.php | 2 +- 10 files changed, 102 insertions(+), 6 deletions(-) create mode 100644 features/ui/cart/adding_product_to_cart_with_maximum_qty.feature create mode 100644 features/ui/cart/adding_product_to_cart_with_minimum_qty.feature diff --git a/features/ui/cart/adding_product_to_cart_with_maximum_qty.feature b/features/ui/cart/adding_product_to_cart_with_maximum_qty.feature new file mode 100644 index 0000000000..a10f90d72a --- /dev/null +++ b/features/ui/cart/adding_product_to_cart_with_maximum_qty.feature @@ -0,0 +1,31 @@ +@ui @cart @wip +Feature: Adding a product to the cart with maximum Quantity to Order + + Background: + Given the site operates on a store in "Austria" + And the store "Austria" is the default store + And the site has a product "TShirt" priced at 10000 + And the product is active and published and available for store "Austria" + + Scenario: Adding product to cart with minimum quantity to order + Given the product "TShirt" has a maximum order quantity of "100" + When I add 99 of this product to the cart + Then I should be on the cart summary page + And I should be notified that the product has been successfully added + And there should be one item in my cart + And this item should have name "TSHIRT" + And I should see "TShirt" with unit price "€100.00" in my cart + + Scenario: Adding product to cart with less than minimum quantity to order + Given the product "TShirt" has a maximum order quantity of "100" + When I add 101 of this product to the cart + Then I should be on the cart summary page + And I should be notified that I can only order a maximum of 100 of TSHIRT + + + Scenario: Adding product to cart with less than minimum quantity to order with smaller quantities + Given the product "TShirt" has a maximum order quantity of "2" + When I add 3 of this product to the cart + Then I should be on the cart summary page + And I should be notified that I can only order a maximum of 2 of TSHIRT + diff --git a/features/ui/cart/adding_product_to_cart_with_minimum_qty.feature b/features/ui/cart/adding_product_to_cart_with_minimum_qty.feature new file mode 100644 index 0000000000..0fdc084549 --- /dev/null +++ b/features/ui/cart/adding_product_to_cart_with_minimum_qty.feature @@ -0,0 +1,31 @@ +@ui @cart @wip +Feature: Adding a product to the cart with minimum Quantity to Order + + Background: + Given the site operates on a store in "Austria" + And the store "Austria" is the default store + And the site has a product "TShirt" priced at 10000 + And the product is active and published and available for store "Austria" + + Scenario: Adding product to cart with minimum quantity to order + Given the product "TShirt" has a minimum order quantity of "100" + When I add 100 of this product to the cart + Then I should be on the cart summary page + And I should be notified that the product has been successfully added + And there should be one item in my cart + And this item should have name "TSHIRT" + And I should see "TShirt" with unit price "€100.00" in my cart + + Scenario: Adding product to cart with less than minimum quantity to order + Given the product "TShirt" has a minimum order quantity of "100" + When I add 99 of this product to the cart + Then I should be on the cart summary page + And I should be notified that I need to order at least 100 of TSHIRT + + + Scenario: Adding product to cart with less than minimum quantity to order with smaller quantities + Given the product "TShirt" has a minimum order quantity of "2" + When I add 1 of this product to the cart + Then I should be on the cart summary page + And I should be notified that I need to order at least 2 of TSHIRT + diff --git a/features/ui/cart/adding_product_to_cart_with_quantity_price_rules.feature b/features/ui/cart/adding_product_to_cart_with_quantity_price_rules.feature index c2661128d4..5d035ece56 100644 --- a/features/ui/cart/adding_product_to_cart_with_quantity_price_rules.feature +++ b/features/ui/cart/adding_product_to_cart_with_quantity_price_rules.feature @@ -1,5 +1,5 @@ @ui @cart @wip -Feature: Adding a product of given quantity to the cart +Feature: Adding a product with a quantity price rule Background: Given the site operates on a store in "Austria" diff --git a/features/ui/cart/adding_product_to_cart_with_quantity_price_rules_and_unit.feature b/features/ui/cart/adding_product_to_cart_with_quantity_price_rules_and_unit.feature index c684372581..d5f1e94d8e 100644 --- a/features/ui/cart/adding_product_to_cart_with_quantity_price_rules_and_unit.feature +++ b/features/ui/cart/adding_product_to_cart_with_quantity_price_rules_and_unit.feature @@ -1,5 +1,5 @@ @ui @cart @wip -Feature: Adding a product of given quantity to the cart +Feature: Adding a product with a quantity price rule and units Background: Given the site operates on a store in "Austria" diff --git a/features/ui/cart/adding_product_to_cart_with_store_price.feature b/features/ui/cart/adding_product_to_cart_with_store_price.feature index e2d0f7aace..1c655f6f9a 100644 --- a/features/ui/cart/adding_product_to_cart_with_store_price.feature +++ b/features/ui/cart/adding_product_to_cart_with_store_price.feature @@ -1,5 +1,6 @@ @ui @cart -Feature: Adding a product to the cart +Feature: Adding a product to the cart with different store prices + Background: Given the site operates on a store in "Austria" And the store "Austria" is the default store diff --git a/features/ui/cart/adding_product_to_cart_with_unit.feature b/features/ui/cart/adding_product_to_cart_with_unit.feature index fb1c641ffa..04ff1a1eb3 100644 --- a/features/ui/cart/adding_product_to_cart_with_unit.feature +++ b/features/ui/cart/adding_product_to_cart_with_unit.feature @@ -1,5 +1,5 @@ @ui @cart @wip -Feature: Adding a product of given quantity to the cart +Feature: Adding a product to cart with a unit Background: Given the site operates on a store in "Austria" diff --git a/features/ui/cart/remove_product_from_cart.feature b/features/ui/cart/remove_product_from_cart.feature index 48598539bb..2876a71063 100644 --- a/features/ui/cart/remove_product_from_cart.feature +++ b/features/ui/cart/remove_product_from_cart.feature @@ -1,5 +1,6 @@ @ui @cart Feature: Removing cart item from cart + Background: Given the site operates on a store in "Austria" And the store "Austria" is the default store diff --git a/src/CoreShop/Behat/Context/Setup/ProductContext.php b/src/CoreShop/Behat/Context/Setup/ProductContext.php index 05669721af..347c1a4d84 100644 --- a/src/CoreShop/Behat/Context/Setup/ProductContext.php +++ b/src/CoreShop/Behat/Context/Setup/ProductContext.php @@ -322,6 +322,16 @@ public function theProductHasAMinimumOrderQuantity(ProductInterface $product, in $this->saveProduct($product); } + /** + * @Given /^the (product "[^"]+") has a maximum order quantity of "([^"]+)"$/ + * @Given /^the (product) has a maximum order quantity of "([^"]+)"$/ + */ + public function theProductHasAMaximumOrderQuantity(ProductInterface $product, int $maximumQuantity) + { + $product->setMaximumQuantityToOrder($maximumQuantity); + $this->saveProduct($product); + } + /** * @Given /^the (product) has the default (unit "[^"]+")$/ * @Given /^the (product "[^"]+") has the default (unit "[^"]+")"$/ diff --git a/src/CoreShop/Behat/Context/Ui/Frontend/CartContext.php b/src/CoreShop/Behat/Context/Ui/Frontend/CartContext.php index ffa74d6ce1..be63d72b39 100644 --- a/src/CoreShop/Behat/Context/Ui/Frontend/CartContext.php +++ b/src/CoreShop/Behat/Context/Ui/Frontend/CartContext.php @@ -136,7 +136,7 @@ public function shouldBeOnMyCartSummaryPage() $this->cartPage->verify(); } - /** + /** * @Then I should be notified that the product has been successfully added */ public function iShouldBeNotifiedThatItHasBeenSuccessfullyAdded() @@ -144,6 +144,28 @@ public function iShouldBeNotifiedThatItHasBeenSuccessfullyAdded() $this->notificationChecker->checkNotification('ITEM ADDED', NotificationType::success()); } + /** + * @Then I should be notified that I need to order at least :quantity of :productName + */ + public function iShouldBeNotifiedThatItNeedToOrderAtLeastOf(string $quantity, string $productName) + { + $this->notificationChecker->checkNotification( + sprintf('YOU NEED TO ORDER AT LEAST %s UNITS OF %s.', $quantity, $productName), + NotificationType::error() + ); + } + + /** + * @Then I should be notified that I can only order a maximum of :quantity of :productName + */ + public function iShouldBeNotifiedThatICanOnlyOrderAMaximumQuantityOf(string $quantity, string $productName) + { + $this->notificationChecker->checkNotification( + sprintf('YOU CAN ORDER A MAXIMUM OF %s UNITS OF %s.', $quantity, $productName), + NotificationType::error() + ); + } + /** * @Then there should be one item in my cart */ diff --git a/src/CoreShop/Behat/Service/NotificationChecker.php b/src/CoreShop/Behat/Service/NotificationChecker.php index 1d42be3946..cd31c311a7 100644 --- a/src/CoreShop/Behat/Service/NotificationChecker.php +++ b/src/CoreShop/Behat/Service/NotificationChecker.php @@ -46,7 +46,7 @@ public function checkNotification(string $message, NotificationType $type): void private function resolveClass(NotificationType $type): string { $typeClassMap = [ - 'failure' => 'alert-danger', + 'error' => 'alert-danger', 'info' => 'alert-info', 'success' => 'alert-success', ]; From 39f76fb15024189991c816a398df241f81565aff Mon Sep 17 00:00:00 2001 From: Dominik Pfaffenbauer Date: Thu, 9 Apr 2020 16:32:09 +0200 Subject: [PATCH 05/12] [3.0] add out-of-stock ui tests --- ..._to_cart_with_out_of_stock_product.feature | 35 +++++++++++++++ .../Behat/Context/Setup/ProductContext.php | 44 +++++++++++++++++++ .../Behat/Context/Ui/Frontend/CartContext.php | 11 +++++ .../Context/Ui/Frontend/ProductContext.php | 9 ++++ .../Behat/Page/Frontend/ProductPage.php | 6 +++ .../Page/Frontend/ProductPageInterface.php | 2 + .../Behat/Resources/config/suites/ui/cart.yml | 1 + .../Resources/views/Product/detail.html.twig | 6 ++- .../Twig/InventoryExtension.php | 9 +++- 9 files changed, 119 insertions(+), 4 deletions(-) create mode 100644 features/ui/cart/adding_product_to_cart_with_out_of_stock_product.feature diff --git a/features/ui/cart/adding_product_to_cart_with_out_of_stock_product.feature b/features/ui/cart/adding_product_to_cart_with_out_of_stock_product.feature new file mode 100644 index 0000000000..d8f1b982a0 --- /dev/null +++ b/features/ui/cart/adding_product_to_cart_with_out_of_stock_product.feature @@ -0,0 +1,35 @@ +@ui @cart @wip +Feature: Adding a product to the cart with a Product that is tracked and out-of-stock + + Background: + Given the site operates on a store in "Austria" + And the store "Austria" is the default store + And the site has a product "TShirt" priced at 10000 + And the product is active and published and available for store "Austria" + And the product is stock tracked + And the product has 2 on hand + And the product has 0 on hold + + Scenario: Adding product to cart with enough quantity left + When I add 2 of this product to the cart + Then I should be on the cart summary page + And I should be notified that the product has been successfully added + And there should be one item in my cart + And this item should have name "TSHIRT" + And I should see "TShirt" with unit price "€100.00" in my cart + + Scenario: Adding product to cart with more than stocked quantity + When I add 3 of this product to the cart + Then I should be on the cart summary page + And I should be notified that TSHIRT does not have sufficient stock + + Scenario: Adding product, with on-hold stock, to cart with more than stocked quantity + Given the product has 2 on hold + Then I should see that this product is out of stock + + Scenario: Adding product, with on-hold stock, to cart with enough quantity + Given the product has 1 on hold + When I add 2 of this product to the cart + Then I should be on the cart summary page + And I should be notified that TSHIRT does not have sufficient stock + diff --git a/src/CoreShop/Behat/Context/Setup/ProductContext.php b/src/CoreShop/Behat/Context/Setup/ProductContext.php index 347c1a4d84..d1fb6720ec 100644 --- a/src/CoreShop/Behat/Context/Setup/ProductContext.php +++ b/src/CoreShop/Behat/Context/Setup/ProductContext.php @@ -246,6 +246,50 @@ public function theProductIsNotActive(ProductInterface $product) $this->saveProduct($product); } + /** + * @Given /^the (product "[^"]+") is stock tracked$/ + * @Given /^the (product) is stock tracked$/ + */ + public function theProductIsTracked(ProductInterface $product) + { + $product->setIsTracked(true); + + $this->saveProduct($product); + } + + /** + * @Given /^the (product "[^"]+") is not stock tracked$/ + * @Given /^the (product) is not stock tracked$/ + */ + public function theProductIsNotTracked(ProductInterface $product) + { + $product->setIsTracked(false); + + $this->saveProduct($product); + } + + /** + * @Given /^the (product "[^"]+") has (\d+) on hand$/ + * @Given /^the (product) has (\d+) on hand$/ + */ + public function theProductHasOnHand(ProductInterface $product, int $onHand) + { + $product->setOnHand($onHand); + + $this->saveProduct($product); + } + + /** + * @Given /^the (product "[^"]+") has (\d+) on hold$/ + * @Given /^the (product) has (\d+) on hold$/ + */ + public function theProductHasOnHold(ProductInterface $product, int $onHold) + { + $product->setOnHold($onHold); + + $this->saveProduct($product); + } + /** * @Given /^the (product "[^"]+") is published$/ * @Given /^the (product) is published$/ diff --git a/src/CoreShop/Behat/Context/Ui/Frontend/CartContext.php b/src/CoreShop/Behat/Context/Ui/Frontend/CartContext.php index be63d72b39..da5a488978 100644 --- a/src/CoreShop/Behat/Context/Ui/Frontend/CartContext.php +++ b/src/CoreShop/Behat/Context/Ui/Frontend/CartContext.php @@ -166,6 +166,17 @@ public function iShouldBeNotifiedThatICanOnlyOrderAMaximumQuantityOf(string $qua ); } + /** + * @Then I should be notified that :productName does not have sufficient stock + */ + public function iShouldBeNotifiedThatDoesNotHaveSufficientStock(string $productName) + { + $this->notificationChecker->checkNotification( + sprintf('%s DOES NOT HAVE SUFFICIENT STOCK.', $productName), + NotificationType::error() + ); + } + /** * @Then there should be one item in my cart */ diff --git a/src/CoreShop/Behat/Context/Ui/Frontend/ProductContext.php b/src/CoreShop/Behat/Context/Ui/Frontend/ProductContext.php index 74054d32aa..4a976d82e0 100644 --- a/src/CoreShop/Behat/Context/Ui/Frontend/ProductContext.php +++ b/src/CoreShop/Behat/Context/Ui/Frontend/ProductContext.php @@ -216,4 +216,13 @@ public function iShouldSeeTheQuantityPriceRuleForUnitStartingFrom(int $number, $ Assert::greaterThan($priceRules, $number+1); Assert::contains($priceRules[$number]['startingFrom'], $startingFrom); } + /** + * @Then /^I should see that this (product) is out of stock$/ + */ + public function iShouldSeeThatThisProductIsOutOfStock(ProductInterface $product) + { + $this->productPage->tryToOpenWithUri($this->linkGenerator->generate($product, null, ['_locale' => 'en'])); + + Assert::true($this->productPage->getIsOutOfStock()); + } } diff --git a/src/CoreShop/Behat/Page/Frontend/ProductPage.php b/src/CoreShop/Behat/Page/Frontend/ProductPage.php index 02fb6b3131..d191d75f40 100644 --- a/src/CoreShop/Behat/Page/Frontend/ProductPage.php +++ b/src/CoreShop/Behat/Page/Frontend/ProductPage.php @@ -60,6 +60,11 @@ public function getTaxRate(): string return $this->getElement('product_tax_rate')->getText(); } + public function getIsOutOfStock(): bool + { + return $this->hasElement('product_ouf_of_stock'); + } + public function getTax(): string { return $this->getElement('product_tax')->getText(); @@ -140,6 +145,7 @@ protected function getDefinedElements(): array 'product_unit_price_carton' => '[data-test-product-unit-price-carton]', 'product_unit_price_palette' => '[data-test-product-unit-price-palette]', 'product_quantity_price_rules' => '[data-test-product-quantity-price-rules]', + 'product_ouf_of_stock' => '[data-test-product-out-of-stock]', ]); } } diff --git a/src/CoreShop/Behat/Page/Frontend/ProductPageInterface.php b/src/CoreShop/Behat/Page/Frontend/ProductPageInterface.php index 61204c28af..80bd9df61b 100644 --- a/src/CoreShop/Behat/Page/Frontend/ProductPageInterface.php +++ b/src/CoreShop/Behat/Page/Frontend/ProductPageInterface.php @@ -36,6 +36,8 @@ public function getTaxRate(): string; public function getTax(): string; + public function getIsOutOfStock(): bool; + public function getQuantityPriceRules(): array; public function getQuantityPriceRulesForUnit(ProductUnitInterface $unit): array; diff --git a/src/CoreShop/Behat/Resources/config/suites/ui/cart.yml b/src/CoreShop/Behat/Resources/config/suites/ui/cart.yml index 54eaaaad97..86b204ca01 100644 --- a/src/CoreShop/Behat/Resources/config/suites/ui/cart.yml +++ b/src/CoreShop/Behat/Resources/config/suites/ui/cart.yml @@ -33,6 +33,7 @@ default: - coreshop.behat.context.setup.exchange_rate - coreshop.behat.context.ui.cart + - coreshop.behat.context.ui.product - coreshop.behat.context.ui.user - coreshop.behat.context.ui.register - coreshop.behat.context.ui.store diff --git a/src/CoreShop/Bundle/FrontendBundle/Resources/views/Product/detail.html.twig b/src/CoreShop/Bundle/FrontendBundle/Resources/views/Product/detail.html.twig index d365ff5c7c..c42e59cb23 100644 --- a/src/CoreShop/Bundle/FrontendBundle/Resources/views/Product/detail.html.twig +++ b/src/CoreShop/Bundle/FrontendBundle/Resources/views/Product/detail.html.twig @@ -58,10 +58,12 @@
  • {{ 'coreshop.ui.availability'|trans }}: {% if product.isTracked %} - {% if coreshop_inventory_is_sufficient(product) %} + {% if coreshop_inventory_is_available(product) %} {{ 'coreshop.ui.in_stock'|trans }} {% else %} - {{ 'coreshop.ui.out_of_stock'|trans }} + + {{ 'coreshop.ui.out_of_stock'|trans }} + {% endif %} {% else %} {{ 'coreshop.ui.in_stock'|trans }} diff --git a/src/CoreShop/Bundle/InventoryBundle/Twig/InventoryExtension.php b/src/CoreShop/Bundle/InventoryBundle/Twig/InventoryExtension.php index bbf370d8fd..1e5217f11b 100644 --- a/src/CoreShop/Bundle/InventoryBundle/Twig/InventoryExtension.php +++ b/src/CoreShop/Bundle/InventoryBundle/Twig/InventoryExtension.php @@ -14,8 +14,8 @@ namespace CoreShop\Bundle\InventoryBundle\Twig; -use CoreShop\Bundle\InventoryBundle\Templating\Helper\InventoryHelper; use CoreShop\Component\Inventory\Checker\AvailabilityCheckerInterface; +use CoreShop\Component\Inventory\Model\StockableInterface; use Twig\Extension\AbstractExtension; use Twig\TwigFunction; @@ -35,7 +35,12 @@ public function getFunctions() { return [ new TwigFunction('coreshop_inventory_is_available', [$this->checker, 'isStockAvailable']), - new TwigFunction('coreshop_inventory_is_sufficient', [$this->checker, 'isStockSufficient']), + new TwigFunction('coreshop_inventory_is_sufficient', [$this, 'isStockSufficient']), ]; } + + public function isStockSufficient(StockableInterface $stockable, $quantity = 1) + { + return $this->checker->isStockSufficient($stockable, $quantity); + } } From 4ea5dc569a0ed30762a89aefa8564de4ef0ec7bf Mon Sep 17 00:00:00 2001 From: Dominik Pfaffenbauer Date: Fri, 10 Apr 2020 09:57:49 +0200 Subject: [PATCH 06/12] [3.0] add cart-price-rule tests --- .../ui/cart/automatic_cart_price_rule.feature | 30 +++++++++++++++++++ features/ui/cart/voucher_code.feature | 30 +++++++++++++++++++ .../Context/Setup/CartPriceRuleContext.php | 5 +++- .../Behat/Context/Ui/Frontend/CartContext.php | 24 +++++++++++++++ src/CoreShop/Behat/Page/Frontend/CartPage.php | 8 +++++ .../Behat/Page/Frontend/CartPageInterface.php | 2 ++ .../Behat/Resources/config/suites/ui/cart.yml | 2 ++ .../config/services/cart-processor.yml | 4 --- .../views/Cart/Summary/_summary.html.twig | 4 +-- .../Order/Processor/CartItemsProcessor.php | 3 ++ .../Order/Processor/CartTotalProcessor.php | 30 ------------------- .../Component/Order/Model/CartPriceRule.php | 2 +- .../Order/Model/CartPriceRuleInterface.php | 2 +- src/CoreShop/Component/Order/Model/Order.php | 2 ++ 14 files changed, 109 insertions(+), 39 deletions(-) create mode 100644 features/ui/cart/automatic_cart_price_rule.feature create mode 100644 features/ui/cart/voucher_code.feature delete mode 100644 src/CoreShop/Component/Core/Order/Processor/CartTotalProcessor.php diff --git a/features/ui/cart/automatic_cart_price_rule.feature b/features/ui/cart/automatic_cart_price_rule.feature new file mode 100644 index 0000000000..81e34465b0 --- /dev/null +++ b/features/ui/cart/automatic_cart_price_rule.feature @@ -0,0 +1,30 @@ +@ui @cart +Feature: Getting an automatic cart price rule + Background: + Given the site operates on a store in "Austria" + And the store "Austria" is the default store + And the site has a product "TShirt" priced at 10000 + And the product is active and published and available for store "Austria" + And adding a cart price rule named "Easter Madness" + And the cart rule is active + And the cart rule is not a voucher rule + + Scenario: Applying an automatic cart rule with fixed discount to the cart + Given the cart rule has a action discount with 20 in currency "EUR" off applied on total + When I add this product to the cart + Then I should be on the cart summary page + And I should be notified that the product has been successfully added + And there should be one item in my cart + And this item should have name "TSHIRT" + And I should see "TShirt" with unit price "€100.00" in my cart + And my cart's total should be "€80.00" + + Scenario: Applying an automatic cart rule with percentage discount to the cart + Given the cart rule has a action discount-percent with 30% discount + When I add this product to the cart + Then I should be on the cart summary page + And I should be notified that the product has been successfully added + And there should be one item in my cart + And this item should have name "TSHIRT" + And I should see "TShirt" with unit price "€100.00" in my cart + And my cart's total should be "€70.00" diff --git a/features/ui/cart/voucher_code.feature b/features/ui/cart/voucher_code.feature new file mode 100644 index 0000000000..4d7d50f41c --- /dev/null +++ b/features/ui/cart/voucher_code.feature @@ -0,0 +1,30 @@ +@ui @cart +Feature: Getting an cart-price-rule with a voucher code + + Background: + Given the site operates on a store in "Austria" + And the store "Austria" is the default store + And the site has a product "TShirt" priced at 10000 + And the product is active and published and available for store "Austria" + And adding a cart price rule named "Easter Madness" + And the cart rule is active + And the cart rule is a voucher rule with code "EASTER" + + Scenario: Applying an voucher cart rule with fixed discount to the cart + Given the cart rule has a action discount with 20 in currency "EUR" off applied on total + When I add this product to the cart + And I apply the voucher code "EASTER" + Then I should be notified that the voucher has been applied + And I should see "TShirt" with unit price "€100.00" in my cart + And my cart's total should be "€80.00" + + + Scenario: Applying an invalid voucher cart rule + Given the cart rule has a action discount with 20 in currency "EUR" off applied on total + And the cart rule has a condition amount with value "200" to "400" + When I add this product to the cart + And I apply the voucher code "EASTER" + Then I should be notified that the voucher is invalid + And I should see "TShirt" with unit price "€100.00" in my cart + And my cart's total should be "€100.00" + diff --git a/src/CoreShop/Behat/Context/Setup/CartPriceRuleContext.php b/src/CoreShop/Behat/Context/Setup/CartPriceRuleContext.php index fd22cb7b26..e9bd5ccc09 100644 --- a/src/CoreShop/Behat/Context/Setup/CartPriceRuleContext.php +++ b/src/CoreShop/Behat/Context/Setup/CartPriceRuleContext.php @@ -404,14 +404,17 @@ public function theCartPriceRuleHasADiscountPercentAction(CartPriceRuleInterface /** * @Given /^the (cart rule "[^"]+") has a action discount with ([^"]+) in (currency "[^"]+") off$/ * @Given /^the (cart rule) has a action discount with ([^"]+) in (currency "[^"]+") off$/ + * @Given /^the (cart rule "[^"]+") has a action discount with ([^"]+) in (currency "[^"]+") off applied on ([^"]+)$/ + * @Given /^the (cart rule) has a action discount with ([^"]+) in (currency "[^"]+") off applied on ([^"]+)$/ */ - public function theCartPriceRuleHasADiscountAmountAction(CartPriceRuleInterface $rule, $amount, CurrencyInterface $currency) + public function theCartPriceRuleHasADiscountAmountAction(CartPriceRuleInterface $rule, $amount, CurrencyInterface $currency, string $appliedOn = 'total') { $this->assertActionForm(DiscountAmountConfigurationType::class, 'discountAmount'); $this->addAction($rule, $this->createActionWithForm('discountAmount', [ 'amount' => (int) $amount, 'currency' => $currency->getId(), + 'applyOn' => $appliedOn ])); } diff --git a/src/CoreShop/Behat/Context/Ui/Frontend/CartContext.php b/src/CoreShop/Behat/Context/Ui/Frontend/CartContext.php index da5a488978..ed846d09ae 100644 --- a/src/CoreShop/Behat/Context/Ui/Frontend/CartContext.php +++ b/src/CoreShop/Behat/Context/Ui/Frontend/CartContext.php @@ -144,6 +144,22 @@ public function iShouldBeNotifiedThatItHasBeenSuccessfullyAdded() $this->notificationChecker->checkNotification('ITEM ADDED', NotificationType::success()); } + /** + * @Then I should be notified that the voucher has been applied + */ + public function iShouldBeNotifiedThatTheVoucherHasBeenApplied() + { + $this->notificationChecker->checkNotification('VOUCHER HAS BEEN SUCCESSFULLY APPLIED', NotificationType::success()); + } + + /** + * @Then I should be notified that the voucher is invalid + */ + public function iShouldBeNotifiedThatTheVoucherIsInvalid() + { + $this->notificationChecker->checkNotification('THIS VOUCHER IS INVALID', NotificationType::error()); + } + /** * @Then I should be notified that I need to order at least :quantity of :productName */ @@ -193,6 +209,14 @@ public function thisProductShouldHaveName($itemName) Assert::true($this->cartPage->hasItemNamed($itemName)); } + /** + * @Given /^I apply the voucher code "([^"]+)"$/ + */ + public function iApplyTheCartRuleToMyCart($voucherCode) + { + $this->cartPage->applyVoucherCode($voucherCode); + } + /** * @Then /^I should see "([^"]+)" with unit price "([^"]+)" in my cart$/ */ diff --git a/src/CoreShop/Behat/Page/Frontend/CartPage.php b/src/CoreShop/Behat/Page/Frontend/CartPage.php index 73a8de35dc..eff4374337 100644 --- a/src/CoreShop/Behat/Page/Frontend/CartPage.php +++ b/src/CoreShop/Behat/Page/Frontend/CartPage.php @@ -96,6 +96,12 @@ public function removeProduct(string $productName): void $this->getElement('delete_button', ['%name%' => $productName])->press(); } + public function applyVoucherCode(string $voucherCode): void + { + $this->getElement('voucher_code')->setValue($voucherCode); + $this->getElement('apply_voucher_button')->click(); + } + public function getTotal(): string { $cartTotalText = $this->getElement('cart_total')->getText(); @@ -141,7 +147,9 @@ protected function getDefinedElements(): array 'item_total_price_unit' => '[data-test-cart-item-row-unit-%unitId%="%name%"] [data-test-cart-item-total-price]', 'item_quantity_input' => '[data-test-cart-item-quantity-input="%name%"]', 'update_cart_button' => '[data-test-update-cart-button]', + 'apply_voucher_button' => '[data-test-apply-voucher-button]', 'delete_button' => '[data-test-cart-remove-button="%name%"]', + 'voucher_code' => '[data-test-voucher-code]', 'cart_total' => '[data-test-cart-total]', 'cart_item_unit' => '[data-test-cart-item-unit-%unitId%="%name%"]', ]); diff --git a/src/CoreShop/Behat/Page/Frontend/CartPageInterface.php b/src/CoreShop/Behat/Page/Frontend/CartPageInterface.php index 1b1db64ea9..b7457ee9f6 100644 --- a/src/CoreShop/Behat/Page/Frontend/CartPageInterface.php +++ b/src/CoreShop/Behat/Page/Frontend/CartPageInterface.php @@ -40,5 +40,7 @@ public function changeQuantity(string $productName, string $quantity): void; public function removeProduct(string $productName): void; + public function applyVoucherCode(string $voucherCode): void; + public function getTotal(): string; } diff --git a/src/CoreShop/Behat/Resources/config/suites/ui/cart.yml b/src/CoreShop/Behat/Resources/config/suites/ui/cart.yml index 86b204ca01..8175edb57c 100644 --- a/src/CoreShop/Behat/Resources/config/suites/ui/cart.yml +++ b/src/CoreShop/Behat/Resources/config/suites/ui/cart.yml @@ -18,6 +18,7 @@ default: - coreshop.behat.context.transform.currency - coreshop.behat.context.transform.product_unit - coreshop.behat.context.transform.product_quantity_price_rule + - coreshop.behat.context.transform.cart_price_rule - coreshop.behat.context.setup.store - coreshop.behat.context.setup.product @@ -31,6 +32,7 @@ default: - coreshop.behat.context.setup.currency - coreshop.behat.context.setup.country - coreshop.behat.context.setup.exchange_rate + - coreshop.behat.context.setup.cart_price_rule - coreshop.behat.context.ui.cart - coreshop.behat.context.ui.product diff --git a/src/CoreShop/Bundle/CoreBundle/Resources/config/services/cart-processor.yml b/src/CoreShop/Bundle/CoreBundle/Resources/config/services/cart-processor.yml index bc7c8310e8..0588c82b90 100644 --- a/src/CoreShop/Bundle/CoreBundle/Resources/config/services/cart-processor.yml +++ b/src/CoreShop/Bundle/CoreBundle/Resources/config/services/cart-processor.yml @@ -77,10 +77,6 @@ services: tags: - { name: coreshop.cart_processor, priority: 350 } - CoreShop\Component\Core\Order\Processor\CartTotalProcessor: - tags: - - { name: coreshop.cart_processor, priority: 300 } - CoreShop\Component\Core\Order\Processor\CartBaseProcessor: arguments: - '@CoreShop\Component\Currency\Converter\CurrencyConverterInterface' diff --git a/src/CoreShop/Bundle/FrontendBundle/Resources/views/Cart/Summary/_summary.html.twig b/src/CoreShop/Bundle/FrontendBundle/Resources/views/Cart/Summary/_summary.html.twig index 2dd720bbc8..1ac4e6e4d9 100644 --- a/src/CoreShop/Bundle/FrontendBundle/Resources/views/Cart/Summary/_summary.html.twig +++ b/src/CoreShop/Bundle/FrontendBundle/Resources/views/Cart/Summary/_summary.html.twig @@ -18,8 +18,8 @@ - {{ form_row(form.cartRuleCoupon) }} - + {{ form_row(form.cartRuleCoupon, coreshop_test_form_attribute('voucher-code')) }} + {{ 'coreshop.ui.subtotal_inc'|trans }}: diff --git a/src/CoreShop/Component/Core/Order/Processor/CartItemsProcessor.php b/src/CoreShop/Component/Core/Order/Processor/CartItemsProcessor.php index 9c9b7ce108..8dbb3f6fc3 100644 --- a/src/CoreShop/Component/Core/Order/Processor/CartItemsProcessor.php +++ b/src/CoreShop/Component/Core/Order/Processor/CartItemsProcessor.php @@ -116,5 +116,8 @@ public function process(OrderInterface $cart): void $cart->setSubtotal($subtotalGross, true); $cart->setSubtotal($subtotalNet, false); + + $cart->setTotal($cart->getSubtotal(false) + $cart->getAdjustmentsTotal(null, false), false); + $cart->setTotal($cart->getSubtotal(true) + $cart->getAdjustmentsTotal(null, true), true); } } diff --git a/src/CoreShop/Component/Core/Order/Processor/CartTotalProcessor.php b/src/CoreShop/Component/Core/Order/Processor/CartTotalProcessor.php deleted file mode 100644 index 9f72c4d8b8..0000000000 --- a/src/CoreShop/Component/Core/Order/Processor/CartTotalProcessor.php +++ /dev/null @@ -1,30 +0,0 @@ -setTotal($cart->getSubtotal(false) + $cart->getAdjustmentsTotal(null, false), false); - $cart->setTotal($cart->getSubtotal(true) + $cart->getAdjustmentsTotal(null, true), true); - } -} diff --git a/src/CoreShop/Component/Order/Model/CartPriceRule.php b/src/CoreShop/Component/Order/Model/CartPriceRule.php index 87e57f0a0d..924bfa446d 100644 --- a/src/CoreShop/Component/Order/Model/CartPriceRule.php +++ b/src/CoreShop/Component/Order/Model/CartPriceRule.php @@ -73,7 +73,7 @@ public function getId() /** * {@inheritdoc} */ - public function getDescription(): string + public function getDescription() { return $this->description; } diff --git a/src/CoreShop/Component/Order/Model/CartPriceRuleInterface.php b/src/CoreShop/Component/Order/Model/CartPriceRuleInterface.php index fcec8eb740..dad0ed2247 100644 --- a/src/CoreShop/Component/Order/Model/CartPriceRuleInterface.php +++ b/src/CoreShop/Component/Order/Model/CartPriceRuleInterface.php @@ -36,7 +36,7 @@ public function setLabel($label, $language = null); /** * @return string */ - public function getDescription(): string; + public function getDescription(); /** * @param string $description diff --git a/src/CoreShop/Component/Order/Model/Order.php b/src/CoreShop/Component/Order/Model/Order.php index 371c019ae6..0870811a82 100644 --- a/src/CoreShop/Component/Order/Model/Order.php +++ b/src/CoreShop/Component/Order/Model/Order.php @@ -738,5 +738,7 @@ protected function recalculateBaseAfterAdjustmentChange() */ protected function recalculateAfterAdjustmentChange() { + $this->setTotal($this->getTotal(true) + $this->getAdjustmentsTotal(null, true), true); + $this->setTotal($this->getTotal(false) + $this->getAdjustmentsTotal(null, false), false); } } From 3b314b63ecbfc68959bed4f407459aea859c1193 Mon Sep 17 00:00:00 2001 From: Dominik Pfaffenbauer Date: Fri, 10 Apr 2020 10:13:03 +0200 Subject: [PATCH 07/12] [3.0] invalidate voucher rule tests --- ...validate_automatic_cart_price_rule.feature | 27 ++++++++++++++++ .../ui/cart/invalidate_voucher_code.feature | 31 +++++++++++++++++++ features/ui/cart/voucher_code.feature | 1 - 3 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 features/ui/cart/invalidate_automatic_cart_price_rule.feature create mode 100644 features/ui/cart/invalidate_voucher_code.feature diff --git a/features/ui/cart/invalidate_automatic_cart_price_rule.feature b/features/ui/cart/invalidate_automatic_cart_price_rule.feature new file mode 100644 index 0000000000..c7d9786f12 --- /dev/null +++ b/features/ui/cart/invalidate_automatic_cart_price_rule.feature @@ -0,0 +1,27 @@ +@ui @cart @wip +Feature: Applying a valid cart-price-rule that gets invalidated after the cart changes + + Background: + Given the site operates on a store in "Austria" + And the store "Austria" is the default store + And the site has a product "TShirt" priced at 10000 + And the product is active and published and available for store "Austria" + And adding a cart price rule named "Easter Madness" + And the cart rule is active + And the cart rule is not a voucher rule + And the cart rule has a action discount with 20 in currency "EUR" off applied on total + And the cart rule has a condition amount with value "1" to "100" + + Scenario: Invalidate Price Rule by adding another Product + When I add this product to the cart + And I should see "TShirt" with unit price "€100.00" in my cart + And my cart's total should be "€80.00" + Given I add this product to the cart + And my cart's total should be "€200.00" + + Scenario: Invalidate Price Rule by changing the quantity + When I add this product to the cart + And I should see "TShirt" with unit price "€100.00" in my cart + And my cart's total should be "€80.00" + When I change "TShirt" quantity to 2 + Then my cart's total should be "€200.00" diff --git a/features/ui/cart/invalidate_voucher_code.feature b/features/ui/cart/invalidate_voucher_code.feature new file mode 100644 index 0000000000..7aa84e2a45 --- /dev/null +++ b/features/ui/cart/invalidate_voucher_code.feature @@ -0,0 +1,31 @@ +@ui @cart @wip +Feature: Applying a valid voucher that gets invalidated after the cart changes + + Background: + Given the site operates on a store in "Austria" + And the store "Austria" is the default store + And the site has a product "TShirt" priced at 10000 + And the product is active and published and available for store "Austria" + And adding a cart price rule named "Easter Madness" + And the cart rule is active + And the cart rule is a voucher rule with code "EASTER" + And the cart rule has a action discount with 20 in currency "EUR" off applied on total + And the cart rule has a condition amount with value "1" to "100" + + Scenario: Invalidate Price Rule by adding another Product + When I add this product to the cart + And I apply the voucher code "EASTER" + Then I should be notified that the voucher has been applied + And I should see "TShirt" with unit price "€100.00" in my cart + And my cart's total should be "€80.00" + Given I add this product to the cart + And my cart's total should be "€200.00" + + Scenario: Invalidate Price Rule by changing the quantity + When I add this product to the cart + And I apply the voucher code "EASTER" + Then I should be notified that the voucher has been applied + And I should see "TShirt" with unit price "€100.00" in my cart + And my cart's total should be "€80.00" + When I change "TShirt" quantity to 2 + Then my cart's total should be "€200.00" diff --git a/features/ui/cart/voucher_code.feature b/features/ui/cart/voucher_code.feature index 4d7d50f41c..42bd1a1492 100644 --- a/features/ui/cart/voucher_code.feature +++ b/features/ui/cart/voucher_code.feature @@ -18,7 +18,6 @@ Feature: Getting an cart-price-rule with a voucher code And I should see "TShirt" with unit price "€100.00" in my cart And my cart's total should be "€80.00" - Scenario: Applying an invalid voucher cart rule Given the cart rule has a action discount with 20 in currency "EUR" off applied on total And the cart rule has a condition amount with value "200" to "400" From 4cbf318845183cd7d664e84e1b84d0431da5114b Mon Sep 17 00:00:00 2001 From: Dominik Pfaffenbauer Date: Fri, 10 Apr 2020 14:11:00 +0200 Subject: [PATCH 08/12] [3.0] start implementing the checkout --- features/ui/checkout/checkout.feature | 28 +++ .../Behat/Context/Setup/CustomerContext.php | 3 + .../Behat/Context/Setup/PaymentContext.php | 5 +- .../Behat/Context/Setup/ShippingContext.php | 37 +++ .../Behat/Context/Setup/StoreContext.php | 7 + .../Context/Transform/CustomerContext.php | 21 +- .../Context/Transform/PaymentContext.php | 2 +- .../Context/Ui/Frontend/CheckoutContext.php | 220 ++++++++++++++++++ .../Page/Frontend/AbstractFrontendPage.php | 19 ++ .../Page/Frontend/Checkout/AddressPage.php | 68 ++++++ .../Checkout/AddressPageInterface.php | 31 +++ .../Page/Frontend/Checkout/CustomerPage.php | 38 +++ .../Checkout/CustomerPageInterface.php | 23 ++ .../Page/Frontend/Checkout/PaymentPage.php | 51 ++++ .../Checkout/PaymentPageInterface.php | 22 ++ .../Page/Frontend/Checkout/ShippingPage.php | 46 ++++ .../Checkout/ShippingPageInterface.php | 22 ++ .../Page/Frontend/Checkout/SummaryPage.php | 61 +++++ .../Checkout/SummaryPageInterface.php | 28 +++ .../Page/Frontend/Checkout/ThankYouPage.php | 32 +++ .../Checkout/ThankYouPageInterface.php | 22 ++ .../config/services/contexts/transform.yml | 1 + .../Resources/config/services/contexts/ui.yml | 14 ++ .../Behat/Resources/config/services/pages.yml | 24 ++ .../Behat/Resources/config/suites/ui.yml | 1 + .../Resources/config/suites/ui/checkout.yml | 50 ++++ .../views/Checkout/steps/address.html.twig | 8 +- .../views/Checkout/steps/payment.html.twig | 6 +- .../views/Checkout/steps/shipping.html.twig | 9 +- .../views/Checkout/steps/summary.html.twig | 21 +- .../Model/PaymentProviderInterface.php | 7 +- 31 files changed, 908 insertions(+), 19 deletions(-) create mode 100644 features/ui/checkout/checkout.feature create mode 100644 src/CoreShop/Behat/Context/Ui/Frontend/CheckoutContext.php create mode 100644 src/CoreShop/Behat/Page/Frontend/Checkout/AddressPage.php create mode 100644 src/CoreShop/Behat/Page/Frontend/Checkout/AddressPageInterface.php create mode 100644 src/CoreShop/Behat/Page/Frontend/Checkout/CustomerPage.php create mode 100644 src/CoreShop/Behat/Page/Frontend/Checkout/CustomerPageInterface.php create mode 100644 src/CoreShop/Behat/Page/Frontend/Checkout/PaymentPage.php create mode 100644 src/CoreShop/Behat/Page/Frontend/Checkout/PaymentPageInterface.php create mode 100644 src/CoreShop/Behat/Page/Frontend/Checkout/ShippingPage.php create mode 100644 src/CoreShop/Behat/Page/Frontend/Checkout/ShippingPageInterface.php create mode 100644 src/CoreShop/Behat/Page/Frontend/Checkout/SummaryPage.php create mode 100644 src/CoreShop/Behat/Page/Frontend/Checkout/SummaryPageInterface.php create mode 100644 src/CoreShop/Behat/Page/Frontend/Checkout/ThankYouPage.php create mode 100644 src/CoreShop/Behat/Page/Frontend/Checkout/ThankYouPageInterface.php create mode 100644 src/CoreShop/Behat/Resources/config/suites/ui/checkout.yml diff --git a/features/ui/checkout/checkout.feature b/features/ui/checkout/checkout.feature new file mode 100644 index 0000000000..c6cbce33a4 --- /dev/null +++ b/features/ui/checkout/checkout.feature @@ -0,0 +1,28 @@ +@ui @checkout +Feature: Ability to complete the checkout + + Background: + Given the site operates on a store in "Austria" + And the store "Austria" is the default store + And the site has a product "TShirt" priced at 10000 + And the product is active and published and available for store "Austria" + And I am a logged in customer + And the customer has an address with country "Austria", "4600", "Wels", "Freiung", "9-11/N3" + And the site has a carrier "Post" and ships for 10 in currency "EUR" + And the site has a payment provider "Bankwire" using factory "offline" + Then I add this product to the cart + + Scenario: I proceed to the checkout + Given I am at the address checkout step + Then I should be on the address checkout step + And I use the last address as invoice address + And I submit the address step + Then I should be on the shipping checkout step + When I submit the shipping step + Then I should be on the payment checkout step + And I select the payment provider "Bankwire" + When I submit the payment step + Then I should be on the summary checkout step + When I accept the checkout terms of service + And I submit the order + Then I should be on the thank you page diff --git a/src/CoreShop/Behat/Context/Setup/CustomerContext.php b/src/CoreShop/Behat/Context/Setup/CustomerContext.php index f84bd18051..1ab2b391a3 100644 --- a/src/CoreShop/Behat/Context/Setup/CustomerContext.php +++ b/src/CoreShop/Behat/Context/Setup/CustomerContext.php @@ -106,6 +106,7 @@ public function iAmCustomer(CustomerInterface $customer) /** * @Given /^the (customer "[^"]+") has an address with (country "[^"]+"), "([^"]+)", "([^"]+)", "([^"]+)", "([^"]+)"$/ + * @Given /^the (customer) has an address with (country "[^"]+"), "([^"]+)", "([^"]+)", "([^"]+)", "([^"]+)"$/ */ public function theCustomerHasAnAddress( CustomerInterface $customer, @@ -131,6 +132,8 @@ public function theCustomerHasAnAddress( $customer->addAddress($address); $customer->save(); + + $this->sharedStorage->set('address', $address); } /** diff --git a/src/CoreShop/Behat/Context/Setup/PaymentContext.php b/src/CoreShop/Behat/Context/Setup/PaymentContext.php index c6b606a3ae..41dca2407c 100644 --- a/src/CoreShop/Behat/Context/Setup/PaymentContext.php +++ b/src/CoreShop/Behat/Context/Setup/PaymentContext.php @@ -49,6 +49,7 @@ public function __construct( /** * @Given /^There is a payment provider "([^"]+)" using factory "([^"]+)"$/ + * @Given /^the site has a payment provider "([^"]+)" using factory "([^"]+)"$/ */ public function thereIsAPaymentProviderUsingFactory($name, $factory) { @@ -69,12 +70,14 @@ public function thereIsAPaymentProviderUsingFactory($name, $factory) $gatewayConfig->setGatewayName($name); $paymentProvider->setGatewayConfig($gatewayConfig); $paymentProvider->setIdentifier($name); + $paymentProvider->addStore($this->sharedStorage->get('store')); + $paymentProvider->setActive(true); $this->entityManager->persist($gatewayConfig); $this->entityManager->persist($paymentProvider); $this->entityManager->flush(); - $this->sharedStorage->set('paymentProvider', $paymentProvider); + $this->sharedStorage->set('payment-provider', $paymentProvider); } /** diff --git a/src/CoreShop/Behat/Context/Setup/ShippingContext.php b/src/CoreShop/Behat/Context/Setup/ShippingContext.php index d23a55edc0..c2a471b54b 100644 --- a/src/CoreShop/Behat/Context/Setup/ShippingContext.php +++ b/src/CoreShop/Behat/Context/Setup/ShippingContext.php @@ -99,6 +99,41 @@ public function theSiteHasACarrier($name) $this->createCarrier($name); } + /** + * @Given /^the site has a carrier "([^"]+)" and ships for (\d+) in (currency "[^"]+")$/ + */ + public function theSiteHasACarrierAndShipsForX($name, int $price, CurrencyInterface $currency) + { + $carrier = $this->createCarrier($name); + + /** + * @var ShippingRuleInterface $rule + */ + $rule = $this->shippingRuleFactory->createNew(); + $rule->setName($name); + $rule->setActive(true); + + $this->assertActionForm(PriceActionConfigurationType::class, 'price'); + + $this->addAction($rule, $this->createActionWithForm('price', [ + 'price' => $price, + 'currency' => $currency->getId(), + ])); + + $shippingRuleGroup = $this->shippingRuleGroupFactory->createNew(); + $shippingRuleGroup->setShippingRule($rule); + $shippingRuleGroup->setPriority(1); + + $carrier->addShippingRule($shippingRuleGroup); + + $this->objectManager->persist($carrier); + $this->objectManager->persist($shippingRuleGroup); + $this->objectManager->persist($rule); + $this->objectManager->flush(); + + $this->sharedStorage->set('shipping-rule', $rule); + } + /** * @Given /^the (carrier "[^"]+") has (tax rule group "[^"]+")$/ * @Given /^the (carrier) has the (tax rule group "[^"]+")$/ @@ -530,6 +565,8 @@ private function createCarrier($name) } $this->saveCarrier($carrier); + + return $carrier; } /** diff --git a/src/CoreShop/Behat/Context/Setup/StoreContext.php b/src/CoreShop/Behat/Context/Setup/StoreContext.php index 7b70124f8c..01fa3720b0 100644 --- a/src/CoreShop/Behat/Context/Setup/StoreContext.php +++ b/src/CoreShop/Behat/Context/Setup/StoreContext.php @@ -156,6 +156,13 @@ private function createStore($name, CurrencyInterface $currency = null, CountryI $country->setIsoCode('AT'); $country->setCurrency($currency); $country->setActive(true); + $country->setAddressFormat(' + %Text(company); + %Text(salutation); %Text(firstname); %Text(lastname); + %Text(street); %Text(number); + %Text(postCode); %Text(city); + %DataObject(country,{"method" : "getName"}); + '); $this->entityManager->persist($country); diff --git a/src/CoreShop/Behat/Context/Transform/CustomerContext.php b/src/CoreShop/Behat/Context/Transform/CustomerContext.php index f926dada77..ea63fee681 100644 --- a/src/CoreShop/Behat/Context/Transform/CustomerContext.php +++ b/src/CoreShop/Behat/Context/Transform/CustomerContext.php @@ -15,16 +15,21 @@ namespace CoreShop\Behat\Context\Transform; use Behat\Behat\Context\Context; +use CoreShop\Behat\Service\SharedStorageInterface; use CoreShop\Component\Core\Model\CustomerInterface; use CoreShop\Component\Customer\Repository\CustomerRepositoryInterface; use Webmozart\Assert\Assert; final class CustomerContext implements Context { + private $sharedStorage; private $customerRepository; - public function __construct(CustomerRepositoryInterface $customerRepository) - { + public function __construct( + SharedStorageInterface $sharedStorage, + CustomerRepositoryInterface $customerRepository + ) { + $this->sharedStorage = $sharedStorage; $this->customerRepository = $customerRepository; } @@ -41,6 +46,18 @@ public function getCustomerByEmail($email) return $customer; } + /** + * @Transform /^customer$/ + */ + public function customer() + { + $customer = $this->sharedStorage->get('customer'); + + Assert::isInstanceOf($customer, CustomerInterface::class); + + return $customer; + } + /** * @Transform /^customer "([^"]+)"$/ * @Transform /^username "([^"]+)"$/ diff --git a/src/CoreShop/Behat/Context/Transform/PaymentContext.php b/src/CoreShop/Behat/Context/Transform/PaymentContext.php index 042e070194..b4d426f06b 100644 --- a/src/CoreShop/Behat/Context/Transform/PaymentContext.php +++ b/src/CoreShop/Behat/Context/Transform/PaymentContext.php @@ -53,6 +53,6 @@ public function getPaymentProviderByTitle($title) */ public function country() { - return $this->sharedStorage->get('paymentProvider'); + return $this->sharedStorage->get('payment-provider'); } } diff --git a/src/CoreShop/Behat/Context/Ui/Frontend/CheckoutContext.php b/src/CoreShop/Behat/Context/Ui/Frontend/CheckoutContext.php new file mode 100644 index 0000000000..ed5bae127a --- /dev/null +++ b/src/CoreShop/Behat/Context/Ui/Frontend/CheckoutContext.php @@ -0,0 +1,220 @@ +sharedStorage = $sharedStorage; + $this->linkGenerator = $linkGenerator; + $this->customerPage = $customerPage; + $this->addressPage = $addressPage; + $this->shippingPage = $shippingPage; + $this->paymentPage = $paymentPage; + $this->summaryPage = $summaryPage; + $this->thankYouPage = $thankYouPage; + } + + /** + * @When I am at the address checkout step + */ + public function IAmAtTheAddressCheckoutStep() + { + $this->addressPage->open(); + } + + /** + * @When I should be on the address checkout step + */ + public function IShouldBeOnTheAddressCheckoutStep() + { + $this->addressPage->verify(); + } + + /** + * @When /^I use the last (address) as invoice address$/ + */ + public function IUseTheLastAddressAsInvoiceAddress(AddressInterface $address) + { + $this->addressPage->useInvoiceAddress($address); + } + + /** + * @When /^I submit the address step$/ + */ + public function ISubmitTheAddressStep() + { + $this->addressPage->submitStep(); + } + + /** + * @When I am at the customer checkout step + */ + public function IAmAtTheCustomerCheckoutStep() + { + $this->customerPage->open(); + } + + /** + * @When I should be on the customer checkout step + */ + public function IShouldBeOnTheCustomerCheckoutStep() + { + $this->customerPage->verify(); + } + + /** + * @When I am at the shipping checkout step + */ + public function IAmAtTheShippingCheckoutStep() + { + $this->shippingPage->open(); + } + + /** + * @When I should be on the shipping checkout step + */ + public function IShouldBeOnTheShippingCheckoutStep() + { + $this->shippingPage->verify(); + } + + /** + * @When /^I submit the shipping step$/ + */ + public function ISubmitTheShippingStep() + { + $this->shippingPage->submitStep(); + } + + /** + * @When I am at the payment checkout step + */ + public function IAmAtThePaymentCheckoutStep() + { + $this->paymentPage->open(); + } + + /** + * @When I should be on the payment checkout step + */ + public function IShouldBeOnThePaymentCheckoutStep() + { + $this->paymentPage->verify(); + } + + /** + * @When /^I select the (payment provider "[^"]+")$/ + */ + public function ISelectThePaymentProvider(PaymentProviderInterface $provider) + { + $this->paymentPage->selectPaymentProvider($provider); + } + + /** + * @When /^I submit the payment step$/ + */ + public function ISubmitThePaymentStep() + { + $this->paymentPage->submitStep(); + } + + /** + * @When I am at the summary checkout step + */ + public function IAmAtTheSummaryCheckoutStep() + { + $this->summaryPage->open(); + } + + /** + * @When I should be on the summary checkout step + */ + public function IShouldBeOnTheSummaryCheckoutStep() + { + $this->summaryPage->verify(); + } + + /** + * @When I accept the checkout terms of service + */ + public function IAcceptTheTermsOfService() + { + $this->summaryPage->acceptTermsOfService(); + } + + /** + * @When I decline the checkout terms of service + */ + public function IDeclineTheTermsOfService() + { + $this->summaryPage->declineTermsOfService(); + } + + /** + * @When I submit the order + */ + public function ISubmitTheOrder() + { + $this->summaryPage->submitOrder(); + } + + /** + * @When I submit the quote + */ + public function ISubmitTheQuote() + { + $this->summaryPage->submitQuote(); + } + + /** + * @When I should be on the thank you page + */ + public function IShouldBeOnTheThankYouPage() + { + $this->thankYouPage->verify(); + } +} diff --git a/src/CoreShop/Behat/Page/Frontend/AbstractFrontendPage.php b/src/CoreShop/Behat/Page/Frontend/AbstractFrontendPage.php index b9fcad8251..c0dd3449cc 100644 --- a/src/CoreShop/Behat/Page/Frontend/AbstractFrontendPage.php +++ b/src/CoreShop/Behat/Page/Frontend/AbstractFrontendPage.php @@ -14,17 +14,36 @@ namespace CoreShop\Behat\Page\Frontend; +use Behat\Mink\Session; use FriendsOfBehat\PageObjectExtension\Page\SymfonyPage; +use Symfony\Component\Routing\RouterInterface; abstract class AbstractFrontendPage extends SymfonyPage implements FrontendPageInterface { protected static $additionalParameters = ['_locale' => 'en']; + public function __construct(Session $session, $minkParameters, RouterInterface $router) + { + parent::__construct($session, $minkParameters, $router); + } + public function isOpenWithUri(string $uri): bool { return $this->getSession()->getCurrentUrl() !== $uri; } + protected function getUrl(array $urlParameters = []): string + { + $urlParameters = array_merge($urlParameters, $this->getAdditionalParameters()); + + return parent::getUrl($urlParameters); + } + + protected function getAdditionalParameters(): array + { + return []; + } + public function tryToOpenWithUri(string $uri): void { $absoluteUrl = $this->makePathAbsolute($uri); diff --git a/src/CoreShop/Behat/Page/Frontend/Checkout/AddressPage.php b/src/CoreShop/Behat/Page/Frontend/Checkout/AddressPage.php new file mode 100644 index 0000000000..e71ff167c4 --- /dev/null +++ b/src/CoreShop/Behat/Page/Frontend/Checkout/AddressPage.php @@ -0,0 +1,68 @@ +getElement('use_invoice_as_shipping')->click(); + } + + public function useShippingAddress(AddressInterface $shippingAddress): void + { + $this->getElement('shipping_address')->selectOption($shippingAddress->getId()); + } + + public function useInvoiceAddress(AddressInterface $invoiceAddress): void + { + $this->getElement('invoice_address')->selectOption($invoiceAddress->getId()); + } + + public function shippingAddressVisible(): bool + { + return null !== $this->getElement('shipping_address'); + } + + public function submitStep(): void + { + $this->getElement('submit_address_step')->click(); + } + + protected function getAdditionalParameters(): array + { + return [ + 'stepIdentifier' => 'address' + ]; + } + + protected function getDefinedElements(): array + { + return array_merge(parent::getDefinedElements(), [ + 'submit_address_step' => '[data-test-submit-address-step]', + 'use_invoice_as_shipping' => '[data-test-use-invoice-as-shipping]', + 'invoice_address' => '[data-test-invoice-address]', + 'shipping_address' => '[data-test-shipping-address]', + ]); + } +} diff --git a/src/CoreShop/Behat/Page/Frontend/Checkout/AddressPageInterface.php b/src/CoreShop/Behat/Page/Frontend/Checkout/AddressPageInterface.php new file mode 100644 index 0000000000..456fadbaa1 --- /dev/null +++ b/src/CoreShop/Behat/Page/Frontend/Checkout/AddressPageInterface.php @@ -0,0 +1,31 @@ + 'customer' + ]; + } + protected function getDefinedElements(): array + { + return array_merge(parent::getDefinedElements(), [ + + ]); + } +} diff --git a/src/CoreShop/Behat/Page/Frontend/Checkout/CustomerPageInterface.php b/src/CoreShop/Behat/Page/Frontend/Checkout/CustomerPageInterface.php new file mode 100644 index 0000000000..fbc691840c --- /dev/null +++ b/src/CoreShop/Behat/Page/Frontend/Checkout/CustomerPageInterface.php @@ -0,0 +1,23 @@ +getElement('payment_provider')->selectOption($paymentProvider->getId()); + } + + public function submitStep(): void + { + $this->getElement('submit_payment_step')->click(); + } + + protected function getAdditionalParameters(): array + { + return [ + 'stepIdentifier' => 'payment' + ]; + } + + protected function getDefinedElements(): array + { + return array_merge(parent::getDefinedElements(), [ + 'submit_payment_step' => '[data-test-submit-payment-step]', + 'payment_provider' => '[data-test-select-payment-provider]', + ]); + } +} diff --git a/src/CoreShop/Behat/Page/Frontend/Checkout/PaymentPageInterface.php b/src/CoreShop/Behat/Page/Frontend/Checkout/PaymentPageInterface.php new file mode 100644 index 0000000000..e8db6b7c3e --- /dev/null +++ b/src/CoreShop/Behat/Page/Frontend/Checkout/PaymentPageInterface.php @@ -0,0 +1,22 @@ +getElement('submit_shipping_step')->click(); + } + + protected function getAdditionalParameters(): array + { + return [ + 'stepIdentifier' => 'shipping' + ]; + } + + protected function getDefinedElements(): array + { + return array_merge(parent::getDefinedElements(), [ + 'submit_shipping_step' => '[data-test-submit-shipping-step]', + ]); + } +} diff --git a/src/CoreShop/Behat/Page/Frontend/Checkout/ShippingPageInterface.php b/src/CoreShop/Behat/Page/Frontend/Checkout/ShippingPageInterface.php new file mode 100644 index 0000000000..db0f77e0f2 --- /dev/null +++ b/src/CoreShop/Behat/Page/Frontend/Checkout/ShippingPageInterface.php @@ -0,0 +1,22 @@ +getElement('submit_order')->click(); + } + + public function acceptTermsOfService(): void + { + $this->getElement('terms_of_service')->check(); + } + + public function declineTermsOfService(): void + { + $this->getElement('terms_of_service')->uncheck(); + } + + public function submitQuote(): void + { + $this->getElement('submit_quote')->click(); + } + + protected function getAdditionalParameters(): array + { + return [ + 'stepIdentifier' => 'summary' + ]; + } + + protected function getDefinedElements(): array + { + return array_merge(parent::getDefinedElements(), [ + 'submit_order' => '[data-test-submit-order]', + 'submit_quote' => '[data-test-submit-quote]', + 'terms_of_service' => '[data-test-accept-terms]', + ]); + } +} diff --git a/src/CoreShop/Behat/Page/Frontend/Checkout/SummaryPageInterface.php b/src/CoreShop/Behat/Page/Frontend/Checkout/SummaryPageInterface.php new file mode 100644 index 0000000000..d7383688eb --- /dev/null +++ b/src/CoreShop/Behat/Page/Frontend/Checkout/SummaryPageInterface.php @@ -0,0 +1,28 @@ +
    - {{ form_row(form.invoiceAddress) }} + {{ form_row(form.invoiceAddress, coreshop_test_form_attribute('invoice-address')) }}
    {% if hasShippableItems %}
    - {{ form_row(form.shippingAddress) }} + {{ form_row(form.shippingAddress, coreshop_test_form_attribute('shipping-address')) }}
    {% endif %} @@ -34,7 +34,7 @@ {% if hasShippableItems %}
    - {{ form_row(form.useInvoiceAsShipping) }} + {{ form_row(form.useInvoiceAsShipping, coreshop_test_form_attribute('use-invoice-as-shipping')) }}
    {% endif %} @@ -93,7 +93,7 @@ {% endif %}
    -
    diff --git a/src/CoreShop/Bundle/FrontendBundle/Resources/views/Checkout/steps/payment.html.twig b/src/CoreShop/Bundle/FrontendBundle/Resources/views/Checkout/steps/payment.html.twig index 1cbb348e1a..7d9d56ba2b 100644 --- a/src/CoreShop/Bundle/FrontendBundle/Resources/views/Checkout/steps/payment.html.twig +++ b/src/CoreShop/Bundle/FrontendBundle/Resources/views/Checkout/steps/payment.html.twig @@ -15,7 +15,7 @@ {{ form_start(form, {'attr': {'novalidate': 'novalidate'}}) }} {{ form_errors(form) }} - {{ form_row(form.paymentProvider) }} + {{ form_row(form.paymentProvider, coreshop_test_form_attribute('select-payment-provider')) }}
    {% if form.paymentSettings is defined %} @@ -41,7 +41,7 @@
    {% endif %}
    -
    @@ -50,4 +50,4 @@ {{ form_end(form) }} -{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/src/CoreShop/Bundle/FrontendBundle/Resources/views/Checkout/steps/shipping.html.twig b/src/CoreShop/Bundle/FrontendBundle/Resources/views/Checkout/steps/shipping.html.twig index fb5a8766e1..3845c79acd 100644 --- a/src/CoreShop/Bundle/FrontendBundle/Resources/views/Checkout/steps/shipping.html.twig +++ b/src/CoreShop/Bundle/FrontendBundle/Resources/views/Checkout/steps/shipping.html.twig @@ -14,8 +14,9 @@ {{ form_start(form, {'attr': {'novalidate': 'novalidate'}}) }} {{ form_errors(form) }} - {{ form_widget(form.carrier) }} - {{ form_row(form.comment) }} + {{ form_widget(form.carrier, coreshop_test_form_attribute('carrier')) }} + {{ form_row(form.comment, coreshop_test_form_attribute('shipping-comment')) }} +
    {% set previousStep = coreshop_checkout_steps_get_previous() %} {% if previousStep is not null %} @@ -27,7 +28,7 @@
    {% endif %}
    -
    @@ -35,4 +36,4 @@ {{ form_end(form) }} -{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/src/CoreShop/Bundle/FrontendBundle/Resources/views/Checkout/steps/summary.html.twig b/src/CoreShop/Bundle/FrontendBundle/Resources/views/Checkout/steps/summary.html.twig index 9f3c37da22..a572423812 100644 --- a/src/CoreShop/Bundle/FrontendBundle/Resources/views/Checkout/steps/summary.html.twig +++ b/src/CoreShop/Bundle/FrontendBundle/Resources/views/Checkout/steps/summary.html.twig @@ -16,14 +16,29 @@ {% endif %} - {{ form_row(form.acceptTerms) }} + {{ form_row(form.acceptTerms, coreshop_test_form_attribute('accept-terms')) }}
    - +
    - +
    diff --git a/src/CoreShop/Component/Payment/Model/PaymentProviderInterface.php b/src/CoreShop/Component/Payment/Model/PaymentProviderInterface.php index 86dbddb3db..0341cf4e2e 100644 --- a/src/CoreShop/Component/Payment/Model/PaymentProviderInterface.php +++ b/src/CoreShop/Component/Payment/Model/PaymentProviderInterface.php @@ -14,12 +14,17 @@ namespace CoreShop\Component\Payment\Model; +use CoreShop\Component\Resource\Model\ResourceInterface; use CoreShop\Component\Resource\Model\TimestampableInterface; use CoreShop\Component\Resource\Model\ToggleableInterface; use CoreShop\Component\Resource\Model\TranslatableInterface; use Pimcore\Model\Asset; -interface PaymentProviderInterface extends ToggleableInterface, TranslatableInterface, TimestampableInterface +interface PaymentProviderInterface extends + ResourceInterface, + ToggleableInterface, + TranslatableInterface, + TimestampableInterface { /** * @return mixed From 9012da99d521e446aa3b9fa58df569873c5b80bf Mon Sep 17 00:00:00 2001 From: Dominik Pfaffenbauer Date: Fri, 10 Apr 2020 14:16:27 +0200 Subject: [PATCH 09/12] [3.0] add prevent empty checkout tests --- .../checkout/prevent_empty_checkout.feature | 24 +++++++++++++++++++ .../Context/Ui/Frontend/CheckoutContext.php | 19 +++++++++------ 2 files changed, 36 insertions(+), 7 deletions(-) create mode 100644 features/ui/checkout/prevent_empty_checkout.feature diff --git a/features/ui/checkout/prevent_empty_checkout.feature b/features/ui/checkout/prevent_empty_checkout.feature new file mode 100644 index 0000000000..dd97e92d29 --- /dev/null +++ b/features/ui/checkout/prevent_empty_checkout.feature @@ -0,0 +1,24 @@ +@ui @checkout +Feature: Ability to complete the checkout + + Background: + Given the site operates on a store in "Austria" + And the store "Austria" is the default store + And I am a logged in customer + + Scenario: Try opening address checkout step + Given I try to open the address checkout step + Then I should be on the cart summary page + + Scenario: Try opening shipping checkout step + Given I try to open the shipping checkout step + Then I should be on the cart summary page + + Scenario: Try opening payment checkout step + Given I try to open the payment checkout step + Then I should be on the cart summary page + + Scenario: Try opening payment checkout step + Given I try to open the summary checkout step + Then I should be on the cart summary page + diff --git a/src/CoreShop/Behat/Context/Ui/Frontend/CheckoutContext.php b/src/CoreShop/Behat/Context/Ui/Frontend/CheckoutContext.php index ed5bae127a..6312aa9ee7 100644 --- a/src/CoreShop/Behat/Context/Ui/Frontend/CheckoutContext.php +++ b/src/CoreShop/Behat/Context/Ui/Frontend/CheckoutContext.php @@ -60,10 +60,11 @@ public function __construct( /** * @When I am at the address checkout step + * @When I try to open the address checkout step */ public function IAmAtTheAddressCheckoutStep() { - $this->addressPage->open(); + $this->addressPage->tryToOpen(); } /** @@ -92,10 +93,11 @@ public function ISubmitTheAddressStep() /** * @When I am at the customer checkout step + * @When I try to open the customer checkout step */ public function IAmAtTheCustomerCheckoutStep() { - $this->customerPage->open(); + $this->customerPage->tryToOpen(); } /** @@ -103,15 +105,16 @@ public function IAmAtTheCustomerCheckoutStep() */ public function IShouldBeOnTheCustomerCheckoutStep() { - $this->customerPage->verify(); + $this->customerPage->tryToOpen(); } /** * @When I am at the shipping checkout step + * @When I try to open the shipping checkout step */ public function IAmAtTheShippingCheckoutStep() { - $this->shippingPage->open(); + $this->shippingPage->tryToOpen(); } /** @@ -119,7 +122,7 @@ public function IAmAtTheShippingCheckoutStep() */ public function IShouldBeOnTheShippingCheckoutStep() { - $this->shippingPage->verify(); + $this->shippingPage->tryToOpen(); } /** @@ -132,10 +135,11 @@ public function ISubmitTheShippingStep() /** * @When I am at the payment checkout step + * @When I try to open the payment checkout step */ public function IAmAtThePaymentCheckoutStep() { - $this->paymentPage->open(); + $this->paymentPage->tryToOpen(); } /** @@ -164,10 +168,11 @@ public function ISubmitThePaymentStep() /** * @When I am at the summary checkout step + * @When I try to open the summary checkout step */ public function IAmAtTheSummaryCheckoutStep() { - $this->summaryPage->open(); + $this->summaryPage->tryToOpen(); } /** From 5be7094279c4c60819919cd8607c25409f0d4179 Mon Sep 17 00:00:00 2001 From: Dominik Pfaffenbauer Date: Fri, 10 Apr 2020 15:37:58 +0200 Subject: [PATCH 10/12] [3.0] revise shipping checkout form and step and add test for disabled carrier --- .../shipping/prevent_disabled_carrier.feature | 22 ++++ .../Behat/Context/Setup/ShippingContext.php | 22 +++- .../Context/Ui/Frontend/CheckoutContext.php | 12 +- .../Page/Frontend/Checkout/ShippingPage.php | 15 ++- .../Checkout/ShippingPageInterface.php | 2 + .../Resources/config/suites/ui/checkout.yml | 1 + .../Checkout/Step/ShippingCheckoutStep.php | 29 +---- .../Form/Type/Checkout/CarrierChoiceType.php | 120 ++++++++++++++++++ .../Form/Type/Checkout/CarrierType.php | 71 +---------- .../Resources/config/services/checkout.yml | 13 +- .../views/Checkout/steps/shipping.html.twig | 32 ++++- .../Form/Type/CarrierChoiceType.php | 2 + 12 files changed, 238 insertions(+), 103 deletions(-) create mode 100644 features/ui/checkout/shipping/prevent_disabled_carrier.feature create mode 100644 src/CoreShop/Bundle/CoreBundle/Form/Type/Checkout/CarrierChoiceType.php diff --git a/features/ui/checkout/shipping/prevent_disabled_carrier.feature b/features/ui/checkout/shipping/prevent_disabled_carrier.feature new file mode 100644 index 0000000000..e884747754 --- /dev/null +++ b/features/ui/checkout/shipping/prevent_disabled_carrier.feature @@ -0,0 +1,22 @@ +@ui @checkout +Feature: Ability to complete the checkout + + Background: + Given the site operates on a store in "Austria" + And the store "Austria" is the default store + And the site has a product "TShirt" priced at 10000 + And the product is active and published and available for store "Austria" + And I am a logged in customer + And the customer has an address with country "Austria", "4600", "Wels", "Freiung", "9-11/N3" + And the site has a carrier "Post" and ships for 10 in currency "EUR" + And the site has a carrier "DHL" and ships for 15 in currency "EUR" + And the carrier "DHL" is disabled for store "Austria" + Then I add this product to the cart + + Scenario: I proceed to the checkout + Given I am at the address checkout step + Then I should be on the address checkout step + And I use the last address as invoice address + And I submit the address step + Then I should be on the shipping checkout step + And I should not see carrier "DHL" diff --git a/src/CoreShop/Behat/Context/Setup/ShippingContext.php b/src/CoreShop/Behat/Context/Setup/ShippingContext.php index c2a471b54b..2a3d872c24 100644 --- a/src/CoreShop/Behat/Context/Setup/ShippingContext.php +++ b/src/CoreShop/Behat/Context/Setup/ShippingContext.php @@ -44,7 +44,6 @@ use CoreShop\Component\Core\Model\CustomerInterface; use CoreShop\Component\Core\Model\ProductInterface; use CoreShop\Component\Core\Model\StoreInterface; -use CoreShop\Component\Core\Repository\CarrierRepositoryInterface; use CoreShop\Component\Customer\Model\CustomerGroupInterface; use CoreShop\Component\Resource\Factory\FactoryInterface; use CoreShop\Component\Rule\Model\ActionInterface; @@ -134,6 +133,27 @@ public function theSiteHasACarrierAndShipsForX($name, int $price, CurrencyInterf $this->sharedStorage->set('shipping-rule', $rule); } + /** + * @Given /^the (carrier "[^"]+") is disabled for (store "[^"]+")$/ + * @Given /^the (carrier) is disabled for (store "[^"]+")$/ + */ + public function theCarrierIsDisabledForStore(CarrierInterface $carrier, StoreInterface $store) + { + $carrier->removeStore($store); + + $this->saveCarrier($carrier); + } + /** + * @Given /^the (carrier "[^"]+") is enabled for (store "[^"]+")$/ + * @Given /^the (carrier) is enabled for (store "[^"]+")$/ + */ + public function theCarrierIsEnabledForStore(CarrierInterface $carrier, StoreInterface $store) + { + $carrier->addStore($store); + + $this->saveCarrier($carrier); + } + /** * @Given /^the (carrier "[^"]+") has (tax rule group "[^"]+")$/ * @Given /^the (carrier) has the (tax rule group "[^"]+")$/ diff --git a/src/CoreShop/Behat/Context/Ui/Frontend/CheckoutContext.php b/src/CoreShop/Behat/Context/Ui/Frontend/CheckoutContext.php index 6312aa9ee7..22da227997 100644 --- a/src/CoreShop/Behat/Context/Ui/Frontend/CheckoutContext.php +++ b/src/CoreShop/Behat/Context/Ui/Frontend/CheckoutContext.php @@ -23,8 +23,10 @@ use CoreShop\Behat\Page\Frontend\Checkout\ThankYouPageInterface; use CoreShop\Behat\Service\SharedStorageInterface; use CoreShop\Component\Address\Model\AddressInterface; +use CoreShop\Component\Core\Model\CarrierInterface; use CoreShop\Component\Core\Model\PaymentProviderInterface; use CoreShop\Component\Pimcore\Routing\LinkGeneratorInterface; +use Webmozart\Assert\Assert; final class CheckoutContext implements Context { @@ -122,7 +124,15 @@ public function IAmAtTheShippingCheckoutStep() */ public function IShouldBeOnTheShippingCheckoutStep() { - $this->shippingPage->tryToOpen(); + $this->shippingPage->verify(); + } + + /** + * @When /^I should not see carrier "([^"]+)"$/ + */ + public function IShouldNotSeeCarrier($carrier) + { + Assert::false(in_array($carrier, $this->shippingPage->getCarriers(), true)); } /** diff --git a/src/CoreShop/Behat/Page/Frontend/Checkout/ShippingPage.php b/src/CoreShop/Behat/Page/Frontend/Checkout/ShippingPage.php index 1c40cee143..3dc03c41c4 100644 --- a/src/CoreShop/Behat/Page/Frontend/Checkout/ShippingPage.php +++ b/src/CoreShop/Behat/Page/Frontend/Checkout/ShippingPage.php @@ -14,9 +14,7 @@ namespace CoreShop\Behat\Page\Frontend\Checkout; -use Behat\Mink\Session; use CoreShop\Behat\Page\Frontend\AbstractFrontendPage; -use Symfony\Component\Routing\RouterInterface; class ShippingPage extends AbstractFrontendPage implements ShippingPageInterface { @@ -30,6 +28,19 @@ public function submitStep(): void $this->getElement('submit_shipping_step')->click(); } + public function getCarriers(): array + { + $inputs = $this->getSession()->getPage()->findAll('css', '[data-test-carrier-label]'); + + $carriers = []; + + foreach ($inputs as $input) { + $carriers[] = trim($input->getText()); + } + + return $carriers; + } + protected function getAdditionalParameters(): array { return [ diff --git a/src/CoreShop/Behat/Page/Frontend/Checkout/ShippingPageInterface.php b/src/CoreShop/Behat/Page/Frontend/Checkout/ShippingPageInterface.php index db0f77e0f2..eb181ce643 100644 --- a/src/CoreShop/Behat/Page/Frontend/Checkout/ShippingPageInterface.php +++ b/src/CoreShop/Behat/Page/Frontend/Checkout/ShippingPageInterface.php @@ -19,4 +19,6 @@ interface ShippingPageInterface extends FrontendPageInterface { public function submitStep(): void; + + public function getCarriers(): array; } diff --git a/src/CoreShop/Behat/Resources/config/suites/ui/checkout.yml b/src/CoreShop/Behat/Resources/config/suites/ui/checkout.yml index 315a5e2fe7..4149680777 100644 --- a/src/CoreShop/Behat/Resources/config/suites/ui/checkout.yml +++ b/src/CoreShop/Behat/Resources/config/suites/ui/checkout.yml @@ -22,6 +22,7 @@ default: - coreshop.behat.context.transform.customer - coreshop.behat.context.transform.address - coreshop.behat.context.transform.payment + - coreshop.behat.context.transform.shipping - coreshop.behat.context.setup.store - coreshop.behat.context.setup.product diff --git a/src/CoreShop/Bundle/CoreBundle/Checkout/Step/ShippingCheckoutStep.php b/src/CoreShop/Bundle/CoreBundle/Checkout/Step/ShippingCheckoutStep.php index 03916e8573..ebd39e163c 100644 --- a/src/CoreShop/Bundle/CoreBundle/Checkout/Step/ShippingCheckoutStep.php +++ b/src/CoreShop/Bundle/CoreBundle/Checkout/Step/ShippingCheckoutStep.php @@ -32,18 +32,15 @@ class ShippingCheckoutStep implements CheckoutStepInterface, OptionalCheckoutStepInterface, ValidationCheckoutStepInterface { - private $carriersResolver; private $shippableCarrierValidator; private $formFactory; private $cartManager; public function __construct( - CarriersResolverInterface $carriersResolver, ShippableCarrierValidatorInterface $shippableCarrierValidator, FormFactoryInterface $formFactory, CartManagerInterface $cartManager ) { - $this->carriersResolver = $carriersResolver; $this->shippableCarrierValidator = $shippableCarrierValidator; $this->formFactory = $formFactory; $this->cartManager = $cartManager; @@ -96,7 +93,7 @@ public function validate(OrderInterface $cart): bool */ public function commitStep(OrderInterface $cart, Request $request): bool { - $form = $this->createForm($request, $this->getCarriers($cart), $cart); + $form = $this->createForm($request, $cart); if ($form->isSubmitted()) { if ($form->isValid()) { @@ -118,34 +115,14 @@ public function commitStep(OrderInterface $cart, Request $request): bool */ public function prepareStep(OrderInterface $cart, Request $request): array { - //Get Carriers - $carriers = $this->getCarriers($cart); - return [ - 'carriers' => $carriers, - 'form' => $this->createForm($request, $carriers, $cart)->createView(), + 'form' => $this->createForm($request, $cart)->createView(), ]; } - /** - * @param OrderInterface $cart - * - * @return \CoreShop\Component\Shipping\Model\CarrierInterface[] - */ - private function getCarriers(OrderInterface $cart): array - { - /** - * @var \CoreShop\Component\Core\Model\OrderInterface $cart - */ - Assert::isInstanceOf($cart, \CoreShop\Component\Core\Model\OrderInterface::class); - - return $this->carriersResolver->resolveCarriers($cart, $cart->getShippingAddress()); - } - - private function createForm(Request $request, array$carriers, OrderInterface $cart): FormInterface + private function createForm(Request $request, OrderInterface $cart): FormInterface { $form = $this->formFactory->createNamed('', CarrierType::class, $cart, [ - 'carriers' => $carriers, 'cart' => $cart, ]); diff --git a/src/CoreShop/Bundle/CoreBundle/Form/Type/Checkout/CarrierChoiceType.php b/src/CoreShop/Bundle/CoreBundle/Form/Type/Checkout/CarrierChoiceType.php new file mode 100644 index 0000000000..ed17626145 --- /dev/null +++ b/src/CoreShop/Bundle/CoreBundle/Form/Type/Checkout/CarrierChoiceType.php @@ -0,0 +1,120 @@ +repository = $repository; + $this->carriersResolver = $carriersResolver; + $this->taxedShippingCalculator = $taxedShippingCalculator; + } + + /** + * {@inheritdoc} + */ + public function configureOptions(OptionsResolver $resolver): void + { + $resolver + ->setDefaults([ + 'choices' => function (Options $options) { + $cart = $options['cart']; + if ($cart instanceof OrderInterface) { + return $this->carriersResolver->resolveCarriers($cart, $cart->getShippingAddress()); + } + + return $this->repository->findAll(); + }, + 'choice_value' => 'id', + 'choice_label' => 'title', + 'choice_translation_domain' => false, + ]) + ->setDefined([ + 'cart', + ]) + ->setDefault('show_carrier_price', true) + ->setDefault('show_carrier_price_with_tax', true) + ->setAllowedTypes('cart', OrderInterface::class); + } + + /** + * {@inheritdoc} + */ + public function buildView(FormView $view, FormInterface $form, array $options) + { + $prices = []; + $cart = $options['cart']; + + foreach ($view->vars['choices'] as $choice) { + $carrier = $choice->data; + + if (!$carrier instanceof CarrierInterface) { + continue; + } + + $price = $this->taxedShippingCalculator->getPrice( + $carrier, + $cart, + $cart->getShippingAddress(), + $options['show_carrier_price_with_tax'] + ); + + $prices[$choice->value] = $price; + } + + $view->vars['prices'] = $prices; + $view->vars['show_carrier_price'] = $options['show_carrier_price']; + } + + /** + * {@inheritdoc} + */ + public function getParent(): string + { + return ChoiceType::class; + } + + /** + * {@inheritdoc} + */ + public function getBlockPrefix(): string + { + return 'coreshop_checkout_carrier_choice'; + } +} diff --git a/src/CoreShop/Bundle/CoreBundle/Form/Type/Checkout/CarrierType.php b/src/CoreShop/Bundle/CoreBundle/Form/Type/Checkout/CarrierType.php index f50c7f875d..d4ac1eae6e 100644 --- a/src/CoreShop/Bundle/CoreBundle/Form/Type/Checkout/CarrierType.php +++ b/src/CoreShop/Bundle/CoreBundle/Form/Type/Checkout/CarrierType.php @@ -15,13 +15,7 @@ namespace CoreShop\Bundle\CoreBundle\Form\Type\Checkout; use CoreShop\Bundle\ResourceBundle\Form\Type\AbstractResourceType; -use CoreShop\Bundle\ShippingBundle\Form\Type\CarrierChoiceType; -use CoreShop\Component\Core\Context\ShopperContextInterface; -use CoreShop\Component\Core\Model\CarrierInterface; use CoreShop\Component\Core\Model\OrderInterface; -use CoreShop\Component\Currency\Converter\CurrencyConverterInterface; -use CoreShop\Component\Currency\Formatter\MoneyFormatterInterface; -use CoreShop\Component\Shipping\Calculator\TaxedShippingCalculatorInterface; use Symfony\Component\Form\Extension\Core\Type\TextareaType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\OptionsResolver\OptionsResolver; @@ -30,62 +24,17 @@ final class CarrierType extends AbstractResourceType { - private $taxedShippingCalculator; - private $currencyConverter; - private $moneyFormatter; - private $shopperContext; - - public function __construct( - $dataClass, - array $validationGroups, - ShopperContextInterface $shopperContext, - TaxedShippingCalculatorInterface $taxedShippingCalculator, - MoneyFormatterInterface $moneyFormatter, - CurrencyConverterInterface $currencyConverter - ) { - parent::__construct($dataClass, $validationGroups); - - $this->taxedShippingCalculator = $taxedShippingCalculator; - $this->shopperContext = $shopperContext; - $this->moneyFormatter = $moneyFormatter; - $this->currencyConverter = $currencyConverter; - } - /** * {@inheritdoc} */ public function buildForm(FormBuilderInterface $builder, array $options): void { - $cart = $options['cart']; - $builder ->add('carrier', CarrierChoiceType::class, [ 'constraints' => [new Valid(), new NotBlank(['groups' => $this->validationGroups])], 'expanded' => true, 'label' => 'coreshop.ui.carrier', - 'choices' => $options['carriers'], - 'choice_value' => function ($carrier) { - if ($carrier instanceof CarrierInterface) { - return $carrier->getId(); - } - - return null; - }, - 'choice_label' => function ($carrier) use ($cart, $options) { - if (!$carrier instanceof CarrierInterface) { - return ''; - } - - if ($options['show_carrier_price'] === false) { - return $carrier->getTitle(); - } - - $carrierPrice = $this->taxedShippingCalculator->getPrice($carrier, $cart, $cart->getShippingAddress(), $options['show_carrier_price_with_tax']); - $amount = $this->currencyConverter->convert($carrierPrice, $this->shopperContext->getStore()->getCurrency()->getIsoCode(), $cart->getCurrency()->getIsoCode()); - $formattedAmount = $this->moneyFormatter->format($amount, $this->shopperContext->getCurrency()->getIsoCode(), $this->shopperContext->getLocaleCode()); - - return sprintf('%s %s', $carrier->getTitle(), $formattedAmount); - }, + 'cart' => $options['cart'], ]) ->add('comment', TextareaType::class, [ 'required' => false, @@ -100,22 +49,8 @@ public function configureOptions(OptionsResolver $resolver): void { parent::configureOptions($resolver); - $resolver->setDefault('carriers', null); - $resolver->setDefault('cart', null); - $resolver->setDefault('show_carrier_price', true); - $resolver->setDefault('show_carrier_price_with_tax', true); - $resolver->setAllowedTypes('cart', [OrderInterface::class]); - $resolver->setAllowedTypes('carriers', 'array') - ->setAllowedValues('carriers', function (array $carriers) { - // we already know it is an array as types are validated first - foreach ($carriers as $carrier) { - if (!$carrier instanceof CarrierInterface) { - return false; - } - } - - return true; - }); + $resolver->setDefined('cart'); + $resolver->setAllowedTypes('cart', OrderInterface::class); } /** diff --git a/src/CoreShop/Bundle/CoreBundle/Resources/config/services/checkout.yml b/src/CoreShop/Bundle/CoreBundle/Resources/config/services/checkout.yml index e289916c78..c32a6d2e11 100644 --- a/src/CoreShop/Bundle/CoreBundle/Resources/config/services/checkout.yml +++ b/src/CoreShop/Bundle/CoreBundle/Resources/config/services/checkout.yml @@ -32,7 +32,6 @@ services: CoreShop\Bundle\CoreBundle\Checkout\Step\ShippingCheckoutStep: arguments: - - '@CoreShop\Component\Shipping\Resolver\CarriersResolverInterface' - '@coreshop.shipping.carrier.validator' - '@form.factory' - '@CoreShop\Component\Order\Manager\CartManagerInterface' @@ -76,9 +75,15 @@ services: arguments: - '%coreshop.model.order.class%' - '%coreshop.form.type.checkout.carrier.validation_groups%' - - '@CoreShop\Component\Core\Context\ShopperContextInterface' + tags: + - {name: form.type} + + CoreShop\Bundle\CoreBundle\Form\Type\Checkout\CarrierChoiceType: + arguments: + - '%coreshop.model.order.class%' + - '%coreshop.form.type.checkout.carrier.validation_groups%' + - '@coreshop.repository.carrier' + - '@CoreShop\Component\Shipping\Resolver\CarriersResolverInterface' - '@CoreShop\Component\Shipping\Calculator\TaxedShippingCalculatorInterface' - - '@CoreShop\Component\Currency\Formatter\MoneyFormatterInterface' - - '@CoreShop\Component\Currency\Converter\CurrencyConverterInterface' tags: - {name: form.type} diff --git a/src/CoreShop/Bundle/FrontendBundle/Resources/views/Checkout/steps/shipping.html.twig b/src/CoreShop/Bundle/FrontendBundle/Resources/views/Checkout/steps/shipping.html.twig index 3845c79acd..26e00a5eb0 100644 --- a/src/CoreShop/Bundle/FrontendBundle/Resources/views/Checkout/steps/shipping.html.twig +++ b/src/CoreShop/Bundle/FrontendBundle/Resources/views/Checkout/steps/shipping.html.twig @@ -1,4 +1,5 @@ {% extends '@CoreShopFrontend/Checkout/layout.html.twig' %} +{% import '@CoreShopFrontend/Common/Macro/currency.html.twig' as currency %} {% form_theme form 'bootstrap_4_layout.html.twig' %} {% block checkout_title %} @@ -14,7 +15,36 @@ {{ form_start(form, {'attr': {'novalidate': 'novalidate'}}) }} {{ form_errors(form) }} - {{ form_widget(form.carrier, coreshop_test_form_attribute('carrier')) }} + {% set show_carrier_price = form.carrier.vars.show_carrier_price %} + + {% for key, carrier_form in form.carrier %} + {% set carrier = form.carrier.vars.choices[key].data %} + {% set price = form.carrier.vars.prices[carrier_form.vars.value] %} + +
    +
    +
    +
    + {{ form_widget(carrier_form, coreshop_test_form_attribute('carrier-select')|coreshop_merge_recursive({'label': false})) }} +
    +
    + + {{ carrier.title }} + + {% if show_carrier_price %} + {{ currency.convertAndFormat(price) }} + {% endif %} +
    +
    +
    + {% if carrier.description %} +
    + {{ carrier.description }} +
    + {% endif %} +
    + {% endfor %} + {{ form_row(form.comment, coreshop_test_form_attribute('shipping-comment')) }}
    diff --git a/src/CoreShop/Bundle/ShippingBundle/Form/Type/CarrierChoiceType.php b/src/CoreShop/Bundle/ShippingBundle/Form/Type/CarrierChoiceType.php index ec54a30f67..afb6749926 100644 --- a/src/CoreShop/Bundle/ShippingBundle/Form/Type/CarrierChoiceType.php +++ b/src/CoreShop/Bundle/ShippingBundle/Form/Type/CarrierChoiceType.php @@ -74,6 +74,8 @@ public function buildView(FormView $view, FormInterface $form, array $options): ]); } + + /** * {@inheritdoc} */ From ad00338cdfa85b6949d6cc3879a3a478f76179aa Mon Sep 17 00:00:00 2001 From: Dominik Pfaffenbauer Date: Fri, 10 Apr 2020 15:49:25 +0200 Subject: [PATCH 11/12] [3.0] add missing function --- .../Behat/Page/Frontend/Checkout/PaymentPageInterface.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/CoreShop/Behat/Page/Frontend/Checkout/PaymentPageInterface.php b/src/CoreShop/Behat/Page/Frontend/Checkout/PaymentPageInterface.php index e8db6b7c3e..8b83a3e30c 100644 --- a/src/CoreShop/Behat/Page/Frontend/Checkout/PaymentPageInterface.php +++ b/src/CoreShop/Behat/Page/Frontend/Checkout/PaymentPageInterface.php @@ -15,8 +15,11 @@ namespace CoreShop\Behat\Page\Frontend\Checkout; use CoreShop\Behat\Page\Frontend\FrontendPageInterface; +use CoreShop\Component\Core\Model\PaymentProviderInterface; interface PaymentPageInterface extends FrontendPageInterface { public function submitStep(): void; + + public function selectPaymentProvider(PaymentProviderInterface $paymentProvider); } From a0a8c8c547e9822866e2312289441f19d266653f Mon Sep 17 00:00:00 2001 From: Dominik Pfaffenbauer Date: Tue, 14 Apr 2020 15:42:40 +0200 Subject: [PATCH 12/12] [3.0] fix tests --- .../Component/Core/Order/Processor/CartItemsProcessor.php | 3 +-- src/CoreShop/Component/Order/Model/Order.php | 6 ++++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/CoreShop/Component/Core/Order/Processor/CartItemsProcessor.php b/src/CoreShop/Component/Core/Order/Processor/CartItemsProcessor.php index 8dbb3f6fc3..2574f16115 100644 --- a/src/CoreShop/Component/Core/Order/Processor/CartItemsProcessor.php +++ b/src/CoreShop/Component/Core/Order/Processor/CartItemsProcessor.php @@ -117,7 +117,6 @@ public function process(OrderInterface $cart): void $cart->setSubtotal($subtotalGross, true); $cart->setSubtotal($subtotalNet, false); - $cart->setTotal($cart->getSubtotal(false) + $cart->getAdjustmentsTotal(null, false), false); - $cart->setTotal($cart->getSubtotal(true) + $cart->getAdjustmentsTotal(null, true), true); + $cart->recalculateAdjustmentsTotal(); } } diff --git a/src/CoreShop/Component/Order/Model/Order.php b/src/CoreShop/Component/Order/Model/Order.php index 0870811a82..08c9510e76 100644 --- a/src/CoreShop/Component/Order/Model/Order.php +++ b/src/CoreShop/Component/Order/Model/Order.php @@ -731,6 +731,8 @@ public function setBackendCreated($backendCreated) */ protected function recalculateBaseAfterAdjustmentChange() { + $this->setBaseTotal($this->getBaseSubtotal(true) + $this->getBaseAdjustmentsTotal(null, true), true); + $this->setBaseTotal($this->getBaseSubtotal(false) + $this->getBaseAdjustmentsTotal(null, false), false); } /** @@ -738,7 +740,7 @@ protected function recalculateBaseAfterAdjustmentChange() */ protected function recalculateAfterAdjustmentChange() { - $this->setTotal($this->getTotal(true) + $this->getAdjustmentsTotal(null, true), true); - $this->setTotal($this->getTotal(false) + $this->getAdjustmentsTotal(null, false), false); + $this->setTotal($this->getSubtotal(true) + $this->getAdjustmentsTotal(null, true), true); + $this->setTotal($this->getSubtotal(false) + $this->getAdjustmentsTotal(null, false), false); } }