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();
28 private function getLoggedInTestUser() {
29 return self
::$users['ApiQueryWatchlistIntegrationTestUser']->getUser();
32 private function getNonLoggedInTestUser() {
33 return self
::$users['ApiQueryWatchlistIntegrationTestUser2']->getUser();
36 private function doPageEdit( User
$user, LinkTarget
$target, $content, $summary ) {
37 $title = Title
::newFromLinkTarget( $target );
38 $page = WikiPage
::factory( $title );
40 ContentHandler
::makeContent( $content, $title ),
48 private function doMinorPageEdit( User
$user, LinkTarget
$target, $content, $summary ) {
49 $title = Title
::newFromLinkTarget( $target );
50 $page = WikiPage
::factory( $title );
52 ContentHandler
::makeContent( $content, $title ),
60 private function doBotPageEdit( User
$user, LinkTarget
$target, $content, $summary ) {
61 $title = Title
::newFromLinkTarget( $target );
62 $page = WikiPage
::factory( $title );
64 ContentHandler
::makeContent( $content, $title ),
72 private function doAnonPageEdit( LinkTarget
$target, $content, $summary ) {
73 $title = Title
::newFromLinkTarget( $target );
74 $page = WikiPage
::factory( $title );
76 ContentHandler
::makeContent( $content, $title ),
84 private function doPatrolledPageEdit(
91 $title = Title
::newFromLinkTarget( $target );
92 $page = WikiPage
::factory( $title );
93 $status = $page->doEditContent(
94 ContentHandler
::makeContent( $content, $title ),
100 /** @var Revision $rev */
101 $rev = $status->value
['revision'];
102 $rc = $rev->getRecentChange();
103 $rc->doMarkPatrolled( $patrollingUser, false, [] );
106 private function deletePage( LinkTarget
$target, $reason ) {
107 $title = Title
::newFromLinkTarget( $target );
108 $page = WikiPage
::factory( $title );
109 $page->doDeleteArticleReal( $reason );
113 * Performs a batch of page edits as a specified user
115 * @param array $editData associative array, keys:
116 * - target => LinkTarget page to edit
117 * - content => string new content
118 * - summary => string edit summary
119 * - minorEdit => bool mark as minor edit if true (defaults to false)
120 * - botEdit => bool mark as bot edit if true (defaults to false)
122 private function doPageEdits( User
$user, array $editData ) {
123 foreach ( $editData as $singleEditData ) {
124 if ( array_key_exists( 'minorEdit', $singleEditData ) && $singleEditData['minorEdit'] ) {
125 $this->doMinorPageEdit(
127 $singleEditData['target'],
128 $singleEditData['content'],
129 $singleEditData['summary']
133 if ( array_key_exists( 'botEdit', $singleEditData ) && $singleEditData['botEdit'] ) {
134 $this->doBotPageEdit(
136 $singleEditData['target'],
137 $singleEditData['content'],
138 $singleEditData['summary']
144 $singleEditData['target'],
145 $singleEditData['content'],
146 $singleEditData['summary']
151 private function getWatchedItemStore() {
152 return MediaWikiServices
::getInstance()->getWatchedItemStore();
157 * @param LinkTarget[] $targets
159 private function watchPages( User
$user, array $targets ) {
160 $store = $this->getWatchedItemStore();
161 $store->addWatchBatchForUser( $user, $targets );
164 private function doListWatchlistRequest( array $params = [], $user = null ) {
165 if ( $user === null ) {
166 $user = $this->getLoggedInTestUser();
168 return $this->doApiRequest(
170 [ 'action' => 'query', 'list' => 'watchlist' ],
172 ), null, false, $user
176 private function doGeneratorWatchlistRequest( array $params = [] ) {
177 return $this->doApiRequest(
179 [ 'action' => 'query', 'generator' => 'watchlist' ],
181 ), null, false, $this->getLoggedInTestUser()
185 private function getItemsFromApiResponse( array $response ) {
186 return $response[0]['query']['watchlist'];
190 * Convenience method to assert that actual items array fetched from API is equal to the expected
191 * array, Unlike assertEquals this only checks if values of specified keys are equal in both
192 * arrays. This could be used e.g. not to compare IDs that could change between test run
193 * but only stable keys.
194 * Optionally this also checks that specified keys are present in the actual item without
195 * performing any checks on the related values.
197 * @param array $actualItems array of actual items (associative arrays)
198 * @param array $expectedItems array of expected items (associative arrays),
199 * those items have less keys than actual items
200 * @param array $keysUsedInValueComparison list of keys of the actual item that will be used
201 * in the comparison of values
202 * @param array $requiredKeys optional, list of keys that must be present in the
203 * actual items. Values of those keys are not checked.
205 private function assertArraySubsetsEqual(
207 array $expectedItems,
208 array $keysUsedInValueComparison,
209 array $requiredKeys = []
211 $this->assertCount( count( $expectedItems ), $actualItems );
213 // not checking values of all keys of the actual item, so removing unwanted keys from comparison
214 $actualItemsOnlyComparedValues = array_map(
215 function ( array $item ) use ( $keysUsedInValueComparison ) {
216 return array_intersect_key( $item, array_flip( $keysUsedInValueComparison ) );
223 $actualItemsOnlyComparedValues
226 // Check that each item in $actualItems contains all of keys specified in $requiredKeys
227 $actualItemsKeysOnly = array_map( 'array_keys', $actualItems );
228 foreach ( $actualItemsKeysOnly as $keysOfTheItem ) {
229 $this->assertEmpty( array_diff( $requiredKeys, $keysOfTheItem ) );
233 private function getTitleFormatter() {
234 return new MediaWikiTitleCodec(
235 Language
::factory( 'en' ),
236 MediaWikiServices
::getInstance()->getGenderCache()
240 private function getPrefixedText( LinkTarget
$target ) {
241 $formatter = $this->getTitleFormatter();
242 return $formatter->getPrefixedText( $target );
245 private function cleanTestUsersWatchlist() {
246 $user = $this->getLoggedInTestUser();
247 $store = $this->getWatchedItemStore();
248 $items = $store->getWatchedItemsForUser( $user );
249 foreach ( $items as $item ) {
250 $store->removeWatch( $user, $item->getLinkTarget() );
254 public function testListWatchlist_returnsWatchedItemsWithRCInfo() {
255 // Clean up after previous tests that might have added something to the watchlist of
256 // the user with the same user ID as user used here as the test user
257 $this->cleanTestUsersWatchlist();
259 $user = $this->getLoggedInTestUser();
260 $target = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
267 $this->watchPages( $user, [ $target ] );
269 $result = $this->doListWatchlistRequest();
271 $this->assertArrayHasKey( 'query', $result[0] );
272 $this->assertArrayHasKey( 'watchlist', $result[0]['query'] );
274 $this->assertArraySubsetsEqual(
275 $this->getItemsFromApiResponse( $result ),
279 'ns' => $target->getNamespace(),
280 'title' => $this->getPrefixedText( $target ),
286 [ 'type', 'ns', 'title', 'bot', 'new', 'minor' ],
287 [ 'pageid', 'revid', 'old_revid' ]
291 public function testIdsPropParameter() {
292 $user = $this->getLoggedInTestUser();
293 $target = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
300 $this->watchPages( $user, [ $target ] );
302 $result = $this->doListWatchlistRequest( [ 'wlprop' => 'ids', ] );
303 $items = $this->getItemsFromApiResponse( $result );
305 $this->assertCount( 1, $items );
306 $this->assertArrayHasKey( 'pageid', $items[0] );
307 $this->assertArrayHasKey( 'revid', $items[0] );
308 $this->assertArrayHasKey( 'old_revid', $items[0] );
309 $this->assertEquals( 'new', $items[0]['type'] );
312 public function testTitlePropParameter() {
313 $user = $this->getLoggedInTestUser();
314 $subjectTarget = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
315 $talkTarget = new TitleValue( 1, 'ApiQueryWatchlistIntegrationTestPage' );
320 'target' => $subjectTarget,
321 'content' => 'Some Content',
322 'summary' => 'Create the page',
325 'target' => $talkTarget,
326 'content' => 'Some Talk Page Content',
327 'summary' => 'Create Talk page',
331 $this->watchPages( $user, [ $subjectTarget, $talkTarget ] );
333 $result = $this->doListWatchlistRequest( [ 'wlprop' => 'title', ] );
339 'ns' => $talkTarget->getNamespace(),
340 'title' => $this->getPrefixedText( $talkTarget ),
344 'ns' => $subjectTarget->getNamespace(),
345 'title' => $this->getPrefixedText( $subjectTarget ),
348 $this->getItemsFromApiResponse( $result )
352 public function testFlagsPropParameter() {
353 $user = $this->getLoggedInTestUser();
354 $normalEditTarget = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
355 $minorEditTarget = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPageM' );
356 $botEditTarget = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPageB' );
361 'target' => $normalEditTarget,
362 'content' => 'Some Content',
363 'summary' => 'Create the page',
366 'target' => $minorEditTarget,
367 'content' => 'Some Content',
368 'summary' => 'Create the page',
371 'target' => $minorEditTarget,
372 'content' => 'Slightly Better Content',
373 'summary' => 'Change content',
377 'target' => $botEditTarget,
378 'content' => 'Some Content',
379 'summary' => 'Create the page with a bot',
384 $this->watchPages( $user, [ $normalEditTarget, $minorEditTarget, $botEditTarget ] );
386 $result = $this->doListWatchlistRequest( [ 'wlprop' => 'flags', ] );
409 $this->getItemsFromApiResponse( $result )
413 public function testUserPropParameter() {
414 $user = $this->getLoggedInTestUser();
415 $userEditTarget = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
416 $anonEditTarget = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPageA' );
423 $this->doAnonPageEdit(
428 $this->watchPages( $user, [ $userEditTarget, $anonEditTarget ] );
430 $result = $this->doListWatchlistRequest( [ 'wlprop' => 'user', ] );
437 'user' => User
::newFromId( 0 )->getName(),
441 'user' => $user->getName(),
444 $this->getItemsFromApiResponse( $result )
448 public function testUserIdPropParameter() {
449 $user = $this->getLoggedInTestUser();
450 $userEditTarget = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
451 $anonEditTarget = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPageA' );
458 $this->doAnonPageEdit(
463 $this->watchPages( $user, [ $userEditTarget, $anonEditTarget ] );
465 $result = $this->doListWatchlistRequest( [ 'wlprop' => 'userid', ] );
477 'user' => $user->getId(),
478 'userid' => $user->getId(),
481 $this->getItemsFromApiResponse( $result )
485 public function testCommentPropParameter() {
486 $user = $this->getLoggedInTestUser();
487 $target = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
492 'Create the <b>page</b>'
494 $this->watchPages( $user, [ $target ] );
496 $result = $this->doListWatchlistRequest( [ 'wlprop' => 'comment', ] );
502 'comment' => 'Create the <b>page</b>',
505 $this->getItemsFromApiResponse( $result )
509 public function testParsedCommentPropParameter() {
510 $user = $this->getLoggedInTestUser();
511 $target = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
516 'Create the <b>page</b>'
518 $this->watchPages( $user, [ $target ] );
520 $result = $this->doListWatchlistRequest( [ 'wlprop' => 'parsedcomment', ] );
526 'parsedcomment' => 'Create the <b>page</b>',
529 $this->getItemsFromApiResponse( $result )
533 public function testTimestampPropParameter() {
534 $user = $this->getLoggedInTestUser();
535 $target = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
542 $this->watchPages( $user, [ $target ] );
544 $result = $this->doListWatchlistRequest( [ 'wlprop' => 'timestamp', ] );
545 $items = $this->getItemsFromApiResponse( $result );
547 $this->assertCount( 1, $items );
548 $this->assertArrayHasKey( 'timestamp', $items[0] );
549 $this->assertInternalType( 'string', $items[0]['timestamp'] );
552 public function testSizesPropParameter() {
553 $user = $this->getLoggedInTestUser();
554 $target = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
561 $this->watchPages( $user, [ $target ] );
563 $result = $this->doListWatchlistRequest( [ 'wlprop' => 'sizes', ] );
573 $this->getItemsFromApiResponse( $result )
577 public function testNotificationTimestampPropParameter() {
578 $otherUser = $this->getNonLoggedInTestUser();
579 $target = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
586 $store = $this->getWatchedItemStore();
587 $store->addWatch( $this->getLoggedInTestUser(), $target );
588 $store->updateNotificationTimestamp(
594 $result = $this->doListWatchlistRequest( [ 'wlprop' => 'notificationtimestamp', ] );
600 'notificationtimestamp' => '2015-12-12T01:01:01Z',
603 $this->getItemsFromApiResponse( $result )
607 private function setupPatrolledSpecificFixtures( User
$user ) {
608 $target = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
610 $this->doPatrolledPageEdit(
614 'Create the page (this gets patrolled)',
618 $this->watchPages( $user, [ $target ] );
621 public function testPatrolPropParameter() {
622 $testUser = static::getTestSysop();
623 $user = $testUser->getUser();
624 $this->setupPatrolledSpecificFixtures( $user );
626 $result = $this->doListWatchlistRequest( [ 'wlprop' => 'patrol', ], $user );
633 'unpatrolled' => false,
634 'autopatrolled' => false,
637 $this->getItemsFromApiResponse( $result )
641 private function createPageAndDeleteIt( LinkTarget
$target ) {
643 $this->getLoggedInTestUser(),
646 'Create the page that will be deleted'
648 $this->deletePage( $target, 'Important Reason' );
651 public function testLoginfoPropParameter() {
652 $target = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
653 $this->createPageAndDeleteIt( $target );
655 $this->watchPages( $this->getLoggedInTestUser(), [ $target ] );
657 $result = $this->doListWatchlistRequest( [ 'wlprop' => 'loginfo', ] );
659 $this->assertArraySubsetsEqual(
660 $this->getItemsFromApiResponse( $result ),
664 'logtype' => 'delete',
665 'logaction' => 'delete',
669 [ 'type', 'logtype', 'logaction', 'logparams' ],
674 public function testEmptyPropParameter() {
675 $user = $this->getLoggedInTestUser();
676 $target = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
683 $this->watchPages( $user, [ $target ] );
685 $result = $this->doListWatchlistRequest( [ 'wlprop' => '', ] );
693 $this->getItemsFromApiResponse( $result )
697 public function testNamespaceParam() {
698 $user = $this->getLoggedInTestUser();
699 $subjectTarget = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
700 $talkTarget = new TitleValue( 1, 'ApiQueryWatchlistIntegrationTestPage' );
705 'target' => $subjectTarget,
706 'content' => 'Some Content',
707 'summary' => 'Create the page',
710 'target' => $talkTarget,
711 'content' => 'Some Content',
712 'summary' => 'Create the talk page',
716 $this->watchPages( $user, [ $subjectTarget, $talkTarget ] );
718 $result = $this->doListWatchlistRequest( [ 'wlnamespace' => '0', ] );
720 $this->assertArraySubsetsEqual(
721 $this->getItemsFromApiResponse( $result ),
725 'title' => $this->getPrefixedText( $subjectTarget ),
732 public function testUserParam() {
733 $user = $this->getLoggedInTestUser();
734 $otherUser = $this->getNonLoggedInTestUser();
735 $subjectTarget = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
736 $talkTarget = new TitleValue( 1, 'ApiQueryWatchlistIntegrationTestPage' );
746 'What is this page about?',
747 'Create the talk page'
749 $this->watchPages( $user, [ $subjectTarget, $talkTarget ] );
751 $result = $this->doListWatchlistRequest( [
752 'wlprop' => 'user|title',
753 'wluser' => $otherUser->getName(),
760 'ns' => $talkTarget->getNamespace(),
761 'title' => $this->getPrefixedText( $talkTarget ),
762 'user' => $otherUser->getName(),
765 $this->getItemsFromApiResponse( $result )
769 public function testExcludeUserParam() {
770 $user = $this->getLoggedInTestUser();
771 $otherUser = $this->getNonLoggedInTestUser();
772 $subjectTarget = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
773 $talkTarget = new TitleValue( 1, 'ApiQueryWatchlistIntegrationTestPage' );
783 'What is this page about?',
784 'Create the talk page'
786 $this->watchPages( $user, [ $subjectTarget, $talkTarget ] );
788 $result = $this->doListWatchlistRequest( [
789 'wlprop' => 'user|title',
790 'wlexcludeuser' => $otherUser->getName(),
797 'ns' => $subjectTarget->getNamespace(),
798 'title' => $this->getPrefixedText( $subjectTarget ),
799 'user' => $user->getName(),
802 $this->getItemsFromApiResponse( $result )
806 public function testShowMinorParams() {
807 $user = $this->getLoggedInTestUser();
808 $target = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
814 'content' => 'Some Content',
815 'summary' => 'Create the page',
819 'content' => 'Slightly Better Content',
820 'summary' => 'Change content',
825 $this->watchPages( $user, [ $target ] );
827 $resultMinor = $this->doListWatchlistRequest( [
828 'wlshow' => WatchedItemQueryService
::FILTER_MINOR
,
831 $resultNotMinor = $this->doListWatchlistRequest( [
832 'wlshow' => WatchedItemQueryService
::FILTER_NOT_MINOR
, 'wlprop' => 'flags'
835 $this->assertArraySubsetsEqual(
836 $this->getItemsFromApiResponse( $resultMinor ),
842 $this->assertEmpty( $this->getItemsFromApiResponse( $resultNotMinor ) );
845 public function testShowBotParams() {
846 $user = $this->getLoggedInTestUser();
847 $target = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
848 $this->doBotPageEdit(
854 $this->watchPages( $user, [ $target ] );
856 $resultBot = $this->doListWatchlistRequest( [
857 'wlshow' => WatchedItemQueryService
::FILTER_BOT
859 $resultNotBot = $this->doListWatchlistRequest( [
860 'wlshow' => WatchedItemQueryService
::FILTER_NOT_BOT
863 $this->assertArraySubsetsEqual(
864 $this->getItemsFromApiResponse( $resultBot ),
870 $this->assertEmpty( $this->getItemsFromApiResponse( $resultNotBot ) );
873 public function testShowAnonParams() {
874 $user = $this->getLoggedInTestUser();
875 $target = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
876 $this->doAnonPageEdit(
881 $this->watchPages( $user, [ $target ] );
883 $resultAnon = $this->doListWatchlistRequest( [
885 'wlshow' => WatchedItemQueryService
::FILTER_ANON
887 $resultNotAnon = $this->doListWatchlistRequest( [
889 'wlshow' => WatchedItemQueryService
::FILTER_NOT_ANON
892 $this->assertArraySubsetsEqual(
893 $this->getItemsFromApiResponse( $resultAnon ),
899 $this->assertEmpty( $this->getItemsFromApiResponse( $resultNotAnon ) );
902 public function testShowUnreadParams() {
903 $user = $this->getLoggedInTestUser();
904 $otherUser = $this->getNonLoggedInTestUser();
905 $subjectTarget = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
906 $talkTarget = new TitleValue( 1, 'ApiQueryWatchlistIntegrationTestPage' );
917 'Create the talk page'
919 $store = $this->getWatchedItemStore();
920 $store->addWatchBatchForUser( $user, [ $subjectTarget, $talkTarget ] );
921 $store->updateNotificationTimestamp(
927 $resultUnread = $this->doListWatchlistRequest( [
928 'wlprop' => 'notificationtimestamp|title',
929 'wlshow' => WatchedItemQueryService
::FILTER_UNREAD
931 $resultNotUnread = $this->doListWatchlistRequest( [
932 'wlprop' => 'notificationtimestamp|title',
933 'wlshow' => WatchedItemQueryService
::FILTER_NOT_UNREAD
940 'notificationtimestamp' => '2015-12-12T01:01:01Z',
941 'ns' => $talkTarget->getNamespace(),
942 'title' => $this->getPrefixedText( $talkTarget )
945 $this->getItemsFromApiResponse( $resultUnread )
951 'notificationtimestamp' => '',
952 'ns' => $subjectTarget->getNamespace(),
953 'title' => $this->getPrefixedText( $subjectTarget )
956 $this->getItemsFromApiResponse( $resultNotUnread )
960 public function testShowPatrolledParams() {
961 $user = static::getTestSysop()->getUser();
962 $this->setupPatrolledSpecificFixtures( $user );
964 $resultPatrolled = $this->doListWatchlistRequest( [
965 'wlprop' => 'patrol',
966 'wlshow' => WatchedItemQueryService
::FILTER_PATROLLED
968 $resultNotPatrolled = $this->doListWatchlistRequest( [
969 'wlprop' => 'patrol',
970 'wlshow' => WatchedItemQueryService
::FILTER_NOT_PATROLLED
978 'unpatrolled' => false,
979 'autopatrolled' => false,
982 $this->getItemsFromApiResponse( $resultPatrolled )
984 $this->assertEmpty( $this->getItemsFromApiResponse( $resultNotPatrolled ) );
987 public function testNewAndEditTypeParameters() {
988 $user = $this->getLoggedInTestUser();
989 $subjectTarget = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
990 $talkTarget = new TitleValue( 1, 'ApiQueryWatchlistIntegrationTestPage' );
995 'target' => $subjectTarget,
996 'content' => 'Some Content',
997 'summary' => 'Create the page',
1000 'target' => $subjectTarget,
1001 'content' => 'Some Other Content',
1002 'summary' => 'Change the content',
1005 'target' => $talkTarget,
1006 'content' => 'Some Talk Page Content',
1007 'summary' => 'Create Talk page',
1011 $this->watchPages( $user, [ $subjectTarget, $talkTarget ] );
1013 $resultNew = $this->doListWatchlistRequest( [ 'wlprop' => 'title', 'wltype' => 'new' ] );
1014 $resultEdit = $this->doListWatchlistRequest( [ 'wlprop' => 'title', 'wltype' => 'edit' ] );
1016 $this->assertEquals(
1020 'ns' => $talkTarget->getNamespace(),
1021 'title' => $this->getPrefixedText( $talkTarget ),
1024 $this->getItemsFromApiResponse( $resultNew )
1026 $this->assertEquals(
1030 'ns' => $subjectTarget->getNamespace(),
1031 'title' => $this->getPrefixedText( $subjectTarget ),
1034 $this->getItemsFromApiResponse( $resultEdit )
1038 public function testLogTypeParameters() {
1039 $user = $this->getLoggedInTestUser();
1040 $subjectTarget = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
1041 $talkTarget = new TitleValue( 1, 'ApiQueryWatchlistIntegrationTestPage' );
1042 $this->createPageAndDeleteIt( $subjectTarget );
1046 'Some Talk Page Content',
1049 $this->watchPages( $user, [ $subjectTarget, $talkTarget ] );
1051 $result = $this->doListWatchlistRequest( [ 'wlprop' => 'title', 'wltype' => 'log' ] );
1053 $this->assertEquals(
1057 'ns' => $subjectTarget->getNamespace(),
1058 'title' => $this->getPrefixedText( $subjectTarget ),
1061 $this->getItemsFromApiResponse( $result )
1065 private function getExternalRC( LinkTarget
$target ) {
1066 $title = Title
::newFromLinkTarget( $target );
1068 $rc = new RecentChange
;
1069 $rc->mTitle
= $title;
1071 'rc_timestamp' => wfTimestamp( TS_MW
),
1072 'rc_namespace' => $title->getNamespace(),
1073 'rc_title' => $title->getDBkey(),
1074 'rc_type' => RC_EXTERNAL
,
1075 'rc_source' => 'foo',
1077 'rc_cur_id' => $title->getArticleID(),
1079 'rc_user_text' => 'ext>External User',
1081 'rc_comment_text' => '',
1082 'rc_comment_data' => null,
1083 'rc_this_oldid' => $title->getLatestRevID(),
1084 'rc_last_oldid' => $title->getLatestRevID(),
1087 'rc_patrolled' => 0,
1089 'rc_old_len' => $title->getLength(),
1090 'rc_new_len' => $title->getLength(),
1093 'rc_log_type' => null,
1094 'rc_log_action' => '',
1098 'prefixedDBkey' => $title->getPrefixedDBkey(),
1099 'lastTimestamp' => 0,
1100 'oldSize' => $title->getLength(),
1101 'newSize' => $title->getLength(),
1102 'pageStatus' => 'changed'
1108 public function testExternalTypeParameters() {
1109 $user = $this->getLoggedInTestUser();
1110 $subjectTarget = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
1111 $talkTarget = new TitleValue( 1, 'ApiQueryWatchlistIntegrationTestPage' );
1121 'Some Talk Page Content',
1125 $rc = $this->getExternalRC( $subjectTarget );
1128 $this->watchPages( $user, [ $subjectTarget, $talkTarget ] );
1130 $result = $this->doListWatchlistRequest( [ 'wlprop' => 'title', 'wltype' => 'external' ] );
1132 $this->assertEquals(
1135 'type' => 'external',
1136 'ns' => $subjectTarget->getNamespace(),
1137 'title' => $this->getPrefixedText( $subjectTarget ),
1140 $this->getItemsFromApiResponse( $result )
1144 public function testCategorizeTypeParameter() {
1145 $user = $this->getLoggedInTestUser();
1146 $subjectTarget = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
1147 $categoryTarget = new TitleValue( NS_CATEGORY
, 'ApiQueryWatchlistIntegrationTestCategory' );
1152 'target' => $categoryTarget,
1153 'content' => 'Some Content',
1154 'summary' => 'Create the category',
1157 'target' => $subjectTarget,
1158 'content' => 'Some Content [[Category:ApiQueryWatchlistIntegrationTestCategory]]t',
1159 'summary' => 'Create the page and add it to the category',
1163 $title = Title
::newFromLinkTarget( $subjectTarget );
1164 $revision = Revision
::newFromTitle( $title );
1166 $rc = RecentChange
::newForCategorization(
1167 $revision->getTimestamp(),
1168 Title
::newFromLinkTarget( $categoryTarget ),
1170 $revision->getComment(),
1179 $this->watchPages( $user, [ $subjectTarget, $categoryTarget ] );
1181 $result = $this->doListWatchlistRequest( [ 'wlprop' => 'title', 'wltype' => 'categorize' ] );
1183 $this->assertEquals(
1186 'type' => 'categorize',
1187 'ns' => $categoryTarget->getNamespace(),
1188 'title' => $this->getPrefixedText( $categoryTarget ),
1191 $this->getItemsFromApiResponse( $result )
1195 public function testLimitParam() {
1196 $user = $this->getLoggedInTestUser();
1197 $target1 = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
1198 $target2 = new TitleValue( 1, 'ApiQueryWatchlistIntegrationTestPage' );
1199 $target3 = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage2' );
1204 'target' => $target1,
1205 'content' => 'Some Content',
1206 'summary' => 'Create the page',
1209 'target' => $target2,
1210 'content' => 'Some Talk Page Content',
1211 'summary' => 'Create Talk page',
1214 'target' => $target3,
1215 'content' => 'Some Other Content',
1216 'summary' => 'Create the page',
1220 $this->watchPages( $user, [ $target1, $target2, $target3 ] );
1222 $resultWithoutLimit = $this->doListWatchlistRequest( [ 'wlprop' => 'title' ] );
1223 $resultWithLimit = $this->doListWatchlistRequest( [ 'wllimit' => 2, 'wlprop' => 'title' ] );
1225 $this->assertEquals(
1229 'ns' => $target3->getNamespace(),
1230 'title' => $this->getPrefixedText( $target3 )
1234 'ns' => $target2->getNamespace(),
1235 'title' => $this->getPrefixedText( $target2 )
1239 'ns' => $target1->getNamespace(),
1240 'title' => $this->getPrefixedText( $target1 )
1243 $this->getItemsFromApiResponse( $resultWithoutLimit )
1245 $this->assertEquals(
1249 'ns' => $target3->getNamespace(),
1250 'title' => $this->getPrefixedText( $target3 )
1254 'ns' => $target2->getNamespace(),
1255 'title' => $this->getPrefixedText( $target2 )
1258 $this->getItemsFromApiResponse( $resultWithLimit )
1260 $this->assertArrayHasKey( 'continue', $resultWithLimit[0] );
1261 $this->assertArrayHasKey( 'wlcontinue', $resultWithLimit[0]['continue'] );
1264 public function testAllRevParam() {
1265 $user = $this->getLoggedInTestUser();
1266 $target = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
1271 'target' => $target,
1272 'content' => 'Some Content',
1273 'summary' => 'Create the page',
1276 'target' => $target,
1277 'content' => 'Some Other Content',
1278 'summary' => 'Change the content',
1282 $this->watchPages( $user, [ $target ] );
1284 $resultAllRev = $this->doListWatchlistRequest( [ 'wlprop' => 'title', 'wlallrev' => '', ] );
1285 $resultNoAllRev = $this->doListWatchlistRequest( [ 'wlprop' => 'title' ] );
1287 $this->assertEquals(
1291 'ns' => $target->getNamespace(),
1292 'title' => $this->getPrefixedText( $target ),
1295 $this->getItemsFromApiResponse( $resultNoAllRev )
1297 $this->assertEquals(
1301 'ns' => $target->getNamespace(),
1302 'title' => $this->getPrefixedText( $target ),
1306 'ns' => $target->getNamespace(),
1307 'title' => $this->getPrefixedText( $target ),
1310 $this->getItemsFromApiResponse( $resultAllRev )
1314 public function testDirParams() {
1315 $user = $this->getLoggedInTestUser();
1316 $subjectTarget = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
1317 $talkTarget = new TitleValue( 1, 'ApiQueryWatchlistIntegrationTestPage' );
1322 'target' => $subjectTarget,
1323 'content' => 'Some Content',
1324 'summary' => 'Create the page',
1327 'target' => $talkTarget,
1328 'content' => 'Some Talk Page Content',
1329 'summary' => 'Create Talk page',
1333 $this->watchPages( $user, [ $subjectTarget, $talkTarget ] );
1335 $resultDirOlder = $this->doListWatchlistRequest( [ 'wldir' => 'older', 'wlprop' => 'title' ] );
1336 $resultDirNewer = $this->doListWatchlistRequest( [ 'wldir' => 'newer', 'wlprop' => 'title' ] );
1338 $this->assertEquals(
1342 'ns' => $talkTarget->getNamespace(),
1343 'title' => $this->getPrefixedText( $talkTarget )
1347 'ns' => $subjectTarget->getNamespace(),
1348 'title' => $this->getPrefixedText( $subjectTarget )
1351 $this->getItemsFromApiResponse( $resultDirOlder )
1353 $this->assertEquals(
1357 'ns' => $subjectTarget->getNamespace(),
1358 'title' => $this->getPrefixedText( $subjectTarget )
1362 'ns' => $talkTarget->getNamespace(),
1363 'title' => $this->getPrefixedText( $talkTarget )
1366 $this->getItemsFromApiResponse( $resultDirNewer )
1370 public function testStartEndParams() {
1371 $user = $this->getLoggedInTestUser();
1372 $target = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
1379 $this->watchPages( $user, [ $target ] );
1381 $resultStart = $this->doListWatchlistRequest( [
1382 'wlstart' => '20010115000000',
1384 'wlprop' => 'title',
1386 $resultEnd = $this->doListWatchlistRequest( [
1387 'wlend' => '20010115000000',
1389 'wlprop' => 'title',
1392 $this->assertEquals(
1396 'ns' => $target->getNamespace(),
1397 'title' => $this->getPrefixedText( $target ),
1400 $this->getItemsFromApiResponse( $resultStart )
1402 $this->assertEmpty( $this->getItemsFromApiResponse( $resultEnd ) );
1405 public function testContinueParam() {
1406 $user = $this->getLoggedInTestUser();
1407 $target1 = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
1408 $target2 = new TitleValue( 1, 'ApiQueryWatchlistIntegrationTestPage' );
1409 $target3 = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage2' );
1414 'target' => $target1,
1415 'content' => 'Some Content',
1416 'summary' => 'Create the page',
1419 'target' => $target2,
1420 'content' => 'Some Talk Page Content',
1421 'summary' => 'Create Talk page',
1424 'target' => $target3,
1425 'content' => 'Some Other Content',
1426 'summary' => 'Create the page',
1430 $this->watchPages( $user, [ $target1, $target2, $target3 ] );
1432 $firstResult = $this->doListWatchlistRequest( [ 'wllimit' => 2, 'wlprop' => 'title' ] );
1433 $this->assertArrayHasKey( 'continue', $firstResult[0] );
1434 $this->assertArrayHasKey( 'wlcontinue', $firstResult[0]['continue'] );
1436 $continuationParam = $firstResult[0]['continue']['wlcontinue'];
1438 $continuedResult = $this->doListWatchlistRequest(
1439 [ 'wlcontinue' => $continuationParam, 'wlprop' => 'title' ]
1442 $this->assertEquals(
1446 'ns' => $target3->getNamespace(),
1447 'title' => $this->getPrefixedText( $target3 ),
1451 'ns' => $target2->getNamespace(),
1452 'title' => $this->getPrefixedText( $target2 ),
1455 $this->getItemsFromApiResponse( $firstResult )
1457 $this->assertEquals(
1461 'ns' => $target1->getNamespace(),
1462 'title' => $this->getPrefixedText( $target1 )
1465 $this->getItemsFromApiResponse( $continuedResult )
1469 public function testOwnerAndTokenParams() {
1470 $target = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
1472 $this->getLoggedInTestUser(),
1478 $otherUser = $this->getNonLoggedInTestUser();
1479 $otherUser->setOption( 'watchlisttoken', '1234567890' );
1480 $otherUser->saveSettings();
1482 $this->watchPages( $otherUser, [ $target ] );
1484 $reloadedUser = User
::newFromName( $otherUser->getName() );
1485 $this->assertEquals( '1234567890', $reloadedUser->getOption( 'watchlisttoken' ) );
1487 $result = $this->doListWatchlistRequest( [
1488 'wlowner' => $otherUser->getName(),
1489 'wltoken' => '1234567890',
1490 'wlprop' => 'title',
1493 $this->assertEquals(
1497 'ns' => $target->getNamespace(),
1498 'title' => $this->getPrefixedText( $target )
1501 $this->getItemsFromApiResponse( $result )
1505 public function testOwnerAndTokenParams_wrongToken() {
1506 $otherUser = $this->getNonLoggedInTestUser();
1507 $otherUser->setOption( 'watchlisttoken', '1234567890' );
1508 $otherUser->saveSettings();
1510 $this->setExpectedException( ApiUsageException
::class, 'Incorrect watchlist token provided' );
1512 $this->doListWatchlistRequest( [
1513 'wlowner' => $otherUser->getName(),
1514 'wltoken' => 'wrong-token',
1518 public function testOwnerAndTokenParams_noWatchlistTokenSet() {
1519 $this->setExpectedException( ApiUsageException
::class, 'Incorrect watchlist token provided' );
1521 $this->doListWatchlistRequest( [
1522 'wlowner' => $this->getNonLoggedInTestUser()->getName(),
1523 'wltoken' => 'some-token',
1527 public function testGeneratorWatchlistPropInfo_returnsWatchedPages() {
1528 $user = $this->getLoggedInTestUser();
1529 $target = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
1536 $this->watchPages( $user, [ $target ] );
1538 $result = $this->doGeneratorWatchlistRequest( [ 'prop' => 'info' ] );
1540 $this->assertArrayHasKey( 'query', $result[0] );
1541 $this->assertArrayHasKey( 'pages', $result[0]['query'] );
1543 // $result[0]['query']['pages'] uses page ids as keys. Page ids don't matter here, so drop them
1544 $pages = array_values( $result[0]['query']['pages'] );
1546 $this->assertArraySubsetsEqual(
1550 'ns' => $target->getNamespace(),
1551 'title' => $this->getPrefixedText( $target ),
1555 [ 'ns', 'title', 'new' ]
1559 public function testGeneratorWatchlistPropRevisions_returnsWatchedItemsRevisions() {
1560 $user = $this->getLoggedInTestUser();
1561 $target = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
1566 'target' => $target,
1567 'content' => 'Some Content',
1568 'summary' => 'Create the page',
1571 'target' => $target,
1572 'content' => 'Some Other Content',
1573 'summary' => 'Change the content',
1577 $this->watchPages( $user, [ $target ] );
1579 $result = $this->doGeneratorWatchlistRequest( [ 'prop' => 'revisions', 'gwlallrev' => '' ] );
1581 $this->assertArrayHasKey( 'query', $result[0] );
1582 $this->assertArrayHasKey( 'pages', $result[0]['query'] );
1584 // $result[0]['query']['pages'] uses page ids as keys. Page ids don't matter here, so drop them
1585 $pages = array_values( $result[0]['query']['pages'] );
1587 $this->assertCount( 1, $pages );
1588 $this->assertEquals( 0, $pages[0]['ns'] );
1589 $this->assertEquals( $this->getPrefixedText( $target ), $pages[0]['title'] );
1590 $this->assertArraySubsetsEqual(
1591 $pages[0]['revisions'],
1594 'comment' => 'Create the page',
1595 'user' => $user->getName(),
1599 'comment' => 'Change the content',
1600 'user' => $user->getName(),
1604 [ 'comment', 'user', 'minor' ]