4 * @group ContentHandler
6 * ^--- important, causes temporary tables to be used instead of the real database
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(
37 protected function setUp() {
39 $this->pages_to_delete
= [];
41 LinkCache
::singleton()->clear(); # avoid cached redirect status, etc
44 protected function tearDown() {
45 foreach ( $this->pages_to_delete
as $p ) {
46 /* @var $p WikiPage */
50 $p->doDeleteArticle( "testing done." );
52 } catch ( MWException
$ex ) {
60 * @param Title|string $title
61 * @param string|null $model
64 protected function newPage( $title, $model = null ) {
65 if ( is_string( $title ) ) {
66 $ns = $this->getDefaultWikitextNS();
67 $title = Title
::newFromText( $title, $ns );
70 $p = new WikiPage( $title );
72 $this->pages_to_delete
[] = $p;
78 * @param string|Title|WikiPage $page
84 protected function createPage( $page, $text, $model = null ) {
85 if ( is_string( $page ) ||
$page instanceof Title
) {
86 $page = $this->newPage( $page, $model );
89 $content = ContentHandler
::makeContent( $text, $page->getTitle(), $model );
90 $page->doEditContent( $content, "testing", EDIT_NEW
);
96 * @covers WikiPage::doEditContent
97 * @covers WikiPage::doModify
98 * @covers WikiPage::doCreate
99 * @covers WikiPage::doEditUpdates
101 public function testDoEditContent() {
102 $page = $this->newPage( "WikiPageTest_testDoEditContent" );
103 $title = $page->getTitle();
105 $content = ContentHandler
::makeContent(
106 "[[Lorem ipsum]] dolor sit amet, consetetur sadipscing elitr, sed diam "
107 . " nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat.",
109 CONTENT_MODEL_WIKITEXT
112 $page->doEditContent( $content, "[[testing]] 1" );
114 $this->assertTrue( $title->getArticleID() > 0, "Title object should have new page id" );
115 $this->assertTrue( $page->getId() > 0, "WikiPage should have new page id" );
116 $this->assertTrue( $title->exists(), "Title object should indicate that the page now exists" );
117 $this->assertTrue( $page->exists(), "WikiPage object should indicate that the page now exists" );
119 $id = $page->getId();
121 # ------------------------
122 $dbr = wfGetDB( DB_REPLICA
);
123 $res = $dbr->select( 'pagelinks', '*', [ 'pl_from' => $id ] );
124 $n = $res->numRows();
127 $this->assertEquals( 1, $n, 'pagelinks should contain one link from the page' );
129 # ------------------------
130 $page = new WikiPage( $title );
132 $retrieved = $page->getContent();
133 $this->assertTrue( $content->equals( $retrieved ), 'retrieved content doesn\'t equal original' );
135 # ------------------------
136 $content = ContentHandler
::makeContent(
137 "At vero eos et accusam et justo duo [[dolores]] et ea rebum. "
138 . "Stet clita kasd [[gubergren]], no sea takimata sanctus est.",
140 CONTENT_MODEL_WIKITEXT
143 $page->doEditContent( $content, "testing 2" );
145 # ------------------------
146 $page = new WikiPage( $title );
148 $retrieved = $page->getContent();
149 $this->assertTrue( $content->equals( $retrieved ), 'retrieved content doesn\'t equal original' );
151 # ------------------------
152 $dbr = wfGetDB( DB_REPLICA
);
153 $res = $dbr->select( 'pagelinks', '*', [ 'pl_from' => $id ] );
154 $n = $res->numRows();
157 $this->assertEquals( 2, $n, 'pagelinks should contain two links from the page' );
161 * @covers WikiPage::doDeleteArticle
163 public function testDoDeleteArticle() {
164 $page = $this->createPage(
165 "WikiPageTest_testDoDeleteArticle",
166 "[[original text]] foo",
167 CONTENT_MODEL_WIKITEXT
169 $id = $page->getId();
171 $page->doDeleteArticle( "testing deletion" );
174 $page->getTitle()->getArticleID() > 0,
175 "Title object should now have page id 0"
177 $this->assertFalse( $page->getId() > 0, "WikiPage should now have page id 0" );
180 "WikiPage::exists should return false after page was deleted"
184 "WikiPage::getContent should return null after page was deleted"
187 $t = Title
::newFromText( $page->getTitle()->getPrefixedText() );
190 "Title::exists should return false after page was deleted"
194 JobQueueGroup
::destroySingletons();
196 $jobs->loadParamsAndArgs( null, [ 'quiet' => true ], null );
199 # ------------------------
200 $dbr = wfGetDB( DB_REPLICA
);
201 $res = $dbr->select( 'pagelinks', '*', [ 'pl_from' => $id ] );
202 $n = $res->numRows();
205 $this->assertEquals( 0, $n, 'pagelinks should contain no more links from the page' );
209 * @covers WikiPage::doDeleteUpdates
211 public function testDoDeleteUpdates() {
212 $page = $this->createPage(
213 "WikiPageTest_testDoDeleteArticle",
214 "[[original text]] foo",
215 CONTENT_MODEL_WIKITEXT
217 $id = $page->getId();
219 // Similar to MovePage logic
220 wfGetDB( DB_MASTER
)->delete( 'page', [ 'page_id' => $id ], __METHOD__
);
221 $page->doDeleteUpdates( $id );
224 JobQueueGroup
::destroySingletons();
226 $jobs->loadParamsAndArgs( null, [ 'quiet' => true ], null );
229 # ------------------------
230 $dbr = wfGetDB( DB_REPLICA
);
231 $res = $dbr->select( 'pagelinks', '*', [ 'pl_from' => $id ] );
232 $n = $res->numRows();
235 $this->assertEquals( 0, $n, 'pagelinks should contain no more links from the page' );
239 * @covers WikiPage::getRevision
241 public function testGetRevision() {
242 $page = $this->newPage( "WikiPageTest_testGetRevision" );
244 $rev = $page->getRevision();
245 $this->assertNull( $rev );
248 $this->createPage( $page, "some text", CONTENT_MODEL_WIKITEXT
);
250 $rev = $page->getRevision();
252 $this->assertEquals( $page->getLatest(), $rev->getId() );
253 $this->assertEquals( "some text", $rev->getContent()->getNativeData() );
257 * @covers WikiPage::getContent
259 public function testGetContent() {
260 $page = $this->newPage( "WikiPageTest_testGetContent" );
262 $content = $page->getContent();
263 $this->assertNull( $content );
266 $this->createPage( $page, "some text", CONTENT_MODEL_WIKITEXT
);
268 $content = $page->getContent();
269 $this->assertEquals( "some text", $content->getNativeData() );
273 * @covers WikiPage::getContentModel
275 public function testGetContentModel() {
276 global $wgContentHandlerUseDB;
278 if ( !$wgContentHandlerUseDB ) {
279 $this->markTestSkipped( '$wgContentHandlerUseDB is disabled' );
282 $page = $this->createPage(
283 "WikiPageTest_testGetContentModel",
285 CONTENT_MODEL_JAVASCRIPT
288 $page = new WikiPage( $page->getTitle() );
289 $this->assertEquals( CONTENT_MODEL_JAVASCRIPT
, $page->getContentModel() );
293 * @covers WikiPage::getContentHandler
295 public function testGetContentHandler() {
296 global $wgContentHandlerUseDB;
298 if ( !$wgContentHandlerUseDB ) {
299 $this->markTestSkipped( '$wgContentHandlerUseDB is disabled' );
302 $page = $this->createPage(
303 "WikiPageTest_testGetContentHandler",
305 CONTENT_MODEL_JAVASCRIPT
308 $page = new WikiPage( $page->getTitle() );
309 $this->assertEquals( 'JavaScriptContentHandler', get_class( $page->getContentHandler() ) );
313 * @covers WikiPage::exists
315 public function testExists() {
316 $page = $this->newPage( "WikiPageTest_testExists" );
317 $this->assertFalse( $page->exists() );
320 $this->createPage( $page, "some text", CONTENT_MODEL_WIKITEXT
);
321 $this->assertTrue( $page->exists() );
323 $page = new WikiPage( $page->getTitle() );
324 $this->assertTrue( $page->exists() );
327 $page->doDeleteArticle( "done testing" );
328 $this->assertFalse( $page->exists() );
330 $page = new WikiPage( $page->getTitle() );
331 $this->assertFalse( $page->exists() );
334 public static function provideHasViewableContent() {
336 [ 'WikiPageTest_testHasViewableContent', false, true ],
337 [ 'Special:WikiPageTest_testHasViewableContent', false ],
338 [ 'MediaWiki:WikiPageTest_testHasViewableContent', false ],
339 [ 'Special:Userlogin', true ],
340 [ 'MediaWiki:help', true ],
345 * @dataProvider provideHasViewableContent
346 * @covers WikiPage::hasViewableContent
348 public function testHasViewableContent( $title, $viewable, $create = false ) {
349 $page = $this->newPage( $title );
350 $this->assertEquals( $viewable, $page->hasViewableContent() );
353 $this->createPage( $page, "some text", CONTENT_MODEL_WIKITEXT
);
354 $this->assertTrue( $page->hasViewableContent() );
356 $page = new WikiPage( $page->getTitle() );
357 $this->assertTrue( $page->hasViewableContent() );
361 public static function provideGetRedirectTarget() {
363 [ 'WikiPageTest_testGetRedirectTarget_1', CONTENT_MODEL_WIKITEXT
, "hello world", null ],
365 'WikiPageTest_testGetRedirectTarget_2',
366 CONTENT_MODEL_WIKITEXT
,
367 "#REDIRECT [[hello world]]",
374 * @dataProvider provideGetRedirectTarget
375 * @covers WikiPage::getRedirectTarget
377 public function testGetRedirectTarget( $title, $model, $text, $target ) {
378 $this->setMwGlobals( [
379 'wgCapitalLinks' => true,
382 $page = $this->createPage( $title, $text, $model );
384 # sanity check, because this test seems to fail for no reason for some people.
385 $c = $page->getContent();
386 $this->assertEquals( 'WikitextContent', get_class( $c ) );
388 # now, test the actual redirect
389 $t = $page->getRedirectTarget();
390 $this->assertEquals( $target, is_null( $t ) ?
null : $t->getPrefixedText() );
394 * @dataProvider provideGetRedirectTarget
395 * @covers WikiPage::isRedirect
397 public function testIsRedirect( $title, $model, $text, $target ) {
398 $page = $this->createPage( $title, $text, $model );
399 $this->assertEquals( !is_null( $target ), $page->isRedirect() );
402 public static function provideIsCountable() {
406 [ 'WikiPageTest_testIsCountable',
407 CONTENT_MODEL_WIKITEXT
,
412 [ 'WikiPageTest_testIsCountable',
413 CONTENT_MODEL_WIKITEXT
,
420 [ 'WikiPageTest_testIsCountable',
421 CONTENT_MODEL_WIKITEXT
,
426 [ 'WikiPageTest_testIsCountable',
427 CONTENT_MODEL_WIKITEXT
,
434 [ 'WikiPageTest_testIsCountable',
435 CONTENT_MODEL_WIKITEXT
,
440 [ 'WikiPageTest_testIsCountable',
441 CONTENT_MODEL_WIKITEXT
,
448 [ 'WikiPageTest_testIsCountable',
449 CONTENT_MODEL_WIKITEXT
,
454 [ 'WikiPageTest_testIsCountable',
455 CONTENT_MODEL_WIKITEXT
,
460 [ 'WikiPageTest_testIsCountable',
461 CONTENT_MODEL_WIKITEXT
,
467 // not a content namespace
468 [ 'Talk:WikiPageTest_testIsCountable',
469 CONTENT_MODEL_WIKITEXT
,
474 [ 'Talk:WikiPageTest_testIsCountable',
475 CONTENT_MODEL_WIKITEXT
,
480 [ 'Talk:WikiPageTest_testIsCountable',
481 CONTENT_MODEL_WIKITEXT
,
487 // not a content namespace, different model
488 [ 'MediaWiki:WikiPageTest_testIsCountable.js',
494 [ 'MediaWiki:WikiPageTest_testIsCountable.js',
500 [ 'MediaWiki:WikiPageTest_testIsCountable.js',
510 * @dataProvider provideIsCountable
511 * @covers WikiPage::isCountable
513 public function testIsCountable( $title, $model, $text, $mode, $expected ) {
514 global $wgContentHandlerUseDB;
516 $this->setMwGlobals( 'wgArticleCountMethod', $mode );
518 $title = Title
::newFromText( $title );
520 if ( !$wgContentHandlerUseDB
522 && ContentHandler
::getDefaultModelFor( $title ) != $model
524 $this->markTestSkipped( "Can not use non-default content model $model for "
525 . $title->getPrefixedDBkey() . " with \$wgContentHandlerUseDB disabled." );
528 $page = $this->createPage( $title, $text, $model );
530 $editInfo = $page->prepareContentForEdit( $page->getContent() );
532 $v = $page->isCountable();
533 $w = $page->isCountable( $editInfo );
538 "isCountable( null ) returned unexpected value " . var_export( $v, true )
539 . " instead of " . var_export( $expected, true )
540 . " in mode `$mode` for text \"$text\""
546 "isCountable( \$editInfo ) returned unexpected value " . var_export( $v, true )
547 . " instead of " . var_export( $expected, true )
548 . " in mode `$mode` for text \"$text\""
552 public static function provideGetParserOutput() {
555 CONTENT_MODEL_WIKITEXT
,
557 "<div class=\"mw-parser-output\"><p>hello <i>world</i></p></div>"
564 * @dataProvider provideGetParserOutput
565 * @covers WikiPage::getParserOutput
567 public function testGetParserOutput( $model, $text, $expectedHtml ) {
568 $page = $this->createPage( 'WikiPageTest_testGetParserOutput', $text, $model );
570 $opt = $page->makeParserOptions( 'canonical' );
571 $po = $page->getParserOutput( $opt );
572 $text = $po->getText();
574 $text = trim( preg_replace( '/<!--.*?-->/sm', '', $text ) ); # strip injected comments
575 $text = preg_replace( '!\s*(</p>|</div>)!sm', '\1', $text ); # don't let tidy confuse us
577 $this->assertEquals( $expectedHtml, $text );
583 * @covers WikiPage::getParserOutput
585 public function testGetParserOutput_nonexisting() {
589 $page = new WikiPage( new Title( "WikiPageTest_testGetParserOutput_nonexisting_$count" ) );
591 $opt = new ParserOptions();
592 $po = $page->getParserOutput( $opt );
594 $this->assertFalse( $po, "getParserOutput() shall return false for non-existing pages." );
598 * @covers WikiPage::getParserOutput
600 public function testGetParserOutput_badrev() {
601 $page = $this->createPage( 'WikiPageTest_testGetParserOutput', "dummy", CONTENT_MODEL_WIKITEXT
);
603 $opt = new ParserOptions();
604 $po = $page->getParserOutput( $opt, $page->getLatest() +
1234 );
606 // @todo would be neat to also test deleted revision
608 $this->assertFalse( $po, "getParserOutput() shall return false for non-existing revisions." );
611 public static $sections =
625 public function dataReplaceSection() {
626 // NOTE: assume the Help namespace to contain wikitext
628 [ 'Help:WikiPageTest_testReplaceSection',
629 CONTENT_MODEL_WIKITEXT
,
634 trim( preg_replace( '/^Intro/sm', 'No more', self
::$sections ) )
636 [ 'Help:WikiPageTest_testReplaceSection',
637 CONTENT_MODEL_WIKITEXT
,
644 [ 'Help:WikiPageTest_testReplaceSection',
645 CONTENT_MODEL_WIKITEXT
,
648 "== TEST ==\nmore fun",
650 trim( preg_replace( '/^== test ==.*== foo ==/sm',
651 "== TEST ==\nmore fun\n\n== foo ==",
654 [ 'Help:WikiPageTest_testReplaceSection',
655 CONTENT_MODEL_WIKITEXT
,
660 trim( self
::$sections )
662 [ 'Help:WikiPageTest_testReplaceSection',
663 CONTENT_MODEL_WIKITEXT
,
668 trim( self
::$sections ) . "\n\n== New ==\n\nNo more"
674 * @dataProvider dataReplaceSection
675 * @covers WikiPage::replaceSectionContent
677 public function testReplaceSectionContent( $title, $model, $text, $section,
678 $with, $sectionTitle, $expected
680 $page = $this->createPage( $title, $text, $model );
682 $content = ContentHandler
::makeContent( $with, $page->getTitle(), $page->getContentModel() );
683 $c = $page->replaceSectionContent( $section, $content, $sectionTitle );
685 $this->assertEquals( $expected, is_null( $c ) ?
null : trim( $c->getNativeData() ) );
689 * @dataProvider dataReplaceSection
690 * @covers WikiPage::replaceSectionAtRev
692 public function testReplaceSectionAtRev( $title, $model, $text, $section,
693 $with, $sectionTitle, $expected
695 $page = $this->createPage( $title, $text, $model );
696 $baseRevId = $page->getLatest();
698 $content = ContentHandler
::makeContent( $with, $page->getTitle(), $page->getContentModel() );
699 $c = $page->replaceSectionAtRev( $section, $content, $sectionTitle, $baseRevId );
701 $this->assertEquals( $expected, is_null( $c ) ?
null : trim( $c->getNativeData() ) );
704 /* @todo FIXME: fix this!
705 public function testGetUndoText() {
706 $this->markTestSkippedIfNoDiff3();
709 $page = $this->createPage( "WikiPageTest_testGetUndoText", $text );
710 $rev1 = $page->getRevision();
713 $page->doEditContent(
714 ContentHandler::makeContent( $text, $page->getTitle() ),
717 $rev2 = $page->getRevision();
719 $text .= "\n\nthree";
720 $page->doEditContent(
721 ContentHandler::makeContent( $text, $page->getTitle() ),
722 "adding section three"
724 $rev3 = $page->getRevision();
727 $page->doEditContent(
728 ContentHandler::makeContent( $text, $page->getTitle() ),
729 "adding section four"
731 $rev4 = $page->getRevision();
734 $page->doEditContent(
735 ContentHandler::makeContent( $text, $page->getTitle() ),
736 "adding section five"
738 $rev5 = $page->getRevision();
741 $page->doEditContent(
742 ContentHandler::makeContent( $text, $page->getTitle() ),
745 $rev6 = $page->getRevision();
747 $undo6 = $page->getUndoText( $rev6 );
748 if ( $undo6 === false ) $this->fail( "getUndoText failed for rev6" );
749 $this->assertEquals( "one\n\ntwo\n\nthree\n\nfour\n\nfive", $undo6 );
751 $undo3 = $page->getUndoText( $rev4, $rev2 );
752 if ( $undo3 === false ) $this->fail( "getUndoText failed for rev4..rev2" );
753 $this->assertEquals( "one\n\ntwo\n\nfive", $undo3 );
755 $undo2 = $page->getUndoText( $rev2 );
756 if ( $undo2 === false ) $this->fail( "getUndoText failed for rev2" );
757 $this->assertEquals( "one\n\nfive", $undo2 );
762 * @covers WikiPage::getOldestRevision
764 public function testGetOldestRevision() {
765 $page = $this->newPage( "WikiPageTest_testGetOldestRevision" );
766 $page->doEditContent(
767 new WikitextContent( 'one' ),
771 $rev1 = $page->getRevision();
773 $page = new WikiPage( $page->getTitle() );
774 $page->doEditContent(
775 new WikitextContent( 'two' ),
780 $page = new WikiPage( $page->getTitle() );
781 $page->doEditContent(
782 new WikitextContent( 'three' ),
788 $this->assertNotEquals(
790 $page->getRevision()->getId(),
791 '$page->getRevision()->getId()'
797 $page->getOldestRevision()->getId(),
798 '$page->getOldestRevision()->getId()'
803 * @todo FIXME: this is a better rollback test than the one below, but it
804 * keeps failing in jenkins for some reason.
806 public function broken_testDoRollback() {
808 $admin->setName( "Admin" );
811 $page = $this->newPage( "WikiPageTest_testDoRollback" );
812 $page->doEditContent( ContentHandler
::makeContent( $text, $page->getTitle() ),
813 "section one", EDIT_NEW
, false, $admin );
816 $user1->setName( "127.0.1.11" );
818 $page = new WikiPage( $page->getTitle() );
819 $page->doEditContent( ContentHandler
::makeContent( $text, $page->getTitle() ),
820 "adding section two", 0, false, $user1 );
823 $user2->setName( "127.0.2.13" );
824 $text .= "\n\nthree";
825 $page = new WikiPage( $page->getTitle() );
826 $page->doEditContent( ContentHandler
::makeContent( $text, $page->getTitle() ),
827 "adding section three", 0, false, $user2 );
829 # we are having issues with doRollback spuriously failing. Apparently
830 # the last revision somehow goes missing or not committed under some
831 # circumstances. So, make sure the last revision has the right user name.
832 $dbr = wfGetDB( DB_REPLICA
);
833 $this->assertEquals( 3, Revision
::countByPageId( $dbr, $page->getId() ) );
835 $page = new WikiPage( $page->getTitle() );
836 $rev3 = $page->getRevision();
837 $this->assertEquals( '127.0.2.13', $rev3->getUserText() );
839 $rev2 = $rev3->getPrevious();
840 $this->assertEquals( '127.0.1.11', $rev2->getUserText() );
842 $rev1 = $rev2->getPrevious();
843 $this->assertEquals( 'Admin', $rev1->getUserText() );
845 # now, try the actual rollback
846 $admin->addToDatabase();
847 $admin->addGroup( "sysop" ); # XXX: make the test user a sysop...
848 $token = $admin->getEditToken(
849 [ $page->getTitle()->getPrefixedText(), $user2->getName() ],
852 $errors = $page->doRollback(
862 $this->fail( "Rollback failed:\n" . print_r( $errors, true )
863 . ";\n" . print_r( $details, true ) );
866 $page = new WikiPage( $page->getTitle() );
867 $this->assertEquals( $rev2->getSha1(), $page->getRevision()->getSha1(),
868 "rollback did not revert to the correct revision" );
869 $this->assertEquals( "one\n\ntwo", $page->getContent()->getNativeData() );
873 * @todo FIXME: the above rollback test is better, but it keeps failing in jenkins for some reason.
874 * @covers WikiPage::doRollback
876 public function testDoRollback() {
878 $admin->setName( "Admin" );
879 $admin->addToDatabase();
882 $page = $this->newPage( "WikiPageTest_testDoRollback" );
883 $page->doEditContent(
884 ContentHandler
::makeContent( $text, $page->getTitle(), CONTENT_MODEL_WIKITEXT
),
890 $rev1 = $page->getRevision();
893 $user1->setName( "127.0.1.11" );
895 $page = new WikiPage( $page->getTitle() );
896 $page->doEditContent(
897 ContentHandler
::makeContent( $text, $page->getTitle(), CONTENT_MODEL_WIKITEXT
),
898 "adding section two",
904 # now, try the rollback
905 $admin->addGroup( "sysop" ); # XXX: make the test user a sysop...
906 $token = $admin->getEditToken( 'rollback' );
907 $errors = $page->doRollback(
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( $rev1->getSha1(), $page->getRevision()->getSha1(),
923 "rollback did not revert to the correct revision" );
924 $this->assertEquals( "one", $page->getContent()->getNativeData() );
928 * @covers WikiPage::doRollback
930 public function testDoRollbackFailureSameContent() {
932 $admin->setName( "Admin" );
933 $admin->addToDatabase();
934 $admin->addGroup( "sysop" ); # XXX: make the test user a sysop...
937 $page = $this->newPage( "WikiPageTest_testDoRollback" );
938 $page->doEditContent(
939 ContentHandler
::makeContent( $text, $page->getTitle(), CONTENT_MODEL_WIKITEXT
),
945 $rev1 = $page->getRevision();
948 $user1->setName( "127.0.1.11" );
949 $user1->addToDatabase();
950 $user1->addGroup( "sysop" ); # XXX: make the test user a sysop...
952 $page = new WikiPage( $page->getTitle() );
953 $page->doEditContent(
954 ContentHandler
::makeContent( $text, $page->getTitle(), CONTENT_MODEL_WIKITEXT
),
955 "adding section two",
961 # now, do a the rollback from the same user was doing the edit before
963 $token = $user1->getEditToken( 'rollback' );
964 $errors = $page->doRollback(
966 "testing revert same user",
973 $this->assertEquals( [], $errors, "Rollback failed same user" );
975 # now, try the rollback
977 $token = $admin->getEditToken( 'rollback' );
978 $errors = $page->doRollback(
987 $this->assertEquals( [ [ 'alreadyrolled', 'WikiPageTest testDoRollback',
988 '127.0.1.11', 'Admin' ] ], $errors, "Rollback not failed" );
990 $page = new WikiPage( $page->getTitle() );
991 $this->assertEquals( $rev1->getSha1(), $page->getRevision()->getSha1(),
992 "rollback did not revert to the correct revision" );
993 $this->assertEquals( "one", $page->getContent()->getNativeData() );
997 * Tests tagging for edits that do rollback action
998 * @covers WikiPage::doRollback
1000 public function testDoRollbackTagging() {
1001 if ( !in_array( 'mw-rollback', ChangeTags
::getSoftwareTags() ) ) {
1002 $this->markTestSkipped( 'Rollback tag deactivated, skipped the test.' );
1005 $admin = new User();
1006 $admin->setName( 'Administrator' );
1007 $admin->addToDatabase();
1009 $text = 'First line';
1010 $page = $this->newPage( 'WikiPageTest_testDoRollbackTagging' );
1011 $page->doEditContent(
1012 ContentHandler
::makeContent( $text, $page->getTitle(), CONTENT_MODEL_WIKITEXT
),
1019 $secondUser = new User();
1020 $secondUser->setName( '92.65.217.32' );
1021 $text .= '\n\nSecond line';
1022 $page = new WikiPage( $page->getTitle() );
1023 $page->doEditContent(
1024 ContentHandler
::makeContent( $text, $page->getTitle(), CONTENT_MODEL_WIKITEXT
),
1025 'Adding second line',
1031 // Now, try the rollback
1032 $admin->addGroup( 'sysop' ); // Make the test user a sysop
1033 $token = $admin->getEditToken( 'rollback' );
1034 $errors = $page->doRollback(
1035 $secondUser->getName(),
1043 // If doRollback completed without errors
1044 if ( $errors === [] ) {
1045 $tags = $resultDetails[ 'tags' ];
1046 $this->assertContains( 'mw-rollback', $tags );
1050 public static function provideGetAutoDeleteReason() {
1060 [ "first edit", null ],
1062 "/first edit.*only contributor/",
1068 [ "first edit", null ],
1069 [ "second edit", null ],
1071 "/second edit.*only contributor/",
1077 [ "first edit", "127.0.2.22" ],
1078 [ "second edit", "127.0.3.33" ],
1088 . "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam "
1089 . " nonumy eirmod tempor invidunt ut labore et dolore magna "
1090 . "aliquyam erat, sed diam voluptua. At vero eos et accusam "
1091 . "et justo duo dolores et ea rebum. Stet clita kasd gubergren, "
1092 . "no sea takimata sanctus est Lorem ipsum dolor sit amet.'",
1096 '/first edit:.*\.\.\."/',
1102 [ "first edit", "127.0.2.22" ],
1103 [ "", "127.0.3.33" ],
1105 "/before blanking.*first edit/",
1113 * @dataProvider provideGetAutoDeleteReason
1114 * @covers WikiPage::getAutoDeleteReason
1116 public function testGetAutoDeleteReason( $edits, $expectedResult, $expectedHistory ) {
1119 // NOTE: assume Help namespace to contain wikitext
1120 $page = $this->newPage( "Help:WikiPageTest_testGetAutoDeleteReason" );
1124 foreach ( $edits as $edit ) {
1127 if ( !empty( $edit[1] ) ) {
1128 $user->setName( $edit[1] );
1133 $content = ContentHandler
::makeContent( $edit[0], $page->getTitle(), $page->getContentModel() );
1135 $page->doEditContent( $content, "test edit $c", $c < 2 ? EDIT_NEW
: 0, false, $user );
1140 $reason = $page->getAutoDeleteReason( $hasHistory );
1142 if ( is_bool( $expectedResult ) ||
is_null( $expectedResult ) ) {
1143 $this->assertEquals( $expectedResult, $reason );
1145 $this->assertTrue( (bool)preg_match( $expectedResult, $reason ),
1146 "Autosummary didn't match expected pattern $expectedResult: $reason" );
1149 $this->assertEquals( $expectedHistory, $hasHistory,
1150 "expected \$hasHistory to be " . var_export( $expectedHistory, true ) );
1152 $page->doDeleteArticle( "done" );
1155 public static function providePreSaveTransform() {
1157 [ 'hello this is ~~~',
1158 "hello this is [[Special:Contributions/127.0.0.1|127.0.0.1]]",
1160 [ 'hello \'\'this\'\' is <nowiki>~~~</nowiki>',
1161 'hello \'\'this\'\' is <nowiki>~~~</nowiki>',
1167 * @covers WikiPage::factory
1169 public function testWikiPageFactory() {
1170 $title = Title
::makeTitle( NS_FILE
, 'Someimage.png' );
1171 $page = WikiPage
::factory( $title );
1172 $this->assertEquals( 'WikiFilePage', get_class( $page ) );
1174 $title = Title
::makeTitle( NS_CATEGORY
, 'SomeCategory' );
1175 $page = WikiPage
::factory( $title );
1176 $this->assertEquals( 'WikiCategoryPage', get_class( $page ) );
1178 $title = Title
::makeTitle( NS_MAIN
, 'SomePage' );
1179 $page = WikiPage
::factory( $title );
1180 $this->assertEquals( 'WikiPage', get_class( $page ) );
1184 * @dataProvider provideCommentMigrationOnDeletion
1185 * @param int $wstage
1186 * @param int $rstage
1188 public function testCommentMigrationOnDeletion( $wstage, $rstage ) {
1189 $this->setMwGlobals( 'wgCommentTableSchemaMigrationStage', $wstage );
1190 $dbr = wfGetDB( DB_REPLICA
);
1192 $page = $this->createPage(
1193 "WikiPageTest_testCommentMigrationOnDeletion",
1195 CONTENT_MODEL_WIKITEXT
1197 $revid = $page->getLatest();
1198 if ( $wstage > MIGRATION_OLD
) {
1199 $comment_id = $dbr->selectField(
1200 'revision_comment_temp',
1201 'revcomment_comment_id',
1202 [ 'revcomment_rev' => $revid ],
1207 $this->setMwGlobals( 'wgCommentTableSchemaMigrationStage', $rstage );
1209 $page->doDeleteArticle( "testing deletion" );
1211 if ( $rstage > MIGRATION_OLD
) {
1212 // Didn't leave behind any 'revision_comment_temp' rows
1213 $n = $dbr->selectField(
1214 'revision_comment_temp', 'COUNT(*)', [ 'revcomment_rev' => $revid ], __METHOD__
1216 $this->assertEquals( 0, $n, 'no entry in revision_comment_temp after deletion' );
1218 // Copied or upgraded the comment_id, as applicable
1219 $ar_comment_id = $dbr->selectField(
1222 [ 'ar_rev_id' => $revid ],
1225 if ( $wstage > MIGRATION_OLD
) {
1226 $this->assertSame( $comment_id, $ar_comment_id );
1228 $this->assertNotEquals( 0, $ar_comment_id );
1232 // Copied rev_comment, if applicable
1233 if ( $rstage <= MIGRATION_WRITE_BOTH
&& $wstage <= MIGRATION_WRITE_BOTH
) {
1234 $ar_comment = $dbr->selectField(
1237 [ 'ar_rev_id' => $revid ],
1240 $this->assertSame( 'testing', $ar_comment );
1244 public static function provideCommentMigrationOnDeletion() {
1246 [ MIGRATION_OLD
, MIGRATION_OLD
],
1247 [ MIGRATION_OLD
, MIGRATION_WRITE_BOTH
],
1248 [ MIGRATION_OLD
, MIGRATION_WRITE_NEW
],
1249 [ MIGRATION_WRITE_BOTH
, MIGRATION_OLD
],
1250 [ MIGRATION_WRITE_BOTH
, MIGRATION_WRITE_BOTH
],
1251 [ MIGRATION_WRITE_BOTH
, MIGRATION_WRITE_NEW
],
1252 [ MIGRATION_WRITE_BOTH
, MIGRATION_NEW
],
1253 [ MIGRATION_WRITE_NEW
, MIGRATION_WRITE_BOTH
],
1254 [ MIGRATION_WRITE_NEW
, MIGRATION_WRITE_NEW
],
1255 [ MIGRATION_WRITE_NEW
, MIGRATION_NEW
],
1256 [ MIGRATION_NEW
, MIGRATION_WRITE_BOTH
],
1257 [ MIGRATION_NEW
, MIGRATION_WRITE_NEW
],
1258 [ MIGRATION_NEW
, MIGRATION_NEW
],