Commit 368f1e14add for woocommerce
commit 368f1e14adde55b590af57828b53a236bd1d03a8
Author: Vlad Olaru <vlad.olaru@automattic.com>
Date: Tue Nov 3 16:39:25 2026 +0200
[tests] Isolate incidental HTTP requests in PHPUnit tests (#70524)
* test(phpunit): Isolate incidental HTTP requests
Tests prepare admin screens and status data that trigger incidental HTTP.
Provide URL-matched responses and suppress unrelated update checks.
Keep these mechanics separate from database fixture reuse.
* docs(changelog): Add PHPUnit HTTP isolation entry
Record the internal testing change without a merchant-facing note.
* test: Fix onboarding profile isolation in PHPUnit fixtures
Two rule-processor teardowns wrote options after WordPress rolled back
the test transaction. That leaked an onboarding profile into dashboard
tests and triggered unrelated remote inbox processing.
Rely on the inherited rollback, remove the unused dashboard inbox
response fixture, and cover the completion callback explicitly with a
small cached feed.
* test: Use the base HTTP responder for incidental request mocks
Six test classes on this branch mocked incidental HTTP requests with
their own pre_http_request filters, each repeating the same preemption
guard and request matching. WP_HTTP_TestCase, which every one of them
extends, already offers a per-test-case responder for this, and the V3
system status test uses it. Review feedback asked for one mocking
pattern across the suite.
Set $this->http_responder in each class (or, for the helper updater,
in the three tests that write the update_plugins transient) and drop
the duplicated preemption guards. The base listener still records
every request. Responses and matching rules are unchanged.
Refs #70524
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
diff --git a/plugins/woocommerce/changelog/test-phpunit-http-response-mocks b/plugins/woocommerce/changelog/test-phpunit-http-response-mocks
new file mode 100644
index 00000000000..a7c74f324b2
--- /dev/null
+++ b/plugins/woocommerce/changelog/test-phpunit-http-response-mocks
@@ -0,0 +1,3 @@
+Significance: patch
+Type: dev
+Comment: Isolate HTTP requests in PHPUnit tests; no production change.
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/rest-api/Tests/Version2/system-status.php b/plugins/woocommerce/tests/legacy/unit-tests/rest-api/Tests/Version2/system-status.php
index a18b7d7237d..b09709af3a1 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/rest-api/Tests/Version2/system-status.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/rest-api/Tests/Version2/system-status.php
@@ -44,6 +44,14 @@ class WC_Tests_REST_System_Status_V2 extends WC_REST_Unit_Test_Case {
);
}
+ /**
+ * Supply deterministic external responses for the real system status report.
+ */
+ public function setUp(): void {
+ parent::setUp();
+ $this->http_responder = array( $this, 'mock_status_http_responses' );
+ }
+
/**
* Fetches the System Status Report data and caches it.
* @param int $user The ID of a WordPress user to switch to before fetching the data.
@@ -413,4 +421,58 @@ class WC_Tests_REST_System_Status_V2 extends WC_REST_Unit_Test_Case {
$this->assertArrayHasKey( 'success', $properties );
$this->assertArrayHasKey( 'message', $properties );
}
+
+ /**
+ * Supply captured public responses while retaining real status report parsing.
+ *
+ * @param array $request HTTP request arguments.
+ * @param string $url HTTP request URL.
+ * @return array|false Fixture response, or false for another request.
+ */
+ protected function mock_status_http_responses( $request, $url ) {
+ $host = wp_parse_url( $url, PHP_URL_HOST );
+ $path = wp_parse_url( $url, PHP_URL_PATH );
+ $method = $request['method'] ?? 'GET';
+
+ if ( 'api.wordpress.org' === $host && '/themes/info/1.2/' === $path && 'GET' === $method ) {
+ return array(
+ 'headers' => array(
+ 'cache-for' => '',
+ 'content-type' => 'application/json; charset=UTF-8',
+ ),
+ 'body' => '{"name":"Default","slug":"default","version":"1.7.2","preview_url":"https://wp-themes.com/default/","author":{"user_nicename":"wordpressdotorg","profile":"https://profiles.wordpress.org/wordpressdotorg/","avatar":"https://secure.gravatar.com/avatar/178f40079143ff7464125e4fbc88e62024a16442920a6a3d6dfa3d7e626be20d?s=96&d=monsterid&r=g","display_name":"WordPress.org","author":false,"author_url":"http://binarybonsai.com/"},"screenshot_url":"//ts.w.org/wp-content/themes/default/screenshot.png?ver=1.7.2","rating":100,"num_ratings":3,"reviews_url":"https://wordpress.org/support/theme/default/reviews/","downloaded":592381,"last_updated":"2010-06-14","last_updated_time":"2010-06-14 22:06:29","creation_time":"2010-03-26 20:14:43","homepage":"https://wordpress.org/themes/default/","download_link":"https://downloads.wordpress.org/theme/default.1.7.2.zip","requires":false,"requires_php":false,"is_commercial":false,"external_support_url":false,"is_community":true,"external_repository_url":""}',
+ 'response' => array(
+ 'code' => 200,
+ ),
+ );
+ }
+
+ if ( 'www.paypal.com' === $host && '/cgi-bin/webscr' === $path && 'POST' === $method ) {
+ return array(
+ 'headers' => array(
+ 'cache-for' => '',
+ 'content-type' => 'text/html; charset=utf-8',
+ ),
+ 'body' => 'INVALID',
+ 'response' => array(
+ 'code' => 200,
+ ),
+ );
+ }
+
+ if ( 'woocommerce.com' === $host && '/wc-api/product-key-api' === $path && 'GET' === $method ) {
+ return array(
+ 'headers' => array(
+ 'cache-for' => '',
+ 'content-type' => 'application/json; charset=UTF-8',
+ ),
+ 'body' => '{"success":true,"data":{"success":true}}',
+ 'response' => array(
+ 'code' => 200,
+ ),
+ );
+ }
+
+ return false;
+ }
}
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/rest-api/Tests/Version3/system-status.php b/plugins/woocommerce/tests/legacy/unit-tests/rest-api/Tests/Version3/system-status.php
index 35fe32bdb8f..6c290e4830e 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/rest-api/Tests/Version3/system-status.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/rest-api/Tests/Version3/system-status.php
@@ -565,6 +565,26 @@ class WC_Tests_REST_System_Status extends WC_REST_Unit_Test_Case {
$mocked_response = array(
'response' => array( 'code' => 200 ),
);
+ } elseif ( 'api.wordpress.org' === wp_parse_url( $url, PHP_URL_HOST ) && '/themes/info/1.2/' === wp_parse_url( $url, PHP_URL_PATH ) ) {
+ $mocked_response = array(
+ 'body' => wp_json_encode(
+ array(
+ 'name' => 'Default',
+ 'slug' => 'default',
+ 'version' => '1.7.2',
+ 'preview_url' => 'https://wp-themes.com/default',
+ 'author' => 'wordpressdotorg',
+ 'screenshot_url' => '//ts.w.org/wp-content/themes/default/screenshot.png?ver=1.7.2',
+ 'rating' => 100,
+ 'num_ratings' => '3',
+ 'downloaded' => 296618,
+ 'last_updated' => '2010-06-14',
+ 'homepage' => 'https://wordpress.org/themes/default/',
+ 'download_link' => 'https://downloads.wordpress.org/theme/default.1.7.2.zip',
+ )
+ ),
+ 'response' => array( 'code' => 200 ),
+ );
} elseif ( 'https://api.wordpress.org/themes/info/1.0/' === $url ) {
$mocked_response = array(
'body' => 'O:8:"stdClass":12:{s:4:"name";s:7:"Default";s:4:"slug";s:7:"default";s:7:"version";s:5:"1.7.2";s:11:"preview_url";s:29:"https://wp-themes.com/default";s:6:"author";s:15:"wordpressdotorg";s:14:"screenshot_url";s:61:"//ts.w.org/wp-content/themes/default/screenshot.png?ver=1.7.2";s:6:"rating";d:100;s:11:"num_ratings";s:1:"3";s:10:"downloaded";i:296618;s:12:"last_updated";s:10:"2010-06-14";s:8:"homepage";s:37:"https://wordpress.org/themes/default/";s:13:"download_link";s:55:"https://downloads.wordpress.org/theme/default.1.7.2.zip";}',
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/onboarding-product-types.php b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/onboarding-product-types.php
index d53ed157f4b..7587ff27978 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/onboarding-product-types.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/onboarding-product-types.php
@@ -25,6 +25,8 @@ class WC_Admin_Tests_API_Onboarding_Product_Types extends WC_REST_Unit_Test_Case
*/
public function setUp(): void {
parent::setUp();
+ $this->http_responder = array( $this, 'mock_product_catalog_response' );
+
$this->user = $this->factory->user->create(
array(
'role' => 'administrator',
@@ -83,4 +85,30 @@ class WC_Admin_Tests_API_Onboarding_Product_Types extends WC_REST_Unit_Test_Case
$this->assertTrue( array_key_exists( 'product', $data_another_country['subscriptions'] ) );
}
+
+ /**
+ * Supply captured product fields for the real onboarding response parser.
+ *
+ * @param array $request HTTP request arguments.
+ * @param string $url HTTP request URL.
+ * @return array|false Fixture response, or false for another request.
+ */
+ protected function mock_product_catalog_response( $request, $url ) {
+ if ( 'woocommerce.com' !== wp_parse_url( $url, PHP_URL_HOST )
+ || '/wp-json/wccom-extensions/1.0/search' !== wp_parse_url( $url, PHP_URL_PATH )
+ || 'GET' !== ( $request['method'] ?? 'GET' ) ) {
+ return false;
+ }
+
+ return array(
+ 'headers' => array(
+ 'cache-for' => '',
+ 'content-type' => 'application/json; charset=UTF-8',
+ ),
+ 'body' => '{"products":[{"id":18618,"price":"$79","excerpt":"Offer add-ons like gift wrapping, special messages or other special options for your products.","link":"https://woocommerce.com/products/product-add-ons/?utm_source=extensionsscreen&utm_medium=product&utm_campaign=wcaddons","slug":"woocommerce-product-addons"},{"id":27147,"price":"$279","excerpt":"WooCommerce Subscriptions is a WooCommerce extension that lets customers subscribe to your products or services and pay on a weekly, monthly, or annual basis. It integrates with over 25 payment gateways for automatic recurring payments and supports automatic rebilling on failed subscription payments. Subscribers can manage their own plan — upgrading, downgrading, suspending, or canceling — and update their shipping address or payment method. It\'s a paid annual extension with a 30-day money-back guarantee.","link":"https://woocommerce.com/products/woocommerce-subscriptions/?utm_source=extensionsscreen&utm_medium=product&utm_campaign=wcaddons","slug":"woocommerce-subscriptions"},{"id":18716,"price":"$79","excerpt":"Offer personalized product bundles, bulk discount packages, and assembled products.","link":"https://woocommerce.com/products/product-bundles/?utm_source=extensionsscreen&utm_medium=product&utm_campaign=wcaddons","slug":"woocommerce-product-bundles"},{"id":390890,"price":"$249","excerpt":"WooCommerce Bookings is the official WooCommerce extension that lets store owners sell appointments, reservations, rentals, or classes with bookable time or date slots. It supports fixed time slots or flexible ranges, group and individual pricing, and resources — staff, rooms, or equipment — each with its own availability to prevent double-booking. It syncs with Google Calendar and works with any WooCommerce payment gateway. It\'s a paid annual extension with a 30-day money-back guarantee.","link":"https://woocommerce.com/products/woocommerce-bookings/?utm_source=extensionsscreen&utm_medium=product&utm_campaign=wcaddons","slug":"woocommerce-bookings"},{"id":958589,"price":"$199","excerpt":"Power your membership association, online magazine, elearning sites, and more with access control to content/products and member discounts.","link":"https://woocommerce.com/products/woocommerce-memberships/?utm_source=extensionsscreen&utm_medium=product&utm_campaign=wcaddons","slug":"woocommerce-memberships"}]}',
+ 'response' => array(
+ 'code' => 200,
+ ),
+ );
+ }
}
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/base-location-state-rule-processor.php b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/base-location-state-rule-processor.php
index d69972954c0..fe3f40bfde6 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/base-location-state-rule-processor.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/base-location-state-rule-processor.php
@@ -8,7 +8,6 @@
declare( strict_types = 1 );
use Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors\BaseLocationStateRuleProcessor;
-use Automattic\WooCommerce\Internal\Admin\Onboarding\OnboardingProfile;
/**
* class WC_Admin_Tests_RemoteSpecs_RuleProcessors_BaseLocationStateRuleProcessor
@@ -30,16 +29,6 @@ class WC_Admin_Tests_RemoteSpecs_RuleProcessors_BaseLocationStateRuleProcessor e
);
}
- /**
- * Tear down.
- */
- public function tearDown(): void {
- parent::tearDown();
- update_option( 'woocommerce_store_address', '' );
- update_option( 'woocommerce_default_country', 'US:CA' );
- update_option( OnboardingProfile::DATA_OPTION, array() );
- }
-
/**
* Tests that the processor returns false if country is not set.
*
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/onboarding-profile-rule-processor.php b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/onboarding-profile-rule-processor.php
index 9f59c1ab06f..6f470b58425 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/onboarding-profile-rule-processor.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/onboarding-profile-rule-processor.php
@@ -30,14 +30,6 @@ class WC_Admin_Tests_RemoteSpecs_RuleProcessors_OnboardingProfileRuleProcessor e
);
}
- /**
- * Tear down.
- */
- public function tearDown(): void {
- parent::tearDown();
- update_option( OnboardingProfile::DATA_OPTION, array() );
- }
-
/**
* Tests that the processor returns false if onboarding profile is empty.
*
diff --git a/plugins/woocommerce/tests/php/includes/admin/class-wc-admin-dashboard-setup-test.php b/plugins/woocommerce/tests/php/includes/admin/class-wc-admin-dashboard-setup-test.php
index 93bf1aee23c..6c80484516a 100644
--- a/plugins/woocommerce/tests/php/includes/admin/class-wc-admin-dashboard-setup-test.php
+++ b/plugins/woocommerce/tests/php/includes/admin/class-wc-admin-dashboard-setup-test.php
@@ -35,6 +35,7 @@ class WC_Admin_Dashboard_Setup_Test extends WC_Unit_Test_Case {
$this->default_country_option_existed = $missing_option !== $this->default_country_option_value;
parent::setUp();
+ $this->http_responder = array( $this, 'mock_dashboard_http_responses' );
// Set default country to non-US so that 'payments' task gets added but 'woocommerce-payments' doesn't,
// by default it won't be considered completed but we can manually change that as needed.
@@ -512,4 +513,34 @@ class WC_Admin_Dashboard_Setup_Test extends WC_Unit_Test_Case {
delete_option( 'woocommerce_onboarding_profile' );
}
+
+ /**
+ * Keep dashboard incentive requests local while retaining real response parsing.
+ *
+ * @param array $request HTTP request arguments.
+ * @param string $url HTTP request URL.
+ * @return array|false Fixture response, or false for another request.
+ */
+ protected function mock_dashboard_http_responses( $request, $url ) {
+ if ( 'GET' !== ( $request['method'] ?? 'GET' ) ) {
+ return false;
+ }
+ $host = wp_parse_url( $url, PHP_URL_HOST );
+ $path = wp_parse_url( $url, PHP_URL_PATH );
+
+ if ( 'public-api.wordpress.com' === $host && '/wpcom/v2/wcpay/incentives' === $path ) {
+ return array(
+ 'headers' => array(
+ 'cache-for' => '172800',
+ 'content-type' => 'application/json; charset=UTF-8',
+ ),
+ 'body' => '[{"id":"wcpay-promo-2023-action-discount","promo_id":"wcpay-promo-2023-action-discount","type":"welcome_page","cta_label":"Install WooPayments for free","tc_url":"https:\\/\\/woocommerce.com\\/terms-conditions\\/woopayments-action-promotion-2023\\/","description":"<b>Save 10%<\\/b> on payment processing costs in your <b>first three months<\\/b> when you sign up for WooPayments today.","task_header_content":"Power your payments with a simple, all-in-one option and <b>save 10% on payment processing costs in your first three months<\\/b>. See <a href=\\"https:\\/\\/woocommerce.com\\/terms-conditions\\/woopayments-action-promotion-2023\\/\\">Terms and Conditions<\\/a> for details.","task_badge":"Save 10% on payment processing fees"},{"id":"wcpay-promo-2023-action-discount__wc_settings_payments","promo_id":"wcpay-promo-2023-action-discount","type":"wc_settings_payments","description":"Use the native payments solution built and supported by Woo to accept online and in-person payments, track revenue, and handle all payment activity in one place.","cta_label":"Install and save 10%","tc_url":"https:\\/\\/woocommerce.com\\/terms-conditions\\/woopayments-action-promotion-2023\\/","title":"Save 10% on processing fees during your first 3 months when you sign up for WooPayments.","short_description":"Save 10% on processing fees during your first 3 months when you sign up for WooPayments.","badge":"Save 10% on processing fees"}]',
+ 'response' => array(
+ 'code' => 200,
+ ),
+ );
+ }
+
+ return false;
+ }
}
diff --git a/plugins/woocommerce/tests/php/includes/admin/class-wc-admin-notices-test.php b/plugins/woocommerce/tests/php/includes/admin/class-wc-admin-notices-test.php
index 47a33e0384a..7de193e9e14 100644
--- a/plugins/woocommerce/tests/php/includes/admin/class-wc-admin-notices-test.php
+++ b/plugins/woocommerce/tests/php/includes/admin/class-wc-admin-notices-test.php
@@ -12,6 +12,10 @@ class WC_Admin_Notices_Test extends WP_Ajax_UnitTestCase {
public function set_up() {
parent::set_up();
+ remove_action( 'admin_init', '_maybe_update_core' );
+ remove_action( 'admin_init', '_maybe_update_plugins' );
+ remove_action( 'admin_init', '_maybe_update_themes' );
+
include_once WC_ABSPATH . 'includes/admin/class-wc-admin-notices.php';
if ( ! has_action( 'wp_ajax_woocommerce_hide_notice', array( 'WC_Admin_Notices', 'ajax_hide_notice' ) ) ) {
diff --git a/plugins/woocommerce/tests/php/includes/admin/helper/class-wc-helper-updater-test.php b/plugins/woocommerce/tests/php/includes/admin/helper/class-wc-helper-updater-test.php
index 08a3fdfad36..929378239b4 100644
--- a/plugins/woocommerce/tests/php/includes/admin/helper/class-wc-helper-updater-test.php
+++ b/plugins/woocommerce/tests/php/includes/admin/helper/class-wc-helper-updater-test.php
@@ -976,6 +976,7 @@ class WC_Helper_Updater_Test extends WC_Unit_Test_Case {
* @testdox Connect notice is skipped when Core already renders an update row for the plugin.
*/
public function test_connect_notice_is_skipped_when_core_renders_an_update_row(): void {
+ $this->mock_plugin_row_update_check();
$this->prepare_plugins_screen();
$transient = new stdClass();
@@ -1064,6 +1065,7 @@ class WC_Helper_Updater_Test extends WC_Unit_Test_Case {
* @testdox Purchase notice links to the product page when the connected account holds no subscription.
*/
public function test_purchase_notice_renders_without_a_subscription(): void {
+ $this->mock_plugin_row_update_check();
$this->prepare_plugins_screen();
$this->set_subscriptions( array() );
@@ -1655,6 +1657,7 @@ class WC_Helper_Updater_Test extends WC_Unit_Test_Case {
* @testdox Subscription notice is skipped when Core already renders an update row for the plugin.
*/
public function test_subscription_notice_is_skipped_when_core_renders_an_update_row(): void {
+ $this->mock_plugin_row_update_check();
$this->prepare_plugins_screen();
$this->set_subscriptions( array() );
@@ -2307,6 +2310,22 @@ class WC_Helper_Updater_Test extends WC_Unit_Test_Case {
);
}
+ /**
+ * Keep fixture transient writes from contacting the public update service.
+ */
+ private function mock_plugin_row_update_check(): void {
+ $this->http_responder = static function ( $request, $url ) {
+ if ( 'POST' !== ( $request['method'] ?? '' ) || 'https://woocommerce.com/wp-json/helper/1.0/update-check-public' !== $url ) {
+ return false;
+ }
+
+ return array(
+ 'response' => array( 'code' => 200 ),
+ 'body' => wp_json_encode( array() ),
+ );
+ };
+ }
+
/**
* Mock WC_Helper_API response for testing.
*
diff --git a/plugins/woocommerce/tests/php/includes/rest-api/Controllers/Version2/class-wc-rest-system-status-v2-controller-test.php b/plugins/woocommerce/tests/php/includes/rest-api/Controllers/Version2/class-wc-rest-system-status-v2-controller-test.php
index 5f31d40b009..28457fabe56 100644
--- a/plugins/woocommerce/tests/php/includes/rest-api/Controllers/Version2/class-wc-rest-system-status-v2-controller-test.php
+++ b/plugins/woocommerce/tests/php/includes/rest-api/Controllers/Version2/class-wc-rest-system-status-v2-controller-test.php
@@ -44,6 +44,11 @@ class WC_REST_System_Status_V2_Controller_Test extends WC_REST_Unit_Test_Case {
*/
public function setUp(): void {
parent::setUp();
+ $this->http_responder = array( $this, 'mock_status_http_responses' );
+
+ remove_action( 'upgrader_process_complete', 'wp_version_check' );
+ remove_action( 'upgrader_process_complete', 'wp_update_plugins' );
+ remove_action( 'upgrader_process_complete', 'wp_update_themes' );
$this->sut = new WC_REST_System_Status_V2_Controller();
delete_transient( 'wc_system_status_theme_info' );
ActionSchedulerUtil::reset_cache();
@@ -254,6 +259,34 @@ class WC_REST_System_Status_V2_Controller_Test extends WC_REST_Unit_Test_Case {
$this->assertSame( $expected, $environment['wp_memory_limit'] );
}
+ /**
+ * Supply captured public responses while retaining real status report parsing.
+ *
+ * @param array $request HTTP request arguments.
+ * @param string $url HTTP request URL.
+ * @return array|false Fixture response, or false for another request.
+ */
+ protected function mock_status_http_responses( $request, $url ) {
+ $host = wp_parse_url( $url, PHP_URL_HOST );
+ $path = wp_parse_url( $url, PHP_URL_PATH );
+ $method = $request['method'] ?? 'GET';
+
+ if ( 'api.wordpress.org' === $host && '/themes/info/1.2/' === $path && 'GET' === $method ) {
+ return array(
+ 'headers' => array(
+ 'cache-for' => '',
+ 'content-type' => 'application/json; charset=UTF-8',
+ ),
+ 'body' => '{"name":"Default","slug":"default","version":"1.7.2","preview_url":"https://wp-themes.com/default/","author":{"user_nicename":"wordpressdotorg","profile":"https://profiles.wordpress.org/wordpressdotorg/","avatar":"https://secure.gravatar.com/avatar/178f40079143ff7464125e4fbc88e62024a16442920a6a3d6dfa3d7e626be20d?s=96&d=monsterid&r=g","display_name":"WordPress.org","author":false,"author_url":"http://binarybonsai.com/"},"screenshot_url":"//ts.w.org/wp-content/themes/default/screenshot.png?ver=1.7.2","rating":100,"num_ratings":3,"reviews_url":"https://wordpress.org/support/theme/default/reviews/","downloaded":592381,"last_updated":"2010-06-14","last_updated_time":"2010-06-14 22:06:29","creation_time":"2010-03-26 20:14:43","homepage":"https://wordpress.org/themes/default/","download_link":"https://downloads.wordpress.org/theme/default.1.7.2.zip","requires":false,"requires_php":false,"is_commercial":false,"external_support_url":false,"is_community":true,"external_repository_url":""}',
+ 'response' => array(
+ 'code' => 200,
+ ),
+ );
+ }
+
+ return false;
+ }
+
/**
* @testdox Should report the bundled Action Scheduler copy as loaded from WooCommerce and not risky.
*/
diff --git a/plugins/woocommerce/tests/php/src/Admin/PluginsHelperTest.php b/plugins/woocommerce/tests/php/src/Admin/PluginsHelperTest.php
index a56aa6ca5c1..ce82f421909 100644
--- a/plugins/woocommerce/tests/php/src/Admin/PluginsHelperTest.php
+++ b/plugins/woocommerce/tests/php/src/Admin/PluginsHelperTest.php
@@ -12,6 +12,17 @@ use WP_Error;
*/
class PluginsHelperTest extends WC_Unit_Test_Case {
+ /**
+ * Prevent unrelated update checks after the real upgrader runs.
+ */
+ public function setUp(): void {
+ parent::setUp();
+
+ remove_action( 'upgrader_process_complete', 'wp_version_check' );
+ remove_action( 'upgrader_process_complete', 'wp_update_plugins' );
+ remove_action( 'upgrader_process_complete', 'wp_update_themes' );
+ }
+
/**
* @testdox Should join the error message and its string data into one reason.
*/
diff --git a/plugins/woocommerce/tests/php/src/Admin/RemoteInboxNotifications/RemoteInboxNotificationsEngineTest.php b/plugins/woocommerce/tests/php/src/Admin/RemoteInboxNotifications/RemoteInboxNotificationsEngineTest.php
index 510baebeccb..a140aa0e01e 100644
--- a/plugins/woocommerce/tests/php/src/Admin/RemoteInboxNotifications/RemoteInboxNotificationsEngineTest.php
+++ b/plugins/woocommerce/tests/php/src/Admin/RemoteInboxNotifications/RemoteInboxNotificationsEngineTest.php
@@ -9,6 +9,7 @@ use Automattic\WooCommerce\Admin\Notes\Note;
use Automattic\WooCommerce\Admin\RemoteInboxNotifications\RemoteInboxNotificationsDataSourcePoller;
use Automattic\WooCommerce\Admin\RemoteInboxNotifications\RemoteInboxNotificationsEngine;
use Automattic\WooCommerce\Admin\RemoteSpecs\DataSourcePoller;
+use Automattic\WooCommerce\Internal\Admin\Onboarding\OnboardingProfile;
use WC_Action_Queue;
use WC_Queue;
use WC_Queue_Interface;
@@ -16,7 +17,7 @@ use WC_Unit_Test_Case;
use WP_Error;
/**
- * Tests for upgrade-triggered remote inbox scheduling and withdrawn alert reconciliation.
+ * Tests for remote inbox triggers and withdrawn alert reconciliation.
*
* @covers \Automattic\WooCommerce\Admin\RemoteInboxNotifications\RemoteInboxNotificationsEngine
*/
@@ -58,6 +59,23 @@ class RemoteInboxNotificationsEngineTest extends WC_Unit_Test_Case {
RemoteInboxNotificationsEngine::init();
}
+ /**
+ * @testdox Completing an existing onboarding profile runs the inbox engine.
+ */
+ public function test_completing_profile_runs_the_inbox_engine(): void {
+ update_option( OnboardingProfile::DATA_OPTION, array() );
+ $note = $this->create_note( 'profile-completion-alert', 'woocommerce.com', Note::E_WC_ADMIN_NOTE_UPDATE, Note::E_WC_ADMIN_NOTE_PENDING );
+ $spec = $this->create_spec( $note->get_name() );
+ $spec->rules = array( (object) array( 'type' => 'pass' ) );
+ $this->arrange_feed( array( $spec ), time() );
+
+ update_option( OnboardingProfile::DATA_OPTION, array( 'completed' => false ) );
+ $this->assertSame( Note::E_WC_ADMIN_NOTE_PENDING, $this->get_status( $note ), 'An incomplete profile must not run the inbox engine.' );
+
+ update_option( OnboardingProfile::DATA_OPTION, array( 'completed' => true ) );
+ $this->assertSame( Note::E_WC_ADMIN_NOTE_UNACTIONED, $this->get_status( $note ), 'Completing the profile must process the published inbox alert.' );
+ }
+
/**
* @testdox Repeated updates do not add pending copies while an upgrade action is running.
* @dataProvider running_action_provider
@@ -615,9 +633,9 @@ class RemoteInboxNotificationsEngineTest extends WC_Unit_Test_Case {
*
* @param string $slug Spec slug.
* @param string|null $source Spec source, or null to omit it.
- * @return object Remote spec.
+ * @return \stdClass Remote spec.
*/
- private function create_spec( string $slug, ?string $source = 'woocommerce.com' ): object {
+ private function create_spec( string $slug, ?string $source = 'woocommerce.com' ): \stdClass {
$spec = (object) array(
'slug' => $slug,
'status' => Note::E_WC_ADMIN_NOTE_UNACTIONED,
diff --git a/plugins/woocommerce/tests/php/src/Internal/Admin/ProductReviews/ReviewsAjaxTest.php b/plugins/woocommerce/tests/php/src/Internal/Admin/ProductReviews/ReviewsAjaxTest.php
index d739bf2008b..ee2bab8e089 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Admin/ProductReviews/ReviewsAjaxTest.php
+++ b/plugins/woocommerce/tests/php/src/Internal/Admin/ProductReviews/ReviewsAjaxTest.php
@@ -38,6 +38,10 @@ class ReviewsAjaxTest extends WP_Ajax_UnitTestCase {
public function set_up(): void {
parent::set_up();
+ remove_action( 'admin_init', '_maybe_update_core' );
+ remove_action( 'admin_init', '_maybe_update_plugins' );
+ remove_action( 'admin_init', '_maybe_update_themes' );
+
$this->reviews = wc_get_container()->get( Reviews::class );
add_action( 'wp_ajax_edit-comment', array( $this->reviews, 'handle_edit_review' ), -1 );
diff --git a/plugins/woocommerce/tests/php/src/Internal/Admin/Suggestions/PaymentsExtensionSuggestionsCountryPlacementTest.php b/plugins/woocommerce/tests/php/src/Internal/Admin/Suggestions/PaymentsExtensionSuggestionsCountryPlacementTest.php
index c85caa565e5..cc52c59b387 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Admin/Suggestions/PaymentsExtensionSuggestionsCountryPlacementTest.php
+++ b/plugins/woocommerce/tests/php/src/Internal/Admin/Suggestions/PaymentsExtensionSuggestionsCountryPlacementTest.php
@@ -104,6 +104,7 @@ class PaymentsExtensionSuggestionsCountryPlacementTest extends WC_Unit_Test_Case
*/
public function setUp(): void {
parent::setUp();
+ $this->http_responder = array( $this, 'mock_placement_http_responses' );
$this->store_admin_id = $this->factory->user->create( array( 'role' => 'administrator' ) );
wp_set_current_user( $this->store_admin_id );
@@ -739,4 +740,28 @@ class PaymentsExtensionSuggestionsCountryPlacementTest extends WC_Unit_Test_Case
return self::$fixture;
}
+
+ /**
+ * Keep placement fixtures in the no-eligible-incentive API scenario.
+ *
+ * @param array $request HTTP request arguments.
+ * @param string $url HTTP request URL.
+ * @return array|false Fixture response, or false for another request.
+ */
+ protected function mock_placement_http_responses( $request, $url ) {
+ if ( 'public-api.wordpress.com' !== wp_parse_url( $url, PHP_URL_HOST )
+ || '/wpcom/v2/wcpay/incentives' !== wp_parse_url( $url, PHP_URL_PATH )
+ || 'GET' !== ( $request['method'] ?? 'GET' ) ) {
+ return false;
+ }
+
+ return array(
+ 'headers' => array(
+ 'cache-for' => '86400',
+ 'content-type' => 'application/json; charset=UTF-8',
+ ),
+ 'body' => '',
+ 'response' => array( 'code' => 204 ),
+ );
+ }
}