fd1f886ff742299a8ad11d0595be5f4a647512dc
[lhc/web/wiklou.git] / tests / phpunit / includes / WikitextContentTest.php
1 <?php
2
3 /**
4 * @group ContentHandler
5 */
6 class WikitextContentTest extends MediaWikiTestCase {
7
8 public function setup() {
9 global $wgUser;
10
11 // anon user
12 $wgUser = new User();
13 $wgUser->setName( '127.0.0.1' );
14
15 $this->context = new RequestContext( new FauxRequest() );
16 $this->context->setTitle( Title::newFromText( "Test" ) );
17 $this->context->setUser( $wgUser );
18 }
19
20 public function newContent( $text ) {
21 return new WikitextContent( $text );
22 }
23
24
25 public function dataGetParserOutput() {
26 return array(
27 array("WikitextContentTest_testGetParserOutput", "hello ''world''\n", "<p>hello <i>world</i>\n</p>"),
28 // @todo: more...?
29 );
30 }
31
32 /**
33 * @dataProvider dataGetParserOutput
34 */
35 public function testGetParserOutput( $title, $text, $expectedHtml ) {
36 $title = Title::newFromText( $title );
37 $content = ContentHandler::makeContent( $text, $title );
38
39 $po = $content->getParserOutput( $title );
40
41 $this->assertEquals( $expectedHtml, $po->getText() );
42 // @todo: assert more properties
43 }
44
45 public function dataGetSecondaryDataUpdates() {
46 return array(
47 array("WikitextContentTest_testGetSecondaryDataUpdates_1", "hello ''world''\n",
48 array( 'LinksUpdate' => array( 'mRecursive' => true,
49 'mLinks' => array() ) )
50 ),
51 array("WikitextContentTest_testGetSecondaryDataUpdates_2", "hello [[world test 21344]]\n",
52 array( 'LinksUpdate' => array( 'mRecursive' => true,
53 'mLinks' => array( array( 'World_test_21344' => 0 ) ) ) )
54 ),
55 // @todo: more...?
56 );
57 }
58
59 /**
60 * @dataProvider dataGetSecondaryDataUpdates
61 * @group Database
62 */
63 public function testGetSecondaryDataUpdates( $title, $text, $expectedStuff ) {
64 $title = Title::newFromText( $title );
65 $title->resetArticleID( 2342 ); //dummy id. fine as long as we don't try to execute the updates!
66
67 $handler = ContentHandler::getForModelID( $title->getContentModel() );
68 $content = ContentHandler::makeContent( $text, $title );
69
70 $updates = $content->getSecondaryDataUpdates( $title );
71
72 // make updates accessible by class name
73 foreach ( $updates as $update ) {
74 $class = get_class( $update );
75 $updates[ $class ] = $update;
76 }
77
78 foreach ( $expectedStuff as $class => $fieldValues ) {
79 $this->assertArrayHasKey( $class, $updates, "missing an update of type $class" );
80
81 $update = $updates[ $class ];
82
83 foreach ( $fieldValues as $field => $value ) {
84 $v = $update->$field; #if the field doesn't exist, just crash and burn
85 $this->assertEquals( $value, $v, "unexpected value for field $field in instance of $class" );
86 }
87 }
88 }
89
90
91 static $sections =
92
93 "Intro
94
95 == stuff ==
96 hello world
97
98 == test ==
99 just a test
100
101 == foo ==
102 more stuff
103 ";
104
105 public function dataGetSection() {
106 return array(
107 array( WikitextContentTest::$sections,
108 "0",
109 "Intro"
110 ),
111 array( WikitextContentTest::$sections,
112 "2",
113 "== test ==
114 just a test"
115 ),
116 array( WikitextContentTest::$sections,
117 "8",
118 false
119 ),
120 );
121 }
122
123 /**
124 * @dataProvider dataGetSection
125 */
126 public function testGetSection( $text, $sectionId, $expectedText ) {
127 $content = $this->newContent( $text );
128
129 $sectionContent = $content->getSection( $sectionId );
130
131 $this->assertEquals( $expectedText, is_null( $sectionContent ) ? null : $sectionContent->getNativeData() );
132 }
133
134 public function dataReplaceSection() {
135 return array(
136 array( WikitextContentTest::$sections,
137 "0",
138 "No more",
139 null,
140 trim( preg_replace( '/^Intro/sm', 'No more', WikitextContentTest::$sections ) )
141 ),
142 array( WikitextContentTest::$sections,
143 "",
144 "No more",
145 null,
146 "No more"
147 ),
148 array( WikitextContentTest::$sections,
149 "2",
150 "== TEST ==\nmore fun",
151 null,
152 trim( preg_replace( '/^== test ==.*== foo ==/sm', "== TEST ==\nmore fun\n\n== foo ==", WikitextContentTest::$sections ) )
153 ),
154 array( WikitextContentTest::$sections,
155 "8",
156 "No more",
157 null,
158 WikitextContentTest::$sections
159 ),
160 array( WikitextContentTest::$sections,
161 "new",
162 "No more",
163 "New",
164 trim( WikitextContentTest::$sections ) . "\n\n\n== New ==\n\nNo more"
165 ),
166 );
167 }
168
169 /**
170 * @dataProvider dataReplaceSection
171 */
172 public function testReplaceSection( $text, $section, $with, $sectionTitle, $expected ) {
173 $content = $this->newContent( $text );
174 $c = $content->replaceSection( $section, $this->newContent( $with ), $sectionTitle );
175
176 $this->assertEquals( $expected, is_null( $c ) ? null : $c->getNativeData() );
177 }
178
179 public function testAddSectionHeader( ) {
180 $content = $this->newContent( 'hello world' );
181 $content = $content->addSectionHeader( 'test' );
182
183 $this->assertEquals( "== test ==\n\nhello world", $content->getNativeData() );
184 }
185
186 public function dataPreSaveTransform() {
187 return array(
188 array( 'hello this is ~~~',
189 "hello this is [[Special:Contributions/127.0.0.1|127.0.0.1]]",
190 ),
191 array( 'hello \'\'this\'\' is <nowiki>~~~</nowiki>',
192 'hello \'\'this\'\' is <nowiki>~~~</nowiki>',
193 ),
194 );
195 }
196
197 /**
198 * @dataProvider dataPreSaveTransform
199 */
200 public function testPreSaveTransform( $text, $expected ) {
201 global $wgContLang;
202
203 $options = ParserOptions::newFromUserAndLang( $this->context->getUser(), $wgContLang );
204
205 $content = $this->newContent( $text );
206 $content = $content->preSaveTransform( $this->context->getTitle(), $this->context->getUser(), $options );
207
208 $this->assertEquals( $expected, $content->getNativeData() );
209 }
210
211 public function dataPreloadTransform() {
212 return array(
213 array( 'hello this is ~~~',
214 "hello this is ~~~",
215 ),
216 array( 'hello \'\'this\'\' is <noinclude>foo</noinclude><includeonly>bar</includeonly>',
217 'hello \'\'this\'\' is bar',
218 ),
219 );
220 }
221
222 /**
223 * @dataProvider dataPreloadTransform
224 */
225 public function testPreloadTransform( $text, $expected ) {
226 global $wgContLang;
227 $options = ParserOptions::newFromUserAndLang( $this->context->getUser(), $wgContLang );
228
229 $content = $this->newContent( $text );
230 $content = $content->preloadTransform( $this->context->getTitle(), $options );
231
232 $this->assertEquals( $expected, $content->getNativeData() );
233 }
234
235 public function dataGetRedirectTarget() {
236 return array(
237 array( '#REDIRECT [[Test]]',
238 'Test',
239 ),
240 array( '#REDIRECT Test',
241 null,
242 ),
243 array( '* #REDIRECT [[Test]]',
244 null,
245 ),
246 );
247 }
248
249 /**
250 * @dataProvider dataGetRedirectTarget
251 */
252 public function testGetRedirectTarget( $text, $expected ) {
253 $content = $this->newContent( $text );
254 $t = $content->getRedirectTarget( );
255
256 if ( is_null( $expected ) ) $this->assertNull( $t, "text should not have generated a redirect target: $text" );
257 else $this->assertEquals( $expected, $t->getPrefixedText() );
258 }
259
260 /**
261 * @dataProvider dataGetRedirectTarget
262 */
263 public function isRedirect( $text, $expected ) {
264 $content = $this->newContent( $text );
265
266 $this->assertEquals( !is_null($expected), $content->isRedirect() );
267 }
268
269
270 /**
271 * @todo: test needs database!
272 */
273 /*
274 public function getRedirectChain() {
275 $text = $this->getNativeData();
276 return Title::newFromRedirectArray( $text );
277 }
278 */
279
280 /**
281 * @todo: test needs database!
282 */
283 /*
284 public function getUltimateRedirectTarget() {
285 $text = $this->getNativeData();
286 return Title::newFromRedirectRecurse( $text );
287 }
288 */
289
290
291 public function dataIsCountable() {
292 return array(
293 array( '',
294 null,
295 'any',
296 true
297 ),
298 array( 'Foo',
299 null,
300 'any',
301 true
302 ),
303 array( 'Foo',
304 null,
305 'comma',
306 false
307 ),
308 array( 'Foo, bar',
309 null,
310 'comma',
311 true
312 ),
313 array( 'Foo',
314 null,
315 'link',
316 false
317 ),
318 array( 'Foo [[bar]]',
319 null,
320 'link',
321 true
322 ),
323 array( 'Foo',
324 true,
325 'link',
326 true
327 ),
328 array( 'Foo [[bar]]',
329 false,
330 'link',
331 false
332 ),
333 array( '#REDIRECT [[bar]]',
334 true,
335 'any',
336 false
337 ),
338 array( '#REDIRECT [[bar]]',
339 true,
340 'comma',
341 false
342 ),
343 array( '#REDIRECT [[bar]]',
344 true,
345 'link',
346 false
347 ),
348 );
349 }
350
351
352 /**
353 * @dataProvider dataIsCountable
354 * @group Database
355 */
356 public function testIsCountable( $text, $hasLinks, $mode, $expected ) {
357 global $wgArticleCountMethod;
358
359 $old = $wgArticleCountMethod;
360 $wgArticleCountMethod = $mode;
361
362 $content = $this->newContent( $text );
363
364 $v = $content->isCountable( $hasLinks, $this->context->getTitle() );
365 $wgArticleCountMethod = $old;
366
367 $this->assertEquals( $expected, $v, "isCountable() returned unexpected value " . var_export( $v, true )
368 . " instead of " . var_export( $expected, true ) . " in mode `$mode` for text \"$text\"" );
369 }
370
371 public function dataGetTextForSummary() {
372 return array(
373 array( "hello\nworld.",
374 16,
375 'hello world.',
376 ),
377 array( 'hello world.',
378 8,
379 'hello...',
380 ),
381 array( '[[hello world]].',
382 8,
383 'hel...',
384 ),
385 );
386 }
387
388 /**
389 * @dataProvider dataGetTextForSummary
390 */
391 public function testGetTextForSummary( $text, $maxlength, $expected ) {
392 $content = $this->newContent( $text );
393
394 $this->assertEquals( $expected, $content->getTextForSummary( $maxlength ) );
395 }
396
397
398 public function testGetTextForSearchIndex( ) {
399 $content = $this->newContent( "hello world." );
400
401 $this->assertEquals( "hello world.", $content->getTextForSearchIndex() );
402 }
403
404 public function testCopy() {
405 $content = $this->newContent( "hello world." );
406 $copy = $content->copy();
407
408 $this->assertTrue( $content->equals( $copy ), "copy must be equal to original" );
409 $this->assertEquals( "hello world.", $copy->getNativeData() );
410 }
411
412 public function testGetSize( ) {
413 $content = $this->newContent( "hello world." );
414
415 $this->assertEquals( 12, $content->getSize() );
416 }
417
418 public function testGetNativeData( ) {
419 $content = $this->newContent( "hello world." );
420
421 $this->assertEquals( "hello world.", $content->getNativeData() );
422 }
423
424 public function testGetWikitextForTransclusion( ) {
425 $content = $this->newContent( "hello world." );
426
427 $this->assertEquals( "hello world.", $content->getWikitextForTransclusion() );
428 }
429
430 public function testMatchMagicWord( ) {
431 $mw = MagicWord::get( "staticredirect" );
432
433 $content = $this->newContent( "#REDIRECT [[FOO]]\n__STATICREDIRECT__" );
434 $this->assertTrue( $content->matchMagicWord( $mw ), "should have matched magic word" );
435
436 $content = $this->newContent( "#REDIRECT [[FOO]]" );
437 $this->assertFalse( $content->matchMagicWord( $mw ), "should not have matched magic word" );
438 }
439
440 public function testUpdateRedirect( ) {
441 $target = Title::newFromText( "testUpdateRedirect_target" );
442
443 // test with non-redirect page
444 $content = $this->newContent( "hello world." );
445 $newContent = $content->updateRedirect( $target );
446
447 $this->assertTrue( $content->equals( $newContent ), "content should be unchanged" );
448
449 // test with actual redirect
450 $content = $this->newContent( "#REDIRECT [[Someplace]]" );
451 $newContent = $content->updateRedirect( $target );
452
453 $this->assertFalse( $content->equals( $newContent ), "content should have changed" );
454 $this->assertTrue( $newContent->isRedirect(), "new content should be a redirect" );
455
456 $this->assertEquals( $target->getFullText(), $newContent->getRedirectTarget()->getFullText() );
457 }
458
459 # =================================================================================================================
460
461 public function testGetModel() {
462 $content = $this->newContent( "hello world." );
463
464 $this->assertEquals( CONTENT_MODEL_WIKITEXT, $content->getModel() );
465 }
466
467 public function testGetContentHandler() {
468 $content = $this->newContent( "hello world." );
469
470 $this->assertEquals( CONTENT_MODEL_WIKITEXT, $content->getContentHandler()->getModelID() );
471 }
472
473 public function dataIsEmpty( ) {
474 return array(
475 array( '', true ),
476 array( ' ', false ),
477 array( '0', false ),
478 array( 'hallo welt.', false ),
479 );
480 }
481
482 /**
483 * @dataProvider dataIsEmpty
484 */
485 public function testIsEmpty( $text, $empty ) {
486 $content = $this->newContent( $text );
487
488 $this->assertEquals( $empty, $content->isEmpty() );
489 }
490
491 public function dataEquals( ) {
492 return array(
493 array( new WikitextContent( "hallo" ), null, false ),
494 array( new WikitextContent( "hallo" ), new WikitextContent( "hallo" ), true ),
495 array( new WikitextContent( "hallo" ), new JavascriptContent( "hallo" ), false ),
496 array( new WikitextContent( "hallo" ), new WikitextContent( "HALLO" ), false ),
497 );
498 }
499
500 /**
501 * @dataProvider dataEquals
502 */
503 public function testEquals( Content $a, Content $b = null, $equal = false ) {
504 $this->assertEquals( $equal, $a->equals( $b ) );
505 }
506
507 public function dataGetDeletionUpdates() {
508 return array(
509 array("WikitextContentTest_testGetSecondaryDataUpdates_1", "hello ''world''\n",
510 array( 'LinksDeletionUpdate' => array( ) )
511 ),
512 array("WikitextContentTest_testGetSecondaryDataUpdates_2", "hello [[world test 21344]]\n",
513 array( 'LinksDeletionUpdate' => array( ) )
514 ),
515 // @todo: more...?
516 );
517 }
518
519 /**
520 * @dataProvider dataGetDeletionUpdates
521 */
522 public function testDeletionUpdates( $title, $text, $expectedStuff ) {
523 $title = Title::newFromText( $title );
524 $title->resetArticleID( 2342 ); //dummy id. fine as long as we don't try to execute the updates!
525
526 $handler = ContentHandler::getForModelID( $title->getContentModel() );
527 $content = ContentHandler::makeContent( $text, $title );
528
529 $updates = $content->getDeletionUpdates( $title );
530
531 // make updates accessible by class name
532 foreach ( $updates as $update ) {
533 $class = get_class( $update );
534 $updates[ $class ] = $update;
535 }
536
537 foreach ( $expectedStuff as $class => $fieldValues ) {
538 $this->assertArrayHasKey( $class, $updates, "missing an update of type $class" );
539
540 $update = $updates[ $class ];
541
542 foreach ( $fieldValues as $field => $value ) {
543 $v = $update->$field; #if the field doesn't exist, just crash and burn
544 $this->assertEquals( $value, $v, "unexpected value for field $field in instance of $class" );
545 }
546 }
547 }
548
549 }