Merge "Test ApiUserrights"
[lhc/web/wiklou.git] / tests / phpunit / includes / api / ApiQueryWatchlistIntegrationTest.php
1 <?php
2
3 use MediaWiki\Linker\LinkTarget;
4 use MediaWiki\MediaWikiServices;
5
6 /**
7 * @group medium
8 * @group API
9 * @group Database
10 *
11 * @covers ApiQueryWatchlist
12 */
13 class ApiQueryWatchlistIntegrationTest extends ApiTestCase {
14
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' ] )
19 );
20 }
21
22 protected function setUp() {
23 parent::setUp();
24 self::$users['ApiQueryWatchlistIntegrationTestUser'] = $this->getMutableTestUser();
25 self::$users['ApiQueryWatchlistIntegrationTestUser2'] = $this->getMutableTestUser();
26 }
27
28 private function getLoggedInTestUser() {
29 return self::$users['ApiQueryWatchlistIntegrationTestUser']->getUser();
30 }
31
32 private function getNonLoggedInTestUser() {
33 return self::$users['ApiQueryWatchlistIntegrationTestUser2']->getUser();
34 }
35
36 private function doPageEdit( User $user, LinkTarget $target, $content, $summary ) {
37 $title = Title::newFromLinkTarget( $target );
38 $page = WikiPage::factory( $title );
39 $page->doEditContent(
40 ContentHandler::makeContent( $content, $title ),
41 $summary,
42 0,
43 false,
44 $user
45 );
46 }
47
48 private function doMinorPageEdit( User $user, LinkTarget $target, $content, $summary ) {
49 $title = Title::newFromLinkTarget( $target );
50 $page = WikiPage::factory( $title );
51 $page->doEditContent(
52 ContentHandler::makeContent( $content, $title ),
53 $summary,
54 EDIT_MINOR,
55 false,
56 $user
57 );
58 }
59
60 private function doBotPageEdit( User $user, LinkTarget $target, $content, $summary ) {
61 $title = Title::newFromLinkTarget( $target );
62 $page = WikiPage::factory( $title );
63 $page->doEditContent(
64 ContentHandler::makeContent( $content, $title ),
65 $summary,
66 EDIT_FORCE_BOT,
67 false,
68 $user
69 );
70 }
71
72 private function doAnonPageEdit( LinkTarget $target, $content, $summary ) {
73 $title = Title::newFromLinkTarget( $target );
74 $page = WikiPage::factory( $title );
75 $page->doEditContent(
76 ContentHandler::makeContent( $content, $title ),
77 $summary,
78 0,
79 false,
80 User::newFromId( 0 )
81 );
82 }
83
84 private function doPatrolledPageEdit(
85 User $user,
86 LinkTarget $target,
87 $content,
88 $summary,
89 User $patrollingUser
90 ) {
91 $title = Title::newFromLinkTarget( $target );
92 $page = WikiPage::factory( $title );
93 $status = $page->doEditContent(
94 ContentHandler::makeContent( $content, $title ),
95 $summary,
96 0,
97 false,
98 $user
99 );
100 /** @var Revision $rev */
101 $rev = $status->value['revision'];
102 $rc = $rev->getRecentChange();
103 $rc->doMarkPatrolled( $patrollingUser, false, [] );
104 }
105
106 private function deletePage( LinkTarget $target, $reason ) {
107 $title = Title::newFromLinkTarget( $target );
108 $page = WikiPage::factory( $title );
109 $page->doDeleteArticleReal( $reason );
110 }
111
112 /**
113 * Performs a batch of page edits as a specified user
114 * @param User $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)
121 */
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(
126 $user,
127 $singleEditData['target'],
128 $singleEditData['content'],
129 $singleEditData['summary']
130 );
131 continue;
132 }
133 if ( array_key_exists( 'botEdit', $singleEditData ) && $singleEditData['botEdit'] ) {
134 $this->doBotPageEdit(
135 $user,
136 $singleEditData['target'],
137 $singleEditData['content'],
138 $singleEditData['summary']
139 );
140 continue;
141 }
142 $this->doPageEdit(
143 $user,
144 $singleEditData['target'],
145 $singleEditData['content'],
146 $singleEditData['summary']
147 );
148 }
149 }
150
151 private function getWatchedItemStore() {
152 return MediaWikiServices::getInstance()->getWatchedItemStore();
153 }
154
155 /**
156 * @param User $user
157 * @param LinkTarget[] $targets
158 */
159 private function watchPages( User $user, array $targets ) {
160 $store = $this->getWatchedItemStore();
161 $store->addWatchBatchForUser( $user, $targets );
162 }
163
164 private function doListWatchlistRequest( array $params = [], $user = null ) {
165 if ( $user === null ) {
166 $user = $this->getLoggedInTestUser();
167 }
168 return $this->doApiRequest(
169 array_merge(
170 [ 'action' => 'query', 'list' => 'watchlist' ],
171 $params
172 ), null, false, $user
173 );
174 }
175
176 private function doGeneratorWatchlistRequest( array $params = [] ) {
177 return $this->doApiRequest(
178 array_merge(
179 [ 'action' => 'query', 'generator' => 'watchlist' ],
180 $params
181 ), null, false, $this->getLoggedInTestUser()
182 );
183 }
184
185 private function getItemsFromApiResponse( array $response ) {
186 return $response[0]['query']['watchlist'];
187 }
188
189 /**
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.
196 *
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.
204 */
205 private function assertArraySubsetsEqual(
206 array $actualItems,
207 array $expectedItems,
208 array $keysUsedInValueComparison,
209 array $requiredKeys = []
210 ) {
211 $this->assertCount( count( $expectedItems ), $actualItems );
212
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 ) );
217 },
218 $actualItems
219 );
220
221 $this->assertEquals(
222 $expectedItems,
223 $actualItemsOnlyComparedValues
224 );
225
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 ) );
230 }
231 }
232
233 private function getTitleFormatter() {
234 return new MediaWikiTitleCodec(
235 Language::factory( 'en' ),
236 MediaWikiServices::getInstance()->getGenderCache()
237 );
238 }
239
240 private function getPrefixedText( LinkTarget $target ) {
241 $formatter = $this->getTitleFormatter();
242 return $formatter->getPrefixedText( $target );
243 }
244
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() );
251 }
252 }
253
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();
258
259 $user = $this->getLoggedInTestUser();
260 $target = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
261 $this->doPageEdit(
262 $user,
263 $target,
264 'Some Content',
265 'Create the page'
266 );
267 $this->watchPages( $user, [ $target ] );
268
269 $result = $this->doListWatchlistRequest();
270
271 $this->assertArrayHasKey( 'query', $result[0] );
272 $this->assertArrayHasKey( 'watchlist', $result[0]['query'] );
273
274 $this->assertArraySubsetsEqual(
275 $this->getItemsFromApiResponse( $result ),
276 [
277 [
278 'type' => 'new',
279 'ns' => $target->getNamespace(),
280 'title' => $this->getPrefixedText( $target ),
281 'bot' => false,
282 'new' => true,
283 'minor' => false,
284 ]
285 ],
286 [ 'type', 'ns', 'title', 'bot', 'new', 'minor' ],
287 [ 'pageid', 'revid', 'old_revid' ]
288 );
289 }
290
291 public function testIdsPropParameter() {
292 $user = $this->getLoggedInTestUser();
293 $target = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
294 $this->doPageEdit(
295 $user,
296 $target,
297 'Some Content',
298 'Create the page'
299 );
300 $this->watchPages( $user, [ $target ] );
301
302 $result = $this->doListWatchlistRequest( [ 'wlprop' => 'ids', ] );
303 $items = $this->getItemsFromApiResponse( $result );
304
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'] );
310 }
311
312 public function testTitlePropParameter() {
313 $user = $this->getLoggedInTestUser();
314 $subjectTarget = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
315 $talkTarget = new TitleValue( 1, 'ApiQueryWatchlistIntegrationTestPage' );
316 $this->doPageEdits(
317 $user,
318 [
319 [
320 'target' => $subjectTarget,
321 'content' => 'Some Content',
322 'summary' => 'Create the page',
323 ],
324 [
325 'target' => $talkTarget,
326 'content' => 'Some Talk Page Content',
327 'summary' => 'Create Talk page',
328 ],
329 ]
330 );
331 $this->watchPages( $user, [ $subjectTarget, $talkTarget ] );
332
333 $result = $this->doListWatchlistRequest( [ 'wlprop' => 'title', ] );
334
335 $this->assertEquals(
336 [
337 [
338 'type' => 'new',
339 'ns' => $talkTarget->getNamespace(),
340 'title' => $this->getPrefixedText( $talkTarget ),
341 ],
342 [
343 'type' => 'new',
344 'ns' => $subjectTarget->getNamespace(),
345 'title' => $this->getPrefixedText( $subjectTarget ),
346 ],
347 ],
348 $this->getItemsFromApiResponse( $result )
349 );
350 }
351
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' );
357 $this->doPageEdits(
358 $user,
359 [
360 [
361 'target' => $normalEditTarget,
362 'content' => 'Some Content',
363 'summary' => 'Create the page',
364 ],
365 [
366 'target' => $minorEditTarget,
367 'content' => 'Some Content',
368 'summary' => 'Create the page',
369 ],
370 [
371 'target' => $minorEditTarget,
372 'content' => 'Slightly Better Content',
373 'summary' => 'Change content',
374 'minorEdit' => true,
375 ],
376 [
377 'target' => $botEditTarget,
378 'content' => 'Some Content',
379 'summary' => 'Create the page with a bot',
380 'botEdit' => true,
381 ],
382 ]
383 );
384 $this->watchPages( $user, [ $normalEditTarget, $minorEditTarget, $botEditTarget ] );
385
386 $result = $this->doListWatchlistRequest( [ 'wlprop' => 'flags', ] );
387
388 $this->assertEquals(
389 [
390 [
391 'type' => 'new',
392 'new' => true,
393 'minor' => false,
394 'bot' => true,
395 ],
396 [
397 'type' => 'edit',
398 'new' => false,
399 'minor' => true,
400 'bot' => false,
401 ],
402 [
403 'type' => 'new',
404 'new' => true,
405 'minor' => false,
406 'bot' => false,
407 ],
408 ],
409 $this->getItemsFromApiResponse( $result )
410 );
411 }
412
413 public function testUserPropParameter() {
414 $user = $this->getLoggedInTestUser();
415 $userEditTarget = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
416 $anonEditTarget = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPageA' );
417 $this->doPageEdit(
418 $user,
419 $userEditTarget,
420 'Some Content',
421 'Create the page'
422 );
423 $this->doAnonPageEdit(
424 $anonEditTarget,
425 'Some Content',
426 'Create the page'
427 );
428 $this->watchPages( $user, [ $userEditTarget, $anonEditTarget ] );
429
430 $result = $this->doListWatchlistRequest( [ 'wlprop' => 'user', ] );
431
432 $this->assertEquals(
433 [
434 [
435 'type' => 'new',
436 'anon' => true,
437 'user' => User::newFromId( 0 )->getName(),
438 ],
439 [
440 'type' => 'new',
441 'user' => $user->getName(),
442 ],
443 ],
444 $this->getItemsFromApiResponse( $result )
445 );
446 }
447
448 public function testUserIdPropParameter() {
449 $user = $this->getLoggedInTestUser();
450 $userEditTarget = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
451 $anonEditTarget = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPageA' );
452 $this->doPageEdit(
453 $user,
454 $userEditTarget,
455 'Some Content',
456 'Create the page'
457 );
458 $this->doAnonPageEdit(
459 $anonEditTarget,
460 'Some Content',
461 'Create the page'
462 );
463 $this->watchPages( $user, [ $userEditTarget, $anonEditTarget ] );
464
465 $result = $this->doListWatchlistRequest( [ 'wlprop' => 'userid', ] );
466
467 $this->assertEquals(
468 [
469 [
470 'type' => 'new',
471 'anon' => true,
472 'user' => 0,
473 'userid' => 0,
474 ],
475 [
476 'type' => 'new',
477 'user' => $user->getId(),
478 'userid' => $user->getId(),
479 ],
480 ],
481 $this->getItemsFromApiResponse( $result )
482 );
483 }
484
485 public function testCommentPropParameter() {
486 $user = $this->getLoggedInTestUser();
487 $target = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
488 $this->doPageEdit(
489 $user,
490 $target,
491 'Some Content',
492 'Create the <b>page</b>'
493 );
494 $this->watchPages( $user, [ $target ] );
495
496 $result = $this->doListWatchlistRequest( [ 'wlprop' => 'comment', ] );
497
498 $this->assertEquals(
499 [
500 [
501 'type' => 'new',
502 'comment' => 'Create the <b>page</b>',
503 ],
504 ],
505 $this->getItemsFromApiResponse( $result )
506 );
507 }
508
509 public function testParsedCommentPropParameter() {
510 $user = $this->getLoggedInTestUser();
511 $target = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
512 $this->doPageEdit(
513 $user,
514 $target,
515 'Some Content',
516 'Create the <b>page</b>'
517 );
518 $this->watchPages( $user, [ $target ] );
519
520 $result = $this->doListWatchlistRequest( [ 'wlprop' => 'parsedcomment', ] );
521
522 $this->assertEquals(
523 [
524 [
525 'type' => 'new',
526 'parsedcomment' => 'Create the &lt;b&gt;page&lt;/b&gt;',
527 ],
528 ],
529 $this->getItemsFromApiResponse( $result )
530 );
531 }
532
533 public function testTimestampPropParameter() {
534 $user = $this->getLoggedInTestUser();
535 $target = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
536 $this->doPageEdit(
537 $user,
538 $target,
539 'Some Content',
540 'Create the page'
541 );
542 $this->watchPages( $user, [ $target ] );
543
544 $result = $this->doListWatchlistRequest( [ 'wlprop' => 'timestamp', ] );
545 $items = $this->getItemsFromApiResponse( $result );
546
547 $this->assertCount( 1, $items );
548 $this->assertArrayHasKey( 'timestamp', $items[0] );
549 $this->assertInternalType( 'string', $items[0]['timestamp'] );
550 }
551
552 public function testSizesPropParameter() {
553 $user = $this->getLoggedInTestUser();
554 $target = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
555 $this->doPageEdit(
556 $user,
557 $target,
558 'Some Content',
559 'Create the page'
560 );
561 $this->watchPages( $user, [ $target ] );
562
563 $result = $this->doListWatchlistRequest( [ 'wlprop' => 'sizes', ] );
564
565 $this->assertEquals(
566 [
567 [
568 'type' => 'new',
569 'oldlen' => 0,
570 'newlen' => 12,
571 ],
572 ],
573 $this->getItemsFromApiResponse( $result )
574 );
575 }
576
577 public function testNotificationTimestampPropParameter() {
578 $otherUser = $this->getNonLoggedInTestUser();
579 $target = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
580 $this->doPageEdit(
581 $otherUser,
582 $target,
583 'Some Content',
584 'Create the page'
585 );
586 $store = $this->getWatchedItemStore();
587 $store->addWatch( $this->getLoggedInTestUser(), $target );
588 $store->updateNotificationTimestamp(
589 $otherUser,
590 $target,
591 '20151212010101'
592 );
593
594 $result = $this->doListWatchlistRequest( [ 'wlprop' => 'notificationtimestamp', ] );
595
596 $this->assertEquals(
597 [
598 [
599 'type' => 'new',
600 'notificationtimestamp' => '2015-12-12T01:01:01Z',
601 ],
602 ],
603 $this->getItemsFromApiResponse( $result )
604 );
605 }
606
607 private function setupPatrolledSpecificFixtures( User $user ) {
608 $target = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
609
610 $this->doPatrolledPageEdit(
611 $user,
612 $target,
613 'Some Content',
614 'Create the page (this gets patrolled)',
615 $user
616 );
617
618 $this->watchPages( $user, [ $target ] );
619 }
620
621 public function testPatrolPropParameter() {
622 $testUser = static::getTestSysop();
623 $user = $testUser->getUser();
624 $this->setupPatrolledSpecificFixtures( $user );
625
626 $result = $this->doListWatchlistRequest( [ 'wlprop' => 'patrol', ], $user );
627
628 $this->assertEquals(
629 [
630 [
631 'type' => 'new',
632 'patrolled' => true,
633 'unpatrolled' => false,
634 'autopatrolled' => false,
635 ]
636 ],
637 $this->getItemsFromApiResponse( $result )
638 );
639 }
640
641 private function createPageAndDeleteIt( LinkTarget $target ) {
642 $this->doPageEdit(
643 $this->getLoggedInTestUser(),
644 $target,
645 'Some Content',
646 'Create the page that will be deleted'
647 );
648 $this->deletePage( $target, 'Important Reason' );
649 }
650
651 public function testLoginfoPropParameter() {
652 $target = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
653 $this->createPageAndDeleteIt( $target );
654
655 $this->watchPages( $this->getLoggedInTestUser(), [ $target ] );
656
657 $result = $this->doListWatchlistRequest( [ 'wlprop' => 'loginfo', ] );
658
659 $this->assertArraySubsetsEqual(
660 $this->getItemsFromApiResponse( $result ),
661 [
662 [
663 'type' => 'log',
664 'logtype' => 'delete',
665 'logaction' => 'delete',
666 'logparams' => [],
667 ],
668 ],
669 [ 'type', 'logtype', 'logaction', 'logparams' ],
670 [ 'logid' ]
671 );
672 }
673
674 public function testEmptyPropParameter() {
675 $user = $this->getLoggedInTestUser();
676 $target = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
677 $this->doPageEdit(
678 $user,
679 $target,
680 'Some Content',
681 'Create the page'
682 );
683 $this->watchPages( $user, [ $target ] );
684
685 $result = $this->doListWatchlistRequest( [ 'wlprop' => '', ] );
686
687 $this->assertEquals(
688 [
689 [
690 'type' => 'new',
691 ]
692 ],
693 $this->getItemsFromApiResponse( $result )
694 );
695 }
696
697 public function testNamespaceParam() {
698 $user = $this->getLoggedInTestUser();
699 $subjectTarget = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
700 $talkTarget = new TitleValue( 1, 'ApiQueryWatchlistIntegrationTestPage' );
701 $this->doPageEdits(
702 $user,
703 [
704 [
705 'target' => $subjectTarget,
706 'content' => 'Some Content',
707 'summary' => 'Create the page',
708 ],
709 [
710 'target' => $talkTarget,
711 'content' => 'Some Content',
712 'summary' => 'Create the talk page',
713 ],
714 ]
715 );
716 $this->watchPages( $user, [ $subjectTarget, $talkTarget ] );
717
718 $result = $this->doListWatchlistRequest( [ 'wlnamespace' => '0', ] );
719
720 $this->assertArraySubsetsEqual(
721 $this->getItemsFromApiResponse( $result ),
722 [
723 [
724 'ns' => 0,
725 'title' => $this->getPrefixedText( $subjectTarget ),
726 ],
727 ],
728 [ 'ns', 'title' ]
729 );
730 }
731
732 public function testUserParam() {
733 $user = $this->getLoggedInTestUser();
734 $otherUser = $this->getNonLoggedInTestUser();
735 $subjectTarget = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
736 $talkTarget = new TitleValue( 1, 'ApiQueryWatchlistIntegrationTestPage' );
737 $this->doPageEdit(
738 $user,
739 $subjectTarget,
740 'Some Content',
741 'Create the page'
742 );
743 $this->doPageEdit(
744 $otherUser,
745 $talkTarget,
746 'What is this page about?',
747 'Create the talk page'
748 );
749 $this->watchPages( $user, [ $subjectTarget, $talkTarget ] );
750
751 $result = $this->doListWatchlistRequest( [
752 'wlprop' => 'user|title',
753 'wluser' => $otherUser->getName(),
754 ] );
755
756 $this->assertEquals(
757 [
758 [
759 'type' => 'new',
760 'ns' => $talkTarget->getNamespace(),
761 'title' => $this->getPrefixedText( $talkTarget ),
762 'user' => $otherUser->getName(),
763 ],
764 ],
765 $this->getItemsFromApiResponse( $result )
766 );
767 }
768
769 public function testExcludeUserParam() {
770 $user = $this->getLoggedInTestUser();
771 $otherUser = $this->getNonLoggedInTestUser();
772 $subjectTarget = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
773 $talkTarget = new TitleValue( 1, 'ApiQueryWatchlistIntegrationTestPage' );
774 $this->doPageEdit(
775 $user,
776 $subjectTarget,
777 'Some Content',
778 'Create the page'
779 );
780 $this->doPageEdit(
781 $otherUser,
782 $talkTarget,
783 'What is this page about?',
784 'Create the talk page'
785 );
786 $this->watchPages( $user, [ $subjectTarget, $talkTarget ] );
787
788 $result = $this->doListWatchlistRequest( [
789 'wlprop' => 'user|title',
790 'wlexcludeuser' => $otherUser->getName(),
791 ] );
792
793 $this->assertEquals(
794 [
795 [
796 'type' => 'new',
797 'ns' => $subjectTarget->getNamespace(),
798 'title' => $this->getPrefixedText( $subjectTarget ),
799 'user' => $user->getName(),
800 ]
801 ],
802 $this->getItemsFromApiResponse( $result )
803 );
804 }
805
806 public function testShowMinorParams() {
807 $user = $this->getLoggedInTestUser();
808 $target = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
809 $this->doPageEdits(
810 $user,
811 [
812 [
813 'target' => $target,
814 'content' => 'Some Content',
815 'summary' => 'Create the page',
816 ],
817 [
818 'target' => $target,
819 'content' => 'Slightly Better Content',
820 'summary' => 'Change content',
821 'minorEdit' => true,
822 ],
823 ]
824 );
825 $this->watchPages( $user, [ $target ] );
826
827 $resultMinor = $this->doListWatchlistRequest( [
828 'wlshow' => WatchedItemQueryService::FILTER_MINOR,
829 'wlprop' => 'flags'
830 ] );
831 $resultNotMinor = $this->doListWatchlistRequest( [
832 'wlshow' => WatchedItemQueryService::FILTER_NOT_MINOR, 'wlprop' => 'flags'
833 ] );
834
835 $this->assertArraySubsetsEqual(
836 $this->getItemsFromApiResponse( $resultMinor ),
837 [
838 [ 'minor' => true, ]
839 ],
840 [ 'minor' ]
841 );
842 $this->assertEmpty( $this->getItemsFromApiResponse( $resultNotMinor ) );
843 }
844
845 public function testShowBotParams() {
846 $user = $this->getLoggedInTestUser();
847 $target = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
848 $this->doBotPageEdit(
849 $user,
850 $target,
851 'Some Content',
852 'Create the page'
853 );
854 $this->watchPages( $user, [ $target ] );
855
856 $resultBot = $this->doListWatchlistRequest( [
857 'wlshow' => WatchedItemQueryService::FILTER_BOT
858 ] );
859 $resultNotBot = $this->doListWatchlistRequest( [
860 'wlshow' => WatchedItemQueryService::FILTER_NOT_BOT
861 ] );
862
863 $this->assertArraySubsetsEqual(
864 $this->getItemsFromApiResponse( $resultBot ),
865 [
866 [ 'bot' => true ],
867 ],
868 [ 'bot' ]
869 );
870 $this->assertEmpty( $this->getItemsFromApiResponse( $resultNotBot ) );
871 }
872
873 public function testShowAnonParams() {
874 $user = $this->getLoggedInTestUser();
875 $target = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
876 $this->doAnonPageEdit(
877 $target,
878 'Some Content',
879 'Create the page'
880 );
881 $this->watchPages( $user, [ $target ] );
882
883 $resultAnon = $this->doListWatchlistRequest( [
884 'wlprop' => 'user',
885 'wlshow' => WatchedItemQueryService::FILTER_ANON
886 ] );
887 $resultNotAnon = $this->doListWatchlistRequest( [
888 'wlprop' => 'user',
889 'wlshow' => WatchedItemQueryService::FILTER_NOT_ANON
890 ] );
891
892 $this->assertArraySubsetsEqual(
893 $this->getItemsFromApiResponse( $resultAnon ),
894 [
895 [ 'anon' => true ],
896 ],
897 [ 'anon' ]
898 );
899 $this->assertEmpty( $this->getItemsFromApiResponse( $resultNotAnon ) );
900 }
901
902 public function testShowUnreadParams() {
903 $user = $this->getLoggedInTestUser();
904 $otherUser = $this->getNonLoggedInTestUser();
905 $subjectTarget = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
906 $talkTarget = new TitleValue( 1, 'ApiQueryWatchlistIntegrationTestPage' );
907 $this->doPageEdit(
908 $user,
909 $subjectTarget,
910 'Some Content',
911 'Create the page'
912 );
913 $this->doPageEdit(
914 $otherUser,
915 $talkTarget,
916 'Some Content',
917 'Create the talk page'
918 );
919 $store = $this->getWatchedItemStore();
920 $store->addWatchBatchForUser( $user, [ $subjectTarget, $talkTarget ] );
921 $store->updateNotificationTimestamp(
922 $otherUser,
923 $talkTarget,
924 '20151212010101'
925 );
926
927 $resultUnread = $this->doListWatchlistRequest( [
928 'wlprop' => 'notificationtimestamp|title',
929 'wlshow' => WatchedItemQueryService::FILTER_UNREAD
930 ] );
931 $resultNotUnread = $this->doListWatchlistRequest( [
932 'wlprop' => 'notificationtimestamp|title',
933 'wlshow' => WatchedItemQueryService::FILTER_NOT_UNREAD
934 ] );
935
936 $this->assertEquals(
937 [
938 [
939 'type' => 'new',
940 'notificationtimestamp' => '2015-12-12T01:01:01Z',
941 'ns' => $talkTarget->getNamespace(),
942 'title' => $this->getPrefixedText( $talkTarget )
943 ]
944 ],
945 $this->getItemsFromApiResponse( $resultUnread )
946 );
947 $this->assertEquals(
948 [
949 [
950 'type' => 'new',
951 'notificationtimestamp' => '',
952 'ns' => $subjectTarget->getNamespace(),
953 'title' => $this->getPrefixedText( $subjectTarget )
954 ]
955 ],
956 $this->getItemsFromApiResponse( $resultNotUnread )
957 );
958 }
959
960 public function testShowPatrolledParams() {
961 $user = static::getTestSysop()->getUser();
962 $this->setupPatrolledSpecificFixtures( $user );
963
964 $resultPatrolled = $this->doListWatchlistRequest( [
965 'wlprop' => 'patrol',
966 'wlshow' => WatchedItemQueryService::FILTER_PATROLLED
967 ], $user );
968 $resultNotPatrolled = $this->doListWatchlistRequest( [
969 'wlprop' => 'patrol',
970 'wlshow' => WatchedItemQueryService::FILTER_NOT_PATROLLED
971 ], $user );
972
973 $this->assertEquals(
974 [
975 [
976 'type' => 'new',
977 'patrolled' => true,
978 'unpatrolled' => false,
979 'autopatrolled' => false,
980 ]
981 ],
982 $this->getItemsFromApiResponse( $resultPatrolled )
983 );
984 $this->assertEmpty( $this->getItemsFromApiResponse( $resultNotPatrolled ) );
985 }
986
987 public function testNewAndEditTypeParameters() {
988 $user = $this->getLoggedInTestUser();
989 $subjectTarget = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
990 $talkTarget = new TitleValue( 1, 'ApiQueryWatchlistIntegrationTestPage' );
991 $this->doPageEdits(
992 $user,
993 [
994 [
995 'target' => $subjectTarget,
996 'content' => 'Some Content',
997 'summary' => 'Create the page',
998 ],
999 [
1000 'target' => $subjectTarget,
1001 'content' => 'Some Other Content',
1002 'summary' => 'Change the content',
1003 ],
1004 [
1005 'target' => $talkTarget,
1006 'content' => 'Some Talk Page Content',
1007 'summary' => 'Create Talk page',
1008 ],
1009 ]
1010 );
1011 $this->watchPages( $user, [ $subjectTarget, $talkTarget ] );
1012
1013 $resultNew = $this->doListWatchlistRequest( [ 'wlprop' => 'title', 'wltype' => 'new' ] );
1014 $resultEdit = $this->doListWatchlistRequest( [ 'wlprop' => 'title', 'wltype' => 'edit' ] );
1015
1016 $this->assertEquals(
1017 [
1018 [
1019 'type' => 'new',
1020 'ns' => $talkTarget->getNamespace(),
1021 'title' => $this->getPrefixedText( $talkTarget ),
1022 ],
1023 ],
1024 $this->getItemsFromApiResponse( $resultNew )
1025 );
1026 $this->assertEquals(
1027 [
1028 [
1029 'type' => 'edit',
1030 'ns' => $subjectTarget->getNamespace(),
1031 'title' => $this->getPrefixedText( $subjectTarget ),
1032 ],
1033 ],
1034 $this->getItemsFromApiResponse( $resultEdit )
1035 );
1036 }
1037
1038 public function testLogTypeParameters() {
1039 $user = $this->getLoggedInTestUser();
1040 $subjectTarget = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
1041 $talkTarget = new TitleValue( 1, 'ApiQueryWatchlistIntegrationTestPage' );
1042 $this->createPageAndDeleteIt( $subjectTarget );
1043 $this->doPageEdit(
1044 $user,
1045 $talkTarget,
1046 'Some Talk Page Content',
1047 'Create Talk page'
1048 );
1049 $this->watchPages( $user, [ $subjectTarget, $talkTarget ] );
1050
1051 $result = $this->doListWatchlistRequest( [ 'wlprop' => 'title', 'wltype' => 'log' ] );
1052
1053 $this->assertEquals(
1054 [
1055 [
1056 'type' => 'log',
1057 'ns' => $subjectTarget->getNamespace(),
1058 'title' => $this->getPrefixedText( $subjectTarget ),
1059 ],
1060 ],
1061 $this->getItemsFromApiResponse( $result )
1062 );
1063 }
1064
1065 private function getExternalRC( LinkTarget $target ) {
1066 $title = Title::newFromLinkTarget( $target );
1067
1068 $rc = new RecentChange;
1069 $rc->mTitle = $title;
1070 $rc->mAttribs = [
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',
1076 'rc_minor' => 0,
1077 'rc_cur_id' => $title->getArticleID(),
1078 'rc_user' => 0,
1079 'rc_user_text' => 'ext>External User',
1080 'rc_comment' => '',
1081 'rc_comment_text' => '',
1082 'rc_comment_data' => null,
1083 'rc_this_oldid' => $title->getLatestRevID(),
1084 'rc_last_oldid' => $title->getLatestRevID(),
1085 'rc_bot' => 0,
1086 'rc_ip' => '',
1087 'rc_patrolled' => 0,
1088 'rc_new' => 0,
1089 'rc_old_len' => $title->getLength(),
1090 'rc_new_len' => $title->getLength(),
1091 'rc_deleted' => 0,
1092 'rc_logid' => 0,
1093 'rc_log_type' => null,
1094 'rc_log_action' => '',
1095 'rc_params' => '',
1096 ];
1097 $rc->mExtra = [
1098 'prefixedDBkey' => $title->getPrefixedDBkey(),
1099 'lastTimestamp' => 0,
1100 'oldSize' => $title->getLength(),
1101 'newSize' => $title->getLength(),
1102 'pageStatus' => 'changed'
1103 ];
1104
1105 return $rc;
1106 }
1107
1108 public function testExternalTypeParameters() {
1109 $user = $this->getLoggedInTestUser();
1110 $subjectTarget = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
1111 $talkTarget = new TitleValue( 1, 'ApiQueryWatchlistIntegrationTestPage' );
1112 $this->doPageEdit(
1113 $user,
1114 $subjectTarget,
1115 'Some Content',
1116 'Create the page'
1117 );
1118 $this->doPageEdit(
1119 $user,
1120 $talkTarget,
1121 'Some Talk Page Content',
1122 'Create Talk page'
1123 );
1124
1125 $rc = $this->getExternalRC( $subjectTarget );
1126 $rc->save();
1127
1128 $this->watchPages( $user, [ $subjectTarget, $talkTarget ] );
1129
1130 $result = $this->doListWatchlistRequest( [ 'wlprop' => 'title', 'wltype' => 'external' ] );
1131
1132 $this->assertEquals(
1133 [
1134 [
1135 'type' => 'external',
1136 'ns' => $subjectTarget->getNamespace(),
1137 'title' => $this->getPrefixedText( $subjectTarget ),
1138 ],
1139 ],
1140 $this->getItemsFromApiResponse( $result )
1141 );
1142 }
1143
1144 public function testCategorizeTypeParameter() {
1145 $user = $this->getLoggedInTestUser();
1146 $subjectTarget = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
1147 $categoryTarget = new TitleValue( NS_CATEGORY, 'ApiQueryWatchlistIntegrationTestCategory' );
1148 $this->doPageEdits(
1149 $user,
1150 [
1151 [
1152 'target' => $categoryTarget,
1153 'content' => 'Some Content',
1154 'summary' => 'Create the category',
1155 ],
1156 [
1157 'target' => $subjectTarget,
1158 'content' => 'Some Content [[Category:ApiQueryWatchlistIntegrationTestCategory]]t',
1159 'summary' => 'Create the page and add it to the category',
1160 ],
1161 ]
1162 );
1163 $title = Title::newFromLinkTarget( $subjectTarget );
1164 $revision = Revision::newFromTitle( $title );
1165
1166 $rc = RecentChange::newForCategorization(
1167 $revision->getTimestamp(),
1168 Title::newFromLinkTarget( $categoryTarget ),
1169 $user,
1170 $revision->getComment(),
1171 $title,
1172 0,
1173 $revision->getId(),
1174 null,
1175 false
1176 );
1177 $rc->save();
1178
1179 $this->watchPages( $user, [ $subjectTarget, $categoryTarget ] );
1180
1181 $result = $this->doListWatchlistRequest( [ 'wlprop' => 'title', 'wltype' => 'categorize' ] );
1182
1183 $this->assertEquals(
1184 [
1185 [
1186 'type' => 'categorize',
1187 'ns' => $categoryTarget->getNamespace(),
1188 'title' => $this->getPrefixedText( $categoryTarget ),
1189 ],
1190 ],
1191 $this->getItemsFromApiResponse( $result )
1192 );
1193 }
1194
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' );
1200 $this->doPageEdits(
1201 $user,
1202 [
1203 [
1204 'target' => $target1,
1205 'content' => 'Some Content',
1206 'summary' => 'Create the page',
1207 ],
1208 [
1209 'target' => $target2,
1210 'content' => 'Some Talk Page Content',
1211 'summary' => 'Create Talk page',
1212 ],
1213 [
1214 'target' => $target3,
1215 'content' => 'Some Other Content',
1216 'summary' => 'Create the page',
1217 ],
1218 ]
1219 );
1220 $this->watchPages( $user, [ $target1, $target2, $target3 ] );
1221
1222 $resultWithoutLimit = $this->doListWatchlistRequest( [ 'wlprop' => 'title' ] );
1223 $resultWithLimit = $this->doListWatchlistRequest( [ 'wllimit' => 2, 'wlprop' => 'title' ] );
1224
1225 $this->assertEquals(
1226 [
1227 [
1228 'type' => 'new',
1229 'ns' => $target3->getNamespace(),
1230 'title' => $this->getPrefixedText( $target3 )
1231 ],
1232 [
1233 'type' => 'new',
1234 'ns' => $target2->getNamespace(),
1235 'title' => $this->getPrefixedText( $target2 )
1236 ],
1237 [
1238 'type' => 'new',
1239 'ns' => $target1->getNamespace(),
1240 'title' => $this->getPrefixedText( $target1 )
1241 ],
1242 ],
1243 $this->getItemsFromApiResponse( $resultWithoutLimit )
1244 );
1245 $this->assertEquals(
1246 [
1247 [
1248 'type' => 'new',
1249 'ns' => $target3->getNamespace(),
1250 'title' => $this->getPrefixedText( $target3 )
1251 ],
1252 [
1253 'type' => 'new',
1254 'ns' => $target2->getNamespace(),
1255 'title' => $this->getPrefixedText( $target2 )
1256 ],
1257 ],
1258 $this->getItemsFromApiResponse( $resultWithLimit )
1259 );
1260 $this->assertArrayHasKey( 'continue', $resultWithLimit[0] );
1261 $this->assertArrayHasKey( 'wlcontinue', $resultWithLimit[0]['continue'] );
1262 }
1263
1264 public function testAllRevParam() {
1265 $user = $this->getLoggedInTestUser();
1266 $target = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
1267 $this->doPageEdits(
1268 $user,
1269 [
1270 [
1271 'target' => $target,
1272 'content' => 'Some Content',
1273 'summary' => 'Create the page',
1274 ],
1275 [
1276 'target' => $target,
1277 'content' => 'Some Other Content',
1278 'summary' => 'Change the content',
1279 ],
1280 ]
1281 );
1282 $this->watchPages( $user, [ $target ] );
1283
1284 $resultAllRev = $this->doListWatchlistRequest( [ 'wlprop' => 'title', 'wlallrev' => '', ] );
1285 $resultNoAllRev = $this->doListWatchlistRequest( [ 'wlprop' => 'title' ] );
1286
1287 $this->assertEquals(
1288 [
1289 [
1290 'type' => 'edit',
1291 'ns' => $target->getNamespace(),
1292 'title' => $this->getPrefixedText( $target ),
1293 ],
1294 ],
1295 $this->getItemsFromApiResponse( $resultNoAllRev )
1296 );
1297 $this->assertEquals(
1298 [
1299 [
1300 'type' => 'edit',
1301 'ns' => $target->getNamespace(),
1302 'title' => $this->getPrefixedText( $target ),
1303 ],
1304 [
1305 'type' => 'new',
1306 'ns' => $target->getNamespace(),
1307 'title' => $this->getPrefixedText( $target ),
1308 ],
1309 ],
1310 $this->getItemsFromApiResponse( $resultAllRev )
1311 );
1312 }
1313
1314 public function testDirParams() {
1315 $user = $this->getLoggedInTestUser();
1316 $subjectTarget = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
1317 $talkTarget = new TitleValue( 1, 'ApiQueryWatchlistIntegrationTestPage' );
1318 $this->doPageEdits(
1319 $user,
1320 [
1321 [
1322 'target' => $subjectTarget,
1323 'content' => 'Some Content',
1324 'summary' => 'Create the page',
1325 ],
1326 [
1327 'target' => $talkTarget,
1328 'content' => 'Some Talk Page Content',
1329 'summary' => 'Create Talk page',
1330 ],
1331 ]
1332 );
1333 $this->watchPages( $user, [ $subjectTarget, $talkTarget ] );
1334
1335 $resultDirOlder = $this->doListWatchlistRequest( [ 'wldir' => 'older', 'wlprop' => 'title' ] );
1336 $resultDirNewer = $this->doListWatchlistRequest( [ 'wldir' => 'newer', 'wlprop' => 'title' ] );
1337
1338 $this->assertEquals(
1339 [
1340 [
1341 'type' => 'new',
1342 'ns' => $talkTarget->getNamespace(),
1343 'title' => $this->getPrefixedText( $talkTarget )
1344 ],
1345 [
1346 'type' => 'new',
1347 'ns' => $subjectTarget->getNamespace(),
1348 'title' => $this->getPrefixedText( $subjectTarget )
1349 ],
1350 ],
1351 $this->getItemsFromApiResponse( $resultDirOlder )
1352 );
1353 $this->assertEquals(
1354 [
1355 [
1356 'type' => 'new',
1357 'ns' => $subjectTarget->getNamespace(),
1358 'title' => $this->getPrefixedText( $subjectTarget )
1359 ],
1360 [
1361 'type' => 'new',
1362 'ns' => $talkTarget->getNamespace(),
1363 'title' => $this->getPrefixedText( $talkTarget )
1364 ],
1365 ],
1366 $this->getItemsFromApiResponse( $resultDirNewer )
1367 );
1368 }
1369
1370 public function testStartEndParams() {
1371 $user = $this->getLoggedInTestUser();
1372 $target = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
1373 $this->doPageEdit(
1374 $user,
1375 $target,
1376 'Some Content',
1377 'Create the page'
1378 );
1379 $this->watchPages( $user, [ $target ] );
1380
1381 $resultStart = $this->doListWatchlistRequest( [
1382 'wlstart' => '20010115000000',
1383 'wldir' => 'newer',
1384 'wlprop' => 'title',
1385 ] );
1386 $resultEnd = $this->doListWatchlistRequest( [
1387 'wlend' => '20010115000000',
1388 'wldir' => 'newer',
1389 'wlprop' => 'title',
1390 ] );
1391
1392 $this->assertEquals(
1393 [
1394 [
1395 'type' => 'new',
1396 'ns' => $target->getNamespace(),
1397 'title' => $this->getPrefixedText( $target ),
1398 ]
1399 ],
1400 $this->getItemsFromApiResponse( $resultStart )
1401 );
1402 $this->assertEmpty( $this->getItemsFromApiResponse( $resultEnd ) );
1403 }
1404
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' );
1410 $this->doPageEdits(
1411 $user,
1412 [
1413 [
1414 'target' => $target1,
1415 'content' => 'Some Content',
1416 'summary' => 'Create the page',
1417 ],
1418 [
1419 'target' => $target2,
1420 'content' => 'Some Talk Page Content',
1421 'summary' => 'Create Talk page',
1422 ],
1423 [
1424 'target' => $target3,
1425 'content' => 'Some Other Content',
1426 'summary' => 'Create the page',
1427 ],
1428 ]
1429 );
1430 $this->watchPages( $user, [ $target1, $target2, $target3 ] );
1431
1432 $firstResult = $this->doListWatchlistRequest( [ 'wllimit' => 2, 'wlprop' => 'title' ] );
1433 $this->assertArrayHasKey( 'continue', $firstResult[0] );
1434 $this->assertArrayHasKey( 'wlcontinue', $firstResult[0]['continue'] );
1435
1436 $continuationParam = $firstResult[0]['continue']['wlcontinue'];
1437
1438 $continuedResult = $this->doListWatchlistRequest(
1439 [ 'wlcontinue' => $continuationParam, 'wlprop' => 'title' ]
1440 );
1441
1442 $this->assertEquals(
1443 [
1444 [
1445 'type' => 'new',
1446 'ns' => $target3->getNamespace(),
1447 'title' => $this->getPrefixedText( $target3 ),
1448 ],
1449 [
1450 'type' => 'new',
1451 'ns' => $target2->getNamespace(),
1452 'title' => $this->getPrefixedText( $target2 ),
1453 ],
1454 ],
1455 $this->getItemsFromApiResponse( $firstResult )
1456 );
1457 $this->assertEquals(
1458 [
1459 [
1460 'type' => 'new',
1461 'ns' => $target1->getNamespace(),
1462 'title' => $this->getPrefixedText( $target1 )
1463 ]
1464 ],
1465 $this->getItemsFromApiResponse( $continuedResult )
1466 );
1467 }
1468
1469 public function testOwnerAndTokenParams() {
1470 $target = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
1471 $this->doPageEdit(
1472 $this->getLoggedInTestUser(),
1473 $target,
1474 'Some Content',
1475 'Create the page'
1476 );
1477
1478 $otherUser = $this->getNonLoggedInTestUser();
1479 $otherUser->setOption( 'watchlisttoken', '1234567890' );
1480 $otherUser->saveSettings();
1481
1482 $this->watchPages( $otherUser, [ $target ] );
1483
1484 $reloadedUser = User::newFromName( $otherUser->getName() );
1485 $this->assertEquals( '1234567890', $reloadedUser->getOption( 'watchlisttoken' ) );
1486
1487 $result = $this->doListWatchlistRequest( [
1488 'wlowner' => $otherUser->getName(),
1489 'wltoken' => '1234567890',
1490 'wlprop' => 'title',
1491 ] );
1492
1493 $this->assertEquals(
1494 [
1495 [
1496 'type' => 'new',
1497 'ns' => $target->getNamespace(),
1498 'title' => $this->getPrefixedText( $target )
1499 ]
1500 ],
1501 $this->getItemsFromApiResponse( $result )
1502 );
1503 }
1504
1505 public function testOwnerAndTokenParams_wrongToken() {
1506 $otherUser = $this->getNonLoggedInTestUser();
1507 $otherUser->setOption( 'watchlisttoken', '1234567890' );
1508 $otherUser->saveSettings();
1509
1510 $this->setExpectedException( ApiUsageException::class, 'Incorrect watchlist token provided' );
1511
1512 $this->doListWatchlistRequest( [
1513 'wlowner' => $otherUser->getName(),
1514 'wltoken' => 'wrong-token',
1515 ] );
1516 }
1517
1518 public function testOwnerAndTokenParams_noWatchlistTokenSet() {
1519 $this->setExpectedException( ApiUsageException::class, 'Incorrect watchlist token provided' );
1520
1521 $this->doListWatchlistRequest( [
1522 'wlowner' => $this->getNonLoggedInTestUser()->getName(),
1523 'wltoken' => 'some-token',
1524 ] );
1525 }
1526
1527 public function testGeneratorWatchlistPropInfo_returnsWatchedPages() {
1528 $user = $this->getLoggedInTestUser();
1529 $target = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
1530 $this->doPageEdit(
1531 $user,
1532 $target,
1533 'Some Content',
1534 'Create the page'
1535 );
1536 $this->watchPages( $user, [ $target ] );
1537
1538 $result = $this->doGeneratorWatchlistRequest( [ 'prop' => 'info' ] );
1539
1540 $this->assertArrayHasKey( 'query', $result[0] );
1541 $this->assertArrayHasKey( 'pages', $result[0]['query'] );
1542
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'] );
1545
1546 $this->assertArraySubsetsEqual(
1547 $pages,
1548 [
1549 [
1550 'ns' => $target->getNamespace(),
1551 'title' => $this->getPrefixedText( $target ),
1552 'new' => true,
1553 ]
1554 ],
1555 [ 'ns', 'title', 'new' ]
1556 );
1557 }
1558
1559 public function testGeneratorWatchlistPropRevisions_returnsWatchedItemsRevisions() {
1560 $user = $this->getLoggedInTestUser();
1561 $target = new TitleValue( 0, 'ApiQueryWatchlistIntegrationTestPage' );
1562 $this->doPageEdits(
1563 $user,
1564 [
1565 [
1566 'target' => $target,
1567 'content' => 'Some Content',
1568 'summary' => 'Create the page',
1569 ],
1570 [
1571 'target' => $target,
1572 'content' => 'Some Other Content',
1573 'summary' => 'Change the content',
1574 ],
1575 ]
1576 );
1577 $this->watchPages( $user, [ $target ] );
1578
1579 $result = $this->doGeneratorWatchlistRequest( [ 'prop' => 'revisions', 'gwlallrev' => '' ] );
1580
1581 $this->assertArrayHasKey( 'query', $result[0] );
1582 $this->assertArrayHasKey( 'pages', $result[0]['query'] );
1583
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'] );
1586
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'],
1592 [
1593 [
1594 'comment' => 'Create the page',
1595 'user' => $user->getName(),
1596 'minor' => false,
1597 ],
1598 [
1599 'comment' => 'Change the content',
1600 'user' => $user->getName(),
1601 'minor' => false,
1602 ],
1603 ],
1604 [ 'comment', 'user', 'minor' ]
1605 );
1606 }
1607
1608 }