Skip to content

Commit 1362451

Browse files
authored
Add JS and JSON script tag tests
1 parent 3f7f227 commit 1362451

File tree

1 file changed

+251
-0
lines changed

1 file changed

+251
-0
lines changed
Lines changed: 251 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,251 @@
1+
<?php
2+
/**
3+
* Unit tests covering WP_HTML_Tag_Processor script tag functionality.
4+
*
5+
* @package WordPress
6+
* @subpackage HTML-API
7+
*
8+
* @group html-api
9+
*
10+
* @coversDefaultClass WP_HTML_Tag_Processor
11+
*/
12+
class Tests_HtmlApi_WpHtmlTagProcessorScriptTag extends WP_UnitTestCase {
13+
/**
14+
* @ticket 64419
15+
*
16+
* @covers WP_HTML_Tag_Processor::is_javascript_script_tag
17+
*
18+
* @dataProvider data_is_javascript_script_tag
19+
*
20+
* @param string $html HTML containing a script tag.
21+
* @param bool $expected_result Whether the script tag should be identified as JavaScript.
22+
*/
23+
public function test_is_javascript_script_tag( string $html, bool $expected_result ) {
24+
$processor = new WP_HTML_Tag_Processor( $html );
25+
$processor->next_tag();
26+
27+
$this->assertSame( 'SCRIPT', $processor->get_tag(), 'Should be positioned on a SCRIPT tag' );
28+
$this->assertSame(
29+
$expected_result,
30+
$processor->is_javascript_script_tag(),
31+
'Failed to correctly identify JavaScript script tag'
32+
);
33+
}
34+
35+
/**
36+
* Data provider for test_is_javascript_script_tag.
37+
*
38+
* @return array[]
39+
*/
40+
public static function data_is_javascript_script_tag() {
41+
return array(
42+
// Script tags without type or language attributes - should be JavaScript.
43+
'Script tag without attributes' => array( '<script></script>', true ),
44+
'Script tag with other attributes' => array( '<script id="test"></script>', true ),
45+
46+
// Script tags with empty type attribute - should be JavaScript.
47+
'Script tag with empty type attribute' => array( '<script type=""></script>', true ),
48+
'Script tag with boolean type attribute' => array( '<script type></script>', true ),
49+
50+
// Script tags with falsy but non-empty type attribute.
51+
'Script tag with type="0"' => array( '<script type="0"></script>', false ),
52+
53+
// Script tags without type but with language attribute - should be JavaScript.
54+
'Script tag with empty language attribute' => array( '<script language=""></script>', true ),
55+
'Script tag with boolean language attribute' => array( '<script language></script>', true ),
56+
57+
// Script tags with falsy but non-empty language attribute.
58+
'Script tag with language="0"' => array( '<script language="0"></script>', false ),
59+
60+
// Script tags with JavaScript MIME types - should be JavaScript.
61+
'Script tag with application/ecmascript' => array( '<script type="application/ecmascript"></script>', true ),
62+
'Script tag with application/javascript' => array( '<script type="application/javascript"></script>', true ),
63+
'Script tag with application/x-ecmascript' => array( '<script type="application/x-ecmascript"></script>', true ),
64+
'Script tag with application/x-javascript' => array( '<script type="application/x-javascript"></script>', true ),
65+
'Script tag with text/ecmascript' => array( '<script type="text/ecmascript"></script>', true ),
66+
'Script tag with text/javascript' => array( '<script type="text/javascript"></script>', true ),
67+
'Script tag with text/javascript1.0' => array( '<script type="text/javascript1.0"></script>', true ),
68+
'Script tag with text/javascript1.1' => array( '<script type="text/javascript1.1"></script>', true ),
69+
'Script tag with text/javascript1.2' => array( '<script type="text/javascript1.2"></script>', true ),
70+
'Script tag with text/javascript1.3' => array( '<script type="text/javascript1.3"></script>', true ),
71+
'Script tag with text/javascript1.4' => array( '<script type="text/javascript1.4"></script>', true ),
72+
'Script tag with text/javascript1.5' => array( '<script type="text/javascript1.5"></script>', true ),
73+
'Script tag with text/jscript' => array( '<script type="text/jscript"></script>', true ),
74+
'Script tag with text/livescript' => array( '<script type="text/livescript"></script>', true ),
75+
'Script tag with text/x-ecmascript' => array( '<script type="text/x-ecmascript"></script>', true ),
76+
'Script tag with text/x-javascript' => array( '<script type="text/x-javascript"></script>', true ),
77+
78+
// Case-insensitive matching for JavaScript MIME types.
79+
'Script tag with UPPERCASE type' => array( '<script type="TEXT/JAVASCRIPT"></script>', true ),
80+
'Script tag with MixedCase type' => array( '<script type="Text/JavaScript"></script>', true ),
81+
'Script tag with APPLICATION/JAVASCRIPT' => array( '<script type="APPLICATION/JAVASCRIPT"></script>', true ),
82+
83+
// Script tags with module type - should be JavaScript.
84+
'Script tag with module type' => array( '<script type="module"></script>', true ),
85+
'Script tag with MODULE type uppercase' => array( '<script type="MODULE"></script>', true ),
86+
'Script tag with MoDuLe type mixed case' => array( '<script type="MoDuLe"></script>', true ),
87+
88+
// Script tags with whitespace around type - should strip whitespace.
89+
'Script tag with leading whitespace' => array( '<script type=" text/javascript"></script>', true ),
90+
'Script tag with trailing whitespace' => array( '<script type="text/javascript "></script>', true ),
91+
'Script tag with surrounding whitespace' => array( '<script type=" text/javascript "></script>', true ),
92+
'Script tag with tab whitespace' => array( "<script type=\"\ttext/javascript\t\"></script>", true ),
93+
'Script tag with newline whitespace' => array( "<script type=\"\ntext/javascript\n\"></script>", true ),
94+
'Script tag with mixed whitespace' => array( "<script type=\" \t\ntext/javascript \t\n\"></script>", true ),
95+
96+
// Script tags with language attribute and non-empty value - should use text/{language}.
97+
'Script tag with language="javascript"' => array( '<script language="javascript"></script>', true ),
98+
'Script tag with language="JavaScript"' => array( '<script language="JavaScript"></script>', true ),
99+
'Script tag with language="ecmascript"' => array( '<script language="ecmascript"></script>', true ),
100+
'Script tag with language="jscript"' => array( '<script language="jscript"></script>', true ),
101+
'Script tag with language="livescript"' => array( '<script language="livescript"></script>', true ),
102+
103+
// Non-JavaScript script tags - should NOT be JavaScript.
104+
'Script tag with importmap type' => array( '<script type="importmap"></script>', false ),
105+
'Script tag with speculationrules type' => array( '<script type="speculationrules"></script>', false ),
106+
'Script tag with application/json type' => array( '<script type="application/json"></script>', false ),
107+
'Script tag with text/json type' => array( '<script type="text/json"></script>', false ),
108+
'Script tag with unknown MIME type' => array( '<script type="text/plain"></script>', false ),
109+
'Script tag with application/xml type' => array( '<script type="application/xml"></script>', false ),
110+
'Script tag with random type' => array( '<script type="random/type"></script>', false ),
111+
112+
// Non-script tags - should NOT be JavaScript.
113+
'DIV tag' => array( '<div></div>', false ),
114+
'SPAN tag' => array( '<span></span>', false ),
115+
'P tag' => array( '<p></p>', false ),
116+
);
117+
}
118+
119+
/**
120+
* @ticket 64419
121+
*
122+
* @covers WP_HTML_Tag_Processor::is_javascript_script_tag
123+
*/
124+
public function test_is_javascript_script_tag_returns_false_before_finding_tags() {
125+
$processor = new WP_HTML_Tag_Processor( 'Just some text' );
126+
$processor->next_token();
127+
128+
$this->assertFalse(
129+
$processor->is_javascript_script_tag(),
130+
'Should return false when not stopped on script tag'
131+
);
132+
}
133+
134+
/**
135+
* @ticket 64419
136+
*
137+
* @covers WP_HTML_Tag_Processor::is_javascript_script_tag
138+
*/
139+
public function test_is_javascript_script_tag_returns_false_for_non_html_namespace() {
140+
$processor = new WP_HTML_Tag_Processor( '<svg><script type="text/javascript"></script></svg>' );
141+
$processor->next_tag( 'SCRIPT' );
142+
143+
$this->assertFalse(
144+
$processor->is_javascript_script_tag(),
145+
'Should return false for script tags in non-HTML namespace'
146+
);
147+
}
148+
149+
/**
150+
* @ticket 64419
151+
*
152+
* @covers WP_HTML_Tag_Processor::is_json_script_tag
153+
*
154+
* @dataProvider data_is_json_script_tag
155+
*
156+
* @param string $html HTML containing a script tag.
157+
* @param bool $expected_result Whether the script tag should be identified as JSON.
158+
*/
159+
public function test_is_json_script_tag( string $html, bool $expected_result ) {
160+
$processor = new WP_HTML_Tag_Processor( $html );
161+
$processor->next_tag();
162+
163+
$this->assertSame( 'SCRIPT', $processor->get_tag(), 'Should be positioned on a SCRIPT tag' );
164+
$this->assertSame(
165+
$expected_result,
166+
$processor->is_json_script_tag(),
167+
'Failed to correctly identify JSON script tag'
168+
);
169+
}
170+
171+
/**
172+
* Data provider for test_is_json_script_tag.
173+
*
174+
* @return array[]
175+
*/
176+
public static function data_is_json_script_tag() {
177+
return array(
178+
// JSON MIME types - should be JSON.
179+
'Script tag with application/json type' => array( '<script type="application/json"></script>', true ),
180+
'Script tag with text/json type' => array( '<script type="text/json"></script>', true ),
181+
182+
// importmap and speculationrules - should be JSON.
183+
'Script tag with importmap type' => array( '<script type="importmap"></script>', true ),
184+
'Script tag with speculationrules type' => array( '<script type="speculationrules"></script>', true ),
185+
186+
// Case-insensitive matching for JSON types.
187+
'Script tag with APPLICATION/JSON uppercase' => array( '<script type="APPLICATION/JSON"></script>', true ),
188+
'Script tag with Text/Json mixed case' => array( '<script type="Text/Json"></script>', true ),
189+
'Script tag with IMPORTMAP uppercase' => array( '<script type="IMPORTMAP"></script>', true ),
190+
'Script tag with ImportMap mixed case' => array( '<script type="ImportMap"></script>', true ),
191+
'Script tag with SPECULATIONRULES uppercase' => array( '<script type="SPECULATIONRULES"></script>', true ),
192+
'Script tag with SpeculationRules mixed' => array( '<script type="SpeculationRules"></script>', true ),
193+
194+
// Whitespace handling - should strip whitespace.
195+
'Script tag with leading whitespace' => array( '<script type=" application/json"></script>', true ),
196+
'Script tag with trailing whitespace' => array( '<script type="application/json "></script>', true ),
197+
'Script tag with surrounding whitespace' => array( '<script type=" application/json "></script>', true ),
198+
'Script tag with tab whitespace' => array( "<script type=\"\tapplication/json\t\"></script>", true ),
199+
'Script tag with newline whitespace' => array( "<script type=\"\napplication/json\n\"></script>", true ),
200+
'Script tag with mixed whitespace' => array( "<script type=\" \t\napplication/json \t\n\"></script>", true ),
201+
202+
// Non-JSON script tags - should NOT be JSON.
203+
'Script tag without type attribute' => array( '<script></script>', false ),
204+
'Script tag with empty type attribute' => array( '<script type=""></script>', false ),
205+
'Script tag with boolean type attribute' => array( '<script type></script>', false ),
206+
207+
// Script tags with falsy but non-empty type attribute.
208+
'Script tag with type="0"' => array( '<script type="0"></script>', false ),
209+
210+
'Script tag with text/javascript type' => array( '<script type="text/javascript"></script>', false ),
211+
'Script tag with module type' => array( '<script type="module"></script>', false ),
212+
'Script tag with unknown MIME type' => array( '<script type="text/plain"></script>', false ),
213+
'Script tag with application/xml type' => array( '<script type="application/xml"></script>', false ),
214+
215+
// Non-script tags - should NOT be JSON.
216+
'DIV tag' => array( '<div></div>', false ),
217+
'SPAN tag' => array( '<span></span>', false ),
218+
'P tag' => array( '<p></p>', false ),
219+
);
220+
}
221+
222+
/**
223+
* @ticket 64419
224+
*
225+
* @covers WP_HTML_Tag_Processor::is_json_script_tag
226+
*/
227+
public function test_is_json_script_tag_returns_false_before_finding_tags() {
228+
$processor = new WP_HTML_Tag_Processor( 'Just some text' );
229+
$processor->next_token();
230+
231+
$this->assertFalse(
232+
$processor->is_json_script_tag(),
233+
'Should return false when not stopped on script tag'
234+
);
235+
}
236+
237+
/**
238+
* @ticket 64419
239+
*
240+
* @covers WP_HTML_Tag_Processor::is_json_script_tag
241+
*/
242+
public function test_is_json_script_tag_returns_false_for_non_html_namespace() {
243+
$processor = new WP_HTML_Tag_Processor( '<svg><script type="application/json"></script></svg>' );
244+
$processor->next_tag( 'SCRIPT' );
245+
246+
$this->assertFalse(
247+
$processor->is_json_script_tag(),
248+
'Should return false for script tags in non-HTML namespace'
249+
);
250+
}
251+
}

0 commit comments

Comments
 (0)