SECURITY: blacklist CSS var()
[lhc/web/wiklou.git] / tests / phpunit / includes / content / JavaScriptContentTest.php
1 <?php
2
3 use MediaWiki\MediaWikiServices;
4
5 /**
6 * @group ContentHandler
7 * @group Database
8 * ^--- needed, because we do need the database to test link updates
9 */
10 class JavaScriptContentTest extends TextContentTest {
11
12 public function newContent( $text ) {
13 return new JavaScriptContent( $text );
14 }
15
16 public static function dataGetParserOutput() {
17 return [
18 [
19 'MediaWiki:Test.js',
20 null,
21 "hello <world>\n",
22 "<pre class=\"mw-code mw-js\" dir=\"ltr\">\nhello &lt;world&gt;\n\n</pre>"
23 ],
24 [
25 'MediaWiki:Test.js',
26 null,
27 "hello(); // [[world]]\n",
28 "<pre class=\"mw-code mw-js\" dir=\"ltr\">\nhello(); // [[world]]\n\n</pre>",
29 [
30 'Links' => [
31 [ 'World' => 0 ]
32 ]
33 ]
34 ],
35
36 // TODO: more...?
37 ];
38 }
39
40 // XXX: Unused function
41 public static function dataGetSection() {
42 return [
43 [ WikitextContentTest::$sections,
44 '0',
45 null
46 ],
47 [ WikitextContentTest::$sections,
48 '2',
49 null
50 ],
51 [ WikitextContentTest::$sections,
52 '8',
53 null
54 ],
55 ];
56 }
57
58 // XXX: Unused function
59 public static function dataReplaceSection() {
60 return [
61 [ WikitextContentTest::$sections,
62 '0',
63 'No more',
64 null,
65 null
66 ],
67 [ WikitextContentTest::$sections,
68 '',
69 'No more',
70 null,
71 null
72 ],
73 [ WikitextContentTest::$sections,
74 '2',
75 "== TEST ==\nmore fun",
76 null,
77 null
78 ],
79 [ WikitextContentTest::$sections,
80 '8',
81 'No more',
82 null,
83 null
84 ],
85 [ WikitextContentTest::$sections,
86 'new',
87 'No more',
88 'New',
89 null
90 ],
91 ];
92 }
93
94 /**
95 * @covers JavaScriptContent::addSectionHeader
96 */
97 public function testAddSectionHeader() {
98 $content = $this->newContent( 'hello world' );
99 $c = $content->addSectionHeader( 'test' );
100
101 $this->assertTrue( $content->equals( $c ) );
102 }
103
104 // XXX: currently, preSaveTransform is applied to scripts. this may change or become optional.
105 public static function dataPreSaveTransform() {
106 return [
107 [ 'hello this is ~~~',
108 "hello this is [[Special:Contributions/127.0.0.1|127.0.0.1]]",
109 ],
110 [ 'hello \'\'this\'\' is <nowiki>~~~</nowiki>',
111 'hello \'\'this\'\' is <nowiki>~~~</nowiki>',
112 ],
113 [ " Foo \n ",
114 " Foo",
115 ],
116 ];
117 }
118
119 public static function dataPreloadTransform() {
120 return [
121 [
122 'hello this is ~~~',
123 'hello this is ~~~',
124 ],
125 [
126 'hello \'\'this\'\' is <noinclude>foo</noinclude><includeonly>bar</includeonly>',
127 'hello \'\'this\'\' is <noinclude>foo</noinclude><includeonly>bar</includeonly>',
128 ],
129 ];
130 }
131
132 public static function dataGetRedirectTarget() {
133 return [
134 [ '#REDIRECT [[Test]]',
135 null,
136 ],
137 [ '#REDIRECT Test',
138 null,
139 ],
140 [ '* #REDIRECT [[Test]]',
141 null,
142 ],
143 ];
144 }
145
146 public static function dataIsCountable() {
147 return [
148 [ '',
149 null,
150 'any',
151 true
152 ],
153 [ 'Foo',
154 null,
155 'any',
156 true
157 ],
158 [ 'Foo',
159 null,
160 'link',
161 false
162 ],
163 [ 'Foo [[bar]]',
164 null,
165 'link',
166 false
167 ],
168 [ 'Foo',
169 true,
170 'link',
171 false
172 ],
173 [ 'Foo [[bar]]',
174 false,
175 'link',
176 false
177 ],
178 [ '#REDIRECT [[bar]]',
179 true,
180 'any',
181 true
182 ],
183 [ '#REDIRECT [[bar]]',
184 true,
185 'link',
186 false
187 ],
188 ];
189 }
190
191 public static function dataGetTextForSummary() {
192 return [
193 [ "hello\nworld.",
194 16,
195 'hello world.',
196 ],
197 [ 'hello world.',
198 8,
199 'hello...',
200 ],
201 [ '[[hello world]].',
202 8,
203 '[[hel...',
204 ],
205 ];
206 }
207
208 /**
209 * @covers JavaScriptContent::matchMagicWord
210 */
211 public function testMatchMagicWord() {
212 $mw = MediaWikiServices::getInstance()->getMagicWordFactory()->get( "staticredirect" );
213
214 $content = $this->newContent( "#REDIRECT [[FOO]]\n__STATICREDIRECT__" );
215 $this->assertFalse(
216 $content->matchMagicWord( $mw ),
217 "should not have matched magic word, since it's not wikitext"
218 );
219 }
220
221 /**
222 * @covers JavaScriptContent::updateRedirect
223 * @dataProvider provideUpdateRedirect
224 */
225 public function testUpdateRedirect( $oldText, $expectedText ) {
226 $this->setMwGlobals( [
227 'wgServer' => '//example.org',
228 'wgScriptPath' => '/w',
229 'wgScript' => '/w/index.php',
230 'wgResourceBasePath' => '/w',
231 ] );
232 $target = Title::newFromText( "testUpdateRedirect_target" );
233
234 $content = new JavaScriptContent( $oldText );
235 $newContent = $content->updateRedirect( $target );
236
237 $this->assertEquals( $expectedText, $newContent->getText() );
238 }
239
240 public static function provideUpdateRedirect() {
241 // phpcs:disable Generic.Files.LineLength
242 return [
243 [
244 '#REDIRECT [[Someplace]]',
245 '#REDIRECT [[Someplace]]',
246 ],
247 [
248 '/* #REDIRECT */mw.loader.load("//example.org/w/index.php?title=MediaWiki:MonoBook.js\u0026action=raw\u0026ctype=text/javascript");',
249 '/* #REDIRECT */mw.loader.load("//example.org/w/index.php?title=TestUpdateRedirect_target\u0026action=raw\u0026ctype=text/javascript");'
250 ]
251 ];
252 // phpcs:enable
253 }
254
255 /**
256 * @covers JavaScriptContent::getModel
257 */
258 public function testGetModel() {
259 $content = $this->newContent( "hello world." );
260
261 $this->assertEquals( CONTENT_MODEL_JAVASCRIPT, $content->getModel() );
262 }
263
264 /**
265 * @covers JavaScriptContent::getContentHandler
266 */
267 public function testGetContentHandler() {
268 $content = $this->newContent( "hello world." );
269
270 $this->assertEquals( CONTENT_MODEL_JAVASCRIPT, $content->getContentHandler()->getModelID() );
271 }
272
273 public static function dataEquals() {
274 return [
275 [ new JavaScriptContent( "hallo" ), null, false ],
276 [ new JavaScriptContent( "hallo" ), new JavaScriptContent( "hallo" ), true ],
277 [ new JavaScriptContent( "hallo" ), new CssContent( "hallo" ), false ],
278 [ new JavaScriptContent( "hallo" ), new JavaScriptContent( "HALLO" ), false ],
279 ];
280 }
281
282 /**
283 * @covers JavaScriptContent::getRedirectTarget
284 * @dataProvider provideGetRedirectTarget
285 */
286 public function testGetRedirectTarget( $title, $text ) {
287 $this->setMwGlobals( [
288 'wgServer' => '//example.org',
289 'wgScriptPath' => '/w',
290 'wgScript' => '/w/index.php',
291 'wgResourceBasePath' => '/w',
292 ] );
293 $content = new JavaScriptContent( $text );
294 $target = $content->getRedirectTarget();
295 $this->assertEquals( $title, $target ? $target->getPrefixedText() : null );
296 }
297
298 /**
299 * Keep this in sync with JavaScriptContentHandlerTest::provideMakeRedirectContent()
300 */
301 public static function provideGetRedirectTarget() {
302 // phpcs:disable Generic.Files.LineLength
303 return [
304 [
305 'MediaWiki:MonoBook.js',
306 '/* #REDIRECT */mw.loader.load("//example.org/w/index.php?title=MediaWiki:MonoBook.js\u0026action=raw\u0026ctype=text/javascript");'
307 ],
308 [
309 'User:FooBar/common.js',
310 '/* #REDIRECT */mw.loader.load("//example.org/w/index.php?title=User:FooBar/common.js\u0026action=raw\u0026ctype=text/javascript");'
311 ],
312 [
313 'Gadget:FooBaz.js',
314 '/* #REDIRECT */mw.loader.load("//example.org/w/index.php?title=Gadget:FooBaz.js\u0026action=raw\u0026ctype=text/javascript");'
315 ],
316 // Unicode
317 [
318 'User:😂/unicode.js',
319 '/* #REDIRECT */mw.loader.load("//example.org/w/index.php?title=User:%F0%9F%98%82/unicode.js\u0026action=raw\u0026ctype=text/javascript");'
320 ],
321 // No #REDIRECT comment
322 [
323 null,
324 'mw.loader.load("//example.org/w/index.php?title=MediaWiki:NoRedirect.js\u0026action=raw\u0026ctype=text/javascript");'
325 ],
326 // Different domain
327 [
328 null,
329 '/* #REDIRECT */mw.loader.load("//example.com/w/index.php?title=MediaWiki:OtherWiki.js\u0026action=raw\u0026ctype=text/javascript");'
330 ],
331 ];
332 // phpcs:enable
333 }
334 }