3 use MediaWiki\MediaWikiServices
;
4 use Wikimedia\TestingAccessWrapper
;
11 * @covers WatchedItemStore
13 class WatchedItemStoreIntegrationTest
extends MediaWikiTestCase
{
15 public function setUp() {
17 self
::$users['WatchedItemStoreIntegrationTestUser']
18 = new TestUser( 'WatchedItemStoreIntegrationTestUser' );
21 private function getUser() {
22 return self
::$users['WatchedItemStoreIntegrationTestUser']->getUser();
25 public function testWatchAndUnWatchItem() {
26 $user = $this->getUser();
27 $title = Title
::newFromText( 'WatchedItemStoreIntegrationTestPage' );
28 $store = MediaWikiServices
::getInstance()->getWatchedItemStore();
29 // Cleanup after previous tests
30 $store->removeWatch( $user, $title );
31 $initialWatchers = $store->countWatchers( $title );
32 $initialUserWatchedItems = $store->countWatchedItems( $user );
35 $store->isWatched( $user, $title ),
36 'Page should not initially be watched'
39 $store->addWatch( $user, $title );
41 $store->isWatched( $user, $title ),
42 'Page should be watched'
44 $this->assertEquals( $initialUserWatchedItems +
1, $store->countWatchedItems( $user ) );
45 $watchedItemsForUser = $store->getWatchedItemsForUser( $user );
46 $this->assertCount( $initialUserWatchedItems +
1, $watchedItemsForUser );
47 $watchedItemsForUserHasExpectedItem = false;
48 foreach ( $watchedItemsForUser as $watchedItem ) {
50 $watchedItem->getUser()->equals( $user ) &&
51 $watchedItem->getLinkTarget() == $title->getTitleValue()
53 $watchedItemsForUserHasExpectedItem = true;
57 $watchedItemsForUserHasExpectedItem,
58 'getWatchedItemsForUser should contain the page'
60 $this->assertEquals( $initialWatchers +
1, $store->countWatchers( $title ) );
63 $store->countWatchersMultiple( [ $title ] )[$title->getNamespace()][$title->getDBkey()]
66 [ 0 => [ 'WatchedItemStoreIntegrationTestPage' => $initialWatchers +
1 ] ],
67 $store->countWatchersMultiple( [ $title ], [ 'minimumWatchers' => $initialWatchers +
1 ] )
70 [ 0 => [ 'WatchedItemStoreIntegrationTestPage' => 0 ] ],
71 $store->countWatchersMultiple( [ $title ], [ 'minimumWatchers' => $initialWatchers +
2 ] )
74 [ $title->getNamespace() => [ $title->getDBkey() => null ] ],
75 $store->getNotificationTimestampsBatch( $user, [ $title ] )
78 $store->removeWatch( $user, $title );
80 $store->isWatched( $user, $title ),
81 'Page should be unwatched'
83 $this->assertEquals( $initialUserWatchedItems, $store->countWatchedItems( $user ) );
84 $watchedItemsForUser = $store->getWatchedItemsForUser( $user );
85 $this->assertCount( $initialUserWatchedItems, $watchedItemsForUser );
86 $watchedItemsForUserHasExpectedItem = false;
87 foreach ( $watchedItemsForUser as $watchedItem ) {
89 $watchedItem->getUser()->equals( $user ) &&
90 $watchedItem->getLinkTarget() == $title->getTitleValue()
92 $watchedItemsForUserHasExpectedItem = true;
96 $watchedItemsForUserHasExpectedItem,
97 'getWatchedItemsForUser should not contain the page'
99 $this->assertEquals( $initialWatchers, $store->countWatchers( $title ) );
102 $store->countWatchersMultiple( [ $title ] )[$title->getNamespace()][$title->getDBkey()]
105 [ $title->getNamespace() => [ $title->getDBkey() => false ] ],
106 $store->getNotificationTimestampsBatch( $user, [ $title ] )
110 public function testWatchBatchAndClearItems() {
111 $user = $this->getUser();
112 $title1 = Title
::newFromText( 'WatchedItemStoreIntegrationTestPage1' );
113 $title2 = Title
::newFromText( 'WatchedItemStoreIntegrationTestPage2' );
114 $store = MediaWikiServices
::getInstance()->getWatchedItemStore();
116 $store->addWatchBatchForUser( $user, [ $title1, $title2 ] );
118 $this->assertTrue( $store->isWatched( $user, $title1 ) );
119 $this->assertTrue( $store->isWatched( $user, $title2 ) );
121 $store->clearUserWatchedItems( $user );
123 $this->assertFalse( $store->isWatched( $user, $title1 ) );
124 $this->assertFalse( $store->isWatched( $user, $title2 ) );
127 public function testUpdateResetAndSetNotificationTimestamp() {
128 $user = $this->getUser();
129 $otherUser = ( new TestUser( 'WatchedItemStoreIntegrationTestUser_otherUser' ) )->getUser();
130 $title = Title
::newFromText( 'WatchedItemStoreIntegrationTestPage' );
131 $store = MediaWikiServices
::getInstance()->getWatchedItemStore();
132 $store->addWatch( $user, $title );
133 $this->assertNull( $store->loadWatchedItem( $user, $title )->getNotificationTimestamp() );
134 $initialVisitingWatchers = $store->countVisitingWatchers( $title, '20150202020202' );
135 $initialUnreadNotifications = $store->countUnreadNotifications( $user );
137 $store->updateNotificationTimestamp( $otherUser, $title, '20150202010101' );
140 $store->loadWatchedItem( $user, $title )->getNotificationTimestamp()
143 [ $title->getNamespace() => [ $title->getDBkey() => '20150202010101' ] ],
144 $store->getNotificationTimestampsBatch( $user, [ $title ] )
147 $initialVisitingWatchers - 1,
148 $store->countVisitingWatchers( $title, '20150202020202' )
151 $initialVisitingWatchers - 1,
152 $store->countVisitingWatchersMultiple(
153 [ [ $title, '20150202020202' ] ]
154 )[$title->getNamespace()][$title->getDBkey()]
157 $initialUnreadNotifications +
1,
158 $store->countUnreadNotifications( $user )
162 $store->countUnreadNotifications( $user, $initialUnreadNotifications +
1 )
165 $this->assertTrue( $store->resetNotificationTimestamp( $user, $title ) );
166 $this->assertNull( $store->getWatchedItem( $user, $title )->getNotificationTimestamp() );
168 [ $title->getNamespace() => [ $title->getDBkey() => null ] ],
169 $store->getNotificationTimestampsBatch( $user, [ $title ] )
173 JobQueueGroup
::destroySingletons();
175 $jobs->loadParamsAndArgs( null, [ 'quiet' => true ], null );
179 $initialVisitingWatchers,
180 $store->countVisitingWatchers( $title, '20150202020202' )
183 $initialVisitingWatchers,
184 $store->countVisitingWatchersMultiple(
185 [ [ $title, '20150202020202' ] ]
186 )[$title->getNamespace()][$title->getDBkey()]
189 [ 0 => [ 'WatchedItemStoreIntegrationTestPage' => $initialVisitingWatchers ] ],
190 $store->countVisitingWatchersMultiple(
191 [ [ $title, '20150202020202' ] ], $initialVisitingWatchers
195 [ 0 => [ 'WatchedItemStoreIntegrationTestPage' => 0 ] ],
196 $store->countVisitingWatchersMultiple(
197 [ [ $title, '20150202020202' ] ], $initialVisitingWatchers +
1
201 // setNotificationTimestampsForUser specifying a title
203 $store->setNotificationTimestampsForUser( $user, '20100202020202', [ $title ] )
207 $store->getWatchedItem( $user, $title )->getNotificationTimestamp()
210 // setNotificationTimestampsForUser not specifying a title
211 // This will try to use a DeferredUpdate; disable that
212 $mockCallback = function ( $callback ) {
215 $scopedOverride = $store->overrideDeferredUpdatesAddCallableUpdateCallback( $mockCallback );
217 $store->setNotificationTimestampsForUser( $user, '20110202020202' )
219 // Because the operation above is normally deferred, it doesn't clear the cache
220 // Clear the cache manually
221 $wrappedStore = TestingAccessWrapper
::newFromObject( $store );
222 $wrappedStore->uncacheUser( $user );
225 $store->getWatchedItem( $user, $title )->getNotificationTimestamp()
229 public function testDuplicateAllAssociatedEntries() {
230 $user = $this->getUser();
231 $titleOld = Title
::newFromText( 'WatchedItemStoreIntegrationTestPageOld' );
232 $titleNew = Title
::newFromText( 'WatchedItemStoreIntegrationTestPageNew' );
233 $store = MediaWikiServices
::getInstance()->getWatchedItemStore();
234 $store->addWatch( $user, $titleOld->getSubjectPage() );
235 $store->addWatch( $user, $titleOld->getTalkPage() );
236 // Cleanup after previous tests
237 $store->removeWatch( $user, $titleNew->getSubjectPage() );
238 $store->removeWatch( $user, $titleNew->getTalkPage() );
240 $store->duplicateAllAssociatedEntries( $titleOld, $titleNew );
242 $this->assertTrue( $store->isWatched( $user, $titleOld->getSubjectPage() ) );
243 $this->assertTrue( $store->isWatched( $user, $titleOld->getTalkPage() ) );
244 $this->assertTrue( $store->isWatched( $user, $titleNew->getSubjectPage() ) );
245 $this->assertTrue( $store->isWatched( $user, $titleNew->getTalkPage() ) );