Commit 3db280ab0bf for woocommerce
commit 3db280ab0bf49e98385ee25b5bf94313320f52e0
Author: Vlad Olaru <vlad.olaru@automattic.com>
Date: Tue Sep 15 17:23:10 2026 +0300
[tests] Demote the my-account shipping-address E2E test to PHPUnit (#68633)
* test(my-account): Move address saving below E2E
my-account-addresses.spec.ts ran the same journey twice: log in
through the storefront, open an address form, fill it, save, and
read the result back off the Addresses page. Once for billing, once
for shipping. They differed only in the address type the endpoint was
given, and in billing carrying one extra field, the phone number.
Move the persistence contract to WC_Form_Handler_Test, where a data
provider runs both types through the real save_address() handler
with a real nonce and a real customer-role user, and reads the
values back from a freshly constructed WC_Customer. It asserts every
field the form submits, ten for shipping and eleven for billing,
where the browser titles filled seven and eight, and it asserts that
no error notice was produced.
Keep the billing journey in the browser. It is the one that proves
the storefront login, the form and the saved-address rendering still
work together; running it a second time for shipping proved only
that a parameter is passed through.
This file is merged onto trunk's version rather than taken from the
migration branch. Trunk added 401 lines to it after the branch was
cut, seventeen members in all, and taking the branch's copy wholesale
would have deleted every one of them.
setUp and tearDown also capture and restore $wp->query_vars, which
trunk does not, because the new test writes query_vars['edit-address'].
Nothing in the class depends on that restore today: PHPUnit runs in
declaration order, and the only tests below the new one are the four
save_account_details tests, which do not read query_vars and neither
does the handler they exercise. It keeps the value out of those and
out of anything added later.
Consolidates the mega-branch slice:
- Slice 102: test(account): Move address persistence below E2E
Refs TESTOPS-288
Refs #68046
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* test(php): Drop the duplicated $wp restore from the form handler test
`WP_UnitTestCase_Base::tear_down()` replaces `$wp` with a fresh `new WP()`
before the next test runs, so saving and restoring `$wp->query_vars`
around each test did nothing. Remove the restore, the capture in setUp
and the property, which leaves both hooks without a use for the global.
Refs TESTOPS-288
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
diff --git a/plugins/woocommerce/changelog/testops-288-my-account-addresses b/plugins/woocommerce/changelog/testops-288-my-account-addresses
new file mode 100644
index 00000000000..101f651d991
--- /dev/null
+++ b/plugins/woocommerce/changelog/testops-288-my-account-addresses
@@ -0,0 +1,4 @@
+Significance: patch
+Type: dev
+Comment: Move my-account shipping-address saving below E2E; two browser titles become one.
+
diff --git a/plugins/woocommerce/tests/e2e/tests/my-account/my-account-addresses.spec.ts b/plugins/woocommerce/tests/e2e/tests/my-account/my-account-addresses.spec.ts
index 7695d8376d4..afa20abf382 100644
--- a/plugins/woocommerce/tests/e2e/tests/my-account/my-account-addresses.spec.ts
+++ b/plugins/woocommerce/tests/e2e/tests/my-account/my-account-addresses.spec.ts
@@ -75,50 +75,4 @@ test.describe( 'Customer can manage addresses in My Account > Addresses page', (
page.locator( `:text("Frisco, CA 97403")` )
).toBeVisible();
} );
-
- test( 'can add shipping address from my account', async ( { page } ) => {
- await page.goto( 'my-account/edit-address/' );
- // sign in as the "customer" user
- await page.locator( '#username' ).fill( customer.username );
- await page.locator( '#password' ).fill( customer.password );
- await page.locator( 'text=Log in' ).click();
-
- // verify that the page exists and that there are no added addresses
- await expect(
- page.getByRole( 'heading', { name: 'Addresses' } )
- ).toBeVisible();
- await expect(
- page.locator( '.woocommerce-Address' ).nth( 1 )
- ).toContainText( 'You have not set up this type of address yet.' );
-
- // go to add shipping address
- await page.goto( 'my-account/edit-address/shipping' );
- await expect(
- page.getByRole( 'heading', { name: 'Shipping address' } )
- ).toBeVisible();
- await page.locator( '#shipping_first_name' ).fill( 'John' );
- await page.locator( '#shipping_last_name' ).fill( 'Doe Shipping' );
- await page
- .locator( '#shipping_address_1' )
- .fill( '456 Nevergreen Terrace' );
- await page.locator( '#shipping_city' ).fill( 'New York' );
- await page.locator( '#shipping_country' ).selectOption( 'US' );
- await page.locator( '#shipping_state' ).selectOption( 'NY' );
- await page.locator( '#shipping_postcode' ).fill( '10010' );
- await page.locator( 'text=Save address' ).click();
-
- // verify shipping address has been applied
- await expect(
- page.getByText( 'Address changed successfully.' )
- ).toBeVisible();
- await expect(
- page.locator( `:text("John Doe Shipping")` )
- ).toBeVisible();
- await expect(
- page.locator( `:text("456 Nevergreen Terrace")` )
- ).toBeVisible();
- await expect(
- page.locator( `:text("New York, NY 10010")` )
- ).toBeVisible();
- } );
} );
diff --git a/plugins/woocommerce/tests/php/includes/class-wc-form-handler-test.php b/plugins/woocommerce/tests/php/includes/class-wc-form-handler-test.php
index bf23ec3fd68..b9dc6ca34da 100644
--- a/plugins/woocommerce/tests/php/includes/class-wc-form-handler-test.php
+++ b/plugins/woocommerce/tests/php/includes/class-wc-form-handler-test.php
@@ -413,6 +413,87 @@ class WC_Form_Handler_Test extends WC_Unit_Test_Case {
$this->dispatch_cancel_order_expecting_redirect( wp_make_link_relative( $order->get_cancel_endpoint() ) );
}
+ /**
+ * @testdox save_address() persists a valid $address_type address through the selected endpoint.
+ *
+ * @dataProvider provide_address_types
+ * @covers WC_Form_Handler::save_address()
+ *
+ * @param string $address_type Address type.
+ * @param array<string,string> $fields Unprefixed address fields.
+ */
+ public function test_save_address_persists_valid_address( string $address_type, array $fields ): void {
+ global $wp;
+
+ $user_id = self::factory()->user->create(
+ array(
+ 'user_login' => $address_type . '-address-customer',
+ 'user_email' => $address_type . '-address-customer@example.test',
+ 'role' => 'customer',
+ )
+ );
+
+ wp_set_current_user( $user_id );
+ $wp->query_vars['edit-address'] = $address_type;
+ $this->prepare_address_request( $address_type, $fields );
+
+ $this->dispatch_address_save_expecting_redirect();
+
+ $customer = new WC_Customer( $user_id );
+ $error_notices = wc_get_notices( 'error' );
+ $success_notices = wc_get_notices( 'success' );
+
+ $this->assertEmpty( $error_notices, 'A valid address should not add error notices.' );
+ $this->assertCount( 1, $success_notices, 'A valid address should add one success notice.' );
+ $this->assertSame( 'Address changed successfully.', $success_notices[0]['notice'] );
+
+ foreach ( $fields as $field => $expected ) {
+ $getter = "get_{$address_type}_{$field}";
+ $this->assertSame( $expected, $customer->{$getter}(), "The persisted {$address_type}_{$field} value should match the submitted address." );
+ }
+ }
+
+ /**
+ * Provides complete billing and shipping address requests.
+ *
+ * @return array<string,array{string,array<string,string>}>
+ */
+ public static function provide_address_types(): array {
+ return array(
+ 'billing' => array(
+ 'billing',
+ array(
+ 'first_name' => 'Ada',
+ 'last_name' => 'Billing',
+ 'company' => 'Analytical Engines',
+ 'address_1' => '123 Market Street',
+ 'address_2' => 'Suite 4',
+ 'city' => 'San Francisco',
+ 'state' => 'CA',
+ 'postcode' => '94105',
+ 'country' => 'US',
+ 'phone' => '4155550100',
+ 'email' => 'ada.billing@example.test',
+ ),
+ ),
+ 'shipping' => array(
+ 'shipping',
+ array(
+ 'first_name' => 'Grace',
+ 'last_name' => 'Shipping',
+ 'company' => 'Compiler Works',
+ 'address_1' => '456 Madison Avenue',
+ 'address_2' => 'Floor 5',
+ 'city' => 'New York',
+ 'state' => 'NY',
+ 'postcode' => '10010',
+ 'country' => 'US',
+ 'phone' => '2125550100',
+ ),
+ ),
+ );
+ }
+
/**
* @testdox save_account_details() saves other account fields when an email-like display name is unchanged.
*
@@ -651,6 +732,30 @@ class WC_Form_Handler_Test extends WC_Unit_Test_Case {
$pending->setValue( null, false );
}
+ /**
+ * Prepares request globals for the address handler.
+ *
+ * @param string $address_type Address type.
+ * @param array<string,string> $fields Unprefixed address fields.
+ */
+ private function prepare_address_request( string $address_type, array $fields ): void {
+ $prefixed_fields = array();
+
+ foreach ( $fields as $field => $value ) {
+ $prefixed_fields[ $address_type . '_' . $field ] = $value;
+ }
+
+ $_POST = array_merge(
+ array(
+ 'action' => 'edit_address',
+ ),
+ $prefixed_fields
+ );
+ $_REQUEST = array(
+ 'woocommerce-edit-address-nonce' => wp_create_nonce( 'woocommerce-edit_address' ),
+ );
+ }
+
/**
* Dispatches the account-details save handler and expects its success redirect.
*/
@@ -668,4 +773,22 @@ class WC_Form_Handler_Test extends WC_Unit_Test_Case {
$this->fail( 'Expected save_account_details() to redirect after a successful save.' );
}
+
+ /**
+ * Dispatches the address handler and expects its success redirect.
+ */
+ private function dispatch_address_save_expecting_redirect(): void {
+ try {
+ WC_Form_Handler::save_address();
+ } catch ( RuntimeException $e ) {
+ $this->assertSame(
+ wc_get_endpoint_url( 'edit-address', '', wc_get_page_permalink( 'myaccount' ) ),
+ $e->getMessage(),
+ 'Successful address saves should redirect to Addresses.'
+ );
+ return;
+ }
+
+ $this->fail( 'Expected save_address() to redirect after a successful save. Notices: ' . wp_json_encode( wc_get_notices() ) );
+ }
}