Merge "Print styles: Wrap CSS-generated URLs"
[lhc/web/wiklou.git] / tests / phpunit / includes / WatchedItemStoreUnitTest.php
index 9b3e798..6c4a6f0 100644 (file)
@@ -1,11 +1,12 @@
 <?php
+use MediaWiki\Linker\LinkTarget;
 
 /**
  * @author Addshore
  *
  * @covers WatchedItemStore
  */
-class WatchedItemStoreUnitTest extends PHPUnit_Framework_TestCase {
+class WatchedItemStoreUnitTest extends MediaWikiTestCase {
 
        /**
         * @return PHPUnit_Framework_MockObject_MockObject|IDatabase
@@ -93,23 +94,6 @@ class WatchedItemStoreUnitTest extends PHPUnit_Framework_TestCase {
                );
        }
 
-       public function testGetDefaultInstance() {
-               $instanceOne = WatchedItemStore::getDefaultInstance();
-               $instanceTwo = WatchedItemStore::getDefaultInstance();
-               $this->assertSame( $instanceOne, $instanceTwo );
-       }
-
-       public function testOverrideDefaultInstance() {
-               $instance = WatchedItemStore::getDefaultInstance();
-               $scopedOverride = $instance->overrideDefaultInstance( null );
-
-               $this->assertNotSame( $instance, WatchedItemStore::getDefaultInstance() );
-
-               unset( $scopedOverride );
-
-               $this->assertSame( $instance, WatchedItemStore::getDefaultInstance() );
-       }
-
        public function testCountWatchedItems() {
                $user = $this->getMockNonAnonUserWithId( 1 );
 
@@ -813,7 +797,20 @@ class WatchedItemStoreUnitTest extends PHPUnit_Framework_TestCase {
                );
        }
 
-       public function testDuplicateAllAssociatedEntries_somethingToDuplicate() {
+       public function provideLinkTargetPairs() {
+               return [
+                       [ Title::newFromText( 'Old_Title' ), Title::newFromText( 'New_Title' ) ],
+                       [ new TitleValue( 0, 'Old_Title' ),  new TitleValue( 0, 'New_Title' ) ],
+               ];
+       }
+
+       /**
+        * @dataProvider provideLinkTargetPairs
+        */
+       public function testDuplicateAllAssociatedEntries_somethingToDuplicate(
+               LinkTarget $oldTarget,
+               LinkTarget $newTarget
+       ) {
                $fakeRows = [
                        $this->getFakeRow( [ 'wl_user' => 1, 'wl_notificationtimestamp' => '20151212010101' ] ),
                ];
@@ -828,8 +825,8 @@ class WatchedItemStoreUnitTest extends PHPUnit_Framework_TestCase {
                                        'wl_notificationtimestamp',
                                ],
                                [
-                                       'wl_namespace' => 0,
-                                       'wl_title' => 'Old_Title',
+                                       'wl_namespace' => $oldTarget->getNamespace(),
+                                       'wl_title' => $oldTarget->getDBkey(),
                                ]
                        )
                        ->will( $this->returnValue( new FakeResultWrapper( $fakeRows ) ) );
@@ -841,8 +838,8 @@ class WatchedItemStoreUnitTest extends PHPUnit_Framework_TestCase {
                                [
                                        [
                                                'wl_user' => 1,
-                                               'wl_namespace' => 0,
-                                               'wl_title' => 'New_Title',
+                                               'wl_namespace' => $newTarget->getNamespace(),
+                                               'wl_title' => $newTarget->getDBkey(),
                                                'wl_notificationtimestamp' => '20151212010101',
                                        ],
                                ],
@@ -857,8 +854,8 @@ class WatchedItemStoreUnitTest extends PHPUnit_Framework_TestCase {
                                        'wl_notificationtimestamp',
                                ],
                                [
-                                       'wl_namespace' => 1,
-                                       'wl_title' => 'Old_Title',
+                                       'wl_namespace' => $oldTarget->getNamespace() + 1,
+                                       'wl_title' => $oldTarget->getDBkey(),
                                ]
                        )
                        ->will( $this->returnValue( new FakeResultWrapper( $fakeRows ) ) );
@@ -870,8 +867,8 @@ class WatchedItemStoreUnitTest extends PHPUnit_Framework_TestCase {
                                [
                                        [
                                                'wl_user' => 1,
-                                               'wl_namespace' => 1,
-                                               'wl_title' => 'New_Title',
+                                               'wl_namespace' => $newTarget->getNamespace() + 1,
+                                               'wl_title' => $newTarget->getDBkey(),
                                                'wl_notificationtimestamp' => '20151212010101',
                                        ],
                                ],
@@ -888,8 +885,8 @@ class WatchedItemStoreUnitTest extends PHPUnit_Framework_TestCase {
                );
 
                $store->duplicateAllAssociatedEntries(
-                       Title::newFromText( 'Old_Title' ),
-                       Title::newFromText( 'New_Title' )
+                       $oldTarget,
+                       $newTarget
                );
        }
 
@@ -1993,6 +1990,33 @@ class WatchedItemStoreUnitTest extends PHPUnit_Framework_TestCase {
                return $title;
        }
 
+       private function verifyCallbackJob(
+               $callback,
+               LinkTarget $expectedTitle,
+               $expectedUserId,
+               callable $notificationTimestampCondition
+       ) {
+               $this->assertInternalType( 'callable', $callback );
+
+               $callbackReflector = new ReflectionFunction( $callback );
+               $vars = $callbackReflector->getStaticVariables();
+               $this->assertArrayHasKey( 'job', $vars );
+               $this->assertInstanceOf( ActivityUpdateJob::class, $vars['job'] );
+
+               /** @var ActivityUpdateJob $job */
+               $job = $vars['job'];
+               $this->assertEquals( $expectedTitle->getDBkey(), $job->getTitle()->getDBkey() );
+               $this->assertEquals( $expectedTitle->getNamespace(), $job->getTitle()->getNamespace() );
+
+               $jobParams = $job->getParams();
+               $this->assertArrayHasKey( 'type', $jobParams );
+               $this->assertEquals( 'updateWatchlistNotification', $jobParams['type'] );
+               $this->assertArrayHasKey( 'userid', $jobParams );
+               $this->assertEquals( $expectedUserId, $jobParams['userid'] );
+               $this->assertArrayHasKey( 'notifTime', $jobParams );
+               $this->assertTrue( $notificationTimestampCondition( $jobParams['notifTime'] ) );
+       }
+
        public function testResetNotificationTimestamp_oldidSpecifiedLatestRevisionForced() {
                $user = $this->getMockNonAnonUserWithId( 1 );
                $oldid = 22;
@@ -2019,12 +2043,18 @@ class WatchedItemStoreUnitTest extends PHPUnit_Framework_TestCase {
                        $mockCache
                );
 
-               // Note: This does not actually assert the job is correct
                $callableCallCounter = 0;
                $scopedOverride = $store->overrideDeferredUpdatesAddCallableUpdateCallback(
-                       function( $callable ) use ( &$callableCallCounter ) {
+                       function( $callable ) use ( &$callableCallCounter, $title, $user ) {
                                $callableCallCounter++;
-                               $this->assertInternalType( 'callable', $callable );
+                               $this->verifyCallbackJob(
+                                       $callable,
+                                       $title,
+                                       $user->getId(),
+                                       function( $time ) {
+                                               return $time === null;
+                                       }
+                               );
                        }
                );
 
@@ -2079,12 +2109,159 @@ class WatchedItemStoreUnitTest extends PHPUnit_Framework_TestCase {
                        $mockCache
                );
 
-               // Note: This does not actually assert the job is correct
                $addUpdateCallCounter = 0;
                $scopedOverrideDeferred = $store->overrideDeferredUpdatesAddCallableUpdateCallback(
-                       function( $callable ) use ( &$addUpdateCallCounter ) {
+                       function( $callable ) use ( &$addUpdateCallCounter, $title, $user ) {
+                               $addUpdateCallCounter++;
+                               $this->verifyCallbackJob(
+                                       $callable,
+                                       $title,
+                                       $user->getId(),
+                                       function( $time ) {
+                                               return $time !== null && $time > '20151212010101';
+                                       }
+                               );
+                       }
+               );
+
+               $getTimestampCallCounter = 0;
+               $scopedOverrideRevision = $store->overrideRevisionGetTimestampFromIdCallback(
+                       function( $titleParam, $oldidParam ) use ( &$getTimestampCallCounter, $title, $oldid ) {
+                               $getTimestampCallCounter++;
+                               $this->assertEquals( $title, $titleParam );
+                               $this->assertEquals( $oldid, $oldidParam );
+                       }
+               );
+
+               $this->assertTrue(
+                       $store->resetNotificationTimestamp(
+                               $user,
+                               $title,
+                               'force',
+                               $oldid
+                       )
+               );
+               $this->assertEquals( 1, $addUpdateCallCounter );
+               $this->assertEquals( 1, $getTimestampCallCounter );
+
+               ScopedCallback::consume( $scopedOverrideDeferred );
+               ScopedCallback::consume( $scopedOverrideRevision );
+       }
+
+       public function testResetNotificationTimestamp_notWatchedPageForced() {
+               $user = $this->getMockNonAnonUserWithId( 1 );
+               $oldid = 22;
+               $title = $this->getMockTitle( 'SomeDbKey' );
+               $title->expects( $this->once() )
+                       ->method( 'getNextRevisionID' )
+                       ->with( $oldid )
+                       ->will( $this->returnValue( 33 ) );
+
+               $mockDb = $this->getMockDb();
+               $mockDb->expects( $this->once() )
+                       ->method( 'selectRow' )
+                       ->with(
+                               'watchlist',
+                               'wl_notificationtimestamp',
+                               [
+                                       'wl_user' => 1,
+                                       'wl_namespace' => 0,
+                                       'wl_title' => 'SomeDbKey',
+                               ]
+                       )
+                       ->will( $this->returnValue( false ) );
+
+               $mockCache = $this->getMockCache();
+               $mockDb->expects( $this->never() )
+                       ->method( 'get' );
+               $mockDb->expects( $this->never() )
+                       ->method( 'set' );
+               $mockDb->expects( $this->never() )
+                       ->method( 'delete' );
+
+               $store = $this->newWatchedItemStore(
+                       $this->getMockLoadBalancer( $mockDb ),
+                       $mockCache
+               );
+
+               $callableCallCounter = 0;
+               $scopedOverride = $store->overrideDeferredUpdatesAddCallableUpdateCallback(
+                       function( $callable ) use ( &$callableCallCounter, $title, $user ) {
+                               $callableCallCounter++;
+                               $this->verifyCallbackJob(
+                                       $callable,
+                                       $title,
+                                       $user->getId(),
+                                       function( $time ) {
+                                               return $time === null;
+                                       }
+                               );
+                       }
+               );
+
+               $this->assertTrue(
+                       $store->resetNotificationTimestamp(
+                               $user,
+                               $title,
+                               'force',
+                               $oldid
+                       )
+               );
+               $this->assertEquals( 1, $callableCallCounter );
+
+               ScopedCallback::consume( $scopedOverride );
+       }
+
+       public function testResetNotificationTimestamp_futureNotificationTimestampForced() {
+               $user = $this->getMockNonAnonUserWithId( 1 );
+               $oldid = 22;
+               $title = $this->getMockTitle( 'SomeDbKey' );
+               $title->expects( $this->once() )
+                       ->method( 'getNextRevisionID' )
+                       ->with( $oldid )
+                       ->will( $this->returnValue( 33 ) );
+
+               $mockDb = $this->getMockDb();
+               $mockDb->expects( $this->once() )
+                       ->method( 'selectRow' )
+                       ->with(
+                               'watchlist',
+                               'wl_notificationtimestamp',
+                               [
+                                       'wl_user' => 1,
+                                       'wl_namespace' => 0,
+                                       'wl_title' => 'SomeDbKey',
+                               ]
+                       )
+                       ->will( $this->returnValue(
+                               $this->getFakeRow( [ 'wl_notificationtimestamp' => '30151212010101' ] )
+                       ) );
+
+               $mockCache = $this->getMockCache();
+               $mockDb->expects( $this->never() )
+                       ->method( 'get' );
+               $mockDb->expects( $this->never() )
+                       ->method( 'set' );
+               $mockDb->expects( $this->never() )
+                       ->method( 'delete' );
+
+               $store = $this->newWatchedItemStore(
+                       $this->getMockLoadBalancer( $mockDb ),
+                       $mockCache
+               );
+
+               $addUpdateCallCounter = 0;
+               $scopedOverrideDeferred = $store->overrideDeferredUpdatesAddCallableUpdateCallback(
+                       function( $callable ) use ( &$addUpdateCallCounter, $title, $user ) {
                                $addUpdateCallCounter++;
-                               $this->assertInternalType( 'callable', $callable );
+                               $this->verifyCallbackJob(
+                                       $callable,
+                                       $title,
+                                       $user->getId(),
+                                       function( $time ) {
+                                               return $time === '30151212010101';
+                                       }
+                               );
                        }
                );
 
@@ -2112,6 +2289,83 @@ class WatchedItemStoreUnitTest extends PHPUnit_Framework_TestCase {
                ScopedCallback::consume( $scopedOverrideRevision );
        }
 
+       public function testResetNotificationTimestamp_futureNotificationTimestampNotForced() {
+               $user = $this->getMockNonAnonUserWithId( 1 );
+               $oldid = 22;
+               $title = $this->getMockTitle( 'SomeDbKey' );
+               $title->expects( $this->once() )
+                       ->method( 'getNextRevisionID' )
+                       ->with( $oldid )
+                       ->will( $this->returnValue( 33 ) );
+
+               $mockDb = $this->getMockDb();
+               $mockDb->expects( $this->once() )
+                       ->method( 'selectRow' )
+                       ->with(
+                               'watchlist',
+                               'wl_notificationtimestamp',
+                               [
+                                       'wl_user' => 1,
+                                       'wl_namespace' => 0,
+                                       'wl_title' => 'SomeDbKey',
+                               ]
+                       )
+                       ->will( $this->returnValue(
+                               $this->getFakeRow( [ 'wl_notificationtimestamp' => '30151212010101' ] )
+                       ) );
+
+               $mockCache = $this->getMockCache();
+               $mockDb->expects( $this->never() )
+                       ->method( 'get' );
+               $mockDb->expects( $this->never() )
+                       ->method( 'set' );
+               $mockDb->expects( $this->never() )
+                       ->method( 'delete' );
+
+               $store = $this->newWatchedItemStore(
+                       $this->getMockLoadBalancer( $mockDb ),
+                       $mockCache
+               );
+
+               $addUpdateCallCounter = 0;
+               $scopedOverrideDeferred = $store->overrideDeferredUpdatesAddCallableUpdateCallback(
+                       function( $callable ) use ( &$addUpdateCallCounter, $title, $user ) {
+                               $addUpdateCallCounter++;
+                               $this->verifyCallbackJob(
+                                       $callable,
+                                       $title,
+                                       $user->getId(),
+                                       function( $time ) {
+                                               return $time === false;
+                                       }
+                               );
+                       }
+               );
+
+               $getTimestampCallCounter = 0;
+               $scopedOverrideRevision = $store->overrideRevisionGetTimestampFromIdCallback(
+                       function( $titleParam, $oldidParam ) use ( &$getTimestampCallCounter, $title, $oldid ) {
+                               $getTimestampCallCounter++;
+                               $this->assertEquals( $title, $titleParam );
+                               $this->assertEquals( $oldid, $oldidParam );
+                       }
+               );
+
+               $this->assertTrue(
+                       $store->resetNotificationTimestamp(
+                               $user,
+                               $title,
+                               '',
+                               $oldid
+                       )
+               );
+               $this->assertEquals( 1, $addUpdateCallCounter );
+               $this->assertEquals( 1, $getTimestampCallCounter );
+
+               ScopedCallback::consume( $scopedOverrideDeferred );
+               ScopedCallback::consume( $scopedOverrideRevision );
+       }
+
        public function testUpdateNotificationTimestamp_watchersExist() {
                $mockDb = $this->getMockDb();
                $mockDb->expects( $this->once() )