From 00d36dc97d0cd2be67c273bd43f22e671cf05dad Mon Sep 17 00:00:00 2001 From: Adrian Moldovan <3854374+adimoldovan@users.noreply.github.com> Date: Fri, 4 Sep 2026 17:17:04 +0300 Subject: [PATCH] Build/Test Tools: Fail tests that make external HTTP requests outside the `external-http` group. Add a `pre_http_request` filter in `WP_UnitTestCase_Base` that blocks an external HTTP request from a test outside the `external-http` group, then fails that test. The filter runs at `PHP_INT_MAX`, so a mock added by the test answers first. The check runs only when `WP_RUN_CORE_TESTS` is set. Add `@group external-http` to `Tests_oEmbed_WpEmbed::test_run_shortcode_url_only`, the only test in trunk that the check catches. --- tests/phpunit/includes/abstract-testcase.php | 49 ++++++++++++++++++++ tests/phpunit/tests/oembed/WpEmbed.php | 2 + 2 files changed, 51 insertions(+) diff --git a/tests/phpunit/includes/abstract-testcase.php b/tests/phpunit/includes/abstract-testcase.php index c87e5e7fd077c..59aa3c84df7e1 100644 --- a/tests/phpunit/includes/abstract-testcase.php +++ b/tests/phpunit/includes/abstract-testcase.php @@ -22,6 +22,13 @@ abstract class WP_UnitTestCase_Base extends PHPUnit_Adapter_TestCase { /** @var non-empty-string[] */ protected $caught_doing_it_wrong = array(); + /** + * URLs of blocked external HTTP requests made during the current test. + * + * @var string[] + */ + protected $blocked_http_requests = array(); + protected static $hooks_saved = array(); protected static $ignore_files; @@ -143,6 +150,12 @@ public function set_up() { $this->expectDeprecated(); add_filter( 'wp_die_handler', array( $this, 'get_wp_die_handler' ) ); add_filter( 'wp_hash_password_options', array( $this, 'wp_hash_password_options' ), 1, 2 ); + + if ( defined( 'WP_RUN_CORE_TESTS' ) && WP_RUN_CORE_TESTS + && ! in_array( 'external-http', $this->getGroups(), true ) + ) { + add_filter( 'pre_http_request', array( $this, 'block_external_http_request' ), PHP_INT_MAX, 3 ); + } } /** @@ -685,6 +698,34 @@ public function expectedDeprecated() { } } + /** + * Blocks an external HTTP request that no other filter has answered. + * + * Added by set_up() for tests that are not in the `external-http` group, and + * runs last on the filter so any mock set up by the test itself gets the + * first say. Requests reaching this point are recorded and fail the test in + * assert_post_conditions(). + * + * @since 7.2.0 + * + * @param false|array|WP_Error $response A preemptive response, or false when none was given. + * @param array $args Request arguments. + * @param string $url The request URL. + * @return array|WP_Error The preemptive response, or an error for a blocked request. + */ + public function block_external_http_request( $response, $args, $url ) { + if ( false !== $response ) { + return $response; + } + + $this->blocked_http_requests[] = $url; + + return new WP_Error( + 'test_external_http_blocked', + 'External HTTP requests are blocked in tests that are not in the `external-http` group.' + ); + } + /** * Detects post-test failure conditions. * @@ -694,6 +735,14 @@ public function expectedDeprecated() { */ protected function assert_post_conditions() { $this->expectedDeprecated(); + + if ( $this->blocked_http_requests ) { + $this->fail( + "This test made an external HTTP request but is not in the `external-http` group.\n" + . "Add `@group external-http` to it, or mock the request with the `pre_http_request` filter.\n" + . '- ' . implode( "\n- ", array_unique( $this->blocked_http_requests ) ) + ); + } } /** diff --git a/tests/phpunit/tests/oembed/WpEmbed.php b/tests/phpunit/tests/oembed/WpEmbed.php index 42d9c9e0f4ed9..f95fbde7b92dd 100644 --- a/tests/phpunit/tests/oembed/WpEmbed.php +++ b/tests/phpunit/tests/oembed/WpEmbed.php @@ -405,6 +405,8 @@ public function test_shortcode_should_make_link_for_unknown_url() { } /** + * @group external-http + * * @covers ::run_shortcode */ public function test_run_shortcode_url_only() {