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