diff options
Diffstat (limited to 'Echo/tests')
59 files changed, 1166 insertions, 422 deletions
diff --git a/Echo/tests/phpunit/AttributeManagerTest.php b/Echo/tests/phpunit/AttributeManagerTest.php index 42ccb992..856c51c7 100644 --- a/Echo/tests/phpunit/AttributeManagerTest.php +++ b/Echo/tests/phpunit/AttributeManagerTest.php @@ -1,12 +1,12 @@ <?php /** - * @covers EchoAttributeManager + * @covers \EchoAttributeManager */ class EchoAttributeManagerTest extends MediaWikiTestCase { public function testNewFromGlobalVars() { - $this->assertInstanceOf( 'EchoAttributeManager', EchoAttributeManager::newFromGlobalVars() ); + $this->assertInstanceOf( EchoAttributeManager::class, EchoAttributeManager::newFromGlobalVars() ); } public static function getUserLocatorsProvider() { @@ -139,10 +139,10 @@ class EchoAttributeManagerTest extends MediaWikiTestCase { 'category_four' => [] ]; $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' ) ); - $this->assertEquals( 10, $manager->getCategoryPriority( 'category_four' ) ); + $this->assertSame( 6, $manager->getCategoryPriority( 'category_one' ) ); + $this->assertSame( 10, $manager->getCategoryPriority( 'category_two' ) ); + $this->assertSame( 10, $manager->getCategoryPriority( 'category_three' ) ); + $this->assertSame( 10, $manager->getCategoryPriority( 'category_four' ) ); } public function testGetNotificationPriority() { @@ -173,10 +173,10 @@ class EchoAttributeManagerTest extends MediaWikiTestCase { 'category_four' => [] ]; $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' ) ); - $this->assertEquals( 10, $manager->getNotificationPriority( 'event_four' ) ); + $this->assertSame( 6, $manager->getNotificationPriority( 'event_one' ) ); + $this->assertSame( 10, $manager->getNotificationPriority( 'event_two' ) ); + $this->assertSame( 10, $manager->getNotificationPriority( 'event_three' ) ); + $this->assertSame( 10, $manager->getNotificationPriority( 'event_four' ) ); } public static function getEventsForSectionProvider() { @@ -240,6 +240,9 @@ class EchoAttributeManagerTest extends MediaWikiTestCase { 'event_three' => [ 'category' => 'category_three' ], + 'event_four' => [ + 'category' => 'category_four' + ] ]; $category = [ 'category_one' => [ @@ -257,10 +260,30 @@ class EchoAttributeManagerTest extends MediaWikiTestCase { 'category_three' => [ 'priority' => 10, ], + 'category_four' => [ + 'priority' => 10, + ] ]; - $manager = new EchoAttributeManager( $notif, $category, [], [] ); - $this->assertEquals( $manager->getUserEnabledEvents( $this->mockUser(), 'web' ), - [ 'event_two', 'event_three' ] ); + $defaultNotifyTypeAvailability = [ + 'web' => true, + 'email' => true, + ]; + $notifyTypeAvailabilityByCategory = [ + 'category_three' => [ + 'web' => false, + 'email' => true, + ] + ]; + $manager = new EchoAttributeManager( + $notif, + $category, + $defaultNotifyTypeAvailability, + $notifyTypeAvailabilityByCategory + ); + $this->assertEquals( + [ 'event_two', 'event_four' ], + $manager->getUserEnabledEvents( $this->mockUser(), 'web' ) + ); } public function testGetUserEnabledEventsbySections() { @@ -279,6 +302,9 @@ class EchoAttributeManagerTest extends MediaWikiTestCase { 'event_four' => [ 'category' => 'category_three', ], + 'event_five' => [ + 'category' => 'category_five' + ] ]; $category = [ 'category_one' => [ @@ -290,26 +316,44 @@ class EchoAttributeManagerTest extends MediaWikiTestCase { 'category_three' => [ 'priority' => 10 ], + 'category_five' => [ + 'priority' => 10 + ] ]; - $manager = new EchoAttributeManager( $notif, $category, [], [] ); + $defaultNotifyTypeAvailability = [ + 'web' => true, + 'email' => true, + ]; + $notifyTypeAvailabilityByCategory = [ + 'category_five' => [ + 'web' => false, + 'email' => true, + ] + ]; + $manager = new EchoAttributeManager( + $notif, + $category, + $defaultNotifyTypeAvailability, + $notifyTypeAvailabilityByCategory + ); $expected = [ 'event_one', 'event_three', 'event_four' ]; - $actual = $manager->getUserEnabledEventsBySections( $this->mockUser(), 'web', [ 'alert' ] ); + $actual = $manager->getUserEnabledEventsbySections( $this->mockUser(), 'web', [ 'alert' ] ); sort( $expected ); sort( $actual ); - $this->assertEquals( $actual, $expected ); + $this->assertEquals( $expected, $actual ); $expected = [ 'event_two' ]; - $actual = $manager->getUserEnabledEventsBySections( $this->mockUser(), 'web', [ 'message' ] ); + $actual = $manager->getUserEnabledEventsbySections( $this->mockUser(), 'web', [ 'message' ] ); sort( $expected ); sort( $actual ); - $this->assertEquals( $actual, $expected ); + $this->assertEquals( $expected, $actual ); $expected = [ 'event_one', 'event_two', 'event_three', 'event_four' ]; - $actual = $manager->getUserEnabledEventsBySections( $this->mockUser(), 'web', + $actual = $manager->getUserEnabledEventsbySections( $this->mockUser(), 'web', [ 'message', 'alert' ] ); sort( $expected ); sort( $actual ); - $this->assertEquals( $actual, $expected ); + $this->assertEquals( $expected, $actual ); } public static function getEventsByCategoryProvider() { @@ -406,8 +450,8 @@ class EchoAttributeManagerTest extends MediaWikiTestCase { } /** - @dataProvider isNotifyTypeAvailableForCategoryProvider - */ + * @dataProvider isNotifyTypeAvailableForCategoryProvider + */ public function testIsNotifyTypeAvailableForCategory( $message, $expected, @@ -479,7 +523,7 @@ class EchoAttributeManagerTest extends MediaWikiTestCase { * Mock object of User */ protected function mockUser() { - $user = $this->getMockBuilder( 'User' ) + $user = $this->getMockBuilder( User::class ) ->disableOriginalConstructor() ->getMock(); $user->expects( $this->any() ) diff --git a/Echo/tests/phpunit/ContainmentSetTest.php b/Echo/tests/phpunit/ContainmentSetTest.php index 1f538291..d85de7f3 100644 --- a/Echo/tests/phpunit/ContainmentSetTest.php +++ b/Echo/tests/phpunit/ContainmentSetTest.php @@ -1,7 +1,7 @@ <?php /** - * @covers EchoContainmentSet + * @covers \EchoContainmentSet * @group Echo * @group Database */ @@ -23,22 +23,20 @@ class ContainmentSetTest extends MediaWikiTestCase { } public function testCachedListInnerListIsOnlyCalledOnce() { - // the global $wgMemc during tests is an EmptyBagOStuff, so it - // wont do anything. We use a HashBagOStuff to get more like a real - // client - $innerCache = new HashBagOStuff; + $innerCache = new HashBagOStuff; // simulate caching + $wanCache = new WANObjectCache( [ 'cache' => $innerCache ] ); $inner = [ 'bing', 'bang' ]; // We use a mock instead of the real thing for the $this->once() assertion // verifying that the cache doesn't just keep asking the inner object - $list = $this->getMockBuilder( 'EchoArrayList' ) + $list = $this->getMockBuilder( EchoArrayList::class ) ->disableOriginalConstructor() ->getMock(); $list->expects( $this->once() ) ->method( 'getValues' ) ->will( $this->returnValue( $inner ) ); - $cached = new EchoCachedList( $innerCache, 'test_key', $list ); + $cached = new EchoCachedList( $wanCache, 'test_key', $list ); // First run through should hit the main list, and save to innerCache $this->assertEquals( $inner, $cached->getValues() ); @@ -46,7 +44,7 @@ class ContainmentSetTest extends MediaWikiTestCase { // Reinitialize to get a fresh instance that will pull directly from // innerCache without hitting the $list - $freshCached = new EchoCachedList( $innerCache, 'test_key', $list ); + $freshCached = new EchoCachedList( $wanCache, 'test_key', $list ); $this->assertEquals( $inner, $freshCached->getValues() ); } @@ -67,11 +65,4 @@ class ContainmentSetTest extends MediaWikiTestCase { $list = new EchoOnWikiList( NS_USER, "Some_Non_Existant_Page" ); $this->assertEquals( [], $list->getValues() ); } - - protected function editPage( $pageName, $text, $summary = '', $defaultNs = NS_MAIN ) { - $title = Title::newFromText( $pageName, $defaultNs ); - $page = WikiPage::factory( $title ); - - return $page->doEditContent( ContentHandler::makeContent( $text, $title ), $summary ); - } } diff --git a/Echo/tests/phpunit/DiscussionParserTest.php b/Echo/tests/phpunit/DiscussionParserTest.php index 391ff078..a161cd07 100644 --- a/Echo/tests/phpunit/DiscussionParserTest.php +++ b/Echo/tests/phpunit/DiscussionParserTest.php @@ -2,10 +2,11 @@ // phpcs:disable Generic.Files.LineLength -- Long html test examples +use MediaWiki\MediaWikiServices; use Wikimedia\TestingAccessWrapper; /** - * @covers EchoDiscussionParser + * @covers \EchoDiscussionParser * @group Echo * @group Database */ @@ -129,12 +130,12 @@ class EchoDiscussionParserTest extends MediaWikiTestCase { ], ]; - protected function setUp() { + protected function setUp() : void { parent::setUp(); $this->setMwGlobals( [ 'wgDiff' => false ] ); } - protected function tearDown() { + protected function tearDown() : void { parent::tearDown(); global $wgHooks; @@ -418,14 +419,12 @@ class EchoDiscussionParserTest extends MediaWikiTestCase { 'type' => 'mention-failure', 'agent' => 'Admin', 'section-title' => 'Hello Users', - 'notifyAgent' => true, 'subject-name' => 'Ping', ], [ 'type' => 'mention-failure', 'agent' => 'Admin', 'section-title' => 'Hello Users', - 'notifyAgent' => true, 'subject-name' => 'Po?ng', ], ], @@ -442,14 +441,12 @@ class EchoDiscussionParserTest extends MediaWikiTestCase { 'type' => 'mention', 'agent' => 'Admin', 'section-title' => 'Hello Users', - 'notifyAgent' => null, 'subject-name' => null, ], [ 'type' => 'mention-success', 'agent' => 'Admin', 'section-title' => 'Hello Users', - 'notifyAgent' => true, 'subject-name' => 'Test11', ], ], @@ -466,7 +463,6 @@ class EchoDiscussionParserTest extends MediaWikiTestCase { 'type' => 'mention-failure', 'agent' => 'Admin', 'section-title' => 'Section 2', - 'notifyAgent' => true, 'subject-name' => 'NoUser', ], ], @@ -483,7 +479,6 @@ class EchoDiscussionParserTest extends MediaWikiTestCase { 'type' => 'mention-failure', 'agent' => 'Admin', 'section-title' => 'Section 2', - 'notifyAgent' => true, 'subject-name' => 'NoUser', ], ], @@ -510,14 +505,12 @@ class EchoDiscussionParserTest extends MediaWikiTestCase { 'agent' => 'Admin', 'section-title' => 'Section 1.5', 'subject-name' => null, - 'notifyAgent' => null, ], [ 'type' => 'mention-success', 'agent' => 'Admin', 'section-title' => 'Section 1.5', 'subject-name' => 'Test11', - 'notifyAgent' => true, ], ], ], @@ -534,14 +527,12 @@ class EchoDiscussionParserTest extends MediaWikiTestCase { 'agent' => 'Admin', 'section-title' => 'Section 1.5', 'subject-name' => 'NoUser1.5', - 'notifyAgent' => true, ], [ 'type' => 'mention-failure', 'agent' => 'Admin', 'section-title' => 'Section 2', 'subject-name' => 'NoUser2', - 'notifyAgent' => true, ], ], ], @@ -558,21 +549,18 @@ class EchoDiscussionParserTest extends MediaWikiTestCase { 'agent' => 'Admin', 'section-title' => 'Section 1', 'subject-name' => 'NoUser1', - 'notifyAgent' => true, ], [ 'type' => 'mention-failure', 'agent' => 'Admin', 'section-title' => 'Section 1.75', 'subject-name' => 'NoUser1.75', - 'notifyAgent' => true, ], [ 'type' => 'mention-failure', 'agent' => 'Admin', 'section-title' => 'Section 2', 'subject-name' => 'NoUser2', - 'notifyAgent' => true, ], ], [ @@ -587,7 +575,6 @@ class EchoDiscussionParserTest extends MediaWikiTestCase { 'agent' => 'Admin', 'section-title' => false, 'subject-name' => null, - 'notifyAgent' => null, ] ], ], [ @@ -603,21 +590,18 @@ class EchoDiscussionParserTest extends MediaWikiTestCase { 'agent' => 'Admin', 'section-title' => 'Section 1', 'subject-name' => null, - 'notifyAgent' => null, ], [ 'type' => 'mention-success', 'agent' => 'Admin', 'section-title' => 'Section 1', 'subject-name' => 'Test11', - 'notifyAgent' => true, ], [ 'type' => 'edit-user-talk', 'agent' => 'Admin', 'section-title' => 'Section 1', 'subject-name' => null, - 'notifyAgent' => null, ], ], ], @@ -635,21 +619,18 @@ class EchoDiscussionParserTest extends MediaWikiTestCase { 'agent' => 'Admin', 'section-title' => 'Section 1', 'subject-name' => null, - 'notifyAgent' => null, ], [ 'type' => 'mention-success', 'agent' => 'Admin', 'section-title' => 'Section 1', 'subject-name' => 'Test11', - 'notifyAgent' => true, ], [ 'type' => 'edit-user-talk', 'agent' => 'Admin', 'section-title' => false, 'subject-name' => null, - 'notifyAgent' => null, ], ], ], @@ -666,21 +647,18 @@ class EchoDiscussionParserTest extends MediaWikiTestCase { 'agent' => 'Admin', 'section-title' => 'Section 2', 'subject-name' => null, - 'notifyAgent' => null, ], [ 'type' => 'mention-success', 'agent' => 'Admin', 'section-title' => 'Section 2', 'subject-name' => 'Test11', - 'notifyAgent' => true, ], [ 'type' => 'edit-user-talk', 'agent' => 'Admin', 'section-title' => 'Section 2', 'subject-name' => null, - 'notifyAgent' => null, ], ], ], @@ -697,14 +675,12 @@ class EchoDiscussionParserTest extends MediaWikiTestCase { 'agent' => 'Admin', 'section-title' => false, 'subject-name' => null, - 'notifyAgent' => null, ], [ 'type' => 'mention-success', 'agent' => 'Admin', 'section-title' => false, 'subject-name' => 'Test11', - 'notifyAgent' => true, ], ], ], @@ -729,7 +705,6 @@ class EchoDiscussionParserTest extends MediaWikiTestCase { 'type' => $event->getType(), 'agent' => $event->getAgent()->getName(), 'section-title' => $event->getExtraParam( 'section-title' ), - 'notifyAgent' => $event->getExtraParam( 'notifyAgent' ), 'subject-name' => $event->getExtraParam( 'subject-name' ), ]; return false; @@ -904,7 +879,7 @@ TEXT * @dataProvider provider_extractSections */ public function testExtractSections( $content, $result ) { - $discussionParser = TestingAccessWrapper::newFromClass( 'EchoDiscussionParser' ); + $discussionParser = TestingAccessWrapper::newFromClass( EchoDiscussionParser::class ); $sections = $discussionParser->extractSections( $content ); $this->assertEquals( $result, $sections ); @@ -951,6 +926,7 @@ TEXT private function setupTestRevisionsForEventGeneration( $newId, $oldId, $username, $lang, $pages, $title, $summary = '' ) { + $store = MediaWikiServices::getInstance()->getRevisionStore(); // 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 ); @@ -958,7 +934,8 @@ TEXT // this one allows Mediawiki:xyz pages to be set as messages 'wgUseDatabaseMessages' => true ] ); - $this->overrideMwServices(); + + $this->resetServices(); // 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! @@ -968,9 +945,9 @@ TEXT $template->doEditContent( new WikitextContent( $pageText ), '' ); } - // force i18n messages to be reloaded (from DB, where a new message + // force i18n messages to be reloaded from MessageCache (from DB, where a new message // might have been created as page) - MessageCache::destroyInstance(); + $this->resetServices(); // grab revision excerpts (didn't include them in this src file because // they can be pretty long) @@ -986,7 +963,7 @@ TEXT $property->setAccessible( true ); $property->setValue( $title, $lang ); - // create stub Revision object + // create stub MutableRevisionRecord object $row = [ 'id' => $newId, 'user_text' => $username, @@ -996,16 +973,17 @@ TEXT 'title' => $title, 'comment' => $summary, ]; - $revision = Revision::newFromRow( $row ); + $revision = $store->newMutableRevisionFromArray( $row ); + $userName = $revision->getUser()->getName(); // generate diff between 2 revisions $changes = EchoDiscussionParser::getMachineReadableDiff( $oldText, $newText ); - $output = EchoDiscussionParser::interpretDiff( $changes, $revision->getUserText(), $title ); + $output = EchoDiscussionParser::interpretDiff( $changes, $userName, $title ); // store diff in some local cache var, to circumvent // EchoDiscussionParser::getChangeInterpretationForRevision's attempt to // retrieve parent revision from DB - $class = new ReflectionClass( 'EchoDiscussionParser' ); + $class = new ReflectionClass( EchoDiscussionParser::class ); $property = $class->getProperty( 'revisionInterpretationCache' ); $property->setAccessible( true ); $property->setValue( [ $revision->getId() => $output ] ); @@ -1032,13 +1010,13 @@ TEXT $timestampRegex = EchoDiscussionParser::getTimestampRegex(); $match = preg_match( '/' . $timestampRegex . '/u', $exemplarTimestamp ); - $this->assertEquals( 1, $match ); + $this->assertSame( 1, $match ); } public function testGetTimestampPosition() { $line = 'Hello World. ' . self::getExemplarTimestamp(); $pos = EchoDiscussionParser::getTimestampPosition( $line ); - $this->assertEquals( 13, $pos ); + $this->assertSame( 13, $pos ); } /** @@ -1059,7 +1037,7 @@ TEXT $output = EchoDiscussionParser::getUserFromLine( $line ); if ( $output === false ) { - $this->assertEquals( false, $expectedUser ); + $this->assertFalse( $expectedUser ); } elseif ( is_array( $expectedUser ) ) { // Sometimes testing for correct user detection, // sometimes testing for offset detection @@ -1509,17 +1487,15 @@ TEXT } public function getExemplarTimestamp() { - $title = $this->getMockBuilder( Title::class ) - ->getMock(); + $title = $this->createMock( Title::class ); - $user = $this->getMockBuilder( User::class ) - ->getMock(); + $user = $this->createMock( User::class ); - $options = new ParserOptions; + $options = ParserOptions::newFromAnon(); - global $wgParser; + $parser = MediaWikiServices::getInstance()->getParser(); $exemplarTimestamp = - $wgParser->preSaveTransform( '~~~~~', $title, $user, $options ); + $parser->preSaveTransform( '~~~~~', $title, $user, $options ); return $exemplarTimestamp; } @@ -1708,11 +1684,11 @@ TEXT $two = "===SubZomg===\nHi there\n"; $three = "==Header==\nOh Hai!\n"; - $this->assertEquals( 1, EchoDiscussionParser::getSectionCount( $one ) ); - $this->assertEquals( 2, EchoDiscussionParser::getSectionCount( $one . $two ) ); - $this->assertEquals( 2, EchoDiscussionParser::getSectionCount( $one . $three ) ); - $this->assertEquals( 3, EchoDiscussionParser::getSectionCount( $one . $two . $three ) ); - $this->assertEquals( 30, EchoDiscussionParser::getSectionCount( + $this->assertSame( 1, EchoDiscussionParser::getSectionCount( $one ) ); + $this->assertSame( 2, EchoDiscussionParser::getSectionCount( $one . $two ) ); + $this->assertSame( 2, EchoDiscussionParser::getSectionCount( $one . $three ) ); + $this->assertSame( 3, EchoDiscussionParser::getSectionCount( $one . $two . $three ) ); + $this->assertSame( 30, EchoDiscussionParser::getSectionCount( file_get_contents( __DIR__ . '/revision_txt/637638133.txt' ) ) ); } @@ -1724,8 +1700,8 @@ TEXT 'anonymousUsers' => [ '127.0.0.1' ], ]; - $discussionParser = TestingAccessWrapper::newFromClass( 'EchoDiscussionParser' ); - $this->assertEquals( 4, $discussionParser->getOverallUserMentionsCount( $userMentions ) ); + $discussionParser = TestingAccessWrapper::newFromClass( EchoDiscussionParser::class ); + $this->assertSame( 4, $discussionParser->getOverallUserMentionsCount( $userMentions ) ); } public function provider_getUserMentions() { @@ -1756,7 +1732,7 @@ TEXT */ public function testGetUserMentions( $userLinks, $expectedUserMentions, $agent ) { $title = Title::newFromText( 'Test' ); - $discussionParser = TestingAccessWrapper::newFromClass( 'EchoDiscussionParser' ); + $discussionParser = TestingAccessWrapper::newFromClass( EchoDiscussionParser::class ); $this->assertEquals( $expectedUserMentions, $discussionParser->getUserMentions( $title, $agent, $userLinks ) ); } @@ -1801,8 +1777,8 @@ TEXT ] ); $title = Title::newFromText( 'Test' ); - $discussionParser = TestingAccessWrapper::newFromClass( 'EchoDiscussionParser' ); - $this->assertEquals( 4, $discussionParser->getOverallUserMentionsCount( $discussionParser->getUserMentions( $title, 1, $userLinks ) ) ); + $discussionParser = TestingAccessWrapper::newFromClass( EchoDiscussionParser::class ); + $this->assertSame( 4, $discussionParser->getOverallUserMentionsCount( $discussionParser->getUserMentions( $title, 1, $userLinks ) ) ); } protected function isParserFunctionsInstalled() { diff --git a/Echo/tests/phpunit/EchoDbFactoryTest.php b/Echo/tests/phpunit/EchoDbFactoryTest.php index 337c92d3..1c10c0d0 100644 --- a/Echo/tests/phpunit/EchoDbFactoryTest.php +++ b/Echo/tests/phpunit/EchoDbFactoryTest.php @@ -4,13 +4,13 @@ use Wikimedia\Rdbms\IDatabase; use Wikimedia\Rdbms\ILoadBalancer; /** - * @covers MWEchoDbFactory + * @covers \MWEchoDbFactory */ class MWEchoDbFactoryTest extends MediaWikiTestCase { public function testNewFromDefault() { $db = MWEchoDbFactory::newFromDefault(); - $this->assertInstanceOf( 'MWEchoDbFactory', $db ); + $this->assertInstanceOf( MWEchoDbFactory::class, $db ); return $db; } @@ -27,7 +27,7 @@ class MWEchoDbFactoryTest extends MediaWikiTestCase { * @depends testNewFromDefault */ public function testGetLB( MWEchoDbFactory $db ) { - $reflection = new ReflectionClass( 'MWEchoDbFactory' ); + $reflection = new ReflectionClass( MWEchoDbFactory::class ); $method = $reflection->getMethod( 'getLB' ); $method->setAccessible( true ); $this->assertInstanceOf( ILoadBalancer::class, $method->invoke( $db ) ); diff --git a/Echo/tests/phpunit/EchoSummaryParserTest.php b/Echo/tests/phpunit/EchoSummaryParserTest.php index 357036fc..7fc7a9bf 100644 --- a/Echo/tests/phpunit/EchoSummaryParserTest.php +++ b/Echo/tests/phpunit/EchoSummaryParserTest.php @@ -9,8 +9,9 @@ class EchoSummaryParserTest extends MediaWikiTestCase { 'Jorm', 'Jim Carter', ]; + /** - * @covers EchoSummaryParser::parse + * @covers \EchoSummaryParser::parse * @dataProvider provideParse * * @param string $summary @@ -26,7 +27,7 @@ class EchoSummaryParserTest extends MediaWikiTestCase { $users = $parser->parse( $summary ); foreach ( $users as $name => $user ) { - $this->assertType( User::class, $user ); + $this->assertInstanceof( User::class, $user ); $this->assertEquals( $name, $user->getName() ); } diff --git a/Echo/tests/phpunit/NotifUserTest.php b/Echo/tests/phpunit/NotifUserTest.php index b25f3dc5..11a182d3 100644 --- a/Echo/tests/phpunit/NotifUserTest.php +++ b/Echo/tests/phpunit/NotifUserTest.php @@ -3,7 +3,7 @@ use MediaWiki\MediaWikiServices; /** - * @covers MWEchoNotifUser + * @covers \MWEchoNotifUser * @group Echo */ class MWEchoNotifUserTest extends MediaWikiTestCase { @@ -13,7 +13,7 @@ class MWEchoNotifUserTest extends MediaWikiTestCase { */ private $cache; - protected function setUp() { + protected function setUp() : void { parent::setUp(); $this->cache = new WANObjectCache( [ 'cache' => MediaWikiServices::getInstance()->getMainObjectStash(), @@ -32,7 +32,7 @@ class MWEchoNotifUserTest extends MediaWikiTestCase { $this->assertTrue( $exception, "Got exception" ); $notifUser = MWEchoNotifUser::newFromUser( User::newFromId( 2 ) ); - $this->assertInstanceOf( 'MWEchoNotifUser', $notifUser ); + $this->assertInstanceOf( MWEchoNotifUser::class, $notifUser ); } public function testGetEmailFormat() { @@ -113,7 +113,7 @@ class MWEchoNotifUserTest extends MediaWikiTestCase { $dbResult += [ 'markRead' => true ]; - $gateway = $this->getMockBuilder( 'EchoUserNotificationGateway' ) + $gateway = $this->getMockBuilder( EchoUserNotificationGateway::class ) ->disableOriginalConstructor() ->getMock(); $gateway->expects( $this->any() ) @@ -122,7 +122,7 @@ class MWEchoNotifUserTest extends MediaWikiTestCase { $gateway->expects( $this->any() ) ->method( 'getDB' ) ->will( $this->returnValue( - $this->getMockBuilder( Database::class ) + $this->getMockBuilder( IDatabase::class ) ->disableOriginalConstructor()->getMock() ) ); @@ -130,7 +130,7 @@ class MWEchoNotifUserTest extends MediaWikiTestCase { } public function mockEchoNotificationMapper( array $result = [] ) { - $mapper = $this->getMockBuilder( 'EchoNotificationMapper' ) + $mapper = $this->getMockBuilder( EchoNotificationMapper::class ) ->disableOriginalConstructor() ->getMock(); $mapper->expects( $this->any() ) @@ -147,7 +147,7 @@ class MWEchoNotifUserTest extends MediaWikiTestCase { } protected function mockEchoNotification() { - $notification = $this->getMockBuilder( 'EchoNotification' ) + $notification = $this->getMockBuilder( EchoNotification::class ) ->disableOriginalConstructor() ->getMock(); $notification->expects( $this->any() ) @@ -158,7 +158,7 @@ class MWEchoNotifUserTest extends MediaWikiTestCase { } protected function mockEchoEvent() { - $event = $this->getMockBuilder( 'EchoEvent' ) + $event = $this->getMockBuilder( EchoEvent::class ) ->disableOriginalConstructor() ->getMock(); $event->expects( $this->any() ) diff --git a/Echo/tests/phpunit/NotificationsTest.php b/Echo/tests/phpunit/NotificationsTest.php index 641e6bd0..ab971a97 100644 --- a/Echo/tests/phpunit/NotificationsTest.php +++ b/Echo/tests/phpunit/NotificationsTest.php @@ -1,5 +1,7 @@ <?php +use MediaWiki\MediaWikiServices; + /** * Tests for the built in notification types * @@ -12,7 +14,7 @@ class NotificationsTest extends MediaWikiTestCase { var $sysop; // @codingStandardsIgnoreEnd - protected function setUp() { + protected function setUp() : void { parent::setUp(); $this->sysop = User::newFromName( 'UTSysop' ); $this->setMwGlobals( 'wgUser', $this->sysop ); @@ -32,7 +34,7 @@ class NotificationsTest extends MediaWikiTestCase { } /** - * @covers EchoHooks::onUserGroupsChanged + * @covers \EchoHooks::onUserGroupsChanged */ public function testUserRightsNotif() { $user = new User(); @@ -41,7 +43,9 @@ class NotificationsTest extends MediaWikiTestCase { $context = new DerivativeContext( RequestContext::getMain() ); $context->setUser( $this->sysop ); - $ur = new UserrightsPage(); + $ur = new UserrightsPage( + MediaWikiServices::getInstance()->getPermissionManager() + ); $ur->setContext( $context ); $ur->doSaveUserGroups( $user, [ 'sysop' ], [], 'reason' ); $event = self::getLatestNotification( $user ); diff --git a/Echo/tests/phpunit/TalkPageFunctionalTest.php b/Echo/tests/phpunit/TalkPageFunctionalTest.php index f33e5020..1e6786c5 100644 --- a/Echo/tests/phpunit/TalkPageFunctionalTest.php +++ b/Echo/tests/phpunit/TalkPageFunctionalTest.php @@ -7,49 +7,37 @@ */ class EchoTalkPageFunctionalTest extends ApiTestCase { - /** - * @var \Wikimedia\Rdbms\IDatabase - */ - protected $dbr; - - protected function setUp() { + protected function setUp() : void { parent::setUp(); - $this->dbr = MWEchoDbFactory::getDB( DB_REPLICA ); + $this->db->delete( 'echo_event', '*' ); } /** * 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(); $talkPage = self::$users['uploader']->getUser()->getName(); - // A set of messages which will be inserted - $messages = [ - 'Moar Cowbell', - "I can haz test\n\nplz?", // checks that the parser allows multi-line comments - 'blah blah', - ]; $messageCount = 0; $this->assertCount( $messageCount, $this->fetchAllEvents() ); // Start a talkpage - $content = "== Section 8 ==\n\n" . $this->signedMessage( $editor, $messages[$messageCount] ); + $content = "== Section 8 ==\n\nblah blah ~~~~\n"; $this->editPage( $talkPage, $content, '', NS_USER_TALK ); // Ensure the proper event was created $events = $this->fetchAllEvents(); - $this->assertCount( 1 + $messageCount, $events, 'After initial edit a single event must exist.' ); // +1 is due to 0 index + // +1 is due to 0 index + $this->assertCount( 1 + $messageCount, $events, 'After initial edit a single event must exist.' ); $row = array_shift( $events ); $this->assertEquals( 'edit-user-talk', $row->event_type ); $this->assertEventSectionTitle( 'Section 8', $row ); // Add another message to the talk page $messageCount++; - $content .= $this->signedMessage( $editor, $messages[$messageCount] ); + $content .= "More content ~~~~\n"; $this->editPage( $talkPage, $content, '', NS_USER_TALK ); // Ensure another event was created @@ -61,7 +49,7 @@ class EchoTalkPageFunctionalTest extends ApiTestCase { // Add a new section and a message within it $messageCount++; - $content .= "\n\n== EE ==\n\n" . $this->signedMessage( $editor, $messages[$messageCount] ); + $content .= "\n\n== EE ==\n\nhere we go with a new section ~~~~\n"; $this->editPage( $talkPage, $content, '', NS_USER_TALK ); // Ensure this event has the new section title @@ -80,16 +68,14 @@ class EchoTalkPageFunctionalTest extends ApiTestCase { } /** - * @return \stdClass[] All events in db sorted from oldest to newest + * @return \stdClass[] All non-watchlist events in db sorted from oldest to newest */ protected function fetchAllEvents() { - $res = $this->dbr->select( 'echo_event', [ '*' ], [], __METHOD__, [ 'ORDER BY' => 'event_id ASC' ] ); + $res = $this->db->select( 'echo_event', EchoEvent::selectFields(), [ + 'event_type != "watchlist-change"' + ], __METHOD__, [ 'ORDER BY' => 'event_id ASC' ] ); return iterator_to_array( $res ); } - protected function signedMessage( $name, $content = 'Moar cowbell', $depth = 1 ) { - return str_repeat( ':', $depth ) . " $content [[User:$name|$name]] ([[User talk:$name|$name]]) 00:17, 7 May 2013 (UTC)\n"; - } - } diff --git a/Echo/tests/phpunit/ThankYouEditTest.php b/Echo/tests/phpunit/ThankYouEditTest.php index 5325c5cd..e9f89a99 100644 --- a/Echo/tests/phpunit/ThankYouEditTest.php +++ b/Echo/tests/phpunit/ThankYouEditTest.php @@ -6,7 +6,7 @@ */ class MWEchoThankYouEditTest extends MediaWikiTestCase { - protected function setUp() { + protected function setUp() : void { parent::setUp(); $this->tablesUsed[] = 'echo_event'; $this->tablesUsed[] = 'echo_notification'; @@ -19,7 +19,7 @@ class MWEchoThankYouEditTest extends MediaWikiTestCase { } /** - * @covers \EchoHooks::onPageContentSaveComplete + * @covers \EchoHooks::onPageSaveComplete */ public function testFirstEdit() { // setup @@ -37,11 +37,11 @@ class MWEchoThankYouEditTest extends MediaWikiTestCase { /** @var EchoNotification $notification */ $notification = reset( $notifications ); - $this->assertEquals( 1, $notification->getEvent()->getExtraParam( 'editCount', 'not found' ) ); + $this->assertSame( 1, $notification->getEvent()->getExtraParam( 'editCount', 'not found' ) ); } /** - * @covers \EchoHooks::onPageContentSaveComplete + * @covers \EchoHooks::onPageSaveComplete */ public function testTenthEdit() { // setup @@ -55,6 +55,8 @@ class MWEchoThankYouEditTest extends MediaWikiTestCase { // are not generated for ( $i = 0; $i < 12; $i++ ) { $this->edit( $title, $user, "this is edit #$i" ); + // Reload to reflect deferred update + $user->clearInstanceCache(); } // assertions @@ -64,7 +66,7 @@ class MWEchoThankYouEditTest extends MediaWikiTestCase { /** @var EchoNotification $notification */ $notification = reset( $notifications ); - $this->assertEquals( 10, $notification->getEvent()->getExtraParam( 'editCount', 'not found' ) ); + $this->assertSame( 10, $notification->getEvent()->getExtraParam( 'editCount', 'not found' ) ); } private function edit( Title $title, User $user, $text ) { diff --git a/Echo/tests/phpunit/UserLocatorTest.php b/Echo/tests/phpunit/UserLocatorTest.php index 514c8226..bcf5b47b 100644 --- a/Echo/tests/phpunit/UserLocatorTest.php +++ b/Echo/tests/phpunit/UserLocatorTest.php @@ -2,7 +2,7 @@ /** * @group Database - * @covers EchoUserLocator + * @covers \EchoUserLocator */ class EchoUserLocatorTest extends MediaWikiTestCase { @@ -21,7 +21,7 @@ class EchoUserLocatorTest extends MediaWikiTestCase { } wfGetDB( DB_MASTER )->insert( 'watchlist', $rows, __METHOD__ ); - $event = $this->getMockBuilder( 'EchoEvent' ) + $event = $this->getMockBuilder( EchoEvent::class ) ->disableOriginalConstructor() ->getMock(); $event->expects( $this->any() ) @@ -29,11 +29,7 @@ class EchoUserLocatorTest extends MediaWikiTestCase { ->will( $this->returnValue( $title ) ); $it = EchoUserLocator::locateUsersWatchingTitle( $event, 10 ); - $count = 0; - foreach ( $it as $user ) { - ++$count; - } - $this->assertEquals( 50, $count ); + $this->assertCount( 50, $it ); // @todo assert more than one query was issued } @@ -264,7 +260,7 @@ class EchoUserLocatorTest extends MediaWikiTestCase { } protected function mockEchoEvent() { - return $this->getMockBuilder( 'EchoEvent' ) + return $this->getMockBuilder( EchoEvent::class ) ->disableOriginalConstructor() ->getMock(); } diff --git a/Echo/tests/phpunit/api/ApiEchoMarkReadTest.php b/Echo/tests/phpunit/api/ApiEchoMarkReadTest.php index 9c41ec37..b5a4b6e1 100644 --- a/Echo/tests/phpunit/api/ApiEchoMarkReadTest.php +++ b/Echo/tests/phpunit/api/ApiEchoMarkReadTest.php @@ -4,11 +4,11 @@ * @group medium * @group API * @group Database - * @covers ApiEchoMarkRead + * @covers \ApiEchoMarkRead */ class ApiEchoMarkReadTest extends ApiTestCase { - function getTokens() { + public function getTokens() { return $this->getTokenList( self::$users['sysop'] ); } @@ -29,13 +29,11 @@ class ApiEchoMarkReadTest extends ApiTestCase { $this->assertArrayHasKey( 'count', $result ); $this->assertArrayHasKey( 'rawcount', $result ); - // Alert $this->assertArrayHasKey( 'alert', $result ); $alert = $result['alert']; $this->assertArrayHasKey( 'rawcount', $alert ); $this->assertArrayHasKey( 'count', $alert ); - // Message $this->assertArrayHasKey( 'message', $result ); $message = $result['message']; $this->assertArrayHasKey( 'rawcount', $message ); @@ -59,13 +57,11 @@ class ApiEchoMarkReadTest extends ApiTestCase { $this->assertArrayHasKey( 'count', $result ); $this->assertArrayHasKey( 'rawcount', $result ); - // Alert $this->assertArrayHasKey( 'alert', $result ); $alert = $result['alert']; $this->assertArrayHasKey( 'rawcount', $alert ); $this->assertArrayHasKey( 'count', $alert ); - // Message $this->assertArrayHasKey( 'message', $result ); $message = $result['message']; $this->assertArrayHasKey( 'rawcount', $message ); @@ -89,13 +85,11 @@ class ApiEchoMarkReadTest extends ApiTestCase { $this->assertArrayHasKey( 'count', $result ); $this->assertArrayHasKey( 'rawcount', $result ); - // Alert $this->assertArrayHasKey( 'alert', $result ); $alert = $result['alert']; $this->assertArrayHasKey( 'rawcount', $alert ); $this->assertArrayHasKey( 'count', $alert ); - // Message $this->assertArrayHasKey( 'message', $result ); $message = $result['message']; $this->assertArrayHasKey( 'rawcount', $message ); diff --git a/Echo/tests/phpunit/api/ApiEchoNotificationsTest.php b/Echo/tests/phpunit/api/ApiEchoNotificationsTest.php index cfcf5c90..d430fa12 100644 --- a/Echo/tests/phpunit/api/ApiEchoNotificationsTest.php +++ b/Echo/tests/phpunit/api/ApiEchoNotificationsTest.php @@ -3,7 +3,7 @@ /** * @group medium * @group API - * @covers ApiEchoNotifications + * @covers \ApiEchoNotifications */ class ApiEchoNotificationsTest extends ApiTestCase { @@ -26,7 +26,6 @@ class ApiEchoNotificationsTest extends ApiTestCase { $this->assertArrayHasKey( 'count', $result ); $this->assertArrayHasKey( 'rawcount', $result ); - // Alert $this->assertArrayHasKey( 'alert', $result ); $alert = $result['alert']; $this->assertArrayHasKey( 'list', $alert ); @@ -34,7 +33,6 @@ class ApiEchoNotificationsTest extends ApiTestCase { $this->assertArrayHasKey( 'rawcount', $alert ); $this->assertArrayHasKey( 'count', $alert ); - // Message $this->assertArrayHasKey( 'message', $result ); $message = $result['message']; $this->assertArrayHasKey( 'list', $message ); diff --git a/Echo/tests/phpunit/api/Push/ApiEchoPushSubscriptionsCreateTest.php b/Echo/tests/phpunit/api/Push/ApiEchoPushSubscriptionsCreateTest.php new file mode 100644 index 00000000..5361309d --- /dev/null +++ b/Echo/tests/phpunit/api/Push/ApiEchoPushSubscriptionsCreateTest.php @@ -0,0 +1,50 @@ +<?php + +/** + * @group medium + * @group API + * @group Database + * @covers \EchoPush\Api\ApiEchoPushSubscriptionsCreate + */ +class ApiEchoPushSubscriptionsCreateTest extends ApiTestCase { + + /** @var User */ + private $user; + + public function setUp(): void { + parent::setUp(); + $this->setMwGlobals( 'wgEchoEnablePush', true ); + $this->tablesUsed[] = 'echo_push_subscription'; + $this->tablesUsed[] = 'echo_push_provider'; + $this->user = $this->getTestUser()->getUser(); + $this->createTestData(); + } + + public function testApiCreateSubscription(): void { + $params = [ + 'action' => 'echopushsubscriptions', + 'command' => 'create', + 'provider' => 'fcm', + 'providertoken' => 'ABC123', + ]; + $result = $this->doApiRequestWithToken( $params, null, $this->user ); + $this->assertEquals( 'Success', $result[0]['create']['result'] ); + } + + public function testApiCreateSubscriptionTokenExists(): void { + $params = [ + 'action' => 'echopushsubscriptions', + 'command' => 'create', + 'provider' => 'fcm', + 'providertoken' => 'XYZ789', + ]; + $this->expectException( ApiUsageException::class ); + $this->doApiRequestWithToken( $params, null, $this->user ); + } + + private function createTestData(): void { + $subscriptionManager = EchoServices::getInstance()->getPushSubscriptionManager(); + $subscriptionManager->create( $this->user, 'fcm', 'XYZ789' ); + } + +} diff --git a/Echo/tests/phpunit/api/Push/ApiEchoPushSubscriptionsDeleteTest.php b/Echo/tests/phpunit/api/Push/ApiEchoPushSubscriptionsDeleteTest.php new file mode 100644 index 00000000..f2ec0d66 --- /dev/null +++ b/Echo/tests/phpunit/api/Push/ApiEchoPushSubscriptionsDeleteTest.php @@ -0,0 +1,48 @@ +<?php + +/** + * @group medium + * @group API + * @group Database + * @covers \EchoPush\Api\ApiEchoPushSubscriptionsDelete + */ +class ApiEchoPushSubscriptionsDeleteTest extends ApiTestCase { + + /** @var User */ + private $user; + + public function setUp(): void { + parent::setUp(); + $this->setMwGlobals( 'wgEchoEnablePush', true ); + $this->tablesUsed[] = 'echo_push_subscription'; + $this->tablesUsed[] = 'echo_push_provider'; + $this->user = $this->getTestUser()->getUser(); + $this->createTestData(); + } + + public function testApiDeleteSubscription(): void { + $params = [ + 'action' => 'echopushsubscriptions', + 'command' => 'delete', + 'providertoken' => 'XYZ789', + ]; + $result = $this->doApiRequestWithToken( $params, null, $this->user ); + $this->assertEquals( 'Success', $result[0]['delete']['result'] ); + } + + public function testApiDeleteSubscriptionNotFound(): void { + $params = [ + 'action' => 'echopushsubscriptions', + 'command' => 'delete', + 'providertoken' => 'ABC123', + ]; + $this->expectException( ApiUsageException::class ); + $this->doApiRequestWithToken( $params, null, $this->user ); + } + + private function createTestData(): void { + $subscriptionManager = EchoServices::getInstance()->getPushSubscriptionManager(); + $subscriptionManager->create( $this->user, 'fcm', 'XYZ789' ); + } + +} diff --git a/Echo/tests/phpunit/api/Push/ApiEchoPushSubscriptionsTest.php b/Echo/tests/phpunit/api/Push/ApiEchoPushSubscriptionsTest.php new file mode 100644 index 00000000..857464a8 --- /dev/null +++ b/Echo/tests/phpunit/api/Push/ApiEchoPushSubscriptionsTest.php @@ -0,0 +1,22 @@ +<?php + +/** + * @group medium + * @group API + * @covers \EchoPush\Api\ApiEchoPushSubscriptions + */ +class ApiEchoPushSubscriptionsTest extends ApiTestCase { + + public function testRequiresToken(): void { + $this->setMwGlobals( 'wgEchoEnablePush', true ); + $params = [ + 'action' => 'echopushsubscriptions', + 'command' => 'create', + 'platform' => 'apns', + 'platformtoken' => 'ABC123', + ]; + $this->expectException( ApiUsageException::class ); + $this->doApiRequest( $params ); + } + +} diff --git a/Echo/tests/phpunit/cache/TitleLocalCacheTest.php b/Echo/tests/phpunit/cache/TitleLocalCacheTest.php index fdd722d3..c046b6ba 100644 --- a/Echo/tests/phpunit/cache/TitleLocalCacheTest.php +++ b/Echo/tests/phpunit/cache/TitleLocalCacheTest.php @@ -3,7 +3,7 @@ use Wikimedia\TestingAccessWrapper; /** - * @covers EchoTitleLocalCache + * @covers \EchoTitleLocalCache * @group Database */ class EchoTitleLocalCacheTest extends MediaWikiTestCase { @@ -65,7 +65,7 @@ class EchoTitleLocalCacheTest extends MediaWikiTestCase { $cache->add( 3 ); $cache->clearAll(); - $this->assertSame( null, $cache->get( 1 ), 'Cache was cleared' ); + $this->assertNull( $cache->get( 1 ), 'Cache was cleared' ); // Lookups batch was cleared $cache->expects( $this->exactly( 1 ) )->method( 'resolve' ) diff --git a/Echo/tests/phpunit/controller/NotificationControllerTest.php b/Echo/tests/phpunit/controller/NotificationControllerTest.php index 9e497024..c7bfb064 100644 --- a/Echo/tests/phpunit/controller/NotificationControllerTest.php +++ b/Echo/tests/phpunit/controller/NotificationControllerTest.php @@ -1,7 +1,7 @@ <?php /** - * @covers EchoNotificationController + * @covers \EchoNotificationController */ class NotificationControllerTest extends MediaWikiTestCase { @@ -54,7 +54,7 @@ class NotificationControllerTest extends MediaWikiTestCase { [ [ 123 ] ], // event user locator config [ - [ 'EchoUserLocator::locateFromEventExtra', [ 'other-user' ] ], + [ [ EchoUserLocator::class, 'locateFromEventExtra' ], [ 'other-user' ] ], ], // additional setup function ( $test, $event ) { @@ -79,7 +79,7 @@ class NotificationControllerTest extends MediaWikiTestCase { ], ] ); - $event = $this->getMockBuilder( 'EchoEvent' ) + $event = $this->getMockBuilder( EchoEvent::class ) ->disableOriginalConstructor() ->getMock(); $event->expects( $this->any() ) @@ -97,7 +97,7 @@ class NotificationControllerTest extends MediaWikiTestCase { public function testEvaluateUserLocatorPassesParameters() { $test = $this; $callback = function ( $event, $firstOption, $secondOption ) use ( $test ) { - $test->assertInstanceOf( 'EchoEvent', $event ); + $test->assertInstanceOf( EchoEvent::class, $event ); $test->assertEquals( 'first', $firstOption ); $test->assertEquals( 'second', $secondOption ); @@ -157,7 +157,7 @@ class NotificationControllerTest extends MediaWikiTestCase { ], ] ); - $event = $this->getMockBuilder( 'EchoEvent' ) + $event = $this->getMockBuilder( EchoEvent::class ) ->disableOriginalConstructor() ->getMock(); $event->expects( $this->any() ) @@ -173,7 +173,7 @@ class NotificationControllerTest extends MediaWikiTestCase { } public function testDoesNotDeliverDisabledEvent() { - $event = $this->getMockBuilder( 'EchoEvent' ) + $event = $this->getMockBuilder( EchoEvent::class ) ->disableOriginalConstructor() ->getMock(); $event->expects( $this->any() ) @@ -197,45 +197,43 @@ class NotificationControllerTest extends MediaWikiTestCase { 'bar', // default notification types configuration [ 'web' => true ], - // type-specific + // per-category notification type availability + [ + 'f' => [ 'email' => true ] + ], + // event types [ 'foo' => [ - 'notify-type-availability' => [ 'email' => true ], + 'category' => 'f', ], + 'bar' => [ + 'category' => 'b', + ] ], ], [ - 'Overrides `all` configuration with event type configuration', + 'Overrides `all` configuration with event category configuration', // expected result [ 'web' ], // event type 'foo', // default notification types configuration [ 'web' => true, 'email' => true ], - // type-specific + // per-category notification type availability + [ + 'f' => [ 'email' => false ], + 'b' => [ 'sms' => true ], + ], + // event types [ 'foo' => [ - 'notify-type-availability' => [ 'email' => false ], + 'category' => 'f', ], 'bar' => [ - 'notify-type-availability' => [ 'sms' => true ], + 'category' => 'b', ], ], - ], - - [ - 'Uses all configuration when notify-type-availability not set at all', - // expected result - [ 'web', 'email' ], - // event type - 'baz', - // default notification types configuration - [ 'web' => true, 'email' => true ], - // type-specific - [ - 'baz' => [], - ], ] ]; } @@ -243,10 +241,22 @@ class NotificationControllerTest extends MediaWikiTestCase { /** * @dataProvider getEventNotifyTypesProvider */ - public function testGetEventNotifyTypes( $message, $expect, $type, array $defaultNotifyTypeAvailability, array $notifications ) { + public function testGetEventNotifyTypes( + $message, + $expect, + $type, + array $defaultNotifyTypeAvailability, + array $notifyTypeAvailabilityByCategory, + array $notifications + ) { $this->setMwGlobals( [ 'wgDefaultNotifyTypeAvailability' => $defaultNotifyTypeAvailability, + 'wgNotifyTypeAvailabilityByCategory' => $notifyTypeAvailabilityByCategory, 'wgEchoNotifications' => $notifications, + 'wgEchoNotificationCategories' => array_fill_keys( + array_keys( $notifyTypeAvailabilityByCategory ), + [ 'priority' => 4 ] + ), ] ); $result = EchoNotificationController::getEventNotifyTypes( $type ); $this->assertEquals( $expect, $result, $message ); diff --git a/Echo/tests/phpunit/formatters/PresentationModelSectionTest.php b/Echo/tests/phpunit/formatters/PresentationModelSectionTest.php new file mode 100644 index 00000000..b17af684 --- /dev/null +++ b/Echo/tests/phpunit/formatters/PresentationModelSectionTest.php @@ -0,0 +1,97 @@ +<?php + +/** + * @group Database + */ +class EchoPresentationModelSectionTest extends MediaWikiTestCase { + + /** + * @covers \EchoPresentationModelSection::getTruncatedSectionTitle + */ + public function testGetTruncatedSectionTitle_short() { + $lang = Language::factory( 'en' ); + $section = new EchoPresentationModelSection( + $this->makeEvent( [ 'event_extra' => serialize( [ 'section-title' => 'asdf' ] ) ] ), + $this->getTestUser()->getUser(), + $lang + ); + + $this->assertEquals( $lang->embedBidi( 'asdf' ), $section->getTruncatedSectionTitle() ); + } + + /** + * @covers \EchoPresentationModelSection::getTruncatedSectionTitle + */ + public function testGetTruncatedSectionTitle_long() { + $lang = Language::factory( 'en' ); + $section = new EchoPresentationModelSection( + $this->makeEvent( [ 'event_extra' => serialize( [ 'section-title' => str_repeat( 'a', 100 ) ] ) ] ), + $this->getTestUser()->getUser(), + $lang + ); + + $this->assertEquals( + $lang->embedBidi( str_repeat( 'a', 50 ) . '...' ), + $section->getTruncatedSectionTitle() + ); + } + + /** + * @covers \EchoPresentationModelSection::getTitleWithSection + */ + public function testGetTitleWithSection() { + $page = $this->getExistingTestPage(); + $section = new EchoPresentationModelSection( + $this->makeEvent( [ + 'event_page_id' => $page->getId(), + 'event_extra' => serialize( [ 'section-title' => 'asdf' ] ), + ] ), + $this->getTestUser()->getUser(), + Language::factory( 'en' ) + ); + + $titleWithSection = $section->getTitleWithSection(); + + $this->assertEquals( 'asdf', $titleWithSection->getFragment() ); + $this->assertEquals( $page->getTitle()->getPrefixedText(), $titleWithSection->getPrefixedText() ); + } + + /** + * @covers \EchoPresentationModelSection::exists + */ + public function testExists_no() { + $section = new EchoPresentationModelSection( + $this->makeEvent(), + $this->getTestUser()->getUser(), + Language::factory( 'en' ) + ); + + $this->assertFalse( $section->exists() ); + } + + /** + * @covers \EchoPresentationModelSection::exists + */ + public function testExists_yes() { + $section = new EchoPresentationModelSection( + $this->makeEvent( [ 'event_extra' => serialize( [ 'section-title' => 'asdf' ] ) ] ), + $this->getTestUser()->getUser(), + Language::factory( 'en' ) + ); + + $this->assertTrue( $section->exists() ); + } + + private function makeEvent( $config = [] ) { + $agent = $this->getTestSysop()->getUser(); + return EchoEvent::newFromRow( (object)array_merge( [ + 'event_id' => 12, + 'event_type' => 'welcome', + 'event_variant' => '1', + 'event_page_id' => 1, + 'event_deleted' => 0, + 'event_agent_id' => $agent->getId(), + 'event_extra' => '', + ], $config ) ); + } +} diff --git a/Echo/tests/phpunit/integration/EchoServicesTest.php b/Echo/tests/phpunit/integration/EchoServicesTest.php new file mode 100644 index 00000000..60c46855 --- /dev/null +++ b/Echo/tests/phpunit/integration/EchoServicesTest.php @@ -0,0 +1,33 @@ +<?php + +use EchoPush\NotificationServiceClient; +use EchoPush\SubscriptionManager; +use MediaWiki\MediaWikiServices; + +/** @covers EchoServices */ +class EchoServicesTest extends MediaWikiIntegrationTestCase { + + /** @var EchoServices */ + private $echoServices; + + public function setUp(): void { + parent::setUp(); + $this->echoServices = EchoServices::getInstance(); + } + + public function testWrap(): void { + $services = EchoServices::wrap( MediaWikiServices::getInstance() ); + $this->assertInstanceOf( EchoServices::class, $services ); + } + + public function testGetPushNotificationServiceClient(): void { + $serviceClient = $this->echoServices->getPushNotificationServiceClient(); + $this->assertInstanceOf( NotificationServiceClient::class, $serviceClient ); + } + + public function testGetPushSubscriptionManager(): void { + $subscriptionManager = $this->echoServices->getPushSubscriptionManager(); + $this->assertInstanceOf( SubscriptionManager::class, $subscriptionManager ); + } + +} diff --git a/Echo/tests/phpunit/integration/Push/NotificationServiceClientTest.php b/Echo/tests/phpunit/integration/Push/NotificationServiceClientTest.php new file mode 100644 index 00000000..26cb868d --- /dev/null +++ b/Echo/tests/phpunit/integration/Push/NotificationServiceClientTest.php @@ -0,0 +1,16 @@ +<?php + +use Wikimedia\TestingAccessWrapper; + +/** @covers \EchoPush\NotificationServiceClient */ +class NotificationServiceClientTest extends MediaWikiIntegrationTestCase { + + public function testConstructRequest(): void { + $client = EchoServices::getInstance()->getPushNotificationServiceClient(); + $client = TestingAccessWrapper::newFromObject( $client ); + $payload = [ 'deviceTokens' => [ 'foo' ], 'messageType' => 'checkEchoV1' ]; + $request = $client->constructRequest( 'fcm', $payload ); + $this->assertInstanceOf( MWHttpRequest::class, $request ); + } + +} diff --git a/Echo/tests/phpunit/integration/Push/PushNotifierTest.php b/Echo/tests/phpunit/integration/Push/PushNotifierTest.php new file mode 100644 index 00000000..1e60f230 --- /dev/null +++ b/Echo/tests/phpunit/integration/Push/PushNotifierTest.php @@ -0,0 +1,20 @@ +<?php + +use EchoPush\NotificationRequestJob; +use EchoPush\PushNotifier; +use Wikimedia\TestingAccessWrapper; + +/** @covers \EchoPush\PushNotifier */ +class PushNotifierTest extends MediaWikiIntegrationTestCase { + + public function testCreateJob(): void { + $notifier = TestingAccessWrapper::newFromClass( PushNotifier::class ); + $user = $this->getTestUser()->getUser(); + $centralId = CentralIdLookup::factory()->centralIdFromLocalUser( $user ); + $job = $notifier->createJob( $user ); + $this->assertInstanceOf( NotificationRequestJob::class, $job ); + $this->assertSame( 'EchoPushNotificationRequest', $job->getType() ); + $this->assertSame( $centralId, $job->getParams()['centralId'] ); + } + +} diff --git a/Echo/tests/phpunit/integration/Push/SubscriptionManagerTest.php b/Echo/tests/phpunit/integration/Push/SubscriptionManagerTest.php new file mode 100644 index 00000000..7a9f32f1 --- /dev/null +++ b/Echo/tests/phpunit/integration/Push/SubscriptionManagerTest.php @@ -0,0 +1,27 @@ +<?php + +/** + * @group Database + * @covers \EchoPush\SubscriptionManager + */ +class SubscriptionManagerTest extends MediaWikiIntegrationTestCase { + + public function setUp(): void { + parent::setUp(); + $this->tablesUsed[] = 'echo_push_subscription'; + $this->tablesUsed[] = 'echo_push_provider'; + } + + public function testManagePushSubscriptions(): void { + $subscriptionManager = EchoServices::getInstance()->getPushSubscriptionManager(); + $user = $this->getTestUser()->getUser(); + $centralId = CentralIdLookup::factory()->centralIdFromLocalUser( $user ); + $subscriptionManager->create( $user, 'test', 'ABC123' ); + $subscriptions = $subscriptionManager->getSubscriptionsForUser( $centralId ); + $this->assertCount( 1, $subscriptions ); + $subscriptionManager->delete( $user, 'ABC123' ); + $subscriptions = $subscriptionManager->getSubscriptionsForUser( $centralId ); + $this->assertCount( 0, $subscriptions ); + } + +} diff --git a/Echo/tests/phpunit/maintenance/SupressionMaintenanceTest.php b/Echo/tests/phpunit/maintenance/SupressionMaintenanceTest.php index 029be88f..31149b46 100644 --- a/Echo/tests/phpunit/maintenance/SupressionMaintenanceTest.php +++ b/Echo/tests/phpunit/maintenance/SupressionMaintenanceTest.php @@ -1,8 +1,10 @@ <?php +use PHPUnit\Framework\TestCase; + /** * @group Echo - * @covers EchoSuppressionRowUpdateGenerator + * @covers \EchoSuppressionRowUpdateGenerator */ class SuppressionMaintenanceTest extends MediaWikiTestCase { @@ -101,8 +103,11 @@ class SuppressionMaintenanceTest extends MediaWikiTestCase { } protected static function attachTitleFor( $id, $providedText, $providedNamespace ) { - return function ( $test, $gen ) use ( $id, $providedText, $providedNamespace ) { - $title = $test->getMock( 'Title' ); + return function ( + TestCase $test, + EchoSuppressionRowUpdateGenerator $gen + ) use ( $id, $providedText, $providedNamespace ) { + $title = $test->createMock( Title::class ); $title->expects( $test->any() ) ->method( 'getArticleId' ) ->will( $test->returnValue( $id ) ); @@ -110,11 +115,7 @@ class SuppressionMaintenanceTest extends MediaWikiTestCase { $titles = [ $providedNamespace => [ $providedText => $title ] ]; $gen->setNewTitleFromNsAndText( function ( $namespace, $text ) use ( $titles ) { - if ( isset( $titles[$namespace][$text] ) ) { - return $titles[$namespace][$text]; - } - - return Title::makeTitleSafe( $namespace, $text ); + return $titles[$namespace][$text] ?? Title::makeTitleSafe( $namespace, $text ); } ); }; } @@ -122,7 +123,7 @@ class SuppressionMaintenanceTest extends MediaWikiTestCase { /** * @dataProvider provider_updateRow */ - public function testUpdateRow( $message, $expected, $input, $callable = null ) { + public function testUpdateRow( $message, array $expected, array $input, callable $callable = null ) { $gen = new EchoSuppressionRowUpdateGenerator; if ( $callable ) { call_user_func( $callable, $this, $gen ); diff --git a/Echo/tests/phpunit/mapper/EchoExecuteFirstArgumentStub.php b/Echo/tests/phpunit/mapper/EchoExecuteFirstArgumentStub.php index 1e2889e7..8ecf0609 100644 --- a/Echo/tests/phpunit/mapper/EchoExecuteFirstArgumentStub.php +++ b/Echo/tests/phpunit/mapper/EchoExecuteFirstArgumentStub.php @@ -1,18 +1,22 @@ <?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' ); +use PHPUnit\Framework\MockObject\Invocation; +use PHPUnit\Framework\MockObject\Invocation\StaticInvocation; +use PHPUnit\Framework\MockObject\Stub\Stub; + +class EchoExecuteFirstArgumentStub implements Stub { + public function invoke( Invocation $invocation ) { + if ( !$invocation instanceof StaticInvocation ) { + throw new PHPUnit\Framework\Exception( 'wrong invocation type' ); } if ( !$invocation->arguments ) { - throw new PHPUnit_Framework_Exception( 'Method call must have an argument' ); + throw new PHPUnit\Framework\Exception( 'Method call must have an argument' ); } return call_user_func( reset( $invocation->arguments ) ); } - public function toString() { + public function toString() : string { 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 e81e183d..f42615f6 100644 --- a/Echo/tests/phpunit/mapper/EventMapperTest.php +++ b/Echo/tests/phpunit/mapper/EventMapperTest.php @@ -1,10 +1,20 @@ <?php +use Wikimedia\Rdbms\IDatabase; + /** - * @covers EchoEventMapper + * @group Database + * @covers \EchoEventMapper */ class EchoEventMapperTest extends MediaWikiTestCase { + protected function setUp() : void { + parent::setUp(); + $this->tablesUsed[] = 'echo_event'; + $this->tablesUsed[] = 'echo_notification'; + $this->tablesUsed[] = 'echo_target_page'; + } + public function provideDataTestInsert() { return [ [ @@ -16,12 +26,7 @@ class EchoEventMapperTest extends MediaWikiTestCase { 'successful insert with insert id = 2', [ 'insert' => true, 'insertId' => 2 ], 2 - ], - [ - 'unsuccessful insert', - [ 'insert' => false, 'insertId' => 2 ], - false - ], + ] ]; } @@ -55,12 +60,9 @@ class EchoEventMapperTest extends MediaWikiTestCase { ) ); $res = $eventMapper->fetchById( 1 ); - $this->assertInstanceOf( 'EchoEvent', $res ); + $this->assertInstanceOf( EchoEvent::class, $res ); } - /** - * @expectedException MWException - */ public function testUnsuccessfulFetchById() { $eventMapper = new EchoEventMapper( $this->mockMWEchoDbFactory( @@ -69,15 +71,15 @@ class EchoEventMapperTest extends MediaWikiTestCase { ] ) ); - $res = $eventMapper->fetchById( 1 ); - $this->assertInstanceOf( 'EchoEvent', $res ); + $this->expectException( MWException::class ); + $eventMapper->fetchById( 1 ); } /** - * Mock object of EchoEvent + * @return EchoEvent */ protected function mockEchoEvent() { - $event = $this->getMockBuilder( 'EchoEvent' ) + $event = $this->getMockBuilder( EchoEvent::class ) ->disableOriginalConstructor() ->getMock(); $event->expects( $this->any() ) @@ -88,10 +90,10 @@ class EchoEventMapperTest extends MediaWikiTestCase { } /** - * Mock object of MWEchoDbFactory + * @return MWEchoDbFactory */ protected function mockMWEchoDbFactory( $dbResult ) { - $dbFactory = $this->getMockBuilder( 'MWEchoDbFactory' ) + $dbFactory = $this->getMockBuilder( MWEchoDbFactory::class ) ->disableOriginalConstructor() ->getMock(); $dbFactory->expects( $this->any() ) @@ -102,8 +104,7 @@ class EchoEventMapperTest extends MediaWikiTestCase { } /** - * Returns a mock database object - * @return \Wikimedia\Rdbms\IDatabase + * @return IDatabase */ protected function mockDb( array $dbResult ) { $dbResult += [ @@ -112,9 +113,7 @@ class EchoEventMapperTest extends MediaWikiTestCase { 'select' => '', 'selectRow' => '' ]; - $db = $this->getMockBuilder( 'DatabaseMysqli' ) - ->disableOriginalConstructor() - ->getMock(); + $db = $this->createMock( IDatabase::class ); $db->expects( $this->any() ) ->method( 'insert' ) ->will( $this->returnValue( $dbResult['insert'] ) ); @@ -131,4 +130,39 @@ class EchoEventMapperTest extends MediaWikiTestCase { return $db; } + /** + * @covers \EchoEventMapper::fetchIdsByPage + */ + public function testFetchByPage() { + $user = $this->getTestUser()->getUser(); + $page = $this->getExistingTestPage(); + + // Create a notification that is not associated with any page + EchoEvent::create( [ + 'type' => 'welcome', + 'agent' => $user, + ] ); + + // Create a notification with a title + $eventWithTitle = EchoEvent::create( [ + 'type' => 'welcome', + 'agent' => $user, + 'title' => $page->getTitle() + ] ); + + // Create a notification with a target-page + $eventWithTargetPage = EchoEvent::create( [ + 'type' => 'welcome', + 'agent' => $user, + 'extra' => [ 'target-page' => $page->getId() ] + ] ); + + $eventMapper = new EchoEventMapper(); + + $this->assertArrayEquals( + [ $eventWithTitle->getId(), $eventWithTargetPage->getId() ], + $eventMapper->fetchIdsByPage( $page->getId() ) + ); + } + } diff --git a/Echo/tests/phpunit/mapper/NotificationMapperTest.php b/Echo/tests/phpunit/mapper/NotificationMapperTest.php index 62359a9c..27a2698a 100644 --- a/Echo/tests/phpunit/mapper/NotificationMapperTest.php +++ b/Echo/tests/phpunit/mapper/NotificationMapperTest.php @@ -1,7 +1,9 @@ <?php +use Wikimedia\Rdbms\IDatabase; + /** - * @covers EchoNotificationMapper + * @covers \EchoNotificationMapper */ class EchoNotificationMapperTest extends MediaWikiTestCase { @@ -31,9 +33,7 @@ class EchoNotificationMapperTest extends MediaWikiTestCase { 'notification_user' => 1, 'notification_timestamp' => '20140615101010', 'notification_read_timestamp' => '', - 'notification_bundle_base' => 1, 'notification_bundle_hash' => 'testhash', - 'notification_bundle_display_hash' => 'testdisplayhash' ] ]; $notifMapper = new EchoNotificationMapper( $this->mockMWEchoDbFactory( [ 'select' => $dbResult ] ) ); @@ -42,10 +42,10 @@ class EchoNotificationMapperTest extends MediaWikiTestCase { $notifMapper = new EchoNotificationMapper( $this->mockMWEchoDbFactory( [ 'select' => $dbResult ] ) ); $res = $notifMapper->fetchUnreadByUser( $this->mockUser(), 10, null, '', [ 'test_event' ] ); - $this->assertInternalType( 'array', $res ); + $this->assertIsArray( $res ); $this->assertNotEmpty( $res ); foreach ( $res as $row ) { - $this->assertInstanceOf( 'EchoNotification', $row ); + $this->assertInstanceOf( EchoNotification::class, $row ); } } @@ -69,9 +69,7 @@ class EchoNotificationMapperTest extends MediaWikiTestCase { 'notification_user' => 1, 'notification_timestamp' => '20140615101010', 'notification_read_timestamp' => '20140616101010', - 'notification_bundle_base' => 1, 'notification_bundle_hash' => 'testhash', - 'notification_bundle_display_hash' => 'testdisplayhash' ] ]; @@ -93,10 +91,10 @@ class EchoNotificationMapperTest extends MediaWikiTestCase { ) ); $res = $notifMapper->fetchByUser( $this->mockUser(), 10, '', [ 'test_event' ] ); - $this->assertInternalType( 'array', $res ); + $this->assertIsArray( $res ); $this->assertNotEmpty( $res ); foreach ( $res as $row ) { - $this->assertInstanceOf( 'EchoNotification', $row ); + $this->assertInstanceOf( EchoNotification::class, $row ); } $notifMapper = new EchoNotificationMapper( $this->mockMWEchoDbFactory( [] ) ); @@ -104,34 +102,6 @@ class EchoNotificationMapperTest extends MediaWikiTestCase { $this->assertEmpty( $res ); } - public function testFetchNewestByUserBundleHash() { - // Unsuccessful select - $notifMapper = new EchoNotificationMapper( $this->mockMWEchoDbFactory( [ 'selectRow' => false ] ) ); - $res = $notifMapper->fetchNewestByUserBundleHash( User::newFromId( 1 ), 'testhash' ); - $this->assertFalse( $res ); - - // Successful select - $dbResult = (object)[ - 'event_id' => 1, - 'event_type' => 'test', - 'event_variant' => '', - 'event_extra' => '', - 'event_page_id' => '', - 'event_agent_id' => '', - 'event_agent_ip' => '', - 'event_deleted' => 0, - 'notification_user' => 1, - 'notification_timestamp' => '20140615101010', - 'notification_read_timestamp' => '20140616101010', - 'notification_bundle_base' => 1, - 'notification_bundle_hash' => 'testhash', - 'notification_bundle_display_hash' => 'testdisplayhash' - ]; - $notifMapper = new EchoNotificationMapper( $this->mockMWEchoDbFactory( [ 'selectRow' => $dbResult ] ) ); - $row = $notifMapper->fetchNewestByUserBundleHash( User::newFromId( 1 ), 'testdisplayhash' ); - $this->assertInstanceOf( 'EchoNotification', $row ); - } - public function testFetchByUserOffset() { // Unsuccessful select $notifMapper = new EchoNotificationMapper( $this->mockMWEchoDbFactory( [ 'selectRow' => false ] ) ); @@ -151,24 +121,37 @@ class EchoNotificationMapperTest extends MediaWikiTestCase { 'notification_user' => 1, 'notification_timestamp' => '20140615101010', 'notification_read_timestamp' => '20140616101010', - 'notification_bundle_base' => 1, 'notification_bundle_hash' => 'testhash', - 'notification_bundle_display_hash' => 'testdisplayhash' ]; $notifMapper = new EchoNotificationMapper( $this->mockMWEchoDbFactory( [ 'selectRow' => $dbResult ] ) ); $row = $notifMapper->fetchByUserOffset( User::newFromId( 1 ), 500 ); - $this->assertInstanceOf( 'EchoNotification', $row ); + $this->assertInstanceOf( EchoNotification::class, $row ); } public function testDeleteByUserEventOffset() { $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 = $this->createMock( IDatabase::class ); + $makeResultRows = function ( $eventIds ) { + return new ArrayIterator( array_map( function ( $eventId ) { + return (object)[ 'notification_event' => $eventId ]; + }, $eventIds ) ); + }; + $mockDb->expects( $this->exactly( 4 ) ) + ->method( 'select' ) + ->willReturnOnConsecutiveCalls( + $this->returnValue( $makeResultRows( [ 1, 2, 3, 5 ] ) ), + $this->returnValue( $makeResultRows( [ 8, 13, 21, 34 ] ) ), + $this->returnValue( $makeResultRows( [ 55, 89 ] ) ), + $this->returnValue( $makeResultRows( [] ) ) + ); $mockDb->expects( $this->exactly( 3 ) ) + ->method( 'selectFieldValues' ) + ->willReturnOnConsecutiveCalls( + $this->returnValue( [] ), + $this->returnValue( [ 13, 21 ] ), + $this->returnValue( [ 55 ] ) + ); + $mockDb->expects( $this->exactly( 7 ) ) ->method( 'delete' ) ->withConsecutive( [ @@ -182,12 +165,32 @@ class EchoNotificationMapperTest extends MediaWikiTestCase { $this->anything() ], [ + $this->equalTo( 'echo_event' ), + $this->equalTo( [ 'event_id' => [ 13, 21 ] ] ), + $this->anything() + ], + [ + $this->equalTo( 'echo_target_page' ), + $this->equalTo( [ 'etp_event' => [ 13, 21 ] ] ), + $this->anything() + ], + [ $this->equalTo( 'echo_notification' ), $this->equalTo( [ 'notification_user' => 1, 'notification_event' => [ 55, 89 ] ] ), $this->anything() + ], + [ + $this->equalTo( 'echo_event' ), + $this->equalTo( [ 'event_id' => [ 55 ] ] ), + $this->anything() + ], + [ + $this->equalTo( 'echo_target_page' ), + $this->equalTo( [ 'etp_event' => [ 55 ] ] ), + $this->anything() ] ) - ->will( $this->returnValue( true ) ); + ->willReturn( true ); $notifMapper = new EchoNotificationMapper( $this->mockMWEchoDbFactory( $mockDb ) ); $this->assertTrue( $notifMapper->deleteByUserEventOffset( User::newFromId( 1 ), 500 ) ); @@ -197,7 +200,7 @@ class EchoNotificationMapperTest extends MediaWikiTestCase { * Mock object of User */ protected function mockUser() { - $user = $this->getMockBuilder( 'User' ) + $user = $this->getMockBuilder( User::class ) ->disableOriginalConstructor() ->getMock(); $user->expects( $this->any() ) @@ -217,7 +220,7 @@ class EchoNotificationMapperTest extends MediaWikiTestCase { * Mock object of EchoNotification */ protected function mockEchoNotification() { - $event = $this->getMockBuilder( 'EchoNotification' ) + $event = $this->getMockBuilder( EchoNotification::class ) ->disableOriginalConstructor() ->getMock(); $event->expects( $this->any() ) @@ -233,7 +236,7 @@ class EchoNotificationMapperTest extends MediaWikiTestCase { */ protected function mockMWEchoDbFactory( $dbResultOrMockDb ) { $mockDb = is_array( $dbResultOrMockDb ) ? $this->mockDb( $dbResultOrMockDb ) : $dbResultOrMockDb; - $dbFactory = $this->getMockBuilder( 'MWEchoDbFactory' ) + $dbFactory = $this->getMockBuilder( MWEchoDbFactory::class ) ->disableOriginalConstructor() ->getMock(); $dbFactory->expects( $this->any() ) @@ -255,9 +258,7 @@ class EchoNotificationMapperTest extends MediaWikiTestCase { 'delete' => '' ]; - $db = $this->getMockBuilder( 'DatabaseMysqli' ) - ->disableOriginalConstructor() - ->getMock(); + $db = $this->createMock( IDatabase::class ); $db->expects( $this->any() ) ->method( 'insert' ) ->will( $this->returnValue( $dbResult['insert'] ) ); @@ -271,7 +272,7 @@ class EchoNotificationMapperTest extends MediaWikiTestCase { ->method( 'selectRow' ) ->will( $this->returnValue( $dbResult['selectRow'] ) ); $db->expects( $this->any() ) - ->method( 'onTransactionIdle' ) + ->method( 'onTransactionCommitOrIdle' ) ->will( new EchoExecuteFirstArgumentStub ); return $db; diff --git a/Echo/tests/phpunit/model/NotificationTest.php b/Echo/tests/phpunit/model/NotificationTest.php index 92522303..92727589 100644 --- a/Echo/tests/phpunit/model/NotificationTest.php +++ b/Echo/tests/phpunit/model/NotificationTest.php @@ -1,7 +1,7 @@ <?php /** - * @covers EchoNotification + * @covers \EchoNotification */ class EchoNotificationTest extends MediaWikiTestCase { @@ -9,14 +9,14 @@ class EchoNotificationTest extends MediaWikiTestCase { $row = $this->mockNotificationRow() + $this->mockEventRow(); $notif = EchoNotification::newFromRow( (object)$row ); - $this->assertInstanceOf( 'EchoNotification', $notif ); + $this->assertInstanceOf( EchoNotification::class, $notif ); // getReadTimestamp() should return null $this->assertNull( $notif->getReadTimestamp() ); $this->assertEquals( $notif->getTimestamp(), wfTimestamp( TS_MW, $row['notification_timestamp'] ) ); - $this->assertInstanceOf( 'EchoEvent', $notif->getEvent() ); + $this->assertInstanceOf( EchoEvent::class, $notif->getEvent() ); $this->assertNull( $notif->getTargetPages() ); // Provide a read timestamp @@ -33,18 +33,16 @@ class EchoNotificationTest extends MediaWikiTestCase { ] ); $this->assertNotEmpty( $notif->getTargetPages() ); foreach ( $notif->getTargetPages() as $targetPage ) { - $this->assertInstanceOf( 'EchoTargetPage', $targetPage ); + $this->assertInstanceOf( EchoTargetPage::class, $targetPage ); } } - /** - * @expectedException MWException - */ public function testNewFromRowWithException() { $row = $this->mockNotificationRow(); // Provide an invalid event id $row['notification_event'] = -1; - $noitf = EchoNotification::newFromRow( (object)$row ); + $this->expectException( MWException::class ); + EchoNotification::newFromRow( (object)$row ); } /** @@ -56,9 +54,7 @@ class EchoNotificationTest extends MediaWikiTestCase { 'notification_event' => 1, 'notification_timestamp' => time(), 'notification_read_timestamp' => '', - 'notification_bundle_base' => 1, 'notification_bundle_hash' => 'testhash', - 'notification_bundle_display_hash' => 'testdisplayhash' ]; } diff --git a/Echo/tests/phpunit/BundlerTest.php b/Echo/tests/phpunit/unit/BundlerTest.php index a4a2e258..121afccc 100644 --- a/Echo/tests/phpunit/BundlerTest.php +++ b/Echo/tests/phpunit/unit/BundlerTest.php @@ -1,9 +1,9 @@ <?php /** - * @covers Bundler + * @covers \Bundler */ -class BundlerTest extends MediaWikiTestCase { +class BundlerTest extends MediaWikiUnitTestCase { public function testBundle() { $read = true; @@ -28,7 +28,7 @@ class BundlerTest extends MediaWikiTestCase { } private function createNotificationForBundling( $bundleHash, $timestamp, $readStatus ) { - $mock = $this->getMockBuilder( 'EchoNotification' ) + $mock = $this->getMockBuilder( EchoNotification::class ) ->disableOriginalConstructor() ->setMethods( [ 'getBundlingKey', diff --git a/Echo/tests/phpunit/DiffParserTest.php b/Echo/tests/phpunit/unit/DiffParserTest.php index aeecef67..aa452830 100644 --- a/Echo/tests/phpunit/DiffParserTest.php +++ b/Echo/tests/phpunit/unit/DiffParserTest.php @@ -1,10 +1,10 @@ <?php /** - * @covers EchoDiffParser + * @covers \EchoDiffParser * @group Echo */ -class EchoDiffParserTest extends MediaWikiTestCase { +class EchoDiffParserTest extends MediaWikiUnitTestCase { /** * @dataProvider provider_getChangeSet diff --git a/Echo/tests/phpunit/unit/EchoContainmentSetTest.php b/Echo/tests/phpunit/unit/EchoContainmentSetTest.php new file mode 100644 index 00000000..edf8cf92 --- /dev/null +++ b/Echo/tests/phpunit/unit/EchoContainmentSetTest.php @@ -0,0 +1,59 @@ +<?php + +/** + * @coversDefaultClass EchoContainmentSet + */ +class EchoContainmentSetTest extends \MediaWikiUnitTestCase { + + /** + * @covers ::addTitleIDsFromUserOption + * @dataProvider addTitlesFromUserOptionProvider + * @param User $user + * @param string $prefData + * @param string $contains + * @param bool $expected + */ + public function testAddTitlesFromUserOption( + $prefData, string $contains, bool $expected + ) { + $user = $this->getDefaultUserMock(); + $user->method( 'getOption' ) + ->willReturn( $prefData ); + $containmentSet = new EchoContainmentSet( $user ); + $containmentSet->addTitleIDsFromUserOption( 'preference-name' ); + $this->assertSame( $expected, $containmentSet->contains( $contains ) ); + } + + public function addTitlesFromUserOptionProvider() :array { + return [ + [ + 'foo', + 'bar', + false + ], + [ + [ 'foo', 'bar' ], + 'foo', + false + ], + [ + "foo\nbar", + 'bar', + true + ], + [ + '{"foo":"bar"}', + 'bar', + false + ] + + ]; + } + + private function getDefaultUserMock() { + return $this->getMockBuilder( User::class ) + ->disableOriginalConstructor() + ->getMock(); + } + +} diff --git a/Echo/tests/phpunit/unit/Push/SubscriptionTest.php b/Echo/tests/phpunit/unit/Push/SubscriptionTest.php new file mode 100644 index 00000000..b63e8c16 --- /dev/null +++ b/Echo/tests/phpunit/unit/Push/SubscriptionTest.php @@ -0,0 +1,22 @@ +<?php + +use EchoPush\Subscription; +use Wikimedia\Timestamp\ConvertibleTimestamp; + +/** @covers \EchoPush\Subscription */ +class SubscriptionTest extends MediaWikiUnitTestCase { + + public function testNewFromRow(): void { + $row = new stdClass(); + $row->eps_token = 'ABC123'; + $row->epp_name = 'fcm'; + $row->eps_updated = '2020-01-01 10:10:10'; + + $subscription = Subscription::newFromRow( $row ); + $this->assertSame( 'ABC123', $subscription->getToken() ); + $this->assertSame( 'fcm', $subscription->getProvider() ); + $this->assertInstanceOf( ConvertibleTimestamp::class, $subscription->getUpdated() ); + $this->assertSame( '1577873410', $subscription->getUpdated()->getTimestamp() ); + } + +} diff --git a/Echo/tests/phpunit/unit/controller/NotificationControllerUnitTest.php b/Echo/tests/phpunit/unit/controller/NotificationControllerUnitTest.php new file mode 100644 index 00000000..9c0c7cb8 --- /dev/null +++ b/Echo/tests/phpunit/unit/controller/NotificationControllerUnitTest.php @@ -0,0 +1,74 @@ +<?php + +use Wikimedia\TestingAccessWrapper; + +/** + * @coversDefaultClass EchoNotificationController + */ +class NotificationControllerUnitTest extends MediaWikiUnitTestCase { + + /** + * @dataProvider PageLinkedTitleMutedByUserDataProvider + * @covers ::isPageLinkedTitleMutedByUser + * @param Title $title + * @param User $user + * @param bool $expected + */ + public function testIsPageLinkedTitleMutedByUser( + Title $title, User $user, bool $expected ): void { + $wrapper = TestingAccessWrapper::newFromClass( EchoNotificationController::class ); + $wrapper->mutedPageLinkedTitlesCache = $this->getMapCacheLruMock(); + $this->assertSame( + $expected, + $wrapper->isPageLinkedTitleMutedByUser( $title, $user ) + ); + } + + public function PageLinkedTitleMutedByUserDataProvider() :array { + return [ + [ + $this->getMockTitle( 123 ), + $this->getMockUser( [] ), + false + ], + [ + $this->getMockTitle( 123 ), + $this->getMockUser( [ 123, 456, 789 ] ), + true + ], + [ + $this->getMockTitle( 456 ), + $this->getMockUser( [ 489 ] ), + false + ] + + ]; + } + + private function getMockTitle( int $articleID ) { + $title = $this->getMockBuilder( Title::class ) + ->disableOriginalConstructor() + ->getMock(); + $title->method( 'getArticleID' ) + ->willReturn( $articleID ); + return $title; + } + + private function getMockUser( $mutedTitlePreferences = [] ) { + $user = $this->getMockBuilder( User::class ) + ->disableOriginalConstructor() + ->getMock(); + $user->method( 'getId' ) + ->willReturn( 456 ); + $user->method( 'getOption' ) + ->willReturn( implode( "\n", $mutedTitlePreferences ) ); + return $user; + } + + private function getMapCacheLruMock() { + return $this->getMockBuilder( MapCacheLRU::class ) + ->disableOriginalConstructor() + ->getMock(); + } + +} diff --git a/Echo/tests/phpunit/gateway/UserNotificationGatewayTest.php b/Echo/tests/phpunit/unit/gateway/UserNotificationGatewayTest.php index 2cc4fd78..2f45ee2f 100644 --- a/Echo/tests/phpunit/gateway/UserNotificationGatewayTest.php +++ b/Echo/tests/phpunit/unit/gateway/UserNotificationGatewayTest.php @@ -1,54 +1,96 @@ <?php +use Wikimedia\Rdbms\IDatabase; + /** - * @covers EchoUserNotificationGateway + * @covers \EchoUserNotificationGateway */ -class EchoUserNotificationGatewayTest extends MediaWikiTestCase { +class EchoUserNotificationGatewayTest extends MediaWikiUnitTestCase { public function testMarkRead() { // no event ids to mark - $gateway = new EchoUserNotificationGateway( User::newFromId( 1 ), $this->mockMWEchoDbFactory() ); + $gateway = new EchoUserNotificationGateway( + User::newFromId( 1 ), + $this->mockMWEchoDbFactory(), + $this->mockConfig() + ); $this->assertFalse( $gateway->markRead( [] ) ); // successful update - $gateway = new EchoUserNotificationGateway( User::newFromId( 1 ), $this->mockMWEchoDbFactory( [ 'update' => true ] ) ); + $gateway = new EchoUserNotificationGateway( + User::newFromId( 1 ), + $this->mockMWEchoDbFactory( [ 'update' => true ] ), + $this->mockConfig() + ); $this->assertTrue( $gateway->markRead( [ 2 ] ) ); // unsuccessful update - $gateway = new EchoUserNotificationGateway( User::newFromId( 1 ), $this->mockMWEchoDbFactory( [ 'update' => false ] ) ); + $gateway = new EchoUserNotificationGateway( + User::newFromId( 1 ), + $this->mockMWEchoDbFactory( [ 'update' => false ] ), + $this->mockConfig() + ); $this->assertFalse( $gateway->markRead( [ 2 ] ) ); } public function testMarkAllRead() { // successful update - $gateway = new EchoUserNotificationGateway( User::newFromId( 1 ), $this->mockMWEchoDbFactory( [ 'update' => true ] ) ); + $gateway = new EchoUserNotificationGateway( + User::newFromId( 1 ), + $this->mockMWEchoDbFactory( [ 'update' => true ] ), + $this->mockConfig() + ); $this->assertTrue( $gateway->markAllRead( [ 2 ] ) ); - // unsuccessful update - $gateway = new EchoUserNotificationGateway( User::newFromId( 1 ), $this->mockMWEchoDbFactory( [ 'update' => false ] ) ); - $this->assertFalse( $gateway->markAllRead( [ 2 ] ) ); + // null update + $gateway = new EchoUserNotificationGateway( + User::newFromId( 1 ), + $this->mockMWEchoDbFactory( [ 'update' => false ] ), + $this->mockConfig() + ); + $this->assertTrue( $gateway->markAllRead( [ 2 ] ) ); } public function testGetNotificationCount() { // unsuccessful select - $gateway = new EchoUserNotificationGateway( $this->mockUser(), $this->mockMWEchoDbFactory( [ 'selectRowCount' => 0 ] ) ); - $this->assertEquals( 0, $gateway->getCappedNotificationCount( DB_REPLICA, [ 'event_one' ] ) ); + $gateway = new EchoUserNotificationGateway( + $this->mockUser(), + $this->mockMWEchoDbFactory( [ 'selectRowCount' => 0 ] ), + $this->mockConfig() + ); + $this->assertSame( 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_REPLICA, [ 'event_one', 'event_two' ] ) ); + $gateway = new EchoUserNotificationGateway( + $this->mockUser(), + $this->mockMWEchoDbFactory( [ 'selectRowCount' => 2 ] ), + $this->mockConfig() + ); + $this->assertSame( 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_REPLICA, [] ) ); + $gateway = new EchoUserNotificationGateway( + $this->mockUser(), + $this->mockMWEchoDbFactory( [ 'selectRowCount' => 2 ] ), + $this->mockConfig() + ); + $this->assertSame( 0, $gateway->getCappedNotificationCount( DB_REPLICA, [] ) ); // successful select - $gateway = new EchoUserNotificationGateway( $this->mockUser(), $this->mockMWEchoDbFactory( [ 'selectRowCount' => 3 ] ) ); - $this->assertEquals( 3, $gateway->getCappedNotificationCount( DB_REPLICA, [ 'event_one' ] ) ); + $gateway = new EchoUserNotificationGateway( + $this->mockUser(), + $this->mockMWEchoDbFactory( [ 'selectRowCount' => 3 ] ), + $this->mockConfig() + ); + $this->assertSame( 3, $gateway->getCappedNotificationCount( DB_REPLICA, [ 'event_one' ] ) ); } public function testGetUnreadNotifications() { - $gateway = new EchoUserNotificationGateway( $this->mockUser(), $this->mockMWEchoDbFactory( [ 'select' => false ] ) ); + $gateway = new EchoUserNotificationGateway( + $this->mockUser(), + $this->mockMWEchoDbFactory( [ 'select' => false ] ), + $this->mockConfig() + ); $this->assertEmpty( $gateway->getUnreadNotifications( 'user_talk' ) ); $dbResult = [ @@ -56,7 +98,11 @@ class EchoUserNotificationGatewayTest extends MediaWikiTestCase { (object)[ 'notification_event' => 2 ], (object)[ 'notification_event' => 3 ], ]; - $gateway = new EchoUserNotificationGateway( $this->mockUser(), $this->mockMWEchoDbFactory( [ 'select' => $dbResult ] ) ); + $gateway = new EchoUserNotificationGateway( + $this->mockUser(), + $this->mockMWEchoDbFactory( [ 'select' => $dbResult ] ), + $this->mockConfig() + ); $res = $gateway->getUnreadNotifications( 'user_talk' ); $this->assertEquals( $res, [ 1 => 1, 2 => 2, 3 => 3 ] ); } @@ -65,7 +111,7 @@ class EchoUserNotificationGatewayTest extends MediaWikiTestCase { * Mock object of User */ protected function mockUser( $group = 'echo_group' ) { - $user = $this->getMockBuilder( 'User' ) + $user = $this->getMockBuilder( User::class ) ->disableOriginalConstructor() ->getMock(); $user->expects( $this->any() ) @@ -85,7 +131,7 @@ class EchoUserNotificationGatewayTest extends MediaWikiTestCase { * Mock object of MWEchoDbFactory */ protected function mockMWEchoDbFactory( array $dbResult = [] ) { - $dbFactory = $this->getMockBuilder( 'MWEchoDbFactory' ) + $dbFactory = $this->getMockBuilder( MWEchoDbFactory::class ) ->disableOriginalConstructor() ->getMock(); $dbFactory->expects( $this->any() ) @@ -95,6 +141,12 @@ class EchoUserNotificationGatewayTest extends MediaWikiTestCase { return $dbFactory; } + protected function mockConfig() { + return new HashConfig( [ + 'UpdateRowsPerQuery' => 500, + ] ); + } + /** * Returns a mock database object * @return \Wikimedia\Rdbms\IDatabase @@ -106,9 +158,7 @@ class EchoUserNotificationGatewayTest extends MediaWikiTestCase { 'selectRow' => '', 'selectRowCount' => '', ]; - $db = $this->getMockBuilder( 'DatabaseMysqli' ) - ->disableOriginalConstructor() - ->getMock(); + $db = $this->createMock( IDatabase::class ); $db->expects( $this->any() ) ->method( 'update' ) ->will( $this->returnValue( $dbResult['update'] ) ); diff --git a/Echo/tests/phpunit/iterator/FilteredSequentialIteratorTest.php b/Echo/tests/phpunit/unit/iterator/FilteredSequentialIteratorTest.php index 7042d633..25086cf2 100644 --- a/Echo/tests/phpunit/iterator/FilteredSequentialIteratorTest.php +++ b/Echo/tests/phpunit/unit/iterator/FilteredSequentialIteratorTest.php @@ -1,10 +1,10 @@ <?php /** - * @covers EchoCallbackIterator - * @covers EchoFilteredSequentialIterator + * @covers \EchoCallbackIterator + * @covers \EchoFilteredSequentialIterator */ -class FilteredSequentialIteratorTest extends MediaWikiTestCase { +class FilteredSequentialIteratorTest extends MediaWikiUnitTestCase { public function testEchoCallbackIteratorDoesntBlowUp() { $it = new EchoCallbackIterator( diff --git a/Echo/tests/phpunit/mapper/AbstractMapperTest.php b/Echo/tests/phpunit/unit/mapper/AbstractMapperTest.php index 02194a02..646caa0f 100644 --- a/Echo/tests/phpunit/mapper/AbstractMapperTest.php +++ b/Echo/tests/phpunit/unit/mapper/AbstractMapperTest.php @@ -1,16 +1,19 @@ <?php /** - * @covers EchoAbstractMapper + * @covers \EchoAbstractMapper */ -class EchoAbstractMapperTest extends MediaWikiTestCase { +class EchoAbstractMapperTest extends MediaWikiUnitTestCase { + /** + * @return array [ 'mapper' => EchoAbstractMapper, 'property' => ReflectionProperty ] + */ public function testAttachListener() { $mapper = new EchoAbstractMapperStub(); $mapper->attachListener( 'testMethod', 'key_a', function () { } ); - $class = new ReflectionClass( 'EchoAbstractMapperStub' ); + $class = new ReflectionClass( EchoAbstractMapperStub::class ); $property = $class->getProperty( 'listeners' ); $property->setAccessible( true ); $listeners = $property->getValue( $mapper ); @@ -22,11 +25,9 @@ class EchoAbstractMapperTest extends MediaWikiTestCase { return [ 'mapper' => $mapper, 'property' => $property ]; } - /** - * @expectedException MWException - */ public function testAttachListenerWithException() { $mapper = new EchoAbstractMapperStub(); + $this->expectException( MWException::class ); $mapper->attachListener( 'nonExistingMethod', 'key_a', function () { } ); } @@ -35,8 +36,8 @@ class EchoAbstractMapperTest extends MediaWikiTestCase { * @depends testAttachListener */ public function testGetMethodListeners( $data ) { + /** @var EchoAbstractMapper $mapper */ $mapper = $data['mapper']; - $property = $data['property']; $listeners = $mapper->getMethodListeners( 'testMethod' ); $this->assertArrayHasKey( 'key_a', $listeners ); @@ -45,20 +46,22 @@ class EchoAbstractMapperTest extends MediaWikiTestCase { /** * @depends testAttachListener - * @expectedException MWException */ public function testGetMethodListenersWithException( $data ) { + /** @var EchoAbstractMapper $mapper */ $mapper = $data['mapper']; - $property = $data['property']; - $listeners = $mapper->getMethodListeners( 'nonExistingMethod' ); + $this->expectException( MWException::class ); + $mapper->getMethodListeners( 'nonExistingMethod' ); } /** * @depends testAttachListener */ public function testDetachListener( $data ) { + /** @var EchoAbstractMapper $mapper */ $mapper = $data['mapper']; + /** @var ReflectionProperty $property */ $property = $data['property']; $mapper->detachListener( 'testMethod', 'key_a' ); diff --git a/Echo/tests/phpunit/mapper/TargetPageMapperTest.php b/Echo/tests/phpunit/unit/mapper/TargetPageMapperTest.php index aaba3e3c..eecc3712 100644 --- a/Echo/tests/phpunit/mapper/TargetPageMapperTest.php +++ b/Echo/tests/phpunit/unit/mapper/TargetPageMapperTest.php @@ -1,9 +1,11 @@ <?php +use Wikimedia\Rdbms\IDatabase; + /** - * @covers EchoTargetPageMapper + * @covers \EchoTargetPageMapper */ -class EchoTargetPageMapperTest extends MediaWikiTestCase { +class EchoTargetPageMapperTest extends MediaWikiUnitTestCase { public function provideDataTestInsert() { return [ @@ -17,11 +19,6 @@ class EchoTargetPageMapperTest extends MediaWikiTestCase { [ 'insert' => true, 'insertId' => 2 ], 2 ], - [ - 'unsuccessful insert', - [ 'insert' => false, 'insertId' => 2 ], - false - ], ]; } @@ -58,7 +55,7 @@ class EchoTargetPageMapperTest extends MediaWikiTestCase { * Mock object of MWEchoDbFactory */ protected function mockMWEchoDbFactory( $dbResult ) { - $dbFactory = $this->getMockBuilder( 'MWEchoDbFactory' ) + $dbFactory = $this->getMockBuilder( MWEchoDbFactory::class ) ->disableOriginalConstructor() ->getMock(); $dbFactory->expects( $this->any() ) @@ -79,9 +76,7 @@ class EchoTargetPageMapperTest extends MediaWikiTestCase { 'select' => '', 'delete' => '' ]; - $db = $this->getMockBuilder( 'DatabaseMysqli' ) - ->disableOriginalConstructor() - ->getMock(); + $db = $this->createMock( IDatabase::class ); $db->expects( $this->any() ) ->method( 'insert' ) ->will( $this->returnValue( $dbResult['insert'] ) ); diff --git a/Echo/tests/phpunit/model/TargetPageTest.php b/Echo/tests/phpunit/unit/model/TargetPageTest.php index f925cfeb..565f5f94 100644 --- a/Echo/tests/phpunit/model/TargetPageTest.php +++ b/Echo/tests/phpunit/unit/model/TargetPageTest.php @@ -1,9 +1,9 @@ <?php /** - * @covers EchoTargetPage + * @covers \EchoTargetPage */ -class EchoTargetPageTest extends MediaWikiTestCase { +class EchoTargetPageTest extends MediaWikiUnitTestCase { public function testCreate() { $this->assertNull( @@ -14,7 +14,7 @@ class EchoTargetPageTest extends MediaWikiTestCase { ); $this->assertInstanceOf( - 'EchoTargetPage', + EchoTargetPage::class, EchoTargetPage::create( $this->mockTitle( 1 ), $this->mockEchoEvent() @@ -22,31 +22,32 @@ class EchoTargetPageTest extends MediaWikiTestCase { ); } + /** + * @return EchoTargetPage + */ public function testNewFromRow() { $row = (object)[ 'etp_page' => 2, 'etp_event' => 3 ]; $obj = EchoTargetPage::newFromRow( $row ); - $this->assertInstanceOf( 'EchoTargetPage', $obj ); + $this->assertInstanceOf( EchoTargetPage::class, $obj ); return $obj; } - /** - * @expectedException MWException - */ public function testNewFromRowWithException() { $row = (object)[ 'etp_event' => 3 ]; - $this->assertInstanceOf( 'EchoTargetPage', EchoTargetPage::newFromRow( $row ) ); + $this->expectException( MWException::class ); + EchoTargetPage::newFromRow( $row ); } /** * @depends testNewFromRow */ - public function testToDbArray( $obj ) { + public function testToDbArray( EchoTargetPage $obj ) { $row = $obj->toDbArray(); $this->assertTrue( is_array( $row ) ); @@ -59,10 +60,10 @@ class EchoTargetPageTest extends MediaWikiTestCase { } /** - * Mock object of Title + * @return Title */ protected function mockTitle( $pageId ) { - $event = $this->getMockBuilder( 'Title' ) + $event = $this->getMockBuilder( Title::class ) ->disableOriginalConstructor() ->getMock(); $event->expects( $this->any() ) @@ -73,10 +74,10 @@ class EchoTargetPageTest extends MediaWikiTestCase { } /** - * Mock object of EchoEvent + * @return EchoEvent */ protected function mockEchoEvent( $eventId = 1 ) { - $event = $this->getMockBuilder( 'EchoEvent' ) + $event = $this->getMockBuilder( EchoEvent::class ) ->disableOriginalConstructor() ->getMock(); $event->expects( $this->any() ) diff --git a/Echo/tests/qunit/.eslintrc.json b/Echo/tests/qunit/.eslintrc.json index 348a1b7f..1b7ccf1c 100644 --- a/Echo/tests/qunit/.eslintrc.json +++ b/Echo/tests/qunit/.eslintrc.json @@ -1,6 +1,11 @@ { "extends": [ - "wikimedia/qunit", - "../../.eslintrc.json" - ] + "wikimedia/qunit" + ], + "rules": { + "no-jquery/no-class-state": "off", + "no-jquery/no-parse-html-literal": "off", + "no-jquery/no-global-selector": "off", + "no-jquery/no-sizzle": "off" + } } diff --git a/Echo/tests/qunit/mobile/index.js b/Echo/tests/qunit/mobile/index.js new file mode 100644 index 00000000..d1dc108f --- /dev/null +++ b/Echo/tests/qunit/mobile/index.js @@ -0,0 +1,7 @@ +mw.template.add( 'ext.echo.mobile', 'NotificationBadge.mustache', + mw.template.get( 'test.Echo', 'NotificationBadge.mustache' ).getSource() +); + +mw.loader.using( 'mobile.startup' ).then( function () { + require( './test_NotificationBadge.js' ); +} ); diff --git a/Echo/tests/qunit/mobile/test_NotificationBadge.js b/Echo/tests/qunit/mobile/test_NotificationBadge.js new file mode 100644 index 00000000..02304ec6 --- /dev/null +++ b/Echo/tests/qunit/mobile/test_NotificationBadge.js @@ -0,0 +1,76 @@ +( function ( M ) { + var OverlayManager = M.require( 'mobile.startup' ).OverlayManager, + NotificationBadge = require( '../../../modules/mobile/NotificationBadge.js' ); + + QUnit.module( 'ext.echo.mobile - NotificationBadge', { + beforeEach: function () { + this.OverlayManager = OverlayManager.getSingleton(); + } + } ); + + QUnit.test( '#setCount', function ( assert ) { + var initialClassExpectationsMet, + badge = new NotificationBadge( { + overlayManager: this.OverlayManager, + hasNotifications: true, + hasUnseenNotifications: true, + notificationCountRaw: 5 + } ); + initialClassExpectationsMet = badge.$el.find( '.mw-ui-icon' ).length === 0 && + badge.$el.find( '.zero' ).length === 0; + + badge.setCount( 0 ); + assert.ok( initialClassExpectationsMet, 'No icon and no zero class' ); + assert.strictEqual( badge.$el.find( '.zero' ).length, 1, 'A zero class is present on the badge' ); + badge.setCount( 105 ); + assert.strictEqual( badge.options.notificationCountRaw, 100, 'Number is capped to 100.' ); + } ); + + QUnit.test( '#setCount (Eastern Arabic numerals)', function ( assert ) { + var badge; + + this.sandbox.stub( mw.language, 'convertNumber' ) + .withArgs( 2 ).returns( '۲' ) + .withArgs( 5 ).returns( '۵' ); + this.sandbox.stub( mw, 'message' ) + .withArgs( 'echo-badge-count', '۵' ).returns( { text: function () { return '۵'; } } ) + .withArgs( 'echo-badge-count', '۲' ).returns( { text: function () { return '۲'; } } ); + + badge = new NotificationBadge( { + overlayManager: this.OverlayManager, + el: $( '<div><a title="n" href="/" class="notification-unseen"><div class="circle" ><span data-notification-count="2">۲</span></div></a></div>' ) + } ); + assert.strictEqual( badge.options.notificationCountRaw, 2, + 'Number is parsed from Eastern Arabic numerals' ); + assert.strictEqual( badge.options.notificationCountString, '۲', + 'Number will be rendered in Eastern Arabic numerals' ); + badge.setCount( 5 ); + assert.strictEqual( badge.options.notificationCountString, '۵', + 'Number will be rendered in Eastern Arabic numerals' ); + } ); + + QUnit.test( '#render [hasUnseenNotifications]', function ( assert ) { + var badge = new NotificationBadge( { + notificationCountRaw: 0, + overlayManager: this.OverlayManager, + hasNotifications: false, + hasUnseenNotifications: false + } ); + assert.strictEqual( badge.$el.find( '.mw-ui-icon' ).length, 1, 'A bell icon is visible' ); + } ); + + QUnit.test( '#markAsSeen', function ( assert ) { + var badge = new NotificationBadge( { + notificationCountRaw: 2, + overlayManager: this.OverlayManager, + hasNotifications: true, + hasUnseenNotifications: true + } ); + // Badge resets counter to zero + badge.setCount( 0 ); + assert.strictEqual( badge.$el.find( '.mw-ui-icon' ).length, 0, 'The bell icon is not visible' ); + badge.markAsSeen(); + assert.strictEqual( badge.$el.find( '.notification-unseen' ).length, 0, + 'Unseen class disappears after markAsSeen called.' ); + } ); +}( mw.mobileFrontend ) ); diff --git a/Echo/tests/qunit/model/test_mw.echo.dm.BundleNotificationItem.js b/Echo/tests/qunit/model/test_mw.echo.dm.BundleNotificationItem.js index 22a4d59b..1903fa03 100644 --- a/Echo/tests/qunit/model/test_mw.echo.dm.BundleNotificationItem.js +++ b/Echo/tests/qunit/model/test_mw.echo.dm.BundleNotificationItem.js @@ -1,4 +1,4 @@ -( function ( mw ) { +( function () { QUnit.module( 'ext.echo.dm - mw.echo.dm.BundleNotificationItem' ); QUnit.test( 'Constructing the model', function ( assert ) { @@ -114,4 +114,4 @@ 'Bundle is marked as read if all items are read' ); } ); -}( mediaWiki ) ); +}() ); diff --git a/Echo/tests/qunit/model/test_mw.echo.dm.CrossWikiNotificationItem.js b/Echo/tests/qunit/model/test_mw.echo.dm.CrossWikiNotificationItem.js index add303e2..d069d3f5 100644 --- a/Echo/tests/qunit/model/test_mw.echo.dm.CrossWikiNotificationItem.js +++ b/Echo/tests/qunit/model/test_mw.echo.dm.CrossWikiNotificationItem.js @@ -1,4 +1,4 @@ -( function ( mw, $ ) { +( function () { var defaults = { getModelName: 'xwiki', getSourceNames: [], @@ -308,4 +308,4 @@ ); } ); -}( mediaWiki, jQuery ) ); +}() ); diff --git a/Echo/tests/qunit/model/test_mw.echo.dm.FiltersModel.js b/Echo/tests/qunit/model/test_mw.echo.dm.FiltersModel.js index 2bc8146c..21855af0 100644 --- a/Echo/tests/qunit/model/test_mw.echo.dm.FiltersModel.js +++ b/Echo/tests/qunit/model/test_mw.echo.dm.FiltersModel.js @@ -1,4 +1,4 @@ -( function ( mw, $ ) { +( function () { var defaultValues = { getReadState: 'all' }; @@ -107,4 +107,4 @@ ); } ); -}( mediaWiki, jQuery ) ); +}() ); diff --git a/Echo/tests/qunit/model/test_mw.echo.dm.NotificationGroupsList.js b/Echo/tests/qunit/model/test_mw.echo.dm.NotificationGroupsList.js index c30a8adc..c71845a5 100644 --- a/Echo/tests/qunit/model/test_mw.echo.dm.NotificationGroupsList.js +++ b/Echo/tests/qunit/model/test_mw.echo.dm.NotificationGroupsList.js @@ -1,4 +1,4 @@ -( function ( mw ) { +( function () { QUnit.module( 'ext.echo.dm - mw.echo.dm.NotificationGroupsList' ); QUnit.test( 'Constructing the model', function ( assert ) { @@ -153,4 +153,4 @@ ); } ); -}( mediaWiki ) ); +}() ); diff --git a/Echo/tests/qunit/model/test_mw.echo.dm.NotificationItem.js b/Echo/tests/qunit/model/test_mw.echo.dm.NotificationItem.js index f49201e4..34003830 100644 --- a/Echo/tests/qunit/model/test_mw.echo.dm.NotificationItem.js +++ b/Echo/tests/qunit/model/test_mw.echo.dm.NotificationItem.js @@ -1,4 +1,4 @@ -( function ( mw, $ ) { +( function () { var fakeData = { type: 'alert', read: true, @@ -143,4 +143,4 @@ ); } ); -}( mediaWiki, jQuery ) ); +}() ); diff --git a/Echo/tests/qunit/model/test_mw.echo.dm.NotificationsList.js b/Echo/tests/qunit/model/test_mw.echo.dm.NotificationsList.js index 02de8bc4..ef700aa5 100644 --- a/Echo/tests/qunit/model/test_mw.echo.dm.NotificationsList.js +++ b/Echo/tests/qunit/model/test_mw.echo.dm.NotificationsList.js @@ -1,4 +1,4 @@ -( function ( mw, $ ) { +( function () { var defaultValues = { getAllItemIds: [], getAllItemIdsByType: [], @@ -186,4 +186,4 @@ ); } ); -}( mediaWiki, jQuery ) ); +}() ); diff --git a/Echo/tests/qunit/model/test_mw.echo.dm.PaginationModel.js b/Echo/tests/qunit/model/test_mw.echo.dm.PaginationModel.js index 84b6ca7f..52dca12a 100644 --- a/Echo/tests/qunit/model/test_mw.echo.dm.PaginationModel.js +++ b/Echo/tests/qunit/model/test_mw.echo.dm.PaginationModel.js @@ -1,4 +1,4 @@ -( function ( mw, $ ) { +( function () { var defaultValues = { getPageContinue: undefined, getCurrPageIndex: 0, @@ -88,4 +88,4 @@ ); } ); -}( mediaWiki, jQuery ) ); +}() ); diff --git a/Echo/tests/qunit/model/test_mw.echo.dm.SeenTimeModel.js b/Echo/tests/qunit/model/test_mw.echo.dm.SeenTimeModel.js index 6adf1d8d..ce25ae14 100644 --- a/Echo/tests/qunit/model/test_mw.echo.dm.SeenTimeModel.js +++ b/Echo/tests/qunit/model/test_mw.echo.dm.SeenTimeModel.js @@ -1,4 +1,4 @@ -( function ( mw ) { +( function () { QUnit.module( 'ext.echo.dm - mw.echo.dm.SeenTimeModel' ); QUnit.test( 'Constructing the model', function ( assert ) { @@ -53,4 +53,4 @@ 'Update event emitted' ); } ); -}( mediaWiki ) ); +}() ); diff --git a/Echo/tests/qunit/model/test_mw.echo.dm.SourcePagesModel.js b/Echo/tests/qunit/model/test_mw.echo.dm.SourcePagesModel.js index 7c98fc6a..49162632 100644 --- a/Echo/tests/qunit/model/test_mw.echo.dm.SourcePagesModel.js +++ b/Echo/tests/qunit/model/test_mw.echo.dm.SourcePagesModel.js @@ -1,4 +1,4 @@ -( function ( mw ) { +( function () { // Mock partial API response we feed into the model var sources = { local: { @@ -169,4 +169,4 @@ ); } ); -}( mediaWiki ) ); +}() ); diff --git a/Echo/tests/qunit/model/test_mw.echo.dm.UnreadNotificationCounter.js b/Echo/tests/qunit/model/test_mw.echo.dm.UnreadNotificationCounter.js index 42eb47aa..2f2a2a09 100644 --- a/Echo/tests/qunit/model/test_mw.echo.dm.UnreadNotificationCounter.js +++ b/Echo/tests/qunit/model/test_mw.echo.dm.UnreadNotificationCounter.js @@ -1,4 +1,4 @@ -( function ( mw ) { +( function () { QUnit.module( 'ext.echo.dm - mw.echo.dm.UnreadNotificationCounter' ); QUnit.test( 'Returning capped notifications count', function ( assert ) { @@ -82,4 +82,4 @@ 'countChange events emitted.' ); } ); -}( mediaWiki ) ); +}() ); diff --git a/Echo/tests/qunit/overlay/test_ext.echo.overlay.js b/Echo/tests/qunit/overlay/test_ext.echo.overlay.js index aa0518a1..9d54139a 100644 --- a/Echo/tests/qunit/overlay/test_ext.echo.overlay.js +++ b/Echo/tests/qunit/overlay/test_ext.echo.overlay.js @@ -1,4 +1,4 @@ -( function ( $, mw ) { +( function () { QUnit.module( 'ext.echo.overlay', { beforeEach: function () { var ApiStub; @@ -348,4 +348,4 @@ assert.strictEqual( $overlay.find( '.mw-echo-notifications' ).eq( 1 ).is( ':visible' ), true, 'Second tab is now visible.' ); } ); -}( jQuery, mediaWiki ) ); +}() ); diff --git a/Echo/tests/selenium/.eslintrc.json b/Echo/tests/selenium/.eslintrc.json index 5efe15d0..b27406cf 100644 --- a/Echo/tests/selenium/.eslintrc.json +++ b/Echo/tests/selenium/.eslintrc.json @@ -1,14 +1,6 @@ { - "extends": "wikimedia", - "env": { - "es6": true, - "mocha": true, - "node": true - }, - "globals": { - "browser": false - }, - "rules": { - "no-console": 0 - } + "root": true, + "extends": [ + "wikimedia/selenium" + ] } diff --git a/Echo/tests/selenium/README.md b/Echo/tests/selenium/README.md index 59fa8eb4..340fd262 100644 --- a/Echo/tests/selenium/README.md +++ b/Echo/tests/selenium/README.md @@ -1,42 +1,40 @@ # Selenium tests -Please see tests/selenium/README.md file in mediawiki/core repository, usually at mediawiki/vagrant/mediawiki folder. +For more information see https://www.mediawiki.org/wiki/Selenium/Node.js and [PATH]/mediawiki/vagrant/mediawiki/tests/selenium/README.md. ## Setup Set up MediaWiki-Vagrant: - cd mediawiki/vagrant + cd [PATH]/mediawiki/vagrant/mediawiki/extensions/Echo vagrant up vagrant roles enable echo vagrant provision - cd mediawiki npm install -## Start Chromedriver and run all tests +Chromedriver has to run in one terminal window: -Run both mediawiki/core and extension tests from mediawiki/core repository (usually at mediawiki/vagrant/mediawiki folder): - - npm run selenium + chromedriver --url-base=wd/hub --port=4444 -## Start Chromedriver +## Run all specs -To run only some tests, you first have to start Chromedriver in one terminal tab (or window): +In another terminal window: - chromedriver --url-base=wd/hub --port=4444 + npm run selenium-test -## Run test(s) from one file +## [T171963](https://phabricator.wikimedia.org/T171963) `No active login attempt is in progress for your session` -Then, in another terminal tab (or window) run this from mediawiki/core repository (usually at mediawiki/vagrant/mediawiki folder): +If you get this error message when logging in at `127.0.0.1:8080`, the workaround +is to log in at `dev.wiki.local.wmftest.net:8080` - ./node_modules/.bin/wdio tests/selenium/wdio.conf.js --spec extensions/EXTENSION-NAME/tests/selenium/specs/FILE-NAME.js + MW_SERVER=http://dev.wiki.local.wmftest.net:8080 npm run selenium-test -`wdio` is a dependency of mediawiki/core that you have installed with `npm install`. +## Run specific tests -## Run specific test(s) +Filter by file name: -To run only test(s) which name contains string TEST-NAME, run this from mediawiki/core repository (usually at mediawiki/vagrant/mediawiki folder): + npm run selenium-test -- --spec tests/selenium/specs/[FILE-NAME].js - ./node_modules/.bin/wdio tests/selenium/wdio.conf.js --spec extensions/EXTENSION-NAME/tests/selenium/specs/FILE-NAME.js --mochaOpts.grep TEST-NAME +Filter by file name and test name: -Make sure Chromedriver is running when executing the above command. + npm run selenium-test -- --spec tests/selenium/specs/[FILE-NAME.js] --mochaOpts.grep [TEST-NAME] diff --git a/Echo/tests/selenium/pageobjects/echo.page.js b/Echo/tests/selenium/pageobjects/echo.page.js index 13a68e97..f2c087fc 100644 --- a/Echo/tests/selenium/pageobjects/echo.page.js +++ b/Echo/tests/selenium/pageobjects/echo.page.js @@ -3,8 +3,11 @@ const Page = require( 'wdio-mediawiki/Page' ); class EchoPage extends Page { - get alerts() { return browser.element( '#pt-notifications-alert' ); } - get notices() { return browser.element( '#pt-notifications-notice' ); } + get alerts() { return $( '#pt-notifications-alert' ); } + get notices() { return $( '#pt-notifications-notice' ); } + get alertsFlyout() { return $( '.oo-ui-labelElement-label*=Alerts' ); } + get noticesFlyout() { return $( '.oo-ui-labelElement-label*=Notices' ); } + get alertMessage() { return $( '.mw-echo-ui-notificationItemWidget-content-message-header' ); } } module.exports = new EchoPage(); diff --git a/Echo/tests/selenium/pageobjects/notifications.page.js b/Echo/tests/selenium/pageobjects/notifications.page.js new file mode 100644 index 00000000..7cd5f983 --- /dev/null +++ b/Echo/tests/selenium/pageobjects/notifications.page.js @@ -0,0 +1,13 @@ +'use strict'; + +const Page = require( 'wdio-mediawiki/Page' ); + +class NotificationsPage extends Page { + + get notificationHeading() { return $( '#firstHeading' ); } + open() { + super.openTitle( 'Special:Notifications', { uselang: 'en' } ); + } +} + +module.exports = new NotificationsPage(); diff --git a/Echo/tests/selenium/specs/echo.js b/Echo/tests/selenium/specs/echo.js index 790109d0..4f0d9637 100644 --- a/Echo/tests/selenium/specs/echo.js +++ b/Echo/tests/selenium/specs/echo.js @@ -1,18 +1,62 @@ 'use strict'; -var assert = require( 'assert' ), +const assert = require( 'assert' ), EchoPage = require( '../pageobjects/echo.page' ), - UserLoginPage = require( 'wdio-mediawiki/LoginPage' ); + UserLoginPage = require( 'wdio-mediawiki/LoginPage' ), + Util = require( 'wdio-mediawiki/Util' ), + Api = require( 'wdio-mediawiki/Api' ); describe( 'Echo', function () { + let bot; - it( 'alerts and notices are visible after logging in', function () { + before( async () => { + bot = await Api.bot(); + } ); + + it( 'alerts and notices are visible after logging in @daily', function () { - UserLoginPage.login( browser.options.username, browser.options.password ); + UserLoginPage.login( browser.config.mwUser, browser.config.mwPwd ); assert( EchoPage.alerts.isExisting() ); assert( EchoPage.notices.isExisting() ); } ); + it( 'flyout for alert appears when clicked @daily', function () { + + UserLoginPage.login( browser.config.mwUser, browser.config.mwPwd ); + EchoPage.alerts.click(); + EchoPage.alertsFlyout.waitForDisplayed(); + + assert( EchoPage.alertsFlyout.isExisting() ); + + } ); + + it( 'flyout for notices appears when clicked @daily', function () { + + UserLoginPage.login( browser.config.mwUser, browser.config.mwPwd ); + EchoPage.notices.click(); + EchoPage.noticesFlyout.waitForDisplayed(); + + assert( EchoPage.noticesFlyout.isExisting() ); + + } ); + + it( 'checks for welcome message after signup', function () { + + const username = Util.getTestString( 'NewUser-' ); + const password = Util.getTestString(); + browser.call( async () => { + await Api.createAccount( bot, username, password ); + } ); + UserLoginPage.login( username, password ); + + EchoPage.notices.click(); + + EchoPage.alertMessage.waitForDisplayed(); + const regexp = /Welcome to .*, .*! We're glad you're here./; + assert( regexp.test( EchoPage.alertMessage.getText() ) ); + + } ); + } ); diff --git a/Echo/tests/selenium/specs/mention.js b/Echo/tests/selenium/specs/mention.js new file mode 100644 index 00000000..cef0217a --- /dev/null +++ b/Echo/tests/selenium/specs/mention.js @@ -0,0 +1,32 @@ +'use strict'; + +const assert = require( 'assert' ), + EchoPage = require( '../pageobjects/echo.page' ), + UserLoginPage = require( 'wdio-mediawiki/LoginPage' ), + Util = require( 'wdio-mediawiki/Util' ), + Api = require( 'wdio-mediawiki/Api' ); + +describe( 'Mention test for Echo', function () { + let bot; + + before( async () => { + bot = await Api.bot(); + } ); + it.skip( 'checks if admin gets alert when mentioned', function () { + + const username = Util.getTestString( 'NewUser-' ); + const password = Util.getTestString(); + browser.call( async () => { + await Api.createAccount( bot, username, password ); + await bot.edit( `User:${username}`, `Hello [[User:${browser.config.mwUser}]] ~~~~`, username, password ); + } ); + UserLoginPage.login( browser.config.mwUser, browser.config.mwPwd ); + + EchoPage.alerts.click(); + + EchoPage.alertMessage.waitForDisplayed(); + const regexp = /.* mentioned you on User:.*./; + assert( regexp.test( EchoPage.alertMessage.getText() ) ); + } ); + +} ); diff --git a/Echo/tests/selenium/specs/notifications.js b/Echo/tests/selenium/specs/notifications.js new file mode 100644 index 00000000..c2b37188 --- /dev/null +++ b/Echo/tests/selenium/specs/notifications.js @@ -0,0 +1,18 @@ +'use strict'; + +const assert = require( 'assert' ), + NotificationsPage = require( '../pageobjects/notifications.page' ), + UserLoginPage = require( 'wdio-mediawiki/LoginPage' ); + +describe( 'Notifications', function () { + + it( 'checks for Notifications Page @daily', function () { + + UserLoginPage.login( browser.config.mwUser, browser.config.mwPwd ); + NotificationsPage.open(); + + assert.strictEqual( NotificationsPage.notificationHeading.getText(), 'Notifications' ); + + } ); + +} ); diff --git a/Echo/tests/selenium/wdio.conf.js b/Echo/tests/selenium/wdio.conf.js index 3b58beb6..196cd227 100644 --- a/Echo/tests/selenium/wdio.conf.js +++ b/Echo/tests/selenium/wdio.conf.js @@ -1,3 +1,5 @@ +'use strict'; + /** * See also: http://webdriver.io/guide/testrunner/configurationfile.html */ @@ -12,8 +14,8 @@ exports.config = { // Defaults are for convenience with MediaWiki-Vagrant // Wiki admin - username: process.env.MEDIAWIKI_USER || 'Admin', - password: process.env.MEDIAWIKI_PASSWORD || 'vagrant', + mwUser: process.env.MEDIAWIKI_USER || 'Admin', + mwPwd: process.env.MEDIAWIKI_PASSWORD || 'vagrant', // Base for browser.url() and Page#openTitle() baseUrl: ( process.env.MW_SERVER || 'http://127.0.0.1:8080' ) + ( @@ -34,7 +36,7 @@ exports.config = { // https://sites.google.com/a/chromium.org/chromedriver/capabilities browserName: 'chrome', maxInstances: 1, - chromeOptions: { + 'goog:chromeOptions': { // If DISPLAY is set, assume developer asked non-headless or CI with Xvfb. // Otherwise, use --headless (added in Chrome 59) // https://chromium.googlesource.com/chromium/src/+/59.0.3030.0/headless/README.md @@ -79,9 +81,8 @@ exports.config = { * @param {Object} test Mocha Test object */ afterTest: function ( test ) { - var filePath; if ( !test.passed ) { - filePath = saveScreenshot( test.title ); + const filePath = saveScreenshot( test.title ); console.log( '\n\tScreenshot: ' + filePath + '\n' ); } } |