diff --git a/features/checkout/shipping_order/seeing_default_shipping_method_selected_based_on_shipping_address.feature b/features/checkout/shipping_order/seeing_default_shipping_method_selected_based_on_shipping_address.feature
new file mode 100644
index 00000000000..a69455c2375
--- /dev/null
+++ b/features/checkout/shipping_order/seeing_default_shipping_method_selected_based_on_shipping_address.feature
@@ -0,0 +1,41 @@
+@checkout
+Feature: Seeing default shipping method selected based on shipping address
+ In order to select correct shipping method for my order
+ As a Customer
+ I want to be able to choose only shipping methods that match shipping category of all my items
+
+ Background:
+ Given the store operates on a channel named "Web"
+ And the store has a product "Star Trek Ship" priced at "$19.99"
+ And the store ships to "United Kingdom"
+ And the store ships to "United States"
+ And the store has a zone "United Kingdom" with code "UK"
+ And this zone has the "United Kingdom" country member
+ And the store has a zone "United States" with code "US"
+ And this zone has the "United States" country member
+ And the store has "DHL" shipping method with "$10.00" fee within the "US" zone
+ And the store has "FedEx" shipping method with "$20.00" fee within the "UK" zone
+ And I am a logged in customer
+
+ @ui
+ Scenario: Seeing default shipping method selected based on country from shipping address
+ Given I have product "Star Trek Ship" in the cart
+ And I am at the checkout addressing step
+ When I specify the shipping address as "Ankh Morpork", "Frost Alley", "90210", "United States" for "Jon Snow"
+ And I complete the addressing step
+ Then I should be on the checkout shipping step
+ And I should see selected "DHL" shipping method
+ And I should not see "FedEx" shipping method
+
+ @ui
+ Scenario: Seeing default shipping method selected based on country from shipping address after readdressing
+ Given I have product "Star Trek Ship" in the cart
+ And I am at the checkout addressing step
+ When I specify the shipping address as "Ankh Morpork", "Frost Alley", "90210", "United States" for "Jon Snow"
+ And I complete the addressing step
+ And I decide to change my address
+ And I specify the shipping address as "Ankh Morpork", "Frost Alley", "90210", "United Kingdom" for "Jon Snow"
+ And I complete the addressing step
+ Then I should be on the checkout shipping step
+ And I should see selected "FedEx" shipping method
+ And I should not see "DHL" shipping method
diff --git a/src/Sylius/Behat/Context/Ui/Shop/Checkout/CheckoutShippingContext.php b/src/Sylius/Behat/Context/Ui/Shop/Checkout/CheckoutShippingContext.php
index f6ecc42343e..c1cd95b81ba 100644
--- a/src/Sylius/Behat/Context/Ui/Shop/Checkout/CheckoutShippingContext.php
+++ b/src/Sylius/Behat/Context/Ui/Shop/Checkout/CheckoutShippingContext.php
@@ -191,6 +191,14 @@ public function iShouldSeeShippingMethod($shippingMethodName)
Assert::true($this->selectShippingPage->hasShippingMethod($shippingMethodName));
}
+ /**
+ * @Then I should see selected :shippingMethodName shipping method
+ */
+ public function iShouldSeeSelectedShippingMethod($shippingMethodName)
+ {
+ Assert::same($this->selectShippingPage->getSelectedShippingMethodName(), $shippingMethodName);
+ }
+
/**
* @Then I should not see :shippingMethodName shipping method
*/
diff --git a/src/Sylius/Behat/Page/Shop/Checkout/SelectShippingPage.php b/src/Sylius/Behat/Page/Shop/Checkout/SelectShippingPage.php
index e1f33820c67..42a1b6876ed 100644
--- a/src/Sylius/Behat/Page/Shop/Checkout/SelectShippingPage.php
+++ b/src/Sylius/Behat/Page/Shop/Checkout/SelectShippingPage.php
@@ -14,6 +14,7 @@
namespace Sylius\Behat\Page\Shop\Checkout;
use Behat\Mink\Driver\Selenium2Driver;
+use Behat\Mink\Element\NodeElement;
use Behat\Mink\Exception\ElementNotFoundException;
use Sylius\Behat\Page\SymfonyPage;
@@ -57,6 +58,24 @@ public function getShippingMethods()
return $shippingMethods;
}
+ /**
+ * {@inheritdoc}
+ */
+ public function getSelectedShippingMethodName(): ?string
+ {
+ $shippingMethods = $this->getSession()->getPage()->findAll('css', '#sylius-shipping-methods .item');
+
+ /** @var NodeElement $shippingMethod */
+ foreach ($shippingMethods as $shippingMethod) {
+ if (null !== $shippingMethod->find('css', 'input:checked')) {
+ return $shippingMethod->find('css', '.content label')->getText();
+ }
+ }
+
+ return null;
+ }
+
+
/**
* {@inheritdoc}
*/
diff --git a/src/Sylius/Behat/Page/Shop/Checkout/SelectShippingPageInterface.php b/src/Sylius/Behat/Page/Shop/Checkout/SelectShippingPageInterface.php
index 40ee608e857..9a3185acdb8 100644
--- a/src/Sylius/Behat/Page/Shop/Checkout/SelectShippingPageInterface.php
+++ b/src/Sylius/Behat/Page/Shop/Checkout/SelectShippingPageInterface.php
@@ -27,6 +27,11 @@ public function selectShippingMethod($shippingMethod);
*/
public function getShippingMethods();
+ /**
+ * @return string|null
+ */
+ public function getSelectedShippingMethodName(): ?string;
+
/**
* @return bool
*/
diff --git a/src/Sylius/Bundle/CoreBundle/Resources/config/services.xml b/src/Sylius/Bundle/CoreBundle/Resources/config/services.xml
index 426b016e223..cdebe83c23d 100644
--- a/src/Sylius/Bundle/CoreBundle/Resources/config/services.xml
+++ b/src/Sylius/Bundle/CoreBundle/Resources/config/services.xml
@@ -70,6 +70,7 @@
+
diff --git a/src/Sylius/Bundle/CoreBundle/Resources/config/services/order_processing.xml b/src/Sylius/Bundle/CoreBundle/Resources/config/services/order_processing.xml
index 503ba37b33d..5d506342560 100644
--- a/src/Sylius/Bundle/CoreBundle/Resources/config/services/order_processing.xml
+++ b/src/Sylius/Bundle/CoreBundle/Resources/config/services/order_processing.xml
@@ -30,6 +30,7 @@
+
diff --git a/src/Sylius/Component/Core/OrderProcessing/OrderShipmentProcessor.php b/src/Sylius/Component/Core/OrderProcessing/OrderShipmentProcessor.php
index 4c0b8da8018..f292431efea 100644
--- a/src/Sylius/Component/Core/OrderProcessing/OrderShipmentProcessor.php
+++ b/src/Sylius/Component/Core/OrderProcessing/OrderShipmentProcessor.php
@@ -20,6 +20,7 @@
use Sylius\Component\Resource\Factory\FactoryInterface;
use Sylius\Component\Shipping\Exception\UnresolvedDefaultShippingMethodException;
use Sylius\Component\Shipping\Resolver\DefaultShippingMethodResolverInterface;
+use Sylius\Component\Shipping\Resolver\ShippingMethodsResolverInterface;
use Webmozart\Assert\Assert;
final class OrderShipmentProcessor implements OrderProcessorInterface
@@ -34,16 +35,31 @@ final class OrderShipmentProcessor implements OrderProcessorInterface
*/
private $shipmentFactory;
+ /**
+ * @var ShippingMethodsResolverInterface|null
+ */
+ private $shippingMethodsResolver;
+
/**
* @param DefaultShippingMethodResolverInterface $defaultShippingMethodResolver
* @param FactoryInterface $shipmentFactory
+ * @param ShippingMethodsResolverInterface|null $shippingMethodsResolver
*/
public function __construct(
DefaultShippingMethodResolverInterface $defaultShippingMethodResolver,
- FactoryInterface $shipmentFactory
+ FactoryInterface $shipmentFactory,
+ ?ShippingMethodsResolverInterface $shippingMethodsResolver = null
) {
$this->defaultShippingMethodResolver = $defaultShippingMethodResolver;
$this->shipmentFactory = $shipmentFactory;
+ $this->shippingMethodsResolver = $shippingMethodsResolver;
+
+ if (2 === func_num_args() || null === $shippingMethodsResolver) {
+ @trigger_error(
+ 'Not passing ShippingMethodsResolverInterface explicitly is deprecated since 1.2 and will be prohibited in 2.0',
+ E_USER_DEPRECATED
+ );
+ }
}
/**
@@ -85,7 +101,7 @@ public function process(BaseOrderInterface $order): void
private function getOrderShipment(OrderInterface $order): ?ShipmentInterface
{
if ($order->hasShipments()) {
- return $order->getShipments()->first();
+ return $this->getExistingShipmentWithProperMethod($order);
}
try {
@@ -101,4 +117,29 @@ private function getOrderShipment(OrderInterface $order): ?ShipmentInterface
return null;
}
}
+
+ /**
+ * @param OrderInterface $order
+ *
+ * @return ShipmentInterface|null
+ */
+ private function getExistingShipmentWithProperMethod(OrderInterface $order): ?ShipmentInterface
+ {
+ /** @var ShipmentInterface $shipment */
+ $shipment = $order->getShipments()->first();
+
+ if (null === $this->shippingMethodsResolver) {
+ return $shipment;
+ }
+
+ if (!in_array($shipment->getMethod(), $this->shippingMethodsResolver->getSupportedMethods($shipment), true)) {
+ try {
+ $shipment->setMethod($this->defaultShippingMethodResolver->getDefaultShippingMethod($shipment));
+ } catch (UnresolvedDefaultShippingMethodException $exception) {
+ return null;
+ }
+ }
+
+ return $shipment;
+ }
}
diff --git a/src/Sylius/Component/Core/Resolver/DefaultShippingMethodResolver.php b/src/Sylius/Component/Core/Resolver/DefaultShippingMethodResolver.php
index e2f0da66d47..6331ff2c4cb 100644
--- a/src/Sylius/Component/Core/Resolver/DefaultShippingMethodResolver.php
+++ b/src/Sylius/Component/Core/Resolver/DefaultShippingMethodResolver.php
@@ -13,6 +13,9 @@
namespace Sylius\Component\Core\Resolver;
+use Sylius\Component\Addressing\Matcher\ZoneMatcherInterface;
+use Sylius\Component\Addressing\Model\ZoneInterface;
+use Sylius\Component\Core\Model\AddressInterface;
use Sylius\Component\Core\Model\ChannelInterface;
use Sylius\Component\Core\Model\ShipmentInterface as CoreShipmentInterface;
use Sylius\Component\Core\Repository\ShippingMethodRepositoryInterface;
@@ -29,12 +32,28 @@ class DefaultShippingMethodResolver implements DefaultShippingMethodResolverInte
*/
private $shippingMethodRepository;
+ /**
+ * @var ZoneMatcherInterface|null
+ */
+ private $zoneMatcher;
+
/**
* @param ShippingMethodRepositoryInterface $shippingMethodRepository
+ * @param ZoneMatcherInterface|null $zoneMatcher
*/
- public function __construct(ShippingMethodRepositoryInterface $shippingMethodRepository)
- {
+ public function __construct(
+ ShippingMethodRepositoryInterface $shippingMethodRepository,
+ ?ZoneMatcherInterface $zoneMatcher = null
+ ) {
$this->shippingMethodRepository = $shippingMethodRepository;
+ $this->zoneMatcher = $zoneMatcher;
+
+ if (1 === func_num_args() || null === $zoneMatcher) {
+ @trigger_error(
+ 'Not passing ZoneMatcherInterface explicitly is deprecated since 1.2 and will be prohibited in 2.0',
+ E_USER_DEPRECATED
+ );
+ }
}
/**
@@ -45,14 +64,36 @@ public function getDefaultShippingMethod(ShipmentInterface $shipment): ShippingM
/** @var CoreShipmentInterface $shipment */
Assert::isInstanceOf($shipment, CoreShipmentInterface::class);
+ $order = $shipment->getOrder();
+
/** @var ChannelInterface $channel */
- $channel = $shipment->getOrder()->getChannel();
+ $channel = $order->getChannel();
+ /** @var AddressInterface $shippingAddress */
+ $shippingAddress = $order->getShippingAddress();
- $shippingMethods = $this->shippingMethodRepository->findEnabledForChannel($channel);
+ $shippingMethods = $this->getShippingMethods($channel, $shippingAddress);
if (empty($shippingMethods)) {
throw new UnresolvedDefaultShippingMethodException();
}
return $shippingMethods[0];
}
+
+ /**
+ * @param ChannelInterface $channel
+ * @param AddressInterface|null $address
+ *
+ * @return array|ShippingMethodInterface[]
+ */
+ private function getShippingMethods(ChannelInterface $channel, ?AddressInterface $address): array
+ {
+ if (null === $address || null === $this->zoneMatcher) {
+ return $this->shippingMethodRepository->findEnabledForChannel($channel);
+ }
+
+ /** @var ZoneInterface[] $zones */
+ $zones = $this->zoneMatcher->matchAll($address);
+
+ return $this->shippingMethodRepository->findEnabledForZonesAndChannel($zones, $channel);
+ }
}
diff --git a/src/Sylius/Component/Core/spec/OrderProcessing/OrderShipmentProcessorSpec.php b/src/Sylius/Component/Core/spec/OrderProcessing/OrderShipmentProcessorSpec.php
index 43d38cd4cca..6d895abc0b3 100644
--- a/src/Sylius/Component/Core/spec/OrderProcessing/OrderShipmentProcessorSpec.php
+++ b/src/Sylius/Component/Core/spec/OrderProcessing/OrderShipmentProcessorSpec.php
@@ -25,14 +25,16 @@
use Sylius\Component\Resource\Factory\FactoryInterface;
use Sylius\Component\Shipping\Model\ShippingMethodInterface;
use Sylius\Component\Shipping\Resolver\DefaultShippingMethodResolverInterface;
+use Sylius\Component\Shipping\Resolver\ShippingMethodsResolverInterface;
final class OrderShipmentProcessorSpec extends ObjectBehavior
{
function let(
DefaultShippingMethodResolverInterface $defaultShippingMethodResolver,
- FactoryInterface $shipmentFactory
+ FactoryInterface $shipmentFactory,
+ ShippingMethodsResolverInterface $shippingMethodsResolver
): void {
- $this->beConstructedWith($defaultShippingMethodResolver, $shipmentFactory);
+ $this->beConstructedWith($defaultShippingMethodResolver, $shipmentFactory, $shippingMethodsResolver);
}
function it_is_an_order_processor(): void
@@ -100,6 +102,44 @@ function it_removes_shipments_and_returns_null_when_shipping_is_not_required(
}
function it_adds_new_item_units_to_existing_shipment(
+ ShippingMethodsResolverInterface $shippingMethodsResolver,
+ OrderInterface $order,
+ ShipmentInterface $shipment,
+ Collection $shipments,
+ OrderItemUnitInterface $itemUnit,
+ OrderItemUnitInterface $itemUnitWithoutShipment,
+ OrderItemInterface $orderItem,
+ ProductVariantInterface $productVariant,
+ ShippingMethodInterface $shippingMethod
+ ): void {
+ $shipments->first()->willReturn($shipment);
+
+ $shipment->getMethod()->willReturn($shippingMethod);
+ $shippingMethodsResolver->getSupportedMethods($shipment)->willReturn([$shippingMethod]);
+
+ $orderItem->getVariant()->willReturn($productVariant);
+
+ $order->isShippingRequired()->willReturn(true);
+
+ $order->getItems()->willReturn(new ArrayCollection([$orderItem->getWrappedObject()]));
+
+ $order->isEmpty()->willReturn(false);
+ $order->hasShipments()->willReturn(true);
+ $order->getItemUnits()->willReturn(new ArrayCollection([$itemUnit->getWrappedObject(), $itemUnitWithoutShipment->getWrappedObject()]));
+ $order->getShipments()->willReturn($shipments);
+
+ $itemUnit->getShipment()->willReturn($shipment);
+
+ $shipment->getUnits()->willReturn(new ArrayCollection([]));
+ $shipment->addUnit($itemUnitWithoutShipment)->shouldBeCalled();
+ $shipment->addUnit($itemUnit)->shouldNotBeCalled();
+
+ $this->process($order);
+ }
+
+ function it_adds_new_item_units_to_existing_shipment_without_checking_methods_if_shipping_methods_resolver_is_not_used(
+ DefaultShippingMethodResolverInterface $defaultShippingMethodResolver,
+ FactoryInterface $shipmentFactory,
OrderInterface $order,
ShipmentInterface $shipment,
Collection $shipments,
@@ -108,6 +148,8 @@ function it_adds_new_item_units_to_existing_shipment(
OrderItemInterface $orderItem,
ProductVariantInterface $productVariant
): void {
+ $this->beConstructedWith($defaultShippingMethodResolver, $shipmentFactory);
+
$shipments->first()->willReturn($shipment);
$orderItem->getVariant()->willReturn($productVariant);
@@ -131,14 +173,19 @@ function it_adds_new_item_units_to_existing_shipment(
}
function it_removes_units_before_adding_new_ones(
+ ShippingMethodsResolverInterface $shippingMethodsResolver,
OrderInterface $order,
ShipmentInterface $shipment,
Collection $shipments,
OrderItemUnitInterface $itemUnit,
- OrderItemUnitInterface $itemUnitWithoutShipment
+ OrderItemUnitInterface $itemUnitWithoutShipment,
+ ShippingMethodInterface $shippingMethod
): void {
$shipments->first()->willReturn($shipment);
+ $shipment->getMethod()->willReturn($shippingMethod);
+ $shippingMethodsResolver->getSupportedMethods($shipment)->willReturn([$shippingMethod]);
+
$order->isShippingRequired()->willReturn(true);
$order->isEmpty()->willReturn(false);
@@ -156,4 +203,45 @@ function it_removes_units_before_adding_new_ones(
$this->process($order);
}
+
+ function it_adds_new_item_units_to_existing_shipment_and_replaces_its_method_if_its_ineligible(
+ DefaultShippingMethodResolverInterface $defaultShippingMethodResolver,
+ ShippingMethodsResolverInterface $shippingMethodsResolver,
+ OrderInterface $order,
+ ShipmentInterface $shipment,
+ Collection $shipments,
+ OrderItemUnitInterface $itemUnit,
+ OrderItemUnitInterface $itemUnitWithoutShipment,
+ OrderItemInterface $orderItem,
+ ProductVariantInterface $productVariant,
+ ShippingMethodInterface $firstShippingMethod,
+ ShippingMethodInterface $secondShippingMethod
+ ): void {
+ $shipments->first()->willReturn($shipment);
+
+ $shipment->getMethod()->willReturn($firstShippingMethod);
+ $shippingMethodsResolver->getSupportedMethods($shipment)->willReturn([$secondShippingMethod]);
+
+ $defaultShippingMethodResolver->getDefaultShippingMethod($shipment)->willReturn($secondShippingMethod);
+ $shipment->setMethod($secondShippingMethod)->shouldBeCalled();
+
+ $orderItem->getVariant()->willReturn($productVariant);
+
+ $order->isShippingRequired()->willReturn(true);
+
+ $order->getItems()->willReturn(new ArrayCollection([$orderItem->getWrappedObject()]));
+
+ $order->isEmpty()->willReturn(false);
+ $order->hasShipments()->willReturn(true);
+ $order->getItemUnits()->willReturn(new ArrayCollection([$itemUnit->getWrappedObject(), $itemUnitWithoutShipment->getWrappedObject()]));
+ $order->getShipments()->willReturn($shipments);
+
+ $itemUnit->getShipment()->willReturn($shipment);
+
+ $shipment->getUnits()->willReturn(new ArrayCollection([]));
+ $shipment->addUnit($itemUnitWithoutShipment)->shouldBeCalled();
+ $shipment->addUnit($itemUnit)->shouldNotBeCalled();
+
+ $this->process($order);
+ }
}
diff --git a/src/Sylius/Component/Core/spec/Resolver/DefaultShippingMethodResolverSpec.php b/src/Sylius/Component/Core/spec/Resolver/DefaultShippingMethodResolverSpec.php
index 6ddc3d284f6..9e2915bab45 100644
--- a/src/Sylius/Component/Core/spec/Resolver/DefaultShippingMethodResolverSpec.php
+++ b/src/Sylius/Component/Core/spec/Resolver/DefaultShippingMethodResolverSpec.php
@@ -14,6 +14,10 @@
namespace spec\Sylius\Component\Core\Resolver;
use PhpSpec\ObjectBehavior;
+use Prophecy\Argument;
+use Sylius\Component\Addressing\Matcher\ZoneMatcherInterface;
+use Sylius\Component\Addressing\Model\ZoneInterface;
+use Sylius\Component\Core\Model\AddressInterface;
use Sylius\Component\Core\Model\ChannelInterface;
use Sylius\Component\Core\Model\OrderInterface;
use Sylius\Component\Core\Model\ShipmentInterface;
@@ -25,9 +29,11 @@
final class DefaultShippingMethodResolverSpec extends ObjectBehavior
{
- function let(ShippingMethodRepositoryInterface $shippingMethodRepository): void
- {
- $this->beConstructedWith($shippingMethodRepository);
+ function let(
+ ShippingMethodRepositoryInterface $shippingMethodRepository,
+ ZoneMatcherInterface $zoneMatcher
+ ): void {
+ $this->beConstructedWith($shippingMethodRepository, $zoneMatcher);
}
function it_implements_a_default_shipping_method_resolver_interface(): void
@@ -35,7 +41,32 @@ function it_implements_a_default_shipping_method_resolver_interface(): void
$this->shouldImplement(DefaultShippingMethodResolverInterface::class);
}
- function it_returns_first_enabled_shipping_method_from_shipment_order_channel_as_default(
+ function it_returns_first_enabled_shipping_method_from_shipment_order_channel_if_there_is_not_shipping_address(
+ ChannelInterface $channel,
+ OrderInterface $order,
+ ShipmentInterface $shipment,
+ ShippingMethodInterface $firstShippingMethod,
+ ShippingMethodInterface $secondShippingMethod,
+ ShippingMethodRepositoryInterface $shippingMethodRepository,
+ ZoneMatcherInterface $zoneMatcher
+ ): void {
+ $shipment->getOrder()->willReturn($order);
+
+ $order->getChannel()->willReturn($channel);
+ $order->getShippingAddress()->willReturn(null);
+
+ $zoneMatcher->matchAll(Argument::any())->shouldNotBeCalled();
+
+ $shippingMethodRepository
+ ->findEnabledForChannel($channel)
+ ->willReturn([$firstShippingMethod, $secondShippingMethod])
+ ;
+
+ $this->getDefaultShippingMethod($shipment)->shouldReturn($firstShippingMethod);
+ }
+
+ function it_returns_first_enabled_shipping_method_from_shipment_order_channel_if_zone_matcher_is_not_used(
+ AddressInterface $shippingAddress,
ChannelInterface $channel,
OrderInterface $order,
ShipmentInterface $shipment,
@@ -43,8 +74,12 @@ function it_returns_first_enabled_shipping_method_from_shipment_order_channel_as
ShippingMethodInterface $secondShippingMethod,
ShippingMethodRepositoryInterface $shippingMethodRepository
): void {
+ $this->beConstructedWith($shippingMethodRepository);
+
$shipment->getOrder()->willReturn($order);
+
$order->getChannel()->willReturn($channel);
+ $order->getShippingAddress()->willReturn($shippingAddress);
$shippingMethodRepository
->findEnabledForChannel($channel)
@@ -54,17 +89,54 @@ function it_returns_first_enabled_shipping_method_from_shipment_order_channel_as
$this->getDefaultShippingMethod($shipment)->shouldReturn($firstShippingMethod);
}
- function it_throws_an_exception_if_there_is_no_enabled_shipping_methods(
- ShippingMethodRepositoryInterface $shippingMethodRepository,
+ function it_returns_first_enabled_shipping_method_matched_by_order_channel_and_shipping_address_zone(
+ AddressInterface $shippingAddress,
+ ChannelInterface $channel,
+ OrderInterface $order,
ShipmentInterface $shipment,
+ ShippingMethodInterface $firstShippingMethod,
+ ShippingMethodInterface $secondShippingMethod,
+ ShippingMethodRepositoryInterface $shippingMethodRepository,
+ ZoneInterface $firstZone,
+ ZoneInterface $secondZone,
+ ZoneMatcherInterface $zoneMatcher
+ ): void {
+ $shipment->getOrder()->willReturn($order);
+
+ $order->getChannel()->willReturn($channel);
+ $order->getShippingAddress()->willReturn($shippingAddress);
+
+ $zoneMatcher->matchAll($shippingAddress)->willReturn([$firstZone, $secondZone]);
+
+ $shippingMethodRepository
+ ->findEnabledForZonesAndChannel([$firstZone, $secondZone], $channel)
+ ->willReturn([$firstShippingMethod, $secondShippingMethod])
+ ;
+
+ $this->getDefaultShippingMethod($shipment)->shouldReturn($firstShippingMethod);
+ }
+
+ function it_throws_an_exception_if_there_is_no_enabled_shipping_methods_for_order_channel_and_zones(
+ AddressInterface $shippingAddress,
ChannelInterface $channel,
- OrderInterface $order
+ OrderInterface $order,
+ ShipmentInterface $shipment,
+ ShippingMethodRepositoryInterface $shippingMethodRepository,
+ ZoneInterface $firstZone,
+ ZoneInterface $secondZone,
+ ZoneMatcherInterface $zoneMatcher
): void {
$shipment->getOrder()->willReturn($order);
+
$order->getChannel()->willReturn($channel);
+ $order->getShippingAddress()->willReturn($shippingAddress);
+
+ $zoneMatcher->matchAll($shippingAddress)->willReturn([$firstZone, $secondZone]);
$shippingMethodRepository
- ->findEnabledForChannel($channel)->willReturn([]);
+ ->findEnabledForZonesAndChannel([$firstZone, $secondZone], $channel)
+ ->willReturn([])
+ ;
$this
->shouldThrow(UnresolvedDefaultShippingMethodException::class)