summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'Echo/tests')
-rw-r--r--Echo/tests/phpunit/AttributeManagerTest.php90
-rw-r--r--Echo/tests/phpunit/ContainmentSetTest.php21
-rw-r--r--Echo/tests/phpunit/DiscussionParserTest.php90
-rw-r--r--Echo/tests/phpunit/EchoDbFactoryTest.php6
-rw-r--r--Echo/tests/phpunit/EchoSummaryParserTest.php5
-rw-r--r--Echo/tests/phpunit/NotifUserTest.php16
-rw-r--r--Echo/tests/phpunit/NotificationsTest.php10
-rw-r--r--Echo/tests/phpunit/TalkPageFunctionalTest.php36
-rw-r--r--Echo/tests/phpunit/ThankYouEditTest.php12
-rw-r--r--Echo/tests/phpunit/UserLocatorTest.php12
-rw-r--r--Echo/tests/phpunit/api/ApiEchoMarkReadTest.php10
-rw-r--r--Echo/tests/phpunit/api/ApiEchoNotificationsTest.php4
-rw-r--r--Echo/tests/phpunit/api/Push/ApiEchoPushSubscriptionsCreateTest.php50
-rw-r--r--Echo/tests/phpunit/api/Push/ApiEchoPushSubscriptionsDeleteTest.php48
-rw-r--r--Echo/tests/phpunit/api/Push/ApiEchoPushSubscriptionsTest.php22
-rw-r--r--Echo/tests/phpunit/cache/TitleLocalCacheTest.php4
-rw-r--r--Echo/tests/phpunit/controller/NotificationControllerTest.php64
-rw-r--r--Echo/tests/phpunit/formatters/PresentationModelSectionTest.php97
-rw-r--r--Echo/tests/phpunit/integration/EchoServicesTest.php33
-rw-r--r--Echo/tests/phpunit/integration/Push/NotificationServiceClientTest.php16
-rw-r--r--Echo/tests/phpunit/integration/Push/PushNotifierTest.php20
-rw-r--r--Echo/tests/phpunit/integration/Push/SubscriptionManagerTest.php27
-rw-r--r--Echo/tests/phpunit/maintenance/SupressionMaintenanceTest.php19
-rw-r--r--Echo/tests/phpunit/mapper/EchoExecuteFirstArgumentStub.php16
-rw-r--r--Echo/tests/phpunit/mapper/EventMapperTest.php78
-rw-r--r--Echo/tests/phpunit/mapper/NotificationMapperTest.php109
-rw-r--r--Echo/tests/phpunit/model/NotificationTest.php16
-rw-r--r--Echo/tests/phpunit/unit/BundlerTest.php (renamed from Echo/tests/phpunit/BundlerTest.php)6
-rw-r--r--Echo/tests/phpunit/unit/DiffParserTest.php (renamed from Echo/tests/phpunit/DiffParserTest.php)4
-rw-r--r--Echo/tests/phpunit/unit/EchoContainmentSetTest.php59
-rw-r--r--Echo/tests/phpunit/unit/Push/SubscriptionTest.php22
-rw-r--r--Echo/tests/phpunit/unit/controller/NotificationControllerUnitTest.php74
-rw-r--r--Echo/tests/phpunit/unit/gateway/UserNotificationGatewayTest.php (renamed from Echo/tests/phpunit/gateway/UserNotificationGatewayTest.php)98
-rw-r--r--Echo/tests/phpunit/unit/iterator/FilteredSequentialIteratorTest.php (renamed from Echo/tests/phpunit/iterator/FilteredSequentialIteratorTest.php)6
-rw-r--r--Echo/tests/phpunit/unit/mapper/AbstractMapperTest.php (renamed from Echo/tests/phpunit/mapper/AbstractMapperTest.php)23
-rw-r--r--Echo/tests/phpunit/unit/mapper/TargetPageMapperTest.php (renamed from Echo/tests/phpunit/mapper/TargetPageMapperTest.php)17
-rw-r--r--Echo/tests/phpunit/unit/model/TargetPageTest.php (renamed from Echo/tests/phpunit/model/TargetPageTest.php)27
-rw-r--r--Echo/tests/qunit/.eslintrc.json11
-rw-r--r--Echo/tests/qunit/mobile/index.js7
-rw-r--r--Echo/tests/qunit/mobile/test_NotificationBadge.js76
-rw-r--r--Echo/tests/qunit/model/test_mw.echo.dm.BundleNotificationItem.js4
-rw-r--r--Echo/tests/qunit/model/test_mw.echo.dm.CrossWikiNotificationItem.js4
-rw-r--r--Echo/tests/qunit/model/test_mw.echo.dm.FiltersModel.js4
-rw-r--r--Echo/tests/qunit/model/test_mw.echo.dm.NotificationGroupsList.js4
-rw-r--r--Echo/tests/qunit/model/test_mw.echo.dm.NotificationItem.js4
-rw-r--r--Echo/tests/qunit/model/test_mw.echo.dm.NotificationsList.js4
-rw-r--r--Echo/tests/qunit/model/test_mw.echo.dm.PaginationModel.js4
-rw-r--r--Echo/tests/qunit/model/test_mw.echo.dm.SeenTimeModel.js4
-rw-r--r--Echo/tests/qunit/model/test_mw.echo.dm.SourcePagesModel.js4
-rw-r--r--Echo/tests/qunit/model/test_mw.echo.dm.UnreadNotificationCounter.js4
-rw-r--r--Echo/tests/qunit/overlay/test_ext.echo.overlay.js4
-rw-r--r--Echo/tests/selenium/.eslintrc.json16
-rw-r--r--Echo/tests/selenium/README.md34
-rw-r--r--Echo/tests/selenium/pageobjects/echo.page.js7
-rw-r--r--Echo/tests/selenium/pageobjects/notifications.page.js13
-rw-r--r--Echo/tests/selenium/specs/echo.js52
-rw-r--r--Echo/tests/selenium/specs/mention.js32
-rw-r--r--Echo/tests/selenium/specs/notifications.js18
-rw-r--r--Echo/tests/selenium/wdio.conf.js11
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' );
}
}