3 use MediaWiki\Linker\LinkTarget
;
4 use MediaWiki\MediaWikiServices
;
11 * @covers ApiQueryRecentChanges
13 class ApiQueryRecentChangesIntegrationTest
extends ApiTestCase
{
15 public function __construct( $name = null, array $data = [], $dataName = '' ) {
16 parent
::__construct( $name, $data, $dataName );
18 $this->tablesUsed
[] = 'recentchanges';
19 $this->tablesUsed
[] = 'page';
22 protected function setUp() {
25 self
::$users['ApiQueryRecentChangesIntegrationTestUser'] = $this->getMutableTestUser();
26 $this->doLogin( 'ApiQueryRecentChangesIntegrationTestUser' );
27 wfGetDB( DB_MASTER
)->delete( 'recentchanges', '*', __METHOD__
);
30 private function getLoggedInTestUser() {
31 return self
::$users['ApiQueryRecentChangesIntegrationTestUser']->getUser();
34 private function doPageEdit( User
$user, LinkTarget
$target, $summary ) {
37 $title = Title
::newFromLinkTarget( $target );
38 $page = WikiPage
::factory( $title );
40 ContentHandler
::makeContent( __CLASS__
. $i++
, $title ),
48 private function doMinorPageEdit( User
$user, LinkTarget
$target, $summary ) {
49 $title = Title
::newFromLinkTarget( $target );
50 $page = WikiPage
::factory( $title );
52 ContentHandler
::makeContent( __CLASS__
, $title ),
60 private function doBotPageEdit( User
$user, LinkTarget
$target, $summary ) {
61 $title = Title
::newFromLinkTarget( $target );
62 $page = WikiPage
::factory( $title );
64 ContentHandler
::makeContent( __CLASS__
, $title ),
72 private function doAnonPageEdit( LinkTarget
$target, $summary ) {
73 $title = Title
::newFromLinkTarget( $target );
74 $page = WikiPage
::factory( $title );
76 ContentHandler
::makeContent( __CLASS__
, $title ),
84 private function deletePage( LinkTarget
$target, $reason ) {
85 $title = Title
::newFromLinkTarget( $target );
86 $page = WikiPage
::factory( $title );
87 $page->doDeleteArticleReal( $reason );
91 * Performs a batch of page edits as a specified user
93 * @param array $editData associative array, keys:
94 * - target => LinkTarget page to edit
95 * - summary => string edit summary
96 * - minorEdit => bool mark as minor edit if true (defaults to false)
97 * - botEdit => bool mark as bot edit if true (defaults to false)
99 private function doPageEdits( User
$user, array $editData ) {
100 foreach ( $editData as $singleEditData ) {
101 if ( array_key_exists( 'minorEdit', $singleEditData ) && $singleEditData['minorEdit'] ) {
102 $this->doMinorPageEdit(
104 $singleEditData['target'],
105 $singleEditData['summary']
109 if ( array_key_exists( 'botEdit', $singleEditData ) && $singleEditData['botEdit'] ) {
110 $this->doBotPageEdit(
112 $singleEditData['target'],
113 $singleEditData['summary']
119 $singleEditData['target'],
120 $singleEditData['summary']
125 private function doListRecentChangesRequest( array $params = [] ) {
126 return $this->doApiRequest(
128 [ 'action' => 'query', 'list' => 'recentchanges' ],
136 private function doGeneratorRecentChangesRequest( array $params = [] ) {
137 return $this->doApiRequest(
139 [ 'action' => 'query', 'generator' => 'recentchanges' ],
145 private function getItemsFromApiResponse( array $response ) {
146 return $response[0]['query']['recentchanges'];
149 private function getTitleFormatter() {
150 return new MediaWikiTitleCodec(
151 Language
::factory( 'en' ),
152 MediaWikiServices
::getInstance()->getGenderCache()
156 private function getPrefixedText( LinkTarget
$target ) {
157 $formatter = $this->getTitleFormatter();
158 return $formatter->getPrefixedText( $target );
161 public function testListRecentChanges_returnsRCInfo() {
162 $target = new TitleValue( 0, 'ApiQueryRecentChangesIntegrationTestPage' );
163 $this->doPageEdit( $this->getLoggedInTestUser(), $target, 'Create the page' );
165 $result = $this->doListRecentChangesRequest();
167 $this->assertArrayHasKey( 'query', $result[0] );
168 $this->assertArrayHasKey( 'recentchanges', $result[0]['query'] );
170 $items = $this->getItemsFromApiResponse( $result );
171 $this->assertCount( 1, $items );
173 $this->assertArraySubset(
176 'ns' => $target->getNamespace(),
177 'title' => $this->getPrefixedText( $target ),
181 $this->assertArrayNotHasKey( 'bot', $item );
182 $this->assertArrayNotHasKey( 'new', $item );
183 $this->assertArrayNotHasKey( 'minor', $item );
184 $this->assertArrayHasKey( 'pageid', $item );
185 $this->assertArrayHasKey( 'revid', $item );
186 $this->assertArrayHasKey( 'old_revid', $item );
189 public function testIdsPropParameter() {
190 $target = new TitleValue( 0, 'ApiQueryRecentChangesIntegrationTestPage' );
191 $this->doPageEdit( $this->getLoggedInTestUser(), $target, 'Create the page' );
193 $result = $this->doListRecentChangesRequest( [ 'rcprop' => 'ids', ] );
194 $items = $this->getItemsFromApiResponse( $result );
196 $this->assertCount( 1, $items );
197 $this->assertArrayHasKey( 'pageid', $items[0] );
198 $this->assertArrayHasKey( 'revid', $items[0] );
199 $this->assertArrayHasKey( 'old_revid', $items[0] );
200 $this->assertEquals( 'new', $items[0]['type'] );
203 public function testTitlePropParameter() {
204 $subjectTarget = new TitleValue( 0, 'ApiQueryRecentChangesIntegrationTestPage' );
205 $talkTarget = new TitleValue( 1, 'ApiQueryRecentChangesIntegrationTestPage' );
207 $this->getLoggedInTestUser(),
210 'target' => $subjectTarget,
211 'summary' => 'Create the page',
214 'target' => $talkTarget,
215 'summary' => 'Create Talk page',
220 $result = $this->doListRecentChangesRequest( [ 'rcprop' => 'title', ] );
226 'ns' => $talkTarget->getNamespace(),
227 'title' => $this->getPrefixedText( $talkTarget ),
231 'ns' => $subjectTarget->getNamespace(),
232 'title' => $this->getPrefixedText( $subjectTarget ),
235 $this->getItemsFromApiResponse( $result )
239 public function testFlagsPropParameter() {
240 $normalEditTarget = new TitleValue( 0, 'ApiQueryRecentChangesIntegrationTestPage' );
241 $minorEditTarget = new TitleValue( 0, 'ApiQueryRecentChangesIntegrationTestPageM' );
242 $botEditTarget = new TitleValue( 0, 'ApiQueryRecentChangesIntegrationTestPageB' );
244 $this->getLoggedInTestUser(),
247 'target' => $normalEditTarget,
248 'summary' => 'Create the page',
251 'target' => $minorEditTarget,
252 'summary' => 'Create the page',
255 'target' => $minorEditTarget,
256 'summary' => 'Change content',
260 'target' => $botEditTarget,
261 'summary' => 'Create the page with a bot',
267 $result = $this->doListRecentChangesRequest( [ 'rcprop' => 'flags', ] );
296 $this->getItemsFromApiResponse( $result )
300 public function testUserPropParameter() {
301 $userEditTarget = new TitleValue( 0, 'ApiQueryRecentChangesIntegrationTestPage' );
302 $anonEditTarget = new TitleValue( 0, 'ApiQueryRecentChangesIntegrationTestPageA' );
303 $this->doPageEdit( $this->getLoggedInTestUser(), $userEditTarget, 'Create the page' );
304 $this->doAnonPageEdit( $anonEditTarget, 'Create the page' );
306 $result = $this->doListRecentChangesRequest( [ 'rcprop' => 'user', ] );
313 'user' => User
::newFromId( 0 )->getName(),
317 'user' => $this->getLoggedInTestUser()->getName(),
320 $this->getItemsFromApiResponse( $result )
324 public function testUserIdPropParameter() {
325 $user = $this->getLoggedInTestUser();
326 $userEditTarget = new TitleValue( 0, 'ApiQueryRecentChangesIntegrationTestPage' );
327 $anonEditTarget = new TitleValue( 0, 'ApiQueryRecentChangesIntegrationTestPageA' );
328 $this->doPageEdit( $user, $userEditTarget, 'Create the page' );
329 $this->doAnonPageEdit( $anonEditTarget, 'Create the page' );
331 $result = $this->doListRecentChangesRequest( [ 'rcprop' => 'userid', ] );
342 'userid' => $user->getId(),
345 $this->getItemsFromApiResponse( $result )
349 public function testCommentPropParameter() {
350 $target = new TitleValue( 0, 'ApiQueryRecentChangesIntegrationTestPage' );
351 $this->doPageEdit( $this->getLoggedInTestUser(), $target, 'Create the <b>page</b>' );
353 $result = $this->doListRecentChangesRequest( [ 'rcprop' => 'comment', ] );
359 'comment' => 'Create the <b>page</b>',
362 $this->getItemsFromApiResponse( $result )
366 public function testParsedCommentPropParameter() {
367 $target = new TitleValue( 0, 'ApiQueryRecentChangesIntegrationTestPage' );
368 $this->doPageEdit( $this->getLoggedInTestUser(), $target, 'Create the <b>page</b>' );
370 $result = $this->doListRecentChangesRequest( [ 'rcprop' => 'parsedcomment', ] );
376 'parsedcomment' => 'Create the <b>page</b>',
379 $this->getItemsFromApiResponse( $result )
383 public function testTimestampPropParameter() {
384 $target = new TitleValue( 0, 'ApiQueryRecentChangesIntegrationTestPage' );
385 $this->doPageEdit( $this->getLoggedInTestUser(), $target, 'Create the page' );
387 $result = $this->doListRecentChangesRequest( [ 'rcprop' => 'timestamp', ] );
388 $items = $this->getItemsFromApiResponse( $result );
390 $this->assertCount( 1, $items );
391 $this->assertArrayHasKey( 'timestamp', $items[0] );
392 $this->assertInternalType( 'string', $items[0]['timestamp'] );
395 public function testSizesPropParameter() {
396 $target = new TitleValue( 0, 'ApiQueryRecentChangesIntegrationTestPage' );
397 $this->doPageEdit( $this->getLoggedInTestUser(), $target, 'Create the page' );
399 $result = $this->doListRecentChangesRequest( [ 'rcprop' => 'sizes', ] );
409 $this->getItemsFromApiResponse( $result )
413 private function createPageAndDeleteIt( LinkTarget
$target ) {
414 $this->doPageEdit( $this->getLoggedInTestUser(),
416 'Create the page that will be deleted'
418 $this->deletePage( $target, 'Important Reason' );
421 public function testLoginfoPropParameter() {
422 $target = new TitleValue( 0, 'ApiQueryRecentChangesIntegrationTestPage' );
423 $this->createPageAndDeleteIt( $target );
425 $result = $this->doListRecentChangesRequest( [ 'rcprop' => 'loginfo', ] );
427 $items = $this->getItemsFromApiResponse( $result );
428 $this->assertCount( 1, $items );
429 $this->assertArraySubset(
432 'logtype' => 'delete',
433 'logaction' => 'delete',
438 $this->assertArrayHasKey( 'logid', $items[0] );
441 public function testEmptyPropParameter() {
442 $user = $this->getLoggedInTestUser();
443 $target = new TitleValue( 0, 'ApiQueryRecentChangesIntegrationTestPage' );
444 $this->doPageEdit( $user, $target, 'Create the page' );
446 $result = $this->doListRecentChangesRequest( [ 'rcprop' => '', ] );
454 $this->getItemsFromApiResponse( $result )
458 public function testNamespaceParam() {
459 $subjectTarget = new TitleValue( 0, 'ApiQueryRecentChangesIntegrationTestPage' );
460 $talkTarget = new TitleValue( 1, 'ApiQueryRecentChangesIntegrationTestPage' );
462 $this->getLoggedInTestUser(),
465 'target' => $subjectTarget,
466 'summary' => 'Create the page',
469 'target' => $talkTarget,
470 'summary' => 'Create the talk page',
475 $result = $this->doListRecentChangesRequest( [ 'rcnamespace' => '0', ] );
477 $items = $this->getItemsFromApiResponse( $result );
478 $this->assertCount( 1, $items );
479 $this->assertArraySubset(
482 'title' => $this->getPrefixedText( $subjectTarget ),
488 public function testShowAnonParams() {
489 $target = new TitleValue( 0, 'ApiQueryRecentChangesIntegrationTestPage' );
490 $this->doAnonPageEdit( $target, 'Create the page' );
492 $resultAnon = $this->doListRecentChangesRequest( [
494 'rcshow' => WatchedItemQueryService
::FILTER_ANON
496 $resultNotAnon = $this->doListRecentChangesRequest( [
498 'rcshow' => WatchedItemQueryService
::FILTER_NOT_ANON
501 $items = $this->getItemsFromApiResponse( $resultAnon );
502 $this->assertCount( 1, $items );
503 $this->assertArraySubset( [ 'anon' => true ], $items[0] );
504 $this->assertEmpty( $this->getItemsFromApiResponse( $resultNotAnon ) );
507 public function testNewAndEditTypeParameters() {
508 $subjectTarget = new TitleValue( 0, 'ApiQueryRecentChangesIntegrationTestPage' );
509 $talkTarget = new TitleValue( 1, 'ApiQueryRecentChangesIntegrationTestPage' );
511 $this->getLoggedInTestUser(),
514 'target' => $subjectTarget,
515 'summary' => 'Create the page',
518 'target' => $subjectTarget,
519 'summary' => 'Change the content',
522 'target' => $talkTarget,
523 'summary' => 'Create Talk page',
528 $resultNew = $this->doListRecentChangesRequest( [ 'rcprop' => 'title', 'rctype' => 'new' ] );
529 $resultEdit = $this->doListRecentChangesRequest( [ 'rcprop' => 'title', 'rctype' => 'edit' ] );
535 'ns' => $talkTarget->getNamespace(),
536 'title' => $this->getPrefixedText( $talkTarget ),
540 'ns' => $subjectTarget->getNamespace(),
541 'title' => $this->getPrefixedText( $subjectTarget ),
544 $this->getItemsFromApiResponse( $resultNew )
550 'ns' => $subjectTarget->getNamespace(),
551 'title' => $this->getPrefixedText( $subjectTarget ),
554 $this->getItemsFromApiResponse( $resultEdit )
558 public function testLogTypeParameters() {
559 $subjectTarget = new TitleValue( 0, 'ApiQueryRecentChangesIntegrationTestPage' );
560 $talkTarget = new TitleValue( 1, 'ApiQueryRecentChangesIntegrationTestPage' );
561 $this->createPageAndDeleteIt( $subjectTarget );
562 $this->doPageEdit( $this->getLoggedInTestUser(), $talkTarget, 'Create Talk page' );
564 $result = $this->doListRecentChangesRequest( [ 'rcprop' => 'title', 'rctype' => 'log' ] );
570 'ns' => $subjectTarget->getNamespace(),
571 'title' => $this->getPrefixedText( $subjectTarget ),
574 $this->getItemsFromApiResponse( $result )
578 private function getExternalRC( LinkTarget
$target ) {
579 $title = Title
::newFromLinkTarget( $target );
581 $rc = new RecentChange
;
582 $rc->mTitle
= $title;
584 'rc_timestamp' => wfTimestamp( TS_MW
),
585 'rc_namespace' => $title->getNamespace(),
586 'rc_title' => $title->getDBkey(),
587 'rc_type' => RC_EXTERNAL
,
588 'rc_source' => 'foo',
590 'rc_cur_id' => $title->getArticleID(),
592 'rc_user_text' => 'External User',
594 'rc_comment_text' => '',
595 'rc_comment_data' => null,
596 'rc_this_oldid' => $title->getLatestRevID(),
597 'rc_last_oldid' => $title->getLatestRevID(),
602 'rc_old_len' => $title->getLength(),
603 'rc_new_len' => $title->getLength(),
606 'rc_log_type' => null,
607 'rc_log_action' => '',
611 'prefixedDBkey' => $title->getPrefixedDBkey(),
612 'lastTimestamp' => 0,
613 'oldSize' => $title->getLength(),
614 'newSize' => $title->getLength(),
615 'pageStatus' => 'changed'
621 public function testExternalTypeParameters() {
622 $user = $this->getLoggedInTestUser();
623 $subjectTarget = new TitleValue( 0, 'ApiQueryRecentChangesIntegrationTestPage' );
624 $talkTarget = new TitleValue( 1, 'ApiQueryRecentChangesIntegrationTestPage' );
625 $this->doPageEdit( $user, $subjectTarget, 'Create the page' );
626 $this->doPageEdit( $user, $talkTarget, 'Create Talk page' );
628 $rc = $this->getExternalRC( $subjectTarget );
631 $result = $this->doListRecentChangesRequest( [ 'rcprop' => 'title', 'rctype' => 'external' ] );
636 'type' => 'external',
637 'ns' => $subjectTarget->getNamespace(),
638 'title' => $this->getPrefixedText( $subjectTarget ),
641 $this->getItemsFromApiResponse( $result )
645 public function testCategorizeTypeParameter() {
646 $user = $this->getLoggedInTestUser();
647 $subjectTarget = new TitleValue( 0, 'ApiQueryRecentChangesIntegrationTestPage' );
648 $categoryTarget = new TitleValue( NS_CATEGORY
, 'ApiQueryRecentChangesIntegrationTestCategory' );
653 'target' => $categoryTarget,
654 'summary' => 'Create the category',
657 'target' => $subjectTarget,
658 'summary' => 'Create the page and add it to the category',
662 $title = Title
::newFromLinkTarget( $subjectTarget );
663 $revision = Revision
::newFromTitle( $title );
665 $rc = RecentChange
::newForCategorization(
666 $revision->getTimestamp(),
667 Title
::newFromLinkTarget( $categoryTarget ),
669 $revision->getComment(),
678 $result = $this->doListRecentChangesRequest( [ 'rcprop' => 'title', 'rctype' => 'categorize' ] );
683 'type' => 'categorize',
684 'ns' => $categoryTarget->getNamespace(),
685 'title' => $this->getPrefixedText( $categoryTarget ),
688 $this->getItemsFromApiResponse( $result )
692 public function testLimitParam() {
693 $target1 = new TitleValue( 0, 'ApiQueryRecentChangesIntegrationTestPage' );
694 $target2 = new TitleValue( 1, 'ApiQueryRecentChangesIntegrationTestPage' );
695 $target3 = new TitleValue( 0, 'ApiQueryRecentChangesIntegrationTestPage2' );
697 $this->getLoggedInTestUser(),
700 'target' => $target1,
701 'summary' => 'Create the page',
704 'target' => $target2,
705 'summary' => 'Create Talk page',
708 'target' => $target3,
709 'summary' => 'Create the page',
714 $resultWithoutLimit = $this->doListRecentChangesRequest( [ 'rcprop' => 'title' ] );
715 $resultWithLimit = $this->doListRecentChangesRequest( [ 'rclimit' => 2, 'rcprop' => 'title' ] );
721 'ns' => $target3->getNamespace(),
722 'title' => $this->getPrefixedText( $target3 )
726 'ns' => $target2->getNamespace(),
727 'title' => $this->getPrefixedText( $target2 )
731 'ns' => $target1->getNamespace(),
732 'title' => $this->getPrefixedText( $target1 )
735 $this->getItemsFromApiResponse( $resultWithoutLimit )
741 'ns' => $target3->getNamespace(),
742 'title' => $this->getPrefixedText( $target3 )
746 'ns' => $target2->getNamespace(),
747 'title' => $this->getPrefixedText( $target2 )
750 $this->getItemsFromApiResponse( $resultWithLimit )
752 $this->assertArrayHasKey( 'continue', $resultWithLimit[0] );
753 $this->assertArrayHasKey( 'rccontinue', $resultWithLimit[0]['continue'] );
756 public function testAllRevParam() {
757 $target = new TitleValue( 0, 'ApiQueryRecentChangesIntegrationTestPage' );
759 $this->getLoggedInTestUser(),
763 'summary' => 'Create the page',
767 'summary' => 'Change the content',
772 $resultAllRev = $this->doListRecentChangesRequest( [ 'rcprop' => 'title', 'rcallrev' => '', ] );
773 $resultNoAllRev = $this->doListRecentChangesRequest( [ 'rcprop' => 'title' ] );
779 'ns' => $target->getNamespace(),
780 'title' => $this->getPrefixedText( $target ),
784 'ns' => $target->getNamespace(),
785 'title' => $this->getPrefixedText( $target ),
788 $this->getItemsFromApiResponse( $resultNoAllRev )
794 'ns' => $target->getNamespace(),
795 'title' => $this->getPrefixedText( $target ),
799 'ns' => $target->getNamespace(),
800 'title' => $this->getPrefixedText( $target ),
803 $this->getItemsFromApiResponse( $resultAllRev )
807 public function testDirParams() {
808 $subjectTarget = new TitleValue( 0, 'ApiQueryRecentChangesIntegrationTestPage' );
809 $talkTarget = new TitleValue( 1, 'ApiQueryRecentChangesIntegrationTestPage' );
811 $this->getLoggedInTestUser(),
814 'target' => $subjectTarget,
815 'summary' => 'Create the page',
818 'target' => $talkTarget,
819 'summary' => 'Create Talk page',
824 $resultDirOlder = $this->doListRecentChangesRequest(
825 [ 'rcdir' => 'older', 'rcprop' => 'title' ]
827 $resultDirNewer = $this->doListRecentChangesRequest(
828 [ 'rcdir' => 'newer', 'rcprop' => 'title' ]
835 'ns' => $talkTarget->getNamespace(),
836 'title' => $this->getPrefixedText( $talkTarget )
840 'ns' => $subjectTarget->getNamespace(),
841 'title' => $this->getPrefixedText( $subjectTarget )
844 $this->getItemsFromApiResponse( $resultDirOlder )
850 'ns' => $subjectTarget->getNamespace(),
851 'title' => $this->getPrefixedText( $subjectTarget )
855 'ns' => $talkTarget->getNamespace(),
856 'title' => $this->getPrefixedText( $talkTarget )
859 $this->getItemsFromApiResponse( $resultDirNewer )
863 public function testStartEndParams() {
864 $target = new TitleValue( 0, 'ApiQueryRecentChangesIntegrationTestPage' );
865 $this->doPageEdit( $this->getLoggedInTestUser(), $target, 'Create the page' );
867 $resultStart = $this->doListRecentChangesRequest( [
868 'rcstart' => '20010115000000',
872 $resultEnd = $this->doListRecentChangesRequest( [
873 'rcend' => '20010115000000',
882 'ns' => $target->getNamespace(),
883 'title' => $this->getPrefixedText( $target ),
886 $this->getItemsFromApiResponse( $resultStart )
888 $this->assertEmpty( $this->getItemsFromApiResponse( $resultEnd ) );
891 public function testContinueParam() {
892 $target1 = new TitleValue( 0, 'ApiQueryRecentChangesIntegrationTestPage' );
893 $target2 = new TitleValue( 1, 'ApiQueryRecentChangesIntegrationTestPage' );
894 $target3 = new TitleValue( 0, 'ApiQueryRecentChangesIntegrationTestPage2' );
896 $this->getLoggedInTestUser(),
899 'target' => $target1,
900 'summary' => 'Create the page',
903 'target' => $target2,
904 'summary' => 'Create Talk page',
907 'target' => $target3,
908 'summary' => 'Create the page',
913 $firstResult = $this->doListRecentChangesRequest( [ 'rclimit' => 2, 'rcprop' => 'title' ] );
914 $this->assertArrayHasKey( 'continue', $firstResult[0] );
915 $this->assertArrayHasKey( 'rccontinue', $firstResult[0]['continue'] );
917 $continuationParam = $firstResult[0]['continue']['rccontinue'];
919 $continuedResult = $this->doListRecentChangesRequest(
920 [ 'rccontinue' => $continuationParam, 'rcprop' => 'title' ]
927 'ns' => $target3->getNamespace(),
928 'title' => $this->getPrefixedText( $target3 ),
932 'ns' => $target2->getNamespace(),
933 'title' => $this->getPrefixedText( $target2 ),
936 $this->getItemsFromApiResponse( $firstResult )
942 'ns' => $target1->getNamespace(),
943 'title' => $this->getPrefixedText( $target1 )
946 $this->getItemsFromApiResponse( $continuedResult )
950 public function testGeneratorRecentChangesPropInfo_returnsRCPages() {
951 $target = new TitleValue( 0, 'ApiQueryRecentChangesIntegrationTestPage' );
952 $this->doPageEdit( $this->getLoggedInTestUser(), $target, 'Create the page' );
954 $result = $this->doGeneratorRecentChangesRequest( [ 'prop' => 'info' ] );
956 $this->assertArrayHasKey( 'query', $result[0] );
957 $this->assertArrayHasKey( 'pages', $result[0]['query'] );
959 // $result[0]['query']['pages'] uses page ids as keys. Page ids don't matter here, so drop them
960 $pages = array_values( $result[0]['query']['pages'] );
962 $this->assertCount( 1, $pages );
963 $this->assertArraySubset(
965 'ns' => $target->getNamespace(),
966 'title' => $this->getPrefixedText( $target ),