Make WordPress Core


Ignore:
Timestamp:
09/25/2023 09:03:19 PM (20 months ago)
Author:
westonruter
Message:

Script Loader: Use wp_get_script_tag() and wp_get_inline_script_tag()/wp_print_inline_script_tag() helper functions to output scripts on the frontend and login screen.

Using script tag helper functions allows plugins to employ the wp_script_attributes and wp_inline_script_attributes filters to inject the nonce attribute to apply Content Security Policy (e.g. Strict CSP). Use of helper functions also simplifies logic in WP_Scripts.

  • Update wp_get_inline_script_tag() to wrap inline script in CDATA blocks for XHTML-compatibility when not using HTML5.
  • Ensure the type attribute is printed first in wp_get_inline_script_tag() for back-compat.
  • Wrap existing <script> tags in output buffering to retain IDE supports.
  • In wp_get_inline_script_tag(), append the newline to $javascript before it is passed into the wp_inline_script_attributes filter so that the CSP hash can be computed properly.
  • In the_block_template_skip_link(), opt to enqueue the inline script rather than print it.
  • Add ext-php to composer.json under suggest as previously it was an undeclared dependency for running PHPUnit tests.
  • Update tests to rely on DOMDocument to compare script markup, normalizing unsemantic differences.

Props westonruter, spacedmonkey, flixos90, 10upsimon, dmsnell, mukesh27, joemcgill, swissspidy, azaozz.
Fixes #58664.
See #39941.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/tests/phpunit/tests/dependencies/scripts.php

    r56559 r56687  
    4343        $this->wp_scripts_print_translations_output  = <<<JS
    4444<script type='text/javascript' id='__HANDLE__-js-translations'>
     45/* <![CDATA[ */
    4546( function( domain, translations ) {
    4647    var localeData = translations.locale_data[ domain ] || translations.locale_data.messages;
     
    4849    wp.i18n.setLocaleData( localeData, domain );
    4950} )( "__DOMAIN__", __JSON_TRANSLATIONS__ );
     51/* ]]> */
    5052</script>
    5153JS;
     
    7880        $expected .= "<script type='text/javascript' src='http://example.com' id='empty-deps-null-version-js'></script>\n";
    7981
    80         $this->assertSame( $expected, get_echo( 'wp_print_scripts' ) );
     82        $this->assertEqualMarkup( $expected, get_echo( 'wp_print_scripts' ) );
    8183
    8284        // No scripts left to print.
     
    119121        $expected  = "<script type='text/javascript' src='http://example.org/ms-isa-1.js' id='ms-isa-1-js' data-wp-strategy='{$strategy}'></script>\n";
    120122        $expected .= wp_get_inline_script_tag(
    121             "console.log(\"after one\");\n",
     123            'console.log("after one");',
    122124            array(
    123125                'id' => 'ms-isa-1-js-after',
    124126            )
    125127        );
    126         $this->assertSame( $expected, $output, 'Inline scripts in the "after" position, that are attached to a deferred main script, are failing to print/execute.' );
     128        $this->assertEqualMarkup( $expected, $output, 'Inline scripts in the "after" position, that are attached to a deferred main script, are failing to print/execute.' );
    127129    }
    128130
     
    147149        $expected  = "<script type='text/javascript' src='http://example.org/ms-insa-3.js' id='ms-insa-3-js'></script>\n";
    148150        $expected .= wp_get_inline_script_tag(
    149             "console.log(\"after one\");\n",
     151            'console.log("after one");',
    150152            array(
    151153                'id' => 'ms-insa-3-js-after',
     
    153155        );
    154156
    155         $this->assertSame( $expected, $output, 'Inline scripts in the "after" position, that are attached to a blocking main script, are failing to print/execute.' );
     157        $this->assertEqualMarkup( $expected, $output, 'Inline scripts in the "after" position, that are attached to a blocking main script, are failing to print/execute.' );
    156158    }
    157159
     
    181183
    182184        $expected  = wp_get_inline_script_tag(
    183             "console.log(\"before first\");\n",
     185            'console.log("before first");',
    184186            array(
    185187                'id' => 'ds-i1-1-js-before',
     
    190192        $expected .= "<script type='text/javascript' src='http://example.org/ds-i1-3.js' id='ds-i1-3-js' $strategy data-wp-strategy='{$strategy}'></script>\n";
    191193        $expected .= wp_get_inline_script_tag(
    192             "console.log(\"before last\");\n",
     194            'console.log("before last");',
    193195            array(
    194196                'id'   => 'ms-i1-1-js-before',
     
    198200        $expected .= "<script type='text/javascript' src='http://example.org/ms-i1-1.js' id='ms-i1-1-js' {$strategy} data-wp-strategy='{$strategy}'></script>\n";
    199201
    200         $this->assertSame( $expected, $output, 'Inline scripts in the "before" position, that are attached to a deferred main script, are failing to print/execute.' );
     202        $this->assertEqualMarkup( $expected, $output, 'Inline scripts in the "before" position, that are attached to a deferred main script, are failing to print/execute.' );
    201203    }
    202204
     
    216218        $output   = get_echo( 'wp_print_scripts' );
    217219        $expected = "<script type='text/javascript' src='/main-script-a1.js' id='main-script-a1-js' async data-wp-strategy='async'></script>\n";
    218         $this->assertSame( $expected, $output, 'Scripts enqueued with an async loading strategy are failing to have the async attribute applied to the script handle when being printed.' );
     220        $this->assertEqualMarkup( $expected, $output, 'Scripts enqueued with an async loading strategy are failing to have the async attribute applied to the script handle when being printed.' );
    219221    }
    220222
     
    236238        wp_enqueue_script( 'dependency-script-a2', '/dependency-script-a2.js', array(), null );
    237239        wp_enqueue_script( 'main-script-a2', '/main-script-a2.js', array( 'dependency-script-a2' ), null, compact( 'strategy' ) );
    238         $output   = get_echo( 'wp_print_scripts' );
    239         $expected = "<script type='text/javascript' src='/main-script-a2.js' id='main-script-a2-js' {$strategy} data-wp-strategy='{$strategy}'></script>";
    240         $this->assertStringContainsString( $expected, $output, 'Dependents of a blocking dependency are free to have any strategy.' );
     240        $output    = get_echo( 'wp_print_scripts' );
     241        $expected  = "<script id='dependency-script-a2-js' src='/dependency-script-a2.js'></script>\n";
     242        $expected .= "<script type='text/javascript' src='/main-script-a2.js' id='main-script-a2-js' {$strategy} data-wp-strategy='{$strategy}'></script>";
     243        $this->assertEqualMarkup( $expected, $output, 'Dependents of a blocking dependency are free to have any strategy.' );
    241244    }
    242245
     
    258261        wp_enqueue_script( 'dependent-script-a3', '/dependent-script-a3.js', array( 'main-script-a3' ), null );
    259262        $output   = get_echo( 'wp_print_scripts' );
    260         $expected = "<script type='text/javascript' src='/main-script-a3.js' id='main-script-a3-js' data-wp-strategy='{$strategy}'></script>";
     263        $expected = str_replace( "'", '"', "<script type='text/javascript' src='/main-script-a3.js' id='main-script-a3-js' data-wp-strategy='{$strategy}'></script>" );
    261264        $this->assertStringContainsString( $expected, $output, 'Blocking dependents must force delayed dependencies to become blocking.' );
    262265    }
     
    276279     */
    277280    public function test_delayed_dependent_with_blocking_dependency_not_enqueued( $strategy ) {
     281        $this->add_html5_script_theme_support();
    278282        wp_enqueue_script( 'main-script-a4', '/main-script-a4.js', array(), null, compact( 'strategy' ) );
    279283        // This dependent is registered but not enqueued, so it should not factor into the eligible loading strategy.
    280284        wp_register_script( 'dependent-script-a4', '/dependent-script-a4.js', array( 'main-script-a4' ), null );
    281285        $output   = get_echo( 'wp_print_scripts' );
    282         $expected = "<script type='text/javascript' src='/main-script-a4.js' id='main-script-a4-js' {$strategy} data-wp-strategy='{$strategy}'></script>";
     286        $expected = str_replace( "'", '"', "<script src='/main-script-a4.js' id='main-script-a4-js' {$strategy} data-wp-strategy='{$strategy}'></script>" );
    283287        $this->assertStringContainsString( $expected, $output, 'Only enqueued dependents should affect the eligible strategy.' );
    284288    }
     
    965969     */
    966970    public function test_loading_strategy_with_defer_having_no_dependents_nor_dependencies() {
     971        $this->add_html5_script_theme_support();
    967972        wp_enqueue_script( 'main-script-d1', 'http://example.com/main-script-d1.js', array(), null, array( 'strategy' => 'defer' ) );
    968973        $output   = get_echo( 'wp_print_scripts' );
    969         $expected = "<script type='text/javascript' src='http://example.com/main-script-d1.js' id='main-script-d1-js' defer data-wp-strategy='defer'></script>\n";
     974        $expected = str_replace( "'", '"', "<script src='http://example.com/main-script-d1.js' id='main-script-d1-js' defer data-wp-strategy='defer'></script>\n" );
    970975        $this->assertStringContainsString( $expected, $output, 'Expected defer, as there is no dependent or dependency' );
    971976    }
     
    981986     */
    982987    public function test_loading_strategy_with_defer_dependent_and_varied_dependencies() {
     988        $this->add_html5_script_theme_support();
    983989        wp_enqueue_script( 'dependency-script-d2-1', 'http://example.com/dependency-script-d2-1.js', array(), null, array( 'strategy' => 'defer' ) );
    984990        wp_enqueue_script( 'dependency-script-d2-2', 'http://example.com/dependency-script-d2-2.js', array(), null );
     
    986992        wp_enqueue_script( 'main-script-d2', 'http://example.com/main-script-d2.js', array( 'dependency-script-d2-1', 'dependency-script-d2-3' ), null, array( 'strategy' => 'defer' ) );
    987993        $output   = get_echo( 'wp_print_scripts' );
    988         $expected = "<script type='text/javascript' src='http://example.com/main-script-d2.js' id='main-script-d2-js' defer data-wp-strategy='defer'></script>\n";
     994        $expected = '<script src="http://example.com/main-script-d2.js" id="main-script-d2-js" defer data-wp-strategy="defer"></script>';
    989995        $this->assertStringContainsString( $expected, $output, 'Expected defer, as all dependencies are either deferred or blocking' );
    990996    }
     
    10001006     */
    10011007    public function test_loading_strategy_with_all_defer_dependencies() {
     1008        $this->add_html5_script_theme_support();
    10021009        wp_enqueue_script( 'main-script-d3', 'http://example.com/main-script-d3.js', array(), null, array( 'strategy' => 'defer' ) );
    10031010        wp_enqueue_script( 'dependent-script-d3-1', 'http://example.com/dependent-script-d3-1.js', array( 'main-script-d3' ), null, array( 'strategy' => 'defer' ) );
     
    10051012        wp_enqueue_script( 'dependent-script-d3-3', 'http://example.com/dependent-script-d3-3.js', array( 'dependent-script-d3-2' ), null, array( 'strategy' => 'defer' ) );
    10061013        $output   = get_echo( 'wp_print_scripts' );
    1007         $expected = "<script type='text/javascript' src='http://example.com/main-script-d3.js' id='main-script-d3-js' defer data-wp-strategy='defer'></script>\n";
     1014        $expected = '<script src="http://example.com/main-script-d3.js" id="main-script-d3-js" defer data-wp-strategy="defer"></script>';
    10081015        $this->assertStringContainsString( $expected, $output, 'Expected defer, as all dependents have defer loading strategy' );
    10091016    }
     
    10301037        $expected .= "<script type='text/javascript' src='/dependent-script-d4-3.js' id='dependent-script-d4-3-js' defer data-wp-strategy='defer'></script>\n";
    10311038
    1032         $this->assertSame( $expected, $output, 'Scripts registered as defer but that have dependents that are async are expected to have said dependents deferred.' );
     1039        $this->assertEqualMarkup( $expected, $output, 'Scripts registered as defer but that have dependents that are async are expected to have said dependents deferred.' );
    10331040    }
    10341041
     
    10501057        wp_enqueue_script( 'dependent-script-d4-3', '/dependent-script-d4-3.js', array( 'dependent-script-d4-2' ), null, array( 'strategy' => 'defer' ) );
    10511058        $output   = get_echo( 'wp_print_scripts' );
    1052         $expected = "<script type='text/javascript' src='/main-script-d4.js' id='main-script-d4-js' data-wp-strategy='defer'></script>\n";
     1059        $expected = str_replace( "'", '"', "<script type='text/javascript' src='/main-script-d4.js' id='main-script-d4-js' data-wp-strategy='defer'></script>\n" );
    10531060        $this->assertStringContainsString( $expected, $output, 'Scripts registered as defer but that have all dependents with no strategy, should become blocking (no strategy).' );
    10541061    }
     
    10681075        $output   = get_echo( 'wp_print_scripts' );
    10691076        $expected = "<script type='text/javascript' src='/main-script-b1.js' id='main-script-b1-js'></script>\n";
     1077        $expected = str_replace( "'", '"', $expected );
    10701078        $this->assertSame( $expected, $output, 'Scripts registered with a "blocking" strategy, and who have no dependencies, should have no loading strategy attributes printed.' );
    10711079
     
    10741082        $output   = get_echo( 'wp_print_scripts' );
    10751083        $expected = "<script type='text/javascript' src='/main-script-b2.js' id='main-script-b2-js'></script>\n";
     1084        $expected = str_replace( "'", '"', $expected );
    10761085        $this->assertSame( $expected, $output, 'Scripts registered with no strategy assigned, and who have no dependencies, should have no loading strategy attributes printed.' );
    10771086    }
     
    11001109        $expected_header .= "<script type='text/javascript' src='/enqueue-header-new.js' id='enqueue-header-new-js'></script>\n";
    11011110
    1102         $this->assertSame( $expected_header, $actual_header, 'Scripts registered/enqueued using the older $in_footer parameter or the newer $args parameter should have the same outcome.' );
     1111        $this->assertEqualMarkup( $expected_header, $actual_header, 'Scripts registered/enqueued using the older $in_footer parameter or the newer $args parameter should have the same outcome.' );
    11031112        $this->assertEmpty( $actual_footer, 'Expected footer to be empty since all scripts were for head.' );
    11041113    }
     
    11281137
    11291138        $this->assertEmpty( $actual_header, 'Expected header to be empty since all scripts targeted footer.' );
    1130         $this->assertSame( $expected_footer, $actual_footer, 'Scripts registered/enqueued using the older $in_footer parameter or the newer $args parameter should have the same outcome.' );
     1139        $this->assertEqualMarkup( $expected_footer, $actual_footer, 'Scripts registered/enqueued using the older $in_footer parameter or the newer $args parameter should have the same outcome.' );
    11311140    }
    11321141
     
    12471256        wp_enqueue_script( 'invalid-strategy' );
    12481257
    1249         $this->assertSame(
     1258        $this->assertEqualMarkup(
    12501259            "<script type='text/javascript' src='/defaults.js' id='invalid-strategy-js'></script>\n",
    12511260            get_echo( 'wp_print_scripts' )
     
    12721281        wp_enqueue_script( 'invalid-strategy' );
    12731282
    1274         $this->assertSame(
     1283        $this->assertEqualMarkup(
    12751284            "<script type='text/javascript' src='/defaults.js' id='invalid-strategy-js'></script>\n",
    12761285            get_echo( 'wp_print_scripts' )
     
    12931302        wp_enqueue_script( 'invalid-strategy', '/defaults.js', array(), null, array( 'strategy' => 'random-strategy' ) );
    12941303
    1295         $this->assertSame(
     1304        $this->assertEqualMarkup(
    12961305            "<script type='text/javascript' src='/defaults.js' id='invalid-strategy-js'></script>\n",
    12971306            get_echo( 'wp_print_scripts' )
     
    13311340        $expected .= "<script type='text/javascript' src='/main-script.js' id='main-defer-script-js' defer data-wp-strategy='defer'></script>\n";
    13321341
    1333         $this->assertSame( $expected, $print_scripts, 'Scripts are being incorrectly concatenated when a main script is registered with a "defer" loading strategy. Deferred scripts should not be part of the script concat loading query.' );
     1342        $this->assertEqualMarkup( $expected, $print_scripts, 'Scripts are being incorrectly concatenated when a main script is registered with a "defer" loading strategy. Deferred scripts should not be part of the script concat loading query.' );
    13341343    }
    13351344
     
    13661375        $expected .= "<script type='text/javascript' src='/main-script.js' id='main-async-script-1-js' async data-wp-strategy='async'></script>\n";
    13671376
    1368         $this->assertSame( $expected, $print_scripts, 'Scripts are being incorrectly concatenated when a main script is registered with an "async" loading strategy. Async scripts should not be part of the script concat loading query.' );
     1377        $this->assertEqualMarkup( $expected, $print_scripts, 'Scripts are being incorrectly concatenated when a main script is registered with an "async" loading strategy. Async scripts should not be part of the script concat loading query.' );
    13691378    }
    13701379
     
    14051414        $expected .= "<script type='text/javascript' src='/main-script.js' id='deferred-script-2-js' defer data-wp-strategy='defer'></script>\n";
    14061415
    1407         $this->assertSame( $expected, $print_scripts, 'Scripts are being incorrectly concatenated when a main script is registered as deferred after other blocking scripts are registered. Deferred scripts should not be part of the script concat loader query string. ' );
     1416        $this->assertEqualMarkup( $expected, $print_scripts, 'Scripts are being incorrectly concatenated when a main script is registered as deferred after other blocking scripts are registered. Deferred scripts should not be part of the script concat loader query string. ' );
    14081417    }
    14091418
     
    14131422    public function test_wp_enqueue_script_with_html5_support_does_not_contain_type_attribute() {
    14141423        global $wp_version;
    1415         add_theme_support( 'html5', array( 'script' ) );
    14161424
    14171425        $GLOBALS['wp_scripts']                  = new WP_Scripts();
     
    14221430        $expected = "<script src='http://example.com?ver={$wp_version}' id='empty-deps-no-version-js'></script>\n";
    14231431
    1424         $this->assertSame( $expected, get_echo( 'wp_print_scripts' ) );
     1432        $this->assertEqualMarkup( $expected, get_echo( 'wp_print_scripts' ) );
    14251433    }
    14261434
     
    14611469
    14621470        // Go!
    1463         $this->assertSame( $expected, get_echo( 'wp_print_scripts' ) );
     1471        $this->assertEqualMarkup( $expected, get_echo( 'wp_print_scripts' ) );
    14641472
    14651473        // No scripts left to print.
     
    15041512
    15051513        // Go!
    1506         $this->assertSame( $expected, get_echo( 'wp_print_scripts' ) );
     1514        $this->assertEqualMarkup( $expected, get_echo( 'wp_print_scripts' ) );
    15071515
    15081516        // No scripts left to print.
     
    15221530
    15231531        // Go!
    1524         $this->assertSame( $expected, get_echo( 'wp_print_scripts' ) );
     1532        $this->assertEqualMarkup( $expected, get_echo( 'wp_print_scripts' ) );
    15251533
    15261534        // No scripts left to print.
     
    15401548        $expected  = "<!--[if lt IE 9]>\n<script type='text/javascript' id='test-conditional-with-data-js-extra'>\n/* <![CDATA[ */\ntesting\n/* ]]> */\n</script>\n<![endif]-->\n";
    15411549        $expected .= "<!--[if lt IE 9]>\n<script type='text/javascript' src='http://example.com' id='test-conditional-with-data-js'></script>\n<![endif]-->\n";
     1550        $expected  = str_replace( "'", '"', $expected );
    15421551
    15431552        // Go!
    1544         $this->assertSame( $expected, get_echo( 'wp_print_scripts' ) );
     1553        $this->assertEqualMarkup( $expected, get_echo( 'wp_print_scripts' ) );
    15451554
    15461555        // No scripts left to print.
     
    15601569
    15611570        // Go!
    1562         $this->assertSame( $expected, get_echo( 'wp_print_scripts' ) );
     1571        $this->assertEqualMarkup( $expected, get_echo( 'wp_print_scripts' ) );
    15631572
    15641573        // No scripts left to print.
    1565         $this->assertSame( '', get_echo( 'wp_print_scripts' ) );
     1574        $this->assertEqualMarkup( '', get_echo( 'wp_print_scripts' ) );
    15661575    }
    15671576
     
    15891598        wp_enqueue_script( 'handle-three' );
    15901599
    1591         $this->assertSame( $expected, get_echo( 'wp_print_scripts' ) );
     1600        $this->assertEqualMarkup( $expected, get_echo( 'wp_print_scripts' ) );
    15921601    }
    15931602
     
    16771686        $expected_footer  = "<script type='text/javascript' src='/parent.js' id='parent-js'></script>\n";
    16781687
    1679         $this->assertSame( $expected_header, $header, 'Expected same header markup.' );
    1680         $this->assertSame( $expected_footer, $footer, 'Expected same footer markup.' );
     1688        $this->assertEqualMarkup( $expected_header, $header, 'Expected same header markup.' );
     1689        $this->assertEqualMarkup( $expected_footer, $footer, 'Expected same footer markup.' );
    16811690    }
    16821691
     
    16981707        $expected_footer .= "<script type='text/javascript' src='/parent.js' id='parent-js'></script>\n";
    16991708
    1700         $this->assertSame( $expected_header, $header, 'Expected same header markup.' );
    1701         $this->assertSame( $expected_footer, $footer, 'Expected same footer markup.' );
     1709        $this->assertEqualMarkup( $expected_header, $header, 'Expected same header markup.' );
     1710        $this->assertEqualMarkup( $expected_footer, $footer, 'Expected same footer markup.' );
    17021711    }
    17031712
     
    17291738        $expected_footer .= "<script type='text/javascript' src='/parent-footer.js' id='parent-footer-js'></script>\n";
    17301739
    1731         $this->assertSame( $expected_header, $header, 'Expected same header markup.' );
    1732         $this->assertSame( $expected_footer, $footer, 'Expected same footer markup.' );
     1740        $this->assertEqualMarkup( $expected_header, $header, 'Expected same header markup.' );
     1741        $this->assertEqualMarkup( $expected_footer, $footer, 'Expected same footer markup.' );
    17331742    }
    17341743
     
    19531962        $expected_localized .= "<script type='text/javascript' id='test-example-js-extra'>\n/* <![CDATA[ */\nvar testExample = {\"foo\":\"bar\"};\n/* ]]> */\n</script>\n";
    19541963        $expected_localized .= "<![endif]-->\n";
     1964        $expected_localized  = str_replace( "'", '"', $expected_localized );
    19551965
    19561966        $expected  = "<!--[if gte IE 9]>\n";
     
    19591969        $expected .= "<script type='text/javascript' id='test-example-js-after'>\nconsole.log(\"after\");\n</script>\n";
    19601970        $expected .= "<![endif]-->\n";
     1971        $expected  = str_replace( "'", '"', $expected );
    19611972
    19621973        wp_enqueue_script( 'test-example', 'example.com', array(), null );
     
    21252136        $print_scripts = $this->getActualOutput();
    21262137
    2127         $tail = substr( $print_scripts, strrpos( $print_scripts, "<script type='text/javascript' src='/customize-dependency.js' id='customize-dependency-js'>" ) );
     2138        $tail = substr( $print_scripts, strrpos( $print_scripts, '<script type="text/javascript" src="/customize-dependency.js" id="customize-dependency-js">' ) );
     2139
    21282140        $this->assertEqualMarkup( $expected_tail, $tail );
    21292141    }
     
    23052317        $expected .= "<script type='text/javascript' src='/wp-includes/js/script.js' id='test-example-js'></script>\n";
    23062318
    2307         $this->assertSameIgnoreEOL( $expected, get_echo( 'wp_print_scripts' ) );
     2319        $this->assertEqualMarkup( $expected, get_echo( 'wp_print_scripts' ) );
    23082320    }
    23092321
     
    23322344        $expected .= "<script type='text/javascript' src='/wp-content/plugins/my-plugin/js/script.js' id='plugin-example-js'></script>\n";
    23332345
    2334         $this->assertSameIgnoreEOL( $expected, get_echo( 'wp_print_scripts' ) );
     2346        $this->assertEqualMarkup( $expected, get_echo( 'wp_print_scripts' ) );
    23352347    }
    23362348
     
    23592371        $expected .= "<script type='text/javascript' src='/wp-content/themes/my-theme/js/script.js' id='theme-example-js'></script>\n";
    23602372
    2361         $this->assertSameIgnoreEOL( $expected, get_echo( 'wp_print_scripts' ) );
     2373        $this->assertEqualMarkup( $expected, get_echo( 'wp_print_scripts' ) );
    23622374    }
    23632375
     
    23862398        $expected .= "<script type='text/javascript' src='/wp-admin/js/script.js' id='script-handle-js'></script>\n";
    23872399
    2388         $this->assertSameIgnoreEOL( $expected, get_echo( 'wp_print_scripts' ) );
     2400        $this->assertEqualMarkup( $expected, get_echo( 'wp_print_scripts' ) );
    23892401    }
    23902402
     
    24162428        $expected .= "<script type='text/javascript' src='/wp-admin/js/script.js' id='test-example-js'></script>\n";
    24172429
    2418         $this->assertSameIgnoreEOL( $expected, get_echo( 'wp_print_scripts' ) );
     2430        $this->assertEqualMarkup( $expected, get_echo( 'wp_print_scripts' ) );
    24192431    }
    24202432
     
    24452457        $expected .= "<script type='text/javascript' src='/wp-includes/js/script.js' id='test-example-js'></script>\n";
    24462458
    2447         $this->assertSameIgnoreEOL( $expected, get_echo( 'wp_print_scripts' ) );
     2459        $this->assertEqualMarkup( $expected, get_echo( 'wp_print_scripts' ) );
    24482460    }
    24492461
     
    24752487        $expected .= "<script type='text/javascript' src='/wp-includes/js/script2.js' id='test-example-js'></script>\n";
    24762488
    2477         $this->assertSameIgnoreEOL( $expected, get_echo( 'wp_print_scripts' ) );
     2489        $this->assertEqualMarkup( $expected, get_echo( 'wp_print_scripts' ) );
    24782490    }
    24792491
     
    28642876        $expected .= "<script type='text/javascript' src='http://example.com' id='test-example-js'></script>\n";
    28652877
    2866         $this->assertSame( $expected, get_echo( 'wp_print_scripts' ) );
     2878        $this->assertEqualMarkup( $expected, get_echo( 'wp_print_scripts' ) );
    28672879    }
    28682880
     
    29292941        $expected .= "<script type='text/javascript' src='/default/common.js' id='common-js'></script>\n";
    29302942
    2931         $this->assertSame( $expected, $print_scripts );
     2943        $this->assertEqualMarkup( $expected, $print_scripts );
    29322944    }
    29332945
     
    29682980     *
    29692981     * @param string $markup Markup.
    2970      * @return DOMElement Body element wrapping supplied markup fragment.
     2982     * @return DOMDocument Document containing the normalized markup fragment.
    29712983     */
    29722984    protected function parse_markup_fragment( $markup ) {
     
    29862998        }
    29872999
    2988         return $body;
    2989     }
    2990 
    2991     /**
    2992      * Assert markup is equal.
     3000        return $dom;
     3001    }
     3002
     3003    /**
     3004     * Assert markup is equal after normalizing script tags.
    29933005     *
    29943006     * @param string $expected Expected markup.
     
    29973009     */
    29983010    protected function assertEqualMarkup( $expected, $actual, $message = '' ) {
     3011        $expected_dom = $this->parse_markup_fragment( $expected );
     3012        $actual_dom   = $this->parse_markup_fragment( $actual );
     3013        foreach ( array( $expected_dom, $actual_dom ) as $dom ) {
     3014            $xpath = new DOMXPath( $dom );
     3015            /** @var DOMElement $script */
     3016
     3017            // Normalize type attribute. When missing, it defaults to text/javascript.
     3018            foreach ( $xpath->query( '//script[ not( @type ) ]' ) as $script ) {
     3019                $script->setAttribute( 'type', 'text/javascript' );
     3020            }
     3021
     3022            // Normalize script contents to remove CDATA wrapper.
     3023            foreach ( $xpath->query( '//script[ contains( text(), "<![CDATA[" ) ]' ) as $script ) {
     3024                $script->textContent = str_replace(
     3025                    array(
     3026                        "/* <![CDATA[ */\n",
     3027                        "\n/* ]]> */",
     3028                    ),
     3029                    '',
     3030                    $script->textContent
     3031                );
     3032            }
     3033
     3034            // Normalize XHTML-compatible boolean attributes to HTML5 ones.
     3035            foreach ( array( 'async', 'defer' ) as $attribute ) {
     3036                foreach ( iterator_to_array( $xpath->query( "//script[ @{$attribute} = '{$attribute}' ]" ) ) as $script ) {
     3037                    $script->removeAttribute( $attribute );
     3038                    $script->setAttributeNode( $dom->createAttribute( $attribute ) );
     3039                }
     3040            }
     3041        }
     3042
    29993043        $this->assertEquals(
    3000             $this->parse_markup_fragment( $expected ),
    3001             $this->parse_markup_fragment( $actual ),
     3044            $expected_dom->getElementsByTagName( 'body' )->item( 0 ),
     3045            $actual_dom->getElementsByTagName( 'body' )->item( 0 ),
    30023046            $message
    30033047        );
    30043048    }
     3049
     3050    /**
     3051     * Adds html5 script theme support.
     3052     */
     3053    protected function add_html5_script_theme_support() {
     3054        add_theme_support( 'html5', array( 'script' ) );
     3055    }
    30053056}
Note: See TracChangeset for help on using the changeset viewer.