X-Git-Url: http://git.heureux-cyclage.org/?a=blobdiff_plain;f=tests%2Fphpunit%2Fincludes%2Fwatcheditem%2FWatchedItemQueryServiceUnitTest.php;h=50e6c202f45c4e5befa26a071ab429c09b9d2e0f;hb=e9044fe58dc46551a6eb630ed8f9ac97a12e075b;hp=b6cf2396e13a20d35d92a6d544198bf30ac85927;hpb=e81a7da6c000384b97319c269ffd1e67afcb8ea8;p=lhc%2Fweb%2Fwiklou.git diff --git a/tests/phpunit/includes/watcheditem/WatchedItemQueryServiceUnitTest.php b/tests/phpunit/includes/watcheditem/WatchedItemQueryServiceUnitTest.php index b6cf2396e1..0b1d0132fb 100644 --- a/tests/phpunit/includes/watcheditem/WatchedItemQueryServiceUnitTest.php +++ b/tests/phpunit/includes/watcheditem/WatchedItemQueryServiceUnitTest.php @@ -1,5 +1,7 @@ getMockBuilder( ActorMigration::class ) + ->disableOriginalConstructor() + ->getMock(); + $mockStore->expects( $this->any() ) + ->method( 'getJoin' ) + ->willReturn( [ + 'tables' => [ 'actormigration' => 'table' ], + 'fields' => [ + 'rc_user' => 'actormigration_user', + 'rc_user_text' => 'actormigration_user_text', + 'rc_actor' => 'actormigration_actor', + ], + 'joins' => [ 'actormigration' => 'join' ], + ] ); + $mockStore->expects( $this->any() ) + ->method( 'getWhere' ) + ->willReturn( [ + 'tables' => [ 'actormigration' => 'table' ], + 'conds' => 'actormigration_conds', + 'joins' => [ 'actormigration' => 'join' ], + ] ); + $mockStore->expects( $this->any() ) + ->method( 'isAnon' ) + ->willReturn( 'actormigration is anon' ); + $mockStore->expects( $this->any() ) + ->method( 'isNotAnon' ) + ->willReturn( 'actormigration is not anon' ); + return $mockStore; + } + /** * @param PHPUnit_Framework_MockObject_MockObject|Database $mockDb * @return WatchedItemQueryService @@ -37,17 +71,17 @@ class WatchedItemQueryServiceUnitTest extends MediaWikiTestCase { private function newService( $mockDb ) { return new WatchedItemQueryService( $this->getMockLoadBalancer( $mockDb ), - $this->getMockCommentStore() + $this->getMockCommentStore(), + $this->getMockActorMigration(), + $this->getMockWatchedItemStore() ); } /** - * @return PHPUnit_Framework_MockObject_MockObject|Database + * @return PHPUnit_Framework_MockObject_MockObject|IDatabase */ private function getMockDb() { - $mock = $this->getMockBuilder( Database::class ) - ->disableOriginalConstructor() - ->getMock(); + $mock = $this->createMock( IDatabase::class ); $mock->expects( $this->any() ) ->method( 'makeList' ) @@ -57,10 +91,17 @@ class WatchedItemQueryServiceUnitTest extends MediaWikiTestCase { ) ->will( $this->returnCallback( function ( $a, $conj ) { $sqlConj = $conj === LIST_AND ? ' AND ' : ' OR '; - return implode( $sqlConj, array_map( function ( $s ) { - return '(' . $s . ')'; - }, $a - ) ); + $conds = []; + foreach ( $a as $k => $v ) { + if ( is_int( $k ) ) { + $conds[] = "($v)"; + } elseif ( is_array( $v ) ) { + $conds[] = "($k IN ('" . implode( "','", $v ) . "'))"; + } else { + $conds[] = "($k = '$v')"; + } + } + return implode( $sqlConj, $conds ); } ) ); $mock->expects( $this->any() ) @@ -83,7 +124,7 @@ class WatchedItemQueryServiceUnitTest extends MediaWikiTestCase { } /** - * @param PHPUnit_Framework_MockObject_MockObject|Database $mockDb + * @param PHPUnit_Framework_MockObject_MockObject|IDatabase $mockDb * @return PHPUnit_Framework_MockObject_MockObject|LoadBalancer */ private function getMockLoadBalancer( $mockDb ) { @@ -97,36 +138,49 @@ class WatchedItemQueryServiceUnitTest extends MediaWikiTestCase { return $mock; } + /** + * @return PHPUnit_Framework_MockObject_MockObject|WatchedItemStore + */ + private function getMockWatchedItemStore() { + $mock = $this->getMockBuilder( WatchedItemStore::class ) + ->disableOriginalConstructor() + ->getMock(); + $mock->expects( $this->any() ) + ->method( 'getLatestNotificationTimestamp' ) + ->will( $this->returnCallback( function ( $timestamp ) { + return $timestamp; + } ) ); + return $mock; + } + /** * @param int $id + * @param string[] $extraMethods Extra methods that are expected might be called * @return PHPUnit_Framework_MockObject_MockObject|User */ - private function getMockNonAnonUserWithId( $id ) { + private function getMockNonAnonUserWithId( $id, array $extraMethods = [] ) { $mock = $this->getMockBuilder( User::class )->getMock(); - $mock->expects( $this->any() ) - ->method( 'isAnon' ) - ->will( $this->returnValue( false ) ); - $mock->expects( $this->any() ) - ->method( 'getId' ) - ->will( $this->returnValue( $id ) ); + $mock->method( 'isRegistered' )->willReturn( true ); + $mock->method( 'getId' )->willReturn( $id ); + $methods = array_merge( [ + 'isRegistered', + 'getId', + ], $extraMethods ); + $mock->expects( $this->never() )->method( $this->anythingBut( ...$methods ) ); return $mock; } /** * @param int $id + * @param string[] $extraMethods Extra methods that are expected might be called * @return PHPUnit_Framework_MockObject_MockObject|User */ - private function getMockUnrestrictedNonAnonUserWithId( $id ) { - $mock = $this->getMockNonAnonUserWithId( $id ); - $mock->expects( $this->any() ) - ->method( 'isAllowed' ) - ->will( $this->returnValue( true ) ); - $mock->expects( $this->any() ) - ->method( 'isAllowedAny' ) - ->will( $this->returnValue( true ) ); - $mock->expects( $this->any() ) - ->method( 'useRCPatrol' ) - ->will( $this->returnValue( true ) ); + private function getMockUnrestrictedNonAnonUserWithId( $id, array $extraMethods = [] ) { + $mock = $this->getMockNonAnonUserWithId( $id, + array_merge( [ 'isAllowed', 'isAllowedAny', 'useRCPatrol' ], $extraMethods ) ); + $mock->method( 'isAllowed' )->willReturn( true ); + $mock->method( 'isAllowedAny' )->willReturn( true ); + $mock->method( 'useRCPatrol' )->willReturn( true ); return $mock; } @@ -136,19 +190,19 @@ class WatchedItemQueryServiceUnitTest extends MediaWikiTestCase { * @return PHPUnit_Framework_MockObject_MockObject|User */ private function getMockNonAnonUserWithIdAndRestrictedPermissions( $id, $notAllowedAction ) { - $mock = $this->getMockNonAnonUserWithId( $id ); + $mock = $this->getMockNonAnonUserWithId( $id, + [ 'isAllowed', 'isAllowedAny', 'useRCPatrol', 'useNPPatrol' ] ); - $mock->expects( $this->any() ) - ->method( 'isAllowed' ) + $mock->method( 'isAllowed' ) ->will( $this->returnCallback( function ( $action ) use ( $notAllowedAction ) { return $action !== $notAllowedAction; } ) ); - $mock->expects( $this->any() ) - ->method( 'isAllowedAny' ) - ->will( $this->returnCallback( function () use ( $notAllowedAction ) { - $actions = func_get_args(); + $mock->method( 'isAllowedAny' ) + ->will( $this->returnCallback( function ( ...$actions ) use ( $notAllowedAction ) { return !in_array( $notAllowedAction, $actions ); } ) ); + $mock->method( 'useRCPatrol' )->willReturn( false ); + $mock->method( 'useNPPatrol' )->willReturn( false ); return $mock; } @@ -158,7 +212,8 @@ class WatchedItemQueryServiceUnitTest extends MediaWikiTestCase { * @return PHPUnit_Framework_MockObject_MockObject|User */ private function getMockNonAnonUserWithIdAndNoPatrolRights( $id ) { - $mock = $this->getMockNonAnonUserWithId( $id ); + $mock = $this->getMockNonAnonUserWithId( $id, + [ 'isAllowed', 'isAllowedAny', 'useRCPatrol', 'useNPPatrol' ] ); $mock->expects( $this->any() ) ->method( 'isAllowed' ) @@ -177,14 +232,6 @@ class WatchedItemQueryServiceUnitTest extends MediaWikiTestCase { return $mock; } - private function getMockAnonUser() { - $mock = $this->getMockBuilder( User::class )->getMock(); - $mock->expects( $this->any() ) - ->method( 'isAnon' ) - ->will( $this->returnValue( true ) ); - return $mock; - } - private function getFakeRow( array $rowValues ) { $fakeRow = new stdClass(); foreach ( $rowValues as $valueName => $value ) { @@ -221,7 +268,7 @@ class WatchedItemQueryServiceUnitTest extends MediaWikiTestCase { ], [ 'watchlist' => [ - 'INNER JOIN', + 'JOIN', [ 'wl_namespace=rc_namespace', 'wl_title=rc_title' @@ -344,7 +391,7 @@ class WatchedItemQueryServiceUnitTest extends MediaWikiTestCase { ], [ 'watchlist' => [ - 'INNER JOIN', + 'JOIN', [ 'wl_namespace=rc_namespace', 'wl_title=rc_title' @@ -490,20 +537,20 @@ class WatchedItemQueryServiceUnitTest extends MediaWikiTestCase { [ [ 'includeFields' => [ WatchedItemQueryService::INCLUDE_USER ] ], null, - [], - [ 'rc_user_text' ], - [], + [ 'actormigration' => 'table' ], + [ 'rc_user_text' => 'actormigration_user_text' ], [], [], + [ 'actormigration' => 'join' ], ], [ [ 'includeFields' => [ WatchedItemQueryService::INCLUDE_USER_ID ] ], null, - [], - [ 'rc_user' ], - [], + [ 'actormigration' => 'table' ], + [ 'rc_user' => 'actormigration_user' ], [], [], + [ 'actormigration' => 'join' ], ], [ [ 'includeFields' => [ WatchedItemQueryService::INCLUDE_COMMENT ] ], @@ -705,20 +752,20 @@ class WatchedItemQueryServiceUnitTest extends MediaWikiTestCase { [ [ 'filters' => [ WatchedItemQueryService::FILTER_ANON ] ], null, + [ 'actormigration' => 'table' ], [], + [ 'actormigration is anon' ], [], - [ 'rc_user = 0' ], - [], - [], + [ 'actormigration' => 'join' ], ], [ [ 'filters' => [ WatchedItemQueryService::FILTER_NOT_ANON ] ], null, + [ 'actormigration' => 'table' ], [], + [ 'actormigration is not anon' ], [], - [ 'rc_user != 0' ], - [], - [], + [ 'actormigration' => 'join' ], ], [ [ 'filters' => [ WatchedItemQueryService::FILTER_PATROLLED ] ], @@ -734,7 +781,7 @@ class WatchedItemQueryServiceUnitTest extends MediaWikiTestCase { null, [], [], - [ 'rc_patrolled = 0' ], + [ 'rc_patrolled' => 0 ], [], [], ], @@ -759,20 +806,20 @@ class WatchedItemQueryServiceUnitTest extends MediaWikiTestCase { [ [ 'onlyByUser' => 'SomeOtherUser' ], null, + [ 'actormigration' => 'table' ], [], + [ 'actormigration_conds' ], [], - [ 'rc_user_text' => 'SomeOtherUser' ], - [], - [], + [ 'actormigration' => 'join' ], ], [ [ 'notByUser' => 'SomeOtherUser' ], null, + [ 'actormigration' => 'table' ], [], + [ 'NOT(actormigration_conds)' ], [], - [ "rc_user_text != 'SomeOtherUser'" ], - [], - [], + [ 'actormigration' => 'join' ], ], [ [ 'dir' => WatchedItemQueryService::DIR_OLDER ], @@ -846,7 +893,7 @@ class WatchedItemQueryServiceUnitTest extends MediaWikiTestCase { $expectedJoinConds = array_merge( [ 'watchlist' => [ - 'INNER JOIN', + 'JOIN', [ 'wl_namespace=rc_namespace', 'wl_title=rc_title' @@ -984,62 +1031,74 @@ class WatchedItemQueryServiceUnitTest extends MediaWikiTestCase { [ [], 'deletedhistory', + [], [ '(rc_type != ' . RC_LOG . ') OR ((rc_deleted & ' . LogPage::DELETED_ACTION . ') != ' . LogPage::DELETED_ACTION . ')' ], + [], ], [ [], 'suppressrevision', + [], [ '(rc_type != ' . RC_LOG . ') OR (' . '(rc_deleted & ' . ( LogPage::DELETED_ACTION | LogPage::DELETED_RESTRICTED ) . ') != ' . ( LogPage::DELETED_ACTION | LogPage::DELETED_RESTRICTED ) . ')' ], + [], ], [ [], 'viewsuppressed', + [], [ '(rc_type != ' . RC_LOG . ') OR (' . '(rc_deleted & ' . ( LogPage::DELETED_ACTION | LogPage::DELETED_RESTRICTED ) . ') != ' . ( LogPage::DELETED_ACTION | LogPage::DELETED_RESTRICTED ) . ')' ], + [], ], [ [ 'onlyByUser' => 'SomeOtherUser' ], 'deletedhistory', + [ 'actormigration' => 'table' ], [ - 'rc_user_text' => 'SomeOtherUser', + 'actormigration_conds', '(rc_deleted & ' . Revision::DELETED_USER . ') != ' . Revision::DELETED_USER, '(rc_type != ' . RC_LOG . ') OR ((rc_deleted & ' . LogPage::DELETED_ACTION . ') != ' . LogPage::DELETED_ACTION . ')' ], + [ 'actormigration' => 'join' ], ], [ [ 'onlyByUser' => 'SomeOtherUser' ], 'suppressrevision', + [ 'actormigration' => 'table' ], [ - 'rc_user_text' => 'SomeOtherUser', + 'actormigration_conds', '(rc_deleted & ' . ( Revision::DELETED_USER | Revision::DELETED_RESTRICTED ) . ') != ' . ( Revision::DELETED_USER | Revision::DELETED_RESTRICTED ), '(rc_type != ' . RC_LOG . ') OR (' . '(rc_deleted & ' . ( LogPage::DELETED_ACTION | LogPage::DELETED_RESTRICTED ) . ') != ' . ( LogPage::DELETED_ACTION | LogPage::DELETED_RESTRICTED ) . ')' ], + [ 'actormigration' => 'join' ], ], [ [ 'onlyByUser' => 'SomeOtherUser' ], 'viewsuppressed', + [ 'actormigration' => 'table' ], [ - 'rc_user_text' => 'SomeOtherUser', + 'actormigration_conds', '(rc_deleted & ' . ( Revision::DELETED_USER | Revision::DELETED_RESTRICTED ) . ') != ' . ( Revision::DELETED_USER | Revision::DELETED_RESTRICTED ), '(rc_type != ' . RC_LOG . ') OR (' . '(rc_deleted & ' . ( LogPage::DELETED_ACTION | LogPage::DELETED_RESTRICTED ) . ') != ' . ( LogPage::DELETED_ACTION | LogPage::DELETED_RESTRICTED ) . ')' ], + [ 'actormigration' => 'join' ], ], ]; } @@ -1050,7 +1109,9 @@ class WatchedItemQueryServiceUnitTest extends MediaWikiTestCase { public function testGetWatchedItemsWithRecentChangeInfo_userPermissionRelatedExtraChecks( array $options, $notAllowedAction, - array $expectedExtraConds + array $expectedExtraTables, + array $expectedExtraConds, + array $expectedExtraJoins ) { $commonConds = [ 'wl_user' => 1, '(rc_this_oldid=page_latest) OR (rc_type=3)' ]; $conds = array_merge( $commonConds, $expectedExtraConds ); @@ -1059,12 +1120,15 @@ class WatchedItemQueryServiceUnitTest extends MediaWikiTestCase { $mockDb->expects( $this->once() ) ->method( 'select' ) ->with( - [ 'recentchanges', 'watchlist', 'page' ], + array_merge( [ 'recentchanges', 'watchlist', 'page' ], $expectedExtraTables ), $this->isType( 'array' ), $conds, $this->isType( 'string' ), $this->isType( 'array' ), - $this->isType( 'array' ) + array_merge( [ + 'watchlist' => [ 'JOIN', [ 'wl_namespace=rc_namespace', 'wl_title=rc_title' ] ], + 'page' => [ 'LEFT JOIN', 'rc_cur_id=page_id' ], + ], $expectedExtraJoins ) ) ->will( $this->returnValue( [] ) ); @@ -1100,7 +1164,7 @@ class WatchedItemQueryServiceUnitTest extends MediaWikiTestCase { [], [ 'watchlist' => [ - 'INNER JOIN', + 'JOIN', [ 'wl_namespace=rc_namespace', 'wl_title=rc_title' @@ -1223,7 +1287,7 @@ class WatchedItemQueryServiceUnitTest extends MediaWikiTestCase { [], [ 'watchlist' => [ - 'INNER JOIN', + 'JOIN', [ 'wl_namespace=rc_namespace', 'wl_title=rc_title' @@ -1269,7 +1333,7 @@ class WatchedItemQueryServiceUnitTest extends MediaWikiTestCase { [], [ 'watchlist' => [ - 'INNER JOIN', + 'JOIN', [ 'wl_namespace=rc_namespace', 'wl_title=rc_title' @@ -1309,7 +1373,7 @@ class WatchedItemQueryServiceUnitTest extends MediaWikiTestCase { $queryService = $this->newService( $mockDb ); $user = $this->getMockUnrestrictedNonAnonUserWithId( 1 ); - $otherUser = $this->getMockUnrestrictedNonAnonUserWithId( 2 ); + $otherUser = $this->getMockUnrestrictedNonAnonUserWithId( 2, [ 'getOption' ] ); $otherUser->expects( $this->once() ) ->method( 'getOption' ) ->with( 'watchlisttoken' ) @@ -1340,7 +1404,7 @@ class WatchedItemQueryServiceUnitTest extends MediaWikiTestCase { $queryService = $this->newService( $mockDb ); $user = $this->getMockUnrestrictedNonAnonUserWithId( 1 ); - $otherUser = $this->getMockUnrestrictedNonAnonUserWithId( 2 ); + $otherUser = $this->getMockUnrestrictedNonAnonUserWithId( 2, [ 'getOption' ] ); $otherUser->expects( $this->once() ) ->method( 'getOption' ) ->with( 'watchlisttoken' ) @@ -1640,7 +1704,8 @@ class WatchedItemQueryServiceUnitTest extends MediaWikiTestCase { $queryService = $this->newService( $mockDb ); - $items = $queryService->getWatchedItemsForUser( $this->getMockAnonUser() ); + $items = $queryService->getWatchedItemsForUser( + new UserIdentityValue( 0, 'AnonUser', 0 ) ); $this->assertEmpty( $items ); }