Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 105 additions & 0 deletions tests/unit/Helpers/ScriptHelperTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
<?php

namespace SkyVerge\WooCommerce\PluginFramework\v6_2_4\Tests\Unit\Helpers;

use SkyVerge\WooCommerce\PluginFramework\v6_2_4\Helpers\ScriptHelper;
use SkyVerge\WooCommerce\PluginFramework\v6_2_4\Tests\TestCase;
use WP_Mock;

/**
* @coversDefaultClass \SkyVerge\WooCommerce\PluginFramework\v6_2_4\Helpers\ScriptHelper
*/
final class ScriptHelperTest extends TestCase
{
/**
* Mocks the WP functions called by addInlineScript after the guard (script already
* registered and enqueued, so register/enqueue branches are skipped).
*/
private function mockScriptFunctions() : void
{
WP_Mock::userFunction('wp_script_is', ['return' => true]);
WP_Mock::userFunction('wp_add_inline_script', ['return' => true]);
}

/**
* @covers ::addInlineScript
*/
public function testNoWarningOnFrontendBeforeFooterScriptsFire() : void
{
WP_Mock::userFunction('is_admin', ['return' => false]);
WP_Mock::userFunction('did_action', [
'return' => static function (string $hook) : int {
return 0; // neither hook has fired
},
]);
$this->mockScriptFunctions();

ScriptHelper::addInlineScript('test-handle', 'console.log(1);');
$this->addToAssertionCount(1);
}

/**
* @covers ::addInlineScript
*/
public function testWarningOnFrontendAfterFooterScriptsFire() : void
{
WP_Mock::userFunction('is_admin', ['return' => false]);
WP_Mock::userFunction('did_action', [
'return' => static function (string $hook) : int {
return $hook === 'wp_print_footer_scripts' ? 1 : 0;
},
]);
WP_Mock::userFunction('_doing_it_wrong', ['times' => 1]);
$this->mockScriptFunctions();

ScriptHelper::addInlineScript('test-handle', 'console.log(1);');
$this->addToAssertionCount(1);
}

/**
* In admin, WP 6.9+'s _wp_get_iframed_editor_assets() calls wp_print_footer_scripts()
* on throwaway WP_Scripts instances, bumping its counter before admin_footer fires.
* addInlineScript must not warn when wp_print_footer_scripts has fired but
* admin_print_footer_scripts has not — this is the key regression the fix addresses.
*
* @covers ::addInlineScript
*/
public function testNoWarningInAdminWhenOnlyWpPrintFooterScriptsFired() : void
{
WP_Mock::userFunction('is_admin', ['return' => true]);
WP_Mock::userFunction('did_action', [
'return' => static function (string $hook) : int {
// Simulates the WP 6.9+ iframed-assets scenario: wp_print_footer_scripts
// counter is elevated but admin_print_footer_scripts has not fired yet.
return $hook === 'wp_print_footer_scripts' ? 1 : 0;
},
]);
$this->mockScriptFunctions();

// _doing_it_wrong is intentionally not mocked; any call would fail the test.
ScriptHelper::addInlineScript('test-handle', 'console.log(1);');
$this->addToAssertionCount(1);
}

/**
* In admin, the warning fires only after admin_print_footer_scripts has run,
* not merely because wp_print_footer_scripts fired (which the iframed-assets
* collector triggers early).
*
* @covers ::addInlineScript
*/
public function testWarningInAdminAfterAdminFooterScriptsFire() : void
{
WP_Mock::userFunction('is_admin', ['return' => true]);
WP_Mock::userFunction('did_action', [
'return' => static function (string $hook) : int {
return $hook === 'admin_print_footer_scripts' ? 1 : 0;
},
]);
WP_Mock::userFunction('_doing_it_wrong', ['times' => 1]);
$this->mockScriptFunctions();

ScriptHelper::addInlineScript('test-handle', 'console.log(1);');
$this->addToAssertionCount(1);
}
}
10 changes: 9 additions & 1 deletion woocommerce/Helpers/ScriptHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,15 @@ class ScriptHelper
*/
public static function addInlineScript(string $handle, string $javaScriptString) : bool
{
if (did_action('wp_print_footer_scripts')) {
// In admin, wp_print_footer_scripts() is called early by _wp_get_iframed_editor_assets()
// (WP 6.9+) on throwaway WP_Scripts instances before admin_footer fires, so its counter
// is unreliable there. admin_print_footer_scripts only fires in admin-footer.php, after
// admin_footer (where notice JS is queued at priority 20), so it is the correct sentinel.
$tooLate = is_admin()
? did_action('admin_print_footer_scripts')
: did_action('wp_print_footer_scripts');

if ($tooLate) {
_doing_it_wrong(__METHOD__, 'Inline scripts should be added before the wp_print_footer_scripts action.', '6.0.1');
}

Expand Down