4 * ^--- important, causes temporary tables to be used instead of the real database
7 class WikiPageTest
extends MediaWikiLangTestCase
{
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() {
34 $this->pages_to_delete
= array();
37 public function tearDown() {
38 foreach ( $this->pages_to_delete
as $p ) {
39 /* @var $p WikiPage */
43 $p->doDeleteArticle( "testing done." );
45 } catch ( MWException
$ex ) {
52 protected function newPage( $title ) {
53 if ( is_string( $title ) ) $title = Title
::newFromText( $title );
55 $p = new WikiPage( $title );
57 $this->pages_to_delete
[] = $p;
62 protected function createPage( $page, $text, $model = null ) {
63 if ( is_string( $page ) ) $page = Title
::newFromText( $page );
64 if ( $page instanceof Title
) $page = $this->newPage( $page );
66 $page->doEdit( $text, "testing", EDIT_NEW
);
71 public function testDoEdit() {
72 $title = Title
::newFromText( "WikiPageTest_testDoEdit" );
74 $page = $this->newPage( $title );
76 $text = "[[Lorem ipsum]] dolor sit amet, consetetur sadipscing elitr, sed diam "
77 . " nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat.";
79 $page->doEdit( $text, "testing 1" );
81 $this->assertTrue( $title->exists(), "Title object should indicate that the page now exists" );
82 $this->assertTrue( $page->exists(), "WikiPage object should indicate that the page now exists" );
86 # ------------------------
87 $page = new WikiPage( $title );
89 $retrieved = $page->getText();
90 $this->assertEquals( $text, $retrieved, 'retrieved text doesn\'t equal original' );
92 # ------------------------
93 $text = "At vero eos et accusam et justo duo [[dolores]] et ea rebum. "
94 . "Stet clita kasd [[gubergren]], no sea takimata sanctus est.";
96 $page->doEdit( $text, "testing 2" );
98 # ------------------------
99 $page = new WikiPage( $title );
101 $retrieved = $page->getText();
102 $this->assertEquals( $text, $retrieved, 'retrieved text doesn\'t equal original' );
104 # ------------------------
105 $dbr = wfGetDB( DB_SLAVE
);
106 $res = $dbr->select( 'pagelinks', '*', array( 'pl_from' => $id ) );
107 $n = $res->numRows();
110 $this->assertEquals( 2, $n, 'pagelinks should contain two links from the page' );
113 public function testDoQuickEdit() {
116 $page = $this->createPage( "WikiPageTest_testDoQuickEdit", "original text" );
118 $text = "quick text";
119 $page->doQuickEdit( $text, $wgUser, "testing q" );
121 # ---------------------
122 $page = new WikiPage( $page->getTitle() );
123 $this->assertEquals( $text, $page->getText() );
126 public function testDoDeleteArticle() {
127 $page = $this->createPage( "WikiPageTest_testDoDeleteArticle", "[[original text]] foo" );
128 $id = $page->getId();
130 $page->doDeleteArticle( "testing deletion" );
132 $this->assertFalse( $page->exists(), "WikiPage::exists should return false after page was deleted" );
133 $this->assertFalse( $page->getText(), "WikiPage::getText should return false after page was deleted" );
135 $t = Title
::newFromText( $page->getTitle()->getPrefixedText() );
136 $this->assertFalse( $t->exists(), "Title::exists should return false after page was deleted" );
138 # ------------------------
139 $dbr = wfGetDB( DB_SLAVE
);
140 $res = $dbr->select( 'pagelinks', '*', array( 'pl_from' => $id ) );
141 $n = $res->numRows();
144 $this->assertEquals( 0, $n, 'pagelinks should contain no more links from the page' );
147 public function testDoDeleteUpdates() {
148 $page = $this->createPage( "WikiPageTest_testDoDeleteArticle", "[[original text]] foo" );
149 $id = $page->getId();
151 $page->doDeleteUpdates( $id );
153 # ------------------------
154 $dbr = wfGetDB( DB_SLAVE
);
155 $res = $dbr->select( 'pagelinks', '*', array( 'pl_from' => $id ) );
156 $n = $res->numRows();
159 $this->assertEquals( 0, $n, 'pagelinks should contain no more links from the page' );
162 public function testGetRevision() {
163 $page = $this->newPage( "WikiPageTest_testGetRevision" );
165 $rev = $page->getRevision();
166 $this->assertNull( $rev );
169 $this->createPage( $page, "some text" );
171 $rev = $page->getRevision();
173 $this->assertEquals( $page->getLatest(), $rev->getId() );
174 $this->assertEquals( "some text", $rev->getText() );
177 public function testGetText() {
178 $page = $this->newPage( "WikiPageTest_testGetText" );
180 $text = $page->getText();
181 $this->assertFalse( $text );
184 $this->createPage( $page, "some text" );
186 $text = $page->getText();
187 $this->assertEquals( "some text", $text );
190 public function testGetRawText() {
191 $page = $this->newPage( "WikiPageTest_testGetRawText" );
193 $text = $page->getRawText();
194 $this->assertFalse( $text );
197 $this->createPage( $page, "some text" );
199 $text = $page->getRawText();
200 $this->assertEquals( "some text", $text );
204 public function testExists() {
205 $page = $this->newPage( "WikiPageTest_testExists" );
206 $this->assertFalse( $page->exists() );
209 $this->createPage( $page, "some text" );
210 $this->assertTrue( $page->exists() );
212 $page = new WikiPage( $page->getTitle() );
213 $this->assertTrue( $page->exists() );
216 $page->doDeleteArticle( "done testing" );
217 $this->assertFalse( $page->exists() );
219 $page = new WikiPage( $page->getTitle() );
220 $this->assertFalse( $page->exists() );
223 public function dataHasViewableContent() {
225 array( 'WikiPageTest_testHasViewableContent', false, true ),
226 array( 'Special:WikiPageTest_testHasViewableContent', false ),
227 array( 'MediaWiki:WikiPageTest_testHasViewableContent', false ),
228 array( 'Special:Userlogin', true ),
229 array( 'MediaWiki:help', true ),
234 * @dataProvider dataHasViewableContent
236 public function testHasViewableContent( $title, $viewable, $create = false ) {
237 $page = $this->newPage( $title );
238 $this->assertEquals( $viewable, $page->hasViewableContent() );
241 $this->createPage( $page, "some text" );
242 $this->assertTrue( $page->hasViewableContent() );
244 $page = new WikiPage( $page->getTitle() );
245 $this->assertTrue( $page->hasViewableContent() );
249 public function dataGetRedirectTarget() {
251 array( 'WikiPageTest_testGetRedirectTarget_1', "hello world", null ),
252 array( 'WikiPageTest_testGetRedirectTarget_2', "#REDIRECT [[hello world]]", "Hello world" ),
257 * @dataProvider dataGetRedirectTarget
259 public function testGetRedirectTarget( $title, $text, $target ) {
260 $page = $this->createPage( $title, $text );
262 # now, test the actual redirect
263 $t = $page->getRedirectTarget();
264 $this->assertEquals( $target, is_null( $t ) ?
null : $t->getPrefixedText() );
268 * @dataProvider dataGetRedirectTarget
270 public function testIsRedirect( $title, $text, $target ) {
271 $page = $this->createPage( $title, $text );
272 $this->assertEquals( !is_null( $target ), $page->isRedirect() );
275 public function dataIsCountable() {
279 array( 'WikiPageTest_testIsCountable',
284 array( 'WikiPageTest_testIsCountable',
291 array( 'WikiPageTest_testIsCountable',
296 array( 'WikiPageTest_testIsCountable',
303 array( 'WikiPageTest_testIsCountable',
308 array( 'WikiPageTest_testIsCountable',
315 array( 'WikiPageTest_testIsCountable',
320 array( 'WikiPageTest_testIsCountable',
325 array( 'WikiPageTest_testIsCountable',
331 // not a content namespace
332 array( 'Talk:WikiPageTest_testIsCountable',
337 array( 'Talk:WikiPageTest_testIsCountable',
342 array( 'Talk:WikiPageTest_testIsCountable',
348 // not a content namespace, different model
349 array( 'MediaWiki:WikiPageTest_testIsCountable.js',
354 array( 'MediaWiki:WikiPageTest_testIsCountable.js',
359 array( 'MediaWiki:WikiPageTest_testIsCountable.js',
369 * @dataProvider dataIsCountable
371 public function testIsCountable( $title, $text, $mode, $expected ) {
372 global $wgArticleCountMethod;
374 $old = $wgArticleCountMethod;
375 $wgArticleCountMethod = $mode;
377 $page = $this->createPage( $title, $text );
378 $editInfo = $page->prepareTextForEdit( $page->getText() );
380 $v = $page->isCountable();
381 $w = $page->isCountable( $editInfo );
382 $wgArticleCountMethod = $old;
384 $this->assertEquals( $expected, $v, "isCountable( null ) returned unexpected value " . var_export( $v, true )
385 . " instead of " . var_export( $expected, true ) . " in mode `$mode` for text \"$text\"" );
387 $this->assertEquals( $expected, $w, "isCountable( \$editInfo ) returned unexpected value " . var_export( $v, true )
388 . " instead of " . var_export( $expected, true ) . " in mode `$mode` for text \"$text\"" );
391 public function dataGetParserOutput() {
393 array("hello ''world''\n", "<p>hello <i>world</i></p>"),
399 * @dataProvider dataGetParserOutput
401 public function testGetParserOutput( $text, $expectedHtml ) {
402 $page = $this->createPage( 'WikiPageTest_testGetParserOutput', $text );
404 $opt = new ParserOptions();
405 $po = $page->getParserOutput( $opt );
406 $text = $po->getText();
408 $text = trim( preg_replace( '/<!--.*?-->/sm', '', $text ) ); # strip injected comments
409 $text = preg_replace( '!\s*(</p>)!sm', '\1', $text ); # don't let tidy confuse us
411 $this->assertEquals( $expectedHtml, $text );
430 public function dataReplaceSection() {
432 array( 'WikiPageTest_testReplaceSection',
433 WikiPageTest
::$sections,
437 trim( preg_replace( '/^Intro/sm', 'No more', WikiPageTest
::$sections ) )
439 array( 'WikiPageTest_testReplaceSection',
440 WikiPageTest
::$sections,
446 array( 'WikiPageTest_testReplaceSection',
447 WikiPageTest
::$sections,
449 "== TEST ==\nmore fun",
451 trim( preg_replace( '/^== test ==.*== foo ==/sm', "== TEST ==\nmore fun\n\n== foo ==", WikiPageTest
::$sections ) )
453 array( 'WikiPageTest_testReplaceSection',
454 WikiPageTest
::$sections,
458 trim( WikiPageTest
::$sections )
460 array( 'WikiPageTest_testReplaceSection',
461 WikiPageTest
::$sections,
465 trim( WikiPageTest
::$sections ) . "\n\n== New ==\n\nNo more"
471 * @dataProvider dataReplaceSection
473 public function testReplaceSection( $title, $text, $section, $with, $sectionTitle, $expected ) {
474 $page = $this->createPage( $title, $text );
475 $text = $page->replaceSection( $section, $with, $sectionTitle );
476 $text = trim( $text );
478 $this->assertEquals( $expected, $text );
482 public function testGetUndoText() {
485 wfSuppressWarnings();
486 $haveDiff3 = $wgDiff3 && file_exists( $wgDiff3 );
490 $this->markTestSkipped( "diff3 not installed or not found" );
495 $page = $this->createPage( "WikiPageTest_testGetUndoText", $text );
496 $rev1 = $page->getRevision();
499 $page->doEditContent( ContentHandler::makeContent( $text, $page->getTitle() ), "adding section two");
500 $rev2 = $page->getRevision();
502 $text .= "\n\nthree";
503 $page->doEditContent( ContentHandler::makeContent( $text, $page->getTitle() ), "adding section three");
504 $rev3 = $page->getRevision();
507 $page->doEditContent( ContentHandler::makeContent( $text, $page->getTitle() ), "adding section four");
508 $rev4 = $page->getRevision();
511 $page->doEditContent( ContentHandler::makeContent( $text, $page->getTitle() ), "adding section five");
512 $rev5 = $page->getRevision();
515 $page->doEditContent( ContentHandler::makeContent( $text, $page->getTitle() ), "adding section six");
516 $rev6 = $page->getRevision();
518 $undo6 = $page->getUndoText( $rev6 );
519 if ( $undo6 === false ) $this->fail( "getUndoText failed for rev6" );
520 $this->assertEquals( "one\n\ntwo\n\nthree\n\nfour\n\nfive", $undo6 );
522 $undo3 = $page->getUndoText( $rev4, $rev2 );
523 if ( $undo3 === false ) $this->fail( "getUndoText failed for rev4..rev2" );
524 $this->assertEquals( "one\n\ntwo\n\nfive", $undo3 );
526 $undo2 = $page->getUndoText( $rev2 );
527 if ( $undo2 === false ) $this->fail( "getUndoText failed for rev2" );
528 $this->assertEquals( "one\n\nfive", $undo2 );
533 * @todo FIXME: this is a better rollback test than the one below, but it keeps failing in jenkins for some reason.
535 public function broken_testDoRollback() {
537 $admin->setName("Admin");
540 $page = $this->newPage( "WikiPageTest_testDoRollback" );
541 $page->doEdit( $text, "section one", EDIT_NEW
, false, $admin );
544 $user1->setName( "127.0.1.11" );
546 $page = new WikiPage( $page->getTitle() );
547 $page->doEdit( $text, "adding section two", 0, false, $user1 );
550 $user2->setName( "127.0.2.13" );
551 $text .= "\n\nthree";
552 $page = new WikiPage( $page->getTitle() );
553 $page->doEdit( $text, "adding section three", 0, false, $user2 );
555 # we are having issues with doRollback spuriously failing. apparently the last revision somehow goes missing
556 # or not committed under some circumstances. so, make sure the last revision has the right user name.
557 $dbr = wfGetDB( DB_SLAVE
);
558 $this->assertEquals( 3, Revision
::countByPageId( $dbr, $page->getId() ) );
560 $page = new WikiPage( $page->getTitle() );
561 $rev3 = $page->getRevision();
562 $this->assertEquals( '127.0.2.13', $rev3->getUserText() );
564 $rev2 = $rev3->getPrevious();
565 $this->assertEquals( '127.0.1.11', $rev2->getUserText() );
567 $rev1 = $rev2->getPrevious();
568 $this->assertEquals( 'Admin', $rev1->getUserText() );
570 # now, try the actual rollback
571 $admin->addGroup( "sysop" ); #XXX: make the test user a sysop...
572 $token = $admin->getEditToken( array( $page->getTitle()->getPrefixedText(), $user2->getName() ), null );
573 $errors = $page->doRollback( $user2->getName(), "testing revert", $token, false, $details, $admin );
576 $this->fail( "Rollback failed:\n" . print_r( $errors, true ) . ";\n" . print_r( $details, true ) );
579 $page = new WikiPage( $page->getTitle() );
580 $this->assertEquals( $rev2->getSha1(), $page->getRevision()->getSha1(), "rollback did not revert to the correct revision" );
581 $this->assertEquals( "one\n\ntwo", $page->getText() );
585 * @todo FIXME: the above rollback test is better, but it keeps failing in jenkins for some reason.
587 public function testDoRollback() {
589 $admin->setName("Admin");
592 $page = $this->newPage( "WikiPageTest_testDoRollback" );
593 $page->doEdit( $text, "section one", EDIT_NEW
, false, $admin );
594 $rev1 = $page->getRevision();
597 $user1->setName( "127.0.1.11" );
599 $page = new WikiPage( $page->getTitle() );
600 $page->doEdit( $text, "adding section two", 0, false, $user1 );
602 # now, try the rollback
603 $admin->addGroup( "sysop" ); #XXX: make the test user a sysop...
604 $token = $admin->getEditToken( array( $page->getTitle()->getPrefixedText(), $user1->getName() ), null );
605 $errors = $page->doRollback( $user1->getName(), "testing revert", $token, false, $details, $admin );
608 $this->fail( "Rollback failed:\n" . print_r( $errors, true ) . ";\n" . print_r( $details, true ) );
611 $page = new WikiPage( $page->getTitle() );
612 $this->assertEquals( $rev1->getSha1(), $page->getRevision()->getSha1(), "rollback did not revert to the correct revision" );
613 $this->assertEquals( "one", $page->getText() );
616 public function dataGetAutosummary( ) {
619 'Hello there, world!',
622 '/^Redirected page .*Foo/'
629 '/^Created page .*Hello/'
633 'Hello there, world!',
640 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut
641 labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et
642 ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.',
645 '/^Replaced .*Hello/'
658 * @dataProvider dataGetAutoSummary
660 public function testGetAutosummary( $old, $new, $flags, $expected ) {
661 $page = $this->newPage( "WikiPageTest_testGetAutosummary" );
663 $summary = $page->getAutosummary( $old, $new, $flags );
665 $this->assertTrue( (bool)preg_match( $expected, $summary ), "Autosummary didn't match expected pattern $expected: $summary" );
668 public function dataGetAutoDeleteReason( ) {
678 array( "first edit", null ),
680 "/first edit.*only contributor/",
686 array( "first edit", null ),
687 array( "second edit", null ),
689 "/second edit.*only contributor/",
695 array( "first edit", "127.0.2.22" ),
696 array( "second edit", "127.0.3.33" ),
704 array( "first edit: "
705 . "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam "
706 . " nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. "
707 . "At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea "
708 . "takimata sanctus est Lorem ipsum dolor sit amet.'", null ),
710 '/first edit:.*\.\.\."/',
716 array( "first edit", "127.0.2.22" ),
717 array( "", "127.0.3.33" ),
719 "/before blanking.*first edit/",
727 * @dataProvider dataGetAutoDeleteReason
729 public function testGetAutoDeleteReason( $edits, $expectedResult, $expectedHistory ) {
732 $page = $this->newPage( "WikiPageTest_testGetAutoDeleteReason" );
736 foreach ( $edits as $edit ) {
739 if ( !empty( $edit[1] ) ) $user->setName( $edit[1] );
740 else $user = $wgUser;
742 $page->doEdit( $edit[0], "test edit $c", $c < 2 ? EDIT_NEW
: 0, false, $user );
747 $reason = $page->getAutoDeleteReason( $hasHistory );
749 if ( is_bool( $expectedResult ) ||
is_null( $expectedResult ) ) $this->assertEquals( $expectedResult, $reason );
750 else $this->assertTrue( (bool)preg_match( $expectedResult, $reason ), "Autosummary didn't match expected pattern $expectedResult: $reason" );
752 $this->assertEquals( $expectedHistory, $hasHistory, "expected \$hasHistory to be " . var_export( $expectedHistory, true ) );
754 $page->doDeleteArticle( "done" );
757 public function dataPreSaveTransform() {
759 array( 'hello this is ~~~',
760 "hello this is [[Special:Contributions/127.0.0.1|127.0.0.1]]",
762 array( 'hello \'\'this\'\' is <nowiki>~~~</nowiki>',
763 'hello \'\'this\'\' is <nowiki>~~~</nowiki>',
769 * @dataProvider dataPreSaveTransform
771 public function testPreSaveTransform( $text, $expected ) {
773 $user->setName("127.0.0.1");
775 $page = $this->newPage( "WikiPageTest_testPreloadTransform" );
776 $text = $page->preSaveTransform( $text, $user );
778 $this->assertEquals( $expected, $text );