diff options
Diffstat (limited to 'Echo/tests/phpunit')
31 files changed, 535 insertions, 242 deletions
diff --git a/Echo/tests/phpunit/AttributeManagerTest.php b/Echo/tests/phpunit/AttributeManagerTest.php index f9b0c939..42ccb992 100644 --- a/Echo/tests/phpunit/AttributeManagerTest.php +++ b/Echo/tests/phpunit/AttributeManagerTest.php @@ -1,5 +1,8 @@ <?php +/** + * @covers EchoAttributeManager + */ class EchoAttributeManagerTest extends MediaWikiTestCase { public function testNewFromGlobalVars() { @@ -55,7 +58,7 @@ class EchoAttributeManagerTest extends MediaWikiTestCase { * @dataProvider getUserLocatorsProvider */ public function testGetUserLocators( $message, $expect, $type, $notifications ) { - $manager = new EchoAttributeManager( $notifications, [], [], [], [] ); + $manager = new EchoAttributeManager( $notifications, [], [], [] ); $result = $manager->getUserCallable( $type, EchoAttributeManager::ATTR_LOCATORS ); $this->assertEquals( $expect, $result, $message ); @@ -72,7 +75,7 @@ class EchoAttributeManagerTest extends MediaWikiTestCase { 'priority' => 10 ] ]; - $manager = new EchoAttributeManager( $notif, $category, [], [], [] ); + $manager = new EchoAttributeManager( $notif, $category, [], [] ); $this->assertTrue( $manager->getCategoryEligibility( $this->mockUser(), 'category_one' ) ); $category = [ 'category_one' => [ @@ -82,7 +85,7 @@ class EchoAttributeManagerTest extends MediaWikiTestCase { ] ] ]; - $manager = new EchoAttributeManager( $notif, $category, [], [], [] ); + $manager = new EchoAttributeManager( $notif, $category, [], [] ); $this->assertFalse( $manager->getCategoryEligibility( $this->mockUser(), 'category_one' ) ); } @@ -97,10 +100,10 @@ class EchoAttributeManagerTest extends MediaWikiTestCase { 'priority' => 10 ] ]; - $manager = new EchoAttributeManager( $notif, $category, [], [], [] ); + $manager = new EchoAttributeManager( $notif, $category, [], [] ); $this->assertEquals( $manager->getNotificationCategory( 'event_one' ), 'category_one' ); - $manager = new EchoAttributeManager( $notif, [], [], [], [] ); + $manager = new EchoAttributeManager( $notif, [], [], [] ); $this->assertEquals( $manager->getNotificationCategory( 'event_one' ), 'other' ); $notif = [ @@ -113,7 +116,7 @@ class EchoAttributeManagerTest extends MediaWikiTestCase { 'priority' => 10 ] ]; - $manager = new EchoAttributeManager( $notif, $category, [], [], [] ); + $manager = new EchoAttributeManager( $notif, $category, [], [] ); $this->assertEquals( $manager->getNotificationCategory( 'event_one' ), 'other' ); } @@ -135,7 +138,7 @@ class EchoAttributeManagerTest extends MediaWikiTestCase { ], 'category_four' => [] ]; - $manager = new EchoAttributeManager( $notif, $category, [], [], [] ); + $manager = new EchoAttributeManager( $notif, $category, [], [] ); $this->assertEquals( 6, $manager->getCategoryPriority( 'category_one' ) ); $this->assertEquals( 10, $manager->getCategoryPriority( 'category_two' ) ); $this->assertEquals( 10, $manager->getCategoryPriority( 'category_three' ) ); @@ -169,7 +172,7 @@ class EchoAttributeManagerTest extends MediaWikiTestCase { ], 'category_four' => [] ]; - $manager = new EchoAttributeManager( $notif, $category, [], [], [] ); + $manager = new EchoAttributeManager( $notif, $category, [], [] ); $this->assertEquals( 6, $manager->getNotificationPriority( 'event_one' ) ); $this->assertEquals( 10, $manager->getNotificationPriority( 'event_two' ) ); $this->assertEquals( 10, $manager->getNotificationPriority( 'event_three' ) ); @@ -221,7 +224,7 @@ class EchoAttributeManagerTest extends MediaWikiTestCase { * @dataProvider getEventsForSectionProvider */ public function testGetEventsForSection( $expected, $notificationTypes, $section, $message ) { - $am = new EchoAttributeManager( $notificationTypes, [], [], [], [] ); + $am = new EchoAttributeManager( $notificationTypes, [], [], [] ); $actual = $am->getEventsForSection( $section ); $this->assertEquals( $expected, $actual, $message ); } @@ -255,8 +258,9 @@ class EchoAttributeManagerTest extends MediaWikiTestCase { 'priority' => 10, ], ]; - $manager = new EchoAttributeManager( $notif, $category, [], [], [] ); - $this->assertEquals( $manager->getUserEnabledEvents( $this->mockUser(), 'web' ), [ 'event_two', 'event_three' ] ); + $manager = new EchoAttributeManager( $notif, $category, [], [] ); + $this->assertEquals( $manager->getUserEnabledEvents( $this->mockUser(), 'web' ), + [ 'event_two', 'event_three' ] ); } public function testGetUserEnabledEventsbySections() { @@ -287,7 +291,7 @@ class EchoAttributeManagerTest extends MediaWikiTestCase { 'priority' => 10 ], ]; - $manager = new EchoAttributeManager( $notif, $category, [], [], [] ); + $manager = new EchoAttributeManager( $notif, $category, [], [] ); $expected = [ 'event_one', 'event_three', 'event_four' ]; $actual = $manager->getUserEnabledEventsBySections( $this->mockUser(), 'web', [ 'alert' ] ); sort( $expected ); @@ -301,7 +305,8 @@ class EchoAttributeManagerTest extends MediaWikiTestCase { $this->assertEquals( $actual, $expected ); $expected = [ 'event_one', 'event_two', 'event_three', 'event_four' ]; - $actual = $manager->getUserEnabledEventsBySections( $this->mockUser(), 'web', [ 'message', 'alert' ] ); + $actual = $manager->getUserEnabledEventsBySections( $this->mockUser(), 'web', + [ 'message', 'alert' ] ); sort( $expected ); sort( $actual ); $this->assertEquals( $actual, $expected ); @@ -352,8 +357,13 @@ class EchoAttributeManagerTest extends MediaWikiTestCase { /** * @dataProvider getEventsByCategoryProvider */ - public function testGetEventsByCategory( $message, $expectedMapping, $categories, $notifications ) { - $am = new EchoAttributeManager( $notifications, $categories, [], [], [] ); + public function testGetEventsByCategory( + $message, + $expectedMapping, + $categories, + $notifications + ) { + $am = new EchoAttributeManager( $notifications, $categories, [], [] ); $actualMapping = $am->getEventsByCategory(); $this->assertEquals( $expectedMapping, $actualMapping, $message ); } @@ -398,8 +408,16 @@ class EchoAttributeManagerTest extends MediaWikiTestCase { /** @dataProvider isNotifyTypeAvailableForCategoryProvider */ - public function testIsNotifyTypeAvailableForCategory( $message, $expected, $categoryName, $notifyType, $defaultNotifyTypeAvailability, $notifyTypeAvailabilityByCategory ) { - $am = new EchoAttributeManager( [], [], $defaultNotifyTypeAvailability, $notifyTypeAvailabilityByCategory, [] ); + public function testIsNotifyTypeAvailableForCategory( + $message, + $expected, + $categoryName, + $notifyType, + $defaultNotifyTypeAvailability, + $notifyTypeAvailabilityByCategory + ) { + $am = new EchoAttributeManager( [], [], $defaultNotifyTypeAvailability, + $notifyTypeAvailabilityByCategory ); $actual = $am->isNotifyTypeAvailableForCategory( $categoryName, $notifyType ); $this->assertEquals( $expected, $actual, $message ); } @@ -445,8 +463,14 @@ class EchoAttributeManagerTest extends MediaWikiTestCase { /** * @dataProvider isNotifyTypeDismissableForCategoryProvider */ - public function testIsNotifyTypeDismissableForCategory( $message, $expected, $categories, $categoryName, $notifyType ) { - $am = new EchoAttributeManager( [], $categories, [], [], [] ); + public function testIsNotifyTypeDismissableForCategory( + $message, + $expected, + $categories, + $categoryName, + $notifyType + ) { + $am = new EchoAttributeManager( [], $categories, [], [] ); $actual = $am->isNotifyTypeDismissableForCategory( $categoryName, $notifyType ); $this->assertEquals( $expected, $actual, $message ); } diff --git a/Echo/tests/phpunit/BundlerTest.php b/Echo/tests/phpunit/BundlerTest.php index bd2f4499..a4a2e258 100644 --- a/Echo/tests/phpunit/BundlerTest.php +++ b/Echo/tests/phpunit/BundlerTest.php @@ -1,5 +1,8 @@ <?php +/** + * @covers Bundler + */ class BundlerTest extends MediaWikiTestCase { public function testBundle() { diff --git a/Echo/tests/phpunit/ContainmentSetTest.php b/Echo/tests/phpunit/ContainmentSetTest.php index 077e235b..1f538291 100644 --- a/Echo/tests/phpunit/ContainmentSetTest.php +++ b/Echo/tests/phpunit/ContainmentSetTest.php @@ -1,7 +1,9 @@ <?php /** + * @covers EchoContainmentSet * @group Echo + * @group Database */ class ContainmentSetTest extends MediaWikiTestCase { @@ -15,6 +17,9 @@ class ContainmentSetTest extends MediaWikiTestCase { $list->addArray( [ 'whammo' ] ); $this->assertTrue( $list->contains( 'whammo' ) ); + + $list->addArray( [ 0 ] ); + $this->assertFalse( $list->contains( 'baz' ) ); } public function testCachedListInnerListIsOnlyCalledOnce() { @@ -46,7 +51,7 @@ class ContainmentSetTest extends MediaWikiTestCase { } /** - * @Database + * @group Database */ public function testOnWikiList() { $this->editPage( 'User:Foo/Bar-baz', "abc\ndef\r\nghi\n\n\n" ); diff --git a/Echo/tests/phpunit/DiffParserTest.php b/Echo/tests/phpunit/DiffParserTest.php index 14dc8a7d..aeecef67 100644 --- a/Echo/tests/phpunit/DiffParserTest.php +++ b/Echo/tests/phpunit/DiffParserTest.php @@ -1,6 +1,7 @@ <?php /** + * @covers EchoDiffParser * @group Echo */ class EchoDiffParserTest extends MediaWikiTestCase { @@ -58,7 +59,7 @@ class EchoDiffParserTest extends MediaWikiTestCase { ], [ - 'Adding content seperated by no change must generate multiple changes', + 'Adding content separated by no change must generate multiple changes', // Expected change set [ self::mockAction( 'add', 'b1', 3 ), diff --git a/Echo/tests/phpunit/DiscussionParserTest.php b/Echo/tests/phpunit/DiscussionParserTest.php index 35da3fae..391ff078 100644 --- a/Echo/tests/phpunit/DiscussionParserTest.php +++ b/Echo/tests/phpunit/DiscussionParserTest.php @@ -1,16 +1,17 @@ <?php -use MediaWiki\MediaWikiServices; -use Wikimedia\ScopedCallback; +// phpcs:disable Generic.Files.LineLength -- Long html test examples + use Wikimedia\TestingAccessWrapper; /** + * @covers EchoDiscussionParser * @group Echo * @group Database */ class EchoDiscussionParserTest extends MediaWikiTestCase { /** - * @var array + * @var string[] */ protected $tablesUsed = [ 'user', 'revision', 'ip_changes', 'text', 'page' ]; @@ -19,7 +20,7 @@ class EchoDiscussionParserTest extends MediaWikiTestCase { * Can be setup one by one using the setupTestUser() method * Or all at once using the setupAllTestUsers() method * - * @var array [username => [user preference => preference value]] + * @var array[] [username => [user preference => preference value]] */ protected $testUsers = [ 'Werdna' => [ @@ -338,6 +339,23 @@ class EchoDiscussionParserTest extends MediaWikiTestCase { 'title' => 'MultipleSignatureMentions', 'expected' => [], ], + [ + 'new' => 1234, + 'old' => 123, + 'username' => 'Admin', + 'lang' => 'en', + 'pages' => [], + 'title' => 'Pings in summary', + 'expected' => [ + [ + 'type' => 'mention-summary', + 'agent' => 'Admin', + 'section-title' => null, + ] + ], + 'precondition' => '', + 'summary' => 'Hey [[User:Werdna|Werdna]] and [[User:Jorm]], [[User:Admin]] here', + ], ]; } @@ -345,7 +363,8 @@ class EchoDiscussionParserTest extends MediaWikiTestCase { * @dataProvider generateEventsForRevisionData */ public function testGenerateEventsForRevision( - $newId, $oldId, $username, $lang, $pages, $title, $expected, $precondition = '' + $newId, $oldId, $username, $lang, $pages, $title, $expected, $precondition = '', + $summary = '' ) { if ( $precondition !== '' ) { $result = $this->$precondition(); @@ -359,7 +378,7 @@ class EchoDiscussionParserTest extends MediaWikiTestCase { $this->setupAllTestUsers(); $revision = $this->setupTestRevisionsForEventGeneration( - $newId, $oldId, $username, $lang, $pages, $title + $newId, $oldId, $username, $lang, $pages, $title, $summary ); $events = []; $this->setupEventCallbackForEventGeneration( @@ -373,10 +392,14 @@ class EchoDiscussionParserTest extends MediaWikiTestCase { } ); - // disable mention failure and success notifications - $this->setMwGlobals( 'wgEchoMentionStatusNotifications', false ); + $this->setMwGlobals( [ + // disable mention failure and success notifications + 'wgEchoMentionStatusNotifications' => false, + // enable pings from summary + 'wgEchoMaxMentionsInEditSummary' => 5, + ] ); - EchoDiscussionParser::generateEventsForRevision( $revision ); + EchoDiscussionParser::generateEventsForRevision( $revision, false ); $this->assertEquals( $expected, $events ); } @@ -718,7 +741,7 @@ class EchoDiscussionParserTest extends MediaWikiTestCase { // enable multiple sections mentions $this->setMwGlobals( 'wgEchoMentionsOnMultipleSectionEdits', true ); - EchoDiscussionParser::generateEventsForRevision( $revision ); + EchoDiscussionParser::generateEventsForRevision( $revision, false ); $this->assertEquals( $expected, $events ); } @@ -920,39 +943,22 @@ TEXT 'wgEchoMaxMentionsCount' => 5 ] ); - EchoDiscussionParser::generateEventsForRevision( $revision ); + EchoDiscussionParser::generateEventsForRevision( $revision, false ); $this->assertEquals( $expected, $events ); } - private function setupTestRevisionsForEventGeneration( $newId, $oldId, $username, $lang, $pages, $title ) { - $langObj = Language::factory( $lang ); + private function setupTestRevisionsForEventGeneration( $newId, $oldId, $username, $lang, $pages, + $title, $summary = '' + ) { + // Content language is used by the code that interprets the namespace part of titles + // (Title::getTitleParser), so should be the fake language ;) + $this->setContentLang( $lang ); $this->setMwGlobals( [ - // this global is used by the code that interprets the namespace part of - // titles (Title::getTitleParser), so should be the fake language ;) - 'wgContLang' => $langObj, // this one allows Mediawiki:xyz pages to be set as messages 'wgUseDatabaseMessages' => true ] ); - - // Since we reset the $wgContLang global, reset the TitleParser service - $services = MediaWikiServices::getInstance(); - if ( is_callable( [ $services, 'getTitleParser' ] ) ) { - // TODO: All of this should use $this->setService() - $services->resetServiceForTesting( 'TitleParser' ); - $services->redefineService( 'TitleParser', function () use ( $langObj ) { - global $wgLocalInterwikis; - return new MediaWikiTitleCodec( - $langObj, - new GenderCache(), - $wgLocalInterwikis - ); - } ); - // Cleanup - $lock = new ScopedCallback( function () use ( $services ) { - $services->resetServiceForTesting( 'TitleParser' ); - } ); - } + $this->overrideMwServices(); // pages to be created: templates may be used to ping users (e.g. // {{u|...}}) but if we don't have that template, it just won't work! @@ -988,6 +994,7 @@ TEXT 'parent_id' => $oldId, 'text' => $newText, 'title' => $title, + 'comment' => $summary, ]; $revision = Revision::newFromRow( $row ); @@ -1501,9 +1508,13 @@ TEXT ]; } - public static function getExemplarTimestamp() { - $title = Title::newMainPage(); - $user = User::newFromName( 'Test' ); + public function getExemplarTimestamp() { + $title = $this->getMockBuilder( Title::class ) + ->getMock(); + + $user = $this->getMockBuilder( User::class ) + ->getMock(); + $options = new ParserOptions; global $wgParser; @@ -1795,7 +1806,7 @@ TEXT } protected function isParserFunctionsInstalled() { - if ( class_exists( 'ExtParserFunctions' ) ) { + if ( ExtensionRegistry::getInstance()->isLoaded( 'ParserFunctions' ) ) { return true; } else { return "ParserFunctions not enabled"; diff --git a/Echo/tests/phpunit/EchoDbFactoryTest.php b/Echo/tests/phpunit/EchoDbFactoryTest.php index 18ac1170..337c92d3 100644 --- a/Echo/tests/phpunit/EchoDbFactoryTest.php +++ b/Echo/tests/phpunit/EchoDbFactoryTest.php @@ -1,5 +1,11 @@ <?php +use Wikimedia\Rdbms\IDatabase; +use Wikimedia\Rdbms\ILoadBalancer; + +/** + * @covers MWEchoDbFactory + */ class MWEchoDbFactoryTest extends MediaWikiTestCase { public function testNewFromDefault() { @@ -13,8 +19,8 @@ class MWEchoDbFactoryTest extends MediaWikiTestCase { * @depends testNewFromDefault */ public function testGetEchoDb( MWEchoDbFactory $db ) { - $this->assertInstanceOf( 'DatabaseBase', $db->getEchoDb( DB_MASTER ) ); - $this->assertInstanceOf( 'DatabaseBase', $db->getEchoDb( DB_SLAVE ) ); + $this->assertInstanceOf( IDatabase::class, $db->getEchoDb( DB_MASTER ) ); + $this->assertInstanceOf( IDatabase::class, $db->getEchoDb( DB_REPLICA ) ); } /** @@ -24,7 +30,7 @@ class MWEchoDbFactoryTest extends MediaWikiTestCase { $reflection = new ReflectionClass( 'MWEchoDbFactory' ); $method = $reflection->getMethod( 'getLB' ); $method->setAccessible( true ); - $this->assertInstanceOf( 'LoadBalancer', $method->invoke( $db ) ); + $this->assertInstanceOf( ILoadBalancer::class, $method->invoke( $db ) ); } } diff --git a/Echo/tests/phpunit/EchoHooksTest.php b/Echo/tests/phpunit/EchoHooksTest.php new file mode 100644 index 00000000..d1f2ac56 --- /dev/null +++ b/Echo/tests/phpunit/EchoHooksTest.php @@ -0,0 +1,53 @@ +<?php + +class EchoHooksTest extends MediaWikiTestCase { + /** + * @covers \EchoHooks::onUserGetDefaultOptions() + */ + public function testOnUserGetDefaultOptions() { + $this->setMwGlobals( [ + 'wgEchoNotificationCategories' => [ + 'emailuser' => [ + 'priority' => 9, + 'tooltip' => 'echo-pref-tooltip-emailuser', + ], + 'mention' => [ + 'priority' => 4, + 'tooltip' => 'echo-pref-tooltip-mention', + ], + 'system' => [ + 'priority' => 9, + 'no-dismiss' => [ + 'all' + ], + ], + 'some-custom-category' => [ + 'priority' => 9001, + ], + ], + 'wgAllowHTMLEmail' => true, + ] ); + + $defaults = [ + 'something' => 'unrelated', + // T174220: don't overwrite defaults set elsewhere + 'echo-subscriptions-web-mention' => false, + ]; + EchoHooks::onUserGetDefaultOptions( $defaults ); + self::assertEquals( + [ + 'something' => 'unrelated', + 'echo-email-format' => 'html', + 'echo-subscriptions-email-mention' => false, + 'echo-subscriptions-web-mention' => false, + 'echo-subscriptions-email-emailuser' => false, + 'echo-subscriptions-web-emailuser' => true, + 'echo-subscriptions-email-system' => true, + 'echo-subscriptions-web-system' => true, + 'echo-subscriptions-email-some-custom-category' => false, + 'echo-subscriptions-web-some-custom-category' => true, + ], + $defaults + ); + } +} diff --git a/Echo/tests/phpunit/EchoSummaryParserTest.php b/Echo/tests/phpunit/EchoSummaryParserTest.php new file mode 100644 index 00000000..357036fc --- /dev/null +++ b/Echo/tests/phpunit/EchoSummaryParserTest.php @@ -0,0 +1,68 @@ +<?php + +/** + * @group Echo + */ +class EchoSummaryParserTest extends MediaWikiTestCase { + private $existingUsers = [ + 'Werdna', + 'Jorm', + 'Jim Carter', + ]; + /** + * @covers EchoSummaryParser::parse + * @dataProvider provideParse + * + * @param string $summary + * @param string[] $expectedUsers + */ + public function testParse( $summary, array $expectedUsers ) { + $parser = new EchoSummaryParser( function ( User $user ) { + if ( in_array( $user->getName(), $this->existingUsers ) ) { + return crc32( $user->getName() ); + } + return 0; + } ); + + $users = $parser->parse( $summary ); + foreach ( $users as $name => $user ) { + $this->assertType( User::class, $user ); + $this->assertEquals( $name, $user->getName() ); + } + + $users = array_keys( $users ); + + $this->assertArrayEquals( $expectedUsers, $users ); + } + + public function provideParse() { + return [ + [ '', [] ], + [ " \t\r\n ", [] ], + [ 'foo bar', [] ], + [ 'Werdna', [] ], + [ 'User:Werdna', [] ], + [ '[User:Werdna]', [] ], + [ '[[]]', [] ], + [ '[[:]]', [] ], + [ '[[|]]', [] ], + [ '[[:|]]', [] ], + [ '[[:|test]]', [] ], + [ '[[User:Nonexistent]]', [] ], + [ '/* [[User:Werdna */', [] ], + [ '[[User talk:Werdna]]', [] ], + [ '[[User:Werdna]]', [ 'Werdna' ] ], + [ 'this is [[ [[User:Werdna]] ]]', [ 'Werdna' ] ], + [ '[[User:Werdna|]]', [ 'Werdna' ] ], + [ '[[User:Werdna| ]]', [ 'Werdna' ] ], + [ '[[User:Werdna|Wer | d[n]a]]', [ 'Werdna' ] ], + [ '[[User:Werdna]][[User:Werdna]][[User:Werdna]]', [ 'Werdna' ] ], + [ '/**/[[User:Werdna]][[user:jorm]]', [ 'Werdna', 'Jorm' ] ], + [ '/* [[User:Werdna]] */ [[ user : jim_ Carter_]]', [ 'Jim Carter' ] ], + [ '[[User:/* Jorm */]][[User:/* remove me */Werdna]]', [] ], + [ '[[:User:Werdna]]', [] ], + [ '[[:User:Werdna|]]', [] ], + [ '[[:User:Werdna|foo]]', [] ], + ]; + } +} diff --git a/Echo/tests/phpunit/NotifUserTest.php b/Echo/tests/phpunit/NotifUserTest.php index d766a546..b25f3dc5 100644 --- a/Echo/tests/phpunit/NotifUserTest.php +++ b/Echo/tests/phpunit/NotifUserTest.php @@ -1,7 +1,9 @@ <?php + use MediaWiki\MediaWikiServices; /** + * @covers MWEchoNotifUser * @group Echo */ class MWEchoNotifUserTest extends MediaWikiTestCase { @@ -33,45 +35,6 @@ class MWEchoNotifUserTest extends MediaWikiTestCase { $this->assertInstanceOf( 'MWEchoNotifUser', $notifUser ); } - public function testFlagCacheWithNewTalkNotification() { - $notifUser = $this->newNotifUser(); - - $notifUser->flagCacheWithNewTalkNotification(); - $this->assertEquals( '1', $this->cache->get( $notifUser->getTalkNotificationCacheKey() ) ); - } - - public function testFlagCacheWithNoTalkNotification() { - $notifUser = $this->newNotifUser(); - - $notifUser->flagCacheWithNoTalkNotification(); - $this->assertEquals( '0', $this->cache->get( $notifUser->getTalkNotificationCacheKey() ) ); - } - - public function testNotifCountHasReachedMax() { - $notifUser = $this->newNotifUser(); - - if ( $notifUser->getLocalNotificationCount() > MWEchoNotifUser::MAX_BADGE_COUNT ) { - $this->assertTrue( $notifUser->notifCountHasReachedMax() ); - } else { - $this->assertFalse( $notifUser->notifCountHasReachedMax() ); - } - } - - public function testClearTalkNotification() { - $notifUser = $this->newNotifUser(); - - $notifUser->flagCacheWithNewTalkNotification(); - - $hasMax = $notifUser->notifCountHasReachedMax(); - - $notifUser->clearTalkNotification(); - if ( $hasMax ) { - $this->assertEquals( '1', $this->cache->get( $notifUser->getTalkNotificationCacheKey() ) ); - } else { - $this->assertEquals( '0', $this->cache->get( $notifUser->getTalkNotificationCacheKey() ) ); - } - } - public function testGetEmailFormat() { $user = User::newFromId( 2 ); $notifUser = MWEchoNotifUser::newFromUser( $user ); @@ -156,6 +119,12 @@ class MWEchoNotifUserTest extends MediaWikiTestCase { $gateway->expects( $this->any() ) ->method( 'markRead' ) ->will( $this->returnValue( $dbResult['markRead'] ) ); + $gateway->expects( $this->any() ) + ->method( 'getDB' ) + ->will( $this->returnValue( + $this->getMockBuilder( Database::class ) + ->disableOriginalConstructor()->getMock() + ) ); return $gateway; } @@ -171,15 +140,10 @@ class MWEchoNotifUserTest extends MediaWikiTestCase { return $mapper; } - public function mockEchoTargetPageMapper( array $result = [] ) { - $mapper = $this->getMockBuilder( 'EchoTargetPageMapper' ) + public function mockEchoTargetPageMapper() { + return $this->getMockBuilder( EchoTargetPageMapper::class ) ->disableOriginalConstructor() ->getMock(); - $mapper->expects( $this->any() ) - ->method( 'deleteByUserEvents' ) - ->will( $this->returnValue( $result ) ); - - return $mapper; } protected function mockEchoNotification() { diff --git a/Echo/tests/phpunit/NotificationStructureTest.php b/Echo/tests/phpunit/NotificationStructureTest.php new file mode 100644 index 00000000..17f5a5f3 --- /dev/null +++ b/Echo/tests/phpunit/NotificationStructureTest.php @@ -0,0 +1,40 @@ +<?php + +class NotificationStructureTest extends MediaWikiTestCase { + /** + * @coversNothing + * @dataProvider provideNotificationTypes + * + * @param string $type + * @param array $info + */ + public function testNotificationTypes( $type, array $info ) { + if ( isset( $info['presentation-model'] ) ) { + self::assertTrue( class_exists( $info['presentation-model'] ), + "Presentation model class {$info['presentation-model']} for {$type} must exist" + ); + } + + if ( isset( $info['user-locators'] ) ) { + $locators = $info['user-locators']; + $locator = reset( $locators ); + if ( is_array( $locator ) ) { + $locator = reset( $locator ); + } + self::assertTrue( is_callable( $locator ), + 'User locator ' . print_r( $locator, true ) . " for {$type} must be callable" + ); + } + } + + public function provideNotificationTypes() { + global $wgEchoNotifications; + + $result = []; + foreach ( $wgEchoNotifications as $type => $info ) { + $result[] = [ $type, $info ]; + } + + return $result; + } +} diff --git a/Echo/tests/phpunit/NotificationsTest.php b/Echo/tests/phpunit/NotificationsTest.php new file mode 100644 index 00000000..641e6bd0 --- /dev/null +++ b/Echo/tests/phpunit/NotificationsTest.php @@ -0,0 +1,56 @@ +<?php + +/** + * Tests for the built in notification types + * + * @group Database + */ +class NotificationsTest extends MediaWikiTestCase { + + /** @var User $sysop */ + // @codingStandardsIgnoreStart + var $sysop; + // @codingStandardsIgnoreEnd + + protected function setUp() { + parent::setUp(); + $this->sysop = User::newFromName( 'UTSysop' ); + $this->setMwGlobals( 'wgUser', $this->sysop ); + } + + /** + * Helper function to get a user's latest notification + * @param User $user + * @return EchoEvent + */ + public static function getLatestNotification( $user ) { + $notifMapper = new EchoNotificationMapper(); + $notifs = $notifMapper->fetchUnreadByUser( $user, 1, '', [ 'user-rights' ] ); + $notif = array_pop( $notifs ); + + return $notif->getEvent(); + } + + /** + * @covers EchoHooks::onUserGroupsChanged + */ + public function testUserRightsNotif() { + $user = new User(); + $user->setName( 'Dummy' ); + $user->addToDatabase(); + + $context = new DerivativeContext( RequestContext::getMain() ); + $context->setUser( $this->sysop ); + $ur = new UserrightsPage(); + $ur->setContext( $context ); + $ur->doSaveUserGroups( $user, [ 'sysop' ], [], 'reason' ); + $event = self::getLatestNotification( $user ); + $this->assertEquals( $event->getType(), 'user-rights' ); + $this->assertEquals( $this->sysop->getName(), $event->getAgent()->getName() ); + $extra = $event->getExtra(); + $this->assertArrayHasKey( 'add', $extra ); + $this->assertArrayEquals( [ 'sysop' ], $extra['add'] ); + $this->assertArrayEquals( [], $extra['remove'] ); + } + +} diff --git a/Echo/tests/phpunit/TalkPageFunctionalTest.php b/Echo/tests/phpunit/TalkPageFunctionalTest.php index 4c80f2e0..f33e5020 100644 --- a/Echo/tests/phpunit/TalkPageFunctionalTest.php +++ b/Echo/tests/phpunit/TalkPageFunctionalTest.php @@ -2,22 +2,26 @@ /** * @group Echo - * @group DataBase + * @group Database * @group medium */ class EchoTalkPageFunctionalTest extends ApiTestCase { + /** + * @var \Wikimedia\Rdbms\IDatabase + */ protected $dbr; protected function setUp() { parent::setUp(); - $this->dbr = MWEchoDbFactory::getDB( DB_SLAVE ); + $this->dbr = MWEchoDbFactory::getDB( DB_REPLICA ); } /** * Creates and updates a user talk page a few times to ensure proper events are * created. The user performing the edits is self::$users['sysop']. * @group Broken + * @covers \EchoDiscussionParser */ public function testAddCommentsToTalkPage() { $editor = self::$users['sysop']->getUser()->getName(); @@ -76,7 +80,7 @@ class EchoTalkPageFunctionalTest extends ApiTestCase { } /** - * @return array All events in db sorted from oldest to newest + * @return \stdClass[] All events in db sorted from oldest to newest */ protected function fetchAllEvents() { $res = $this->dbr->select( 'echo_event', [ '*' ], [], __METHOD__, [ 'ORDER BY' => 'event_id ASC' ] ); diff --git a/Echo/tests/phpunit/ThankYouEditTest.php b/Echo/tests/phpunit/ThankYouEditTest.php index a573bdb1..5325c5cd 100644 --- a/Echo/tests/phpunit/ThankYouEditTest.php +++ b/Echo/tests/phpunit/ThankYouEditTest.php @@ -2,6 +2,7 @@ /** * @group Echo + * @group Database */ class MWEchoThankYouEditTest extends MediaWikiTestCase { @@ -17,6 +18,9 @@ class MWEchoThankYouEditTest extends MediaWikiTestCase { $db->delete( 'echo_notification', '*', __METHOD__ ); } + /** + * @covers \EchoHooks::onPageContentSaveComplete + */ public function testFirstEdit() { // setup $this->deleteEchoData(); @@ -36,6 +40,9 @@ class MWEchoThankYouEditTest extends MediaWikiTestCase { $this->assertEquals( 1, $notification->getEvent()->getExtraParam( 'editCount', 'not found' ) ); } + /** + * @covers \EchoHooks::onPageContentSaveComplete + */ public function testTenthEdit() { // setup $this->deleteEchoData(); diff --git a/Echo/tests/phpunit/UserLocatorTest.php b/Echo/tests/phpunit/UserLocatorTest.php index f09f80a9..514c8226 100644 --- a/Echo/tests/phpunit/UserLocatorTest.php +++ b/Echo/tests/phpunit/UserLocatorTest.php @@ -1,7 +1,8 @@ <?php /** - * @Database + * @group Database + * @covers EchoUserLocator */ class EchoUserLocatorTest extends MediaWikiTestCase { diff --git a/Echo/tests/phpunit/api/ApiEchoMarkReadTest.php b/Echo/tests/phpunit/api/ApiEchoMarkReadTest.php index 135d1867..9c41ec37 100644 --- a/Echo/tests/phpunit/api/ApiEchoMarkReadTest.php +++ b/Echo/tests/phpunit/api/ApiEchoMarkReadTest.php @@ -4,15 +4,10 @@ * @group medium * @group API * @group Database - * @covers ApiQuery + * @covers ApiEchoMarkRead */ class ApiEchoMarkReadTest extends ApiTestCase { - protected function setUp() { - parent::setUp(); - $this->doLogin(); - } - function getTokens() { return $this->getTokenList( self::$users['sysop'] ); } diff --git a/Echo/tests/phpunit/api/ApiEchoNotificationsTest.php b/Echo/tests/phpunit/api/ApiEchoNotificationsTest.php index 9f86a6ef..cfcf5c90 100644 --- a/Echo/tests/phpunit/api/ApiEchoNotificationsTest.php +++ b/Echo/tests/phpunit/api/ApiEchoNotificationsTest.php @@ -3,7 +3,7 @@ /** * @group medium * @group API - * @covers ApiQuery + * @covers ApiEchoNotifications */ class ApiEchoNotificationsTest extends ApiTestCase { diff --git a/Echo/tests/phpunit/cache/TitleLocalCacheTest.php b/Echo/tests/phpunit/cache/TitleLocalCacheTest.php index af255edb..fdd722d3 100644 --- a/Echo/tests/phpunit/cache/TitleLocalCacheTest.php +++ b/Echo/tests/phpunit/cache/TitleLocalCacheTest.php @@ -1,90 +1,85 @@ <?php +use Wikimedia\TestingAccessWrapper; + +/** + * @covers EchoTitleLocalCache + * @group Database + */ class EchoTitleLocalCacheTest extends MediaWikiTestCase { public function testCreate() { $cache = EchoTitleLocalCache::create(); - $this->assertInstanceOf( 'EchoTitleLocalCache', $cache ); - - return $cache; + $this->assertInstanceOf( EchoTitleLocalCache::class, $cache ); } - /** - * @depends testCreate - */ - public function testAdd( $cache ) { - $cache->clearAll(); + public function testAdd() { + $cache = $this->getMockBuilder( EchoTitleLocalCache::class ) + ->setMethods( [ 'resolve' ] )->getMock(); + $cache->add( 1 ); - $this->assertEquals( count( $cache->getLookups() ), 1 ); - $this->assertArrayHasKey( 1, $cache->getLookups() ); + $cache->add( 9 ); + + // Resolutions should be batched + $cache->expects( $this->exactly( 1 ) )->method( 'resolve' ) + ->with( [ 1, 9 ] )->willReturn( [] ); + + // Trigger + $cache->get( 9 ); } - /** - * @depends testCreate - */ - public function testGet( $cache ) { - $map = new HashBagOStuff( [ 'maxKeys' => EchoLocalCache::TARGET_MAX_NUM ] ); - $titleIds = []; + public function testGet() { + $cache = $this->getMockBuilder( EchoTitleLocalCache::class ) + ->setMethods( [ 'resolve' ] )->getMock(); + $cachePriv = TestingAccessWrapper::newFromObject( $cache ); // First title included in cache - $res = $this->insertPage( 'EchoTitleLocalCacheTest_testGet' ); - $titleIds[$res['id']] = $res['id']; - $map->set( $res['id'], $res['title'] ); - + $res1 = $this->insertPage( 'EchoTitleLocalCacheTest_testGet1' ); + $cachePriv->targets->set( $res1['id'], $res1['title'] ); // Second title not in internal cache, resolves from db. - $res = $this->insertPage( 'EchoTitleLocalCacheTest_testGet2' ); - $titleIds[$res['id']] = $res['id']; - - $object = new \ReflectionObject( $cache ); - - // Load our generated map in as the targets (known mapping from - // title id to title object) into $cache - $targets = $object->getProperty( 'targets' ); - $targets->setAccessible( true ); - $targets->setValue( $cache, $map ); - - // Load both of the titles we are curious about into the list of titles - // to be looked up - $lookups = $object->getProperty( 'lookups' ); - $lookups->setAccessible( true ); - $lookups->setValue( $cache, $titleIds ); - - // Requesting the first object, which is within the known targets, should - // not resolve the pending lookups. - $this->assertInstanceOf( 'Title', $cache->get( reset( $titleIds ) ) ); - $this->assertGreaterThan( 0, count( $cache->getLookups() ) ); - - // Requesting the second object, which is not within the known targets, should - // resolve the pending lookups and reset the list to lookup. - $this->assertInstanceOf( 'Title', $cache->get( end( $titleIds ) ) ); - $this->assertEquals( 0, count( $cache->getLookups() ) ); + $res2 = $this->insertPage( 'EchoTitleLocalCacheTest_testGet2' ); + $cache->expects( $this->exactly( 1 ) )->method( 'resolve' ) + ->with( [ $res2['id'] ] ) + ->willReturn( [ $res2['id'] => $res2['title'] ] ); + + // Register demand for both + $cache->add( $res1['id'] ); + $cache->add( $res2['id'] ); + + // Should not call resolve() for first title + $this->assertSame( $res1['title'], $cache->get( $res1['id'] ), 'First title' ); + + // Should resolve() for second title + $this->assertSame( $res2['title'], $cache->get( $res2['id'] ), 'Second title' ); } - /** - * @depends testCreate - */ - public function testClearAll( $cache ) { - $map = new HashBagOStuff( [ 'maxKeys' => EchoLocalCache::TARGET_MAX_NUM ] ); - $map->set( 1, $this->mockTitle() ); - $object = new \ReflectionObject( $cache ); - $targets = $object->getProperty( 'targets' ); - $targets->setAccessible( true ); - $targets->setValue( $cache, $map ); - $lookups = $object->getProperty( 'lookups' ); - $lookups->setAccessible( true ); - $lookups->setValue( $cache, [ '1' => '1', '2' => '2' ] ); + public function testClearAll() { + $cache = $this->getMockBuilder( EchoTitleLocalCache::class ) + ->setMethods( [ 'resolve' ] )->getMock(); + // Add 1 to cache + $cachePriv = TestingAccessWrapper::newFromObject( $cache ); + $cachePriv->targets->set( 1, $this->mockTitle() ); + // Add 2 and 3 to demand + $cache->add( 2 ); + $cache->add( 3 ); $cache->clearAll(); - $this->assertTrue( count( $cache->getLookups() ) == 0 ); - $this->assertEquals( false, $cache->getTargets()->get( 1 ) ); - $this->assertEquals( false, $cache->getTargets()->get( '1' ) ); + + $this->assertSame( null, $cache->get( 1 ), 'Cache was cleared' ); + + // Lookups batch was cleared + $cache->expects( $this->exactly( 1 ) )->method( 'resolve' ) + ->with( [ 4 ] ) + ->willReturn( [] ); + $cache->add( 4 ); + $cache->get( 4 ); } /** - * Mock object of Title + * @return Title */ protected function mockTitle() { - $title = $this->getMockBuilder( 'Title' ) + $title = $this->getMockBuilder( Title::class ) ->disableOriginalConstructor() ->getMock(); diff --git a/Echo/tests/phpunit/controller/NotificationControllerTest.php b/Echo/tests/phpunit/controller/NotificationControllerTest.php index 8a38a7e5..9e497024 100644 --- a/Echo/tests/phpunit/controller/NotificationControllerTest.php +++ b/Echo/tests/phpunit/controller/NotificationControllerTest.php @@ -1,5 +1,8 @@ <?php +/** + * @covers EchoNotificationController + */ class NotificationControllerTest extends MediaWikiTestCase { public function evaluateUserLocatorsProvider() { diff --git a/Echo/tests/phpunit/gateway/UserNotificationGatewayTest.php b/Echo/tests/phpunit/gateway/UserNotificationGatewayTest.php index 7e656e19..2cc4fd78 100644 --- a/Echo/tests/phpunit/gateway/UserNotificationGatewayTest.php +++ b/Echo/tests/phpunit/gateway/UserNotificationGatewayTest.php @@ -1,11 +1,14 @@ <?php +/** + * @covers EchoUserNotificationGateway + */ class EchoUserNotificationGatewayTest extends MediaWikiTestCase { public function testMarkRead() { // no event ids to mark $gateway = new EchoUserNotificationGateway( User::newFromId( 1 ), $this->mockMWEchoDbFactory() ); - $this->assertNull( $gateway->markRead( [] ) ); + $this->assertFalse( $gateway->markRead( [] ) ); // successful update $gateway = new EchoUserNotificationGateway( User::newFromId( 1 ), $this->mockMWEchoDbFactory( [ 'update' => true ] ) ); @@ -29,19 +32,19 @@ class EchoUserNotificationGatewayTest extends MediaWikiTestCase { public function testGetNotificationCount() { // unsuccessful select $gateway = new EchoUserNotificationGateway( $this->mockUser(), $this->mockMWEchoDbFactory( [ 'selectRowCount' => 0 ] ) ); - $this->assertEquals( 0, $gateway->getCappedNotificationCount( DB_SLAVE, [ 'event_one' ] ) ); + $this->assertEquals( 0, $gateway->getCappedNotificationCount( DB_REPLICA, [ 'event_one' ] ) ); // successful select of alert $gateway = new EchoUserNotificationGateway( $this->mockUser(), $this->mockMWEchoDbFactory( [ 'selectRowCount' => 2 ] ) ); - $this->assertEquals( 2, $gateway->getCappedNotificationCount( DB_SLAVE, [ 'event_one', 'event_two' ] ) ); + $this->assertEquals( 2, $gateway->getCappedNotificationCount( DB_REPLICA, [ 'event_one', 'event_two' ] ) ); // there is event, should return 0 $gateway = new EchoUserNotificationGateway( $this->mockUser(), $this->mockMWEchoDbFactory( [ 'selectRowCount' => 2 ] ) ); - $this->assertEquals( 0, $gateway->getCappedNotificationCount( DB_SLAVE, [] ) ); + $this->assertEquals( 0, $gateway->getCappedNotificationCount( DB_REPLICA, [] ) ); // successful select $gateway = new EchoUserNotificationGateway( $this->mockUser(), $this->mockMWEchoDbFactory( [ 'selectRowCount' => 3 ] ) ); - $this->assertEquals( 3, $gateway->getCappedNotificationCount( DB_SLAVE, [ 'event_one' ] ) ); + $this->assertEquals( 3, $gateway->getCappedNotificationCount( DB_REPLICA, [ 'event_one' ] ) ); } public function testGetUnreadNotifications() { @@ -93,7 +96,8 @@ class EchoUserNotificationGatewayTest extends MediaWikiTestCase { } /** - * Mock object of DatabaseMysql ( DatabaseBase ) + * Returns a mock database object + * @return \Wikimedia\Rdbms\IDatabase */ protected function mockDb( array $dbResult = [] ) { $dbResult += [ @@ -102,7 +106,7 @@ class EchoUserNotificationGatewayTest extends MediaWikiTestCase { 'selectRow' => '', 'selectRowCount' => '', ]; - $db = $this->getMockBuilder( 'DatabaseMysql' ) + $db = $this->getMockBuilder( 'DatabaseMysqli' ) ->disableOriginalConstructor() ->getMock(); $db->expects( $this->any() ) @@ -117,9 +121,10 @@ class EchoUserNotificationGatewayTest extends MediaWikiTestCase { $db->expects( $this->any() ) ->method( 'selectRowCount' ) ->will( $this->returnValue( $dbResult['selectRowCount'] ) ); + $numRows = is_array( $dbResult['select'] ) ? count( $dbResult['select'] ) : 0; $db->expects( $this->any() ) ->method( 'numRows' ) - ->will( $this->returnValue( count( $dbResult['select'] ) ) ); + ->will( $this->returnValue( $numRows ) ); return $db; } diff --git a/Echo/tests/phpunit/iterator/FilteredSequentialIteratorTest.php b/Echo/tests/phpunit/iterator/FilteredSequentialIteratorTest.php index b05e3229..7042d633 100644 --- a/Echo/tests/phpunit/iterator/FilteredSequentialIteratorTest.php +++ b/Echo/tests/phpunit/iterator/FilteredSequentialIteratorTest.php @@ -1,5 +1,9 @@ <?php +/** + * @covers EchoCallbackIterator + * @covers EchoFilteredSequentialIterator + */ class FilteredSequentialIteratorTest extends MediaWikiTestCase { public function testEchoCallbackIteratorDoesntBlowUp() { diff --git a/Echo/tests/phpunit/maintenance/SupressionMaintenanceTest.php b/Echo/tests/phpunit/maintenance/SupressionMaintenanceTest.php index 0a32d8af..029be88f 100644 --- a/Echo/tests/phpunit/maintenance/SupressionMaintenanceTest.php +++ b/Echo/tests/phpunit/maintenance/SupressionMaintenanceTest.php @@ -2,6 +2,7 @@ /** * @group Echo + * @covers EchoSuppressionRowUpdateGenerator */ class SuppressionMaintenanceTest extends MediaWikiTestCase { diff --git a/Echo/tests/phpunit/mapper/AbstractMapperTest.php b/Echo/tests/phpunit/mapper/AbstractMapperTest.php index 5c3a5826..02194a02 100644 --- a/Echo/tests/phpunit/mapper/AbstractMapperTest.php +++ b/Echo/tests/phpunit/mapper/AbstractMapperTest.php @@ -1,5 +1,8 @@ <?php +/** + * @covers EchoAbstractMapper + */ class EchoAbstractMapperTest extends MediaWikiTestCase { public function testAttachListener() { @@ -65,13 +68,3 @@ class EchoAbstractMapperTest extends MediaWikiTestCase { } } - -/** - * Create a stub class for testing the abstract class - */ -class EchoAbstractMapperStub extends EchoAbstractMapper { - - public function testMethod() { - } - -} diff --git a/Echo/tests/phpunit/mapper/EchoAbstractMapperStub.php b/Echo/tests/phpunit/mapper/EchoAbstractMapperStub.php new file mode 100644 index 00000000..359e97ff --- /dev/null +++ b/Echo/tests/phpunit/mapper/EchoAbstractMapperStub.php @@ -0,0 +1,11 @@ +<?php + +/** + * Create a stub class for testing the abstract class + */ +class EchoAbstractMapperStub extends EchoAbstractMapper { + + public function testMethod() { + } + +} diff --git a/Echo/tests/phpunit/mapper/EchoExecuteFirstArgumentStub.php b/Echo/tests/phpunit/mapper/EchoExecuteFirstArgumentStub.php new file mode 100644 index 00000000..1e2889e7 --- /dev/null +++ b/Echo/tests/phpunit/mapper/EchoExecuteFirstArgumentStub.php @@ -0,0 +1,18 @@ +<?php + +class EchoExecuteFirstArgumentStub implements PHPUnit_Framework_MockObject_Stub { + public function invoke( PHPUnit_Framework_MockObject_Invocation $invocation ) { + if ( !$invocation instanceof PHPUnit_Framework_MockObject_Invocation_Static ) { + throw new PHPUnit_Framework_Exception( 'wrong invocation type' ); + } + if ( !$invocation->arguments ) { + throw new PHPUnit_Framework_Exception( 'Method call must have an argument' ); + } + + return call_user_func( reset( $invocation->arguments ) ); + } + + public function toString() { + return 'return result of call_user_func on first invocation argument'; + } +} diff --git a/Echo/tests/phpunit/mapper/EventMapperTest.php b/Echo/tests/phpunit/mapper/EventMapperTest.php index e9528ca9..e81e183d 100644 --- a/Echo/tests/phpunit/mapper/EventMapperTest.php +++ b/Echo/tests/phpunit/mapper/EventMapperTest.php @@ -1,5 +1,8 @@ <?php +/** + * @covers EchoEventMapper + */ class EchoEventMapperTest extends MediaWikiTestCase { public function provideDataTestInsert() { @@ -99,7 +102,8 @@ class EchoEventMapperTest extends MediaWikiTestCase { } /** - * Mock object of DatabaseMysql ( DatabaseBase ) + * Returns a mock database object + * @return \Wikimedia\Rdbms\IDatabase */ protected function mockDb( array $dbResult ) { $dbResult += [ @@ -108,7 +112,7 @@ class EchoEventMapperTest extends MediaWikiTestCase { 'select' => '', 'selectRow' => '' ]; - $db = $this->getMockBuilder( 'DatabaseMysql' ) + $db = $this->getMockBuilder( 'DatabaseMysqli' ) ->disableOriginalConstructor() ->getMock(); $db->expects( $this->any() ) diff --git a/Echo/tests/phpunit/mapper/NotificationMapperTest.php b/Echo/tests/phpunit/mapper/NotificationMapperTest.php index 420c0934..62359a9c 100644 --- a/Echo/tests/phpunit/mapper/NotificationMapperTest.php +++ b/Echo/tests/phpunit/mapper/NotificationMapperTest.php @@ -1,5 +1,8 @@ <?php +/** + * @covers EchoNotificationMapper + */ class EchoNotificationMapperTest extends MediaWikiTestCase { /** @@ -39,8 +42,8 @@ class EchoNotificationMapperTest extends MediaWikiTestCase { $notifMapper = new EchoNotificationMapper( $this->mockMWEchoDbFactory( [ 'select' => $dbResult ] ) ); $res = $notifMapper->fetchUnreadByUser( $this->mockUser(), 10, null, '', [ 'test_event' ] ); - $this->assertTrue( is_array( $res ) ); - $this->assertGreaterThan( 0, count( $res ) ); + $this->assertInternalType( 'array', $res ); + $this->assertNotEmpty( $res ); foreach ( $res as $row ) { $this->assertInstanceOf( 'EchoNotification', $row ); } @@ -90,8 +93,8 @@ class EchoNotificationMapperTest extends MediaWikiTestCase { ) ); $res = $notifMapper->fetchByUser( $this->mockUser(), 10, '', [ 'test_event' ] ); - $this->assertTrue( is_array( $res ) ); - $this->assertGreaterThan( 0, count( $res ) ); + $this->assertInternalType( 'array', $res ); + $this->assertNotEmpty( $res ); foreach ( $res as $row ) { $this->assertInstanceOf( 'EchoNotification', $row ); } @@ -158,13 +161,36 @@ class EchoNotificationMapperTest extends MediaWikiTestCase { } public function testDeleteByUserEventOffset() { - $dbResult = [ 'delete' => true ]; - $notifMapper = new EchoNotificationMapper( $this->mockMWEchoDbFactory( $dbResult ) ); - $this->assertTrue( $notifMapper->deleteByUserEventOffset( User::newFromId( 1 ), 500 ) ); + $this->setMwGlobals( [ 'wgUpdateRowsPerQuery' => 4 ] ); + $mockDb = $this->getMockBuilder( 'DatabaseMysqli' ) + ->disableOriginalConstructor() + ->getMock(); + $mockDb->expects( $this->any() ) + ->method( 'selectFieldValues' ) + ->will( $this->returnValue( [ 1, 2, 3, 5, 8, 13, 21, 34, 55, 89 ] ) ); + $mockDb->expects( $this->exactly( 3 ) ) + ->method( 'delete' ) + ->withConsecutive( + [ + $this->equalTo( 'echo_notification' ), + $this->equalTo( [ 'notification_user' => 1, 'notification_event' => [ 1, 2, 3, 5 ] ] ), + $this->anything() + ], + [ + $this->equalTo( 'echo_notification' ), + $this->equalTo( [ 'notification_user' => 1, 'notification_event' => [ 8, 13, 21, 34 ] ] ), + $this->anything() + ], + [ + $this->equalTo( 'echo_notification' ), + $this->equalTo( [ 'notification_user' => 1, 'notification_event' => [ 55, 89 ] ] ), + $this->anything() + ] + ) + ->will( $this->returnValue( true ) ); - $dbResult = [ 'delete' => false ]; - $notifMapper = new EchoNotificationMapper( $this->mockMWEchoDbFactory( $dbResult ) ); - $this->assertFalse( $notifMapper->deleteByUserEventOffset( User::newFromId( 1 ), 500 ) ); + $notifMapper = new EchoNotificationMapper( $this->mockMWEchoDbFactory( $mockDb ) ); + $this->assertTrue( $notifMapper->deleteByUserEventOffset( User::newFromId( 1 ), 500 ) ); } /** @@ -203,20 +229,23 @@ class EchoNotificationMapperTest extends MediaWikiTestCase { /** * Mock object of MWEchoDbFactory + * @param array|\Wikimedia\Rdbms\IDatabase $dbResultOrMockDb */ - protected function mockMWEchoDbFactory( $dbResult ) { + protected function mockMWEchoDbFactory( $dbResultOrMockDb ) { + $mockDb = is_array( $dbResultOrMockDb ) ? $this->mockDb( $dbResultOrMockDb ) : $dbResultOrMockDb; $dbFactory = $this->getMockBuilder( 'MWEchoDbFactory' ) ->disableOriginalConstructor() ->getMock(); $dbFactory->expects( $this->any() ) ->method( 'getEchoDb' ) - ->will( $this->returnValue( $this->mockDb( $dbResult ) ) ); + ->will( $this->returnValue( $mockDb ) ); return $dbFactory; } /** - * Mock object of DatabaseMysql ( DatabaseBase ) + * Returns a mock database object + * @return \Wikimedia\Rdbms\IDatabase */ protected function mockDb( array $dbResult ) { $dbResult += [ @@ -226,7 +255,7 @@ class EchoNotificationMapperTest extends MediaWikiTestCase { 'delete' => '' ]; - $db = $this->getMockBuilder( 'DatabaseMysql' ) + $db = $this->getMockBuilder( 'DatabaseMysqli' ) ->disableOriginalConstructor() ->getMock(); $db->expects( $this->any() ) @@ -249,20 +278,3 @@ class EchoNotificationMapperTest extends MediaWikiTestCase { } } - -class EchoExecuteFirstArgumentStub implements PHPUnit_Framework_MockObject_Stub { - public function invoke( PHPUnit_Framework_MockObject_Invocation $invocation ) { - if ( !$invocation instanceof PHPUnit_Framework_MockObject_Invocation_Static ) { - throw new PHPUnit_Framework_Exception( 'wrong invocation type' ); - } - if ( !$invocation->arguments ) { - throw new PHPUnit_Framework_Exception( 'Method call must have an argument' ); - } - - return call_user_func( reset( $invocation->arguments ) ); - } - - public function toString() { - return 'return result of call_user_func on first invocation argument'; - } -} diff --git a/Echo/tests/phpunit/mapper/TargetPageMapperTest.php b/Echo/tests/phpunit/mapper/TargetPageMapperTest.php index 522ee34d..aaba3e3c 100644 --- a/Echo/tests/phpunit/mapper/TargetPageMapperTest.php +++ b/Echo/tests/phpunit/mapper/TargetPageMapperTest.php @@ -1,5 +1,8 @@ <?php +/** + * @covers EchoTargetPageMapper + */ class EchoTargetPageMapperTest extends MediaWikiTestCase { public function provideDataTestInsert() { @@ -35,16 +38,13 @@ class EchoTargetPageMapperTest extends MediaWikiTestCase { * Mock object of EchoTargetPage */ protected function mockEchoTargetPage() { - $target = $this->getMockBuilder( 'EchoTargetPage' ) + $target = $this->getMockBuilder( EchoTargetPage::class ) ->disableOriginalConstructor() ->getMock(); $target->expects( $this->any() ) ->method( 'toDbArray' ) ->will( $this->returnValue( [] ) ); $target->expects( $this->any() ) - ->method( 'getUser' ) - ->will( $this->returnValue( User::newFromId( 1 ) ) ); - $target->expects( $this->any() ) ->method( 'getPageId' ) ->will( $this->returnValue( 2 ) ); $target->expects( $this->any() ) @@ -69,7 +69,8 @@ class EchoTargetPageMapperTest extends MediaWikiTestCase { } /** - * Mock object of DatabaseMysql ( DatabaseBase ) + * Returns a mock database object + * @return \Wikimedia\Rdbms\IDatabase */ protected function mockDb( array $dbResult ) { $dbResult += [ @@ -78,7 +79,7 @@ class EchoTargetPageMapperTest extends MediaWikiTestCase { 'select' => '', 'delete' => '' ]; - $db = $this->getMockBuilder( 'DatabaseMysql' ) + $db = $this->getMockBuilder( 'DatabaseMysqli' ) ->disableOriginalConstructor() ->getMock(); $db->expects( $this->any() ) diff --git a/Echo/tests/phpunit/model/NotificationTest.php b/Echo/tests/phpunit/model/NotificationTest.php index d6d45c3e..92522303 100644 --- a/Echo/tests/phpunit/model/NotificationTest.php +++ b/Echo/tests/phpunit/model/NotificationTest.php @@ -1,5 +1,8 @@ <?php +/** + * @covers EchoNotification + */ class EchoNotificationTest extends MediaWikiTestCase { public function testNewFromRow() { @@ -28,7 +31,7 @@ class EchoNotificationTest extends MediaWikiTestCase { $notif = EchoNotification::newFromRow( (object)$row, [ EchoTargetPage::newFromRow( (object)$this->mockTargetPageRow() ) ] ); - $this->assertGreaterThan( 0, count( $notif->getTargetPages() ) ); + $this->assertNotEmpty( $notif->getTargetPages() ); foreach ( $notif->getTargetPages() as $targetPage ) { $this->assertInstanceOf( 'EchoTargetPage', $targetPage ); } diff --git a/Echo/tests/phpunit/model/TargetPageTest.php b/Echo/tests/phpunit/model/TargetPageTest.php index a7f7c035..f925cfeb 100644 --- a/Echo/tests/phpunit/model/TargetPageTest.php +++ b/Echo/tests/phpunit/model/TargetPageTest.php @@ -1,5 +1,8 @@ <?php +/** + * @covers EchoTargetPage + */ class EchoTargetPageTest extends MediaWikiTestCase { public function testCreate() { diff --git a/Echo/tests/phpunit/revision_txt/123.txt b/Echo/tests/phpunit/revision_txt/123.txt new file mode 100644 index 00000000..257cc564 --- /dev/null +++ b/Echo/tests/phpunit/revision_txt/123.txt @@ -0,0 +1 @@ +foo diff --git a/Echo/tests/phpunit/revision_txt/1234.txt b/Echo/tests/phpunit/revision_txt/1234.txt new file mode 100644 index 00000000..d675fa44 --- /dev/null +++ b/Echo/tests/phpunit/revision_txt/1234.txt @@ -0,0 +1 @@ +foo bar |