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