diff --git a/tests/phpunit/tests/html-api/wpHtmlTagProcessorScriptTag.php b/tests/phpunit/tests/html-api/wpHtmlTagProcessorScriptTag.php new file mode 100644 index 0000000000000..df74d2f6be50b --- /dev/null +++ b/tests/phpunit/tests/html-api/wpHtmlTagProcessorScriptTag.php @@ -0,0 +1,251 @@ +next_tag(); + + $this->assertSame( 'SCRIPT', $processor->get_tag(), 'Should be positioned on a SCRIPT tag' ); + $this->assertSame( + $expected_result, + $processor->is_javascript_script_tag(), + 'Failed to correctly identify JavaScript script tag' + ); + } + + /** + * Data provider for test_is_javascript_script_tag. + * + * @return array[] + */ + public static function data_is_javascript_script_tag() { + return array( + // Script tags without type or language attributes - should be JavaScript. + 'Script tag without attributes' => array( '', true ), + 'Script tag with other attributes' => array( '', true ), + + // Script tags with empty type attribute - should be JavaScript. + 'Script tag with empty type attribute' => array( '', true ), + 'Script tag with boolean type attribute' => array( '', true ), + + // Script tags with falsy but non-empty type attribute. + 'Script tag with type="0"' => array( '', false ), + + // Script tags without type but with language attribute - should be JavaScript. + 'Script tag with empty language attribute' => array( '', true ), + 'Script tag with boolean language attribute' => array( '', true ), + + // Script tags with falsy but non-empty language attribute. + 'Script tag with language="0"' => array( '', false ), + + // Script tags with JavaScript MIME types - should be JavaScript. + 'Script tag with application/ecmascript' => array( '', true ), + 'Script tag with application/javascript' => array( '', true ), + 'Script tag with application/x-ecmascript' => array( '', true ), + 'Script tag with application/x-javascript' => array( '', true ), + 'Script tag with text/ecmascript' => array( '', true ), + 'Script tag with text/javascript' => array( '', true ), + 'Script tag with text/javascript1.0' => array( '', true ), + 'Script tag with text/javascript1.1' => array( '', true ), + 'Script tag with text/javascript1.2' => array( '', true ), + 'Script tag with text/javascript1.3' => array( '', true ), + 'Script tag with text/javascript1.4' => array( '', true ), + 'Script tag with text/javascript1.5' => array( '', true ), + 'Script tag with text/jscript' => array( '', true ), + 'Script tag with text/livescript' => array( '', true ), + 'Script tag with text/x-ecmascript' => array( '', true ), + 'Script tag with text/x-javascript' => array( '', true ), + + // Case-insensitive matching for JavaScript MIME types. + 'Script tag with UPPERCASE type' => array( '', true ), + 'Script tag with MixedCase type' => array( '', true ), + 'Script tag with APPLICATION/JAVASCRIPT' => array( '', true ), + + // Script tags with module type - should be JavaScript. + 'Script tag with module type' => array( '', true ), + 'Script tag with MODULE type uppercase' => array( '', true ), + 'Script tag with MoDuLe type mixed case' => array( '', true ), + + // Script tags with whitespace around type - should strip whitespace. + 'Script tag with leading whitespace' => array( '', true ), + 'Script tag with trailing whitespace' => array( '', true ), + 'Script tag with surrounding whitespace' => array( '', true ), + 'Script tag with tab whitespace' => array( "", true ), + 'Script tag with newline whitespace' => array( "", true ), + 'Script tag with mixed whitespace' => array( "", true ), + + // Script tags with language attribute and non-empty value - should use text/{language}. + 'Script tag with language="javascript"' => array( '', true ), + 'Script tag with language="JavaScript"' => array( '', true ), + 'Script tag with language="ecmascript"' => array( '', true ), + 'Script tag with language="jscript"' => array( '', true ), + 'Script tag with language="livescript"' => array( '', true ), + + // Non-JavaScript script tags - should NOT be JavaScript. + 'Script tag with importmap type' => array( '', false ), + 'Script tag with speculationrules type' => array( '', false ), + 'Script tag with application/json type' => array( '', false ), + 'Script tag with text/json type' => array( '', false ), + 'Script tag with unknown MIME type' => array( '', false ), + 'Script tag with application/xml type' => array( '', false ), + 'Script tag with random type' => array( '', false ), + + // Non-script tags - should NOT be JavaScript. + 'DIV tag' => array( '
', false ), + 'SPAN tag' => array( '', false ), + 'P tag' => array( '

', false ), + ); + } + + /** + * @ticket 64419 + * + * @covers WP_HTML_Tag_Processor::is_javascript_script_tag + */ + public function test_is_javascript_script_tag_returns_false_before_finding_tags() { + $processor = new WP_HTML_Tag_Processor( 'Just some text' ); + $processor->next_token(); + + $this->assertFalse( + $processor->is_javascript_script_tag(), + 'Should return false when not stopped on script tag' + ); + } + + /** + * @ticket 64419 + * + * @covers WP_HTML_Tag_Processor::is_javascript_script_tag + */ + public function test_is_javascript_script_tag_returns_false_for_non_html_namespace() { + $processor = new WP_HTML_Tag_Processor( '' ); + $processor->next_tag( 'SCRIPT' ); + + $this->assertFalse( + $processor->is_javascript_script_tag(), + 'Should return false for script tags in non-HTML namespace' + ); + } + + /** + * @ticket 64419 + * + * @covers WP_HTML_Tag_Processor::is_json_script_tag + * + * @dataProvider data_is_json_script_tag + * + * @param string $html HTML containing a script tag. + * @param bool $expected_result Whether the script tag should be identified as JSON. + */ + public function test_is_json_script_tag( string $html, bool $expected_result ) { + $processor = new WP_HTML_Tag_Processor( $html ); + $processor->next_tag(); + + $this->assertSame( 'SCRIPT', $processor->get_tag(), 'Should be positioned on a SCRIPT tag' ); + $this->assertSame( + $expected_result, + $processor->is_json_script_tag(), + 'Failed to correctly identify JSON script tag' + ); + } + + /** + * Data provider for test_is_json_script_tag. + * + * @return array[] + */ + public static function data_is_json_script_tag() { + return array( + // JSON MIME types - should be JSON. + 'Script tag with application/json type' => array( '', true ), + 'Script tag with text/json type' => array( '', true ), + + // importmap and speculationrules - should be JSON. + 'Script tag with importmap type' => array( '', true ), + 'Script tag with speculationrules type' => array( '', true ), + + // Case-insensitive matching for JSON types. + 'Script tag with APPLICATION/JSON uppercase' => array( '', true ), + 'Script tag with Text/Json mixed case' => array( '', true ), + 'Script tag with IMPORTMAP uppercase' => array( '', true ), + 'Script tag with ImportMap mixed case' => array( '', true ), + 'Script tag with SPECULATIONRULES uppercase' => array( '', true ), + 'Script tag with SpeculationRules mixed' => array( '', true ), + + // Whitespace handling - should strip whitespace. + 'Script tag with leading whitespace' => array( '', true ), + 'Script tag with trailing whitespace' => array( '', true ), + 'Script tag with surrounding whitespace' => array( '', true ), + 'Script tag with tab whitespace' => array( "", true ), + 'Script tag with newline whitespace' => array( "", true ), + 'Script tag with mixed whitespace' => array( "", true ), + + // Non-JSON script tags - should NOT be JSON. + 'Script tag without type attribute' => array( '', false ), + 'Script tag with empty type attribute' => array( '', false ), + 'Script tag with boolean type attribute' => array( '', false ), + + // Script tags with falsy but non-empty type attribute. + 'Script tag with type="0"' => array( '', false ), + + 'Script tag with text/javascript type' => array( '', false ), + 'Script tag with module type' => array( '', false ), + 'Script tag with unknown MIME type' => array( '', false ), + 'Script tag with application/xml type' => array( '', false ), + + // Non-script tags - should NOT be JSON. + 'DIV tag' => array( '
', false ), + 'SPAN tag' => array( '', false ), + 'P tag' => array( '

', false ), + ); + } + + /** + * @ticket 64419 + * + * @covers WP_HTML_Tag_Processor::is_json_script_tag + */ + public function test_is_json_script_tag_returns_false_before_finding_tags() { + $processor = new WP_HTML_Tag_Processor( 'Just some text' ); + $processor->next_token(); + + $this->assertFalse( + $processor->is_json_script_tag(), + 'Should return false when not stopped on script tag' + ); + } + + /** + * @ticket 64419 + * + * @covers WP_HTML_Tag_Processor::is_json_script_tag + */ + public function test_is_json_script_tag_returns_false_for_non_html_namespace() { + $processor = new WP_HTML_Tag_Processor( '' ); + $processor->next_tag( 'SCRIPT' ); + + $this->assertFalse( + $processor->is_json_script_tag(), + 'Should return false for script tags in non-HTML namespace' + ); + } +}