Merge "RevisionStoreDbTestBase, remove redundant needsDB override"
[lhc/web/wiklou.git] / tests / phpunit / includes / Storage / PageUpdaterTest.php
1 <?php
2
3 namespace MediaWiki\Tests\Storage;
4
5 use CommentStoreComment;
6 use Content;
7 use MediaWiki\MediaWikiServices;
8 use MediaWiki\Storage\RevisionRecord;
9 use MediaWikiTestCase;
10 use ParserOptions;
11 use RecentChange;
12 use Revision;
13 use TextContent;
14 use Title;
15 use User;
16 use WikiPage;
17
18 /**
19 * @covers \MediaWiki\Storage\PageUpdater
20 * @group Database
21 */
22 class PageUpdaterTest extends MediaWikiTestCase {
23
24 private function getDummyTitle( $method ) {
25 return Title::newFromText( $method, $this->getDefaultWikitextNS() );
26 }
27
28 /**
29 * @param int $revId
30 *
31 * @return null|RecentChange
32 */
33 private function getRecentChangeFor( $revId ) {
34 $qi = RecentChange::getQueryInfo();
35 $row = $this->db->selectRow(
36 $qi['tables'],
37 $qi['fields'],
38 [ 'rc_this_oldid' => $revId ],
39 __METHOD__,
40 [],
41 $qi['joins']
42 );
43
44 return $row ? RecentChange::newFromRow( $row ) : null;
45 }
46
47 // TODO: test setAjaxEditStash();
48
49 /**
50 * @covers \MediaWiki\Storage\PageUpdater::saveRevision()
51 * @covers \WikiPage::newPageUpdater()
52 */
53 public function testCreatePage() {
54 $user = $this->getTestUser()->getUser();
55
56 $title = $this->getDummyTitle( __METHOD__ );
57 $page = WikiPage::factory( $title );
58 $updater = $page->newPageUpdater( $user );
59
60 $oldStats = $this->db->selectRow( 'site_stats', '*', '1=1' );
61
62 $this->assertFalse( $updater->wasCommitted(), 'wasCommitted' );
63 $this->assertFalse( $updater->getOriginalRevisionId(), 'getOriginalRevisionId' );
64 $this->assertSame( 0, $updater->getUndidRevisionId(), 'getUndidRevisionId' );
65
66 $updater->addTag( 'foo' );
67 $updater->addTags( [ 'bar', 'qux' ] );
68
69 $tags = $updater->getExplicitTags();
70 sort( $tags );
71 $this->assertSame( [ 'bar', 'foo', 'qux' ], $tags, 'getExplicitTags' );
72
73 // TODO: MCR: test additional slots
74 $content = new TextContent( 'Lorem Ipsum' );
75 $updater->setContent( 'main', $content );
76
77 $parent = $updater->grabParentRevision();
78
79 $this->assertNull( $parent, 'getParentRevision' );
80 $this->assertFalse( $updater->wasCommitted(), 'wasCommitted' );
81
82 // TODO: test that hasEditConflict() grabs the parent revision
83 $this->assertFalse( $updater->hasEditConflict( 0 ), 'hasEditConflict' );
84 $this->assertTrue( $updater->hasEditConflict( 1 ), 'hasEditConflict' );
85
86 // TODO: test failure with EDIT_UPDATE
87 // TODO: test EDIT_MINOR, EDIT_BOT, etc
88 $summary = CommentStoreComment::newUnsavedComment( 'Just a test' );
89 $rev = $updater->saveRevision( $summary );
90
91 $this->assertNotNull( $rev );
92 $this->assertSame( 0, $rev->getParentId() );
93 $this->assertSame( $summary->text, $rev->getComment( RevisionRecord::RAW )->text );
94 $this->assertSame( $user->getName(), $rev->getUser( RevisionRecord::RAW )->getName() );
95
96 $this->assertTrue( $updater->wasCommitted(), 'wasCommitted()' );
97 $this->assertTrue( $updater->wasSuccessful(), 'wasSuccessful()' );
98 $this->assertTrue( $updater->getStatus()->isOK(), 'getStatus()->isOK()' );
99 $this->assertTrue( $updater->isNew(), 'isNew()' );
100 $this->assertFalse( $updater->isUnchanged(), 'isUnchanged()' );
101 $this->assertNotNull( $updater->getNewRevision(), 'getNewRevision()' );
102 $this->assertInstanceOf( Revision::class, $updater->getStatus()->value['revision'] );
103
104 $rev = $updater->getNewRevision();
105 $revContent = $rev->getContent( 'main' );
106 $this->assertSame( 'Lorem Ipsum', $revContent->serialize(), 'revision content' );
107
108 // were the WikiPage and Title objects updated?
109 $this->assertTrue( $page->exists(), 'WikiPage::exists()' );
110 $this->assertTrue( $title->exists(), 'Title::exists()' );
111 $this->assertSame( $rev->getId(), $page->getLatest(), 'WikiPage::getRevision()' );
112 $this->assertNotNull( $page->getRevision(), 'WikiPage::getRevision()' );
113
114 // re-load
115 $page2 = WikiPage::factory( $title );
116 $this->assertTrue( $page2->exists(), 'WikiPage::exists()' );
117 $this->assertSame( $rev->getId(), $page2->getLatest(), 'WikiPage::getRevision()' );
118 $this->assertNotNull( $page2->getRevision(), 'WikiPage::getRevision()' );
119
120 // Check RC entry
121 $rc = $this->getRecentChangeFor( $rev->getId() );
122 $this->assertNotNull( $rc, 'RecentChange' );
123
124 // check site stats - this asserts that derived data updates where run.
125 $stats = $this->db->selectRow( 'site_stats', '*', '1=1' );
126 $this->assertSame( $oldStats->ss_total_pages + 1, (int)$stats->ss_total_pages );
127 $this->assertSame( $oldStats->ss_total_edits + 1, (int)$stats->ss_total_edits );
128
129 // re-edit with same content - should be a "null-edit"
130 $updater = $page->newPageUpdater( $user );
131 $updater->setContent( 'main', $content );
132
133 $summary = CommentStoreComment::newUnsavedComment( 'to to re-edit' );
134 $rev = $updater->saveRevision( $summary );
135 $status = $updater->getStatus();
136
137 $this->assertNull( $rev, 'getNewRevision()' );
138 $this->assertNull( $updater->getNewRevision(), 'getNewRevision()' );
139 $this->assertTrue( $updater->isUnchanged(), 'isUnchanged' );
140 $this->assertTrue( $updater->wasSuccessful(), 'wasSuccessful()' );
141 $this->assertTrue( $status->isOK(), 'getStatus()->isOK()' );
142 $this->assertTrue( $status->hasMessage( 'edit-no-change' ), 'edit-no-change' );
143 }
144
145 /**
146 * @covers \MediaWiki\Storage\PageUpdater::saveRevision()
147 * @covers \WikiPage::newPageUpdater()
148 */
149 public function testUpdatePage() {
150 $user = $this->getTestUser()->getUser();
151
152 $title = $this->getDummyTitle( __METHOD__ );
153 $this->insertPage( $title );
154
155 $page = WikiPage::factory( $title );
156 $parentId = $page->getLatest();
157
158 $updater = $page->newPageUpdater( $user );
159
160 $oldStats = $this->db->selectRow( 'site_stats', '*', '1=1' );
161
162 $updater->setOriginalRevisionId( 7 );
163 $this->assertSame( 7, $updater->getOriginalRevisionId(), 'getOriginalRevisionId' );
164
165 $this->assertFalse( $updater->hasEditConflict( $parentId ), 'hasEditConflict' );
166 $this->assertTrue( $updater->hasEditConflict( $parentId - 1 ), 'hasEditConflict' );
167 $this->assertTrue( $updater->hasEditConflict( 0 ), 'hasEditConflict' );
168
169 // TODO: MCR: test additional slots
170 $updater->setContent( 'main', new TextContent( 'Lorem Ipsum' ) );
171
172 // TODO: test all flags for saveRevision()!
173 $summary = CommentStoreComment::newUnsavedComment( 'Just a test' );
174 $rev = $updater->saveRevision( $summary );
175
176 $this->assertNotNull( $rev );
177 $this->assertSame( $parentId, $rev->getParentId() );
178 $this->assertSame( $summary->text, $rev->getComment( RevisionRecord::RAW )->text );
179 $this->assertSame( $user->getName(), $rev->getUser( RevisionRecord::RAW )->getName() );
180
181 $this->assertTrue( $updater->wasCommitted(), 'wasCommitted()' );
182 $this->assertTrue( $updater->wasSuccessful(), 'wasSuccessful()' );
183 $this->assertTrue( $updater->getStatus()->isOK(), 'getStatus()->isOK()' );
184 $this->assertFalse( $updater->isNew(), 'isNew()' );
185 $this->assertNotNull( $updater->getNewRevision(), 'getNewRevision()' );
186 $this->assertInstanceOf( Revision::class, $updater->getStatus()->value['revision'] );
187 $this->assertFalse( $updater->isUnchanged(), 'isUnchanged()' );
188
189 // TODO: Test null revision (with different user): new revision!
190
191 $rev = $updater->getNewRevision();
192 $revContent = $rev->getContent( 'main' );
193 $this->assertSame( 'Lorem Ipsum', $revContent->serialize(), 'revision content' );
194
195 // were the WikiPage and Title objects updated?
196 $this->assertTrue( $page->exists(), 'WikiPage::exists()' );
197 $this->assertTrue( $title->exists(), 'Title::exists()' );
198 $this->assertSame( $rev->getId(), $page->getLatest(), 'WikiPage::getRevision()' );
199 $this->assertNotNull( $page->getRevision(), 'WikiPage::getRevision()' );
200
201 // re-load
202 $page2 = WikiPage::factory( $title );
203 $this->assertTrue( $page2->exists(), 'WikiPage::exists()' );
204 $this->assertSame( $rev->getId(), $page2->getLatest(), 'WikiPage::getRevision()' );
205 $this->assertNotNull( $page2->getRevision(), 'WikiPage::getRevision()' );
206
207 // Check RC entry
208 $rc = $this->getRecentChangeFor( $rev->getId() );
209 $this->assertNotNull( $rc, 'RecentChange' );
210
211 // re-edit
212 $updater = $page->newPageUpdater( $user );
213 $updater->setContent( 'main', new TextContent( 'dolor sit amet' ) );
214
215 $summary = CommentStoreComment::newUnsavedComment( 're-edit' );
216 $updater->saveRevision( $summary );
217 $this->assertTrue( $updater->wasSuccessful(), 'wasSuccessful()' );
218 $this->assertTrue( $updater->getStatus()->isOK(), 'getStatus()->isOK()' );
219
220 // check site stats - this asserts that derived data updates where run.
221 $stats = $this->db->selectRow( 'site_stats', '*', '1=1' );
222 $this->assertNotNull( $stats, 'site_stats' );
223 $this->assertSame( $oldStats->ss_total_pages + 0, (int)$stats->ss_total_pages );
224 $this->assertSame( $oldStats->ss_total_edits + 2, (int)$stats->ss_total_edits );
225 }
226
227 /**
228 * Creates a revision in the database.
229 *
230 * @param WikiPage $page
231 * @param $summary
232 * @param null|string|Content $content
233 *
234 * @return RevisionRecord|null
235 */
236 private function createRevision( WikiPage $page, $summary, $content = null ) {
237 $user = $this->getTestUser()->getUser();
238 $comment = CommentStoreComment::newUnsavedComment( $summary );
239
240 if ( !$content instanceof Content ) {
241 $content = new TextContent( $content ?? $summary );
242 }
243
244 $updater = $page->newPageUpdater( $user );
245 $updater->setContent( 'main', $content );
246 $rev = $updater->saveRevision( $comment );
247 return $rev;
248 }
249
250 /**
251 * @covers \MediaWiki\Storage\PageUpdater::grabParentRevision()
252 * @covers \MediaWiki\Storage\PageUpdater::saveRevision()
253 */
254 public function testCompareAndSwapFailure() {
255 $user = $this->getTestUser()->getUser();
256
257 $title = $this->getDummyTitle( __METHOD__ );
258
259 // start editing non-existing page
260 $page = WikiPage::factory( $title );
261 $updater = $page->newPageUpdater( $user );
262 $updater->grabParentRevision();
263
264 // create page concurrently
265 $concurrentPage = WikiPage::factory( $title );
266 $this->createRevision( $concurrentPage, __METHOD__ . '-one' );
267
268 // try creating the page - should trigger CAS failure.
269 $summary = CommentStoreComment::newUnsavedComment( 'create?!' );
270 $updater->setContent( 'main', new TextContent( 'Lorem ipsum' ) );
271 $updater->saveRevision( $summary );
272 $status = $updater->getStatus();
273
274 $this->assertFalse( $updater->wasSuccessful(), 'wasSuccessful()' );
275 $this->assertNull( $updater->getNewRevision(), 'getNewRevision()' );
276 $this->assertFalse( $status->isOK(), 'getStatus()->isOK()' );
277 $this->assertTrue( $status->hasMessage( 'edit-already-exists' ), 'edit-conflict' );
278
279 // start editing existing page
280 $page = WikiPage::factory( $title );
281 $updater = $page->newPageUpdater( $user );
282 $updater->grabParentRevision();
283
284 // update page concurrently
285 $concurrentPage = WikiPage::factory( $title );
286 $this->createRevision( $concurrentPage, __METHOD__ . '-two' );
287
288 // try creating the page - should trigger CAS failure.
289 $summary = CommentStoreComment::newUnsavedComment( 'edit?!' );
290 $updater->setContent( 'main', new TextContent( 'dolor sit amet' ) );
291 $updater->saveRevision( $summary );
292 $status = $updater->getStatus();
293
294 $this->assertFalse( $updater->wasSuccessful(), 'wasSuccessful()' );
295 $this->assertNull( $updater->getNewRevision(), 'getNewRevision()' );
296 $this->assertFalse( $status->isOK(), 'getStatus()->isOK()' );
297 $this->assertTrue( $status->hasMessage( 'edit-conflict' ), 'edit-conflict' );
298 }
299
300 /**
301 * @covers \MediaWiki\Storage\PageUpdater::saveRevision()
302 */
303 public function testFailureOnEditFlags() {
304 $user = $this->getTestUser()->getUser();
305
306 $title = $this->getDummyTitle( __METHOD__ );
307
308 // start editing non-existing page
309 $page = WikiPage::factory( $title );
310 $updater = $page->newPageUpdater( $user );
311
312 // update with EDIT_UPDATE flag should fail
313 $summary = CommentStoreComment::newUnsavedComment( 'udpate?!' );
314 $updater->setContent( 'main', new TextContent( 'Lorem ipsum' ) );
315 $updater->saveRevision( $summary, EDIT_UPDATE );
316 $status = $updater->getStatus();
317
318 $this->assertFalse( $updater->wasSuccessful(), 'wasSuccessful()' );
319 $this->assertNull( $updater->getNewRevision(), 'getNewRevision()' );
320 $this->assertFalse( $status->isOK(), 'getStatus()->isOK()' );
321 $this->assertTrue( $status->hasMessage( 'edit-gone-missing' ), 'edit-gone-missing' );
322
323 // create the page
324 $this->createRevision( $page, __METHOD__ );
325
326 // update with EDIT_NEW flag should fail
327 $summary = CommentStoreComment::newUnsavedComment( 'create?!' );
328 $updater = $page->newPageUpdater( $user );
329 $updater->setContent( 'main', new TextContent( 'dolor sit amet' ) );
330 $updater->saveRevision( $summary, EDIT_NEW );
331 $status = $updater->getStatus();
332
333 $this->assertFalse( $updater->wasSuccessful(), 'wasSuccessful()' );
334 $this->assertNull( $updater->getNewRevision(), 'getNewRevision()' );
335 $this->assertFalse( $status->isOK(), 'getStatus()->isOK()' );
336 $this->assertTrue( $status->hasMessage( 'edit-already-exists' ), 'edit-already-exists' );
337 }
338
339 public function provideSetRcPatrolStatus( $patrolled ) {
340 yield [ RecentChange::PRC_UNPATROLLED ];
341 yield [ RecentChange::PRC_AUTOPATROLLED ];
342 }
343
344 /**
345 * @dataProvider provideSetRcPatrolStatus
346 * @covers \MediaWiki\Storage\PageUpdater::setRcPatrolStatus()
347 */
348 public function testSetRcPatrolStatus( $patrolled ) {
349 $revisionStore = MediaWikiServices::getInstance()->getRevisionStore();
350
351 $user = $this->getTestUser()->getUser();
352
353 $title = $this->getDummyTitle( __METHOD__ );
354
355 $page = WikiPage::factory( $title );
356 $updater = $page->newPageUpdater( $user );
357
358 $summary = CommentStoreComment::newUnsavedComment( 'Lorem ipsum ' . $patrolled );
359 $updater->setContent( 'main', new TextContent( 'Lorem ipsum ' . $patrolled ) );
360 $updater->setRcPatrolStatus( $patrolled );
361 $rev = $updater->saveRevision( $summary );
362
363 $rc = $revisionStore->getRecentChange( $rev );
364 $this->assertEquals( $patrolled, $rc->getAttribute( 'rc_patrolled' ) );
365 }
366
367 /**
368 * @covers \MediaWiki\Storage\PageUpdater::inheritSlot()
369 * @covers \MediaWiki\Storage\PageUpdater::setContent()
370 */
371 public function testInheritSlot() {
372 $user = $this->getTestUser()->getUser();
373 $title = $this->getDummyTitle( __METHOD__ );
374 $page = WikiPage::factory( $title );
375
376 $updater = $page->newPageUpdater( $user );
377 $summary = CommentStoreComment::newUnsavedComment( 'one' );
378 $updater->setContent( 'main', new TextContent( 'Lorem ipsum' ) );
379 $rev1 = $updater->saveRevision( $summary, EDIT_NEW );
380
381 $updater = $page->newPageUpdater( $user );
382 $summary = CommentStoreComment::newUnsavedComment( 'two' );
383 $updater->setContent( 'main', new TextContent( 'Foo Bar' ) );
384 $rev2 = $updater->saveRevision( $summary, EDIT_UPDATE );
385
386 $updater = $page->newPageUpdater( $user );
387 $summary = CommentStoreComment::newUnsavedComment( 'three' );
388 $updater->inheritSlot( $rev1->getSlot( 'main' ) );
389 $rev3 = $updater->saveRevision( $summary, EDIT_UPDATE );
390
391 $this->assertNotSame( $rev1->getId(), $rev3->getId() );
392 $this->assertNotSame( $rev2->getId(), $rev3->getId() );
393
394 $main1 = $rev1->getSlot( 'main' );
395 $main3 = $rev3->getSlot( 'main' );
396
397 $this->assertNotSame( $main1->getRevision(), $main3->getRevision() );
398 $this->assertSame( $main1->getAddress(), $main3->getAddress() );
399 $this->assertTrue( $main1->getContent()->equals( $main3->getContent() ) );
400 }
401
402 // TODO: MCR: test adding multiple slots, inheriting parent slots, and removing slots.
403
404 public function testSetUseAutomaticEditSummaries() {
405 $this->setContentLang( 'qqx' );
406 $user = $this->getTestUser()->getUser();
407
408 $title = $this->getDummyTitle( __METHOD__ );
409 $page = WikiPage::factory( $title );
410
411 $updater = $page->newPageUpdater( $user );
412 $updater->setUseAutomaticEditSummaries( true );
413 $updater->setContent( 'main', new TextContent( 'Lorem Ipsum' ) );
414
415 // empty comment triggers auto-summary
416 $summary = CommentStoreComment::newUnsavedComment( '' );
417 $updater->saveRevision( $summary, EDIT_AUTOSUMMARY );
418
419 $rev = $updater->getNewRevision();
420 $comment = $rev->getComment( RevisionRecord::RAW );
421 $this->assertSame( '(autosumm-new: Lorem Ipsum)', $comment->text, 'comment text' );
422
423 // check that this also works when blanking the page
424 $updater = $page->newPageUpdater( $user );
425 $updater->setUseAutomaticEditSummaries( true );
426 $updater->setContent( 'main', new TextContent( '' ) );
427
428 $summary = CommentStoreComment::newUnsavedComment( '' );
429 $updater->saveRevision( $summary, EDIT_AUTOSUMMARY );
430
431 $rev = $updater->getNewRevision();
432 $comment = $rev->getComment( RevisionRecord::RAW );
433 $this->assertSame( '(autosumm-blank)', $comment->text, 'comment text' );
434
435 // check that we can also disable edit-summaries
436 $title2 = $this->getDummyTitle( __METHOD__ . '/2' );
437 $page2 = WikiPage::factory( $title2 );
438
439 $updater = $page2->newPageUpdater( $user );
440 $updater->setUseAutomaticEditSummaries( false );
441 $updater->setContent( 'main', new TextContent( 'Lorem Ipsum' ) );
442
443 $summary = CommentStoreComment::newUnsavedComment( '' );
444 $updater->saveRevision( $summary, EDIT_AUTOSUMMARY );
445
446 $rev = $updater->getNewRevision();
447 $comment = $rev->getComment( RevisionRecord::RAW );
448 $this->assertSame( '', $comment->text, 'comment text should still be lank' );
449
450 // check that we don't do auto.summaries without the EDIT_AUTOSUMMARY flag
451 $updater = $page2->newPageUpdater( $user );
452 $updater->setUseAutomaticEditSummaries( true );
453 $updater->setContent( 'main', new TextContent( '' ) );
454
455 $summary = CommentStoreComment::newUnsavedComment( '' );
456 $updater->saveRevision( $summary, 0 );
457
458 $rev = $updater->getNewRevision();
459 $comment = $rev->getComment( RevisionRecord::RAW );
460 $this->assertSame( '', $comment->text, 'comment text' );
461 }
462
463 public function provideSetUsePageCreationLog() {
464 yield [ true, [ [ 'create', 'create' ] ] ];
465 yield [ false, [] ];
466 }
467
468 /**
469 * @dataProvider provideSetUsePageCreationLog
470 * @param bool $use
471 */
472 public function testSetUsePageCreationLog( $use, $expected ) {
473 $user = $this->getTestUser()->getUser();
474 $title = $this->getDummyTitle( __METHOD__ . ( $use ? '_logged' : '_unlogged' ) );
475 $page = WikiPage::factory( $title );
476
477 $updater = $page->newPageUpdater( $user );
478 $updater->setUsePageCreationLog( $use );
479 $summary = CommentStoreComment::newUnsavedComment( 'cmt' );
480 $updater->setContent( 'main', new TextContent( 'Lorem Ipsum' ) );
481 $updater->saveRevision( $summary, EDIT_NEW );
482
483 $rev = $updater->getNewRevision();
484 $this->assertSelect(
485 'logging',
486 [ 'log_type', 'log_action' ],
487 [ 'log_page' => $rev->getPageId() ],
488 $expected
489 );
490 }
491
492 public function provideMagicWords() {
493 yield 'PAGEID' => [
494 'Test {{PAGEID}} Test',
495 function ( RevisionRecord $rev ) {
496 return $rev->getPageId();
497 }
498 ];
499
500 yield 'REVISIONID' => [
501 'Test {{REVISIONID}} Test',
502 function ( RevisionRecord $rev ) {
503 return $rev->getId();
504 }
505 ];
506
507 yield 'REVISIONUSER' => [
508 'Test {{REVISIONUSER}} Test',
509 function ( RevisionRecord $rev ) {
510 return $rev->getUser()->getName();
511 }
512 ];
513
514 yield 'REVISIONTIMESTAMP' => [
515 'Test {{REVISIONTIMESTAMP}} Test',
516 function ( RevisionRecord $rev ) {
517 return $rev->getTimestamp();
518 }
519 ];
520
521 yield 'subst:REVISIONUSER' => [
522 'Test {{subst:REVISIONUSER}} Test',
523 function ( RevisionRecord $rev ) {
524 return $rev->getUser()->getName();
525 },
526 'subst'
527 ];
528
529 yield 'subst:PAGENAME' => [
530 'Test {{subst:PAGENAME}} Test',
531 function ( RevisionRecord $rev ) {
532 return 'PageUpdaterTest::testMagicWords';
533 },
534 'subst'
535 ];
536 }
537
538 /**
539 * @covers \MediaWiki\Storage\PageUpdater::saveRevision()
540 *
541 * Integration test for PageUpdater, DerivedPageDataUpdater, RevisionRenderer
542 * and RenderedRevision, that ensures that magic words depending on revision meta-data
543 * are handled correctly. Note that each magic word needs to be tested separately,
544 * to assert correct behavior for each "vary" flag in the ParserOutput.
545 *
546 * @dataProvider provideMagicWords
547 */
548 public function testMagicWords( $wikitext, $callback, $subst = false ) {
549 $user = User::newFromName( 'A user for ' . __METHOD__ );
550 $user->addToDatabase();
551
552 $title = $this->getDummyTitle( __METHOD__ . '-' . $this->getName() );
553 $this->insertPage( $title );
554
555 $page = WikiPage::factory( $title );
556 $updater = $page->newPageUpdater( $user );
557
558 $updater->setContent( 'main', new \WikitextContent( $wikitext ) );
559
560 $summary = CommentStoreComment::newUnsavedComment( 'Just a test' );
561 $rev = $updater->saveRevision( $summary, EDIT_UPDATE );
562
563 if ( !$rev ) {
564 $this->fail( $updater->getStatus()->getWikiText() );
565 }
566
567 $expected = strval( $callback( $rev ) );
568
569 $output = $page->getParserOutput( ParserOptions::newCanonical( 'canonical' ) );
570 $html = $output->getText();
571 $text = $rev->getContent( 'main' )->serialize();
572
573 if ( $subst ) {
574 $this->assertContains( $expected, $text, 'In Wikitext' );
575 }
576
577 $this->assertContains( $expected, $html, 'In HTML' );
578 }
579
580 }