Commit e7ad58a9b18 for woocommerce
commit e7ad58a9b182c21d57acc3a260fd3a86f3c3bb18
Author: Ján Mikláš <neosinner@gmail.com>
Date: Mon Aug 10 17:35:58 2026 +0200
Fix admin script 404s when the minified-js feature is enabled on core builds (#67515)
* Fix admin script 404s when minified-js feature is enabled on core builds
* Add changelog entry for minified-js asset fallback fix
diff --git a/plugins/woocommerce/changelog/66575-fix-minified-js-feature-404 b/plugins/woocommerce/changelog/66575-fix-minified-js-feature-404
new file mode 100644
index 00000000000..9f4552987cf
--- /dev/null
+++ b/plugins/woocommerce/changelog/66575-fix-minified-js-feature-404
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Serve minified admin scripts only when the minified file actually exists, preventing broken admin pages when the minified-js feature is force-enabled (e.g. via WooCommerce Beta Tester) on builds that do not ship minified JS files.
diff --git a/plugins/woocommerce/src/Internal/Admin/WCAdminAssets.php b/plugins/woocommerce/src/Internal/Admin/WCAdminAssets.php
index 3ce46b2a440..0ea36ed912a 100644
--- a/plugins/woocommerce/src/Internal/Admin/WCAdminAssets.php
+++ b/plugins/woocommerce/src/Internal/Admin/WCAdminAssets.php
@@ -89,10 +89,12 @@ class WCAdminAssets {
public static function get_url( $file, $ext ) {
$suffix = '';
- // Potentially enqueue minified JavaScript.
+ // Potentially enqueue minified JavaScript, but only if the minified file exists.
+ // Core builds do not ship minified JS files, so this also guards against the
+ // 'minified-js' feature being force-enabled (e.g. via WooCommerce Beta Tester).
if ( $ext === 'js' ) {
$script_debug = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG;
- $suffix = self::should_use_minified_js_file( $script_debug ) ? '.min' : '';
+ $suffix = self::should_use_minified_js_file( $script_debug ) && is_readable( WC_ADMIN_ABSPATH . self::get_path( $ext ) . $file . '.min.' . $ext ) ? '.min' : '';
}
return plugins_url( self::get_path( $ext ) . $file . $suffix . '.' . $ext, WC_ADMIN_PLUGIN_FILE );
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/wc-admin-assets.php b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/wc-admin-assets.php
index 1b1b28056fd..6a1ef2f4a4a 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/wc-admin-assets.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/wc-admin-assets.php
@@ -19,25 +19,25 @@ class WC_Admin_Tests_WCAdminAssets extends WP_UnitTestCase {
public function setUp(): void {
parent::setUp();
- add_filter( 'woocommerce_admin_features', array( $this, 'turn_on_unminified_js_feature' ), 20, 1 );
+ add_filter( 'woocommerce_admin_features', array( $this, 'turn_on_minified_js_feature' ), 20, 1 );
}
/**
* Tear Down
*/
public function tearDown(): void {
- remove_filter( 'woocommerce_admin_features', array( $this, 'turn_on_unminified_js_feature' ), 20 );
+ remove_filter( 'woocommerce_admin_features', array( $this, 'turn_on_minified_js_feature' ), 20 );
parent::tearDown();
}
/**
- * Filter to enable unminified-js feature.
+ * Filter to enable the minified-js feature.
*
* @param array $features Array of active features.
*/
- public static function turn_on_unminified_js_feature( $features ) {
- return array_merge( $features, array( 'unminified-js' ) );
+ public static function turn_on_minified_js_feature( $features ) {
+ return array_merge( $features, array( 'minified-js' ) );
}
/**
@@ -50,13 +50,11 @@ class WC_Admin_Tests_WCAdminAssets extends WP_UnitTestCase {
$parts = explode( '/', $result );
$final_file_name = array_pop( $parts );
- // Since this can vary depending on the env the tests are running in, we will make this assertion based upon the SCRIPT_DEBUG value.
- $expected_value = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? 'flavortown.js' : 'flavortown.min.js';
-
+ // No minified build of this file exists, so the unminified file name should be served regardless of SCRIPT_DEBUG.
$this->assertEquals(
- $expected_value,
+ 'flavortown.js',
$final_file_name,
- 'the anticipated js file name should use .min when SCRIPT_DEBUG is off, and have no .min when SCRIPT_DEBUG is on.'
+ 'the anticipated js file name should not use .min when no minified file exists.'
);
}
diff --git a/plugins/woocommerce/tests/php/src/Internal/Admin/WCAdminAssetsTest.php b/plugins/woocommerce/tests/php/src/Internal/Admin/WCAdminAssetsTest.php
new file mode 100644
index 00000000000..7dc9ccbf7e1
--- /dev/null
+++ b/plugins/woocommerce/tests/php/src/Internal/Admin/WCAdminAssetsTest.php
@@ -0,0 +1,100 @@
+<?php
+declare( strict_types = 1 );
+
+namespace Automattic\WooCommerce\Tests\Internal\Admin;
+
+use Automattic\WooCommerce\Internal\Admin\WCAdminAssets;
+use WC_Unit_Test_Case;
+
+/**
+ * Tests for the WCAdminAssets class.
+ */
+class WCAdminAssetsTest extends WC_Unit_Test_Case {
+
+ /**
+ * Path of the temporary minified JS file created by a test, if any.
+ *
+ * @var string|null
+ */
+ private $temp_min_file = null;
+
+ /**
+ * Set up test fixtures.
+ */
+ public function setUp(): void {
+ parent::setUp();
+
+ add_filter( 'woocommerce_admin_features', array( $this, 'enable_minified_js_feature' ), 20 );
+ }
+
+ /**
+ * Tear down test fixtures.
+ */
+ public function tearDown(): void {
+ remove_filter( 'woocommerce_admin_features', array( $this, 'enable_minified_js_feature' ), 20 );
+
+ if ( $this->temp_min_file && file_exists( $this->temp_min_file ) ) {
+ wp_delete_file( $this->temp_min_file );
+ $this->temp_min_file = null;
+ }
+
+ parent::tearDown();
+ }
+
+ /**
+ * Filter callback to enable the minified-js feature.
+ *
+ * @param array $features Array of active features.
+ * @return array
+ */
+ public function enable_minified_js_feature( $features ) {
+ return array_merge( $features, array( 'minified-js' ) );
+ }
+
+ /**
+ * Skips the test when SCRIPT_DEBUG is on, as the minified file is never served then and the test would pass vacuously.
+ */
+ private function skip_if_script_debug(): void {
+ if ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) {
+ $this->markTestSkipped( 'Minified files are never served when SCRIPT_DEBUG is on.' );
+ }
+ }
+
+ /**
+ * @testdox get_url should not use the .min suffix when the minified file does not exist, even with the minified-js feature enabled.
+ */
+ public function test_get_url_falls_back_to_unminified_file_when_minified_file_is_missing(): void {
+ $this->skip_if_script_debug();
+
+ $url = WCAdminAssets::get_url( 'nonexistent-test-script/index', 'js' );
+
+ $this->assertStringEndsWith(
+ 'nonexistent-test-script/index.js',
+ $url,
+ 'The unminified file name should be served when no minified file exists.'
+ );
+ }
+
+ /**
+ * @testdox get_url should use the .min suffix when the minified file exists, the minified-js feature is enabled and SCRIPT_DEBUG is off.
+ */
+ public function test_get_url_uses_minified_file_when_it_exists(): void {
+ $this->skip_if_script_debug();
+
+ $dist_js_path = WC_ADMIN_ABSPATH . WC_ADMIN_DIST_JS_FOLDER;
+ if ( ! wp_is_writable( $dist_js_path ) ) {
+ $this->markTestSkipped( 'The admin dist JS folder is not writable.' );
+ }
+
+ $this->temp_min_file = $dist_js_path . 'wc-admin-assets-test.min.js';
+ file_put_contents( $this->temp_min_file, '/* test */' ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_file_put_contents
+
+ $url = WCAdminAssets::get_url( 'wc-admin-assets-test', 'js' );
+
+ $this->assertStringEndsWith(
+ 'wc-admin-assets-test.min.js',
+ $url,
+ 'The minified file name should be served when the minified file exists and SCRIPT_DEBUG is off.'
+ );
+ }
+}