API: Fixes for AuthManager
[mediawiki.git] / tests / phpunit / includes / page / WikiPageTest.php
blob10e0f5962a7afc929327ec73f1d0aeb39db48b92
1 <?php
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 {
11 protected $pages_to_delete;
13 function __construct( $name = null, array $data = [], $dataName = '' ) {
14 parent::__construct( $name, $data, $dataName );
16 $this->tablesUsed = array_merge(
17 $this->tablesUsed,
18 [ 'page',
19 'revision',
20 'text',
22 'recentchanges',
23 'logging',
25 'page_props',
26 'pagelinks',
27 'categorylinks',
28 'langlinks',
29 'externallinks',
30 'imagelinks',
31 'templatelinks',
32 'iwlinks' ] );
35 protected function setUp() {
36 parent::setUp();
37 $this->pages_to_delete = [];
39 LinkCache::singleton()->clear(); # avoid cached redirect status, etc
42 protected function tearDown() {
43 foreach ( $this->pages_to_delete as $p ) {
44 /* @var $p WikiPage */
46 try {
47 if ( $p->exists() ) {
48 $p->doDeleteArticle( "testing done." );
50 } catch ( MWException $ex ) {
51 // fail silently
54 parent::tearDown();
57 /**
58 * @param Title|string $title
59 * @param string|null $model
60 * @return WikiPage
62 protected function newPage( $title, $model = null ) {
63 if ( is_string( $title ) ) {
64 $ns = $this->getDefaultWikitextNS();
65 $title = Title::newFromText( $title, $ns );
68 $p = new WikiPage( $title );
70 $this->pages_to_delete[] = $p;
72 return $p;
75 /**
76 * @param string|Title|WikiPage $page
77 * @param string $text
78 * @param int $model
80 * @return WikiPage
82 protected function createPage( $page, $text, $model = null ) {
83 if ( is_string( $page ) || $page instanceof Title ) {
84 $page = $this->newPage( $page, $model );
87 $content = ContentHandler::makeContent( $text, $page->getTitle(), $model );
88 $page->doEditContent( $content, "testing", EDIT_NEW );
90 return $page;
93 /**
94 * @covers WikiPage::doEditContent
96 public function testDoEditContent() {
97 $page = $this->newPage( "WikiPageTest_testDoEditContent" );
98 $title = $page->getTitle();
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
107 $page->doEditContent( $content, "[[testing]] 1" );
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" );
114 $id = $page->getId();
116 # ------------------------
117 $dbr = wfGetDB( DB_SLAVE );
118 $res = $dbr->select( 'pagelinks', '*', [ 'pl_from' => $id ] );
119 $n = $res->numRows();
120 $res->free();
122 $this->assertEquals( 1, $n, 'pagelinks should contain one link from the page' );
124 # ------------------------
125 $page = new WikiPage( $title );
127 $retrieved = $page->getContent();
128 $this->assertTrue( $content->equals( $retrieved ), 'retrieved content doesn\'t equal original' );
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
138 $page->doEditContent( $content, "testing 2" );
140 # ------------------------
141 $page = new WikiPage( $title );
143 $retrieved = $page->getContent();
144 $this->assertTrue( $content->equals( $retrieved ), 'retrieved content doesn\'t equal original' );
146 # ------------------------
147 $dbr = wfGetDB( DB_SLAVE );
148 $res = $dbr->select( 'pagelinks', '*', [ 'pl_from' => $id ] );
149 $n = $res->numRows();
150 $res->free();
152 $this->assertEquals( 2, $n, 'pagelinks should contain two links from the page' );
156 * @covers WikiPage::doEdit
158 public function testDoEdit() {
159 $this->hideDeprecated( "WikiPage::doEdit" );
160 $this->hideDeprecated( "WikiPage::getText" );
161 $this->hideDeprecated( "Revision::getText" );
163 // NOTE: assume help namespace will default to wikitext
164 $title = Title::newFromText( "Help:WikiPageTest_testDoEdit" );
166 $page = $this->newPage( $title );
168 $text = "[[Lorem ipsum]] dolor sit amet, consetetur sadipscing elitr, sed diam "
169 . " nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat.";
171 $page->doEdit( $text, "[[testing]] 1" );
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" );
178 $id = $page->getId();
180 # ------------------------
181 $dbr = wfGetDB( DB_SLAVE );
182 $res = $dbr->select( 'pagelinks', '*', [ 'pl_from' => $id ] );
183 $n = $res->numRows();
184 $res->free();
186 $this->assertEquals( 1, $n, 'pagelinks should contain one link from the page' );
188 # ------------------------
189 $page = new WikiPage( $title );
191 $retrieved = $page->getText();
192 $this->assertEquals( $text, $retrieved, 'retrieved text doesn\'t equal original' );
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.";
198 $page->doEdit( $text, "testing 2" );
200 # ------------------------
201 $page = new WikiPage( $title );
203 $retrieved = $page->getText();
204 $this->assertEquals( $text, $retrieved, 'retrieved text doesn\'t equal original' );
206 # ------------------------
207 $dbr = wfGetDB( DB_SLAVE );
208 $res = $dbr->select( 'pagelinks', '*', [ 'pl_from' => $id ] );
209 $n = $res->numRows();
210 $res->free();
212 $this->assertEquals( 2, $n, 'pagelinks should contain two links from the page' );
216 * @covers WikiPage::doQuickEditContent
218 public function testDoQuickEditContent() {
219 global $wgUser;
221 $page = $this->createPage(
222 "WikiPageTest_testDoQuickEditContent",
223 "original text",
224 CONTENT_MODEL_WIKITEXT
227 $content = ContentHandler::makeContent(
228 "quick text",
229 $page->getTitle(),
230 CONTENT_MODEL_WIKITEXT
232 $page->doQuickEditContent( $content, $wgUser, "testing q" );
234 # ---------------------
235 $page = new WikiPage( $page->getTitle() );
236 $this->assertTrue( $content->equals( $page->getContent() ) );
240 * @covers WikiPage::doDeleteArticle
242 public function testDoDeleteArticle() {
243 $page = $this->createPage(
244 "WikiPageTest_testDoDeleteArticle",
245 "[[original text]] foo",
246 CONTENT_MODEL_WIKITEXT
248 $id = $page->getId();
250 $page->doDeleteArticle( "testing deletion" );
252 $this->assertFalse(
253 $page->getTitle()->getArticleID() > 0,
254 "Title object should now have page id 0"
256 $this->assertFalse( $page->getId() > 0, "WikiPage should now have page id 0" );
257 $this->assertFalse(
258 $page->exists(),
259 "WikiPage::exists should return false after page was deleted"
261 $this->assertNull(
262 $page->getContent(),
263 "WikiPage::getContent should return null after page was deleted"
265 $this->assertFalse(
266 $page->getText(),
267 "WikiPage::getText should return false after page was deleted"
270 $t = Title::newFromText( $page->getTitle()->getPrefixedText() );
271 $this->assertFalse(
272 $t->exists(),
273 "Title::exists should return false after page was deleted"
276 // Run the job queue
277 JobQueueGroup::destroySingletons();
278 $jobs = new RunJobs;
279 $jobs->loadParamsAndArgs( null, [ 'quiet' => true ], null );
280 $jobs->execute();
282 # ------------------------
283 $dbr = wfGetDB( DB_SLAVE );
284 $res = $dbr->select( 'pagelinks', '*', [ 'pl_from' => $id ] );
285 $n = $res->numRows();
286 $res->free();
288 $this->assertEquals( 0, $n, 'pagelinks should contain no more links from the page' );
292 * @covers WikiPage::doDeleteUpdates
294 public function testDoDeleteUpdates() {
295 $page = $this->createPage(
296 "WikiPageTest_testDoDeleteArticle",
297 "[[original text]] foo",
298 CONTENT_MODEL_WIKITEXT
300 $id = $page->getId();
302 // Similar to MovePage logic
303 wfGetDB( DB_MASTER )->delete( 'page', [ 'page_id' => $id ], __METHOD__ );
304 $page->doDeleteUpdates( $id );
306 // Run the job queue
307 JobQueueGroup::destroySingletons();
308 $jobs = new RunJobs;
309 $jobs->loadParamsAndArgs( null, [ 'quiet' => true ], null );
310 $jobs->execute();
312 # ------------------------
313 $dbr = wfGetDB( DB_SLAVE );
314 $res = $dbr->select( 'pagelinks', '*', [ 'pl_from' => $id ] );
315 $n = $res->numRows();
316 $res->free();
318 $this->assertEquals( 0, $n, 'pagelinks should contain no more links from the page' );
322 * @covers WikiPage::getRevision
324 public function testGetRevision() {
325 $page = $this->newPage( "WikiPageTest_testGetRevision" );
327 $rev = $page->getRevision();
328 $this->assertNull( $rev );
330 # -----------------
331 $this->createPage( $page, "some text", CONTENT_MODEL_WIKITEXT );
333 $rev = $page->getRevision();
335 $this->assertEquals( $page->getLatest(), $rev->getId() );
336 $this->assertEquals( "some text", $rev->getContent()->getNativeData() );
340 * @covers WikiPage::getContent
342 public function testGetContent() {
343 $page = $this->newPage( "WikiPageTest_testGetContent" );
345 $content = $page->getContent();
346 $this->assertNull( $content );
348 # -----------------
349 $this->createPage( $page, "some text", CONTENT_MODEL_WIKITEXT );
351 $content = $page->getContent();
352 $this->assertEquals( "some text", $content->getNativeData() );
356 * @covers WikiPage::getText
358 public function testGetText() {
359 $this->hideDeprecated( "WikiPage::getText" );
361 $page = $this->newPage( "WikiPageTest_testGetText" );
363 $text = $page->getText();
364 $this->assertFalse( $text );
366 # -----------------
367 $this->createPage( $page, "some text", CONTENT_MODEL_WIKITEXT );
369 $text = $page->getText();
370 $this->assertEquals( "some text", $text );
374 * @covers WikiPage::getContentModel
376 public function testGetContentModel() {
377 global $wgContentHandlerUseDB;
379 if ( !$wgContentHandlerUseDB ) {
380 $this->markTestSkipped( '$wgContentHandlerUseDB is disabled' );
383 $page = $this->createPage(
384 "WikiPageTest_testGetContentModel",
385 "some text",
386 CONTENT_MODEL_JAVASCRIPT
389 $page = new WikiPage( $page->getTitle() );
390 $this->assertEquals( CONTENT_MODEL_JAVASCRIPT, $page->getContentModel() );
394 * @covers WikiPage::getContentHandler
396 public function testGetContentHandler() {
397 global $wgContentHandlerUseDB;
399 if ( !$wgContentHandlerUseDB ) {
400 $this->markTestSkipped( '$wgContentHandlerUseDB is disabled' );
403 $page = $this->createPage(
404 "WikiPageTest_testGetContentHandler",
405 "some text",
406 CONTENT_MODEL_JAVASCRIPT
409 $page = new WikiPage( $page->getTitle() );
410 $this->assertEquals( 'JavaScriptContentHandler', get_class( $page->getContentHandler() ) );
414 * @covers WikiPage::exists
416 public function testExists() {
417 $page = $this->newPage( "WikiPageTest_testExists" );
418 $this->assertFalse( $page->exists() );
420 # -----------------
421 $this->createPage( $page, "some text", CONTENT_MODEL_WIKITEXT );
422 $this->assertTrue( $page->exists() );
424 $page = new WikiPage( $page->getTitle() );
425 $this->assertTrue( $page->exists() );
427 # -----------------
428 $page->doDeleteArticle( "done testing" );
429 $this->assertFalse( $page->exists() );
431 $page = new WikiPage( $page->getTitle() );
432 $this->assertFalse( $page->exists() );
435 public static function provideHasViewableContent() {
436 return [
437 [ 'WikiPageTest_testHasViewableContent', false, true ],
438 [ 'Special:WikiPageTest_testHasViewableContent', false ],
439 [ 'MediaWiki:WikiPageTest_testHasViewableContent', false ],
440 [ 'Special:Userlogin', true ],
441 [ 'MediaWiki:help', true ],
446 * @dataProvider provideHasViewableContent
447 * @covers WikiPage::hasViewableContent
449 public function testHasViewableContent( $title, $viewable, $create = false ) {
450 $page = $this->newPage( $title );
451 $this->assertEquals( $viewable, $page->hasViewableContent() );
453 if ( $create ) {
454 $this->createPage( $page, "some text", CONTENT_MODEL_WIKITEXT );
455 $this->assertTrue( $page->hasViewableContent() );
457 $page = new WikiPage( $page->getTitle() );
458 $this->assertTrue( $page->hasViewableContent() );
462 public static function provideGetRedirectTarget() {
463 return [
464 [ 'WikiPageTest_testGetRedirectTarget_1', CONTENT_MODEL_WIKITEXT, "hello world", null ],
466 'WikiPageTest_testGetRedirectTarget_2',
467 CONTENT_MODEL_WIKITEXT,
468 "#REDIRECT [[hello world]]",
469 "Hello world"
475 * @dataProvider provideGetRedirectTarget
476 * @covers WikiPage::getRedirectTarget
478 public function testGetRedirectTarget( $title, $model, $text, $target ) {
479 $this->setMwGlobals( [
480 'wgCapitalLinks' => true,
481 ] );
483 $page = $this->createPage( $title, $text, $model );
485 # sanity check, because this test seems to fail for no reason for some people.
486 $c = $page->getContent();
487 $this->assertEquals( 'WikitextContent', get_class( $c ) );
489 # now, test the actual redirect
490 $t = $page->getRedirectTarget();
491 $this->assertEquals( $target, is_null( $t ) ? null : $t->getPrefixedText() );
495 * @dataProvider provideGetRedirectTarget
496 * @covers WikiPage::isRedirect
498 public function testIsRedirect( $title, $model, $text, $target ) {
499 $page = $this->createPage( $title, $text, $model );
500 $this->assertEquals( !is_null( $target ), $page->isRedirect() );
503 public static function provideIsCountable() {
504 return [
506 // any
507 [ 'WikiPageTest_testIsCountable',
508 CONTENT_MODEL_WIKITEXT,
510 'any',
511 true
513 [ 'WikiPageTest_testIsCountable',
514 CONTENT_MODEL_WIKITEXT,
515 'Foo',
516 'any',
517 true
520 // comma
521 [ 'WikiPageTest_testIsCountable',
522 CONTENT_MODEL_WIKITEXT,
523 'Foo',
524 'comma',
525 false
527 [ 'WikiPageTest_testIsCountable',
528 CONTENT_MODEL_WIKITEXT,
529 'Foo, bar',
530 'comma',
531 true
534 // link
535 [ 'WikiPageTest_testIsCountable',
536 CONTENT_MODEL_WIKITEXT,
537 'Foo',
538 'link',
539 false
541 [ 'WikiPageTest_testIsCountable',
542 CONTENT_MODEL_WIKITEXT,
543 'Foo [[bar]]',
544 'link',
545 true
548 // redirects
549 [ 'WikiPageTest_testIsCountable',
550 CONTENT_MODEL_WIKITEXT,
551 '#REDIRECT [[bar]]',
552 'any',
553 false
555 [ 'WikiPageTest_testIsCountable',
556 CONTENT_MODEL_WIKITEXT,
557 '#REDIRECT [[bar]]',
558 'comma',
559 false
561 [ 'WikiPageTest_testIsCountable',
562 CONTENT_MODEL_WIKITEXT,
563 '#REDIRECT [[bar]]',
564 'link',
565 false
568 // not a content namespace
569 [ 'Talk:WikiPageTest_testIsCountable',
570 CONTENT_MODEL_WIKITEXT,
571 'Foo',
572 'any',
573 false
575 [ 'Talk:WikiPageTest_testIsCountable',
576 CONTENT_MODEL_WIKITEXT,
577 'Foo, bar',
578 'comma',
579 false
581 [ 'Talk:WikiPageTest_testIsCountable',
582 CONTENT_MODEL_WIKITEXT,
583 'Foo [[bar]]',
584 'link',
585 false
588 // not a content namespace, different model
589 [ 'MediaWiki:WikiPageTest_testIsCountable.js',
590 null,
591 'Foo',
592 'any',
593 false
595 [ 'MediaWiki:WikiPageTest_testIsCountable.js',
596 null,
597 'Foo, bar',
598 'comma',
599 false
601 [ 'MediaWiki:WikiPageTest_testIsCountable.js',
602 null,
603 'Foo [[bar]]',
604 'link',
605 false
611 * @dataProvider provideIsCountable
612 * @covers WikiPage::isCountable
614 public function testIsCountable( $title, $model, $text, $mode, $expected ) {
615 global $wgContentHandlerUseDB;
617 $this->setMwGlobals( 'wgArticleCountMethod', $mode );
619 $title = Title::newFromText( $title );
621 if ( !$wgContentHandlerUseDB
622 && $model
623 && ContentHandler::getDefaultModelFor( $title ) != $model
625 $this->markTestSkipped( "Can not use non-default content model $model for "
626 . $title->getPrefixedDBkey() . " with \$wgContentHandlerUseDB disabled." );
629 $page = $this->createPage( $title, $text, $model );
631 $editInfo = $page->prepareContentForEdit( $page->getContent() );
633 $v = $page->isCountable();
634 $w = $page->isCountable( $editInfo );
636 $this->assertEquals(
637 $expected,
639 "isCountable( null ) returned unexpected value " . var_export( $v, true )
640 . " instead of " . var_export( $expected, true )
641 . " in mode `$mode` for text \"$text\""
644 $this->assertEquals(
645 $expected,
647 "isCountable( \$editInfo ) returned unexpected value " . var_export( $v, true )
648 . " instead of " . var_export( $expected, true )
649 . " in mode `$mode` for text \"$text\""
653 public static function provideGetParserOutput() {
654 return [
655 [ CONTENT_MODEL_WIKITEXT, "hello ''world''\n", "<p>hello <i>world</i></p>" ],
656 // @todo more...?
661 * @dataProvider provideGetParserOutput
662 * @covers WikiPage::getParserOutput
664 public function testGetParserOutput( $model, $text, $expectedHtml ) {
665 $page = $this->createPage( 'WikiPageTest_testGetParserOutput', $text, $model );
667 $opt = $page->makeParserOptions( 'canonical' );
668 $po = $page->getParserOutput( $opt );
669 $text = $po->getText();
671 $text = trim( preg_replace( '/<!--.*?-->/sm', '', $text ) ); # strip injected comments
672 $text = preg_replace( '!\s*(</p>)!sm', '\1', $text ); # don't let tidy confuse us
674 $this->assertEquals( $expectedHtml, $text );
676 return $po;
680 * @covers WikiPage::getParserOutput
682 public function testGetParserOutput_nonexisting() {
683 static $count = 0;
684 $count++;
686 $page = new WikiPage( new Title( "WikiPageTest_testGetParserOutput_nonexisting_$count" ) );
688 $opt = new ParserOptions();
689 $po = $page->getParserOutput( $opt );
691 $this->assertFalse( $po, "getParserOutput() shall return false for non-existing pages." );
695 * @covers WikiPage::getParserOutput
697 public function testGetParserOutput_badrev() {
698 $page = $this->createPage( 'WikiPageTest_testGetParserOutput', "dummy", CONTENT_MODEL_WIKITEXT );
700 $opt = new ParserOptions();
701 $po = $page->getParserOutput( $opt, $page->getLatest() + 1234 );
703 // @todo would be neat to also test deleted revision
705 $this->assertFalse( $po, "getParserOutput() shall return false for non-existing revisions." );
708 public static $sections =
710 "Intro
712 == stuff ==
713 hello world
715 == test ==
716 just a test
718 == foo ==
719 more stuff
722 public function dataReplaceSection() {
723 // NOTE: assume the Help namespace to contain wikitext
724 return [
725 [ 'Help:WikiPageTest_testReplaceSection',
726 CONTENT_MODEL_WIKITEXT,
727 WikiPageTest::$sections,
728 "0",
729 "No more",
730 null,
731 trim( preg_replace( '/^Intro/sm', 'No more', WikiPageTest::$sections ) )
733 [ 'Help:WikiPageTest_testReplaceSection',
734 CONTENT_MODEL_WIKITEXT,
735 WikiPageTest::$sections,
737 "No more",
738 null,
739 "No more"
741 [ 'Help:WikiPageTest_testReplaceSection',
742 CONTENT_MODEL_WIKITEXT,
743 WikiPageTest::$sections,
744 "2",
745 "== TEST ==\nmore fun",
746 null,
747 trim( preg_replace( '/^== test ==.*== foo ==/sm',
748 "== TEST ==\nmore fun\n\n== foo ==",
749 WikiPageTest::$sections ) )
751 [ 'Help:WikiPageTest_testReplaceSection',
752 CONTENT_MODEL_WIKITEXT,
753 WikiPageTest::$sections,
754 "8",
755 "No more",
756 null,
757 trim( WikiPageTest::$sections )
759 [ 'Help:WikiPageTest_testReplaceSection',
760 CONTENT_MODEL_WIKITEXT,
761 WikiPageTest::$sections,
762 "new",
763 "No more",
764 "New",
765 trim( WikiPageTest::$sections ) . "\n\n== New ==\n\nNo more"
771 * @dataProvider dataReplaceSection
772 * @covers WikiPage::replaceSectionContent
774 public function testReplaceSectionContent( $title, $model, $text, $section,
775 $with, $sectionTitle, $expected
777 $page = $this->createPage( $title, $text, $model );
779 $content = ContentHandler::makeContent( $with, $page->getTitle(), $page->getContentModel() );
780 $c = $page->replaceSectionContent( $section, $content, $sectionTitle );
782 $this->assertEquals( $expected, is_null( $c ) ? null : trim( $c->getNativeData() ) );
786 * @dataProvider dataReplaceSection
787 * @covers WikiPage::replaceSectionAtRev
789 public function testReplaceSectionAtRev( $title, $model, $text, $section,
790 $with, $sectionTitle, $expected
792 $page = $this->createPage( $title, $text, $model );
793 $baseRevId = $page->getLatest();
795 $content = ContentHandler::makeContent( $with, $page->getTitle(), $page->getContentModel() );
796 $c = $page->replaceSectionAtRev( $section, $content, $sectionTitle, $baseRevId );
798 $this->assertEquals( $expected, is_null( $c ) ? null : trim( $c->getNativeData() ) );
801 /* @todo FIXME: fix this!
802 public function testGetUndoText() {
803 $this->markTestSkippedIfNoDiff3();
805 $text = "one";
806 $page = $this->createPage( "WikiPageTest_testGetUndoText", $text );
807 $rev1 = $page->getRevision();
809 $text .= "\n\ntwo";
810 $page->doEditContent(
811 ContentHandler::makeContent( $text, $page->getTitle() ),
812 "adding section two"
814 $rev2 = $page->getRevision();
816 $text .= "\n\nthree";
817 $page->doEditContent(
818 ContentHandler::makeContent( $text, $page->getTitle() ),
819 "adding section three"
821 $rev3 = $page->getRevision();
823 $text .= "\n\nfour";
824 $page->doEditContent(
825 ContentHandler::makeContent( $text, $page->getTitle() ),
826 "adding section four"
828 $rev4 = $page->getRevision();
830 $text .= "\n\nfive";
831 $page->doEditContent(
832 ContentHandler::makeContent( $text, $page->getTitle() ),
833 "adding section five"
835 $rev5 = $page->getRevision();
837 $text .= "\n\nsix";
838 $page->doEditContent(
839 ContentHandler::makeContent( $text, $page->getTitle() ),
840 "adding section six"
842 $rev6 = $page->getRevision();
844 $undo6 = $page->getUndoText( $rev6 );
845 if ( $undo6 === false ) $this->fail( "getUndoText failed for rev6" );
846 $this->assertEquals( "one\n\ntwo\n\nthree\n\nfour\n\nfive", $undo6 );
848 $undo3 = $page->getUndoText( $rev4, $rev2 );
849 if ( $undo3 === false ) $this->fail( "getUndoText failed for rev4..rev2" );
850 $this->assertEquals( "one\n\ntwo\n\nfive", $undo3 );
852 $undo2 = $page->getUndoText( $rev2 );
853 if ( $undo2 === false ) $this->fail( "getUndoText failed for rev2" );
854 $this->assertEquals( "one\n\nfive", $undo2 );
859 * @todo FIXME: this is a better rollback test than the one below, but it
860 * keeps failing in jenkins for some reason.
862 public function broken_testDoRollback() {
863 $admin = new User();
864 $admin->setName( "Admin" );
866 $text = "one";
867 $page = $this->newPage( "WikiPageTest_testDoRollback" );
868 $page->doEditContent( ContentHandler::makeContent( $text, $page->getTitle() ),
869 "section one", EDIT_NEW, false, $admin );
871 $user1 = new User();
872 $user1->setName( "127.0.1.11" );
873 $text .= "\n\ntwo";
874 $page = new WikiPage( $page->getTitle() );
875 $page->doEditContent( ContentHandler::makeContent( $text, $page->getTitle() ),
876 "adding section two", 0, false, $user1 );
878 $user2 = new User();
879 $user2->setName( "127.0.2.13" );
880 $text .= "\n\nthree";
881 $page = new WikiPage( $page->getTitle() );
882 $page->doEditContent( ContentHandler::makeContent( $text, $page->getTitle() ),
883 "adding section three", 0, false, $user2 );
885 # we are having issues with doRollback spuriously failing. Apparently
886 # the last revision somehow goes missing or not committed under some
887 # circumstances. So, make sure the last revision has the right user name.
888 $dbr = wfGetDB( DB_SLAVE );
889 $this->assertEquals( 3, Revision::countByPageId( $dbr, $page->getId() ) );
891 $page = new WikiPage( $page->getTitle() );
892 $rev3 = $page->getRevision();
893 $this->assertEquals( '127.0.2.13', $rev3->getUserText() );
895 $rev2 = $rev3->getPrevious();
896 $this->assertEquals( '127.0.1.11', $rev2->getUserText() );
898 $rev1 = $rev2->getPrevious();
899 $this->assertEquals( 'Admin', $rev1->getUserText() );
901 # now, try the actual rollback
902 $admin->addGroup( "sysop" ); # XXX: make the test user a sysop...
903 $token = $admin->getEditToken(
904 [ $page->getTitle()->getPrefixedText(), $user2->getName() ],
905 null
907 $errors = $page->doRollback(
908 $user2->getName(),
909 "testing revert",
910 $token,
911 false,
912 $details,
913 $admin
916 if ( $errors ) {
917 $this->fail( "Rollback failed:\n" . print_r( $errors, true )
918 . ";\n" . print_r( $details, true ) );
921 $page = new WikiPage( $page->getTitle() );
922 $this->assertEquals( $rev2->getSha1(), $page->getRevision()->getSha1(),
923 "rollback did not revert to the correct revision" );
924 $this->assertEquals( "one\n\ntwo", $page->getContent()->getNativeData() );
928 * @todo FIXME: the above rollback test is better, but it keeps failing in jenkins for some reason.
929 * @covers WikiPage::doRollback
931 public function testDoRollback() {
932 $admin = new User();
933 $admin->setName( "Admin" );
935 $text = "one";
936 $page = $this->newPage( "WikiPageTest_testDoRollback" );
937 $page->doEditContent(
938 ContentHandler::makeContent( $text, $page->getTitle(), CONTENT_MODEL_WIKITEXT ),
939 "section one",
940 EDIT_NEW,
941 false,
942 $admin
944 $rev1 = $page->getRevision();
946 $user1 = new User();
947 $user1->setName( "127.0.1.11" );
948 $text .= "\n\ntwo";
949 $page = new WikiPage( $page->getTitle() );
950 $page->doEditContent(
951 ContentHandler::makeContent( $text, $page->getTitle(), CONTENT_MODEL_WIKITEXT ),
952 "adding section two",
954 false,
955 $user1
958 # now, try the rollback
959 $admin->addGroup( "sysop" ); # XXX: make the test user a sysop...
960 $token = $admin->getEditToken(
961 [ $page->getTitle()->getPrefixedText(), $user1->getName() ],
962 null
964 $errors = $page->doRollback(
965 $user1->getName(),
966 "testing revert",
967 $token,
968 false,
969 $details,
970 $admin
973 if ( $errors ) {
974 $this->fail( "Rollback failed:\n" . print_r( $errors, true )
975 . ";\n" . print_r( $details, true ) );
978 $page = new WikiPage( $page->getTitle() );
979 $this->assertEquals( $rev1->getSha1(), $page->getRevision()->getSha1(),
980 "rollback did not revert to the correct revision" );
981 $this->assertEquals( "one", $page->getContent()->getNativeData() );
985 * @covers WikiPage::doRollback
987 public function testDoRollbackFailureSameContent() {
988 $admin = new User();
989 $admin->setName( "Admin" );
990 $admin->addGroup( "sysop" ); # XXX: make the test user a sysop...
992 $text = "one";
993 $page = $this->newPage( "WikiPageTest_testDoRollback" );
994 $page->doEditContent(
995 ContentHandler::makeContent( $text, $page->getTitle(), CONTENT_MODEL_WIKITEXT ),
996 "section one",
997 EDIT_NEW,
998 false,
999 $admin
1001 $rev1 = $page->getRevision();
1003 $user1 = new User();
1004 $user1->setName( "127.0.1.11" );
1005 $user1->addGroup( "sysop" ); # XXX: make the test user a sysop...
1006 $text .= "\n\ntwo";
1007 $page = new WikiPage( $page->getTitle() );
1008 $page->doEditContent(
1009 ContentHandler::makeContent( $text, $page->getTitle(), CONTENT_MODEL_WIKITEXT ),
1010 "adding section two",
1012 false,
1013 $user1
1016 # now, do a the rollback from the same user was doing the edit before
1017 $resultDetails = [];
1018 $token = $user1->getEditToken(
1019 [ $page->getTitle()->getPrefixedText(), $user1->getName() ],
1020 null
1022 $errors = $page->doRollback(
1023 $user1->getName(),
1024 "testing revert same user",
1025 $token,
1026 false,
1027 $resultDetails,
1028 $admin
1031 $this->assertEquals( [], $errors, "Rollback failed same user" );
1033 # now, try the rollback
1034 $resultDetails = [];
1035 $token = $admin->getEditToken(
1036 [ $page->getTitle()->getPrefixedText(), $user1->getName() ],
1037 null
1039 $errors = $page->doRollback(
1040 $user1->getName(),
1041 "testing revert",
1042 $token,
1043 false,
1044 $resultDetails,
1045 $admin
1048 $this->assertEquals( [ [ 'alreadyrolled', 'WikiPageTest testDoRollback',
1049 '127.0.1.11', 'Admin' ] ], $errors, "Rollback not failed" );
1051 $page = new WikiPage( $page->getTitle() );
1052 $this->assertEquals( $rev1->getSha1(), $page->getRevision()->getSha1(),
1053 "rollback did not revert to the correct revision" );
1054 $this->assertEquals( "one", $page->getContent()->getNativeData() );
1057 public static function provideGetAutosummary() {
1058 return [
1060 'Hello there, world!',
1061 '#REDIRECT [[Foo]]',
1063 '/^Redirected page .*Foo/'
1067 null,
1068 'Hello world!',
1069 EDIT_NEW,
1070 '/^Created page .*Hello/'
1074 'Hello there, world!',
1077 '/^Blanked/'
1081 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy
1082 eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam
1083 voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet
1084 clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.',
1085 'Hello world!',
1087 '/^Replaced .*Hello/'
1091 'foo',
1092 'bar',
1094 '/^$/'
1100 * @dataProvider provideGetAutoSummary
1101 * @covers WikiPage::getAutosummary
1103 public function testGetAutosummary( $old, $new, $flags, $expected ) {
1104 $this->hideDeprecated( "WikiPage::getAutosummary" );
1106 $page = $this->newPage( "WikiPageTest_testGetAutosummary" );
1108 $summary = $page->getAutosummary( $old, $new, $flags );
1110 $this->assertTrue( (bool)preg_match( $expected, $summary ),
1111 "Autosummary didn't match expected pattern $expected: $summary" );
1114 public static function provideGetAutoDeleteReason() {
1115 return [
1118 false,
1119 false
1124 [ "first edit", null ],
1126 "/first edit.*only contributor/",
1127 false
1132 [ "first edit", null ],
1133 [ "second edit", null ],
1135 "/second edit.*only contributor/",
1136 true
1141 [ "first edit", "127.0.2.22" ],
1142 [ "second edit", "127.0.3.33" ],
1144 "/second edit/",
1145 true
1151 "first edit: "
1152 . "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam "
1153 . " nonumy eirmod tempor invidunt ut labore et dolore magna "
1154 . "aliquyam erat, sed diam voluptua. At vero eos et accusam "
1155 . "et justo duo dolores et ea rebum. Stet clita kasd gubergren, "
1156 . "no sea takimata sanctus est Lorem ipsum dolor sit amet.'",
1157 null
1160 '/first edit:.*\.\.\."/',
1161 false
1166 [ "first edit", "127.0.2.22" ],
1167 [ "", "127.0.3.33" ],
1169 "/before blanking.*first edit/",
1170 true
1177 * @dataProvider provideGetAutoDeleteReason
1178 * @covers WikiPage::getAutoDeleteReason
1180 public function testGetAutoDeleteReason( $edits, $expectedResult, $expectedHistory ) {
1181 global $wgUser;
1183 // NOTE: assume Help namespace to contain wikitext
1184 $page = $this->newPage( "Help:WikiPageTest_testGetAutoDeleteReason" );
1186 $c = 1;
1188 foreach ( $edits as $edit ) {
1189 $user = new User();
1191 if ( !empty( $edit[1] ) ) {
1192 $user->setName( $edit[1] );
1193 } else {
1194 $user = $wgUser;
1197 $content = ContentHandler::makeContent( $edit[0], $page->getTitle(), $page->getContentModel() );
1199 $page->doEditContent( $content, "test edit $c", $c < 2 ? EDIT_NEW : 0, false, $user );
1201 $c += 1;
1204 $reason = $page->getAutoDeleteReason( $hasHistory );
1206 if ( is_bool( $expectedResult ) || is_null( $expectedResult ) ) {
1207 $this->assertEquals( $expectedResult, $reason );
1208 } else {
1209 $this->assertTrue( (bool)preg_match( $expectedResult, $reason ),
1210 "Autosummary didn't match expected pattern $expectedResult: $reason" );
1213 $this->assertEquals( $expectedHistory, $hasHistory,
1214 "expected \$hasHistory to be " . var_export( $expectedHistory, true ) );
1216 $page->doDeleteArticle( "done" );
1219 public static function providePreSaveTransform() {
1220 return [
1221 [ 'hello this is ~~~',
1222 "hello this is [[Special:Contributions/127.0.0.1|127.0.0.1]]",
1224 [ 'hello \'\'this\'\' is <nowiki>~~~</nowiki>',
1225 'hello \'\'this\'\' is <nowiki>~~~</nowiki>',
1231 * @covers WikiPage::factory
1233 public function testWikiPageFactory() {
1234 $title = Title::makeTitle( NS_FILE, 'Someimage.png' );
1235 $page = WikiPage::factory( $title );
1236 $this->assertEquals( 'WikiFilePage', get_class( $page ) );
1238 $title = Title::makeTitle( NS_CATEGORY, 'SomeCategory' );
1239 $page = WikiPage::factory( $title );
1240 $this->assertEquals( 'WikiCategoryPage', get_class( $page ) );
1242 $title = Title::makeTitle( NS_MAIN, 'SomePage' );
1243 $page = WikiPage::factory( $title );
1244 $this->assertEquals( 'WikiPage', get_class( $page ) );