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