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.' );
+	}
+}