7 * @covers ApiComparePages
9 class ApiComparePagesTest
extends ApiTestCase
{
11 protected static $repl = [];
13 protected function addPage( $page, $text, $model = CONTENT_MODEL_WIKITEXT
) {
14 $title = Title
::newFromText( 'ApiComparePagesTest ' . $page );
15 $content = ContentHandler
::makeContent( $text, $title, $model );
17 $page = WikiPage
::factory( $title );
18 $user = static::getTestSysop()->getUser();
19 $status = $page->doEditContent(
20 $content, 'Test for ApiComparePagesTest: ' . $text, 0, false, $user
22 if ( !$status->isOK() ) {
23 $this->fail( "Failed to create $title: " . $status->getWikiText( false, false, 'en' ) );
25 return $status->value
['revision']->getId();
28 public function addDBDataOnce() {
29 $user = static::getTestSysop()->getUser();
30 self
::$repl['creator'] = $user->getName();
31 self
::$repl['creatorid'] = $user->getId();
33 self
::$repl['revA1'] = $this->addPage( 'A', 'A 1' );
34 self
::$repl['revA2'] = $this->addPage( 'A', 'A 2' );
35 self
::$repl['revA3'] = $this->addPage( 'A', 'A 3' );
36 self
::$repl['revA4'] = $this->addPage( 'A', 'A 4' );
37 self
::$repl['pageA'] = Title
::newFromText( 'ApiComparePagesTest A' )->getArticleID();
39 self
::$repl['revB1'] = $this->addPage( 'B', 'B 1' );
40 self
::$repl['revB2'] = $this->addPage( 'B', 'B 2' );
41 self
::$repl['revB3'] = $this->addPage( 'B', 'B 3' );
42 self
::$repl['revB4'] = $this->addPage( 'B', 'B 4' );
43 self
::$repl['pageB'] = Title
::newFromText( 'ApiComparePagesTest B' )->getArticleID();
45 self
::$repl['revC1'] = $this->addPage( 'C', 'C 1' );
46 self
::$repl['revC2'] = $this->addPage( 'C', 'C 2' );
47 self
::$repl['revC3'] = $this->addPage( 'C', 'C 3' );
48 self
::$repl['pageC'] = Title
::newFromText( 'ApiComparePagesTest C' )->getArticleID();
50 $id = $this->addPage( 'D', 'D 1' );
51 self
::$repl['pageD'] = Title
::newFromText( 'ApiComparePagesTest D' )->getArticleID();
52 wfGetDB( DB_MASTER
)->delete( 'revision', [ 'rev_id' => $id ] );
54 self
::$repl['revE1'] = $this->addPage( 'E', 'E 1' );
55 self
::$repl['revE2'] = $this->addPage( 'E', 'E 2' );
56 self
::$repl['revE3'] = $this->addPage( 'E', 'E 3' );
57 self
::$repl['revE4'] = $this->addPage( 'E', 'E 4' );
58 self
::$repl['pageE'] = Title
::newFromText( 'ApiComparePagesTest E' )->getArticleID();
59 wfGetDB( DB_MASTER
)->update(
60 'page', [ 'page_latest' => 0 ], [ 'page_id' => self
::$repl['pageE'] ]
63 self
::$repl['revF1'] = $this->addPage( 'F', "== Section 1 ==\nF 1.1\n\n== Section 2 ==\nF 1.2" );
64 self
::$repl['pageF'] = Title
::newFromText( 'ApiComparePagesTest F' )->getArticleID();
66 self
::$repl['revG1'] = $this->addPage( 'G', "== Section 1 ==\nG 1.1", CONTENT_MODEL_TEXT
);
67 self
::$repl['pageG'] = Title
::newFromText( 'ApiComparePagesTest G' )->getArticleID();
69 WikiPage
::factory( Title
::newFromText( 'ApiComparePagesTest C' ) )
70 ->doDeleteArticleReal( 'Test for ApiComparePagesTest' );
72 RevisionDeleter
::createList(
74 RequestContext
::getMain(),
75 Title
::newFromText( 'ApiComparePagesTest B' ),
76 [ self
::$repl['revB2'] ]
79 Revision
::DELETED_TEXT
=> 1,
80 Revision
::DELETED_USER
=> 1,
81 Revision
::DELETED_COMMENT
=> 1,
83 'comment' => 'Test for ApiComparePages',
86 RevisionDeleter
::createList(
88 RequestContext
::getMain(),
89 Title
::newFromText( 'ApiComparePagesTest B' ),
90 [ self
::$repl['revB3'] ]
93 Revision
::DELETED_USER
=> 1,
94 Revision
::DELETED_COMMENT
=> 1,
95 Revision
::DELETED_RESTRICTED
=> 1,
97 'comment' => 'Test for ApiComparePages',
100 Title
::clearCaches(); // Otherwise it has the wrong latest revision for some reason
103 protected function doReplacements( &$value ) {
104 if ( is_string( $value ) ) {
105 if ( preg_match( '/^{{REPL:(.+?)}}$/', $value, $m ) ) {
106 $value = self
::$repl[$m[1]];
108 $value = preg_replace_callback( '/{{REPL:(.+?)}}/', function ( $m ) {
109 return self
::$repl[$m[1]] ??
$m[0];
112 } elseif ( is_array( $value ) ||
is_object( $value ) ) {
113 foreach ( $value as &$v ) {
114 $this->doReplacements( $v );
121 * @dataProvider provideDiff
123 public function testDiff( $params, $expect, $exceptionCode = false, $sysop = false ) {
124 $this->setMwGlobals( [ 'wgDiffEngine' => 'php' ] );
126 $this->doReplacements( $params );
129 'action' => 'compare',
130 'errorformat' => 'none',
134 ?
static::getTestSysop()->getUser()
135 : static::getTestUser()->getUser();
136 if ( $exceptionCode ) {
138 $this->doApiRequest( $params, null, false, $user );
139 $this->fail( 'Expected exception not thrown' );
140 } catch ( ApiUsageException
$ex ) {
141 $this->assertTrue( $this->apiExceptionHasCode( $ex, $exceptionCode ),
142 "Exception with code $exceptionCode" );
145 $apiResult = $this->doApiRequest( $params, null, false, $user );
146 $apiResult = $apiResult[0];
147 $this->doReplacements( $expect );
148 $this->assertEquals( $expect, $apiResult );
152 private static function makeDeprecationWarnings( ...$params ) {
154 foreach ( $params as $p ) {
156 'code' => 'deprecation',
157 'data' => [ 'feature' => "action=compare&{$p}" ],
158 'module' => 'compare',
160 if ( count( $warn ) === 1 ) {
162 'code' => 'deprecation-help',
171 public static function provideDiff() {
172 // phpcs:disable Generic.Files.LineLength.TooLong
174 'Basic diff, titles' => [
176 'fromtitle' => 'ApiComparePagesTest A',
177 'totitle' => 'ApiComparePagesTest B',
181 'fromid' => '{{REPL:pageA}}',
182 'fromrevid' => '{{REPL:revA4}}',
184 'fromtitle' => 'ApiComparePagesTest A',
185 'toid' => '{{REPL:pageB}}',
186 'torevid' => '{{REPL:revB4}}',
188 'totitle' => 'ApiComparePagesTest B',
189 'body' => '<tr><td colspan="2" class="diff-lineno" id="mw-diff-left-l1" >Line 1:</td>' . "\n"
190 . '<td colspan="2" class="diff-lineno">Line 1:</td></tr>' . "\n"
191 . '<tr><td class=\'diff-marker\'>−</td><td class=\'diff-deletedline\'><div><del class="diffchange diffchange-inline">A </del>4</div></td><td class=\'diff-marker\'>+</td><td class=\'diff-addedline\'><div><ins class="diffchange diffchange-inline">B </ins>4</div></td></tr>' . "\n",
195 'Basic diff, page IDs' => [
197 'fromid' => '{{REPL:pageA}}',
198 'toid' => '{{REPL:pageB}}',
202 'fromid' => '{{REPL:pageA}}',
203 'fromrevid' => '{{REPL:revA4}}',
205 'fromtitle' => 'ApiComparePagesTest A',
206 'toid' => '{{REPL:pageB}}',
207 'torevid' => '{{REPL:revB4}}',
209 'totitle' => 'ApiComparePagesTest B',
210 'body' => '<tr><td colspan="2" class="diff-lineno" id="mw-diff-left-l1" >Line 1:</td>' . "\n"
211 . '<td colspan="2" class="diff-lineno">Line 1:</td></tr>' . "\n"
212 . '<tr><td class=\'diff-marker\'>−</td><td class=\'diff-deletedline\'><div><del class="diffchange diffchange-inline">A </del>4</div></td><td class=\'diff-marker\'>+</td><td class=\'diff-addedline\'><div><ins class="diffchange diffchange-inline">B </ins>4</div></td></tr>' . "\n",
216 'Basic diff, revision IDs' => [
218 'fromrev' => '{{REPL:revA2}}',
219 'torev' => '{{REPL:revA3}}',
223 'fromid' => '{{REPL:pageA}}',
224 'fromrevid' => '{{REPL:revA2}}',
226 'fromtitle' => 'ApiComparePagesTest A',
227 'toid' => '{{REPL:pageA}}',
228 'torevid' => '{{REPL:revA3}}',
230 'totitle' => 'ApiComparePagesTest A',
231 'body' => '<tr><td colspan="2" class="diff-lineno" id="mw-diff-left-l1" >Line 1:</td>' . "\n"
232 . '<td colspan="2" class="diff-lineno">Line 1:</td></tr>' . "\n"
233 . '<tr><td class=\'diff-marker\'>−</td><td class=\'diff-deletedline\'><div>A <del class="diffchange diffchange-inline">2</del></div></td><td class=\'diff-marker\'>+</td><td class=\'diff-addedline\'><div>A <ins class="diffchange diffchange-inline">3</ins></div></td></tr>' . "\n",
237 'Basic diff, deleted revision ID as sysop' => [
239 'fromrev' => '{{REPL:revA2}}',
240 'torev' => '{{REPL:revC2}}',
244 'fromid' => '{{REPL:pageA}}',
245 'fromrevid' => '{{REPL:revA2}}',
247 'fromtitle' => 'ApiComparePagesTest A',
249 'torevid' => '{{REPL:revC2}}',
251 'totitle' => 'ApiComparePagesTest C',
253 'body' => '<tr><td colspan="2" class="diff-lineno" id="mw-diff-left-l1" >Line 1:</td>' . "\n"
254 . '<td colspan="2" class="diff-lineno">Line 1:</td></tr>' . "\n"
255 . '<tr><td class=\'diff-marker\'>−</td><td class=\'diff-deletedline\'><div><del class="diffchange diffchange-inline">A </del>2</div></td><td class=\'diff-marker\'>+</td><td class=\'diff-addedline\'><div><ins class="diffchange diffchange-inline">C </ins>2</div></td></tr>' . "\n",
260 'Basic diff, revdel as sysop' => [
262 'fromrev' => '{{REPL:revA2}}',
263 'torev' => '{{REPL:revB2}}',
267 'fromid' => '{{REPL:pageA}}',
268 'fromrevid' => '{{REPL:revA2}}',
270 'fromtitle' => 'ApiComparePagesTest A',
271 'toid' => '{{REPL:pageB}}',
272 'torevid' => '{{REPL:revB2}}',
274 'totitle' => 'ApiComparePagesTest B',
275 'totexthidden' => true,
276 'touserhidden' => true,
277 'tocommenthidden' => true,
278 'body' => '<tr><td colspan="2" class="diff-lineno" id="mw-diff-left-l1" >Line 1:</td>' . "\n"
279 . '<td colspan="2" class="diff-lineno">Line 1:</td></tr>' . "\n"
280 . '<tr><td class=\'diff-marker\'>−</td><td class=\'diff-deletedline\'><div><del class="diffchange diffchange-inline">A </del>2</div></td><td class=\'diff-marker\'>+</td><td class=\'diff-addedline\'><div><ins class="diffchange diffchange-inline">B </ins>2</div></td></tr>' . "\n",
285 'Basic diff, text' => [
287 'fromslots' => 'main',
288 'fromtext-main' => 'From text',
289 'fromcontentmodel-main' => 'wikitext',
291 'totext-main' => 'To text {{subst:PAGENAME}}',
292 'tocontentmodel-main' => 'wikitext',
296 'body' => '<tr><td colspan="2" class="diff-lineno" id="mw-diff-left-l1" >Line 1:</td>' . "\n"
297 . '<td colspan="2" class="diff-lineno">Line 1:</td></tr>' . "\n"
298 . '<tr><td class=\'diff-marker\'>−</td><td class=\'diff-deletedline\'><div><del class="diffchange diffchange-inline">From </del>text</div></td><td class=\'diff-marker\'>+</td><td class=\'diff-addedline\'><div><ins class="diffchange diffchange-inline">To </ins>text <ins class="diffchange diffchange-inline">{{subst:PAGENAME}}</ins></div></td></tr>' . "\n",
302 'Basic diff, text 2' => [
304 'fromslots' => 'main',
305 'fromtext-main' => 'From text',
307 'totext-main' => 'To text {{subst:PAGENAME}}',
308 'tocontentmodel-main' => 'wikitext',
312 'body' => '<tr><td colspan="2" class="diff-lineno" id="mw-diff-left-l1" >Line 1:</td>' . "\n"
313 . '<td colspan="2" class="diff-lineno">Line 1:</td></tr>' . "\n"
314 . '<tr><td class=\'diff-marker\'>−</td><td class=\'diff-deletedline\'><div><del class="diffchange diffchange-inline">From </del>text</div></td><td class=\'diff-marker\'>+</td><td class=\'diff-addedline\'><div><ins class="diffchange diffchange-inline">To </ins>text <ins class="diffchange diffchange-inline">{{subst:PAGENAME}}</ins></div></td></tr>' . "\n",
318 'Basic diff, guessed model' => [
320 'fromslots' => 'main',
321 'fromtext-main' => 'From text',
323 'totext-main' => 'To text',
326 'warnings' => [ [ 'code' => 'compare-nocontentmodel', 'module' => 'compare' ] ],
328 'body' => '<tr><td colspan="2" class="diff-lineno" id="mw-diff-left-l1" >Line 1:</td>' . "\n"
329 . '<td colspan="2" class="diff-lineno">Line 1:</td></tr>' . "\n"
330 . '<tr><td class=\'diff-marker\'>−</td><td class=\'diff-deletedline\'><div><del class="diffchange diffchange-inline">From </del>text</div></td><td class=\'diff-marker\'>+</td><td class=\'diff-addedline\'><div><ins class="diffchange diffchange-inline">To </ins>text</div></td></tr>' . "\n",
334 'Basic diff, text with title and PST' => [
336 'fromslots' => 'main',
337 'fromtext-main' => 'From text',
340 'totext-main' => 'To text {{subst:PAGENAME}}',
345 'body' => '<tr><td colspan="2" class="diff-lineno" id="mw-diff-left-l1" >Line 1:</td>' . "\n"
346 . '<td colspan="2" class="diff-lineno">Line 1:</td></tr>' . "\n"
347 . '<tr><td class=\'diff-marker\'>−</td><td class=\'diff-deletedline\'><div><del class="diffchange diffchange-inline">From </del>text</div></td><td class=\'diff-marker\'>+</td><td class=\'diff-addedline\'><div><ins class="diffchange diffchange-inline">To </ins>text <ins class="diffchange diffchange-inline">Test</ins></div></td></tr>' . "\n",
351 'Basic diff, text with page ID and PST' => [
353 'fromslots' => 'main',
354 'fromtext-main' => 'From text',
355 'toid' => '{{REPL:pageB}}',
357 'totext-main' => 'To text {{subst:PAGENAME}}',
362 'body' => '<tr><td colspan="2" class="diff-lineno" id="mw-diff-left-l1" >Line 1:</td>' . "\n"
363 . '<td colspan="2" class="diff-lineno">Line 1:</td></tr>' . "\n"
364 . '<tr><td class=\'diff-marker\'>−</td><td class=\'diff-deletedline\'><div><del class="diffchange diffchange-inline">From </del>text</div></td><td class=\'diff-marker\'>+</td><td class=\'diff-addedline\'><div><ins class="diffchange diffchange-inline">To </ins>text <ins class="diffchange diffchange-inline">ApiComparePagesTest B</ins></div></td></tr>' . "\n",
368 'Basic diff, text with revision and PST' => [
370 'fromslots' => 'main',
371 'fromtext-main' => 'From text',
372 'torev' => '{{REPL:revB2}}',
374 'totext-main' => 'To text {{subst:PAGENAME}}',
379 'body' => '<tr><td colspan="2" class="diff-lineno" id="mw-diff-left-l1" >Line 1:</td>' . "\n"
380 . '<td colspan="2" class="diff-lineno">Line 1:</td></tr>' . "\n"
381 . '<tr><td class=\'diff-marker\'>−</td><td class=\'diff-deletedline\'><div><del class="diffchange diffchange-inline">From </del>text</div></td><td class=\'diff-marker\'>+</td><td class=\'diff-addedline\'><div><ins class="diffchange diffchange-inline">To </ins>text <ins class="diffchange diffchange-inline">ApiComparePagesTest B</ins></div></td></tr>' . "\n",
385 'Basic diff, text with deleted revision and PST' => [
387 'fromslots' => 'main',
388 'fromtext-main' => 'From text',
389 'torev' => '{{REPL:revC2}}',
391 'totext-main' => 'To text {{subst:PAGENAME}}',
396 'body' => '<tr><td colspan="2" class="diff-lineno" id="mw-diff-left-l1" >Line 1:</td>' . "\n"
397 . '<td colspan="2" class="diff-lineno">Line 1:</td></tr>' . "\n"
398 . '<tr><td class=\'diff-marker\'>−</td><td class=\'diff-deletedline\'><div><del class="diffchange diffchange-inline">From </del>text</div></td><td class=\'diff-marker\'>+</td><td class=\'diff-addedline\'><div><ins class="diffchange diffchange-inline">To </ins>text <ins class="diffchange diffchange-inline">ApiComparePagesTest C</ins></div></td></tr>' . "\n",
403 'Basic diff, test with sections' => [
405 'fromtitle' => 'ApiComparePagesTest F',
406 'fromslots' => 'main',
407 'fromtext-main' => "== Section 2 ==\nFrom text?",
408 'fromsection-main' => 2,
409 'totitle' => 'ApiComparePagesTest F',
411 'totext-main' => "== Section 1 ==\nTo text?",
412 'tosection-main' => 1,
416 'body' => '<tr><td colspan="2" class="diff-lineno" id="mw-diff-left-l1" >Line 1:</td>' . "\n"
417 . '<td colspan="2" class="diff-lineno">Line 1:</td></tr>' . "\n"
418 . '<tr><td class=\'diff-marker\'>Â </td><td class=\'diff-context\'><div>== Section 1 ==</div></td><td class=\'diff-marker\'>Â </td><td class=\'diff-context\'><div>== Section 1 ==</div></td></tr>' . "\n"
419 . '<tr><td class=\'diff-marker\'>−</td><td class=\'diff-deletedline\'><div><del class="diffchange diffchange-inline">F 1.1</del></div></td><td class=\'diff-marker\'>+</td><td class=\'diff-addedline\'><div><ins class="diffchange diffchange-inline">To text?</ins></div></td></tr>' . "\n"
420 . '<tr><td class=\'diff-marker\'>Â </td><td class=\'diff-context\'></td><td class=\'diff-marker\'>Â </td><td class=\'diff-context\'></td></tr>' . "\n"
421 . '<tr><td class=\'diff-marker\'>Â </td><td class=\'diff-context\'><div>== Section 2 ==</div></td><td class=\'diff-marker\'>Â </td><td class=\'diff-context\'><div>== Section 2 ==</div></td></tr>' . "\n"
422 . '<tr><td class=\'diff-marker\'>−</td><td class=\'diff-deletedline\'><div><del class="diffchange diffchange-inline">From text?</del></div></td><td class=\'diff-marker\'>+</td><td class=\'diff-addedline\'><div><ins class="diffchange diffchange-inline">F 1.2</ins></div></td></tr>' . "\n",
426 'Diff with all props' => [
428 'fromrev' => '{{REPL:revB1}}',
429 'torev' => '{{REPL:revB3}}',
430 'totitle' => 'ApiComparePagesTest B',
431 'prop' => 'diff|diffsize|rel|ids|title|user|comment|parsedcomment|size'
435 'fromid' => '{{REPL:pageB}}',
436 'fromrevid' => '{{REPL:revB1}}',
438 'fromtitle' => 'ApiComparePagesTest B',
440 'fromuser' => '{{REPL:creator}}',
441 'fromuserid' => '{{REPL:creatorid}}',
442 'fromcomment' => 'Test for ApiComparePagesTest: B 1',
443 'fromparsedcomment' => 'Test for ApiComparePagesTest: B 1',
444 'toid' => '{{REPL:pageB}}',
445 'torevid' => '{{REPL:revB3}}',
447 'totitle' => 'ApiComparePagesTest B',
449 'touserhidden' => true,
450 'tocommenthidden' => true,
451 'tosuppressed' => true,
452 'next' => '{{REPL:revB4}}',
454 'body' => '<tr><td colspan="2" class="diff-lineno" id="mw-diff-left-l1" >Line 1:</td>' . "\n"
455 . '<td colspan="2" class="diff-lineno">Line 1:</td></tr>' . "\n"
456 . '<tr><td class=\'diff-marker\'>−</td><td class=\'diff-deletedline\'><div>B <del class="diffchange diffchange-inline">1</del></div></td><td class=\'diff-marker\'>+</td><td class=\'diff-addedline\'><div>B <ins class="diffchange diffchange-inline">3</ins></div></td></tr>' . "\n",
460 'Diff with all props as sysop' => [
462 'fromrev' => '{{REPL:revB2}}',
463 'torev' => '{{REPL:revB3}}',
464 'totitle' => 'ApiComparePagesTest B',
465 'prop' => 'diff|diffsize|rel|ids|title|user|comment|parsedcomment|size'
469 'fromid' => '{{REPL:pageB}}',
470 'fromrevid' => '{{REPL:revB2}}',
472 'fromtitle' => 'ApiComparePagesTest B',
474 'fromtexthidden' => true,
475 'fromuserhidden' => true,
476 'fromuser' => '{{REPL:creator}}',
477 'fromuserid' => '{{REPL:creatorid}}',
478 'fromcommenthidden' => true,
479 'fromcomment' => 'Test for ApiComparePagesTest: B 2',
480 'fromparsedcomment' => 'Test for ApiComparePagesTest: B 2',
481 'toid' => '{{REPL:pageB}}',
482 'torevid' => '{{REPL:revB3}}',
484 'totitle' => 'ApiComparePagesTest B',
486 'touserhidden' => true,
487 'tocommenthidden' => true,
488 'tosuppressed' => true,
489 'prev' => '{{REPL:revB1}}',
490 'next' => '{{REPL:revB4}}',
492 'body' => '<tr><td colspan="2" class="diff-lineno" id="mw-diff-left-l1" >Line 1:</td>' . "\n"
493 . '<td colspan="2" class="diff-lineno">Line 1:</td></tr>' . "\n"
494 . '<tr><td class=\'diff-marker\'>−</td><td class=\'diff-deletedline\'><div>B <del class="diffchange diffchange-inline">2</del></div></td><td class=\'diff-marker\'>+</td><td class=\'diff-addedline\'><div>B <ins class="diffchange diffchange-inline">3</ins></div></td></tr>' . "\n",
499 'Relative diff, cur' => [
501 'fromrev' => '{{REPL:revA2}}',
502 'torelative' => 'cur',
507 'fromid' => '{{REPL:pageA}}',
508 'fromrevid' => '{{REPL:revA2}}',
509 'toid' => '{{REPL:pageA}}',
510 'torevid' => '{{REPL:revA4}}',
514 'Relative diff, next' => [
516 'fromrev' => '{{REPL:revE2}}',
517 'torelative' => 'next',
522 'fromid' => '{{REPL:pageE}}',
523 'fromrevid' => '{{REPL:revE2}}',
524 'toid' => '{{REPL:pageE}}',
525 'torevid' => '{{REPL:revE3}}',
526 'prev' => '{{REPL:revE1}}',
527 'next' => '{{REPL:revE4}}',
531 'Relative diff, prev' => [
533 'fromrev' => '{{REPL:revE3}}',
534 'torelative' => 'prev',
539 'fromid' => '{{REPL:pageE}}',
540 'fromrevid' => '{{REPL:revE2}}',
541 'toid' => '{{REPL:pageE}}',
542 'torevid' => '{{REPL:revE3}}',
543 'prev' => '{{REPL:revE1}}',
544 'next' => '{{REPL:revE4}}',
548 'Relative diff, no prev' => [
550 'fromrev' => '{{REPL:revA1}}',
551 'torelative' => 'prev',
552 'prop' => 'ids|rel|diff|title|user|comment',
557 'code' => 'compare-no-prev',
558 'module' => 'compare',
562 'toid' => '{{REPL:pageA}}',
563 'torevid' => '{{REPL:revA1}}',
565 'totitle' => 'ApiComparePagesTest A',
566 'touser' => '{{REPL:creator}}',
567 'touserid' => '{{REPL:creatorid}}',
568 'tocomment' => 'Test for ApiComparePagesTest: A 1',
569 'toparsedcomment' => 'Test for ApiComparePagesTest: A 1',
570 'next' => '{{REPL:revA2}}',
571 'body' => '<tr><td colspan="2" class="diff-lineno" id="mw-diff-left-l1" >Line 1:</td>' . "\n"
572 . '<td colspan="2" class="diff-lineno">Line 1:</td></tr>' . "\n"
573 . '<tr><td class=\'diff-marker\'>−</td><td class=\'diff-deletedline\'><div> </div></td><td class=\'diff-marker\'>+</td><td class=\'diff-addedline\'><div><ins class="diffchange diffchange-inline">A 1</ins></div></td></tr>' . "\n",
577 'Relative diff, no next' => [
579 'fromrev' => '{{REPL:revA4}}',
580 'torelative' => 'next',
581 'prop' => 'ids|rel|diff|title|user|comment',
586 'code' => 'compare-no-next',
587 'module' => 'compare',
591 'fromid' => '{{REPL:pageA}}',
592 'fromrevid' => '{{REPL:revA4}}',
594 'fromtitle' => 'ApiComparePagesTest A',
595 'fromuser' => '{{REPL:creator}}',
596 'fromuserid' => '{{REPL:creatorid}}',
597 'fromcomment' => 'Test for ApiComparePagesTest: A 4',
598 'fromparsedcomment' => 'Test for ApiComparePagesTest: A 4',
599 'prev' => '{{REPL:revA3}}',
604 'Diff for specific slots' => [
605 // @todo Use a page with multiple slots here
607 'fromrev' => '{{REPL:revA1}}',
608 'torev' => '{{REPL:revA3}}',
615 'main' => '<tr><td colspan="2" class="diff-lineno" id="mw-diff-left-l1" >Line 1:</td>' . "\n"
616 . '<td colspan="2" class="diff-lineno">Line 1:</td></tr>' . "\n"
617 . '<tr><td class=\'diff-marker\'>−</td><td class=\'diff-deletedline\'><div>A <del class="diffchange diffchange-inline">1</del></div></td><td class=\'diff-marker\'>+</td><td class=\'diff-addedline\'><div>A <ins class="diffchange diffchange-inline">3</ins></div></td></tr>' . "\n",
622 // @todo Add a test for diffing with a deleted slot. Deleting 'main' doesn't work.
624 'Basic diff, deprecated text' => [
626 'fromtext' => 'From text',
627 'fromcontentmodel' => 'wikitext',
628 'totext' => 'To text {{subst:PAGENAME}}',
629 'tocontentmodel' => 'wikitext',
632 'warnings' => self
::makeDeprecationWarnings( 'fromtext', 'fromcontentmodel', 'totext', 'tocontentmodel' ),
634 'body' => '<tr><td colspan="2" class="diff-lineno" id="mw-diff-left-l1" >Line 1:</td>' . "\n"
635 . '<td colspan="2" class="diff-lineno">Line 1:</td></tr>' . "\n"
636 . '<tr><td class=\'diff-marker\'>−</td><td class=\'diff-deletedline\'><div><del class="diffchange diffchange-inline">From </del>text</div></td><td class=\'diff-marker\'>+</td><td class=\'diff-addedline\'><div><ins class="diffchange diffchange-inline">To </ins>text <ins class="diffchange diffchange-inline">{{subst:PAGENAME}}</ins></div></td></tr>' . "\n",
640 'Basic diff, deprecated text 2' => [
642 'fromtext' => 'From text',
643 'totext' => 'To text {{subst:PAGENAME}}',
644 'tocontentmodel' => 'wikitext',
647 'warnings' => self
::makeDeprecationWarnings( 'fromtext', 'totext', 'tocontentmodel' ),
649 'body' => '<tr><td colspan="2" class="diff-lineno" id="mw-diff-left-l1" >Line 1:</td>' . "\n"
650 . '<td colspan="2" class="diff-lineno">Line 1:</td></tr>' . "\n"
651 . '<tr><td class=\'diff-marker\'>−</td><td class=\'diff-deletedline\'><div><del class="diffchange diffchange-inline">From </del>text</div></td><td class=\'diff-marker\'>+</td><td class=\'diff-addedline\'><div><ins class="diffchange diffchange-inline">To </ins>text <ins class="diffchange diffchange-inline">{{subst:PAGENAME}}</ins></div></td></tr>' . "\n",
655 'Basic diff, deprecated text, guessed model' => [
657 'fromtext' => 'From text',
658 'totext' => 'To text',
661 'warnings' => array_merge( self
::makeDeprecationWarnings( 'fromtext', 'totext' ), [
662 [ 'code' => 'compare-nocontentmodel', 'module' => 'compare' ],
665 'body' => '<tr><td colspan="2" class="diff-lineno" id="mw-diff-left-l1" >Line 1:</td>' . "\n"
666 . '<td colspan="2" class="diff-lineno">Line 1:</td></tr>' . "\n"
667 . '<tr><td class=\'diff-marker\'>−</td><td class=\'diff-deletedline\'><div><del class="diffchange diffchange-inline">From </del>text</div></td><td class=\'diff-marker\'>+</td><td class=\'diff-addedline\'><div><ins class="diffchange diffchange-inline">To </ins>text</div></td></tr>' . "\n",
671 'Basic diff, deprecated text with title and PST' => [
673 'fromtext' => 'From text',
675 'totext' => 'To text {{subst:PAGENAME}}',
679 'warnings' => self
::makeDeprecationWarnings( 'fromtext', 'totext' ),
681 'body' => '<tr><td colspan="2" class="diff-lineno" id="mw-diff-left-l1" >Line 1:</td>' . "\n"
682 . '<td colspan="2" class="diff-lineno">Line 1:</td></tr>' . "\n"
683 . '<tr><td class=\'diff-marker\'>−</td><td class=\'diff-deletedline\'><div><del class="diffchange diffchange-inline">From </del>text</div></td><td class=\'diff-marker\'>+</td><td class=\'diff-addedline\'><div><ins class="diffchange diffchange-inline">To </ins>text <ins class="diffchange diffchange-inline">Test</ins></div></td></tr>' . "\n",
687 'Basic diff, deprecated text with page ID and PST' => [
689 'fromtext' => 'From text',
690 'toid' => '{{REPL:pageB}}',
691 'totext' => 'To text {{subst:PAGENAME}}',
695 'warnings' => self
::makeDeprecationWarnings( 'fromtext', 'totext' ),
697 'body' => '<tr><td colspan="2" class="diff-lineno" id="mw-diff-left-l1" >Line 1:</td>' . "\n"
698 . '<td colspan="2" class="diff-lineno">Line 1:</td></tr>' . "\n"
699 . '<tr><td class=\'diff-marker\'>−</td><td class=\'diff-deletedline\'><div><del class="diffchange diffchange-inline">From </del>text</div></td><td class=\'diff-marker\'>+</td><td class=\'diff-addedline\'><div><ins class="diffchange diffchange-inline">To </ins>text <ins class="diffchange diffchange-inline">ApiComparePagesTest B</ins></div></td></tr>' . "\n",
703 'Basic diff, deprecated text with revision and PST' => [
705 'fromtext' => 'From text',
706 'torev' => '{{REPL:revB2}}',
707 'totext' => 'To text {{subst:PAGENAME}}',
711 'warnings' => self
::makeDeprecationWarnings( 'fromtext', 'totext' ),
713 'body' => '<tr><td colspan="2" class="diff-lineno" id="mw-diff-left-l1" >Line 1:</td>' . "\n"
714 . '<td colspan="2" class="diff-lineno">Line 1:</td></tr>' . "\n"
715 . '<tr><td class=\'diff-marker\'>−</td><td class=\'diff-deletedline\'><div><del class="diffchange diffchange-inline">From </del>text</div></td><td class=\'diff-marker\'>+</td><td class=\'diff-addedline\'><div><ins class="diffchange diffchange-inline">To </ins>text <ins class="diffchange diffchange-inline">ApiComparePagesTest B</ins></div></td></tr>' . "\n",
719 'Basic diff, deprecated text with deleted revision and PST' => [
721 'fromtext' => 'From text',
722 'torev' => '{{REPL:revC2}}',
723 'totext' => 'To text {{subst:PAGENAME}}',
727 'warnings' => self
::makeDeprecationWarnings( 'fromtext', 'totext' ),
729 'body' => '<tr><td colspan="2" class="diff-lineno" id="mw-diff-left-l1" >Line 1:</td>' . "\n"
730 . '<td colspan="2" class="diff-lineno">Line 1:</td></tr>' . "\n"
731 . '<tr><td class=\'diff-marker\'>−</td><td class=\'diff-deletedline\'><div><del class="diffchange diffchange-inline">From </del>text</div></td><td class=\'diff-marker\'>+</td><td class=\'diff-addedline\'><div><ins class="diffchange diffchange-inline">To </ins>text <ins class="diffchange diffchange-inline">ApiComparePagesTest C</ins></div></td></tr>' . "\n",
736 'Basic diff, test with deprecated sections' => [
738 'fromtitle' => 'ApiComparePagesTest F',
740 'totext' => "== Section 1 ==\nTo text\n\n== Section 2 ==\nTo text?",
744 'warnings' => self
::makeDeprecationWarnings( 'fromsection', 'totext', 'tosection' ),
746 'body' => '<tr><td colspan="2" class="diff-lineno" id="mw-diff-left-l1" >Line 1:</td>' . "\n"
747 . '<td colspan="2" class="diff-lineno">Line 1:</td></tr>' . "\n"
748 . '<tr><td class=\'diff-marker\'>−</td><td class=\'diff-deletedline\'><div>== Section <del class="diffchange diffchange-inline">1 </del>==</div></td><td class=\'diff-marker\'>+</td><td class=\'diff-addedline\'><div>== Section <ins class="diffchange diffchange-inline">2 </ins>==</div></td></tr>' . "\n"
749 . '<tr><td class=\'diff-marker\'>−</td><td class=\'diff-deletedline\'><div><del class="diffchange diffchange-inline">F 1.1</del></div></td><td class=\'diff-marker\'>+</td><td class=\'diff-addedline\'><div><ins class="diffchange diffchange-inline">To text?</ins></div></td></tr>' . "\n",
750 'fromid' => '{{REPL:pageF}}',
751 'fromrevid' => '{{REPL:revF1}}',
753 'fromtitle' => 'ApiComparePagesTest F',
757 'Basic diff, test with deprecated sections and revdel, non-sysop' => [
759 'fromrev' => '{{REPL:revB2}}',
761 'torev' => '{{REPL:revB4}}',
767 'Basic diff, test with deprecated sections and revdel, sysop' => [
769 'fromrev' => '{{REPL:revB2}}',
771 'torev' => '{{REPL:revB4}}',
775 'warnings' => self
::makeDeprecationWarnings( 'fromsection', 'tosection' ),
777 'body' => '<tr><td colspan="2" class="diff-lineno" id="mw-diff-left-l1" >Line 1:</td>' . "\n"
778 . '<td colspan="2" class="diff-lineno">Line 1:</td></tr>' . "\n"
779 . '<tr><td class=\'diff-marker\'>−</td><td class=\'diff-deletedline\'><div>B <del class="diffchange diffchange-inline">2</del></div></td><td class=\'diff-marker\'>+</td><td class=\'diff-addedline\'><div>B <ins class="diffchange diffchange-inline">4</ins></div></td></tr>' . "\n",
780 'fromid' => '{{REPL:pageB}}',
781 'fromrevid' => '{{REPL:revB2}}',
783 'fromtitle' => 'ApiComparePagesTest B',
784 'fromtexthidden' => true,
785 'fromuserhidden' => true,
786 'fromcommenthidden' => true,
787 'toid' => '{{REPL:pageB}}',
788 'torevid' => '{{REPL:revB4}}',
790 'totitle' => 'ApiComparePagesTest B',
796 'Error, missing title' => [
798 'fromtitle' => 'ApiComparePagesTest X',
799 'totitle' => 'ApiComparePagesTest B',
804 'Error, invalid title' => [
806 'fromtitle' => '<bad>',
807 'totitle' => 'ApiComparePagesTest B',
812 'Error, missing page ID' => [
815 'totitle' => 'ApiComparePagesTest B',
820 'Error, page with missing revision' => [
822 'fromtitle' => 'ApiComparePagesTest D',
823 'totitle' => 'ApiComparePagesTest B',
828 'Error, page with no revision' => [
830 'fromtitle' => 'ApiComparePagesTest E',
831 'totitle' => 'ApiComparePagesTest B',
836 'Error, bad rev ID' => [
838 'fromrev' => 8817900,
839 'totitle' => 'ApiComparePagesTest B',
844 'Error, deleted revision ID, non-sysop' => [
846 'fromrev' => '{{REPL:revA2}}',
847 'torev' => '{{REPL:revC2}}',
852 'Error, deleted revision ID and torelative=prev' => [
854 'fromrev' => '{{REPL:revC2}}',
855 'torelative' => 'prev',
858 'compare-relative-to-deleted', true
860 'Error, deleted revision ID and torelative=next' => [
862 'fromrev' => '{{REPL:revC2}}',
863 'torelative' => 'next',
866 'compare-relative-to-deleted', true
868 'Deleted revision ID and torelative=cur' => [
870 'fromrev' => '{{REPL:revC2}}',
871 'torelative' => 'cur',
876 'Error, revision-deleted content' => [
878 'fromrev' => '{{REPL:revA2}}',
879 'torev' => '{{REPL:revB2}}',
884 'Error, text with no title and PST' => [
886 'fromtext' => 'From text',
887 'totext' => 'To text {{subst:PAGENAME}}',
893 'Error, test with invalid from section ID' => [
895 'fromtitle' => 'ApiComparePagesTest F',
897 'totext' => "== Section 1 ==\nTo text\n\n== Section 2 ==\nTo text?",
903 'Error, test with invalid to section ID' => [
905 'fromtitle' => 'ApiComparePagesTest F',
907 'totext' => "== Section 1 ==\nTo text\n\n== Section 2 ==\nTo text?",
913 'Error, Relative diff, no from revision' => [
916 'torelative' => 'cur',
920 'compare-relative-to-nothing'
922 'Error, Relative diff, cur with no current revision' => [
924 'fromrev' => '{{REPL:revE2}}',
925 'torelative' => 'cur',
931 'Error, Relative diff, next revdeleted' => [
933 'fromrev' => '{{REPL:revB1}}',
934 'torelative' => 'next',
940 'Error, Relative diff, prev revdeleted' => [
942 'fromrev' => '{{REPL:revB3}}',
943 'torelative' => 'prev',
949 'Error, section diff with no revision' => [
951 'fromtitle' => 'ApiComparePagesTest F',
953 'totext-main' => "== Section 1 ==\nTo text?",
954 'tosection-main' => 1,
957 'compare-notorevision',
959 'Error, section diff with revdeleted revision' => [
961 'fromtitle' => 'ApiComparePagesTest F',
962 'torev' => '{{REPL:revB2}}',
964 'totext-main' => "== Section 1 ==\nTo text?",
965 'tosection-main' => 1,
970 'Error, section diff with a content model not supporting sections' => [
972 'fromtitle' => 'ApiComparePagesTest G',
973 'torev' => '{{REPL:revG1}}',
975 'totext-main' => "== Section 1 ==\nTo text?",
976 'tosection-main' => 1,
979 'sectionsnotsupported',
981 'Error, section diff with bad content model' => [
983 'fromtitle' => 'ApiComparePagesTest F',
984 'torev' => '{{REPL:revF1}}',
986 'totext-main' => "== Section 1 ==\nTo text?",
987 'tosection-main' => 1,
988 'tocontentmodel-main' => CONTENT_MODEL_TEXT
,
991 'sectionreplacefailed',
993 'Error, deleting the main slot' => [
995 'fromtitle' => 'ApiComparePagesTest A',
996 'totitle' => 'ApiComparePagesTest A',
1000 'compare-maintextrequired',
1002 // @todo Add a test for using 'tosection-foo' without 'totext-foo' (can't do it with main)