Drop 'comma' value for wgArticleCountMethod
[lhc/web/wiklou.git] / tests / phpunit / includes / content / WikitextContentTest.php
1 <?php
2
3 /**
4 * @group ContentHandler
5 *
6 * @group Database
7 * ^--- needed, because we do need the database to test link updates
8 */
9 class WikitextContentTest extends TextContentTest {
10 public static $sections = "Intro
11
12 == stuff ==
13 hello world
14
15 == test ==
16 just a test
17
18 == foo ==
19 more stuff
20 ";
21
22 public function newContent( $text ) {
23 return new WikitextContent( $text );
24 }
25
26 public static function dataGetParserOutput() {
27 return [
28 [
29 "WikitextContentTest_testGetParserOutput",
30 CONTENT_MODEL_WIKITEXT,
31 "hello ''world''\n",
32 "<div class=\"mw-parser-output\"><p>hello <i>world</i>\n</p>\n\n\n</div>"
33 ],
34 // TODO: more...?
35 ];
36 }
37
38 public static function dataGetSecondaryDataUpdates() {
39 return [
40 [ "WikitextContentTest_testGetSecondaryDataUpdates_1",
41 CONTENT_MODEL_WIKITEXT, "hello ''world''\n",
42 [
43 LinksUpdate::class => [
44 'mRecursive' => true,
45 'mLinks' => []
46 ]
47 ]
48 ],
49 [ "WikitextContentTest_testGetSecondaryDataUpdates_2",
50 CONTENT_MODEL_WIKITEXT, "hello [[world test 21344]]\n",
51 [
52 LinksUpdate::class => [
53 'mRecursive' => true,
54 'mLinks' => [
55 [ 'World_test_21344' => 0 ]
56 ]
57 ]
58 ]
59 ],
60 // TODO: more...?
61 ];
62 }
63
64 /**
65 * @dataProvider dataGetSecondaryDataUpdates
66 * @group Database
67 * @covers WikitextContent::getSecondaryDataUpdates
68 */
69 public function testGetSecondaryDataUpdates( $title, $model, $text, $expectedStuff ) {
70 $ns = $this->getDefaultWikitextNS();
71 $title = Title::newFromText( $title, $ns );
72
73 $content = ContentHandler::makeContent( $text, $title, $model );
74
75 $page = WikiPage::factory( $title );
76 $page->doEditContent( $content, '' );
77
78 $updates = $content->getSecondaryDataUpdates( $title );
79
80 // make updates accessible by class name
81 foreach ( $updates as $update ) {
82 $class = get_class( $update );
83 $updates[$class] = $update;
84 }
85
86 foreach ( $expectedStuff as $class => $fieldValues ) {
87 $this->assertArrayHasKey( $class, $updates, "missing an update of type $class" );
88
89 $update = $updates[$class];
90
91 foreach ( $fieldValues as $field => $value ) {
92 $v = $update->$field; # if the field doesn't exist, just crash and burn
93 $this->assertEquals(
94 $value,
95 $v,
96 "unexpected value for field $field in instance of $class"
97 );
98 }
99 }
100
101 $page->doDeleteArticle( '' );
102 }
103
104 public static function dataGetSection() {
105 return [
106 [ self::$sections,
107 "0",
108 "Intro"
109 ],
110 [ self::$sections,
111 "2",
112 "== test ==
113 just a test"
114 ],
115 [ self::$sections,
116 "8",
117 false
118 ],
119 ];
120 }
121
122 /**
123 * @dataProvider dataGetSection
124 * @covers WikitextContent::getSection
125 */
126 public function testGetSection( $text, $sectionId, $expectedText ) {
127 $content = $this->newContent( $text );
128
129 $sectionContent = $content->getSection( $sectionId );
130 if ( is_object( $sectionContent ) ) {
131 $sectionText = $sectionContent->getNativeData();
132 } else {
133 $sectionText = $sectionContent;
134 }
135
136 $this->assertEquals( $expectedText, $sectionText );
137 }
138
139 public static function dataReplaceSection() {
140 return [
141 [ self::$sections,
142 "0",
143 "No more",
144 null,
145 trim( preg_replace( '/^Intro/sm', 'No more', self::$sections ) )
146 ],
147 [ self::$sections,
148 "",
149 "No more",
150 null,
151 "No more"
152 ],
153 [ self::$sections,
154 "2",
155 "== TEST ==\nmore fun",
156 null,
157 trim( preg_replace(
158 '/^== test ==.*== foo ==/sm', "== TEST ==\nmore fun\n\n== foo ==",
159 self::$sections
160 ) )
161 ],
162 [ self::$sections,
163 "8",
164 "No more",
165 null,
166 self::$sections
167 ],
168 [ self::$sections,
169 "new",
170 "No more",
171 "New",
172 trim( self::$sections ) . "\n\n\n== New ==\n\nNo more"
173 ],
174 ];
175 }
176
177 /**
178 * @dataProvider dataReplaceSection
179 * @covers WikitextContent::replaceSection
180 */
181 public function testReplaceSection( $text, $section, $with, $sectionTitle, $expected ) {
182 $content = $this->newContent( $text );
183 $c = $content->replaceSection( $section, $this->newContent( $with ), $sectionTitle );
184
185 $this->assertEquals( $expected, is_null( $c ) ? null : $c->getNativeData() );
186 }
187
188 /**
189 * @covers WikitextContent::addSectionHeader
190 */
191 public function testAddSectionHeader() {
192 $content = $this->newContent( 'hello world' );
193 $content = $content->addSectionHeader( 'test' );
194
195 $this->assertEquals( "== test ==\n\nhello world", $content->getNativeData() );
196 }
197
198 public static function dataPreSaveTransform() {
199 return [
200 [ 'hello this is ~~~',
201 "hello this is [[Special:Contributions/127.0.0.1|127.0.0.1]]",
202 ],
203 [ 'hello \'\'this\'\' is <nowiki>~~~</nowiki>',
204 'hello \'\'this\'\' is <nowiki>~~~</nowiki>',
205 ],
206 [ // rtrim
207 " Foo \n ",
208 " Foo",
209 ],
210 ];
211 }
212
213 public static function dataPreloadTransform() {
214 return [
215 [
216 'hello this is ~~~',
217 "hello this is ~~~",
218 ],
219 [
220 'hello \'\'this\'\' is <noinclude>foo</noinclude><includeonly>bar</includeonly>',
221 'hello \'\'this\'\' is bar',
222 ],
223 ];
224 }
225
226 public static function dataGetRedirectTarget() {
227 return [
228 [ '#REDIRECT [[Test]]',
229 'Test',
230 ],
231 [ '#REDIRECT Test',
232 null,
233 ],
234 [ '* #REDIRECT [[Test]]',
235 null,
236 ],
237 ];
238 }
239
240 public static function dataGetTextForSummary() {
241 return [
242 [ "hello\nworld.",
243 16,
244 'hello world.',
245 ],
246 [ 'hello world.',
247 8,
248 'hello...',
249 ],
250 [ '[[hello world]].',
251 8,
252 'hel...',
253 ],
254 ];
255 }
256
257 public static function dataIsCountable() {
258 return [
259 [ '',
260 null,
261 'any',
262 true
263 ],
264 [ 'Foo',
265 null,
266 'any',
267 true
268 ],
269 [ 'Foo',
270 null,
271 'link',
272 false
273 ],
274 [ 'Foo [[bar]]',
275 null,
276 'link',
277 true
278 ],
279 [ 'Foo',
280 true,
281 'link',
282 true
283 ],
284 [ 'Foo [[bar]]',
285 false,
286 'link',
287 false
288 ],
289 [ '#REDIRECT [[bar]]',
290 true,
291 'any',
292 false
293 ],
294 [ '#REDIRECT [[bar]]',
295 true,
296 'link',
297 false
298 ],
299 ];
300 }
301
302 /**
303 * @covers WikitextContent::matchMagicWord
304 */
305 public function testMatchMagicWord() {
306 $mw = MagicWord::get( "staticredirect" );
307
308 $content = $this->newContent( "#REDIRECT [[FOO]]\n__STATICREDIRECT__" );
309 $this->assertTrue( $content->matchMagicWord( $mw ), "should have matched magic word" );
310
311 $content = $this->newContent( "#REDIRECT [[FOO]]" );
312 $this->assertFalse(
313 $content->matchMagicWord( $mw ),
314 "should not have matched magic word"
315 );
316 }
317
318 /**
319 * @covers WikitextContent::updateRedirect
320 */
321 public function testUpdateRedirect() {
322 $target = Title::newFromText( "testUpdateRedirect_target" );
323
324 // test with non-redirect page
325 $content = $this->newContent( "hello world." );
326 $newContent = $content->updateRedirect( $target );
327
328 $this->assertTrue( $content->equals( $newContent ), "content should be unchanged" );
329
330 // test with actual redirect
331 $content = $this->newContent( "#REDIRECT [[Someplace]]" );
332 $newContent = $content->updateRedirect( $target );
333
334 $this->assertFalse( $content->equals( $newContent ), "content should have changed" );
335 $this->assertTrue( $newContent->isRedirect(), "new content should be a redirect" );
336
337 $this->assertEquals(
338 $target->getFullText(),
339 $newContent->getRedirectTarget()->getFullText()
340 );
341 }
342
343 /**
344 * @covers WikitextContent::getModel
345 */
346 public function testGetModel() {
347 $content = $this->newContent( "hello world." );
348
349 $this->assertEquals( CONTENT_MODEL_WIKITEXT, $content->getModel() );
350 }
351
352 /**
353 * @covers WikitextContent::getContentHandler
354 */
355 public function testGetContentHandler() {
356 $content = $this->newContent( "hello world." );
357
358 $this->assertEquals( CONTENT_MODEL_WIKITEXT, $content->getContentHandler()->getModelID() );
359 }
360
361 public function testRedirectParserOption() {
362 $title = Title::newFromText( 'testRedirectParserOption' );
363
364 // Set up hook and its reporting variables
365 $wikitext = null;
366 $redirectTarget = null;
367 $this->mergeMwGlobalArrayValue( 'wgHooks', [
368 'InternalParseBeforeLinks' => [
369 function ( &$parser, &$text, &$stripState ) use ( &$wikitext, &$redirectTarget ) {
370 $wikitext = $text;
371 $redirectTarget = $parser->getOptions()->getRedirectTarget();
372 }
373 ]
374 ] );
375
376 // Test with non-redirect page
377 $wikitext = false;
378 $redirectTarget = false;
379 $content = $this->newContent( 'hello world.' );
380 $options = $content->getContentHandler()->makeParserOptions( 'canonical' );
381 $options->setRedirectTarget( $title );
382 $content->getParserOutput( $title, null, $options );
383 $this->assertEquals( 'hello world.', $wikitext,
384 'Wikitext passed to hook was not as expected'
385 );
386 $this->assertEquals( null, $redirectTarget, 'Redirect seen in hook was not null' );
387 $this->assertEquals( $title, $options->getRedirectTarget(),
388 'ParserOptions\' redirectTarget was changed'
389 );
390
391 // Test with a redirect page
392 $wikitext = false;
393 $redirectTarget = false;
394 $content = $this->newContent(
395 "#REDIRECT [[TestRedirectParserOption/redir]]\nhello redirect."
396 );
397 $options = $content->getContentHandler()->makeParserOptions( 'canonical' );
398 $content->getParserOutput( $title, null, $options );
399 $this->assertEquals(
400 'hello redirect.',
401 $wikitext,
402 'Wikitext passed to hook was not as expected'
403 );
404 $this->assertNotEquals(
405 null,
406 $redirectTarget,
407 'Redirect seen in hook was null' );
408 $this->assertEquals(
409 'TestRedirectParserOption/redir',
410 $redirectTarget->getFullText(),
411 'Redirect seen in hook was not the expected title'
412 );
413 $this->assertEquals(
414 null,
415 $options->getRedirectTarget(),
416 'ParserOptions\' redirectTarget was changed'
417 );
418 }
419
420 public static function dataEquals() {
421 return [
422 [ new WikitextContent( "hallo" ), null, false ],
423 [ new WikitextContent( "hallo" ), new WikitextContent( "hallo" ), true ],
424 [ new WikitextContent( "hallo" ), new JavaScriptContent( "hallo" ), false ],
425 [ new WikitextContent( "hallo" ), new TextContent( "hallo" ), false ],
426 [ new WikitextContent( "hallo" ), new WikitextContent( "HALLO" ), false ],
427 ];
428 }
429
430 public static function dataGetDeletionUpdates() {
431 return [
432 [ "WikitextContentTest_testGetSecondaryDataUpdates_1",
433 CONTENT_MODEL_WIKITEXT, "hello ''world''\n",
434 [ LinksDeletionUpdate::class => [] ]
435 ],
436 [ "WikitextContentTest_testGetSecondaryDataUpdates_2",
437 CONTENT_MODEL_WIKITEXT, "hello [[world test 21344]]\n",
438 [ LinksDeletionUpdate::class => [] ]
439 ],
440 // @todo more...?
441 ];
442 }
443 }