Commit 4e0b17ac66b for woocommerce
commit 4e0b17ac66b812bfa9c0fc6fa212fd77106c3d6a
Author: Taha Paksu <3295+tpaksu@users.noreply.github.com>
Date: Wed Oct 7 15:32:16 2026 +0300
[tests] Pin when a separate shipping address is asked for (#69291)
* [tests] Pin that forcing shipping to billing stops the cart asking for a separate shipping address
* Add changefile(s) from automation for the following project(s): woocommerce
* [tests] Pin that No location by default leaves the shopper nowhere and quotes no tax
* Drop redundant teardowns and clear the session customer in the address tests
* Note the no-default customer-location tests in the changelog
* Add changefile(s) from automation for the following project(s): woocommerce
* Add changefile(s) from automation for the following project(s): woocommerce
---------
Co-authored-by: woocommercebot <woocommercebot@users.noreply.github.com>
diff --git a/plugins/woocommerce/changelog/69291-wooplug-7846-shipping-tests-which-address-is-used b/plugins/woocommerce/changelog/69291-wooplug-7846-shipping-tests-which-address-is-used
new file mode 100644
index 00000000000..02dc314990a
--- /dev/null
+++ b/plugins/woocommerce/changelog/69291-wooplug-7846-shipping-tests-which-address-is-used
@@ -0,0 +1,5 @@
+Significance: patch
+Type: dev
+Comment: Add tests for the forced-billing shipping destination and no-default customer-location settings.
+
+
diff --git a/plugins/woocommerce/tests/php/includes/class-wc-cart-ship-to-billing-test.php b/plugins/woocommerce/tests/php/includes/class-wc-cart-ship-to-billing-test.php
new file mode 100644
index 00000000000..5fa68b203d2
--- /dev/null
+++ b/plugins/woocommerce/tests/php/includes/class-wc-cart-ship-to-billing-test.php
@@ -0,0 +1,86 @@
+<?php
+/**
+ * Tests for forced billing deciding whether a separate shipping address is collected.
+ *
+ * @package WooCommerce\Tests\Cart
+ */
+
+declare( strict_types = 1 );
+
+/**
+ * WC_Cart::needs_shipping_address() under the "Shipping destination" setting.
+ *
+ * "Force shipping to the customer billing address" is the setting that decides which address an
+ * order ships to. Its server-side effect is that the cart stops asking for a separate shipping
+ * address, which is what hides the second form and writes the billing address onto the order. The
+ * legacy test for needs_shipping_address() re-derives the method's own formula and so never pins a
+ * concrete outcome; these set the outcome explicitly.
+ */
+class WC_Cart_Ship_To_Billing_Test extends WC_Unit_Test_Case {
+
+ /**
+ * Put a shippable product in the cart and a shipping method on the store, so the cart needs
+ * shipping at all.
+ */
+ public function setUp(): void {
+ parent::setUp();
+
+ $zone = new WC_Shipping_Zone();
+ $zone->set_zone_name( 'Ship to billing' );
+ $zone->save();
+ $zone->add_shipping_method( 'flat_rate' );
+ WC_Cache_Helper::get_transient_version( 'shipping', true );
+ delete_transient( 'wc_shipping_method_count' );
+
+ $product = WC_Helper_Product::create_simple_product();
+ WC()->cart->add_to_cart( $product->get_id(), 1 );
+ }
+
+ /**
+ * With the destination set to the shipping address, a cart that needs shipping asks for a
+ * separate shipping address.
+ *
+ * @testdox A cart that needs shipping asks for a shipping address when the destination is the shipping address.
+ */
+ public function test_a_separate_shipping_address_is_asked_for_when_the_destination_is_shipping(): void {
+ update_option( 'woocommerce_ship_to_destination', 'shipping' );
+
+ $this->assertTrue( WC()->cart->needs_shipping(), 'The fixture cart should need shipping, or this proves nothing.' );
+ $this->assertTrue(
+ WC()->cart->needs_shipping_address(),
+ 'A separate shipping address should be asked for when shipping is not forced to billing.'
+ );
+ }
+
+ /**
+ * Forcing shipping to the billing address stops the cart asking for a separate shipping
+ * address, which is what hides the second form and sends the billing address to the order.
+ *
+ * @testdox Forcing shipping to the billing address stops the cart asking for a separate one.
+ */
+ public function test_forced_billing_stops_asking_for_a_shipping_address(): void {
+ update_option( 'woocommerce_ship_to_destination', 'billing_only' );
+
+ $this->assertTrue( WC()->cart->needs_shipping(), 'The cart still needs shipping; only the address question changes.' );
+ $this->assertFalse(
+ WC()->cart->needs_shipping_address(),
+ 'With billing forced, no separate shipping address should be asked for.'
+ );
+ }
+
+ /**
+ * "Default to customer billing address" (the plain billing value, not billing_only) leaves the
+ * shipping address question in place: it changes the default, not whether the form appears.
+ *
+ * @testdox Defaulting to billing without forcing still asks for a shipping address.
+ */
+ public function test_defaulting_to_billing_without_forcing_still_asks(): void {
+ update_option( 'woocommerce_ship_to_destination', 'billing' );
+
+ $this->assertTrue( WC()->cart->needs_shipping(), 'The cart should need shipping, or the address question below proves nothing.' );
+ $this->assertTrue(
+ WC()->cart->needs_shipping_address(),
+ 'Only the forced billing_only value removes the shipping address; the plain billing default keeps it.'
+ );
+ }
+}
diff --git a/plugins/woocommerce/tests/php/includes/class-wc-no-default-location-test.php b/plugins/woocommerce/tests/php/includes/class-wc-no-default-location-test.php
new file mode 100644
index 00000000000..ee2c5b92b41
--- /dev/null
+++ b/plugins/woocommerce/tests/php/includes/class-wc-no-default-location-test.php
@@ -0,0 +1,106 @@
+<?php
+/**
+ * Tests for the "No location by default" customer-location setting.
+ *
+ * @package WooCommerce\Tests\Customer
+ */
+
+declare( strict_types = 1 );
+
+use Automattic\WooCommerce\Enums\DefaultCustomerAddress;
+
+/**
+ * "No location by default" (Settings > General > Default customer location).
+ *
+ * With it chosen, a shopper who has entered no address is assumed to be nowhere, so they are quoted
+ * no tax until they say where they are. Only the helper that reads the setting was pinned before;
+ * these pin the end: an empty default location, and a real cart that quotes no tax against it.
+ */
+class WC_No_Default_Location_Test extends WC_Unit_Test_Case {
+
+ /**
+ * The session customer to restore, since the tests replace it.
+ *
+ * @var WC_Customer
+ */
+ private $original_customer;
+
+ /**
+ * Turn taxes on, put a US rate in place, and a cart with a taxable product, so "no tax quoted"
+ * is a real outcome rather than the result of taxes being off or an empty cart.
+ */
+ public function setUp(): void {
+ parent::setUp();
+
+ update_option( 'woocommerce_calc_taxes', 'yes' );
+ update_option( 'woocommerce_tax_based_on', 'shipping' );
+ update_option( 'woocommerce_default_country', 'US:CA' );
+ WC_Tax::_insert_tax_rate(
+ array(
+ 'tax_rate_country' => 'US',
+ 'tax_rate_state' => '',
+ 'tax_rate' => '10.0000',
+ 'tax_rate_name' => 'US Tax',
+ 'tax_rate_priority' => 1,
+ 'tax_rate_compound' => 0,
+ 'tax_rate_shipping' => 1,
+ 'tax_rate_order' => 1,
+ 'tax_rate_class' => '',
+ )
+ );
+
+ $product = WC_Helper_Product::create_simple_product();
+ $product->set_regular_price( 100 );
+ $product->save();
+ WC()->cart->add_to_cart( $product->get_id(), 1 );
+
+ // new WC_Customer( 0, true ) in the tests reads the shared session, so an address a
+ // previous test left there would decide the result. Save the customer to restore it, and
+ // start from an empty session customer so the outcome is the setting's doing.
+ $this->original_customer = WC()->customer;
+ WC()->session->set( 'customer', null );
+ }
+
+ /**
+ * Restore the session customer the tests replaced; the base teardown rolls back the rest.
+ */
+ public function tearDown(): void {
+ WC()->session->set( 'customer', null );
+ WC()->customer = $this->original_customer;
+ parent::tearDown();
+ }
+
+ /**
+ * With no default location, a shopper who entered no address is placed nowhere, so the default
+ * location carries no country and the cart quotes no tax.
+ *
+ * @testdox No location by default leaves the shopper nowhere, so the cart quotes no tax.
+ */
+ public function test_no_default_location_quotes_no_tax(): void {
+ update_option( 'woocommerce_default_customer_address', DefaultCustomerAddress::NO_DEFAULT );
+
+ $this->assertSame( '', wc_get_customer_default_location()['country'], 'No default location should leave the country empty.' );
+
+ WC()->customer = new WC_Customer( 0, true );
+ $this->assertSame( '', WC()->customer->get_taxable_address()[0], 'The taxable address should carry no country.' );
+
+ WC()->cart->calculate_totals();
+ $this->assertEquals( 0, WC()->cart->get_taxes_total(), 'With the shopper placed nowhere, no tax should be quoted.' );
+ }
+
+ /**
+ * The contrast: with "Shop base address", the shopper is placed at the shop's country, where the
+ * US rate applies, so the empty result above is the setting's doing rather than taxes being off.
+ *
+ * @testdox Shop base address places the shopper at the shop, where the rate is quoted.
+ */
+ public function test_shop_base_places_the_shopper_at_the_shop(): void {
+ update_option( 'woocommerce_default_customer_address', DefaultCustomerAddress::BASE );
+
+ WC()->customer = new WC_Customer( 0, true );
+ $this->assertSame( 'US', WC()->customer->get_taxable_address()[0], 'The shopper should be placed at the shop country.' );
+
+ WC()->cart->calculate_totals();
+ $this->assertGreaterThan( 0, WC()->cart->get_taxes_total(), 'At the shop, the US rate should be quoted, or the other test proves nothing.' );
+ }
+}