4 * ^--- important, causes temporary tables to be used instead of the real database
7 class WikiPageTest
extends MediaWikiTestCase
{
11 function __construct( $name = null, array $data = array(), $dataName = '' ) {
12 parent
::__construct( $name, $data, $dataName );
14 $this->tablesUsed
= array_merge ( $this->tablesUsed
,
32 public function setUp() {
33 $this->pages_to_delete
= array();
36 public function tearDown() {
37 foreach ( $this->pages_to_delete
as $p ) {
38 /* @var $p WikiPage */
42 $p->doDeleteArticle( "testing done." );
44 } catch ( MWException
$ex ) {
50 protected function newPage( $title ) {
51 if ( is_string( $title ) ) $title = Title
::newFromText( $title );
53 $p = new WikiPage( $title );
55 $this->pages_to_delete
[] = $p;
60 protected function createPage( $page, $text, $model = null ) {
61 if ( is_string( $page ) ) $page = Title
::newFromText( $page );
62 if ( $page instanceof Title
) $page = $this->newPage( $page );
64 $page->doEdit( $text, "testing", EDIT_NEW
);
69 public function testDoEdit() {
70 $title = Title
::newFromText( "WikiPageTest_testDoEdit" );
72 $page = $this->newPage( $title );
74 $text = "[[Lorem ipsum]] dolor sit amet, consetetur sadipscing elitr, sed diam "
75 . " nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat.";
77 $page->doEdit( $text, "testing 1" );
79 $this->assertTrue( $title->exists(), "Title object should indicate that the page now exists" );
80 $this->assertTrue( $page->exists(), "WikiPage object should indicate that the page now exists" );
84 # ------------------------
85 $page = new WikiPage( $title );
87 $retrieved = $page->getText();
88 $this->assertEquals( $text, $retrieved, 'retrieved text doesn\'t equal original' );
90 # ------------------------
91 $text = "At vero eos et accusam et justo duo [[dolores]] et ea rebum. "
92 . "Stet clita kasd [[gubergren]], no sea takimata sanctus est.";
94 $page->doEdit( $text, "testing 2" );
96 # ------------------------
97 $page = new WikiPage( $title );
99 $retrieved = $page->getText();
100 $this->assertEquals( $text, $retrieved, 'retrieved text doesn\'t equal original' );
102 # ------------------------
103 $dbr = wfGetDB( DB_SLAVE
);
104 $res = $dbr->select( 'pagelinks', '*', array( 'pl_from' => $id ) );
105 $n = $res->numRows();
108 $this->assertEquals( 2, $n, 'pagelinks should contain two links from the page' );
111 public function testDoQuickEdit() {
114 $page = $this->createPage( "WikiPageTest_testDoQuickEdit", "original text" );
116 $text = "quick text";
117 $page->doQuickEdit( $text, $wgUser, "testing q" );
119 # ---------------------
120 $page = new WikiPage( $page->getTitle() );
121 $this->assertEquals( $text, $page->getText() );
124 public function testDoDeleteArticle() {
125 $page = $this->createPage( "WikiPageTest_testDoDeleteArticle", "[[original text]] foo" );
126 $id = $page->getId();
128 $page->doDeleteArticle( "testing deletion" );
130 $this->assertFalse( $page->exists(), "WikiPage::exists should return false after page was deleted" );
131 $this->assertFalse( $page->getText(), "WikiPage::getText should return false after page was deleted" );
133 $t = Title
::newFromText( $page->getTitle()->getPrefixedText() );
134 $this->assertFalse( $t->exists(), "Title::exists should return false after page was deleted" );
136 # ------------------------
137 $dbr = wfGetDB( DB_SLAVE
);
138 $res = $dbr->select( 'pagelinks', '*', array( 'pl_from' => $id ) );
139 $n = $res->numRows();
142 $this->assertEquals( 0, $n, 'pagelinks should contain no more links from the page' );
145 public function testGetRevision() {
146 $page = $this->newPage( "WikiPageTest_testGetRevision" );
148 $rev = $page->getRevision();
149 $this->assertNull( $rev );
152 $this->createPage( $page, "some text" );
154 $rev = $page->getRevision();
156 $this->assertEquals( $page->getLatest(), $rev->getId() );
157 $this->assertEquals( "some text", $rev->getText() );
160 public function testGetText() {
161 $page = $this->newPage( "WikiPageTest_testGetText" );
163 $text = $page->getText();
164 $this->assertFalse( $text );
167 $this->createPage( $page, "some text" );
169 $text = $page->getText();
170 $this->assertEquals( "some text", $text );
173 public function testGetRawText() {
174 $page = $this->newPage( "WikiPageTest_testGetRawText" );
176 $text = $page->getRawText();
177 $this->assertFalse( $text );
180 $this->createPage( $page, "some text" );
182 $text = $page->getRawText();
183 $this->assertEquals( "some text", $text );
187 public function testExists() {
188 $page = $this->newPage( "WikiPageTest_testExists" );
189 $this->assertFalse( $page->exists() );
192 $this->createPage( $page, "some text" );
193 $this->assertTrue( $page->exists() );
195 $page = new WikiPage( $page->getTitle() );
196 $this->assertTrue( $page->exists() );
199 $page->doDeleteArticle( "done testing" );
200 $this->assertFalse( $page->exists() );
202 $page = new WikiPage( $page->getTitle() );
203 $this->assertFalse( $page->exists() );
206 public function dataHasViewableContent() {
208 array( 'WikiPageTest_testHasViewableContent', false, true ),
209 array( 'Special:WikiPageTest_testHasViewableContent', false ),
210 array( 'MediaWiki:WikiPageTest_testHasViewableContent', false ),
211 array( 'Special:Userlogin', true ),
212 array( 'MediaWiki:help', true ),
217 * @dataProvider dataHasViewableContent
219 public function testHasViewableContent( $title, $viewable, $create = false ) {
220 $page = $this->newPage( $title );
221 $this->assertEquals( $viewable, $page->hasViewableContent() );
224 $this->createPage( $page, "some text" );
225 $this->assertTrue( $page->hasViewableContent() );
227 $page = new WikiPage( $page->getTitle() );
228 $this->assertTrue( $page->hasViewableContent() );
232 public function dataGetRedirectTarget() {
234 array( 'WikiPageTest_testGetRedirectTarget_1', "hello world", null ),
235 array( 'WikiPageTest_testGetRedirectTarget_2', "#REDIRECT [[hello world]]", "Hello world" ),
240 * @dataProvider dataGetRedirectTarget
242 public function testGetRedirectTarget( $title, $text, $target ) {
243 $page = $this->createPage( $title, $text );
245 # now, test the actual redirect
246 $t = $page->getRedirectTarget();
247 $this->assertEquals( $target, is_null( $t ) ?
null : $t->getPrefixedText() );
251 * @dataProvider dataGetRedirectTarget
253 public function testIsRedirect( $title, $text, $target ) {
254 $page = $this->createPage( $title, $text );
255 $this->assertEquals( !is_null( $target ), $page->isRedirect() );
258 public function dataIsCountable() {
262 array( 'WikiPageTest_testIsCountable',
267 array( 'WikiPageTest_testIsCountable',
274 array( 'WikiPageTest_testIsCountable',
279 array( 'WikiPageTest_testIsCountable',
286 array( 'WikiPageTest_testIsCountable',
291 array( 'WikiPageTest_testIsCountable',
298 array( 'WikiPageTest_testIsCountable',
303 array( 'WikiPageTest_testIsCountable',
308 array( 'WikiPageTest_testIsCountable',
314 // not a content namespace
315 array( 'Talk:WikiPageTest_testIsCountable',
320 array( 'Talk:WikiPageTest_testIsCountable',
325 array( 'Talk:WikiPageTest_testIsCountable',
331 // not a content namespace, different model
332 array( 'MediaWiki:WikiPageTest_testIsCountable.js',
337 array( 'MediaWiki:WikiPageTest_testIsCountable.js',
342 array( 'MediaWiki:WikiPageTest_testIsCountable.js',
352 * @dataProvider dataIsCountable
354 public function testIsCountable( $title, $text, $mode, $expected ) {
355 global $wgArticleCountMethod;
357 $old = $wgArticleCountMethod;
358 $wgArticleCountMethod = $mode;
360 $page = $this->createPage( $title, $text );
361 $editInfo = $page->prepareTextForEdit( $page->getText() );
363 $v = $page->isCountable();
364 $w = $page->isCountable( $editInfo );
365 $wgArticleCountMethod = $old;
367 $this->assertEquals( $expected, $v, "isCountable( null ) returned unexpected value " . var_export( $v, true )
368 . " instead of " . var_export( $expected, true ) . " in mode `$mode` for text \"$text\"" );
370 $this->assertEquals( $expected, $w, "isCountable( \$editInfo ) returned unexpected value " . var_export( $v, true )
371 . " instead of " . var_export( $expected, true ) . " in mode `$mode` for text \"$text\"" );
374 public function dataGetParserOutput() {
376 array("hello ''world''\n", "<p>hello <i>world</i></p>"),
382 * @dataProvider dataGetParserOutput
384 public function testGetParserOutput( $text, $expectedHtml ) {
385 $page = $this->createPage( 'WikiPageTest_testGetParserOutput', $text );
387 $opt = new ParserOptions();
388 $po = $page->getParserOutput( $opt );
389 $text = $po->getText();
391 $text = trim( preg_replace( '/<!--.*?-->/sm', '', $text ) ); # strip injected comments
392 $text = preg_replace( '!\s*(</p>)!sm', '\1', $text ); # don't let tidy confuse us
394 $this->assertEquals( $expectedHtml, $text );
413 public function dataReplaceSection() {
415 array( 'WikiPageTest_testReplaceSection',
416 WikiPageTest
::$sections,
420 trim( preg_replace( '/^Intro/sm', 'No more', WikiPageTest
::$sections ) )
422 array( 'WikiPageTest_testReplaceSection',
423 WikiPageTest
::$sections,
429 array( 'WikiPageTest_testReplaceSection',
430 WikiPageTest
::$sections,
432 "== TEST ==\nmore fun",
434 trim( preg_replace( '/^== test ==.*== foo ==/sm', "== TEST ==\nmore fun\n\n== foo ==", WikiPageTest
::$sections ) )
436 array( 'WikiPageTest_testReplaceSection',
437 WikiPageTest
::$sections,
441 trim( WikiPageTest
::$sections )
443 array( 'WikiPageTest_testReplaceSection',
444 WikiPageTest
::$sections,
448 trim( WikiPageTest
::$sections ) . "\n\n== New ==\n\nNo more"
454 * @dataProvider dataReplaceSection
456 public function testReplaceSection( $title, $text, $section, $with, $sectionTitle, $expected ) {
457 $page = $this->createPage( $title, $text );
458 $text = $page->replaceSection( $section, $with, $sectionTitle );
459 $text = trim( $text );
461 $this->assertEquals( $expected, $text );
465 public function testGetUndoText() {
468 wfSuppressWarnings();
469 $haveDiff3 = $wgDiff3 && file_exists( $wgDiff3 );
473 $this->markTestSkipped( "diff3 not installed or not found" );
478 $page = $this->createPage( "WikiPageTest_testGetUndoText", $text );
479 $rev1 = $page->getRevision();
482 $page->doEditContent( ContentHandler::makeContent( $text, $page->getTitle() ), "adding section two");
483 $rev2 = $page->getRevision();
485 $text .= "\n\nthree";
486 $page->doEditContent( ContentHandler::makeContent( $text, $page->getTitle() ), "adding section three");
487 $rev3 = $page->getRevision();
490 $page->doEditContent( ContentHandler::makeContent( $text, $page->getTitle() ), "adding section four");
491 $rev4 = $page->getRevision();
494 $page->doEditContent( ContentHandler::makeContent( $text, $page->getTitle() ), "adding section five");
495 $rev5 = $page->getRevision();
498 $page->doEditContent( ContentHandler::makeContent( $text, $page->getTitle() ), "adding section six");
499 $rev6 = $page->getRevision();
501 $undo6 = $page->getUndoText( $rev6 );
502 if ( $undo6 === false ) $this->fail( "getUndoText failed for rev6" );
503 $this->assertEquals( "one\n\ntwo\n\nthree\n\nfour\n\nfive", $undo6 );
505 $undo3 = $page->getUndoText( $rev4, $rev2 );
506 if ( $undo3 === false ) $this->fail( "getUndoText failed for rev4..rev2" );
507 $this->assertEquals( "one\n\ntwo\n\nfive", $undo3 );
509 $undo2 = $page->getUndoText( $rev2 );
510 if ( $undo2 === false ) $this->fail( "getUndoText failed for rev2" );
511 $this->assertEquals( "one\n\nfive", $undo2 );
516 * @todo FIXME: this is a better rollback test than the one below, but it keeps failing in jenkins for some reason.
518 public function broken_testDoRollback() {
520 $admin->setName("Admin");
523 $page = $this->newPage( "WikiPageTest_testDoRollback" );
524 $page->doEdit( $text, "section one", EDIT_NEW
, false, $admin );
527 $user1->setName( "127.0.1.11" );
529 $page = new WikiPage( $page->getTitle() );
530 $page->doEdit( $text, "adding section two", 0, false, $user1 );
533 $user2->setName( "127.0.2.13" );
534 $text .= "\n\nthree";
535 $page = new WikiPage( $page->getTitle() );
536 $page->doEdit( $text, "adding section three", 0, false, $user2 );
538 # we are having issues with doRollback spuriously failing. apparently the last revision somehow goes missing
539 # or not committed under some circumstances. so, make sure the last revision has the right user name.
540 $dbr = wfGetDB( DB_SLAVE
);
541 $this->assertEquals( 3, Revision
::countByPageId( $dbr, $page->getId() ) );
543 $page = new WikiPage( $page->getTitle() );
544 $rev3 = $page->getRevision();
545 $this->assertEquals( '127.0.2.13', $rev3->getUserText() );
547 $rev2 = $rev3->getPrevious();
548 $this->assertEquals( '127.0.1.11', $rev2->getUserText() );
550 $rev1 = $rev2->getPrevious();
551 $this->assertEquals( 'Admin', $rev1->getUserText() );
553 # now, try the actual rollback
554 $admin->addGroup( "sysop" ); #XXX: make the test user a sysop...
555 $token = $admin->getEditToken( array( $page->getTitle()->getPrefixedText(), $user2->getName() ), null );
556 $errors = $page->doRollback( $user2->getName(), "testing revert", $token, false, $details, $admin );
559 $this->fail( "Rollback failed:\n" . print_r( $errors, true ) . ";\n" . print_r( $details, true ) );
562 $page = new WikiPage( $page->getTitle() );
563 $this->assertEquals( $rev2->getSha1(), $page->getRevision()->getSha1(), "rollback did not revert to the correct revision" );
564 $this->assertEquals( "one\n\ntwo", $page->getText() );
568 * @todo FIXME: the above rollback test is better, but it keeps failing in jenkins for some reason.
570 public function testDoRollback() {
572 $admin->setName("Admin");
575 $page = $this->newPage( "WikiPageTest_testDoRollback" );
576 $page->doEdit( $text, "section one", EDIT_NEW
, false, $admin );
577 $rev1 = $page->getRevision();
580 $user1->setName( "127.0.1.11" );
582 $page = new WikiPage( $page->getTitle() );
583 $page->doEdit( $text, "adding section two", 0, false, $user1 );
585 # now, try the rollback
586 $admin->addGroup( "sysop" ); #XXX: make the test user a sysop...
587 $token = $admin->getEditToken( array( $page->getTitle()->getPrefixedText(), $user1->getName() ), null );
588 $errors = $page->doRollback( $user1->getName(), "testing revert", $token, false, $details, $admin );
591 $this->fail( "Rollback failed:\n" . print_r( $errors, true ) . ";\n" . print_r( $details, true ) );
594 $page = new WikiPage( $page->getTitle() );
595 $this->assertEquals( $rev1->getSha1(), $page->getRevision()->getSha1(), "rollback did not revert to the correct revision" );
596 $this->assertEquals( "one", $page->getText() );
599 public function dataGetAutosummary( ) {
602 'Hello there, world!',
605 '/^Redirected page .*Foo/'
612 '/^Created page .*Hello/'
616 'Hello there, world!',
623 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut
624 labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et
625 ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.',
628 '/^Replaced .*Hello/'
641 * @dataProvider dataGetAutoSummary
643 public function testGetAutosummary( $old, $new, $flags, $expected ) {
644 $page = $this->newPage( "WikiPageTest_testGetAutosummary" );
646 $summary = $page->getAutosummary( $old, $new, $flags );
648 $this->assertTrue( (bool)preg_match( $expected, $summary ), "Autosummary didn't match expected pattern $expected: $summary" );
651 public function dataGetAutoDeleteReason( ) {
661 array( "first edit", null ),
663 "/first edit.*only contributor/",
669 array( "first edit", null ),
670 array( "second edit", null ),
672 "/second edit.*only contributor/",
678 array( "first edit", "127.0.2.22" ),
679 array( "second edit", "127.0.3.33" ),
687 array( "first edit: "
688 . "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam "
689 . " nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. "
690 . "At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea "
691 . "takimata sanctus est Lorem ipsum dolor sit amet.'", null ),
693 '/first edit:.*\.\.\."/',
699 array( "first edit", "127.0.2.22" ),
700 array( "", "127.0.3.33" ),
702 "/before blanking.*first edit/",
710 * @dataProvider dataGetAutoDeleteReason
712 public function testGetAutoDeleteReason( $edits, $expectedResult, $expectedHistory ) {
715 $page = $this->newPage( "WikiPageTest_testGetAutoDeleteReason" );
719 foreach ( $edits as $edit ) {
722 if ( !empty( $edit[1] ) ) $user->setName( $edit[1] );
723 else $user = $wgUser;
725 $page->doEdit( $edit[0], "test edit $c", $c < 2 ? EDIT_NEW
: 0, false, $user );
730 $reason = $page->getAutoDeleteReason( $hasHistory );
732 if ( is_bool( $expectedResult ) ||
is_null( $expectedResult ) ) $this->assertEquals( $expectedResult, $reason );
733 else $this->assertTrue( (bool)preg_match( $expectedResult, $reason ), "Autosummary didn't match expected pattern $expectedResult: $reason" );
735 $this->assertEquals( $expectedHistory, $hasHistory, "expected \$hasHistory to be " . var_export( $expectedHistory, true ) );
737 $page->doDeleteArticle( "done" );
740 public function dataPreSaveTransform() {
742 array( 'hello this is ~~~',
743 "hello this is [[Special:Contributions/127.0.0.1|127.0.0.1]]",
745 array( 'hello \'\'this\'\' is <nowiki>~~~</nowiki>',
746 'hello \'\'this\'\' is <nowiki>~~~</nowiki>',
752 * @dataProvider dataPreSaveTransform
754 public function testPreSaveTransform( $text, $expected ) {
756 $user->setName("127.0.0.1");
758 $page = $this->newPage( "WikiPageTest_testPreloadTransform" );
759 $text = $page->preSaveTransform( $text, $user );
761 $this->assertEquals( $expected, $text );