3 use MediaWiki\Linker\LinkTarget
;
4 use MediaWiki\MediaWikiServices
;
11 * @covers ApiQueryWatchlist
13 class ApiQueryWatchlistIntegrationTest
extends ApiTestCase
{
15 public function __construct( $name = null, array $data = [], $dataName = '' ) {
16 parent
::__construct( $name, $data, $dataName );
17 $this->tablesUsed
= array_unique(
18 array_merge( $this->tablesUsed
, [ 'watchlist', 'recentchanges', 'page' ] )
22 protected function setUp() {
24 self
::$users['ApiQueryWatchlistIntegrationTestUser'] = $this->getMutableTestUser();
25 self
::$users['ApiQueryWatchlistIntegrationTestUser2'] = $this->getMutableTestUser();
26 $this->doLogin( 'ApiQueryWatchlistIntegrationTestUser' );
29 private function getLoggedInTestUser() {
30 return self
::$users['ApiQueryWatchlistIntegrationTestUser']->getUser();
33 private function getNonLoggedInTestUser() {
34 return self
::$users['ApiQueryWatchlistIntegrationTestUser2']->getUser();
37 private function doPageEdit( User
$user, LinkTarget
$target, $content, $summary ) {
38 $title = Title
::newFromLinkTarget( $target );
39 $page = WikiPage
::factory( $title );
41 ContentHandler
::makeContent( $content, $title ),
49 private function doMinorPageEdit( User
$user, LinkTarget
$target, $content, $summary ) {
50 $title = Title
::newFromLinkTarget( $target );
51 $page = WikiPage
::factory( $title );
53 ContentHandler
::makeContent( $content, $title ),
61 private function doBotPageEdit( User
$user, LinkTarget
$target, $content, $summary ) {
62 $title = Title
::newFromLinkTarget( $target );
63 $page = WikiPage
::factory( $title );
65 ContentHandler
::makeContent( $content, $title ),
73 private function doAnonPageEdit( LinkTarget
$target, $content, $summary ) {
74 $title = Title
::newFromLinkTarget( $target );
75 $page = WikiPage
::factory( $title );
77 ContentHandler
::makeContent( $content, $title ),
85 private function doPatrolledPageEdit(
92 $title = Title
::newFromLinkTarget( $target );
93 $page = WikiPage
::factory( $title );
94 $status = $page->doEditContent(
95 ContentHandler
::makeContent( $content, $title ),
101 /** @var Revision $rev */
102 $rev = $status->value
['revision'];
103 $rc = $rev->getRecentChange();
104 $rc->doMarkPatrolled( $patrollingUser, false, [] );
107 private function deletePage( LinkTarget
$target, $reason ) {
108 $title = Title
::newFromLinkTarget( $target );
109 $page = WikiPage
::factory( $title );
110 $page->doDeleteArticleReal( $reason );
114 * Performs a batch of page edits as a specified user
116 * @param array $editData associative array, keys:
117 * - target => LinkTarget page to edit
118 * - content => string new content
119 * - summary => string edit summary
120 * - minorEdit => bool mark as minor edit if true (defaults to false)
121 * - botEdit => bool mark as bot edit if true (defaults to false)
123 private function doPageEdits( User
$user, array $editData ) {
124 foreach ( $editData as $singleEditData ) {
125 if ( array_key_exists( 'minorEdit', $singleEditData ) && $singleEditData['minorEdit'] ) {
126 $this->doMinorPageEdit(
128 $singleEditData['target'],
129 $singleEditData['content'],
130 $singleEditData['summary']
134 if ( array_key_exists( 'botEdit', $singleEditData ) && $singleEditData['botEdit'] ) {
135 $this->doBotPageEdit(
137 $singleEditData['target'],
138 $singleEditData['content'],
139 $singleEditData['summary']
145 $singleEditData['target'],
146 $singleEditData['content'],
147 $singleEditData['summary']
152 private function getWatchedItemStore() {
153 return MediaWikiServices
::getInstance()->getWatchedItemStore();
158 * @param LinkTarget[] $targets
160 private function watchPages( User
$user, array $targets ) {
161 $store = $this->getWatchedItemStore();
162 $store->addWatchBatchForUser( $user, $targets );
165 private function doListWatchlistRequest( array $params = [], $user = null ) {
166 return $this->doApiRequest(
168 [ 'action' => 'query', 'list' => 'watchlist' ],
170 ), null, false, $user
174 private function doGeneratorWatchlistRequest( array $params = [] ) {
175 return $this->doApiRequest(
177 [ 'action' => 'query', 'generator' => 'watchlist' ],
183 private function getItemsFromApiResponse( array $response ) {
184 return $response[0]['query']['watchlist'];
188 * Convenience method to assert that actual items array fetched from API is equal to the expected
189 * array, Unlike assertEquals this only checks if values of specified keys are equal in both
190 * arrays. This could be used e.g. not to compare IDs that could change between test run
191 * but only stable keys.
192 * Optionally this also checks that specified keys are present in the actual item without
193 * performing any checks on the related values.
195 * @param array $actualItems array of actual items (associative arrays)
196 * @param array $expectedItems array of expected items (associative arrays),
197 * those items have less keys than actual items
198 * @param array $keysUsedInValueComparison list of keys of the actual item that will be used
199 * in the comparison of values
200 * @param array $requiredKeys optional, list of keys that must be present in the
201 * actual items. Values of those keys are not checked.
203 private function assertArraySubsetsEqual(
205 array $expectedItems,
206 array $keysUsedInValueComparison,
207 array $requiredKeys = []
209 $this->assertCount( count( $expectedItems ), $actualItems );
211 // not checking values of all keys of the actual item, so removing unwanted keys from comparison
212 $actualItemsOnlyComparedValues = array_map(
213 function( array $item ) use ( $keysUsedInValueComparison ) {
214 return array_intersect_key( $item, array_flip( $keysUsedInValueComparison ) );
221 $actualItemsOnlyComparedValues
224 // Check that each item in $actualItems contains all of keys specified in $requiredKeys
225 $actualItemsKeysOnly = array_map( 'array_keys', $actualItems );
226 foreach ( $actualItemsKeysOnly as $keysOfTheItem ) {
227 $this->assertEmpty( array_diff( $requiredKeys, $keysOfTheItem ) );
231 private function getTitleFormatter() {
232 return new MediaWikiTitleCodec( Language
::factory( 'en' ), GenderCache
::singleton() );
235 private function getPrefixedText( LinkTarget
$target ) {
236 $formatter = $this->getTitleFormatter();
237 return $formatter->getPrefixedText( $target );
240 private function cleanTestUsersWatchlist() {
241 $user = $this->getLoggedInTestUser();
242 $store = $this->getWatchedItemStore();
243 $items = $store->getWatchedItemsForUser( $user );
244 foreach ( $items as $item ) {
245 $store->removeWatch( $user, $item->getLinkTarget() );
249 public function testListWatchlist_returnsWatchedItemsWithRCInfo() {
250 // Clean up after previous tests that might have added something to the watchlist of
251 // the user with the same user ID as user used here as the test user
252 $this->cleanTestUsersWatchlist();
254 $user = $this->getLoggedInTestUser();
255 $target = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
262 $this->watchPages( $user, [ $target ] );
264 $result = $this->doListWatchlistRequest();
266 $this->assertArrayHasKey( 'query', $result[0] );
267 $this->assertArrayHasKey( 'watchlist', $result[0]['query'] );
269 $this->assertArraySubsetsEqual(
270 $this->getItemsFromApiResponse( $result ),
274 'ns' => $target->getNamespace(),
275 'title' => $this->getPrefixedText( $target ),
281 [ 'type', 'ns', 'title', 'bot', 'new', 'minor' ],
282 [ 'pageid', 'revid', 'old_revid' ]
286 public function testIdsPropParameter() {
287 $user = $this->getLoggedInTestUser();
288 $target = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
295 $this->watchPages( $user, [ $target ] );
297 $result = $this->doListWatchlistRequest( [ 'wlprop' => 'ids', ] );
298 $items = $this->getItemsFromApiResponse( $result );
300 $this->assertCount( 1, $items );
301 $this->assertArrayHasKey( 'pageid', $items[0] );
302 $this->assertArrayHasKey( 'revid', $items[0] );
303 $this->assertArrayHasKey( 'old_revid', $items[0] );
304 $this->assertEquals( 'new', $items[0]['type'] );
307 public function testTitlePropParameter() {
308 $user = $this->getLoggedInTestUser();
309 $subjectTarget = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
310 $talkTarget = new TitleValue( 1, 'ApiQueryWatchlistIntegrationTestPage' );
315 'target' => $subjectTarget,
316 'content' => 'Some Content',
317 'summary' => 'Create the page',
320 'target' => $talkTarget,
321 'content' => 'Some Talk Page Content',
322 'summary' => 'Create Talk page',
326 $this->watchPages( $user, [ $subjectTarget, $talkTarget ] );
328 $result = $this->doListWatchlistRequest( [ 'wlprop' => 'title', ] );
334 'ns' => $talkTarget->getNamespace(),
335 'title' => $this->getPrefixedText( $talkTarget ),
339 'ns' => $subjectTarget->getNamespace(),
340 'title' => $this->getPrefixedText( $subjectTarget ),
343 $this->getItemsFromApiResponse( $result )
347 public function testFlagsPropParameter() {
348 $user = $this->getLoggedInTestUser();
349 $normalEditTarget = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
350 $minorEditTarget = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPageM' );
351 $botEditTarget = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPageB' );
356 'target' => $normalEditTarget,
357 'content' => 'Some Content',
358 'summary' => 'Create the page',
361 'target' => $minorEditTarget,
362 'content' => 'Some Content',
363 'summary' => 'Create the page',
366 'target' => $minorEditTarget,
367 'content' => 'Slightly Better Content',
368 'summary' => 'Change content',
372 'target' => $botEditTarget,
373 'content' => 'Some Content',
374 'summary' => 'Create the page with a bot',
379 $this->watchPages( $user, [ $normalEditTarget, $minorEditTarget, $botEditTarget ] );
381 $result = $this->doListWatchlistRequest( [ 'wlprop' => 'flags', ] );
404 $this->getItemsFromApiResponse( $result )
408 public function testUserPropParameter() {
409 $user = $this->getLoggedInTestUser();
410 $userEditTarget = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
411 $anonEditTarget = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPageA' );
418 $this->doAnonPageEdit(
423 $this->watchPages( $user, [ $userEditTarget, $anonEditTarget ] );
425 $result = $this->doListWatchlistRequest( [ 'wlprop' => 'user', ] );
432 'user' => User
::newFromId( 0 )->getName(),
436 'user' => $user->getName(),
439 $this->getItemsFromApiResponse( $result )
443 public function testUserIdPropParameter() {
444 $user = $this->getLoggedInTestUser();
445 $userEditTarget = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
446 $anonEditTarget = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPageA' );
453 $this->doAnonPageEdit(
458 $this->watchPages( $user, [ $userEditTarget, $anonEditTarget ] );
460 $result = $this->doListWatchlistRequest( [ 'wlprop' => 'userid', ] );
472 'user' => $user->getId(),
473 'userid' => $user->getId(),
476 $this->getItemsFromApiResponse( $result )
480 public function testCommentPropParameter() {
481 $user = $this->getLoggedInTestUser();
482 $target = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
487 'Create the <b>page</b>'
489 $this->watchPages( $user, [ $target ] );
491 $result = $this->doListWatchlistRequest( [ 'wlprop' => 'comment', ] );
497 'comment' => 'Create the <b>page</b>',
500 $this->getItemsFromApiResponse( $result )
504 public function testParsedCommentPropParameter() {
505 $user = $this->getLoggedInTestUser();
506 $target = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
511 'Create the <b>page</b>'
513 $this->watchPages( $user, [ $target ] );
515 $result = $this->doListWatchlistRequest( [ 'wlprop' => 'parsedcomment', ] );
521 'parsedcomment' => 'Create the <b>page</b>',
524 $this->getItemsFromApiResponse( $result )
528 public function testTimestampPropParameter() {
529 $user = $this->getLoggedInTestUser();
530 $target = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
537 $this->watchPages( $user, [ $target ] );
539 $result = $this->doListWatchlistRequest( [ 'wlprop' => 'timestamp', ] );
540 $items = $this->getItemsFromApiResponse( $result );
542 $this->assertCount( 1, $items );
543 $this->assertArrayHasKey( 'timestamp', $items[0] );
544 $this->assertInternalType( 'string', $items[0]['timestamp'] );
547 public function testSizesPropParameter() {
548 $user = $this->getLoggedInTestUser();
549 $target = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
556 $this->watchPages( $user, [ $target ] );
558 $result = $this->doListWatchlistRequest( [ 'wlprop' => 'sizes', ] );
568 $this->getItemsFromApiResponse( $result )
572 public function testNotificationTimestampPropParameter() {
573 $otherUser = $this->getNonLoggedInTestUser();
574 $target = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
581 $store = $this->getWatchedItemStore();
582 $store->addWatch( $this->getLoggedInTestUser(), $target );
583 $store->updateNotificationTimestamp(
589 $result = $this->doListWatchlistRequest( [ 'wlprop' => 'notificationtimestamp', ] );
595 'notificationtimestamp' => '2015-12-12T01:01:01Z',
598 $this->getItemsFromApiResponse( $result )
602 private function setupPatrolledSpecificFixtures( User
$user ) {
603 $target = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
605 $this->doPatrolledPageEdit(
609 'Create the page (this gets patrolled)',
613 $this->watchPages( $user, [ $target ] );
616 public function testPatrolPropParameter() {
617 $testUser = static::getTestSysop();
618 $user = $testUser->getUser();
619 $this->setupPatrolledSpecificFixtures( $user );
621 $result = $this->doListWatchlistRequest( [ 'wlprop' => 'patrol', ], $user );
628 'unpatrolled' => false,
631 $this->getItemsFromApiResponse( $result )
635 private function createPageAndDeleteIt( LinkTarget
$target ) {
637 $this->getLoggedInTestUser(),
640 'Create the page that will be deleted'
642 $this->deletePage( $target, 'Important Reason' );
645 public function testLoginfoPropParameter() {
646 $target = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
647 $this->createPageAndDeleteIt( $target );
649 $this->watchPages( $this->getLoggedInTestUser(), [ $target ] );
651 $result = $this->doListWatchlistRequest( [ 'wlprop' => 'loginfo', ] );
653 $this->assertArraySubsetsEqual(
654 $this->getItemsFromApiResponse( $result ),
658 'logtype' => 'delete',
659 'logaction' => 'delete',
663 [ 'type', 'logtype', 'logaction', 'logparams' ],
668 public function testEmptyPropParameter() {
669 $user = $this->getLoggedInTestUser();
670 $target = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
677 $this->watchPages( $user, [ $target ] );
679 $result = $this->doListWatchlistRequest( [ 'wlprop' => '', ] );
687 $this->getItemsFromApiResponse( $result )
691 public function testNamespaceParam() {
692 $user = $this->getLoggedInTestUser();
693 $subjectTarget = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
694 $talkTarget = new TitleValue( 1, 'ApiQueryWatchlistIntegrationTestPage' );
699 'target' => $subjectTarget,
700 'content' => 'Some Content',
701 'summary' => 'Create the page',
704 'target' => $talkTarget,
705 'content' => 'Some Content',
706 'summary' => 'Create the talk page',
710 $this->watchPages( $user, [ $subjectTarget, $talkTarget ] );
712 $result = $this->doListWatchlistRequest( [ 'wlnamespace' => '0', ] );
714 $this->assertArraySubsetsEqual(
715 $this->getItemsFromApiResponse( $result ),
719 'title' => $this->getPrefixedText( $subjectTarget ),
726 public function testUserParam() {
727 $user = $this->getLoggedInTestUser();
728 $otherUser = $this->getNonLoggedInTestUser();
729 $subjectTarget = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
730 $talkTarget = new TitleValue( 1, 'ApiQueryWatchlistIntegrationTestPage' );
740 'What is this page about?',
741 'Create the talk page'
743 $this->watchPages( $user, [ $subjectTarget, $talkTarget ] );
745 $result = $this->doListWatchlistRequest( [
746 'wlprop' => 'user|title',
747 'wluser' => $otherUser->getName(),
754 'ns' => $talkTarget->getNamespace(),
755 'title' => $this->getPrefixedText( $talkTarget ),
756 'user' => $otherUser->getName(),
759 $this->getItemsFromApiResponse( $result )
763 public function testExcludeUserParam() {
764 $user = $this->getLoggedInTestUser();
765 $otherUser = $this->getNonLoggedInTestUser();
766 $subjectTarget = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
767 $talkTarget = new TitleValue( 1, 'ApiQueryWatchlistIntegrationTestPage' );
777 'What is this page about?',
778 'Create the talk page'
780 $this->watchPages( $user, [ $subjectTarget, $talkTarget ] );
782 $result = $this->doListWatchlistRequest( [
783 'wlprop' => 'user|title',
784 'wlexcludeuser' => $otherUser->getName(),
791 'ns' => $subjectTarget->getNamespace(),
792 'title' => $this->getPrefixedText( $subjectTarget ),
793 'user' => $user->getName(),
796 $this->getItemsFromApiResponse( $result )
800 public function testShowMinorParams() {
801 $user = $this->getLoggedInTestUser();
802 $target = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
808 'content' => 'Some Content',
809 'summary' => 'Create the page',
813 'content' => 'Slightly Better Content',
814 'summary' => 'Change content',
819 $this->watchPages( $user, [ $target ] );
821 $resultMinor = $this->doListWatchlistRequest( [ 'wlshow' => 'minor', 'wlprop' => 'flags' ] );
822 $resultNotMinor = $this->doListWatchlistRequest( [ 'wlshow' => '!minor', 'wlprop' => 'flags' ] );
824 $this->assertArraySubsetsEqual(
825 $this->getItemsFromApiResponse( $resultMinor ),
831 $this->assertEmpty( $this->getItemsFromApiResponse( $resultNotMinor ) );
834 public function testShowBotParams() {
835 $user = $this->getLoggedInTestUser();
836 $target = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
837 $this->doBotPageEdit(
843 $this->watchPages( $user, [ $target ] );
845 $resultBot = $this->doListWatchlistRequest( [ 'wlshow' => 'bot' ] );
846 $resultNotBot = $this->doListWatchlistRequest( [ 'wlshow' => '!bot' ] );
848 $this->assertArraySubsetsEqual(
849 $this->getItemsFromApiResponse( $resultBot ),
855 $this->assertEmpty( $this->getItemsFromApiResponse( $resultNotBot ) );
858 public function testShowAnonParams() {
859 $user = $this->getLoggedInTestUser();
860 $target = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
861 $this->doAnonPageEdit(
866 $this->watchPages( $user, [ $target ] );
868 $resultAnon = $this->doListWatchlistRequest( [
872 $resultNotAnon = $this->doListWatchlistRequest( [
877 $this->assertArraySubsetsEqual(
878 $this->getItemsFromApiResponse( $resultAnon ),
884 $this->assertEmpty( $this->getItemsFromApiResponse( $resultNotAnon ) );
887 public function testShowUnreadParams() {
888 $user = $this->getLoggedInTestUser();
889 $otherUser = $this->getNonLoggedInTestUser();
890 $subjectTarget = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
891 $talkTarget = new TitleValue( 1, 'ApiQueryWatchlistIntegrationTestPage' );
902 'Create the talk page'
904 $store = $this->getWatchedItemStore();
905 $store->addWatchBatchForUser( $user, [ $subjectTarget, $talkTarget ] );
906 $store->updateNotificationTimestamp(
912 $resultUnread = $this->doListWatchlistRequest( [
913 'wlprop' => 'notificationtimestamp|title',
916 $resultNotUnread = $this->doListWatchlistRequest( [
917 'wlprop' => 'notificationtimestamp|title',
918 'wlshow' => '!unread'
925 'notificationtimestamp' => '2015-12-12T01:01:01Z',
926 'ns' => $talkTarget->getNamespace(),
927 'title' => $this->getPrefixedText( $talkTarget )
930 $this->getItemsFromApiResponse( $resultUnread )
936 'notificationtimestamp' => '',
937 'ns' => $subjectTarget->getNamespace(),
938 'title' => $this->getPrefixedText( $subjectTarget )
941 $this->getItemsFromApiResponse( $resultNotUnread )
945 public function testShowPatrolledParams() {
946 $user = static::getTestSysop()->getUser();
947 $this->setupPatrolledSpecificFixtures( $user );
949 $resultPatrolled = $this->doListWatchlistRequest( [
950 'wlprop' => 'patrol',
951 'wlshow' => 'patrolled'
953 $resultNotPatrolled = $this->doListWatchlistRequest( [
954 'wlprop' => 'patrol',
955 'wlshow' => '!patrolled'
963 'unpatrolled' => false,
966 $this->getItemsFromApiResponse( $resultPatrolled )
968 $this->assertEmpty( $this->getItemsFromApiResponse( $resultNotPatrolled ) );
971 public function testNewAndEditTypeParameters() {
972 $user = $this->getLoggedInTestUser();
973 $subjectTarget = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
974 $talkTarget = new TitleValue( 1, 'ApiQueryWatchlistIntegrationTestPage' );
979 'target' => $subjectTarget,
980 'content' => 'Some Content',
981 'summary' => 'Create the page',
984 'target' => $subjectTarget,
985 'content' => 'Some Other Content',
986 'summary' => 'Change the content',
989 'target' => $talkTarget,
990 'content' => 'Some Talk Page Content',
991 'summary' => 'Create Talk page',
995 $this->watchPages( $user, [ $subjectTarget, $talkTarget ] );
997 $resultNew = $this->doListWatchlistRequest( [ 'wlprop' => 'title', 'wltype' => 'new' ] );
998 $resultEdit = $this->doListWatchlistRequest( [ 'wlprop' => 'title', 'wltype' => 'edit' ] );
1000 $this->assertEquals(
1004 'ns' => $talkTarget->getNamespace(),
1005 'title' => $this->getPrefixedText( $talkTarget ),
1008 $this->getItemsFromApiResponse( $resultNew )
1010 $this->assertEquals(
1014 'ns' => $subjectTarget->getNamespace(),
1015 'title' => $this->getPrefixedText( $subjectTarget ),
1018 $this->getItemsFromApiResponse( $resultEdit )
1022 public function testLogTypeParameters() {
1023 $user = $this->getLoggedInTestUser();
1024 $subjectTarget = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
1025 $talkTarget = new TitleValue( 1, 'ApiQueryWatchlistIntegrationTestPage' );
1026 $this->createPageAndDeleteIt( $subjectTarget );
1030 'Some Talk Page Content',
1033 $this->watchPages( $user, [ $subjectTarget, $talkTarget ] );
1035 $result = $this->doListWatchlistRequest( [ 'wlprop' => 'title', 'wltype' => 'log' ] );
1037 $this->assertEquals(
1041 'ns' => $subjectTarget->getNamespace(),
1042 'title' => $this->getPrefixedText( $subjectTarget ),
1045 $this->getItemsFromApiResponse( $result )
1049 private function getExternalRC( LinkTarget
$target ) {
1050 $title = Title
::newFromLinkTarget( $target );
1052 $rc = new RecentChange
;
1053 $rc->mTitle
= $title;
1055 'rc_timestamp' => wfTimestamp( TS_MW
),
1056 'rc_namespace' => $title->getNamespace(),
1057 'rc_title' => $title->getDBkey(),
1058 'rc_type' => RC_EXTERNAL
,
1059 'rc_source' => 'foo',
1061 'rc_cur_id' => $title->getArticleID(),
1063 'rc_user_text' => 'External User',
1065 'rc_this_oldid' => $title->getLatestRevID(),
1066 'rc_last_oldid' => $title->getLatestRevID(),
1069 'rc_patrolled' => 0,
1071 'rc_old_len' => $title->getLength(),
1072 'rc_new_len' => $title->getLength(),
1075 'rc_log_type' => null,
1076 'rc_log_action' => '',
1080 'prefixedDBkey' => $title->getPrefixedDBkey(),
1081 'lastTimestamp' => 0,
1082 'oldSize' => $title->getLength(),
1083 'newSize' => $title->getLength(),
1084 'pageStatus' => 'changed'
1090 public function testExternalTypeParameters() {
1091 $user = $this->getLoggedInTestUser();
1092 $subjectTarget = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
1093 $talkTarget = new TitleValue( 1, 'ApiQueryWatchlistIntegrationTestPage' );
1103 'Some Talk Page Content',
1107 $rc = $this->getExternalRC( $subjectTarget );
1110 $this->watchPages( $user, [ $subjectTarget, $talkTarget ] );
1112 $result = $this->doListWatchlistRequest( [ 'wlprop' => 'title', 'wltype' => 'external' ] );
1114 $this->assertEquals(
1117 'type' => 'external',
1118 'ns' => $subjectTarget->getNamespace(),
1119 'title' => $this->getPrefixedText( $subjectTarget ),
1122 $this->getItemsFromApiResponse( $result )
1126 public function testCategorizeTypeParameter() {
1127 $user = $this->getLoggedInTestUser();
1128 $subjectTarget = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
1129 $categoryTarget = new TitleValue( NS_CATEGORY
, 'ApiQueryWatchlistIntegrationTestCategory' );
1134 'target' => $categoryTarget,
1135 'content' => 'Some Content',
1136 'summary' => 'Create the category',
1139 'target' => $subjectTarget,
1140 'content' => 'Some Content [[Category:ApiQueryWatchlistIntegrationTestCategory]]t',
1141 'summary' => 'Create the page and add it to the category',
1145 $title = Title
::newFromLinkTarget( $subjectTarget );
1146 $revision = Revision
::newFromTitle( $title );
1148 $rc = RecentChange
::newForCategorization(
1149 $revision->getTimestamp(),
1150 Title
::newFromLinkTarget( $categoryTarget ),
1152 $revision->getComment(),
1161 $this->watchPages( $user, [ $subjectTarget, $categoryTarget ] );
1163 $result = $this->doListWatchlistRequest( [ 'wlprop' => 'title', 'wltype' => 'categorize' ] );
1165 $this->assertEquals(
1168 'type' => 'categorize',
1169 'ns' => $categoryTarget->getNamespace(),
1170 'title' => $this->getPrefixedText( $categoryTarget ),
1173 $this->getItemsFromApiResponse( $result )
1177 public function testLimitParam() {
1178 $user = $this->getLoggedInTestUser();
1179 $target1 = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
1180 $target2 = new TitleValue( 1, 'ApiQueryWatchlistIntegrationTestPage' );
1181 $target3 = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage2' );
1186 'target' => $target1,
1187 'content' => 'Some Content',
1188 'summary' => 'Create the page',
1191 'target' => $target2,
1192 'content' => 'Some Talk Page Content',
1193 'summary' => 'Create Talk page',
1196 'target' => $target3,
1197 'content' => 'Some Other Content',
1198 'summary' => 'Create the page',
1202 $this->watchPages( $user, [ $target1, $target2, $target3 ] );
1204 $resultWithoutLimit = $this->doListWatchlistRequest( [ 'wlprop' => 'title' ] );
1205 $resultWithLimit = $this->doListWatchlistRequest( [ 'wllimit' => 2, 'wlprop' => 'title' ] );
1207 $this->assertEquals(
1211 'ns' => $target3->getNamespace(),
1212 'title' => $this->getPrefixedText( $target3 )
1216 'ns' => $target2->getNamespace(),
1217 'title' => $this->getPrefixedText( $target2 )
1221 'ns' => $target1->getNamespace(),
1222 'title' => $this->getPrefixedText( $target1 )
1225 $this->getItemsFromApiResponse( $resultWithoutLimit )
1227 $this->assertEquals(
1231 'ns' => $target3->getNamespace(),
1232 'title' => $this->getPrefixedText( $target3 )
1236 'ns' => $target2->getNamespace(),
1237 'title' => $this->getPrefixedText( $target2 )
1240 $this->getItemsFromApiResponse( $resultWithLimit )
1242 $this->assertArrayHasKey( 'continue', $resultWithLimit[0] );
1243 $this->assertArrayHasKey( 'wlcontinue', $resultWithLimit[0]['continue'] );
1246 public function testAllRevParam() {
1247 $user = $this->getLoggedInTestUser();
1248 $target = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
1253 'target' => $target,
1254 'content' => 'Some Content',
1255 'summary' => 'Create the page',
1258 'target' => $target,
1259 'content' => 'Some Other Content',
1260 'summary' => 'Change the content',
1264 $this->watchPages( $user, [ $target ] );
1266 $resultAllRev = $this->doListWatchlistRequest( [ 'wlprop' => 'title', 'wlallrev' => '', ] );
1267 $resultNoAllRev = $this->doListWatchlistRequest( [ 'wlprop' => 'title' ] );
1269 $this->assertEquals(
1273 'ns' => $target->getNamespace(),
1274 'title' => $this->getPrefixedText( $target ),
1277 $this->getItemsFromApiResponse( $resultNoAllRev )
1279 $this->assertEquals(
1283 'ns' => $target->getNamespace(),
1284 'title' => $this->getPrefixedText( $target ),
1288 'ns' => $target->getNamespace(),
1289 'title' => $this->getPrefixedText( $target ),
1292 $this->getItemsFromApiResponse( $resultAllRev )
1296 public function testDirParams() {
1297 $user = $this->getLoggedInTestUser();
1298 $subjectTarget = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
1299 $talkTarget = new TitleValue( 1, 'ApiQueryWatchlistIntegrationTestPage' );
1304 'target' => $subjectTarget,
1305 'content' => 'Some Content',
1306 'summary' => 'Create the page',
1309 'target' => $talkTarget,
1310 'content' => 'Some Talk Page Content',
1311 'summary' => 'Create Talk page',
1315 $this->watchPages( $user, [ $subjectTarget, $talkTarget ] );
1317 $resultDirOlder = $this->doListWatchlistRequest( [ 'wldir' => 'older', 'wlprop' => 'title' ] );
1318 $resultDirNewer = $this->doListWatchlistRequest( [ 'wldir' => 'newer', 'wlprop' => 'title' ] );
1320 $this->assertEquals(
1324 'ns' => $talkTarget->getNamespace(),
1325 'title' => $this->getPrefixedText( $talkTarget )
1329 'ns' => $subjectTarget->getNamespace(),
1330 'title' => $this->getPrefixedText( $subjectTarget )
1333 $this->getItemsFromApiResponse( $resultDirOlder )
1335 $this->assertEquals(
1339 'ns' => $subjectTarget->getNamespace(),
1340 'title' => $this->getPrefixedText( $subjectTarget )
1344 'ns' => $talkTarget->getNamespace(),
1345 'title' => $this->getPrefixedText( $talkTarget )
1348 $this->getItemsFromApiResponse( $resultDirNewer )
1352 public function testStartEndParams() {
1353 $user = $this->getLoggedInTestUser();
1354 $target = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
1361 $this->watchPages( $user, [ $target ] );
1363 $resultStart = $this->doListWatchlistRequest( [
1364 'wlstart' => '20010115000000',
1366 'wlprop' => 'title',
1368 $resultEnd = $this->doListWatchlistRequest( [
1369 'wlend' => '20010115000000',
1371 'wlprop' => 'title',
1374 $this->assertEquals(
1378 'ns' => $target->getNamespace(),
1379 'title' => $this->getPrefixedText( $target ),
1382 $this->getItemsFromApiResponse( $resultStart )
1384 $this->assertEmpty( $this->getItemsFromApiResponse( $resultEnd ) );
1387 public function testContinueParam() {
1388 $user = $this->getLoggedInTestUser();
1389 $target1 = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
1390 $target2 = new TitleValue( 1, 'ApiQueryWatchlistIntegrationTestPage' );
1391 $target3 = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage2' );
1396 'target' => $target1,
1397 'content' => 'Some Content',
1398 'summary' => 'Create the page',
1401 'target' => $target2,
1402 'content' => 'Some Talk Page Content',
1403 'summary' => 'Create Talk page',
1406 'target' => $target3,
1407 'content' => 'Some Other Content',
1408 'summary' => 'Create the page',
1412 $this->watchPages( $user, [ $target1, $target2, $target3 ] );
1414 $firstResult = $this->doListWatchlistRequest( [ 'wllimit' => 2, 'wlprop' => 'title' ] );
1415 $this->assertArrayHasKey( 'continue', $firstResult[0] );
1416 $this->assertArrayHasKey( 'wlcontinue', $firstResult[0]['continue'] );
1418 $continuationParam = $firstResult[0]['continue']['wlcontinue'];
1420 $continuedResult = $this->doListWatchlistRequest(
1421 [ 'wlcontinue' => $continuationParam, 'wlprop' => 'title' ]
1424 $this->assertEquals(
1428 'ns' => $target3->getNamespace(),
1429 'title' => $this->getPrefixedText( $target3 ),
1433 'ns' => $target2->getNamespace(),
1434 'title' => $this->getPrefixedText( $target2 ),
1437 $this->getItemsFromApiResponse( $firstResult )
1439 $this->assertEquals(
1443 'ns' => $target1->getNamespace(),
1444 'title' => $this->getPrefixedText( $target1 )
1447 $this->getItemsFromApiResponse( $continuedResult )
1451 public function testOwnerAndTokenParams() {
1452 $target = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
1454 $this->getLoggedInTestUser(),
1460 $otherUser = $this->getNonLoggedInTestUser();
1461 $otherUser->setOption( 'watchlisttoken', '1234567890' );
1462 $otherUser->saveSettings();
1464 $this->watchPages( $otherUser, [ $target ] );
1466 $result = $this->doListWatchlistRequest( [
1467 'wlowner' => $otherUser->getName(),
1468 'wltoken' => '1234567890',
1469 'wlprop' => 'title',
1472 $this->assertEquals(
1476 'ns' => $target->getNamespace(),
1477 'title' => $this->getPrefixedText( $target )
1480 $this->getItemsFromApiResponse( $result )
1484 public function testOwnerAndTokenParams_wrongToken() {
1485 $otherUser = $this->getNonLoggedInTestUser();
1486 $otherUser->setOption( 'watchlisttoken', '1234567890' );
1487 $otherUser->saveSettings();
1489 $this->setExpectedException( UsageException
::class, 'Incorrect watchlist token provided' );
1491 $this->doListWatchlistRequest( [
1492 'wlowner' => $otherUser->getName(),
1493 'wltoken' => 'wrong-token',
1497 public function testOwnerAndTokenParams_noWatchlistTokenSet() {
1498 $this->setExpectedException( UsageException
::class, 'Incorrect watchlist token provided' );
1500 $this->doListWatchlistRequest( [
1501 'wlowner' => $this->getNonLoggedInTestUser()->getName(),
1502 'wltoken' => 'some-token',
1506 public function testGeneratorWatchlistPropInfo_returnsWatchedPages() {
1507 $user = $this->getLoggedInTestUser();
1508 $target = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
1515 $this->watchPages( $user, [ $target ] );
1517 $result = $this->doGeneratorWatchlistRequest( [ 'prop' => 'info' ] );
1519 $this->assertArrayHasKey( 'query', $result[0] );
1520 $this->assertArrayHasKey( 'pages', $result[0]['query'] );
1522 // $result[0]['query']['pages'] uses page ids as keys. Page ids don't matter here, so drop them
1523 $pages = array_values( $result[0]['query']['pages'] );
1525 $this->assertArraySubsetsEqual(
1529 'ns' => $target->getNamespace(),
1530 'title' => $this->getPrefixedText( $target ),
1534 [ 'ns', 'title', 'new' ]
1538 public function testGeneratorWatchlistPropRevisions_returnsWatchedItemsRevisions() {
1539 $user = $this->getLoggedInTestUser();
1540 $target = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
1545 'target' => $target,
1546 'content' => 'Some Content',
1547 'summary' => 'Create the page',
1550 'target' => $target,
1551 'content' => 'Some Other Content',
1552 'summary' => 'Change the content',
1556 $this->watchPages( $user, [ $target ] );
1558 $result = $this->doGeneratorWatchlistRequest( [ 'prop' => 'revisions', 'gwlallrev' => '' ] );
1560 $this->assertArrayHasKey( 'query', $result[0] );
1561 $this->assertArrayHasKey( 'pages', $result[0]['query'] );
1563 // $result[0]['query']['pages'] uses page ids as keys. Page ids don't matter here, so drop them
1564 $pages = array_values( $result[0]['query']['pages'] );
1566 $this->assertCount( 1, $pages );
1567 $this->assertEquals( 0, $pages[0]['ns'] );
1568 $this->assertEquals( $this->getPrefixedText( $target ), $pages[0]['title'] );
1569 $this->assertArraySubsetsEqual(
1570 $pages[0]['revisions'],
1573 'comment' => 'Create the page',
1574 'user' => $user->getName(),
1578 'comment' => 'Change the content',
1579 'user' => $user->getName(),
1583 [ 'comment', 'user', 'minor' ]