Merge "mediawiki.searchSuggest: Show full article title as a tooltip for each suggestion"
[lhc/web/wiklou.git] / tests / phpunit / includes / WikiPageTest.php
1 <?php
2
3 /**
4 * @group ContentHandler
5 * @group Database
6 * ^--- important, causes temporary tables to be used instead of the real database
7 * @group medium
8 **/
9 class WikiPageTest extends MediaWikiLangTestCase {
10
11 protected $pages_to_delete;
12
13 function __construct( $name = null, array $data = array(), $dataName = '' ) {
14 parent::__construct( $name, $data, $dataName );
15
16 $this->tablesUsed = array_merge(
17 $this->tablesUsed,
18 array( 'page',
19 'revision',
20 'text',
21
22 'recentchanges',
23 'logging',
24
25 'page_props',
26 'pagelinks',
27 'categorylinks',
28 'langlinks',
29 'externallinks',
30 'imagelinks',
31 'templatelinks',
32 'iwlinks' ) );
33 }
34
35 protected function setUp() {
36 parent::setUp();
37 $this->pages_to_delete = array();
38
39 LinkCache::singleton()->clear(); # avoid cached redirect status, etc
40 }
41
42 protected function tearDown() {
43 foreach ( $this->pages_to_delete as $p ) {
44 /* @var $p WikiPage */
45
46 try {
47 if ( $p->exists() ) {
48 $p->doDeleteArticle( "testing done." );
49 }
50 } catch ( MWException $ex ) {
51 // fail silently
52 }
53 }
54 parent::tearDown();
55 }
56
57 /**
58 * @param Title $title
59 * @param string $model
60 * @return WikiPage
61 */
62 protected function newPage( $title, $model = null ) {
63 if ( is_string( $title ) ) {
64 $ns = $this->getDefaultWikitextNS();
65 $title = Title::newFromText( $title, $ns );
66 }
67
68 $p = new WikiPage( $title );
69
70 $this->pages_to_delete[] = $p;
71
72 return $p;
73 }
74
75 /**
76 * @param string|Title|WikiPage $page
77 * @param string $text
78 * @param int $model
79 *
80 * @return WikiPage
81 */
82 protected function createPage( $page, $text, $model = null ) {
83 if ( is_string( $page ) || $page instanceof Title ) {
84 $page = $this->newPage( $page, $model );
85 }
86
87 $content = ContentHandler::makeContent( $text, $page->getTitle(), $model );
88 $page->doEditContent( $content, "testing", EDIT_NEW );
89
90 return $page;
91 }
92
93 /**
94 * @covers WikiPage::doEditContent
95 */
96 public function testDoEditContent() {
97 $page = $this->newPage( "WikiPageTest_testDoEditContent" );
98 $title = $page->getTitle();
99
100 $content = ContentHandler::makeContent(
101 "[[Lorem ipsum]] dolor sit amet, consetetur sadipscing elitr, sed diam "
102 . " nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat.",
103 $title,
104 CONTENT_MODEL_WIKITEXT
105 );
106
107 $page->doEditContent( $content, "[[testing]] 1" );
108
109 $this->assertTrue( $title->getArticleID() > 0, "Title object should have new page id" );
110 $this->assertTrue( $page->getId() > 0, "WikiPage should have new page id" );
111 $this->assertTrue( $title->exists(), "Title object should indicate that the page now exists" );
112 $this->assertTrue( $page->exists(), "WikiPage object should indicate that the page now exists" );
113
114 $id = $page->getId();
115
116 # ------------------------
117 $dbr = wfGetDB( DB_SLAVE );
118 $res = $dbr->select( 'pagelinks', '*', array( 'pl_from' => $id ) );
119 $n = $res->numRows();
120 $res->free();
121
122 $this->assertEquals( 1, $n, 'pagelinks should contain one link from the page' );
123
124 # ------------------------
125 $page = new WikiPage( $title );
126
127 $retrieved = $page->getContent();
128 $this->assertTrue( $content->equals( $retrieved ), 'retrieved content doesn\'t equal original' );
129
130 # ------------------------
131 $content = ContentHandler::makeContent(
132 "At vero eos et accusam et justo duo [[dolores]] et ea rebum. "
133 . "Stet clita kasd [[gubergren]], no sea takimata sanctus est.",
134 $title,
135 CONTENT_MODEL_WIKITEXT
136 );
137
138 $page->doEditContent( $content, "testing 2" );
139
140 # ------------------------
141 $page = new WikiPage( $title );
142
143 $retrieved = $page->getContent();
144 $this->assertTrue( $content->equals( $retrieved ), 'retrieved content doesn\'t equal original' );
145
146 # ------------------------
147 $dbr = wfGetDB( DB_SLAVE );
148 $res = $dbr->select( 'pagelinks', '*', array( 'pl_from' => $id ) );
149 $n = $res->numRows();
150 $res->free();
151
152 $this->assertEquals( 2, $n, 'pagelinks should contain two links from the page' );
153 }
154
155 /**
156 * @covers WikiPage::doEdit
157 */
158 public function testDoEdit() {
159 $this->hideDeprecated( "WikiPage::doEdit" );
160 $this->hideDeprecated( "WikiPage::getText" );
161 $this->hideDeprecated( "Revision::getText" );
162
163 //NOTE: assume help namespace will default to wikitext
164 $title = Title::newFromText( "Help:WikiPageTest_testDoEdit" );
165
166 $page = $this->newPage( $title );
167
168 $text = "[[Lorem ipsum]] dolor sit amet, consetetur sadipscing elitr, sed diam "
169 . " nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat.";
170
171 $page->doEdit( $text, "[[testing]] 1" );
172
173 $this->assertTrue( $title->getArticleID() > 0, "Title object should have new page id" );
174 $this->assertTrue( $page->getId() > 0, "WikiPage should have new page id" );
175 $this->assertTrue( $title->exists(), "Title object should indicate that the page now exists" );
176 $this->assertTrue( $page->exists(), "WikiPage object should indicate that the page now exists" );
177
178 $id = $page->getId();
179
180 # ------------------------
181 $dbr = wfGetDB( DB_SLAVE );
182 $res = $dbr->select( 'pagelinks', '*', array( 'pl_from' => $id ) );
183 $n = $res->numRows();
184 $res->free();
185
186 $this->assertEquals( 1, $n, 'pagelinks should contain one link from the page' );
187
188 # ------------------------
189 $page = new WikiPage( $title );
190
191 $retrieved = $page->getText();
192 $this->assertEquals( $text, $retrieved, 'retrieved text doesn\'t equal original' );
193
194 # ------------------------
195 $text = "At vero eos et accusam et justo duo [[dolores]] et ea rebum. "
196 . "Stet clita kasd [[gubergren]], no sea takimata sanctus est.";
197
198 $page->doEdit( $text, "testing 2" );
199
200 # ------------------------
201 $page = new WikiPage( $title );
202
203 $retrieved = $page->getText();
204 $this->assertEquals( $text, $retrieved, 'retrieved text doesn\'t equal original' );
205
206 # ------------------------
207 $dbr = wfGetDB( DB_SLAVE );
208 $res = $dbr->select( 'pagelinks', '*', array( 'pl_from' => $id ) );
209 $n = $res->numRows();
210 $res->free();
211
212 $this->assertEquals( 2, $n, 'pagelinks should contain two links from the page' );
213 }
214
215 /**
216 * @covers WikiPage::doQuickEdit
217 */
218 public function testDoQuickEdit() {
219 global $wgUser;
220
221 $this->hideDeprecated( "WikiPage::doQuickEdit" );
222
223 //NOTE: assume help namespace will default to wikitext
224 $page = $this->createPage( "Help:WikiPageTest_testDoQuickEdit", "original text" );
225
226 $text = "quick text";
227 $page->doQuickEdit( $text, $wgUser, "testing q" );
228
229 # ---------------------
230 $page = new WikiPage( $page->getTitle() );
231 $this->assertEquals( $text, $page->getText() );
232 }
233
234 /**
235 * @covers WikiPage::doQuickEditContent
236 */
237 public function testDoQuickEditContent() {
238 global $wgUser;
239
240 $page = $this->createPage(
241 "WikiPageTest_testDoQuickEditContent",
242 "original text",
243 CONTENT_MODEL_WIKITEXT
244 );
245
246 $content = ContentHandler::makeContent(
247 "quick text",
248 $page->getTitle(),
249 CONTENT_MODEL_WIKITEXT
250 );
251 $page->doQuickEditContent( $content, $wgUser, "testing q" );
252
253 # ---------------------
254 $page = new WikiPage( $page->getTitle() );
255 $this->assertTrue( $content->equals( $page->getContent() ) );
256 }
257
258 /**
259 * @covers WikiPage::doDeleteArticle
260 */
261 public function testDoDeleteArticle() {
262 $page = $this->createPage(
263 "WikiPageTest_testDoDeleteArticle",
264 "[[original text]] foo",
265 CONTENT_MODEL_WIKITEXT
266 );
267 $id = $page->getId();
268
269 $page->doDeleteArticle( "testing deletion" );
270
271 $this->assertFalse(
272 $page->getTitle()->getArticleID() > 0,
273 "Title object should now have page id 0"
274 );
275 $this->assertFalse( $page->getId() > 0, "WikiPage should now have page id 0" );
276 $this->assertFalse(
277 $page->exists(),
278 "WikiPage::exists should return false after page was deleted"
279 );
280 $this->assertNull(
281 $page->getContent(),
282 "WikiPage::getContent should return null after page was deleted"
283 );
284 $this->assertFalse(
285 $page->getText(),
286 "WikiPage::getText should return false after page was deleted"
287 );
288
289 $t = Title::newFromText( $page->getTitle()->getPrefixedText() );
290 $this->assertFalse(
291 $t->exists(),
292 "Title::exists should return false after page was deleted"
293 );
294
295 # ------------------------
296 $dbr = wfGetDB( DB_SLAVE );
297 $res = $dbr->select( 'pagelinks', '*', array( 'pl_from' => $id ) );
298 $n = $res->numRows();
299 $res->free();
300
301 $this->assertEquals( 0, $n, 'pagelinks should contain no more links from the page' );
302 }
303
304 /**
305 * @covers WikiPage::doDeleteUpdates
306 */
307 public function testDoDeleteUpdates() {
308 $page = $this->createPage(
309 "WikiPageTest_testDoDeleteArticle",
310 "[[original text]] foo",
311 CONTENT_MODEL_WIKITEXT
312 );
313 $id = $page->getId();
314
315 $page->doDeleteUpdates( $id );
316
317 # ------------------------
318 $dbr = wfGetDB( DB_SLAVE );
319 $res = $dbr->select( 'pagelinks', '*', array( 'pl_from' => $id ) );
320 $n = $res->numRows();
321 $res->free();
322
323 $this->assertEquals( 0, $n, 'pagelinks should contain no more links from the page' );
324 }
325
326 /**
327 * @covers WikiPage::getRevision
328 */
329 public function testGetRevision() {
330 $page = $this->newPage( "WikiPageTest_testGetRevision" );
331
332 $rev = $page->getRevision();
333 $this->assertNull( $rev );
334
335 # -----------------
336 $this->createPage( $page, "some text", CONTENT_MODEL_WIKITEXT );
337
338 $rev = $page->getRevision();
339
340 $this->assertEquals( $page->getLatest(), $rev->getId() );
341 $this->assertEquals( "some text", $rev->getContent()->getNativeData() );
342 }
343
344 /**
345 * @covers WikiPage::getContent
346 */
347 public function testGetContent() {
348 $page = $this->newPage( "WikiPageTest_testGetContent" );
349
350 $content = $page->getContent();
351 $this->assertNull( $content );
352
353 # -----------------
354 $this->createPage( $page, "some text", CONTENT_MODEL_WIKITEXT );
355
356 $content = $page->getContent();
357 $this->assertEquals( "some text", $content->getNativeData() );
358 }
359
360 /**
361 * @covers WikiPage::getText
362 */
363 public function testGetText() {
364 $this->hideDeprecated( "WikiPage::getText" );
365
366 $page = $this->newPage( "WikiPageTest_testGetText" );
367
368 $text = $page->getText();
369 $this->assertFalse( $text );
370
371 # -----------------
372 $this->createPage( $page, "some text", CONTENT_MODEL_WIKITEXT );
373
374 $text = $page->getText();
375 $this->assertEquals( "some text", $text );
376 }
377
378 /**
379 * @covers WikiPage::getRawText
380 */
381 public function testGetRawText() {
382 $this->hideDeprecated( "WikiPage::getRawText" );
383
384 $page = $this->newPage( "WikiPageTest_testGetRawText" );
385
386 $text = $page->getRawText();
387 $this->assertFalse( $text );
388
389 # -----------------
390 $this->createPage( $page, "some text", CONTENT_MODEL_WIKITEXT );
391
392 $text = $page->getRawText();
393 $this->assertEquals( "some text", $text );
394 }
395
396 /**
397 * @covers WikiPage::getContentModel
398 */
399 public function testGetContentModel() {
400 global $wgContentHandlerUseDB;
401
402 if ( !$wgContentHandlerUseDB ) {
403 $this->markTestSkipped( '$wgContentHandlerUseDB is disabled' );
404 }
405
406 $page = $this->createPage(
407 "WikiPageTest_testGetContentModel",
408 "some text",
409 CONTENT_MODEL_JAVASCRIPT
410 );
411
412 $page = new WikiPage( $page->getTitle() );
413 $this->assertEquals( CONTENT_MODEL_JAVASCRIPT, $page->getContentModel() );
414 }
415
416 /**
417 * @covers WikiPage::getContentHandler
418 */
419 public function testGetContentHandler() {
420 global $wgContentHandlerUseDB;
421
422 if ( !$wgContentHandlerUseDB ) {
423 $this->markTestSkipped( '$wgContentHandlerUseDB is disabled' );
424 }
425
426 $page = $this->createPage(
427 "WikiPageTest_testGetContentHandler",
428 "some text",
429 CONTENT_MODEL_JAVASCRIPT
430 );
431
432 $page = new WikiPage( $page->getTitle() );
433 $this->assertEquals( 'JavaScriptContentHandler', get_class( $page->getContentHandler() ) );
434 }
435
436 /**
437 * @covers WikiPage::exists
438 */
439 public function testExists() {
440 $page = $this->newPage( "WikiPageTest_testExists" );
441 $this->assertFalse( $page->exists() );
442
443 # -----------------
444 $this->createPage( $page, "some text", CONTENT_MODEL_WIKITEXT );
445 $this->assertTrue( $page->exists() );
446
447 $page = new WikiPage( $page->getTitle() );
448 $this->assertTrue( $page->exists() );
449
450 # -----------------
451 $page->doDeleteArticle( "done testing" );
452 $this->assertFalse( $page->exists() );
453
454 $page = new WikiPage( $page->getTitle() );
455 $this->assertFalse( $page->exists() );
456 }
457
458 public static function provideHasViewableContent() {
459 return array(
460 array( 'WikiPageTest_testHasViewableContent', false, true ),
461 array( 'Special:WikiPageTest_testHasViewableContent', false ),
462 array( 'MediaWiki:WikiPageTest_testHasViewableContent', false ),
463 array( 'Special:Userlogin', true ),
464 array( 'MediaWiki:help', true ),
465 );
466 }
467
468 /**
469 * @dataProvider provideHasViewableContent
470 * @covers WikiPage::hasViewableContent
471 */
472 public function testHasViewableContent( $title, $viewable, $create = false ) {
473 $page = $this->newPage( $title );
474 $this->assertEquals( $viewable, $page->hasViewableContent() );
475
476 if ( $create ) {
477 $this->createPage( $page, "some text", CONTENT_MODEL_WIKITEXT );
478 $this->assertTrue( $page->hasViewableContent() );
479
480 $page = new WikiPage( $page->getTitle() );
481 $this->assertTrue( $page->hasViewableContent() );
482 }
483 }
484
485 public static function provideGetRedirectTarget() {
486 return array(
487 array( 'WikiPageTest_testGetRedirectTarget_1', CONTENT_MODEL_WIKITEXT, "hello world", null ),
488 array(
489 'WikiPageTest_testGetRedirectTarget_2',
490 CONTENT_MODEL_WIKITEXT,
491 "#REDIRECT [[hello world]]",
492 "Hello world"
493 ),
494 );
495 }
496
497 /**
498 * @dataProvider provideGetRedirectTarget
499 * @covers WikiPage::getRedirectTarget
500 */
501 public function testGetRedirectTarget( $title, $model, $text, $target ) {
502 $page = $this->createPage( $title, $text, $model );
503
504 # sanity check, because this test seems to fail for no reason for some people.
505 $c = $page->getContent();
506 $this->assertEquals( 'WikitextContent', get_class( $c ) );
507
508 # now, test the actual redirect
509 $t = $page->getRedirectTarget();
510 $this->assertEquals( $target, is_null( $t ) ? null : $t->getPrefixedText() );
511 }
512
513 /**
514 * @dataProvider provideGetRedirectTarget
515 * @covers WikiPage::isRedirect
516 */
517 public function testIsRedirect( $title, $model, $text, $target ) {
518 $page = $this->createPage( $title, $text, $model );
519 $this->assertEquals( !is_null( $target ), $page->isRedirect() );
520 }
521
522 public static function provideIsCountable() {
523 return array(
524
525 // any
526 array( 'WikiPageTest_testIsCountable',
527 CONTENT_MODEL_WIKITEXT,
528 '',
529 'any',
530 true
531 ),
532 array( 'WikiPageTest_testIsCountable',
533 CONTENT_MODEL_WIKITEXT,
534 'Foo',
535 'any',
536 true
537 ),
538
539 // comma
540 array( 'WikiPageTest_testIsCountable',
541 CONTENT_MODEL_WIKITEXT,
542 'Foo',
543 'comma',
544 false
545 ),
546 array( 'WikiPageTest_testIsCountable',
547 CONTENT_MODEL_WIKITEXT,
548 'Foo, bar',
549 'comma',
550 true
551 ),
552
553 // link
554 array( 'WikiPageTest_testIsCountable',
555 CONTENT_MODEL_WIKITEXT,
556 'Foo',
557 'link',
558 false
559 ),
560 array( 'WikiPageTest_testIsCountable',
561 CONTENT_MODEL_WIKITEXT,
562 'Foo [[bar]]',
563 'link',
564 true
565 ),
566
567 // redirects
568 array( 'WikiPageTest_testIsCountable',
569 CONTENT_MODEL_WIKITEXT,
570 '#REDIRECT [[bar]]',
571 'any',
572 false
573 ),
574 array( 'WikiPageTest_testIsCountable',
575 CONTENT_MODEL_WIKITEXT,
576 '#REDIRECT [[bar]]',
577 'comma',
578 false
579 ),
580 array( 'WikiPageTest_testIsCountable',
581 CONTENT_MODEL_WIKITEXT,
582 '#REDIRECT [[bar]]',
583 'link',
584 false
585 ),
586
587 // not a content namespace
588 array( 'Talk:WikiPageTest_testIsCountable',
589 CONTENT_MODEL_WIKITEXT,
590 'Foo',
591 'any',
592 false
593 ),
594 array( 'Talk:WikiPageTest_testIsCountable',
595 CONTENT_MODEL_WIKITEXT,
596 'Foo, bar',
597 'comma',
598 false
599 ),
600 array( 'Talk:WikiPageTest_testIsCountable',
601 CONTENT_MODEL_WIKITEXT,
602 'Foo [[bar]]',
603 'link',
604 false
605 ),
606
607 // not a content namespace, different model
608 array( 'MediaWiki:WikiPageTest_testIsCountable.js',
609 null,
610 'Foo',
611 'any',
612 false
613 ),
614 array( 'MediaWiki:WikiPageTest_testIsCountable.js',
615 null,
616 'Foo, bar',
617 'comma',
618 false
619 ),
620 array( 'MediaWiki:WikiPageTest_testIsCountable.js',
621 null,
622 'Foo [[bar]]',
623 'link',
624 false
625 ),
626 );
627 }
628
629 /**
630 * @dataProvider provideIsCountable
631 * @covers WikiPage::isCountable
632 */
633 public function testIsCountable( $title, $model, $text, $mode, $expected ) {
634 global $wgContentHandlerUseDB;
635
636 $this->setMwGlobals( 'wgArticleCountMethod', $mode );
637
638 $title = Title::newFromText( $title );
639
640 if ( !$wgContentHandlerUseDB
641 && $model
642 && ContentHandler::getDefaultModelFor( $title ) != $model
643 ) {
644 $this->markTestSkipped( "Can not use non-default content model $model for "
645 . $title->getPrefixedDBkey() . " with \$wgContentHandlerUseDB disabled." );
646 }
647
648 $page = $this->createPage( $title, $text, $model );
649
650 $editInfo = $page->prepareContentForEdit( $page->getContent() );
651
652 $v = $page->isCountable();
653 $w = $page->isCountable( $editInfo );
654
655 $this->assertEquals(
656 $expected,
657 $v,
658 "isCountable( null ) returned unexpected value " . var_export( $v, true )
659 . " instead of " . var_export( $expected, true )
660 . " in mode `$mode` for text \"$text\""
661 );
662
663 $this->assertEquals(
664 $expected,
665 $w,
666 "isCountable( \$editInfo ) returned unexpected value " . var_export( $v, true )
667 . " instead of " . var_export( $expected, true )
668 . " in mode `$mode` for text \"$text\""
669 );
670 }
671
672 public static function provideGetParserOutput() {
673 return array(
674 array( CONTENT_MODEL_WIKITEXT, "hello ''world''\n", "<p>hello <i>world</i></p>" ),
675 // @todo more...?
676 );
677 }
678
679 /**
680 * @dataProvider provideGetParserOutput
681 * @covers WikiPage::getParserOutput
682 */
683 public function testGetParserOutput( $model, $text, $expectedHtml ) {
684 $page = $this->createPage( 'WikiPageTest_testGetParserOutput', $text, $model );
685
686 $opt = $page->makeParserOptions( 'canonical' );
687 $po = $page->getParserOutput( $opt );
688 $text = $po->getText();
689
690 $text = trim( preg_replace( '/<!--.*?-->/sm', '', $text ) ); # strip injected comments
691 $text = preg_replace( '!\s*(</p>)!sm', '\1', $text ); # don't let tidy confuse us
692
693 $this->assertEquals( $expectedHtml, $text );
694
695 return $po;
696 }
697
698 /**
699 * @covers WikiPage::getParserOutput
700 */
701 public function testGetParserOutput_nonexisting() {
702 static $count = 0;
703 $count++;
704
705 $page = new WikiPage( new Title( "WikiPageTest_testGetParserOutput_nonexisting_$count" ) );
706
707 $opt = new ParserOptions();
708 $po = $page->getParserOutput( $opt );
709
710 $this->assertFalse( $po, "getParserOutput() shall return false for non-existing pages." );
711 }
712
713 /**
714 * @covers WikiPage::getParserOutput
715 */
716 public function testGetParserOutput_badrev() {
717 $page = $this->createPage( 'WikiPageTest_testGetParserOutput', "dummy", CONTENT_MODEL_WIKITEXT );
718
719 $opt = new ParserOptions();
720 $po = $page->getParserOutput( $opt, $page->getLatest() + 1234 );
721
722 // @todo would be neat to also test deleted revision
723
724 $this->assertFalse( $po, "getParserOutput() shall return false for non-existing revisions." );
725 }
726
727 public static $sections =
728
729 "Intro
730
731 == stuff ==
732 hello world
733
734 == test ==
735 just a test
736
737 == foo ==
738 more stuff
739 ";
740
741 public function dataReplaceSection() {
742 //NOTE: assume the Help namespace to contain wikitext
743 return array(
744 array( 'Help:WikiPageTest_testReplaceSection',
745 CONTENT_MODEL_WIKITEXT,
746 WikiPageTest::$sections,
747 "0",
748 "No more",
749 null,
750 trim( preg_replace( '/^Intro/sm', 'No more', WikiPageTest::$sections ) )
751 ),
752 array( 'Help:WikiPageTest_testReplaceSection',
753 CONTENT_MODEL_WIKITEXT,
754 WikiPageTest::$sections,
755 "",
756 "No more",
757 null,
758 "No more"
759 ),
760 array( 'Help:WikiPageTest_testReplaceSection',
761 CONTENT_MODEL_WIKITEXT,
762 WikiPageTest::$sections,
763 "2",
764 "== TEST ==\nmore fun",
765 null,
766 trim( preg_replace( '/^== test ==.*== foo ==/sm',
767 "== TEST ==\nmore fun\n\n== foo ==",
768 WikiPageTest::$sections ) )
769 ),
770 array( 'Help:WikiPageTest_testReplaceSection',
771 CONTENT_MODEL_WIKITEXT,
772 WikiPageTest::$sections,
773 "8",
774 "No more",
775 null,
776 trim( WikiPageTest::$sections )
777 ),
778 array( 'Help:WikiPageTest_testReplaceSection',
779 CONTENT_MODEL_WIKITEXT,
780 WikiPageTest::$sections,
781 "new",
782 "No more",
783 "New",
784 trim( WikiPageTest::$sections ) . "\n\n== New ==\n\nNo more"
785 ),
786 );
787 }
788
789 /**
790 * @dataProvider dataReplaceSection
791 * @covers WikiPage::replaceSection
792 */
793 public function testReplaceSection( $title, $model, $text, $section, $with,
794 $sectionTitle, $expected
795 ) {
796 $this->hideDeprecated( "WikiPage::replaceSection" );
797
798 $page = $this->createPage( $title, $text, $model );
799 $text = $page->replaceSection( $section, $with, $sectionTitle );
800 $text = trim( $text );
801
802 $this->assertEquals( $expected, $text );
803 }
804
805 /**
806 * @dataProvider dataReplaceSection
807 * @covers WikiPage::replaceSectionContent
808 */
809 public function testReplaceSectionContent( $title, $model, $text, $section,
810 $with, $sectionTitle, $expected
811 ) {
812 $page = $this->createPage( $title, $text, $model );
813
814 $content = ContentHandler::makeContent( $with, $page->getTitle(), $page->getContentModel() );
815 $c = $page->replaceSectionContent( $section, $content, $sectionTitle );
816
817 $this->assertEquals( $expected, is_null( $c ) ? null : trim( $c->getNativeData() ) );
818 }
819
820 /* @todo FIXME: fix this!
821 public function testGetUndoText() {
822 $this->checkHasDiff3();
823
824 $text = "one";
825 $page = $this->createPage( "WikiPageTest_testGetUndoText", $text );
826 $rev1 = $page->getRevision();
827
828 $text .= "\n\ntwo";
829 $page->doEditContent(
830 ContentHandler::makeContent( $text, $page->getTitle() ),
831 "adding section two"
832 );
833 $rev2 = $page->getRevision();
834
835 $text .= "\n\nthree";
836 $page->doEditContent(
837 ContentHandler::makeContent( $text, $page->getTitle() ),
838 "adding section three"
839 );
840 $rev3 = $page->getRevision();
841
842 $text .= "\n\nfour";
843 $page->doEditContent(
844 ContentHandler::makeContent( $text, $page->getTitle() ),
845 "adding section four"
846 );
847 $rev4 = $page->getRevision();
848
849 $text .= "\n\nfive";
850 $page->doEditContent(
851 ContentHandler::makeContent( $text, $page->getTitle() ),
852 "adding section five"
853 );
854 $rev5 = $page->getRevision();
855
856 $text .= "\n\nsix";
857 $page->doEditContent(
858 ContentHandler::makeContent( $text, $page->getTitle() ),
859 "adding section six"
860 );
861 $rev6 = $page->getRevision();
862
863 $undo6 = $page->getUndoText( $rev6 );
864 if ( $undo6 === false ) $this->fail( "getUndoText failed for rev6" );
865 $this->assertEquals( "one\n\ntwo\n\nthree\n\nfour\n\nfive", $undo6 );
866
867 $undo3 = $page->getUndoText( $rev4, $rev2 );
868 if ( $undo3 === false ) $this->fail( "getUndoText failed for rev4..rev2" );
869 $this->assertEquals( "one\n\ntwo\n\nfive", $undo3 );
870
871 $undo2 = $page->getUndoText( $rev2 );
872 if ( $undo2 === false ) $this->fail( "getUndoText failed for rev2" );
873 $this->assertEquals( "one\n\nfive", $undo2 );
874 }
875 */
876
877 /**
878 * @todo FIXME: this is a better rollback test than the one below, but it
879 * keeps failing in jenkins for some reason.
880 */
881 public function broken_testDoRollback() {
882 $admin = new User();
883 $admin->setName( "Admin" );
884
885 $text = "one";
886 $page = $this->newPage( "WikiPageTest_testDoRollback" );
887 $page->doEditContent( ContentHandler::makeContent( $text, $page->getTitle() ),
888 "section one", EDIT_NEW, false, $admin );
889
890 $user1 = new User();
891 $user1->setName( "127.0.1.11" );
892 $text .= "\n\ntwo";
893 $page = new WikiPage( $page->getTitle() );
894 $page->doEditContent( ContentHandler::makeContent( $text, $page->getTitle() ),
895 "adding section two", 0, false, $user1 );
896
897 $user2 = new User();
898 $user2->setName( "127.0.2.13" );
899 $text .= "\n\nthree";
900 $page = new WikiPage( $page->getTitle() );
901 $page->doEditContent( ContentHandler::makeContent( $text, $page->getTitle() ),
902 "adding section three", 0, false, $user2 );
903
904 # we are having issues with doRollback spuriously failing. Apparently
905 # the last revision somehow goes missing or not committed under some
906 # circumstances. So, make sure the last revision has the right user name.
907 $dbr = wfGetDB( DB_SLAVE );
908 $this->assertEquals( 3, Revision::countByPageId( $dbr, $page->getId() ) );
909
910 $page = new WikiPage( $page->getTitle() );
911 $rev3 = $page->getRevision();
912 $this->assertEquals( '127.0.2.13', $rev3->getUserText() );
913
914 $rev2 = $rev3->getPrevious();
915 $this->assertEquals( '127.0.1.11', $rev2->getUserText() );
916
917 $rev1 = $rev2->getPrevious();
918 $this->assertEquals( 'Admin', $rev1->getUserText() );
919
920 # now, try the actual rollback
921 $admin->addGroup( "sysop" ); #XXX: make the test user a sysop...
922 $token = $admin->getEditToken(
923 array( $page->getTitle()->getPrefixedText(), $user2->getName() ),
924 null
925 );
926 $errors = $page->doRollback(
927 $user2->getName(),
928 "testing revert",
929 $token,
930 false,
931 $details,
932 $admin
933 );
934
935 if ( $errors ) {
936 $this->fail( "Rollback failed:\n" . print_r( $errors, true )
937 . ";\n" . print_r( $details, true ) );
938 }
939
940 $page = new WikiPage( $page->getTitle() );
941 $this->assertEquals( $rev2->getSha1(), $page->getRevision()->getSha1(),
942 "rollback did not revert to the correct revision" );
943 $this->assertEquals( "one\n\ntwo", $page->getContent()->getNativeData() );
944 }
945
946 /**
947 * @todo FIXME: the above rollback test is better, but it keeps failing in jenkins for some reason.
948 * @covers WikiPage::doRollback
949 */
950 public function testDoRollback() {
951 $admin = new User();
952 $admin->setName( "Admin" );
953
954 $text = "one";
955 $page = $this->newPage( "WikiPageTest_testDoRollback" );
956 $page->doEditContent(
957 ContentHandler::makeContent( $text, $page->getTitle(), CONTENT_MODEL_WIKITEXT ),
958 "section one",
959 EDIT_NEW,
960 false,
961 $admin
962 );
963 $rev1 = $page->getRevision();
964
965 $user1 = new User();
966 $user1->setName( "127.0.1.11" );
967 $text .= "\n\ntwo";
968 $page = new WikiPage( $page->getTitle() );
969 $page->doEditContent(
970 ContentHandler::makeContent( $text, $page->getTitle(), CONTENT_MODEL_WIKITEXT ),
971 "adding section two",
972 0,
973 false,
974 $user1
975 );
976
977 # now, try the rollback
978 $admin->addGroup( "sysop" ); #XXX: make the test user a sysop...
979 $token = $admin->getEditToken(
980 array( $page->getTitle()->getPrefixedText(), $user1->getName() ),
981 null
982 );
983 $errors = $page->doRollback(
984 $user1->getName(),
985 "testing revert",
986 $token,
987 false,
988 $details,
989 $admin
990 );
991
992 if ( $errors ) {
993 $this->fail( "Rollback failed:\n" . print_r( $errors, true )
994 . ";\n" . print_r( $details, true ) );
995 }
996
997 $page = new WikiPage( $page->getTitle() );
998 $this->assertEquals( $rev1->getSha1(), $page->getRevision()->getSha1(),
999 "rollback did not revert to the correct revision" );
1000 $this->assertEquals( "one", $page->getContent()->getNativeData() );
1001 }
1002
1003 /**
1004 * @covers WikiPage::doRollback
1005 */
1006 public function testDoRollbackFailureSameContent() {
1007 $admin = new User();
1008 $admin->setName( "Admin" );
1009 $admin->addGroup( "sysop" ); #XXX: make the test user a sysop...
1010
1011 $text = "one";
1012 $page = $this->newPage( "WikiPageTest_testDoRollback" );
1013 $page->doEditContent(
1014 ContentHandler::makeContent( $text, $page->getTitle(), CONTENT_MODEL_WIKITEXT ),
1015 "section one",
1016 EDIT_NEW,
1017 false,
1018 $admin
1019 );
1020 $rev1 = $page->getRevision();
1021
1022 $user1 = new User();
1023 $user1->setName( "127.0.1.11" );
1024 $user1->addGroup( "sysop" ); #XXX: make the test user a sysop...
1025 $text .= "\n\ntwo";
1026 $page = new WikiPage( $page->getTitle() );
1027 $page->doEditContent(
1028 ContentHandler::makeContent( $text, $page->getTitle(), CONTENT_MODEL_WIKITEXT ),
1029 "adding section two",
1030 0,
1031 false,
1032 $user1
1033 );
1034
1035 # now, do a the rollback from the same user was doing the edit before
1036 $resultDetails = array();
1037 $token = $user1->getEditToken(
1038 array( $page->getTitle()->getPrefixedText(), $user1->getName() ),
1039 null
1040 );
1041 $errors = $page->doRollback(
1042 $user1->getName(),
1043 "testing revert same user",
1044 $token,
1045 false,
1046 $resultDetails,
1047 $admin
1048 );
1049
1050 $this->assertEquals( array(), $errors, "Rollback failed same user" );
1051
1052 # now, try the rollback
1053 $resultDetails = array();
1054 $token = $admin->getEditToken(
1055 array( $page->getTitle()->getPrefixedText(), $user1->getName() ),
1056 null
1057 );
1058 $errors = $page->doRollback(
1059 $user1->getName(),
1060 "testing revert",
1061 $token,
1062 false,
1063 $resultDetails,
1064 $admin
1065 );
1066
1067 $this->assertEquals( array( array( 'alreadyrolled', 'WikiPageTest testDoRollback',
1068 '127.0.1.11', 'Admin' ) ), $errors, "Rollback not failed" );
1069
1070 $page = new WikiPage( $page->getTitle() );
1071 $this->assertEquals( $rev1->getSha1(), $page->getRevision()->getSha1(),
1072 "rollback did not revert to the correct revision" );
1073 $this->assertEquals( "one", $page->getContent()->getNativeData() );
1074 }
1075
1076 public static function provideGetAutosummary() {
1077 return array(
1078 array(
1079 'Hello there, world!',
1080 '#REDIRECT [[Foo]]',
1081 0,
1082 '/^Redirected page .*Foo/'
1083 ),
1084
1085 array(
1086 null,
1087 'Hello world!',
1088 EDIT_NEW,
1089 '/^Created page .*Hello/'
1090 ),
1091
1092 array(
1093 'Hello there, world!',
1094 '',
1095 0,
1096 '/^Blanked/'
1097 ),
1098
1099 array(
1100 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy
1101 eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam
1102 voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet
1103 clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.',
1104 'Hello world!',
1105 0,
1106 '/^Replaced .*Hello/'
1107 ),
1108
1109 array(
1110 'foo',
1111 'bar',
1112 0,
1113 '/^$/'
1114 ),
1115 );
1116 }
1117
1118 /**
1119 * @dataProvider provideGetAutoSummary
1120 * @covers WikiPage::getAutosummary
1121 */
1122 public function testGetAutosummary( $old, $new, $flags, $expected ) {
1123 $this->hideDeprecated( "WikiPage::getAutosummary" );
1124
1125 $page = $this->newPage( "WikiPageTest_testGetAutosummary" );
1126
1127 $summary = $page->getAutosummary( $old, $new, $flags );
1128
1129 $this->assertTrue( (bool)preg_match( $expected, $summary ),
1130 "Autosummary didn't match expected pattern $expected: $summary" );
1131 }
1132
1133 public static function provideGetAutoDeleteReason() {
1134 return array(
1135 array(
1136 array(),
1137 false,
1138 false
1139 ),
1140
1141 array(
1142 array(
1143 array( "first edit", null ),
1144 ),
1145 "/first edit.*only contributor/",
1146 false
1147 ),
1148
1149 array(
1150 array(
1151 array( "first edit", null ),
1152 array( "second edit", null ),
1153 ),
1154 "/second edit.*only contributor/",
1155 true
1156 ),
1157
1158 array(
1159 array(
1160 array( "first edit", "127.0.2.22" ),
1161 array( "second edit", "127.0.3.33" ),
1162 ),
1163 "/second edit/",
1164 true
1165 ),
1166
1167 array(
1168 array(
1169 array(
1170 "first edit: "
1171 . "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam "
1172 . " nonumy eirmod tempor invidunt ut labore et dolore magna "
1173 . "aliquyam erat, sed diam voluptua. At vero eos et accusam "
1174 . "et justo duo dolores et ea rebum. Stet clita kasd gubergren, "
1175 . "no sea takimata sanctus est Lorem ipsum dolor sit amet.'",
1176 null
1177 ),
1178 ),
1179 '/first edit:.*\.\.\."/',
1180 false
1181 ),
1182
1183 array(
1184 array(
1185 array( "first edit", "127.0.2.22" ),
1186 array( "", "127.0.3.33" ),
1187 ),
1188 "/before blanking.*first edit/",
1189 true
1190 ),
1191
1192 );
1193 }
1194
1195 /**
1196 * @dataProvider provideGetAutoDeleteReason
1197 * @covers WikiPage::getAutoDeleteReason
1198 */
1199 public function testGetAutoDeleteReason( $edits, $expectedResult, $expectedHistory ) {
1200 global $wgUser;
1201
1202 //NOTE: assume Help namespace to contain wikitext
1203 $page = $this->newPage( "Help:WikiPageTest_testGetAutoDeleteReason" );
1204
1205 $c = 1;
1206
1207 foreach ( $edits as $edit ) {
1208 $user = new User();
1209
1210 if ( !empty( $edit[1] ) ) {
1211 $user->setName( $edit[1] );
1212 } else {
1213 $user = $wgUser;
1214 }
1215
1216 $content = ContentHandler::makeContent( $edit[0], $page->getTitle(), $page->getContentModel() );
1217
1218 $page->doEditContent( $content, "test edit $c", $c < 2 ? EDIT_NEW : 0, false, $user );
1219
1220 $c += 1;
1221 }
1222
1223 $reason = $page->getAutoDeleteReason( $hasHistory );
1224
1225 if ( is_bool( $expectedResult ) || is_null( $expectedResult ) ) {
1226 $this->assertEquals( $expectedResult, $reason );
1227 } else {
1228 $this->assertTrue( (bool)preg_match( $expectedResult, $reason ),
1229 "Autosummary didn't match expected pattern $expectedResult: $reason" );
1230 }
1231
1232 $this->assertEquals( $expectedHistory, $hasHistory,
1233 "expected \$hasHistory to be " . var_export( $expectedHistory, true ) );
1234
1235 $page->doDeleteArticle( "done" );
1236 }
1237
1238 public static function providePreSaveTransform() {
1239 return array(
1240 array( 'hello this is ~~~',
1241 "hello this is [[Special:Contributions/127.0.0.1|127.0.0.1]]",
1242 ),
1243 array( 'hello \'\'this\'\' is <nowiki>~~~</nowiki>',
1244 'hello \'\'this\'\' is <nowiki>~~~</nowiki>',
1245 ),
1246 );
1247 }
1248
1249 /**
1250 * @dataProvider providePreSaveTransform
1251 * @covers WikiPage::preSaveTransform
1252 */
1253 public function testPreSaveTransform( $text, $expected ) {
1254 $this->hideDeprecated( 'WikiPage::preSaveTransform' );
1255 $user = new User();
1256 $user->setName( "127.0.0.1" );
1257
1258 //NOTE: assume Help namespace to contain wikitext
1259 $page = $this->newPage( "Help:WikiPageTest_testPreloadTransform" );
1260 $text = $page->preSaveTransform( $text, $user );
1261
1262 $this->assertEquals( $expected, $text );
1263 }
1264
1265 /**
1266 * @covers WikiPage::factory
1267 */
1268 public function testWikiPageFactory() {
1269 $title = Title::makeTitle( NS_FILE, 'Someimage.png' );
1270 $page = WikiPage::factory( $title );
1271 $this->assertEquals( 'WikiFilePage', get_class( $page ) );
1272
1273 $title = Title::makeTitle( NS_CATEGORY, 'SomeCategory' );
1274 $page = WikiPage::factory( $title );
1275 $this->assertEquals( 'WikiCategoryPage', get_class( $page ) );
1276
1277 $title = Title::makeTitle( NS_MAIN, 'SomePage' );
1278 $page = WikiPage::factory( $title );
1279 $this->assertEquals( 'WikiPage', get_class( $page ) );
1280 }
1281 }