diff --git a/features/checkout/addressing_order/returning_to_addressing_step_with_a_different_shipping_address.feature b/features/checkout/addressing_order/returning_to_addressing_step_with_a_different_shipping_address.feature
new file mode 100644
index 0000000000..d84f6e2e49
--- /dev/null
+++ b/features/checkout/addressing_order/returning_to_addressing_step_with_a_different_shipping_address.feature
@@ -0,0 +1,52 @@
+@checkout
+Feature: Returning to addressing step with a different shipping address
+ In order to change the shipping address
+ As a Visitor
+ I want to return to the addressing step and change the shipping address
+
+ Background:
+ Given the store operates on a single channel in "United States"
+ And the store has a product "Summer T-Shirt" priced at "$19.99"
+ And the store ships everywhere for free
+
+ @ui
+ Scenario: Going back to addressing step after submitting a different shipping address
+ Given I have product "Summer T-Shirt" in the cart
+ And I am at the checkout addressing step
+ When I specify the email as "john.doe@example.com"
+ And I specify the billing address as "Brooklyn", "9036 Country Club Ave.", "11230", "United States" for "John Doe"
+ And I specify the shipping address as "Brooklyn", "70 Joy Ridge St", "11225", "United States" for "Jane Doe"
+ And I complete the addressing step
+ And I decide to change my address
+ Then different shipping address should be checked
+
+ @ui
+ Scenario: Going back to addressing step after not submitting a different shipping address
+ Given I have product "Summer T-Shirt" in the cart
+ And I am at the checkout addressing step
+ When I specify the email as "john.doe@example.com"
+ And I specify the billing address as "Brooklyn", "9036 Country Club Ave.", "11230", "United States" for "John Doe"
+ And I complete the addressing step
+ And I decide to change my address
+ Then different shipping address should not be checked
+
+ @ui @javascript
+ Scenario: Going back to addressing step after submitting a different shipping address
+ Given I have product "Summer T-Shirt" in the cart
+ And I am at the checkout addressing step
+ When I specify the email as "john.doe@example.com"
+ And I specify the billing address as "Brooklyn", "9036 Country Club Ave.", "11230", "United States" for "John Doe"
+ And I specify the shipping address as "Brooklyn", "70 Joy Ridge St", "11225", "United States" for "Jane Doe"
+ And I complete the addressing step
+ And I decide to change my address
+ And shipping address should be visible
+
+ @ui @javascript
+ Scenario: Going back to addressing step after not submitting a different shipping address
+ Given I have product "Summer T-Shirt" in the cart
+ And I am at the checkout addressing step
+ When I specify the email as "john.doe@example.com"
+ And I specify the billing address as "Brooklyn", "9036 Country Club Ave.", "11230", "United States" for "John Doe"
+ And I complete the addressing step
+ And I decide to change my address
+ And shipping address should not be visible
diff --git a/src/Sylius/Behat/Context/Ui/Shop/Checkout/CheckoutAddressingContext.php b/src/Sylius/Behat/Context/Ui/Shop/Checkout/CheckoutAddressingContext.php
index d6c9e454a9..4b524b13d5 100644
--- a/src/Sylius/Behat/Context/Ui/Shop/Checkout/CheckoutAddressingContext.php
+++ b/src/Sylius/Behat/Context/Ui/Shop/Checkout/CheckoutAddressingContext.php
@@ -377,6 +377,38 @@ final class CheckoutAddressingContext implements Context
Assert::true($this->addressComparator->equal($address, $this->addressPage->getPreFilledBillingAddress()));
}
+ /**
+ * @Then different shipping address should be checked
+ */
+ public function differentShippingAddressShouldBeChecked(): void
+ {
+ Assert::true($this->addressPage->isDifferentShippingAddressChecked());
+ }
+
+ /**
+ * @Then different shipping address should not be checked
+ */
+ public function differentShippingAddressShouldNotBeChecked(): void
+ {
+ Assert::false($this->addressPage->isDifferentShippingAddressChecked());
+ }
+
+ /**
+ * @Then shipping address should be visible
+ */
+ public function shippingAddressShouldBeVisible(): void
+ {
+ Assert::true($this->addressPage->isShippingAddressVisible());
+ }
+
+ /**
+ * @Then shipping address should not be visible
+ */
+ public function shippingAddressShouldNotBeVisible(): void
+ {
+ Assert::false($this->addressPage->isShippingAddressVisible());
+ }
+
/**
* @Then /^I should(?:| also) be notified that the "([^"]+)" and the "([^"]+)" in (shipping|billing) details are required$/
*/
diff --git a/src/Sylius/Behat/Page/Shop/Checkout/AddressPage.php b/src/Sylius/Behat/Page/Shop/Checkout/AddressPage.php
index ba88316674..2278fda38a 100644
--- a/src/Sylius/Behat/Page/Shop/Checkout/AddressPage.php
+++ b/src/Sylius/Behat/Page/Shop/Checkout/AddressPage.php
@@ -16,6 +16,7 @@ namespace Sylius\Behat\Page\Shop\Checkout;
use Behat\Mink\Driver\Selenium2Driver;
use Behat\Mink\Element\NodeElement;
use Behat\Mink\Exception\ElementNotFoundException;
+use Behat\Mink\Exception\UnsupportedDriverActionException;
use Behat\Mink\Session;
use DMore\ChromeDriver\ChromeDriver;
use FriendsOfBehat\PageObjectExtension\Page\SymfonyPage;
@@ -68,6 +69,21 @@ class AddressPage extends SymfonyPage implements AddressPageInterface
$billingAddressSwitch->check();
}
+ public function isDifferentShippingAddressChecked(): bool
+ {
+ return $this->getElement('different_shipping_address')->isChecked();
+ }
+
+ public function isShippingAddressVisible(): bool
+ {
+ try {
+ return $this->getElement('shipping_address')->isVisible();
+ } catch (UnsupportedDriverActionException $e) {
+ // it's visible by default and is being hidden with JS
+ return true;
+ }
+ }
+
public function checkInvalidCredentialsValidation(): bool
{
/** @var NodeElement $validationElement */
@@ -285,6 +301,7 @@ class AddressPage extends SymfonyPage implements AddressPageInterface
'login_password' => '[data-test-password-input]',
'login_validation_error' => '[data-test-login-validation-error]',
'next_step' => '[data-test-next-step]',
+ 'shipping_address' => '[data-test-shipping-address]',
'shipping_address_book' => '[data-test-shipping-address] [data-test-address-book]',
'shipping_city' => '[data-test-shipping-city]',
'shipping_country' => '[data-test-shipping-country]',
diff --git a/src/Sylius/Behat/Page/Shop/Checkout/AddressPageInterface.php b/src/Sylius/Behat/Page/Shop/Checkout/AddressPageInterface.php
index 34e4a8c790..130319e62d 100644
--- a/src/Sylius/Behat/Page/Shop/Checkout/AddressPageInterface.php
+++ b/src/Sylius/Behat/Page/Shop/Checkout/AddressPageInterface.php
@@ -71,4 +71,8 @@ interface AddressPageInterface extends SymfonyPageInterface
/** @return string[] */
public function getAvailableBillingCountries(): array;
+
+ public function isDifferentShippingAddressChecked(): bool;
+
+ public function isShippingAddressVisible(): bool;
}
diff --git a/src/Sylius/Bundle/CoreBundle/Form/Type/Checkout/AddressType.php b/src/Sylius/Bundle/CoreBundle/Form/Type/Checkout/AddressType.php
index a6db4e84d9..49e8a2a6c5 100644
--- a/src/Sylius/Bundle/CoreBundle/Form/Type/Checkout/AddressType.php
+++ b/src/Sylius/Bundle/CoreBundle/Form/Type/Checkout/AddressType.php
@@ -16,6 +16,8 @@ namespace Sylius\Bundle\CoreBundle\Form\Type\Checkout;
use Sylius\Bundle\AddressingBundle\Form\Type\AddressType as SyliusAddressType;
use Sylius\Bundle\CoreBundle\Form\Type\Customer\CustomerCheckoutGuestType;
use Sylius\Bundle\ResourceBundle\Form\Type\AbstractResourceType;
+use Sylius\Component\Addressing\Comparator\AddressComparatorInterface;
+use Sylius\Component\Core\Model\AddressInterface;
use Sylius\Component\Core\Model\CustomerInterface;
use Sylius\Component\Core\Model\OrderInterface;
use Sylius\Component\Customer\Model\CustomerAwareInterface;
@@ -29,6 +31,29 @@ use Webmozart\Assert\Assert;
final class AddressType extends AbstractResourceType
{
+ /** @var AddressComparatorInterface|null */
+ private $addressComparator;
+
+ public function __construct(string $dataClass, array $validationGroups = [], ?AddressComparatorInterface $addressComparator = null)
+ {
+ parent::__construct($dataClass, $validationGroups);
+
+ if (null === $addressComparator) {
+ @trigger_error(
+ sprintf(
+ 'Not passing an $addressComparator to "%s" constructor is deprecated since Sylius 1.8 and will be impossible in Sylius 2.0.',
+ __CLASS__,
+ ),
+ \E_USER_DEPRECATED
+ );
+ }
+
+ $this->addressComparator = $addressComparator;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
@@ -44,11 +69,11 @@ final class AddressType extends AbstractResourceType
])
->addEventListener(FormEvents::PRE_SET_DATA, static function (FormEvent $event): void {
$form = $event->getForm();
- $order = $event->getData();
+
+ Assert::isInstanceOf($event->getData(), OrderInterface::class);
/** @var OrderInterface $order */
- Assert::isInstanceOf($order, OrderInterface::class);
-
+ $order = $event->getData();
$channel = $order->getChannel();
$form
@@ -63,6 +88,18 @@ final class AddressType extends AbstractResourceType
])
;
})
+ ->addEventListener(FormEvents::POST_SET_DATA, function (FormEvent $event): void {
+ $form = $event->getForm();
+
+ Assert::isInstanceOf($event->getData(), OrderInterface::class);
+
+ /** @var OrderInterface $order */
+ $order = $event->getData();
+ $areAddressesDifferent = $this->areAddressesDifferent($order->getBillingAddress(), $order->getShippingAddress());
+
+ $form->get('differentBillingAddress')->setData($areAddressesDifferent);
+ $form->get('differentShippingAddress')->setData($areAddressesDifferent);
+ })
->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) use ($options): void {
$form = $event->getForm();
$resource = $event->getData();
@@ -114,4 +151,13 @@ final class AddressType extends AbstractResourceType
{
return 'sylius_checkout_address';
}
+
+ private function areAddressesDifferent(?AddressInterface $firstAddress, ?AddressInterface $secondAddress): bool
+ {
+ if (null === $this->addressComparator || null === $firstAddress || null === $secondAddress) {
+ return false;
+ }
+
+ return !$this->addressComparator->equal($firstAddress, $secondAddress);
+ }
}
diff --git a/src/Sylius/Bundle/CoreBundle/Resources/config/services/checkout.xml b/src/Sylius/Bundle/CoreBundle/Resources/config/services/checkout.xml
index c89ae5768e..650eb100d6 100644
--- a/src/Sylius/Bundle/CoreBundle/Resources/config/services/checkout.xml
+++ b/src/Sylius/Bundle/CoreBundle/Resources/config/services/checkout.xml
@@ -39,6 +39,7 @@
%sylius.model.order.class%
%sylius.form.type.checkout_address.validation_groups%
+