feature #11367 Check different shipping address field and display shipping address form (vvasiloi)

This PR was merged into the 1.7-dev branch.

Discussion
----------

When shipping and billing addresses are different

| Q               | A
| --------------- | -----
| Branch?         | 1.7
| Bug fix?        | yes
| New feature?    | no
| BC breaks?      | no
| Deprecations?   | yes
| Related tickets | fixes #11348
| License         | MIT


Commits
-------

9fe9181b6e check different shipping address field and display shipping address form when addresses are different
949d6f07cd review updates
bf7ff7f76b simplify address comparison
7cd003db17 fix psalm errors
This commit is contained in:
Łukasz Chruściel 2020-06-30 10:08:28 +02:00 committed by GitHub
commit 4493328bd6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 155 additions and 3 deletions

View file

@ -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

View file

@ -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$/
*/

View file

@ -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]',

View file

@ -71,4 +71,8 @@ interface AddressPageInterface extends SymfonyPageInterface
/** @return string[] */
public function getAvailableBillingCountries(): array;
public function isDifferentShippingAddressChecked(): bool;
public function isShippingAddressVisible(): bool;
}

View file

@ -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);
}
}

View file

@ -39,6 +39,7 @@
<service id="sylius.form.type.checkout_address" class="Sylius\Bundle\CoreBundle\Form\Type\Checkout\AddressType">
<argument>%sylius.model.order.class%</argument>
<argument>%sylius.form.type.checkout_address.validation_groups%</argument>
<argument type="service" id="sylius.address_comparator" />
<tag name="form.type" />
</service>
<service id="sylius.form.type.checkout_select_shipping" class="Sylius\Bundle\CoreBundle\Form\Type\Checkout\SelectShippingType">