- {% for optionValue in variant.optionValues %}
-
diff --git a/src/Resources/views/Admin/Product/Tab/_bundle.html.twig b/src/Resources/views/Admin/Product/Tab/_bundle.html.twig
index 586e8568..aa724a8e 100644
--- a/src/Resources/views/Admin/Product/Tab/_bundle.html.twig
+++ b/src/Resources/views/Admin/Product/Tab/_bundle.html.twig
@@ -3,6 +3,10 @@
{{ form_row(form.productBundle.isPackedProduct) }}
+ {{ form_help(form.productBundle.isPackedProduct, {
+ 'help': 'bitbag_sylius_product_bundle.ui.is_packed_help'|trans,
+ 'help_attr': {'class':'ui info message'}
+ }) }}
{{ form_row(form.productBundle.productBundleItems) }}
{{ sonata_block_render_event('sylius.admin.product.' ~ action ~ '.tab_bundle', {'form': form }) }}
diff --git a/src/Resources/views/Admin/Product/Update/_toolbar.html.twig b/src/Resources/views/Admin/Product/Update/_toolbar.html.twig
new file mode 100644
index 00000000..fbc86335
--- /dev/null
+++ b/src/Resources/views/Admin/Product/Update/_toolbar.html.twig
@@ -0,0 +1,7 @@
+
+ {% if not product.bundle %}
+ {% set menu = knp_menu_get('sylius.admin.product.update', [], {'product': product}) %}
+ {{ knp_menu_render(menu, {'template': '@SyliusUi/Menu/top.html.twig'}) }}
+ {% endif %}
+ {% include '@SyliusAdmin/Product/_showInShopButton.html.twig' %}
+
diff --git a/src/Resources/views/Admin/Product/show.html.twig b/src/Resources/views/Admin/Product/show.html.twig
new file mode 100644
index 00000000..aeb97dc3
--- /dev/null
+++ b/src/Resources/views/Admin/Product/show.html.twig
@@ -0,0 +1,54 @@
+{% extends '@SyliusAdmin/layout.html.twig' %}
+
+{% block title %}{{ 'sylius.ui.show_product'|trans }} | {{ product.name }}{% endblock %}
+
+{% block content %}
+ {% if product.variants|length == 1 %}
+ {% include "@SyliusAdmin/Product/Show/_simpleProduct.html.twig" %}
+ {% else %}
+ {% include "@SyliusAdmin/Product/Show/_configurableProduct.html.twig" %}
+ {% endif %}
+
+ {% set bundles = bitbag_get_bundles_containing_product(product) %}
+ {% if bundles|length > 0 %}
+
+
+
+ {% for bundle in bundles %}
+
+ {% endfor %}
+
+ {% endif %}
+
+ {% if product.isBundle %}
+ {% set bundledProducts = bitbag_get_products_from_bundle(product) %}
+
+
+
+ {% for bundledProduct in bundledProducts %}
+ {% set variant = bundledProduct.productVariant %}
+ {% set product = variant.product %}
+
+ {% endfor %}
+
+ {% endif %}
+{% endblock %}
diff --git a/tests/Application/templates/bundles/SyliusAdminBundle/_scripts.html.twig b/src/Resources/views/Admin/_scripts.html.twig
similarity index 59%
rename from tests/Application/templates/bundles/SyliusAdminBundle/_scripts.html.twig
rename to src/Resources/views/Admin/_scripts.html.twig
index 54be86fa..ba1e4025 100644
--- a/tests/Application/templates/bundles/SyliusAdminBundle/_scripts.html.twig
+++ b/src/Resources/views/Admin/_scripts.html.twig
@@ -1,2 +1 @@
-{{ encore_entry_script_tags('admin-entry', null, 'admin') }}
{{ encore_entry_script_tags('bitbag-productBundle-admin', null, 'product_bundle_admin') }}
diff --git a/tests/Application/templates/bundles/SyliusAdminBundle/_styles.html.twig b/src/Resources/views/Admin/_styles.html.twig
similarity index 60%
rename from tests/Application/templates/bundles/SyliusAdminBundle/_styles.html.twig
rename to src/Resources/views/Admin/_styles.html.twig
index d87343da..66909a90 100644
--- a/tests/Application/templates/bundles/SyliusAdminBundle/_styles.html.twig
+++ b/src/Resources/views/Admin/_styles.html.twig
@@ -1,2 +1 @@
-{{ encore_entry_link_tags('admin-entry', null, 'admin') }}
{{ encore_entry_link_tags('bitbag-productBundle-admin', null, 'product_bundle_admin') }}
diff --git a/src/Resources/views/Shop/Cart/Summary/_item.html.twig b/src/Resources/views/Shop/Cart/Summary/_item.html.twig
new file mode 100644
index 00000000..6ce5b1d7
--- /dev/null
+++ b/src/Resources/views/Shop/Cart/Summary/_item.html.twig
@@ -0,0 +1,42 @@
+{% import "@SyliusShop/Common/Macro/money.html.twig" as money %}
+
+{% set product_variant = item.variant %}
+{% set original_price_to_display = sylius_order_item_original_price_to_display(item) %}
+{% set is_bundle = item.product.bundle %}
+
+
+
+ {% include '@SyliusShop/Product/_info.html.twig' with {'variant': product_variant} %}
+ |
+
+ {% if original_price_to_display is not null %}
+
+ {{ money.convertAndFormat(original_price_to_display) }}
+
+ {% endif %}
+ {{ money.convertAndFormat(item.discountedUnitPrice) }}
+ |
+
+
+ {{ form_widget(form.quantity, sylius_test_form_attribute('cart-item-quantity-input', item.productName)|sylius_merge_recursive({'attr': {'form': main_form}})) }}
+ {{ form_errors(form.quantity) }}
+
+ |
+
+
+ |
+
+ {{ money.convertAndFormat(item.subtotal) }}
+ |
+
+{% if item.product.bundle %}
+
+
+ {{ bitbag_render_shop_product_bundle_order_items(item) }}
+ |
+
+{% endif %}
diff --git a/src/Resources/views/Shop/Common/Order/Table/_item.html.twig b/src/Resources/views/Shop/Common/Order/Table/_item.html.twig
new file mode 100644
index 00000000..de0185ba
--- /dev/null
+++ b/src/Resources/views/Shop/Common/Order/Table/_item.html.twig
@@ -0,0 +1,31 @@
+{% import "@SyliusShop/Common/Macro/money.html.twig" as money %}
+
+{% set unitPromotionAdjustment = constant('Sylius\\Component\\Core\\Model\\AdjustmentInterface::ORDER_UNIT_PROMOTION_ADJUSTMENT') %}
+{% set unitPromotions = item.units.first.adjustments(unitPromotionAdjustment) %}
+{% set is_bundle = item.product.bundle %}
+
+
+ {% include '@SyliusShop/Product/_info.html.twig' with {'variant': item.variant} %}
+ |
+
+ {% if item.unitPrice != item.discountedUnitPrice %}
+ {{ money.convertAndFormat(item.unitPrice) }}
+ {% endif %}
+ {{ money.convertAndFormat(item.discountedUnitPrice) }}
+ {% if item.unitPrice != item.discountedUnitPrice %}
+
+ {% endif %}
+
+ |
+ {{ item.quantity }} |
+ {{ money.convertAndFormat(item.subtotal) }} |
+
+{% if item.product.bundle %}
+
+
+ {{ bitbag_render_shop_product_bundle_order_items(item) }}
+ |
+
+{% endif %}
diff --git a/src/Resources/views/Shop/Order/Show/_productBundleOrderItems.html.twig b/src/Resources/views/Shop/Order/Show/_productBundleOrderItems.html.twig
new file mode 100644
index 00000000..4e835f98
--- /dev/null
+++ b/src/Resources/views/Shop/Order/Show/_productBundleOrderItems.html.twig
@@ -0,0 +1,27 @@
+
+
+
+
+ {% for item in items %}
+ {% set variant = item.productVariant %}
+ {% set product = variant.product %}
+
+
+
+
+ {% endfor %}
+
+
diff --git a/tests/Application/templates/bundles/SyliusShopBundle/Product/Show/_inventory.html.twig b/src/Resources/views/Shop/Product/Show/_inventory.html.twig
similarity index 80%
rename from tests/Application/templates/bundles/SyliusShopBundle/Product/Show/_inventory.html.twig
rename to src/Resources/views/Shop/Product/Show/_inventory.html.twig
index 31efa961..6019f8aa 100644
--- a/tests/Application/templates/bundles/SyliusShopBundle/Product/Show/_inventory.html.twig
+++ b/src/Resources/views/Shop/Product/Show/_inventory.html.twig
@@ -1,4 +1,4 @@
-{% if product.variants.empty() or product.simple and not sylius_inventory_is_available(product.variants.first) %}
+{% if product.enabledVariants.empty() or product.simple and not sylius_inventory_is_available(product.enabledVariants.first) %}
{% include '@SyliusShop/Product/Show/_outOfStock.html.twig' %}
{% else %}
{% if product.isBundle %}
diff --git a/src/Resources/views/Shop/Product/_variantSelection.html.twig b/src/Resources/views/Shop/Product/_variantSelection.html.twig
new file mode 100644
index 00000000..30f96ac7
--- /dev/null
+++ b/src/Resources/views/Shop/Product/_variantSelection.html.twig
@@ -0,0 +1,7 @@
+{% if product.isConfigurable() and product.getVariantSelectionMethod() == 'match' and not product.enabledVariants.empty() %}
+ {% include '@SyliusShop/Product/Show/_variantsPricing.html.twig' with {'pricing': sylius_product_variant_prices(product, sylius.channel), 'variants': product.enabledVariants} %}
+{% endif %}
+
+{% include '@BitBagSyliusProductBundlePlugin/Shop/Product/Show/_inventory.html.twig' %}
+
+
diff --git a/tests/Application/templates/bundles/SyliusShopBundle/_scripts.html.twig b/src/Resources/views/Shop/_scripts.html.twig
similarity index 60%
rename from tests/Application/templates/bundles/SyliusShopBundle/_scripts.html.twig
rename to src/Resources/views/Shop/_scripts.html.twig
index 278c091e..658945c3 100644
--- a/tests/Application/templates/bundles/SyliusShopBundle/_scripts.html.twig
+++ b/src/Resources/views/Shop/_scripts.html.twig
@@ -1,2 +1 @@
-{{ encore_entry_script_tags('shop-entry', null, 'shop') }}
{{ encore_entry_script_tags('bitbag-productBundle-shop', null, 'product_bundle_shop') }}
diff --git a/tests/Application/templates/bundles/SyliusShopBundle/_styles.html.twig b/src/Resources/views/Shop/_styles.html.twig
similarity index 60%
rename from tests/Application/templates/bundles/SyliusShopBundle/_styles.html.twig
rename to src/Resources/views/Shop/_styles.html.twig
index 5365a60e..94657919 100644
--- a/tests/Application/templates/bundles/SyliusShopBundle/_styles.html.twig
+++ b/src/Resources/views/Shop/_styles.html.twig
@@ -1,2 +1 @@
-{{ encore_entry_link_tags('shop-entry', null, 'shop') }}
{{ encore_entry_link_tags('bitbag-productBundle-shop', null, 'product_bundle_shop') }}
diff --git a/src/Twig/Extension/ProductBundleOrderItemExtension.php b/src/Twig/Extension/ProductBundleOrderItemExtension.php
index 5bc1eafd..99d1f1bf 100644
--- a/src/Twig/Extension/ProductBundleOrderItemExtension.php
+++ b/src/Twig/Extension/ProductBundleOrderItemExtension.php
@@ -21,33 +21,56 @@
final class ProductBundleOrderItemExtension extends AbstractExtension
{
public function __construct(
- private RepositoryInterface $productBundleOrderItemRepository,
- private Environment $twig,
+ private readonly RepositoryInterface $productBundleOrderItemRepository,
+ private readonly Environment $twig,
) {
}
public function getFunctions(): array
{
return [
- new TwigFunction('bitbag_render_product_bundle_order_items', [$this, 'renderProductBundleOrderItems'], ['is_safe' => ['html']]),
+ new TwigFunction('bitbag_render_admin_product_bundle_order_items', [$this, 'renderAdminProductBundleOrderItems'], ['is_safe' => ['html']]),
+ new TwigFunction('bitbag_render_shop_product_bundle_order_items', [$this, 'renderShopProductBundleOrderItems'], ['is_safe' => ['html']]),
];
}
- public function renderProductBundleOrderItems(OrderItemInterface $orderItem): string
+ public function renderAdminProductBundleOrderItems(OrderItemInterface $orderItem): string
{
- /** @var ProductInterface $product */
- $product = $orderItem->getProduct();
+ $items = $this->getItems($orderItem);
- if (!$product->isBundle()) {
+ if ([] === $items) {
return '';
}
- $items = $this->productBundleOrderItemRepository->findBy([
- 'orderItem' => $orderItem,
+ return $this->twig->render('@BitBagSyliusProductBundlePlugin/Admin/Order/Show/_productBundleOrderItems.html.twig', [
+ 'items' => $items,
]);
+ }
- return $this->twig->render('@BitBagSyliusProductBundlePlugin/Admin/Order/Show/_productBundleOrderItems.html.twig', [
+ public function renderShopProductBundleOrderItems(OrderItemInterface $orderItem): string
+ {
+ $items = $this->getItems($orderItem);
+
+ if ([] === $items) {
+ return '';
+ }
+
+ return $this->twig->render('@BitBagSyliusProductBundlePlugin/Shop/Order/Show/_productBundleOrderItems.html.twig', [
'items' => $items,
]);
}
+
+ private function getItems(OrderItemInterface $orderItem): array
+ {
+ /** @var ProductInterface $product */
+ $product = $orderItem->getProduct();
+
+ if (!$product->isBundle()) {
+ return [];
+ }
+
+ return $this->productBundleOrderItemRepository->findBy([
+ 'orderItem' => $orderItem,
+ ]);
+ }
}
diff --git a/src/Twig/Extension/ProductBundlesExtension.php b/src/Twig/Extension/ProductBundlesExtension.php
new file mode 100644
index 00000000..39556207
--- /dev/null
+++ b/src/Twig/Extension/ProductBundlesExtension.php
@@ -0,0 +1,49 @@
+ ['html']]),
+ new TwigFunction('bitbag_get_products_from_bundle', [$this, 'getProductsFromBundle'], ['is_safe' => ['html']]),
+ ];
+ }
+
+ /** @return ProductBundleInterface[] */
+ public function getBundlesForProduct(ProductInterface $product): array
+ {
+ return $this->productBundleRepository->findBundlesByVariants($product->getVariants());
+ }
+
+ /** @return ProductBundleItemInterface[] */
+ public function getProductsFromBundle(ProductInterface $product): array
+ {
+ return $this->productBundleItemRepository->findByBundleCode((string) $product->getCode());
+ }
+}
diff --git a/tests/Application/.babelrc b/tests/Application/.babelrc
deleted file mode 100644
index e563a62e..00000000
--- a/tests/Application/.babelrc
+++ /dev/null
@@ -1,15 +0,0 @@
-{
- "presets": [
- ["env", {
- "targets": {
- "node": "6"
- },
- "useBuiltIns": true
- }]
- ],
- "plugins": [
- ["transform-object-rest-spread", {
- "useBuiltIns": true
- }]
- ]
-}
diff --git a/tests/Application/.env b/tests/Application/.env
index 6fa8b962..57445681 100644
--- a/tests/Application/.env
+++ b/tests/Application/.env
@@ -23,6 +23,13 @@ DATABASE_URL=sqlite:///%kernel.project_dir%/var/data_%kernel.environment%.db
MESSENGER_TRANSPORT_DSN=sync://
###< symfony/messenger ###
+###> sylius/sylius >= 12.4 ###
+SYLIUS_MESSENGER_TRANSPORT_MAIN_DSN=${MESSENGER_TRANSPORT_DSN}
+SYLIUS_MESSENGER_TRANSPORT_MAIN_FAILED_DSN=${MESSENGER_TRANSPORT_DSN}
+SYLIUS_MESSENGER_TRANSPORT_CATALOG_PROMOTION_REMOVAL_DSN=${MESSENGER_TRANSPORT_DSN}
+SYLIUS_MESSENGER_TRANSPORT_CATALOG_PROMOTION_REMOVAL_FAILED_DSN=${MESSENGER_TRANSPORT_DSN}
+###< sylius/sylius ###
+
###> lexik/jwt-authentication-bundle ###
JWT_SECRET_KEY=%kernel.project_dir%/config/jwt/private.pem
JWT_PUBLIC_KEY=%kernel.project_dir%/config/jwt/public.pem
@@ -35,3 +42,7 @@ JWT_PASSPHRASE=acme_plugin_development
# Delivery is disabled by default via "null://localhost"
MAILER_URL=smtp://localhost
###< symfony/swiftmailer-bundle ###
+
+###> bitbag/product-bundle-plugin ###
+BUNDLED_PRODUCTS_INVENTORY_MANAGEMENT_FEATURE=true
+###< bitbag/product-bundle-plugin ###
diff --git a/tests/Application/config/packages/_sylius.yaml b/tests/Application/config/packages/_sylius.yaml
index 5277c18c..e39d353e 100644
--- a/tests/Application/config/packages/_sylius.yaml
+++ b/tests/Application/config/packages/_sylius.yaml
@@ -1,61 +1,30 @@
imports:
- - { resource: "@SyliusCoreBundle/Resources/config/app/config.yml" }
+ - { resource: "@SyliusCoreBundle/Resources/config/app/config.yml" }
- - { resource: "@SyliusAdminBundle/Resources/config/app/config.yml" }
+ - { resource: "@SyliusAdminBundle/Resources/config/app/config.yml" }
- - { resource: "@SyliusShopBundle/Resources/config/app/config.yml" }
+ - { resource: "@SyliusShopBundle/Resources/config/app/config.yml" }
- - { resource: "@SyliusApiBundle/Resources/config/app/config.yaml" }
+ - { resource: "@SyliusApiBundle/Resources/config/app/config.yaml" }
sylius_api:
- enabled: true
+ enabled: true
parameters:
- sylius_core.public_dir: '%kernel.project_dir%/public'
+ sylius_core.public_dir: '%kernel.project_dir%/public'
sylius_product:
- resources:
- product:
- classes:
- model: Tests\BitBag\SyliusProductBundlePlugin\Entity\Product
- product_variant:
- classes:
- repository: BitBag\SyliusProductBundlePlugin\Repository\ProductVariantRepository
+ resources:
+ product:
+ classes:
+ model: Tests\BitBag\SyliusProductBundlePlugin\Entity\Product
sylius_order:
- resources:
- order_item:
- classes:
- model: Tests\BitBag\SyliusProductBundlePlugin\Entity\OrderItem
+ resources:
+ order_item:
+ classes:
+ model: Tests\BitBag\SyliusProductBundlePlugin\Entity\OrderItem
sylius_shop:
- product_grid:
- include_all_descendants: true
-
-sylius_grid:
- grids:
- sylius_admin_product:
- actions:
- main:
- create:
- type: links
- label: sylius.ui.create
- options:
- class: primary
- icon: plus
- header:
- icon: cube
- label: sylius.ui.type
- links:
- simple:
- label: sylius.ui.simple_product
- icon: plus
- route: sylius_admin_product_create_simple
- configurable:
- label: sylius.ui.configurable_product
- icon: plus
- route: sylius_admin_product_create
- bundle:
- label: bitbag_sylius_product_bundle.ui.bundle
- icon: plus
- route: bitbag_product_bundle_admin_product_create_bundle
+ product_grid:
+ include_all_descendants: true
diff --git a/tests/Application/config/packages/bitbag_sylius_product_bundle_plugin.yml b/tests/Application/config/packages/bitbag_sylius_product_bundle_plugin.yml
index bd17eb83..71204aee 100644
--- a/tests/Application/config/packages/bitbag_sylius_product_bundle_plugin.yml
+++ b/tests/Application/config/packages/bitbag_sylius_product_bundle_plugin.yml
@@ -1,2 +1,46 @@
imports:
- - { resource: "@BitBagSyliusProductBundlePlugin/Resources/config/config.yml" }
+ - { resource: "@BitBagSyliusProductBundlePlugin/Resources/config/config.yml" }
+
+sylius_fixtures:
+ suites:
+ default:
+ fixtures:
+ tshirt_bundle_products:
+ name: product
+ options:
+ custom:
+ - name: 'Packed T-Shirt bundle'
+ tax_category: 'clothing'
+ channels:
+ - 'FASHION_WEB'
+ main_taxon: 'mens_t_shirts'
+ taxons:
+ - 't_shirts'
+ - 'mens_t_shirts'
+
+ - name: 'Not packed T-Shirt bundle'
+ tax_category: 'clothing'
+ channels:
+ - 'FASHION_WEB'
+ main_taxon: 'womens_t_shirts'
+ taxons:
+ - 't_shirts'
+ - 'womens_t_shirts'
+
+ tshirt_bundles:
+ name: product_bundle
+ options:
+ custom:
+ - bundle: 'Packed_T_Shirt_bundle'
+ items:
+ - 'Sport_basic_white_T_Shirt-variant-0'
+ - 'Raglan_grey_&_black_Tee-variant-0'
+ - 'Oversize_white_cotton_T_Shirt-variant-0'
+ is_packed: true
+
+ - bundle: 'Not_packed_T_Shirt_bundle'
+ items:
+ - 'Everyday_white_basic_T_Shirt-variant-0'
+ - 'Loose_white_designer_T_Shirt-variant-0'
+ - 'Ribbed_copper_slim_fit_Tee-variant-0'
+ is_packed: false
diff --git a/tests/Application/config/packages/dev/framework.yaml b/tests/Application/config/packages/dev/framework.yaml
index 4b116def..1e2ebc1f 100644
--- a/tests/Application/config/packages/dev/framework.yaml
+++ b/tests/Application/config/packages/dev/framework.yaml
@@ -1,2 +1,2 @@
framework:
- profiler: { only_exceptions: false }
+ profiler: { only_exceptions: false }
diff --git a/tests/Application/config/packages/dev/monolog.yaml b/tests/Application/config/packages/dev/monolog.yaml
index da2b092d..a8ae3c7d 100644
--- a/tests/Application/config/packages/dev/monolog.yaml
+++ b/tests/Application/config/packages/dev/monolog.yaml
@@ -1,9 +1,9 @@
monolog:
- handlers:
- main:
- type: stream
- path: "%kernel.logs_dir%/%kernel.environment%.log"
- level: debug
- firephp:
- type: firephp
- level: info
+ handlers:
+ main:
+ type: stream
+ path: "%kernel.logs_dir%/%kernel.environment%.log"
+ level: debug
+ firephp:
+ type: firephp
+ level: info
diff --git a/tests/Application/config/packages/dev/routing.yaml b/tests/Application/config/packages/dev/routing.yaml
index 4116679a..a3d2503d 100644
--- a/tests/Application/config/packages/dev/routing.yaml
+++ b/tests/Application/config/packages/dev/routing.yaml
@@ -1,3 +1,3 @@
framework:
- router:
- strict_requirements: true
+ router:
+ strict_requirements: true
diff --git a/tests/Application/config/packages/dev/web_profiler.yaml b/tests/Application/config/packages/dev/web_profiler.yaml
index 1f1cb2bb..be5064e3 100644
--- a/tests/Application/config/packages/dev/web_profiler.yaml
+++ b/tests/Application/config/packages/dev/web_profiler.yaml
@@ -1,3 +1,3 @@
web_profiler:
- toolbar: true
- intercept_redirects: false
+ toolbar: true
+ intercept_redirects: false
diff --git a/tests/Application/config/packages/doctrine.yaml b/tests/Application/config/packages/doctrine.yaml
index b4126767..c74b2072 100644
--- a/tests/Application/config/packages/doctrine.yaml
+++ b/tests/Application/config/packages/doctrine.yaml
@@ -1,25 +1,25 @@
parameters:
- # Adds a fallback DATABASE_URL if the env var is not set.
- # This allows you to run cache:warmup even if your
- # environment variables are not available yet.
- # You should not need to change this value.
- env(DATABASE_URL): ''
+ # Adds a fallback DATABASE_URL if the env var is not set.
+ # This allows you to run cache:warmup even if your
+ # environment variables are not available yet.
+ # You should not need to change this value.
+ env(DATABASE_URL): ''
doctrine:
- dbal:
- driver: 'pdo_mysql'
- server_version: '5.7'
- charset: UTF8
+ dbal:
+ driver: 'pdo_mysql'
+ server_version: '5.7'
+ charset: UTF8
- url: '%env(resolve:DATABASE_URL)%'
+ url: '%env(resolve:DATABASE_URL)%'
- orm:
- auto_generate_proxy_classes: '%kernel.debug%'
- naming_strategy: doctrine.orm.naming_strategy.underscore
- auto_mapping: true
- mappings:
- App:
- is_bundle: false
- type: xml
- dir: '%kernel.project_dir%/src/Resources/config/doctrine'
- prefix: 'Tests\BitBag\SyliusProductBundlePlugin\Entity'
+ orm:
+ auto_generate_proxy_classes: '%kernel.debug%'
+ naming_strategy: doctrine.orm.naming_strategy.underscore
+ auto_mapping: true
+ mappings:
+ App:
+ is_bundle: false
+ type: xml
+ dir: '%kernel.project_dir%/src/Resources/config/doctrine'
+ prefix: 'Tests\BitBag\SyliusProductBundlePlugin\Entity'
diff --git a/tests/Application/config/packages/doctrine_migrations.yaml b/tests/Application/config/packages/doctrine_migrations.yaml
index cdbc01ae..2b3bacda 100644
--- a/tests/Application/config/packages/doctrine_migrations.yaml
+++ b/tests/Application/config/packages/doctrine_migrations.yaml
@@ -1,4 +1,4 @@
doctrine_migrations:
- storage:
- table_storage:
- table_name: sylius_migrations
+ storage:
+ table_storage:
+ table_name: sylius_migrations
diff --git a/tests/Application/config/packages/fos_rest.yaml b/tests/Application/config/packages/fos_rest.yaml
index a72eef7c..6e54cbdc 100644
--- a/tests/Application/config/packages/fos_rest.yaml
+++ b/tests/Application/config/packages/fos_rest.yaml
@@ -1,11 +1,11 @@
fos_rest:
- exception: true
- view:
- formats:
- json: true
- xml: true
- empty_content: 204
- format_listener:
- rules:
- - { path: '^/api/.*', priorities: ['json', 'xml'], fallback_format: json, prefer_extension: true }
- - { path: '^/', stop: true }
+ exception: true
+ view:
+ formats:
+ json: true
+ xml: true
+ empty_content: 204
+ format_listener:
+ rules:
+ - { path: '^/api/.*', priorities: [ 'json', 'xml' ], fallback_format: json, prefer_extension: true }
+ - { path: '^/', stop: true }
diff --git a/tests/Application/config/packages/framework.yaml b/tests/Application/config/packages/framework.yaml
index 9b445011..22e9f619 100644
--- a/tests/Application/config/packages/framework.yaml
+++ b/tests/Application/config/packages/framework.yaml
@@ -1,6 +1,6 @@
framework:
- secret: '%env(APP_SECRET)%'
- form: true
- csrf_protection: true
- session:
- handler_id: ~
+ secret: '%env(APP_SECRET)%'
+ form: true
+ csrf_protection: true
+ session:
+ handler_id: ~
diff --git a/tests/Application/config/packages/lexik_jwt_authentication.yaml b/tests/Application/config/packages/lexik_jwt_authentication.yaml
index edfb69dc..20f1cb0c 100644
--- a/tests/Application/config/packages/lexik_jwt_authentication.yaml
+++ b/tests/Application/config/packages/lexik_jwt_authentication.yaml
@@ -1,4 +1,4 @@
lexik_jwt_authentication:
- secret_key: '%env(resolve:JWT_SECRET_KEY)%'
- public_key: '%env(resolve:JWT_PUBLIC_KEY)%'
- pass_phrase: '%env(JWT_PASSPHRASE)%'
+ secret_key: '%env(resolve:JWT_SECRET_KEY)%'
+ public_key: '%env(resolve:JWT_PUBLIC_KEY)%'
+ pass_phrase: '%env(JWT_PASSPHRASE)%'
diff --git a/tests/Application/config/packages/liip_imagine.yaml b/tests/Application/config/packages/liip_imagine.yaml
index bb2e7ceb..28b2e2cf 100644
--- a/tests/Application/config/packages/liip_imagine.yaml
+++ b/tests/Application/config/packages/liip_imagine.yaml
@@ -1,6 +1,6 @@
liip_imagine:
- resolvers:
- default:
- web_path:
- web_root: "%kernel.project_dir%/public"
- cache_prefix: "media/cache"
+ resolvers:
+ default:
+ web_path:
+ web_root: "%kernel.project_dir%/public"
+ cache_prefix: "media/cache"
diff --git a/tests/Application/config/packages/prod/doctrine.yaml b/tests/Application/config/packages/prod/doctrine.yaml
index 2f16f0fd..a0f45e57 100644
--- a/tests/Application/config/packages/prod/doctrine.yaml
+++ b/tests/Application/config/packages/prod/doctrine.yaml
@@ -1,31 +1,31 @@
doctrine:
- orm:
- metadata_cache_driver:
- type: service
- id: doctrine.system_cache_provider
- query_cache_driver:
- type: service
- id: doctrine.system_cache_provider
- result_cache_driver:
- type: service
- id: doctrine.result_cache_provider
+ orm:
+ metadata_cache_driver:
+ type: service
+ id: doctrine.system_cache_provider
+ query_cache_driver:
+ type: service
+ id: doctrine.system_cache_provider
+ result_cache_driver:
+ type: service
+ id: doctrine.result_cache_provider
services:
- doctrine.result_cache_provider:
- class: Symfony\Component\Cache\DoctrineProvider
- public: false
- arguments:
- - '@doctrine.result_cache_pool'
- doctrine.system_cache_provider:
- class: Symfony\Component\Cache\DoctrineProvider
- public: false
- arguments:
- - '@doctrine.system_cache_pool'
+ doctrine.result_cache_provider:
+ class: Symfony\Component\Cache\DoctrineProvider
+ public: false
+ arguments:
+ - '@doctrine.result_cache_pool'
+ doctrine.system_cache_provider:
+ class: Symfony\Component\Cache\DoctrineProvider
+ public: false
+ arguments:
+ - '@doctrine.system_cache_pool'
framework:
- cache:
- pools:
- doctrine.result_cache_pool:
- adapter: cache.app
- doctrine.system_cache_pool:
- adapter: cache.system
+ cache:
+ pools:
+ doctrine.result_cache_pool:
+ adapter: cache.app
+ doctrine.system_cache_pool:
+ adapter: cache.system
diff --git a/tests/Application/config/packages/prod/monolog.yaml b/tests/Application/config/packages/prod/monolog.yaml
index 64612114..f17d1996 100644
--- a/tests/Application/config/packages/prod/monolog.yaml
+++ b/tests/Application/config/packages/prod/monolog.yaml
@@ -1,10 +1,10 @@
monolog:
- handlers:
- main:
- type: fingers_crossed
- action_level: error
- handler: nested
- nested:
- type: stream
- path: "%kernel.logs_dir%/%kernel.environment%.log"
- level: debug
+ handlers:
+ main:
+ type: fingers_crossed
+ action_level: error
+ handler: nested
+ nested:
+ type: stream
+ path: "%kernel.logs_dir%/%kernel.environment%.log"
+ level: debug
diff --git a/tests/Application/config/packages/routing.yaml b/tests/Application/config/packages/routing.yaml
index 368bc7f4..17ae5482 100644
--- a/tests/Application/config/packages/routing.yaml
+++ b/tests/Application/config/packages/routing.yaml
@@ -1,3 +1,3 @@
framework:
- router:
- strict_requirements: ~
+ router:
+ strict_requirements: ~
diff --git a/tests/Application/config/packages/staging/monolog.yaml b/tests/Application/config/packages/staging/monolog.yaml
index 64612114..f17d1996 100644
--- a/tests/Application/config/packages/staging/monolog.yaml
+++ b/tests/Application/config/packages/staging/monolog.yaml
@@ -1,10 +1,10 @@
monolog:
- handlers:
- main:
- type: fingers_crossed
- action_level: error
- handler: nested
- nested:
- type: stream
- path: "%kernel.logs_dir%/%kernel.environment%.log"
- level: debug
+ handlers:
+ main:
+ type: fingers_crossed
+ action_level: error
+ handler: nested
+ nested:
+ type: stream
+ path: "%kernel.logs_dir%/%kernel.environment%.log"
+ level: debug
diff --git a/tests/Application/config/packages/stof_doctrine_extensions.yaml b/tests/Application/config/packages/stof_doctrine_extensions.yaml
index 7770f74e..b2e32470 100644
--- a/tests/Application/config/packages/stof_doctrine_extensions.yaml
+++ b/tests/Application/config/packages/stof_doctrine_extensions.yaml
@@ -1,4 +1,4 @@
# Read the documentation: https://symfony.com/doc/current/bundles/StofDoctrineExtensionsBundle/index.html
# See the official DoctrineExtensions documentation for more details: https://github.com/Atlantic18/DoctrineExtensions/tree/master/doc/
stof_doctrine_extensions:
- default_locale: '%locale%'
+ default_locale: '%locale%'
diff --git a/tests/Application/config/packages/sylius_ui.yaml b/tests/Application/config/packages/sylius_ui.yaml
new file mode 100644
index 00000000..2ef12fd6
--- /dev/null
+++ b/tests/Application/config/packages/sylius_ui.yaml
@@ -0,0 +1,31 @@
+sylius_ui:
+ events:
+ sylius.shop.product.show.right_sidebar:
+ blocks:
+ variant_selection:
+ template: "@BitBagSyliusProductBundlePlugin/Shop/Product/_variantSelection.html.twig"
+ priority: 10
+
+ sylius.shop.layout.javascripts:
+ blocks:
+ plugin_scripts:
+ template: "@BitBagSyliusProductBundlePlugin/Shop/_scripts.html.twig"
+ priority: 20
+
+ sylius.shop.layout.stylesheets:
+ blocks:
+ plugin_stylesheets:
+ template: "@BitBagSyliusProductBundlePlugin/Shop/_styles.html.twig"
+ priority: 20
+
+ sylius.admin.layout.javascripts:
+ blocks:
+ plugin_scripts:
+ template: "@BitBagSyliusProductBundlePlugin/Admin/_scripts.html.twig"
+ priority: 20
+
+ sylius.admin.layout.stylesheets:
+ blocks:
+ plugin_stylesheets:
+ template: "@BitBagSyliusProductBundlePlugin/Admin/_styles.html.twig"
+ priority: 20
diff --git a/tests/Application/config/packages/test/framework.yaml b/tests/Application/config/packages/test/framework.yaml
index daf04d4e..2734c0ca 100644
--- a/tests/Application/config/packages/test/framework.yaml
+++ b/tests/Application/config/packages/test/framework.yaml
@@ -1,4 +1,4 @@
framework:
- test: ~
- session:
- handler_id: ~
+ test: ~
+ session:
+ handler_id: ~
diff --git a/tests/Application/config/packages/test/monolog.yaml b/tests/Application/config/packages/test/monolog.yaml
index 7e2b9e3a..d5cefe75 100644
--- a/tests/Application/config/packages/test/monolog.yaml
+++ b/tests/Application/config/packages/test/monolog.yaml
@@ -1,6 +1,6 @@
monolog:
- handlers:
- main:
- type: stream
- path: "%kernel.logs_dir%/%kernel.environment%.log"
- level: error
+ handlers:
+ main:
+ type: stream
+ path: "%kernel.logs_dir%/%kernel.environment%.log"
+ level: error
diff --git a/tests/Application/config/packages/test/sylius_theme.yaml b/tests/Application/config/packages/test/sylius_theme.yaml
index 4d34199f..3cc3d971 100644
--- a/tests/Application/config/packages/test/sylius_theme.yaml
+++ b/tests/Application/config/packages/test/sylius_theme.yaml
@@ -1,3 +1,3 @@
sylius_theme:
- sources:
- test: ~
+ sources:
+ test: ~
diff --git a/tests/Application/config/packages/test/sylius_uploader.yaml b/tests/Application/config/packages/test/sylius_uploader.yaml
index ab9d6ca0..cfc5d05b 100644
--- a/tests/Application/config/packages/test/sylius_uploader.yaml
+++ b/tests/Application/config/packages/test/sylius_uploader.yaml
@@ -1,3 +1,3 @@
services:
- Sylius\Component\Core\Generator\ImagePathGeneratorInterface:
- class: Sylius\Behat\Service\Generator\UploadedImagePathGenerator
+ Sylius\Component\Core\Generator\ImagePathGeneratorInterface:
+ class: Sylius\Behat\Service\Generator\UploadedImagePathGenerator
diff --git a/tests/Application/config/packages/test/web_profiler.yaml b/tests/Application/config/packages/test/web_profiler.yaml
index 03752de2..808c4cf9 100644
--- a/tests/Application/config/packages/test/web_profiler.yaml
+++ b/tests/Application/config/packages/test/web_profiler.yaml
@@ -1,6 +1,6 @@
web_profiler:
- toolbar: false
- intercept_redirects: false
+ toolbar: false
+ intercept_redirects: false
framework:
- profiler: { collect: false }
+ profiler: { collect: false }
diff --git a/tests/Application/config/packages/test_cached/doctrine.yaml b/tests/Application/config/packages/test_cached/doctrine.yaml
index 49528606..316da829 100644
--- a/tests/Application/config/packages/test_cached/doctrine.yaml
+++ b/tests/Application/config/packages/test_cached/doctrine.yaml
@@ -1,16 +1,16 @@
doctrine:
- orm:
- entity_managers:
- default:
- result_cache_driver:
- type: memcached
- host: localhost
- port: 11211
- query_cache_driver:
- type: memcached
- host: localhost
- port: 11211
- metadata_cache_driver:
- type: memcached
- host: localhost
- port: 11211
+ orm:
+ entity_managers:
+ default:
+ result_cache_driver:
+ type: memcached
+ host: localhost
+ port: 11211
+ query_cache_driver:
+ type: memcached
+ host: localhost
+ port: 11211
+ metadata_cache_driver:
+ type: memcached
+ host: localhost
+ port: 11211
diff --git a/tests/Application/config/packages/test_cached/fos_rest.yaml b/tests/Application/config/packages/test_cached/fos_rest.yaml
index 2b4189da..c36c93f9 100644
--- a/tests/Application/config/packages/test_cached/fos_rest.yaml
+++ b/tests/Application/config/packages/test_cached/fos_rest.yaml
@@ -1,3 +1,3 @@
fos_rest:
- exception:
- debug: true
+ exception:
+ debug: true
diff --git a/tests/Application/config/packages/test_cached/framework.yaml b/tests/Application/config/packages/test_cached/framework.yaml
index daf04d4e..2734c0ca 100644
--- a/tests/Application/config/packages/test_cached/framework.yaml
+++ b/tests/Application/config/packages/test_cached/framework.yaml
@@ -1,4 +1,4 @@
framework:
- test: ~
- session:
- handler_id: ~
+ test: ~
+ session:
+ handler_id: ~
diff --git a/tests/Application/config/packages/test_cached/monolog.yaml b/tests/Application/config/packages/test_cached/monolog.yaml
index 7e2b9e3a..d5cefe75 100644
--- a/tests/Application/config/packages/test_cached/monolog.yaml
+++ b/tests/Application/config/packages/test_cached/monolog.yaml
@@ -1,6 +1,6 @@
monolog:
- handlers:
- main:
- type: stream
- path: "%kernel.logs_dir%/%kernel.environment%.log"
- level: error
+ handlers:
+ main:
+ type: stream
+ path: "%kernel.logs_dir%/%kernel.environment%.log"
+ level: error
diff --git a/tests/Application/config/packages/test_cached/sylius_channel.yaml b/tests/Application/config/packages/test_cached/sylius_channel.yaml
index bab83ef2..88ff5989 100644
--- a/tests/Application/config/packages/test_cached/sylius_channel.yaml
+++ b/tests/Application/config/packages/test_cached/sylius_channel.yaml
@@ -1,2 +1,2 @@
sylius_channel:
- debug: true
+ debug: true
diff --git a/tests/Application/config/packages/test_cached/sylius_theme.yaml b/tests/Application/config/packages/test_cached/sylius_theme.yaml
index 4d34199f..3cc3d971 100644
--- a/tests/Application/config/packages/test_cached/sylius_theme.yaml
+++ b/tests/Application/config/packages/test_cached/sylius_theme.yaml
@@ -1,3 +1,3 @@
sylius_theme:
- sources:
- test: ~
+ sources:
+ test: ~
diff --git a/tests/Application/config/packages/test_cached/sylius_uploader.yaml b/tests/Application/config/packages/test_cached/sylius_uploader.yaml
index cfa727e2..fcb02b15 100644
--- a/tests/Application/config/packages/test_cached/sylius_uploader.yaml
+++ b/tests/Application/config/packages/test_cached/sylius_uploader.yaml
@@ -1,2 +1,2 @@
imports:
- - { resource: "../test/sylius_uploader.yaml" }
+ - { resource: "../test/sylius_uploader.yaml" }
diff --git a/tests/Application/config/packages/test_cached/twig.yaml b/tests/Application/config/packages/test_cached/twig.yaml
index 8c6e0b40..d82243ff 100644
--- a/tests/Application/config/packages/test_cached/twig.yaml
+++ b/tests/Application/config/packages/test_cached/twig.yaml
@@ -1,2 +1,2 @@
twig:
- strict_variables: true
+ strict_variables: true
diff --git a/tests/Application/config/packages/translation.yaml b/tests/Application/config/packages/translation.yaml
index 1f4f9664..5b162856 100644
--- a/tests/Application/config/packages/translation.yaml
+++ b/tests/Application/config/packages/translation.yaml
@@ -1,8 +1,8 @@
framework:
- default_locale: '%locale%'
- translator:
- paths:
- - '%kernel.project_dir%/translations'
- fallbacks:
- - '%locale%'
- - 'en'
+ default_locale: '%locale%'
+ translator:
+ paths:
+ - '%kernel.project_dir%/translations'
+ fallbacks:
+ - '%locale%'
+ - 'en'
diff --git a/tests/Application/config/packages/twig.yaml b/tests/Application/config/packages/twig.yaml
index 8545473d..0d575c1c 100644
--- a/tests/Application/config/packages/twig.yaml
+++ b/tests/Application/config/packages/twig.yaml
@@ -1,12 +1,12 @@
twig:
- paths: ['%kernel.project_dir%/templates']
- debug: '%kernel.debug%'
- strict_variables: '%kernel.debug%'
+ paths: [ '%kernel.project_dir%/templates' ]
+ debug: '%kernel.debug%'
+ strict_variables: '%kernel.debug%'
services:
- _defaults:
- public: false
- autowire: true
- autoconfigure: true
+ _defaults:
+ public: false
+ autowire: true
+ autoconfigure: true
- Twig\Extra\Intl\IntlExtension: ~
+ Twig\Extra\Intl\IntlExtension: ~
diff --git a/tests/Application/config/packages/validator.yaml b/tests/Application/config/packages/validator.yaml
index 61807db6..e6553b33 100644
--- a/tests/Application/config/packages/validator.yaml
+++ b/tests/Application/config/packages/validator.yaml
@@ -1,3 +1,3 @@
framework:
- validation:
- enable_annotations: true
+ validation:
+ enable_annotations: true
diff --git a/tests/Application/config/routes.yaml b/tests/Application/config/routes.yaml
index 7b7ee8bd..d3e703e0 100644
--- a/tests/Application/config/routes.yaml
+++ b/tests/Application/config/routes.yaml
@@ -1,2 +1,2 @@
bitbag_sylius_product_bundle_plugin:
- resource: "@BitBagSyliusProductBundlePlugin/Resources/config/routing.yml"
+ resource: "@BitBagSyliusProductBundlePlugin/Resources/config/routing.yml"
diff --git a/tests/Application/config/routes/dev/web_profiler.yaml b/tests/Application/config/routes/dev/web_profiler.yaml
index 3e79dc21..f54957a8 100644
--- a/tests/Application/config/routes/dev/web_profiler.yaml
+++ b/tests/Application/config/routes/dev/web_profiler.yaml
@@ -1,7 +1,7 @@
_wdt:
- resource: "@WebProfilerBundle/Resources/config/routing/wdt.xml"
- prefix: /_wdt
+ resource: "@WebProfilerBundle/Resources/config/routing/wdt.xml"
+ prefix: /_wdt
_profiler:
- resource: "@WebProfilerBundle/Resources/config/routing/profiler.xml"
- prefix: /_profiler
+ resource: "@WebProfilerBundle/Resources/config/routing/profiler.xml"
+ prefix: /_profiler
diff --git a/tests/Application/config/routes/liip_imagine.yaml b/tests/Application/config/routes/liip_imagine.yaml
index 201cbd5d..4e89a350 100644
--- a/tests/Application/config/routes/liip_imagine.yaml
+++ b/tests/Application/config/routes/liip_imagine.yaml
@@ -1,2 +1,2 @@
_liip_imagine:
- resource: "@LiipImagineBundle/Resources/config/routing.yaml"
+ resource: "@LiipImagineBundle/Resources/config/routing.yaml"
diff --git a/tests/Application/config/routes/sylius_admin.yaml b/tests/Application/config/routes/sylius_admin.yaml
index 1ba48d6c..baa3afdc 100644
--- a/tests/Application/config/routes/sylius_admin.yaml
+++ b/tests/Application/config/routes/sylius_admin.yaml
@@ -1,3 +1,3 @@
sylius_admin:
- resource: "@SyliusAdminBundle/Resources/config/routing.yml"
- prefix: /admin
+ resource: "@SyliusAdminBundle/Resources/config/routing.yml"
+ prefix: /admin
diff --git a/tests/Application/config/routes/sylius_api.yaml b/tests/Application/config/routes/sylius_api.yaml
index ae01ffce..4ed7e8f3 100644
--- a/tests/Application/config/routes/sylius_api.yaml
+++ b/tests/Application/config/routes/sylius_api.yaml
@@ -1,3 +1,3 @@
sylius_api:
- resource: "@SyliusApiBundle/Resources/config/routing.yml"
- prefix: "%sylius.security.new_api_route%"
+ resource: "@SyliusApiBundle/Resources/config/routing.yml"
+ prefix: "%sylius.security.new_api_route%"
diff --git a/tests/Application/config/routes/sylius_shop.yaml b/tests/Application/config/routes/sylius_shop.yaml
index fae46cbf..38d83337 100644
--- a/tests/Application/config/routes/sylius_shop.yaml
+++ b/tests/Application/config/routes/sylius_shop.yaml
@@ -1,14 +1,14 @@
sylius_shop:
- resource: "@SyliusShopBundle/Resources/config/routing.yml"
- prefix: /{_locale}
- requirements:
- _locale: ^[A-Za-z]{2,4}(_([A-Za-z]{4}|[0-9]{3}))?(_([A-Za-z]{2}|[0-9]{3}))?$
+ resource: "@SyliusShopBundle/Resources/config/routing.yml"
+ prefix: /{_locale}
+ requirements:
+ _locale: ^[A-Za-z]{2,4}(_([A-Za-z]{4}|[0-9]{3}))?(_([A-Za-z]{2}|[0-9]{3}))?$
sylius_shop_payum:
- resource: "@SyliusShopBundle/Resources/config/routing/payum.yml"
+ resource: "@SyliusShopBundle/Resources/config/routing/payum.yml"
sylius_shop_default_locale:
- path: /
- methods: [GET]
- defaults:
- _controller: sylius.controller.shop.locale_switch::switchAction
+ path: /
+ methods: [ GET ]
+ defaults:
+ _controller: sylius.controller.shop.locale_switch::switchAction
diff --git a/tests/Application/config/routes/test/sylius_test_plugin.yaml b/tests/Application/config/routes/test/sylius_test_plugin.yaml
index 0ca57d9a..138859f8 100644
--- a/tests/Application/config/routes/test/sylius_test_plugin.yaml
+++ b/tests/Application/config/routes/test/sylius_test_plugin.yaml
@@ -1,5 +1,5 @@
sylius_test_plugin_main:
- path: /test/main
- controller: FrameworkBundle:Template:template
- defaults:
- template: "@SyliusTestPlugin/main.html.twig"
+ path: /test/main
+ controller: FrameworkBundle:Template:template
+ defaults:
+ template: "@SyliusTestPlugin/main.html.twig"
diff --git a/tests/Application/config/routes/test_cached/routing.yaml b/tests/Application/config/routes/test_cached/routing.yaml
index 0ca57d9a..138859f8 100644
--- a/tests/Application/config/routes/test_cached/routing.yaml
+++ b/tests/Application/config/routes/test_cached/routing.yaml
@@ -1,5 +1,5 @@
sylius_test_plugin_main:
- path: /test/main
- controller: FrameworkBundle:Template:template
- defaults:
- template: "@SyliusTestPlugin/main.html.twig"
+ path: /test/main
+ controller: FrameworkBundle:Template:template
+ defaults:
+ template: "@SyliusTestPlugin/main.html.twig"
diff --git a/tests/Application/config/routes/test_cached/sylius_test_plugin.yaml b/tests/Application/config/routes/test_cached/sylius_test_plugin.yaml
index 0ca57d9a..138859f8 100644
--- a/tests/Application/config/routes/test_cached/sylius_test_plugin.yaml
+++ b/tests/Application/config/routes/test_cached/sylius_test_plugin.yaml
@@ -1,5 +1,5 @@
sylius_test_plugin_main:
- path: /test/main
- controller: FrameworkBundle:Template:template
- defaults:
- template: "@SyliusTestPlugin/main.html.twig"
+ path: /test/main
+ controller: FrameworkBundle:Template:template
+ defaults:
+ template: "@SyliusTestPlugin/main.html.twig"
diff --git a/tests/Application/config/services.yaml b/tests/Application/config/services.yaml
index 615506eb..ee3b8248 100644
--- a/tests/Application/config/services.yaml
+++ b/tests/Application/config/services.yaml
@@ -1,4 +1,4 @@
# Put parameters here that don't need to change on each machine where the app is deployed
# https://symfony.com/doc/current/best_practices/configuration.html#application-related-configuration
parameters:
- locale: en_US
+ locale: en_US
diff --git a/tests/Application/config/services_test.yaml b/tests/Application/config/services_test.yaml
index 9edf553d..f90fe420 100644
--- a/tests/Application/config/services_test.yaml
+++ b/tests/Application/config/services_test.yaml
@@ -1,8 +1,8 @@
imports:
- - { resource: "../../Behat/Resources/services.yml" }
- - { resource: "../../../vendor/sylius/sylius/src/Sylius/Behat/Resources/config/services.xml" }
+ - { resource: "../../Behat/Resources/services.yml" }
+ - { resource: "../../../vendor/sylius/sylius/src/Sylius/Behat/Resources/config/services.xml" }
# workaround needed for strange "test.client.history" problem
# see https://github.com/FriendsOfBehat/SymfonyExtension/issues/88
services:
- Symfony\Component\BrowserKit\AbstractBrowser: '@test.client'
+ Symfony\Component\BrowserKit\AbstractBrowser: '@test.client'
diff --git a/tests/Application/config/services_test_cached.yaml b/tests/Application/config/services_test_cached.yaml
index 0de380ea..5d2c7fa4 100644
--- a/tests/Application/config/services_test_cached.yaml
+++ b/tests/Application/config/services_test_cached.yaml
@@ -1,2 +1,2 @@
imports:
- - { resource: "services_test.yaml" }
+ - { resource: "services_test.yaml" }
diff --git a/tests/Application/config/sylius/1.12/packages/jms_serializer.yaml b/tests/Application/config/sylius/1.12/packages/jms_serializer.yaml
index ed7bc613..fa43f5b6 100644
--- a/tests/Application/config/sylius/1.12/packages/jms_serializer.yaml
+++ b/tests/Application/config/sylius/1.12/packages/jms_serializer.yaml
@@ -1,4 +1,4 @@
jms_serializer:
- visitors:
- xml_serialization:
- format_output: '%kernel.debug%'
+ visitors:
+ xml_serialization:
+ format_output: '%kernel.debug%'
diff --git a/tests/Application/config/sylius/1.12/packages/security.yaml b/tests/Application/config/sylius/1.12/packages/security.yaml
index 2b277f55..cb926ec4 100644
--- a/tests/Application/config/sylius/1.12/packages/security.yaml
+++ b/tests/Application/config/sylius/1.12/packages/security.yaml
@@ -113,9 +113,9 @@ security:
security: false
access_control:
- - { path: "%sylius.security.admin_regex%/_partial", role: PUBLIC_ACCESS, ips: [127.0.0.1, ::1] }
+ - { path: "%sylius.security.admin_regex%/_partial", role: PUBLIC_ACCESS, ips: [ 127.0.0.1, ::1 ] }
- { path: "%sylius.security.admin_regex%/_partial", role: ROLE_NO_ACCESS }
- - { path: "%sylius.security.shop_regex%/_partial", role: PUBLIC_ACCESS, ips: [127.0.0.1, ::1] }
+ - { path: "%sylius.security.shop_regex%/_partial", role: PUBLIC_ACCESS, ips: [ 127.0.0.1, ::1 ] }
- { path: "%sylius.security.shop_regex%/_partial", role: ROLE_NO_ACCESS }
- { path: "%sylius.security.admin_regex%/login", role: PUBLIC_ACCESS }
diff --git a/tests/Application/config/sylius/1.13/packages/jms_serializer.yaml b/tests/Application/config/sylius/1.13/packages/jms_serializer.yaml
index ed7bc613..fa43f5b6 100644
--- a/tests/Application/config/sylius/1.13/packages/jms_serializer.yaml
+++ b/tests/Application/config/sylius/1.13/packages/jms_serializer.yaml
@@ -1,4 +1,4 @@
jms_serializer:
- visitors:
- xml_serialization:
- format_output: '%kernel.debug%'
+ visitors:
+ xml_serialization:
+ format_output: '%kernel.debug%'
diff --git a/tests/Application/config/sylius/1.13/packages/security.yaml b/tests/Application/config/sylius/1.13/packages/security.yaml
index 7458c77a..6df8cb5a 100644
--- a/tests/Application/config/sylius/1.13/packages/security.yaml
+++ b/tests/Application/config/sylius/1.13/packages/security.yaml
@@ -102,9 +102,9 @@ security:
security: false
access_control:
- - { path: "%sylius.security.admin_regex%/_partial", role: PUBLIC_ACCESS, ips: [127.0.0.1, ::1] }
+ - { path: "%sylius.security.admin_regex%/_partial", role: PUBLIC_ACCESS, ips: [ 127.0.0.1, ::1 ] }
- { path: "%sylius.security.admin_regex%/_partial", role: ROLE_NO_ACCESS }
- - { path: "%sylius.security.shop_regex%/_partial", role: PUBLIC_ACCESS, ips: [127.0.0.1, ::1] }
+ - { path: "%sylius.security.shop_regex%/_partial", role: PUBLIC_ACCESS, ips: [ 127.0.0.1, ::1 ] }
- { path: "%sylius.security.shop_regex%/_partial", role: ROLE_NO_ACCESS }
- { path: "%sylius.security.admin_regex%/login", role: PUBLIC_ACCESS }
diff --git a/tests/Application/config/symfony/4.4/packages/framework.yaml b/tests/Application/config/symfony/4.4/packages/framework.yaml
index 62f82d35..4cc0d5ae 100644
--- a/tests/Application/config/symfony/4.4/packages/framework.yaml
+++ b/tests/Application/config/symfony/4.4/packages/framework.yaml
@@ -1,2 +1,2 @@
framework:
- templating: { engines: ["twig"] }
+ templating: { engines: [ "twig" ] }
diff --git a/tests/Application/gulpfile.babel.js b/tests/Application/gulpfile.babel.js
deleted file mode 100644
index 5920316f..00000000
--- a/tests/Application/gulpfile.babel.js
+++ /dev/null
@@ -1,60 +0,0 @@
-import chug from 'gulp-chug';
-import gulp from 'gulp';
-import yargs from 'yargs';
-
-const { argv } = yargs
- .options({
- rootPath: {
- description: '
path to public assets directory',
- type: 'string',
- requiresArg: true,
- required: false,
- },
- nodeModulesPath: {
- description: ' path to node_modules directory',
- type: 'string',
- requiresArg: true,
- required: false,
- },
- });
-
-const config = [
- '--rootPath',
- argv.rootPath || '../../../../../../../tests/Application/public/assets',
- '--nodeModulesPath',
- argv.nodeModulesPath || '../../../../../../../tests/Application/node_modules',
-];
-
-export const buildAdmin = function buildAdmin() {
- return gulp.src('../../vendor/sylius/sylius/src/Sylius/Bundle/AdminBundle/gulpfile.babel.js', { read: false })
- .pipe(chug({ args: config, tasks: 'build' }));
-};
-buildAdmin.description = 'Build admin assets.';
-
-export const watchAdmin = function watchAdmin() {
- return gulp.src('../../vendor/sylius/sylius/src/Sylius/Bundle/AdminBundle/gulpfile.babel.js', { read: false })
- .pipe(chug({ args: config, tasks: 'watch' }));
-};
-watchAdmin.description = 'Watch admin asset sources and rebuild on changes.';
-
-export const buildShop = function buildShop() {
- return gulp.src('../../vendor/sylius/sylius/src/Sylius/Bundle/ShopBundle/gulpfile.babel.js', { read: false })
- .pipe(chug({ args: config, tasks: 'build' }));
-};
-buildShop.description = 'Build shop assets.';
-
-export const watchShop = function watchShop() {
- return gulp.src('../../vendor/sylius/sylius/src/Sylius/Bundle/ShopBundle/gulpfile.babel.js', { read: false })
- .pipe(chug({ args: config, tasks: 'watch' }));
-};
-watchShop.description = 'Watch shop asset sources and rebuild on changes.';
-
-export const build = gulp.parallel(buildAdmin, buildShop);
-build.description = 'Build assets.';
-
-gulp.task('admin', buildAdmin);
-gulp.task('admin-watch', watchAdmin);
-gulp.task('shop', buildShop);
-gulp.task('shop-watch', watchShop);
-
-export default build;
diff --git a/tests/Application/package.json b/tests/Application/package.json
index 16de6eea..dfe32583 100644
--- a/tests/Application/package.json
+++ b/tests/Application/package.json
@@ -1,44 +1,13 @@
{
- "dependencies": {
- "babel-polyfill": "^6.26.0",
- "jquery": "^3.4.0",
- "jquery.dirtyforms": "^2.0.0",
- "lightbox2": "^2.9.0",
- "semantic-ui-css": "^2.2.0",
- "slick-carousel": "^1.8.1",
- "chart.js": "^3.7.1"
- },
- "devDependencies": {
- "@symfony/webpack-encore": "^1.6.1",
- "babel-core": "^6.26.3",
- "babel-plugin-external-helpers": "^6.22.0",
- "babel-plugin-module-resolver": "^3.1.1",
- "babel-plugin-transform-object-rest-spread": "^6.26.0",
- "babel-preset-env": "^1.7.0",
- "babel-register": "^6.26.0",
- "dedent": "^0.7.0",
- "eslint": "^4.19.1",
- "eslint-config-airbnb-base": "^12.1.0",
- "eslint-import-resolver-babel-module": "^4.0.0",
- "eslint-plugin-import": "^2.11.0",
- "fast-async": "^6.3.7",
- "merge-stream": "^1.0.0",
- "sass": "^1.50.0",
- "sass-loader": "^7.0.1",
- "upath": "^1.1.0",
- "webpack": "^5.76.1",
- "yargs": "^6.4.0"
- },
+ "license": "MIT",
"scripts": {
- "build": "encore production",
- "dev": "encore dev",
+ "build": "encore dev",
+ "build:prod": "encore production",
+ "postinstall": "semantic-ui-css-patch",
"lint": "yarn lint:js",
- "lint:js": "eslint gulpfile.babel.js"
+ "watch": "encore dev --watch"
},
- "repository": {
- "type": "git",
- "url": "git+https://github.com/Sylius/Sylius.git"
- },
- "author": "Paweł Jędrzejewski",
- "license": "MIT"
+ "devDependencies": {
+ "@sylius-ui/frontend": "^1.0"
+ }
}
diff --git a/tests/Application/src/Resources/config/doctrine/OrderItem.orm.xml b/tests/Application/src/Resources/config/doctrine/OrderItem.orm.xml
index 5f6eaa93..b87772f8 100644
--- a/tests/Application/src/Resources/config/doctrine/OrderItem.orm.xml
+++ b/tests/Application/src/Resources/config/doctrine/OrderItem.orm.xml
@@ -5,7 +5,9 @@
http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd"
>
-
+
diff --git a/tests/Application/src/Resources/config/doctrine/Product.orm.xml b/tests/Application/src/Resources/config/doctrine/Product.orm.xml
index 974072b7..d291029b 100644
--- a/tests/Application/src/Resources/config/doctrine/Product.orm.xml
+++ b/tests/Application/src/Resources/config/doctrine/Product.orm.xml
@@ -5,7 +5,8 @@
http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd"
>
-
+
diff --git a/tests/Application/templates/bundles/SyliusAdminBundle/Layout/_logo.html.twig b/tests/Application/templates/bundles/SyliusAdminBundle/Layout/_logo.html.twig
deleted file mode 100644
index 1d9fa7d0..00000000
--- a/tests/Application/templates/bundles/SyliusAdminBundle/Layout/_logo.html.twig
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
-
-
diff --git a/tests/Application/templates/bundles/SyliusAdminBundle/Order/Show/Summary/_item.html.twig b/tests/Application/templates/bundles/SyliusAdminBundle/Order/Show/Summary/_item.html.twig
index 6d94509c..3c48d043 100644
--- a/tests/Application/templates/bundles/SyliusAdminBundle/Order/Show/Summary/_item.html.twig
+++ b/tests/Application/templates/bundles/SyliusAdminBundle/Order/Show/Summary/_item.html.twig
@@ -1,38 +1 @@
-{% import "@SyliusAdmin/Common/Macro/money.html.twig" as money %}
-
-{% set orderPromotionAdjustment = constant('Sylius\\Component\\Core\\Model\\AdjustmentInterface::ORDER_PROMOTION_ADJUSTMENT') %}
-{% set itemPromotionAdjustment = constant('Sylius\\Component\\Core\\Model\\AdjustmentInterface::ORDER_ITEM_PROMOTION_ADJUSTMENT') %}
-{% set shippingAdjustment = constant('Sylius\\Component\\Core\\Model\\AdjustmentInterface::SHIPPING_ADJUSTMENT') %}
-{% set taxAdjustment = constant('Sylius\\Component\\Core\\Model\\AdjustmentInterface::TAX_ADJUSTMENT') %}
-
-{% set variant = item.variant %}
-{% set product = variant.product %}
-
-
-
- {% include '@SyliusAdmin/Product/_info.html.twig' %}
-
- {{ bitbag_render_product_bundle_order_items(item) }}
- |
-
- {{ money.format(item.unitPrice, order.currencyCode) }}
- |
-
- {{ money.format(item.discountedUnitPrice, order.currencyCode) }}
- |
-
- {{ item.quantity }}
- |
-
- {{ money.format(item.subtotal, order.currencyCode) }}
- |
-
- {{ money.format(item.getAdjustmentsTotalRecursively(orderPromotionAdjustment), order.currencyCode) }}
- |
-
- {{ money.format(item.taxTotal, order.currencyCode) }}
- |
-
- {{ money.format(item.total, order.currencyCode) }}
- |
-
+{% include '@BitBagSyliusProductBundlePlugin/Admin/Order/Show/Summary/_item.html.twig' %}
diff --git a/tests/Application/templates/bundles/SyliusAdminBundle/Product/Update/_toolbar.html.twig b/tests/Application/templates/bundles/SyliusAdminBundle/Product/Update/_toolbar.html.twig
new file mode 100644
index 00000000..ab8bbcf4
--- /dev/null
+++ b/tests/Application/templates/bundles/SyliusAdminBundle/Product/Update/_toolbar.html.twig
@@ -0,0 +1 @@
+{% include '@BitBagSyliusProductBundlePlugin/Admin/Product/Update/_toolbar.html.twig' %}
diff --git a/tests/Application/templates/bundles/SyliusAdminBundle/Product/show.html.twig b/tests/Application/templates/bundles/SyliusAdminBundle/Product/show.html.twig
new file mode 100644
index 00000000..054123dd
--- /dev/null
+++ b/tests/Application/templates/bundles/SyliusAdminBundle/Product/show.html.twig
@@ -0,0 +1 @@
+{% include '@BitBagSyliusProductBundlePlugin/Admin/Product/show.html.twig' %}
diff --git a/tests/Application/templates/bundles/SyliusShopBundle/Cart/Summary/_item.html.twig b/tests/Application/templates/bundles/SyliusShopBundle/Cart/Summary/_item.html.twig
new file mode 100644
index 00000000..36dd5077
--- /dev/null
+++ b/tests/Application/templates/bundles/SyliusShopBundle/Cart/Summary/_item.html.twig
@@ -0,0 +1 @@
+{% include '@BitBagSyliusProductBundlePlugin/Shop/Cart/Summary/_item.html.twig' %}
diff --git a/tests/Application/templates/bundles/SyliusShopBundle/Common/Order/Table/_item.html.twig b/tests/Application/templates/bundles/SyliusShopBundle/Common/Order/Table/_item.html.twig
new file mode 100644
index 00000000..271a5aac
--- /dev/null
+++ b/tests/Application/templates/bundles/SyliusShopBundle/Common/Order/Table/_item.html.twig
@@ -0,0 +1 @@
+{% include '@BitBagSyliusProductBundlePlugin/Shop/Common/Order/Table/_item.html.twig' %}
diff --git a/tests/Application/templates/bundles/SyliusShopBundle/Layout/Header/_logo.html.twig b/tests/Application/templates/bundles/SyliusShopBundle/Layout/Header/_logo.html.twig
deleted file mode 100644
index 84b8df56..00000000
--- a/tests/Application/templates/bundles/SyliusShopBundle/Layout/Header/_logo.html.twig
+++ /dev/null
@@ -1,5 +0,0 @@
-
diff --git a/tests/Behat/Context/Api/ProductBundleContext.php b/tests/Behat/Context/Api/ProductBundleContext.php
new file mode 100644
index 00000000..d408136c
--- /dev/null
+++ b/tests/Behat/Context/Api/ProductBundleContext.php
@@ -0,0 +1,155 @@
+requestFactory->customItemAction(
+ 'shop',
+ Resources::ORDERS,
+ $this->sharedStorage->get('cart_token'),
+ HttpRequest::METHOD_PATCH,
+ 'product-bundle',
+ );
+ $request->updateContent([
+ 'productCode' => $product->getCode(),
+ 'quantity' => $quantity,
+ ]);
+
+ $this->client->executeCustomRequest($request);
+ }
+
+ /**
+ * @When I add bundle :product with quantity :quantity to my cart and overwrite :oldVariant with :newVariant
+ */
+ public function iAddProductBundleToMyCartAndOverwriteVariant(
+ ProductInterface $product,
+ int $quantity,
+ string $oldVariant,
+ string $newVariant,
+ ): void {
+ $request = $this->requestFactory->customItemAction(
+ 'shop',
+ Resources::ORDERS,
+ $this->sharedStorage->get('cart_token'),
+ HttpRequest::METHOD_PATCH,
+ 'product-bundle',
+ );
+ $request->updateContent([
+ 'productCode' => $product->getCode(),
+ 'quantity' => $quantity,
+ 'overwrittenVariants' => [
+ [
+ AddProductBundleItemToCartCommandProvider::FROM => $oldVariant,
+ AddProductBundleItemToCartCommandProvider::TO => $newVariant,
+ ],
+ ],
+ ]);
+
+ $this->client->executeCustomRequest($request);
+ }
+
+ /**
+ * @When I should have bundle :product with quantity :quantity in my cart
+ */
+ public function iShouldHaveBundleWithQuantityInMyCart(ProductInterface $product, int $quantity): void
+ {
+ $response = $this->client->show(Resources::ORDERS, $this->sharedStorage->get('cart_token'));
+
+ $item = $this->responseChecker->getValue($response, 'items')[0];
+ Assert::eq($item['productName'], $product->getName());
+ Assert::eq($item['quantity'], $quantity);
+ }
+
+ /**
+ * @When I should have product :product in bundled items
+ */
+ public function iShouldHaveProductInBundledItems(ProductInterface $product): void
+ {
+ $response = $this->client->show(Resources::ORDERS, $this->sharedStorage->get('cart_token'));
+
+ $productBundleOrderItems = $this->responseChecker->getValue($response, 'items')[0]['productBundleOrderItems'];
+ foreach ($productBundleOrderItems as $item) {
+ if ($item['productVariant']['code'] === $product->getCode()) {
+ return;
+ }
+ }
+
+ throw new \InvalidArgumentException('Product not found in bundled items');
+ }
+
+ /**
+ * @When I should have product variant :productVariant in bundled items
+ */
+ public function iShouldHaveProductVariantInBundledItems(string $productVariant): void
+ {
+ $productVariant = $this->productVariantRepository->findOneBy(['code' => $productVariant]);
+ Assert::isInstanceOf($productVariant, ProductVariantInterface::class);
+
+ $response = $this->client->show(Resources::ORDERS, $this->sharedStorage->get('cart_token'));
+
+ $productBundleOrderItems = $this->responseChecker->getValue($response, 'items')[0]['productBundleOrderItems'];
+ foreach ($productBundleOrderItems as $item) {
+ if ($item['productVariant']['code'] === $productVariant->getCode()) {
+ return;
+ }
+ }
+
+ throw new \InvalidArgumentException('Product not found in bundled items');
+ }
+
+ /**
+ * @When I should not have product variant :productVariant in bundled items
+ */
+ public function iShouldNotHaveProductVariantInBundledItems(string $productVariant): void
+ {
+ $productVariant = $this->productVariantRepository->findOneBy(['code' => $productVariant]);
+ Assert::isInstanceOf($productVariant, ProductVariantInterface::class);
+
+ $response = $this->client->show(Resources::ORDERS, $this->sharedStorage->get('cart_token'));
+
+ $productBundleOrderItems = $this->responseChecker->getValue($response, 'items')[0]['productBundleOrderItems'];
+ foreach ($productBundleOrderItems as $item) {
+ if ($item['productVariant']['code'] === $productVariant->getCode()) {
+ throw new \InvalidArgumentException(\sprintf('Product variant %s found in bundled items', $productVariant->getName()));
+ }
+ }
+ }
+}
diff --git a/tests/Behat/Context/Setup/ProductBundleContext.php b/tests/Behat/Context/Setup/ProductBundleContext.php
index ab406ff0..6b689bd2 100644
--- a/tests/Behat/Context/Setup/ProductBundleContext.php
+++ b/tests/Behat/Context/Setup/ProductBundleContext.php
@@ -14,16 +14,22 @@
use Behat\Behat\Context\Context;
use BitBag\SyliusProductBundlePlugin\Entity\ProductBundleItemInterface;
use BitBag\SyliusProductBundlePlugin\Entity\ProductInterface;
+use BitBag\SyliusProductBundlePlugin\Factory\OrderItemFactoryInterface;
+use BitBag\SyliusProductBundlePlugin\Factory\ProductBundleOrderItemFactoryInterface;
use BitBag\SyliusProductBundlePlugin\Factory\ProductFactory;
+use BitBag\SyliusProductBundlePlugin\Repository\ProductBundleRepositoryInterface;
use Doctrine\ORM\EntityManagerInterface;
use Sylius\Behat\Service\SharedStorageInterface;
use Sylius\Component\Core\Formatter\StringInflector;
use Sylius\Component\Core\Model\ChannelInterface;
use Sylius\Component\Core\Model\ChannelPricingInterface;
+use Sylius\Component\Core\Model\OrderInterface;
use Sylius\Component\Core\Model\ProductTaxonInterface;
use Sylius\Component\Core\Model\ProductVariantInterface;
use Sylius\Component\Core\Model\TaxonInterface;
use Sylius\Component\Core\Repository\ProductRepositoryInterface;
+use Sylius\Component\Order\Modifier\OrderItemQuantityModifierInterface;
+use Sylius\Component\Order\Modifier\OrderModifierInterface;
use Sylius\Component\Product\Generator\SlugGeneratorInterface;
use Sylius\Component\Product\Resolver\ProductVariantResolverInterface;
use Sylius\Component\Resource\Factory\FactoryInterface;
@@ -31,16 +37,22 @@
final class ProductBundleContext implements Context
{
public function __construct(
- private SharedStorageInterface $sharedStorage,
- private FactoryInterface $taxonFactory,
- private ProductRepositoryInterface $productRepository,
- private FactoryInterface $productTaxonFactory,
- private EntityManagerInterface $productTaxonManager,
- private ProductFactory $productFactory,
- private FactoryInterface $productBundleItemFactory,
- private FactoryInterface $channelPricingFactory,
- private ProductVariantResolverInterface $productVariantResolver,
- private SlugGeneratorInterface $slugGenerator,
+ private readonly SharedStorageInterface $sharedStorage,
+ private readonly FactoryInterface $taxonFactory,
+ private readonly ProductRepositoryInterface $productRepository,
+ private readonly FactoryInterface $productTaxonFactory,
+ private readonly EntityManagerInterface $productTaxonManager,
+ private readonly ProductFactory $productFactory,
+ private readonly FactoryInterface $productBundleItemFactory,
+ private readonly FactoryInterface $channelPricingFactory,
+ private readonly ProductVariantResolverInterface $productVariantResolver,
+ private readonly SlugGeneratorInterface $slugGenerator,
+ private readonly EntityManagerInterface $objectManager,
+ private readonly OrderItemQuantityModifierInterface $orderItemQuantityModifier,
+ private readonly ProductBundleOrderItemFactoryInterface $productBundleOrderItemFactory,
+ private readonly OrderModifierInterface $orderModifier,
+ private readonly OrderItemFactoryInterface $cartItemFactory,
+ private readonly ProductBundleRepositoryInterface $productBundleRepository,
) {
}
@@ -149,4 +161,37 @@ private function createProduct(
return $product;
}
+
+ /**
+ * @When the customer bought a single bundle :product
+ */
+ public function theCustomerBoughtBundle(ProductInterface $product): void
+ {
+ /** @var OrderInterface|null $cart */
+ $cart = $this->sharedStorage->get('order');
+ /** @var ProductVariantInterface|null $variant */
+ $variant = $product->getVariants()->first();
+
+ $cartItem = $this->cartItemFactory->createWithVariant($variant);
+ $this->orderItemQuantityModifier->modify($cartItem, 1);
+
+ foreach ($product->getProductBundle()->getProductBundleItems() as $bundleItem) {
+ $productBundleOrderItem = $this->productBundleOrderItemFactory->createFromProductBundleItem($bundleItem);
+ $cartItem->addProductBundleOrderItem($productBundleOrderItem);
+ }
+
+ $this->orderModifier->addToOrder($cart, $cartItem);
+
+ $this->objectManager->flush();
+ }
+
+ /**
+ * @Given product bundle :productBundleCode is packed
+ */
+ public function productBundleIsPacked(string $productBundleCode): void
+ {
+ $bundle = $this->productBundleRepository->findOneByProductCode($productBundleCode);
+ $bundle->setIsPackedProduct(true);
+ $this->objectManager->flush();
+ }
}
diff --git a/tests/Behat/Context/Ui/ProductBundleContext.php b/tests/Behat/Context/Ui/ProductBundleContext.php
index 43058dc5..5087e04d 100644
--- a/tests/Behat/Context/Ui/ProductBundleContext.php
+++ b/tests/Behat/Context/Ui/ProductBundleContext.php
@@ -12,13 +12,21 @@
namespace Tests\BitBag\SyliusProductBundlePlugin\Behat\Context\Ui;
use Behat\Behat\Context\Context;
+use BitBag\SyliusProductBundlePlugin\Entity\ProductBundleItemInterface;
+use BitBag\SyliusProductBundlePlugin\Entity\ProductInterface;
use Sylius\Component\Core\Model\ChannelInterface;
+use Sylius\Component\Core\Repository\ProductRepositoryInterface;
use Tests\BitBag\SyliusProductBundlePlugin\Behat\Page\Admin\CreateBundledProductPageInterface;
+use Tests\BitBag\SyliusProductBundlePlugin\Behat\Page\Shop\BundledProductsListPageInterface;
+use Webmozart\Assert\Assert;
class ProductBundleContext implements Context
{
public function __construct(
private CreateBundledProductPageInterface $createBundledProductPage,
+ private ProductRepositoryInterface $productRepository,
+ private BundledProductsListPageInterface $summaryPage,
+ private BundledProductsListPageInterface $orderShowPage,
) {
}
@@ -90,4 +98,67 @@ public function iAddProductsToBundledProduct(...$productsNames)
{
$this->createBundledProductPage->addProductsToBundle($productsNames);
}
+
+ /**
+ * @When I add product :firstProductName with quantity :firstQuantity and :secondProductName with quantity :secondQuantity to the bundle
+ */
+ public function iAddProductsWithQuantitiesToBundledProduct(string $firstProductName, string $secondProductName, int $firstQuantity, int $secondQuantity)
+ {
+ $this->createBundledProductPage->addProductsToBundle([$firstProductName, $secondProductName], [$firstQuantity, $secondQuantity]);
+ }
+
+ /**
+ * @When there should be a :bundleName bundle containing :productName with quantity :quantity
+ */
+ public function theProductBundleShouldContainProductWithQuantity(string $bundleCode, string $productName, int $quantity): void
+ {
+ /** @var ProductInterface $product */
+ $product = $this->productRepository->findOneBy(['code' => $bundleCode]);
+
+ Assert::notNull($product->getProductBundle());
+
+ $bundleItems = $product->getProductBundle()->getProductBundleItems();
+ /** @var ProductBundleItemInterface $item */
+ foreach ($bundleItems as $item) {
+ if ($item->getProductVariant()->getProduct()->getName() === $productName) {
+ Assert::same($item->getQuantity(), $quantity);
+
+ return;
+ }
+ }
+
+ throw new \InvalidArgumentException(sprintf('Product "%s" not found in bundle "%s"', $productName, $bundleCode));
+ }
+
+ /**
+ * @When there should be bundled products listed
+ */
+ public function thereShouldBeBundledProductsListed(): void
+ {
+ Assert::true($this->summaryPage->hasBundledProductsList());
+ }
+
+ /**
+ * @When the list should contain :productName
+ */
+ public function thereShouldBeAProductOnTheList(string $productName): void
+ {
+ Assert::true($this->summaryPage->hasBundledProduct($productName));
+ }
+
+ /**
+ * @When there should be bundled products listed in order details
+ */
+ public function thereShouldBeBundledProductsListedOnOrderShowPage(): void
+ {
+ Assert::true($this->orderShowPage->hasBundledProductsList());
+ }
+
+ /**
+ * @When the list should contain :productName in order details
+ */
+ public function thereShouldBeAProductOnTheListOnOrderShowPage(string $productName): void
+ {
+ Assert::true($this->orderShowPage->hasBundledProduct($productName));
+ }
}
diff --git a/tests/Behat/Page/Admin/CreateBundledProductPage.php b/tests/Behat/Page/Admin/CreateBundledProductPage.php
index eb2f8ae0..23067825 100644
--- a/tests/Behat/Page/Admin/CreateBundledProductPage.php
+++ b/tests/Behat/Page/Admin/CreateBundledProductPage.php
@@ -60,13 +60,13 @@ public function specifyOriginalPrice(ChannelInterface $channel, int $originalPri
$this->getElement('original_price', ['%channelCode%' => $channel->getCode()])->setValue($originalPrice);
}
- public function addProductsToBundle(array $productsNames): void
+ public function addProductsToBundle(array $productsNames, array $quantites = []): void
{
$this->clickTabIfItsNotActive('bundle');
$productCounter = 0;
- foreach ($productsNames as $productName) {
+ foreach ($productsNames as $i => $productName) {
$addSelector = $this->getElement('add_product_to_bundle_button');
$addSelector->click();
$addSelector->waitFor(5, fn () => $this->hasElement('product_selector_dropdown'));
@@ -80,7 +80,8 @@ public function addProductsToBundle(array $productsNames): void
]);
$item->click();
- $this->getElement('product_selector_quantity', ['%productCounter%' => $productCounter])->setValue('1');
+ $quantity = array_key_exists($i, $quantites) ? (string) $quantites[$i] : '1';
+ $this->getElement('product_selector_quantity', ['%productCounter%' => $productCounter])->setValue($quantity);
++$productCounter;
}
diff --git a/tests/Behat/Page/Shop/BundledProductsListPageInterface.php b/tests/Behat/Page/Shop/BundledProductsListPageInterface.php
new file mode 100644
index 00000000..971d19aa
--- /dev/null
+++ b/tests/Behat/Page/Shop/BundledProductsListPageInterface.php
@@ -0,0 +1,19 @@
+hasElement('products_in_bundle');
+ }
+
+ public function hasBundledProduct(string $productName): bool
+ {
+ return $this->hasElement('bundled_product', ['%productName%' => $productName]);
+ }
+
+ protected function getDefinedElements(): array
+ {
+ return array_merge(parent::getDefinedElements(), [
+ 'products_in_bundle' => '#sylius-order > tbody > tr:nth-child(2) > td > div > div.title.bundled-items-header > strong:contains("Products in bundle")',
+ 'bundled_product' => '#sylius-order > tbody > tr:nth-child(2) > td > div > div.content.bundled-items > div > div > div > div:contains("%productName%")',
+ ]);
+ }
+}
diff --git a/tests/Behat/Page/Shop/SummaryPage.php b/tests/Behat/Page/Shop/SummaryPage.php
new file mode 100644
index 00000000..8acb33fd
--- /dev/null
+++ b/tests/Behat/Page/Shop/SummaryPage.php
@@ -0,0 +1,35 @@
+hasElement('products_in_bundle');
+ }
+
+ public function hasBundledProduct(string $productName): bool
+ {
+ return $this->hasElement('bundled_product', ['%productName%' => $productName]);
+ }
+
+ protected function getDefinedElements(): array
+ {
+ return array_merge(parent::getDefinedElements(), [
+ 'products_in_bundle' => '#sylius-cart-items > tbody > tr:nth-child(2) > td > div > div.title.bundled-items-header > strong:contains("Products in bundle")',
+ 'bundled_product' => '#sylius-cart-items > tbody > tr:nth-child(2) > td > div > div.content.bundled-items > div > div > div > div:contains("%productName%")',
+ ]);
+ }
+}
diff --git a/tests/Behat/Resources/services.yml b/tests/Behat/Resources/services.yml
index f6ae41e7..25ae9378 100644
--- a/tests/Behat/Resources/services.yml
+++ b/tests/Behat/Resources/services.yml
@@ -14,6 +14,12 @@ services:
- '@sylius.factory.channel_pricing'
- '@sylius.product_variant_resolver.default'
- '@sylius.generator.slug'
+ - '@doctrine.orm.entity_manager'
+ - '@sylius.order_item_quantity_modifier'
+ - '@bitbag_sylius_product_bundle.custom_factory.product_bundle_order_item'
+ - '@sylius.order_modifier'
+ - '@bitbag_sylius_product_bundle.custom_factory.order_item'
+ - '@bitbag_sylius_product_bundle.repository.product_bundle'
bitbag_sylius_product_bundle_plugin.behat.page.create_bundled_product_page:
class: Tests\BitBag\SyliusProductBundlePlugin\Behat\Page\Admin\CreateBundledProductPage
@@ -22,7 +28,29 @@ services:
arguments:
- 'bitbag_product_bundle_admin_product_create_bundle'
+ bitbag_sylius_product_bundle_plugin.behat.page.summary_page:
+ class: Tests\BitBag\SyliusProductBundlePlugin\Behat\Page\Shop\SummaryPage
+ parent: sylius.behat.page.shop.cart_summary
+ public: false
+
+ bitbag_sylius_product_bundle_plugin.behat.page.account.order_show_page:
+ class: Tests\BitBag\SyliusProductBundlePlugin\Behat\Page\Shop\OrderShowPage
+ parent: sylius.behat.page.shop.account.order.show
+ public: false
+
bitbag_sylius_product_bundle_plugin.behat.context.ui.product_bundle:
class: Tests\BitBag\SyliusProductBundlePlugin\Behat\Context\Ui\ProductBundleContext
arguments:
- '@bitbag_sylius_product_bundle_plugin.behat.page.create_bundled_product_page'
+ - '@sylius.repository.product'
+ - '@bitbag_sylius_product_bundle_plugin.behat.page.summary_page'
+ - '@bitbag_sylius_product_bundle_plugin.behat.page.account.order_show_page'
+
+ bitbag_sylius_product_bundle_plugin.behat.context.api.product_bundle:
+ class: Tests\BitBag\SyliusProductBundlePlugin\Behat\Context\Api\ProductBundleContext
+ arguments:
+ - '@sylius.behat.shared_storage'
+ - '@sylius.behat.api_platform_client.shop'
+ - '@sylius.behat.request_factory'
+ - '@Sylius\Behat\Client\ResponseCheckerInterface'
+ - '@sylius.repository.product_variant'
diff --git a/tests/Behat/Resources/suites.yml b/tests/Behat/Resources/suites.yml
index 70c3f6c8..56af2b95 100644
--- a/tests/Behat/Resources/suites.yml
+++ b/tests/Behat/Resources/suites.yml
@@ -4,24 +4,29 @@ default:
contexts:
- sylius.behat.context.hook.doctrine_orm
- - sylius.behat.context.transform.lexical
- - sylius.behat.context.transform.product
- - sylius.behat.context.transform.address
- - sylius.behat.context.transform.payment
- - sylius.behat.context.transform.shipping_method
- - sylius.behat.context.transform.zone
- - sylius.behat.context.transform.locale
- - sylius.behat.context.transform.channel
-
- - sylius.behat.context.setup.currency
- - sylius.behat.context.setup.locale
+ - sylius.behat.context.setup.admin_security
- sylius.behat.context.setup.channel
+ - sylius.behat.context.setup.currency
- sylius.behat.context.setup.customer
- - sylius.behat.context.setup.shop_security
+ - sylius.behat.context.setup.locale
+ - sylius.behat.context.setup.payment
- sylius.behat.context.setup.product
- - sylius.behat.context.setup.admin_security
+ - sylius.behat.context.setup.promotion
+ - sylius.behat.context.setup.taxation
- sylius.behat.context.setup.shipping
- - sylius.behat.context.setup.payment
+ - sylius.behat.context.setup.shop_security
+
+ - sylius.behat.context.transform.address
+ - sylius.behat.context.transform.channel
+ - sylius.behat.context.transform.lexical
+ - sylius.behat.context.transform.locale
+ - sylius.behat.context.transform.payment
+ - sylius.behat.context.transform.product
+ - sylius.behat.context.transform.promotion
+ - sylius.behat.context.transform.shared_storage
+ - sylius.behat.context.transform.shipping_method
+ - sylius.behat.context.transform.tax_category
+ - sylius.behat.context.transform.zone
- sylius.behat.context.ui.shop.cart
- sylius.behat.context.ui.shop.checkout.addressing
@@ -30,7 +35,75 @@ default:
- sylius.behat.context.ui.shop.checkout.thank_you
- sylius.behat.context.ui.admin.notification
+ - bitbag_sylius_product_bundle_plugin.behat.context.ui.product_bundle
- bitbag_sylius_product_bundle_plugin.behat.context.setup.product_bundle
+
+ filters:
+ tags: "@bundled_product&&@ui&&~@shop"
+
+ shop_bundled_product:
+ contexts:
+ - sylius.behat.context.hook.doctrine_orm
+
+ - sylius.behat.context.setup.channel
+ - sylius.behat.context.setup.customer
+ - sylius.behat.context.setup.order
+ - sylius.behat.context.setup.payment
+ - sylius.behat.context.setup.product
+ - sylius.behat.context.setup.shipping
+ - sylius.behat.context.setup.shop_security
+
+ - sylius.behat.context.transform.address
+ - sylius.behat.context.transform.customer
+ - sylius.behat.context.transform.lexical
+ - sylius.behat.context.transform.order
+ - sylius.behat.context.transform.payment
+ - sylius.behat.context.transform.product
+ - sylius.behat.context.transform.shared_storage
+ - sylius.behat.context.transform.shipping_method
+
+ - sylius.behat.context.ui.shop.account
+ - sylius.behat.context.ui.shop.cart
+
- bitbag_sylius_product_bundle_plugin.behat.context.ui.product_bundle
+ - bitbag_sylius_product_bundle_plugin.behat.context.setup.product_bundle
+
+ filters:
+ tags: "@bundled_product&&@ui&&@shop"
+
+ api_bundled_product:
+ contexts:
+ - sylius.behat.context.hook.doctrine_orm
+
+ - sylius.behat.context.setup.admin_security
+ - sylius.behat.context.setup.channel
+ - sylius.behat.context.setup.currency
+ - sylius.behat.context.setup.customer
+ - sylius.behat.context.setup.locale
+ - sylius.behat.context.setup.payment
+ - sylius.behat.context.setup.product
+ - sylius.behat.context.setup.promotion
+ - sylius.behat.context.setup.taxation
+ - sylius.behat.context.setup.shipping
+ - sylius.behat.context.setup.shop_security
+
+ - sylius.behat.context.transform.address
+ - sylius.behat.context.transform.channel
+ - sylius.behat.context.transform.lexical
+ - sylius.behat.context.transform.locale
+ - sylius.behat.context.transform.payment
+ - sylius.behat.context.transform.product
+ - sylius.behat.context.transform.promotion
+ - sylius.behat.context.transform.shared_storage
+ - sylius.behat.context.transform.shipping_method
+ - sylius.behat.context.transform.tax_category
+ - sylius.behat.context.transform.zone
+
+ - sylius.behat.context.api.shop.cart
+ - sylius.behat.context.api.shop.checkout
+
+ - bitbag_sylius_product_bundle_plugin.behat.context.api.product_bundle
+ - bitbag_sylius_product_bundle_plugin.behat.context.setup.product_bundle
+
filters:
- tags: "@bundled_product"
+ tags: "@bundled_product&&@api"
diff --git a/tests/Unit/DataTransformer/AddProductBundleToCartDtoDataTransformerTest.php b/tests/Unit/DataTransformer/AddProductBundleToCartDtoDataTransformerTest.php
index f4ec9ad8..a7fc87ec 100644
--- a/tests/Unit/DataTransformer/AddProductBundleToCartDtoDataTransformerTest.php
+++ b/tests/Unit/DataTransformer/AddProductBundleToCartDtoDataTransformerTest.php
@@ -7,19 +7,17 @@
* an email on hello@bitbag.io.
*/
-/*
- * This file was created by developers working at BitBag
- * Do you need more information about us and what we do? Visit our https://bitbag.io website!
- * We are hiring developers from all over the world. Join us and start your new, exciting adventure and become part of us: https://bitbag.io/career
- */
-
declare(strict_types=1);
namespace Tests\BitBag\SyliusProductBundlePlugin\Unit\DataTransformer;
+use BitBag\SyliusProductBundlePlugin\Command\AddProductBundleItemToCartCommandInterface;
use BitBag\SyliusProductBundlePlugin\Command\AddProductBundleToCartCommand;
use BitBag\SyliusProductBundlePlugin\DataTransformer\AddProductBundleToCartDtoDataTransformer;
use BitBag\SyliusProductBundlePlugin\Dto\Api\AddProductBundleToCartDto;
+use BitBag\SyliusProductBundlePlugin\Provider\AddProductBundleItemToCartCommandProviderInterface;
+use Doctrine\Common\Collections\ArrayCollection;
+use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Tests\BitBag\SyliusProductBundlePlugin\Unit\MotherObject\Api\AddProductBundleToCartDtoMother;
use Tests\BitBag\SyliusProductBundlePlugin\Unit\MotherObject\OrderMother;
@@ -28,6 +26,16 @@
final class AddProductBundleToCartDtoDataTransformerTest extends TestCase
{
+ private AddProductBundleItemToCartCommandProviderInterface|MockObject $provider;
+
+ private AddProductBundleItemToCartCommandInterface|MockObject $addProductBundleItemToCartCommand;
+
+ public function setUp(): void
+ {
+ $this->provider = $this->createMock(AddProductBundleItemToCartCommandProviderInterface::class);
+ $this->addProductBundleItemToCartCommand = $this->createMock(AddProductBundleItemToCartCommandInterface::class);
+ }
+
public function testThrowErrorIfObjectIsNotInstanceOfAddProductBundleToCartDto(): void
{
$this->expectException(InvalidArgumentException::class);
@@ -36,7 +44,8 @@ public function testThrowErrorIfObjectIsNotInstanceOfAddProductBundleToCartDto()
);
$object = new \stdClass();
- $dataTransformer = new AddProductBundleToCartDtoDataTransformer();
+ $this->provider->expects(self::never())->method(self::anything());
+ $dataTransformer = new AddProductBundleToCartDtoDataTransformer($this->provider);
$dataTransformer->transform($object, '');
}
@@ -47,7 +56,8 @@ public function testThrowIfObjectToPopulateDoesntExist(): void
$this->expectExceptionMessage(TypeExceptionMessage::EXPECTED_VALUE_OTHER_THAN_NULL);
$object = AddProductBundleToCartDtoMother::create('PRODUCT_CODE');
- $dataTransformer = new AddProductBundleToCartDtoDataTransformer();
+ $this->provider->expects(self::never())->method(self::anything());
+ $dataTransformer = new AddProductBundleToCartDtoDataTransformer($this->provider);
$dataTransformer->transform($object, '');
}
@@ -58,7 +68,16 @@ public function testReturnAddProductBundleToCart(): void
$context = [
AddProductBundleToCartDtoDataTransformer::OBJECT_TO_POPULATE => OrderMother::createWithId(3),
];
- $dataTransformer = new AddProductBundleToCartDtoDataTransformer();
+
+ $addProductBundleItemToCartCommands = new ArrayCollection([$this->addProductBundleItemToCartCommand]);
+
+ $this->provider
+ ->expects(self::once())
+ ->method('provide')
+ ->with('PRODUCT_CODE', [])
+ ->willReturn($addProductBundleItemToCartCommands);
+
+ $dataTransformer = new AddProductBundleToCartDtoDataTransformer($this->provider);
$addProductBundleToCartCommand = $dataTransformer->transform($object, '', $context);
@@ -66,5 +85,6 @@ public function testReturnAddProductBundleToCart(): void
self::assertSame('PRODUCT_CODE', $addProductBundleToCartCommand->getProductCode());
self::assertSame(2, $addProductBundleToCartCommand->getQuantity());
self::assertSame(3, $addProductBundleToCartCommand->getOrderId());
+ self::assertSame($addProductBundleItemToCartCommands, $addProductBundleToCartCommand->getProductBundleItems());
}
}
diff --git a/tests/Unit/EventListener/AddProductToProductBundleWhenEditNormalProductEventListenerTest.php b/tests/Unit/EventListener/AddProductToProductBundleWhenEditNormalProductEventListenerTest.php
new file mode 100644
index 00000000..7f8fb7ab
--- /dev/null
+++ b/tests/Unit/EventListener/AddProductToProductBundleWhenEditNormalProductEventListenerTest.php
@@ -0,0 +1,110 @@
+instance = new AddProductToProductBundleWhenEditNormalProductEventListener();
+ $this->resourceControllerEvent = $this->createMock(ResourceControllerEvent::class);
+ $this->product = $this->createMock(ProductInterface::class);
+ $this->productBundle = $this->createMock(ProductBundleInterface::class);
+ }
+
+ public function testAddProductToProductBundle(): void
+ {
+ $this->productBundle
+ ->expects(self::once())
+ ->method('getProduct')
+ ->willReturn(null);
+
+ $this->product
+ ->expects(self::exactly(3))
+ ->method('getProductBundle')
+ ->willReturn($this->productBundle);
+
+ $this->productBundle
+ ->expects(self::once())
+ ->method('setProduct')
+ ->with($this->product);
+
+ $this->resourceControllerEvent
+ ->expects(self::once())
+ ->method('getSubject')
+ ->willReturn($this->product);
+
+ $this->instance->addProductToProductBundle($this->resourceControllerEvent);
+ }
+
+ public function testWillNotAddProductToProductBundleIfProductHasBundle(): void
+ {
+ $this->productBundle
+ ->expects(self::never())
+ ->method('getProduct');
+
+ $this->product
+ ->expects(self::once())
+ ->method('getProductBundle')
+ ->willReturn(null);
+
+ $this->productBundle
+ ->expects(self::never())
+ ->method('setProduct');
+
+ $this->resourceControllerEvent
+ ->expects(self::once())
+ ->method('getSubject')
+ ->willReturn($this->product);
+
+ $this->instance->addProductToProductBundle($this->resourceControllerEvent);
+ }
+
+ public function testWillNotAddProductToProductBundleIfProductBundleHasProduct(): void
+ {
+ $this->productBundle
+ ->expects(self::once())
+ ->method('getProduct')
+ ->willReturn($this->product);
+
+ $this->product
+ ->expects(self::exactly(2))
+ ->method('getProductBundle')
+ ->willReturn($this->productBundle);
+
+ $this->productBundle
+ ->expects(self::never())
+ ->method('setProduct');
+
+ $this->resourceControllerEvent
+ ->expects(self::once())
+ ->method('getSubject')
+ ->willReturn($this->product);
+
+ $this->instance->addProductToProductBundle($this->resourceControllerEvent);
+ }
+}
diff --git a/tests/Unit/Factory/AddProductBundleItemToCartCommandFactoryTest.php b/tests/Unit/Factory/AddProductBundleItemToCartCommandFactoryTest.php
index 2a3f0764..e77b6425 100644
--- a/tests/Unit/Factory/AddProductBundleItemToCartCommandFactoryTest.php
+++ b/tests/Unit/Factory/AddProductBundleItemToCartCommandFactoryTest.php
@@ -11,7 +11,7 @@
namespace Tests\BitBag\SyliusProductBundlePlugin\Unit\Factory;
-use BitBag\SyliusProductBundlePlugin\Command\AddProductBundleItemToCartCommand;
+use BitBag\SyliusProductBundlePlugin\Command\AddProductBundleItemToCartCommandInterface;
use BitBag\SyliusProductBundlePlugin\Factory\AddProductBundleItemToCartCommandFactory;
use PHPUnit\Framework\TestCase;
use Tests\BitBag\SyliusProductBundlePlugin\Unit\MotherObject\ProductBundleItemMother;
@@ -25,6 +25,6 @@ public function testCreateAddProductBundleItemToCartCommand(): void
$factory = new AddProductBundleItemToCartCommandFactory();
$command = $factory->createNew($productBundleItem);
- self::assertInstanceOf(AddProductBundleItemToCartCommand::class, $command);
+ self::assertInstanceOf(AddProductBundleItemToCartCommandInterface::class, $command);
}
}
diff --git a/tests/Unit/Factory/AddProductBundleToCartCommandFactoryTest.php b/tests/Unit/Factory/AddProductBundleToCartCommandFactoryTest.php
index 4df89fd4..7e4c0bb3 100644
--- a/tests/Unit/Factory/AddProductBundleToCartCommandFactoryTest.php
+++ b/tests/Unit/Factory/AddProductBundleToCartCommandFactoryTest.php
@@ -11,8 +11,10 @@
namespace Tests\BitBag\SyliusProductBundlePlugin\Unit\Factory;
+use BitBag\SyliusProductBundlePlugin\Command\AddProductBundleItemToCartCommandInterface;
use BitBag\SyliusProductBundlePlugin\Command\AddProductBundleToCartCommand;
use BitBag\SyliusProductBundlePlugin\Factory\AddProductBundleToCartCommandFactory;
+use Doctrine\Common\Collections\ArrayCollection;
use PHPUnit\Framework\TestCase;
use Tests\BitBag\SyliusProductBundlePlugin\Unit\MotherObject\AddProductBundleToCartDtoMother;
@@ -26,13 +28,17 @@ final class AddProductBundleToCartCommandFactoryTest extends TestCase
public function testCreateAddProductBundleToCartCommandObject(): void
{
+ $addProductBundleItemToCartCommand = $this->createMock(AddProductBundleItemToCartCommandInterface::class);
+ $commands = new ArrayCollection([$addProductBundleItemToCartCommand]);
+
$factory = new AddProductBundleToCartCommandFactory();
- $command = $factory->createNew(self::ORDER_ID, self::PRODUCT_CODE, self::QUANTITY);
+ $command = $factory->createNew(self::ORDER_ID, self::PRODUCT_CODE, self::QUANTITY, $commands);
self::assertInstanceOf(AddProductBundleToCartCommand::class, $command);
self::assertEquals(self::ORDER_ID, $command->getOrderId());
self::assertEquals(self::PRODUCT_CODE, $command->getProductCode());
self::assertEquals(self::QUANTITY, $command->getQuantity());
+ self::assertEquals($commands, $command->getProductBundleItems());
}
public function testCreateAddProductBundleToCartCommandObjectFromDto(): void
diff --git a/tests/Unit/Handler/AddProductBundleToCartHandler/CartProcessorTest.php b/tests/Unit/Handler/AddProductBundleToCartHandler/CartProcessorTest.php
index 3a492db4..64bea086 100644
--- a/tests/Unit/Handler/AddProductBundleToCartHandler/CartProcessorTest.php
+++ b/tests/Unit/Handler/AddProductBundleToCartHandler/CartProcessorTest.php
@@ -11,11 +11,10 @@
namespace Tests\BitBag\SyliusProductBundlePlugin\Unit\Handler\AddProductBundleToCartHandler;
+use BitBag\SyliusProductBundlePlugin\Command\AddProductBundleItemToCartCommandInterface;
use BitBag\SyliusProductBundlePlugin\Entity\OrderItemInterface;
use BitBag\SyliusProductBundlePlugin\Entity\ProductBundle;
use BitBag\SyliusProductBundlePlugin\Entity\ProductBundleInterface;
-use BitBag\SyliusProductBundlePlugin\Entity\ProductBundleItem;
-use BitBag\SyliusProductBundlePlugin\Entity\ProductBundleItemInterface;
use BitBag\SyliusProductBundlePlugin\Entity\ProductBundleOrderItem;
use BitBag\SyliusProductBundlePlugin\Entity\ProductBundleOrderItemInterface;
use BitBag\SyliusProductBundlePlugin\Entity\ProductInterface;
@@ -23,6 +22,7 @@
use BitBag\SyliusProductBundlePlugin\Factory\ProductBundleOrderItemFactoryInterface;
use BitBag\SyliusProductBundlePlugin\Handler\AddProductBundleToCartHandler\CartProcessor;
use BitBag\SyliusProductBundlePlugin\Handler\AddProductBundleToCartHandler\CartProcessorInterface;
+use Doctrine\Common\Collections\ArrayCollection;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Sylius\Component\Core\Model\ProductVariant;
@@ -37,17 +37,15 @@
final class CartProcessorTest extends TestCase
{
- /** @var mixed|MockObject|OrderItemQuantityModifierInterface */
- private $orderItemQuantityModifier;
+ private OrderItemQuantityModifierInterface|MockObject $orderItemQuantityModifier;
- /** @var ProductBundleOrderItemFactoryInterface|mixed|MockObject */
- private $productBundleOrderItemFactory;
+ private ProductBundleOrderItemFactoryInterface|MockObject $productBundleOrderItemFactory;
- /** @var mixed|MockObject|OrderModifierInterface */
- private $orderModifier;
+ private OrderModifierInterface|MockObject $orderModifier;
- /** @var OrderItemFactoryInterface|mixed|MockObject */
- private $cartItemFactory;
+ private OrderItemFactoryInterface|MockObject $cartItemFactory;
+
+ private AddProductBundleItemToCartCommandInterface|MockObject $addProductBundleItemToCartCommand;
protected function setUp(): void
{
@@ -55,6 +53,7 @@ protected function setUp(): void
$this->productBundleOrderItemFactory = $this->createMock(ProductBundleOrderItemFactoryInterface::class);
$this->orderModifier = $this->createMock(OrderModifierInterface::class);
$this->cartItemFactory = $this->createMock(OrderItemFactoryInterface::class);
+ $this->addProductBundleItemToCartCommand = $this->createMock(AddProductBundleItemToCartCommandInterface::class);
}
public function testThrowExceptionIfQuantityNotGreaterThanZero(): void
@@ -65,7 +64,7 @@ public function testThrowExceptionIfQuantityNotGreaterThanZero(): void
$productBundle = $this->createProductBundle();
$processor = $this->createProcessor();
- $processor->process($cart, $productBundle, 0);
+ $processor->process($cart, $productBundle, 0, new ArrayCollection());
}
public function testThrowExceptionIfProductIsNull(): void
@@ -76,7 +75,7 @@ public function testThrowExceptionIfProductIsNull(): void
$productBundle = $this->createProductBundle();
$processor = $this->createProcessor();
- $processor->process($cart, $productBundle, 1);
+ $processor->process($cart, $productBundle, 1, new ArrayCollection());
}
public function testThrowExceptionIfProductHasNoVariant(): void
@@ -87,7 +86,7 @@ public function testThrowExceptionIfProductHasNoVariant(): void
$productBundle = $this->createProductBundleWithProduct();
$processor = $this->createProcessor();
- $processor->process($cart, $productBundle, 1);
+ $processor->process($cart, $productBundle, 1, new ArrayCollection());
}
public function testCreateCartItem(): void
@@ -103,7 +102,7 @@ public function testCreateCartItem(): void
;
$processor = $this->createProcessor();
- $processor->process($cart, $productBundle, 2);
+ $processor->process($cart, $productBundle, 2, new ArrayCollection([$this->addProductBundleItemToCartCommand]));
}
public function testModifyCartItemQuantity(): void
@@ -124,13 +123,13 @@ public function testModifyCartItemQuantity(): void
;
$processor = $this->createProcessor();
- $processor->process($cart, $productBundle, 2);
+ $processor->process($cart, $productBundle, 2, new ArrayCollection([$this->addProductBundleItemToCartCommand]));
}
public function testCreateBundleOrderItemsFromBundleItems(): void
{
- $bundleItem1 = $this->createProductBundleItem();
- $bundleItem2 = $this->createProductBundleItem();
+ $addBundleItemToCartCommand1 = $this->createMock(AddProductBundleItemToCartCommandInterface::class);
+ $addBundleItemToCartCommand2 = $this->createMock(AddProductBundleItemToCartCommandInterface::class);
$productBundleOrderItem1 = $this->createProductBundleOrderItem();
$productBundleOrderItem2 = $this->createProductBundleOrderItem();
@@ -138,8 +137,6 @@ public function testCreateBundleOrderItemsFromBundleItems(): void
$cart = $this->createCart();
$product = $this->createProductWithVariant();
$productBundle = $this->createProductBundleWithProduct($product);
- $productBundle->addProductBundleItem($bundleItem1);
- $productBundle->addProductBundleItem($bundleItem2);
$cartItem = $this->createMock(OrderItemInterface::class);
$cartItem->expects(self::exactly(2))
@@ -152,13 +149,13 @@ public function testCreateBundleOrderItemsFromBundleItems(): void
->willReturn($cartItem)
;
$this->productBundleOrderItemFactory->expects(self::exactly(2))
- ->method('createFromProductBundleItem')
- ->withConsecutive([$bundleItem1], [$bundleItem2])
+ ->method('createFromAddProductBundleItemToCartCommand')
+ ->withConsecutive([$addBundleItemToCartCommand1], [$addBundleItemToCartCommand2])
->willReturn($productBundleOrderItem1, $productBundleOrderItem2)
;
$processor = $this->createProcessor();
- $processor->process($cart, $productBundle, 1);
+ $processor->process($cart, $productBundle, 1, new ArrayCollection([$addBundleItemToCartCommand1, $addBundleItemToCartCommand2]));
}
public function testAddCartItemToOrder(): void
@@ -178,7 +175,7 @@ public function testAddCartItemToOrder(): void
;
$processor = $this->createProcessor();
- $processor->process($cart, $productBundle, 1);
+ $processor->process($cart, $productBundle, 1, new ArrayCollection([$this->addProductBundleItemToCartCommand]));
}
private function createProcessor(): CartProcessorInterface
@@ -230,11 +227,6 @@ private function createProductBundleWithProduct(?ProductInterface $product = nul
return $productBundle;
}
- private function createProductBundleItem(): ProductBundleItemInterface
- {
- return new ProductBundleItem();
- }
-
private function createProductBundleOrderItem(): ProductBundleOrderItemInterface
{
return new ProductBundleOrderItem();
diff --git a/tests/Unit/Handler/AddProductBundleToCartHandlerTest.php b/tests/Unit/Handler/AddProductBundleToCartHandlerTest.php
index 922efa27..4df1d108 100644
--- a/tests/Unit/Handler/AddProductBundleToCartHandlerTest.php
+++ b/tests/Unit/Handler/AddProductBundleToCartHandlerTest.php
@@ -11,10 +11,12 @@
namespace Tests\BitBag\SyliusProductBundlePlugin\Unit\Handler;
+use BitBag\SyliusProductBundlePlugin\Command\AddProductBundleItemToCartCommandInterface;
use BitBag\SyliusProductBundlePlugin\Command\AddProductBundleToCartCommand;
use BitBag\SyliusProductBundlePlugin\Entity\ProductInterface;
use BitBag\SyliusProductBundlePlugin\Handler\AddProductBundleToCartHandler;
use BitBag\SyliusProductBundlePlugin\Handler\AddProductBundleToCartHandler\CartProcessorInterface;
+use Doctrine\Common\Collections\ArrayCollection;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Sylius\Component\Core\Model\OrderInterface;
@@ -28,20 +30,20 @@
final class AddProductBundleToCartHandlerTest extends TestCase
{
- /** @var mixed|MockObject|OrderRepositoryInterface */
- private $orderRepository;
+ private OrderRepositoryInterface|MockObject $orderRepository;
- /** @var mixed|MockObject|ProductRepositoryInterface */
- private $productRepository;
+ private ProductRepositoryInterface|MockObject $productRepository;
- /** @var CartProcessorInterface|mixed|MockObject */
- private $cartProcessor;
+ private CartProcessorInterface|MockObject $cartProcessor;
+
+ private AddProductBundleItemToCartCommandInterface|MockObject $addProductBundleItemToCartCommand;
protected function setUp(): void
{
$this->orderRepository = $this->createMock(OrderRepositoryInterface::class);
$this->productRepository = $this->createMock(ProductRepositoryInterface::class);
$this->cartProcessor = $this->createMock(CartProcessorInterface::class);
+ $this->addProductBundleItemToCartCommand = $this->createMock(AddProductBundleItemToCartCommandInterface::class);
}
public function testThrowExceptionIfCartDoesntExist(): void
@@ -122,10 +124,12 @@ public function testProcessCart(): void
$this->cartProcessor->expects(self::once())
->method('process')
- ->with($cart, $productBundle, 2)
+ ->with($cart, $productBundle, 2, new ArrayCollection([$this->addProductBundleItemToCartCommand]))
;
$command = new AddProductBundleToCartCommand(1, '', 2);
+ $command->setProductBundleItems(new ArrayCollection([$this->addProductBundleItemToCartCommand]));
+
$handler = $this->createHandler();
$handler($command);
}
@@ -149,6 +153,8 @@ public function testAddCartToRepository(): void
;
$command = new AddProductBundleToCartCommand(1, '', 1);
+ $command->setProductBundleItems(new ArrayCollection([$this->addProductBundleItemToCartCommand]));
+
$handler = $this->createHandler();
$handler($command);
}
diff --git a/tests/Unit/Inventory/Checker/BundledProductsInventoryManagementFeatureFlagCheckerTest.php b/tests/Unit/Inventory/Checker/BundledProductsInventoryManagementFeatureFlagCheckerTest.php
new file mode 100644
index 00000000..2478a637
--- /dev/null
+++ b/tests/Unit/Inventory/Checker/BundledProductsInventoryManagementFeatureFlagCheckerTest.php
@@ -0,0 +1,30 @@
+isEnabled());
+ }
+
+ public function testIsDisabled(): void
+ {
+ $checker = new BundledProductsInventoryManagementFeatureFlagChecker(false);
+ self::assertFalse($checker->isEnabled());
+ }
+}
diff --git a/tests/Unit/Inventory/Checker/OrderItemAvailabilityCheckerTest.php b/tests/Unit/Inventory/Checker/OrderItemAvailabilityCheckerTest.php
new file mode 100644
index 00000000..54d64fe2
--- /dev/null
+++ b/tests/Unit/Inventory/Checker/OrderItemAvailabilityCheckerTest.php
@@ -0,0 +1,117 @@
+decorated = $this->createMock(OrderItemAvailabilityCheckerInterface::class);
+ $this->featureFlagChecker = $this->createMock(FeatureFlagCheckerInterface::class);
+ $this->bundleOrderItemAvailabilityChecker = $this->createMock(ProductBundleOrderItemAvailabilityCheckerInterface::class);
+
+ $this->checker = new OrderItemAvailabilityChecker(
+ $this->decorated,
+ $this->featureFlagChecker,
+ $this->bundleOrderItemAvailabilityChecker,
+ );
+ }
+
+ public function testItCallsDecoratedIfFeatureDisabled(): void
+ {
+ $this->featureFlagChecker
+ ->expects(self::once())
+ ->method('isEnabled')
+ ->willReturn(false);
+
+ $this->decorated
+ ->expects(self::once())
+ ->method('isReservedStockSufficient');
+
+ $this->bundleOrderItemAvailabilityChecker->expects(self::never())->method(self::anything());
+
+ $this->checker->isReservedStockSufficient($this->createMock(OrderItemInterface::class));
+ }
+
+ public function testItCallsDecoratedIfProductIsNotBundle(): void
+ {
+ $this->featureFlagChecker
+ ->expects(self::once())
+ ->method('isEnabled')
+ ->willReturn(true);
+ $this->decorated
+ ->expects(self::once())
+ ->method('isReservedStockSufficient');
+
+ $this->bundleOrderItemAvailabilityChecker->expects(self::never())->method(self::anything());
+
+ $product = $this->createMock(ProductInterface::class);
+ $product
+ ->expects(self::once())
+ ->method('isBundle')
+ ->willReturn(false);
+
+ $orderItem = $this->createMock(OrderItemInterface::class);
+ $orderItem
+ ->expects(self::once())
+ ->method('getProduct')
+ ->willReturn($product);
+
+ $this->checker->isReservedStockSufficient($orderItem);
+ }
+
+ public function testItCallsProductBundleCheckerIfProductIsBundle(): void
+ {
+ $this->featureFlagChecker
+ ->expects(self::once())
+ ->method('isEnabled')
+ ->willReturn(true);
+
+ $this->decorated->expects(self::never())->method(self::anything());
+
+ $product = $this->createMock(ProductInterface::class);
+ $product
+ ->expects(self::once())
+ ->method('isBundle')
+ ->willReturn(true);
+
+ $orderItem = $this->createMock(OrderItemInterface::class);
+ $orderItem
+ ->expects(self::once())
+ ->method('getProduct')
+ ->willReturn($product);
+
+ $this->bundleOrderItemAvailabilityChecker
+ ->expects(self::once())
+ ->method('areOrderedBundledProductVariantsAvailable')
+ ->with($orderItem);
+
+ $this->checker->isReservedStockSufficient($orderItem);
+ }
+}
diff --git a/tests/Unit/Inventory/Checker/ProductBundleOrderItemAvailabilityCheckerTest.php b/tests/Unit/Inventory/Checker/ProductBundleOrderItemAvailabilityCheckerTest.php
new file mode 100644
index 00000000..91402120
--- /dev/null
+++ b/tests/Unit/Inventory/Checker/ProductBundleOrderItemAvailabilityCheckerTest.php
@@ -0,0 +1,133 @@
+areOrderedBundledProductVariantsAvailable($orderItem));
+ }
+
+ public function provideAreOrderedBundledProductVariantsAvailable(): array
+ {
+ $unTrackedVariant = $this->mockProductVariant(false, 0, 0);
+ $unTrackedBundleOrderItem = $this->mockBundleOrderItem($unTrackedVariant, 2);
+ $orderItem1 = $this->mockOrderItem([$unTrackedBundleOrderItem], 2);
+
+ $trackedVariantOutOfStock = $this->mockProductVariant(true, 0, 0);
+ $trackedOutOfStockBundleOrderItem = $this->mockBundleOrderItem($trackedVariantOutOfStock, 2);
+ $orderItem2 = $this->mockOrderItem([$trackedOutOfStockBundleOrderItem], 2);
+
+ $trackedVariantInStock = $this->mockProductVariant(true, 10, 20);
+ $trackedInStockBundleOrderItem = $this->mockBundleOrderItem($trackedVariantInStock, 2);
+ $orderItem3 = $this->mockOrderItem([$trackedOutOfStockBundleOrderItem, $trackedInStockBundleOrderItem], 2);
+
+ $orderItem4 = $this->mockOrderItem([$trackedInStockBundleOrderItem], 5);
+
+ $trackedVariantInStock2 = $this->mockProductVariant(true, 20, 10);
+ $trackedInStockBundleOrderItem2 = $this->mockBundleOrderItem($trackedVariantInStock2, 2);
+ $orderItem5 = $this->mockOrderItem([$trackedInStockBundleOrderItem2], 5);
+
+ $trackedVariantInStock3 = $this->mockProductVariant(true, 10, 9);
+ $trackedInStockBundleOrderItem3 = $this->mockBundleOrderItem($trackedVariantInStock3, 2);
+ $orderItem6 = $this->mockOrderItem([$trackedInStockBundleOrderItem3], 5);
+
+ $trackedVariantInStock4 = $this->mockProductVariant(true, 9, 10);
+ $trackedInStockBundleOrderItem4 = $this->mockBundleOrderItem($trackedVariantInStock4, 2);
+ $orderItem7 = $this->mockOrderItem([$trackedInStockBundleOrderItem4], 5);
+
+ return [
+ 'untracked variant' => [
+ $orderItem1,
+ true,
+ ],
+ 'variant out of stock' => [
+ $orderItem2,
+ false,
+ ],
+ 'one variant out of stock, one in stock' => [
+ $orderItem3,
+ false,
+ ],
+ 'on-hold edge case' => [
+ $orderItem4,
+ true,
+ ],
+ 'on-hand edge case' => [
+ $orderItem5,
+ true,
+ ],
+ 'on-hold insufficient' => [
+ $orderItem6,
+ false,
+ ],
+ 'on-hand insufficient' => [
+ $orderItem6,
+ false,
+ ],
+ ];
+ }
+
+ private function mockProductVariant(bool $isTracked, int $onHold, int $onHand): ProductVariantInterface
+ {
+ $variant = $this->createMock(ProductVariantInterface::class);
+ $variant
+ ->method('isTracked')
+ ->willReturn($isTracked);
+ $variant
+ ->method('getOnHold')
+ ->willReturn($onHold);
+ $variant
+ ->method('getOnHand')
+ ->willReturn($onHand);
+
+ return $variant;
+ }
+
+ private function mockBundleOrderItem(ProductVariantInterface $variant, int $quantity): ProductBundleOrderItemInterface
+ {
+ $item = $this->createMock(ProductBundleOrderItemInterface::class);
+ $item
+ ->method('getProductVariant')
+ ->willReturn($variant);
+ $item
+ ->method('getQuantity')
+ ->willReturn($quantity);
+
+ return $item;
+ }
+
+ /** @param ProductBundleOrderItemInterface[] $bundleOrderItems */
+ private function mockOrderItem(array $bundleOrderItems, int $quantity): OrderItemInterface
+ {
+ $orderItem = $this->createMock(OrderItemInterface::class);
+ $orderItem
+ ->method('getProductBundleOrderItems')
+ ->willReturn($bundleOrderItems);
+ $orderItem
+ ->method('getQuantity')
+ ->willReturn($quantity);
+
+ return $orderItem;
+ }
+}
diff --git a/tests/Unit/Inventory/Operator/OrderInventoryOperatorTest.php b/tests/Unit/Inventory/Operator/OrderInventoryOperatorTest.php
new file mode 100644
index 00000000..a19b01be
--- /dev/null
+++ b/tests/Unit/Inventory/Operator/OrderInventoryOperatorTest.php
@@ -0,0 +1,175 @@
+decorated = $this->createMock(SyliusOrderInventoryOperatorInterface::class);
+ $this->productVariantManager = $this->createMock(EntityManagerInterface::class);
+ $this->featureFlagChecker = $this->createMock(FeatureFlagCheckerInterface::class);
+ $this->productBundleOrderInventoryOperator = $this->createMock(ProductBundleOrderInventoryOperatorInterface::class);
+
+ $this->orderInventoryOperator = new OrderInventoryOperator(
+ $this->decorated,
+ $this->productVariantManager,
+ $this->featureFlagChecker,
+ $this->productBundleOrderInventoryOperator,
+ );
+ }
+
+ public function testCancelCallsDecoratedIfFeatureFlagDisabled(): void
+ {
+ $order = $this->createMock(OrderInterface::class);
+
+ $this->featureFlagChecker
+ ->expects(self::once())
+ ->method('isEnabled')
+ ->willReturn(false);
+
+ $this->decorated
+ ->expects(self::once())
+ ->method('cancel')
+ ->with($order);
+
+ $this->orderInventoryOperator->cancel($order);
+ }
+
+ public function testCancelGivesBackInventoryIfOrderPaidOrRefunded(): void
+ {
+ $order = $this->createMock(OrderInterface::class);
+
+ $order->method('getPaymentState')
+ ->willReturn(OrderPaymentStates::STATE_PAID);
+
+ $this->featureFlagChecker
+ ->method('isEnabled')
+ ->willReturn(true);
+
+ $this->productBundleOrderInventoryOperator
+ ->expects(self::once())
+ ->method('giveBack')
+ ->with($order);
+
+ $this->orderInventoryOperator->cancel($order);
+ }
+
+ public function testCancelReleasesInventoryIfNotPaidOrRefunded(): void
+ {
+ $order = $this->createMock(OrderInterface::class);
+
+ $order->method('getPaymentState')
+ ->willReturn(OrderPaymentStates::STATE_CART);
+
+ $this->featureFlagChecker
+ ->method('isEnabled')
+ ->willReturn(true);
+
+ $this->productBundleOrderInventoryOperator
+ ->expects(self::once())
+ ->method('release')
+ ->with($order);
+
+ $this->orderInventoryOperator->cancel($order);
+ }
+
+ public function testHoldCallsDecoratedIfFeatureFlagDisabled(): void
+ {
+ $order = $this->createMock(OrderInterface::class);
+
+ $this->featureFlagChecker
+ ->expects(self::once())
+ ->method('isEnabled')
+ ->willReturn(false);
+
+ $this->decorated
+ ->expects(self::once())
+ ->method('hold')
+ ->with($order);
+
+ $this->orderInventoryOperator->hold($order);
+ }
+
+ public function testHoldHandlesBundleIfFeatureFlagEnabled(): void
+ {
+ $order = $this->createMock(OrderInterface::class);
+
+ $this->decorated->expects(self::never())->method(self::anything());
+
+ $this->featureFlagChecker
+ ->method('isEnabled')
+ ->willReturn(true);
+
+ $this->productBundleOrderInventoryOperator
+ ->expects(self::once())
+ ->method('hold')
+ ->with($order);
+
+ $this->orderInventoryOperator->hold($order);
+ }
+
+ public function testSellCallsDecoratedIfFeatureFlagDisabled(): void
+ {
+ $order = $this->createMock(OrderInterface::class);
+
+ $this->featureFlagChecker
+ ->expects(self::once())
+ ->method('isEnabled')
+ ->willReturn(false);
+
+ $this->decorated
+ ->expects(self::once())
+ ->method('sell')
+ ->with($order);
+
+ $this->orderInventoryOperator->sell($order);
+ }
+
+ public function testSellHandlesBundleIfFeatureFlagEnabled(): void
+ {
+ $order = $this->createMock(OrderInterface::class);
+
+ $this->decorated->expects(self::never())->method(self::anything());
+
+ $this->featureFlagChecker
+ ->method('isEnabled')
+ ->willReturn(true);
+
+ $this->productBundleOrderInventoryOperator
+ ->expects(self::once())
+ ->method('sell')
+ ->with($order);
+
+ $this->orderInventoryOperator->sell($order);
+ }
+}
diff --git a/tests/Unit/Inventory/Operator/ProductBundleOrderInventoryOperatorTest.php b/tests/Unit/Inventory/Operator/ProductBundleOrderInventoryOperatorTest.php
new file mode 100644
index 00000000..e6e04a54
--- /dev/null
+++ b/tests/Unit/Inventory/Operator/ProductBundleOrderInventoryOperatorTest.php
@@ -0,0 +1,368 @@
+bundle = $this->createMock(ProductInterface::class);
+ $this->bundle
+ ->method('isBundle')
+ ->willReturn(true);
+
+ $this->regularProduct = $this->createMock(ProductInterface::class);
+ $this->regularProduct
+ ->method('isBundle')
+ ->willReturn(false);
+
+ $this->operator = new ProductBundleOrderInventoryOperator();
+ }
+
+ public function testItHolds(): void
+ {
+ $bundleVariant1 = $this->createMock(ProductVariantInterface::class);
+ $bundleVariant1
+ ->method('isTracked')
+ ->willReturn(true);
+ $bundleVariant1
+ ->method('getOnHold')
+ ->willReturn(10);
+ $bundleVariant1
+ ->method('setOnHold')
+ ->with(14);
+
+ $bundleVariant2 = $this->createMock(ProductVariantInterface::class);
+ $bundleVariant2
+ ->method('isTracked')
+ ->willReturn(true);
+ $bundleVariant2
+ ->method('getOnHold')
+ ->willReturn(20);
+ $bundleVariant2
+ ->method('setOnHold')
+ ->with(26);
+
+ $bundleOrderItem = $this->createMock(OrderItemInterface::class);
+ $bundleOrderItem
+ ->expects(self::once())
+ ->method('getProduct')
+ ->willReturn($this->bundle);
+
+ $bundleOrderItem
+ ->expects(self::exactly(2))
+ ->method('getQuantity')
+ ->willReturn(2);
+
+ $bundleOrderItem
+ ->expects(self::once())
+ ->method('getProductBundleOrderItems')
+ ->willReturn([
+ $this->mockProductBundleOrderItem($bundleVariant1, 2),
+ $this->mockProductBundleOrderItem($bundleVariant2, 3),
+ ]);
+ $bundleOrderItem->expects(self::never())->method('getVariant');
+
+ $regularOrderItem = $this->createMock(OrderItemInterface::class);
+ $regularOrderItem
+ ->expects(self::once())
+ ->method('getProduct')
+ ->willReturn($this->regularProduct);
+ $regularOrderItem
+ ->expects(self::once())
+ ->method('getQuantity')
+ ->willReturn(3);
+
+ $variant = $this->createMock(ProductVariantInterface::class);
+ $variant
+ ->method('isTracked')
+ ->willReturn(true);
+ $variant
+ ->method('getOnHold')
+ ->willReturn(100);
+ $variant
+ ->method('setOnHold')
+ ->with(103);
+
+ $regularOrderItem
+ ->expects(self::once())
+ ->method('getVariant')
+ ->willReturn($variant);
+
+ $regularOrderItem->expects(self::never())->method('getProductBundleOrderItems');
+
+ $order = $this->mockOrder(
+ $regularOrderItem,
+ $bundleOrderItem,
+ );
+
+ $this->operator->hold($order);
+ }
+
+ public function testItSells(): void
+ {
+ $bundleVariant1 = $this->createMock(ProductVariantInterface::class);
+ $bundleVariant1
+ ->method('isTracked')
+ ->willReturn(true);
+ $bundleVariant1
+ ->method('getOnHold')
+ ->willReturn(10);
+ $bundleVariant1
+ ->method('getOnHand')
+ ->willReturn(20);
+ $bundleVariant1
+ ->method('setOnHold')
+ ->with(6);
+ $bundleVariant1
+ ->method('setOnHand')
+ ->with(16);
+
+ $bundleOrderItem = $this->createMock(OrderItemInterface::class);
+ $bundleOrderItem
+ ->expects(self::once())
+ ->method('getProduct')
+ ->willReturn($this->bundle);
+
+ $bundleOrderItem
+ ->expects(self::once())
+ ->method('getQuantity')
+ ->willReturn(2);
+
+ $bundleOrderItem
+ ->expects(self::once())
+ ->method('getProductBundleOrderItems')
+ ->willReturn([
+ $this->mockProductBundleOrderItem($bundleVariant1, 2),
+ ]);
+ $bundleOrderItem->expects(self::never())->method('getVariant');
+
+ $regularOrderItem = $this->createMock(OrderItemInterface::class);
+ $regularOrderItem
+ ->expects(self::once())
+ ->method('getProduct')
+ ->willReturn($this->regularProduct);
+ $regularOrderItem
+ ->expects(self::once())
+ ->method('getQuantity')
+ ->willReturn(3);
+
+ $variant = $this->createMock(ProductVariantInterface::class);
+ $variant
+ ->method('isTracked')
+ ->willReturn(true);
+ $variant
+ ->method('getOnHold')
+ ->willReturn(100);
+ $variant
+ ->method('setOnHold')
+ ->with(97);
+ $variant
+ ->method('getOnHand')
+ ->willReturn(200);
+ $variant
+ ->method('setOnHand')
+ ->with(197);
+
+ $regularOrderItem
+ ->expects(self::once())
+ ->method('getVariant')
+ ->willReturn($variant);
+
+ $regularOrderItem->expects(self::never())->method('getProductBundleOrderItems');
+
+ $order = $this->mockOrder(
+ $regularOrderItem,
+ $bundleOrderItem,
+ );
+
+ $this->operator->sell($order);
+ }
+
+ public function testItReleases(): void
+ {
+ $bundleVariant1 = $this->createMock(ProductVariantInterface::class);
+ $bundleVariant1
+ ->method('isTracked')
+ ->willReturn(true);
+ $bundleVariant1
+ ->method('getOnHold')
+ ->willReturn(10);
+ $bundleVariant1
+ ->method('setOnHold')
+ ->with(6);
+
+ $bundleOrderItem = $this->createMock(OrderItemInterface::class);
+ $bundleOrderItem
+ ->expects(self::once())
+ ->method('getProduct')
+ ->willReturn($this->bundle);
+
+ $bundleOrderItem
+ ->expects(self::once())
+ ->method('getQuantity')
+ ->willReturn(2);
+
+ $bundleOrderItem
+ ->expects(self::once())
+ ->method('getProductBundleOrderItems')
+ ->willReturn([
+ $this->mockProductBundleOrderItem($bundleVariant1, 2),
+ ]);
+ $bundleOrderItem->expects(self::never())->method('getVariant');
+
+ $regularOrderItem = $this->createMock(OrderItemInterface::class);
+ $regularOrderItem
+ ->expects(self::once())
+ ->method('getProduct')
+ ->willReturn($this->regularProduct);
+ $regularOrderItem
+ ->expects(self::once())
+ ->method('getQuantity')
+ ->willReturn(3);
+
+ $variant = $this->createMock(ProductVariantInterface::class);
+ $variant
+ ->method('isTracked')
+ ->willReturn(true);
+ $variant
+ ->method('getOnHold')
+ ->willReturn(100);
+ $variant
+ ->method('setOnHold')
+ ->with(97);
+
+ $regularOrderItem
+ ->expects(self::once())
+ ->method('getVariant')
+ ->willReturn($variant);
+
+ $regularOrderItem->expects(self::never())->method('getProductBundleOrderItems');
+
+ $order = $this->mockOrder(
+ $regularOrderItem,
+ $bundleOrderItem,
+ );
+
+ $this->operator->release($order);
+ }
+
+ public function testItGivesBack(): void
+ {
+ $bundleVariant1 = $this->createMock(ProductVariantInterface::class);
+ $bundleVariant1
+ ->method('isTracked')
+ ->willReturn(true);
+ $bundleVariant1
+ ->method('getOnHand')
+ ->willReturn(10);
+ $bundleVariant1
+ ->method('setOnHand')
+ ->with(14);
+
+ $bundleOrderItem = $this->createMock(OrderItemInterface::class);
+ $bundleOrderItem
+ ->expects(self::once())
+ ->method('getProduct')
+ ->willReturn($this->bundle);
+
+ $bundleOrderItem
+ ->expects(self::once())
+ ->method('getQuantity')
+ ->willReturn(2);
+
+ $bundleOrderItem
+ ->expects(self::once())
+ ->method('getProductBundleOrderItems')
+ ->willReturn([
+ $this->mockProductBundleOrderItem($bundleVariant1, 2),
+ ]);
+ $bundleOrderItem->expects(self::never())->method('getVariant');
+
+ $regularOrderItem = $this->createMock(OrderItemInterface::class);
+ $regularOrderItem
+ ->expects(self::once())
+ ->method('getProduct')
+ ->willReturn($this->regularProduct);
+ $regularOrderItem
+ ->expects(self::once())
+ ->method('getQuantity')
+ ->willReturn(3);
+
+ $variant = $this->createMock(ProductVariantInterface::class);
+ $variant
+ ->method('isTracked')
+ ->willReturn(true);
+ $variant
+ ->method('getOnHand')
+ ->willReturn(100);
+ $variant
+ ->method('setOnHand')
+ ->with(103);
+
+ $regularOrderItem
+ ->expects(self::once())
+ ->method('getVariant')
+ ->willReturn($variant);
+
+ $regularOrderItem->expects(self::never())->method('getProductBundleOrderItems');
+
+ $order = $this->mockOrder(
+ $regularOrderItem,
+ $bundleOrderItem,
+ );
+
+ $this->operator->giveBack($order);
+ }
+
+ private function mockProductBundleOrderItem(
+ ProductVariantInterface $variant,
+ int $quantity,
+ ): ProductBundleOrderItemInterface {
+ $bundleOrderItem = $this->createMock(ProductBundleOrderItemInterface::class);
+ $bundleOrderItem
+ ->method('getProductVariant')
+ ->willReturn($variant);
+ $bundleOrderItem
+ ->method('getQuantity')
+ ->willReturn($quantity);
+
+ return $bundleOrderItem;
+ }
+
+ private function mockOrder(OrderItemInterface ...$items): OrderInterface
+ {
+ $order = $this->createMock(OrderInterface::class);
+ $order
+ ->method('getItems')
+ ->willReturn(new ArrayCollection($items));
+
+ return $order;
+ }
+}
diff --git a/tests/Unit/MotherObject/AddProductBundleItemToCartCommandMother.php b/tests/Unit/MotherObject/AddProductBundleItemToCartCommandMother.php
index 6912c547..0d296c5d 100644
--- a/tests/Unit/MotherObject/AddProductBundleItemToCartCommandMother.php
+++ b/tests/Unit/MotherObject/AddProductBundleItemToCartCommandMother.php
@@ -12,11 +12,12 @@
namespace Tests\BitBag\SyliusProductBundlePlugin\Unit\MotherObject;
use BitBag\SyliusProductBundlePlugin\Command\AddProductBundleItemToCartCommand;
+use BitBag\SyliusProductBundlePlugin\Command\AddProductBundleItemToCartCommandInterface;
use BitBag\SyliusProductBundlePlugin\Entity\ProductBundleItemInterface;
final class AddProductBundleItemToCartCommandMother
{
- public static function create(ProductBundleItemInterface $bundleItem): AddProductBundleItemToCartCommand
+ public static function create(ProductBundleItemInterface $bundleItem): AddProductBundleItemToCartCommandInterface
{
return new AddProductBundleItemToCartCommand($bundleItem);
}
diff --git a/tests/Unit/Provider/AddProductBundleItemToCartCommandProviderTest.php b/tests/Unit/Provider/AddProductBundleItemToCartCommandProviderTest.php
new file mode 100644
index 00000000..de5b8492
--- /dev/null
+++ b/tests/Unit/Provider/AddProductBundleItemToCartCommandProviderTest.php
@@ -0,0 +1,189 @@
+addProductBundleItemToCartCommandFactory = $this->createMock(AddProductBundleItemToCartCommandFactoryInterface::class);
+ $this->productBundleRepository = $this->createMock(ProductBundleRepositoryInterface::class);
+ $this->productVariantRepository = $this->createMock(ProductVariantRepositoryInterface::class);
+
+ $this->bundleItem1 = $this->createMock(ProductBundleItemInterface::class);
+ $this->bundleItem2 = $this->createMock(ProductBundleItemInterface::class);
+ $this->bundle = $this->createMock(ProductBundleInterface::class);
+ $this->bundle
+ ->expects(self::any())
+ ->method('getProductBundleItems')
+ ->willReturn(new ArrayCollection([$this->bundleItem1, $this->bundleItem2]));
+
+ $this->provider = new AddProductBundleItemToCartCommandProvider(
+ $this->addProductBundleItemToCartCommandFactory,
+ $this->productBundleRepository,
+ $this->productVariantRepository,
+ );
+ }
+
+ public function testItThrowsExceptionIfBundleIsNotFound(): void
+ {
+ self::expectException(\Exception::class);
+ self::expectExceptionMessage('Product bundle not found');
+
+ $this->productBundleRepository
+ ->expects(self::once())
+ ->method('findOneByProductCode')
+ ->with('BUNDLE_CODE')
+ ->willReturn(null);
+
+ $this->provider->provide('BUNDLE_CODE', []);
+ }
+
+ public function testItWillNotOverwriteIfBundleIsPacked(): void
+ {
+ $this->bundle
+ ->expects(self::exactly(2))
+ ->method('isPackedProduct')
+ ->willReturn(true);
+
+ $this->productBundleRepository
+ ->expects(self::once())
+ ->method('findOneByProductCode')
+ ->with('BUNDLE_CODE')
+ ->willReturn($this->bundle);
+
+ $addProductBundleItemToCartCommand = $this->createMock(AddProductBundleItemToCartCommandInterface::class);
+
+ $this->addProductBundleItemToCartCommandFactory
+ ->expects(self::exactly(2))
+ ->method('createNew')
+ ->withConsecutive([$this->bundleItem1], [$this->bundleItem2])
+ ->willReturn($addProductBundleItemToCartCommand);
+
+ $this->productVariantRepository->expects(self::never())->method(self::anything());
+
+ $this->provider->provide('BUNDLE_CODE', []);
+ }
+
+ public function testItWillNotOverwriteIfOverwrittenVariantsIsEmpty(): void
+ {
+ $this->bundle
+ ->expects(self::exactly(2))
+ ->method('isPackedProduct')
+ ->willReturn(false);
+
+ $this->productBundleRepository
+ ->expects(self::once())
+ ->method('findOneByProductCode')
+ ->with('BUNDLE_CODE')
+ ->willReturn($this->bundle);
+
+ $addProductBundleItemToCartCommand = $this->createMock(AddProductBundleItemToCartCommandInterface::class);
+
+ $this->addProductBundleItemToCartCommandFactory
+ ->expects(self::exactly(2))
+ ->method('createNew')
+ ->withConsecutive([$this->bundleItem1], [$this->bundleItem2])
+ ->willReturn($addProductBundleItemToCartCommand);
+
+ $this->productVariantRepository->expects(self::never())->method(self::anything());
+
+ $this->provider->provide('BUNDLE_CODE', []);
+ }
+
+ public function testItOverwrites(): void
+ {
+ $this->bundle
+ ->expects(self::exactly(2))
+ ->method('isPackedProduct')
+ ->willReturn(false);
+
+ $this->productBundleRepository
+ ->expects(self::once())
+ ->method('findOneByProductCode')
+ ->with('BUNDLE_CODE')
+ ->willReturn($this->bundle);
+
+ $product = $this->createMock(ProductInterface::class);
+
+ $oldProductVariant = $this->createMock(ProductVariantInterface::class);
+ $oldProductVariant
+ ->expects(self::once())
+ ->method('getCode')
+ ->willReturn('OLD_VARIANT_CODE');
+ $oldProductVariant
+ ->expects(self::once())
+ ->method('getProduct')
+ ->willReturn($product);
+
+ $newProductVariant = $this->createMock(ProductVariantInterface::class);
+ $newProductVariant
+ ->expects(self::once())
+ ->method('getProduct')
+ ->willReturn($product);
+
+ $this->bundleItem1
+ ->expects(self::once())
+ ->method('getProductVariant')
+ ->willReturn($oldProductVariant);
+
+ $this->productVariantRepository
+ ->expects(self::exactly(3))
+ ->method('findOneBy')
+ ->willReturnOnConsecutiveCalls($oldProductVariant, $newProductVariant, $newProductVariant);
+
+ $addProductBundleItemToCartCommand = $this->createMock(AddProductBundleItemToCartCommandInterface::class);
+
+ $this->addProductBundleItemToCartCommandFactory
+ ->expects(self::exactly(2))
+ ->method('createNew')
+ ->withConsecutive([$this->bundleItem1], [$this->bundleItem2])
+ ->willReturn($addProductBundleItemToCartCommand);
+
+ $overwrittenVariants = [
+ [
+ 'from' => 'OLD_VARIANT_CODE',
+ 'to' => 'NEW_VARIANT_CODE',
+ ],
+ ];
+
+ $this->provider->provide('BUNDLE_CODE', $overwrittenVariants);
+ }
+}