diff --git a/includes/assets.php b/includes/assets.php index d9d4b836..b47c215a 100644 --- a/includes/assets.php +++ b/includes/assets.php @@ -144,6 +144,27 @@ private function register_react_jsx_runtime_polyfill( $version ) { ); } + /** + * Registers a fallback for the wp-polyfill script handle. + * + * Generated asset files list this handle as a dependency of every SCF + * script. Systems that never register it, such as ClassicPress, silently + * drop each dependent script, which leaves the inline footer code + * running against a missing acf global. + * + * @since SCF 6.9.6 + * + * @param string $version The script version. + * @return void + */ + private function register_wp_polyfill_fallback( $version ) { + if ( wp_script_is( 'wp-polyfill', 'registered' ) ) { + return; + } + + wp_register_script( 'wp-polyfill', false, array(), $version, true ); + } + /** * Returns whether the legacy SCF block bindings editor script can run. * @@ -174,6 +195,7 @@ public function register_scripts() { $version = acf_get_setting( 'version' ); $this->register_react_jsx_runtime_polyfill( $version ); + $this->register_wp_polyfill_fallback( $version ); // Define path patterns. $js_path_patterns = array( diff --git a/tests/e2e/fixtures.js b/tests/e2e/fixtures.js index 59d8b016..c8fee97e 100644 --- a/tests/e2e/fixtures.js +++ b/tests/e2e/fixtures.js @@ -144,22 +144,25 @@ const test = wpTest.extend( { 'role=button[name="View"i]' ); - if ( + const hasViewButton = ( await viewButton.count() ) > 0 && - ( await viewButton.first().isVisible() ) - ) { - return editor.openPreviewPage(); - } + ( await viewButton.first().isVisible() ); - await editorTopBar - .locator( 'role=button[name="Preview"i]' ) - .click(); + await ( hasViewButton + ? viewButton.first() + : editorTopBar.locator( 'role=button[name="Preview"i]' ) + ).click(); + // WordPress trunk renamed the menu item to + // "Preview (opens in a new tab)", so match on the shared + // "Preview ... new tab" text instead of the exact label. const [ previewPage ] = await Promise.all( [ context.waitForEvent( 'page' ), - page.click( - 'role=menuitem[name=/Preview in new tab/i]' - ), + page + .getByRole( 'menuitem', { + name: /Preview.*new tab/i, + } ) + .click(), ] ); return previewPage; diff --git a/tests/php/includes/test-assets.php b/tests/php/includes/test-assets.php index 67545793..b141999c 100644 --- a/tests/php/includes/test-assets.php +++ b/tests/php/includes/test-assets.php @@ -52,6 +52,7 @@ public function set_up() { wp_dequeue_script( 'acf-pro-ui-options-page' ); wp_dequeue_script( 'scf-bindings' ); wp_deregister_script( 'react-jsx-runtime' ); + wp_deregister_script( 'wp-polyfill' ); wp_deregister_script( 'scf-commands-admin' ); wp_deregister_script( 'scf-bindings' ); } @@ -67,6 +68,7 @@ public function tear_down() { wp_dequeue_script( 'acf-pro-ui-options-page' ); wp_dequeue_script( 'scf-bindings' ); wp_deregister_script( 'react-jsx-runtime' ); + wp_deregister_script( 'wp-polyfill' ); wp_deregister_script( 'scf-commands-admin' ); wp_deregister_script( 'scf-bindings' ); @@ -107,6 +109,29 @@ public function test_register_scripts_adds_react_jsx_runtime_polyfill_when_missi ); } + /** + * Test installs without wp-polyfill get a fallback registration. + */ + public function test_register_scripts_adds_wp_polyfill_fallback_when_missing() { + acf_get_instance( 'ACF_Assets' )->register_scripts(); + + $this->assertTrue( wp_script_is( 'wp-polyfill', 'registered' ) ); + } + + /** + * Test an existing wp-polyfill registration is left untouched. + */ + public function test_register_scripts_keeps_existing_wp_polyfill_registration() { + wp_register_script( 'wp-polyfill', 'https://example.org/polyfill.js', array(), 'test-version', true ); + + acf_get_instance( 'ACF_Assets' )->register_scripts(); + + $wp_scripts = wp_scripts(); + + $this->assertSame( 'https://example.org/polyfill.js', $wp_scripts->registered['wp-polyfill']->src ); + $this->assertSame( 'test-version', $wp_scripts->registered['wp-polyfill']->ver ); + } + /** * Test command scripts include generated asset dependencies. */