summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'Echo/tests')
-rw-r--r--Echo/tests/browser/README.md1
-rw-r--r--Echo/tests/browser/ci.yml9
-rw-r--r--Echo/tests/browser/environments.yml48
-rw-r--r--Echo/tests/browser/features/no_javascript.feature11
-rw-r--r--Echo/tests/browser/features/notifications.feature22
-rw-r--r--Echo/tests/browser/features/step_definition/badge_steps.rb10
-rw-r--r--Echo/tests/browser/features/step_definition/no_javascript.rb21
-rw-r--r--Echo/tests/browser/features/step_definition/notifications_steps.rb76
-rw-r--r--Echo/tests/browser/features/step_definition/popup_steps.rb11
-rw-r--r--Echo/tests/browser/features/support/components/notifications.rb21
-rw-r--r--Echo/tests/browser/features/support/data_manager.rb11
-rw-r--r--Echo/tests/browser/features/support/echo_api_helper.rb25
-rw-r--r--Echo/tests/browser/features/support/echo_pageobject_extension.rb9
-rw-r--r--Echo/tests/browser/features/support/env.rb10
-rw-r--r--Echo/tests/browser/features/support/hooks.rb10
-rw-r--r--Echo/tests/browser/features/support/pages/article_page.rb8
-rw-r--r--Echo/tests/browser/features/support/pages/special_notifications_page.rb8
-rw-r--r--Echo/tests/phpunit/AttributeManagerTest.php62
-rw-r--r--Echo/tests/phpunit/BundlerTest.php3
-rw-r--r--Echo/tests/phpunit/ContainmentSetTest.php7
-rw-r--r--Echo/tests/phpunit/DiffParserTest.php3
-rw-r--r--Echo/tests/phpunit/DiscussionParserTest.php89
-rw-r--r--Echo/tests/phpunit/EchoDbFactoryTest.php12
-rw-r--r--Echo/tests/phpunit/EchoHooksTest.php53
-rw-r--r--Echo/tests/phpunit/EchoSummaryParserTest.php68
-rw-r--r--Echo/tests/phpunit/NotifUserTest.php56
-rw-r--r--Echo/tests/phpunit/NotificationStructureTest.php40
-rw-r--r--Echo/tests/phpunit/NotificationsTest.php (renamed from Echo/tests/NotificationsTest.php)9
-rw-r--r--Echo/tests/phpunit/TalkPageFunctionalTest.php10
-rw-r--r--Echo/tests/phpunit/ThankYouEditTest.php7
-rw-r--r--Echo/tests/phpunit/UserLocatorTest.php3
-rw-r--r--Echo/tests/phpunit/api/ApiEchoMarkReadTest.php7
-rw-r--r--Echo/tests/phpunit/api/ApiEchoNotificationsTest.php2
-rw-r--r--Echo/tests/phpunit/cache/TitleLocalCacheTest.php123
-rw-r--r--Echo/tests/phpunit/controller/NotificationControllerTest.php3
-rw-r--r--Echo/tests/phpunit/gateway/UserNotificationGatewayTest.php21
-rw-r--r--Echo/tests/phpunit/iterator/FilteredSequentialIteratorTest.php4
-rw-r--r--Echo/tests/phpunit/maintenance/SupressionMaintenanceTest.php1
-rw-r--r--Echo/tests/phpunit/mapper/AbstractMapperTest.php13
-rw-r--r--Echo/tests/phpunit/mapper/EchoAbstractMapperStub.php11
-rw-r--r--Echo/tests/phpunit/mapper/EchoExecuteFirstArgumentStub.php18
-rw-r--r--Echo/tests/phpunit/mapper/EventMapperTest.php8
-rw-r--r--Echo/tests/phpunit/mapper/NotificationMapperTest.php74
-rw-r--r--Echo/tests/phpunit/mapper/TargetPageMapperTest.php13
-rw-r--r--Echo/tests/phpunit/model/NotificationTest.php5
-rw-r--r--Echo/tests/phpunit/model/TargetPageTest.php3
-rw-r--r--Echo/tests/phpunit/revision_txt/123.txt1
-rw-r--r--Echo/tests/phpunit/revision_txt/1234.txt1
-rw-r--r--Echo/tests/qunit/.eslintrc.json6
-rw-r--r--Echo/tests/qunit/model/test_mw.echo.dm.BundleNotificationItem.js18
-rw-r--r--Echo/tests/qunit/model/test_mw.echo.dm.CrossWikiNotificationItem.js12
-rw-r--r--Echo/tests/qunit/model/test_mw.echo.dm.FiltersModel.js8
-rw-r--r--Echo/tests/qunit/model/test_mw.echo.dm.NotificationGroupsList.js12
-rw-r--r--Echo/tests/qunit/model/test_mw.echo.dm.NotificationsList.js8
-rw-r--r--Echo/tests/qunit/model/test_mw.echo.dm.SourcePagesModel.js12
-rw-r--r--Echo/tests/qunit/model/test_mw.echo.dm.UnreadNotificationCounter.js16
-rw-r--r--Echo/tests/qunit/overlay/test_ext.echo.overlay.js16
-rw-r--r--Echo/tests/rspec/README.md7
-rw-r--r--Echo/tests/rspec/notification_spec.rb55
-rw-r--r--Echo/tests/selenium/.eslintrc.json14
-rw-r--r--Echo/tests/selenium/README.md42
-rw-r--r--Echo/tests/selenium/pageobjects/echo.page.js10
-rw-r--r--Echo/tests/selenium/specs/echo.js18
-rw-r--r--Echo/tests/selenium/wdio.conf.js88
64 files changed, 713 insertions, 670 deletions
diff --git a/Echo/tests/browser/README.md b/Echo/tests/browser/README.md
deleted file mode 100644
index 36319498..00000000
--- a/Echo/tests/browser/README.md
+++ /dev/null
@@ -1 +0,0 @@
-Please see https://github.com/wikimedia/mediawiki-selenium for instructions on how to run tests.
diff --git a/Echo/tests/browser/ci.yml b/Echo/tests/browser/ci.yml
deleted file mode 100644
index c2eca934..00000000
--- a/Echo/tests/browser/ci.yml
+++ /dev/null
@@ -1,9 +0,0 @@
-BROWSER:
- - chrome
- - firefox
-
-MEDIAWIKI_ENVIRONMENT:
- - beta
-
-PLATFORM:
- - Linux
diff --git a/Echo/tests/browser/environments.yml b/Echo/tests/browser/environments.yml
deleted file mode 100644
index c32e21bb..00000000
--- a/Echo/tests/browser/environments.yml
+++ /dev/null
@@ -1,48 +0,0 @@
-# Customize this configuration as necessary to provide defaults for various
-# test environments.
-#
-# The set of defaults to use is determined by the MEDIAWIKI_ENVIRONMENT
-# environment variable.
-#
-# export MEDIAWIKI_ENVIRONMENT=mw-vagrant-host
-# bundle exec cucumber
-#
-# Additional variables set by the environment will override the corresponding
-# defaults defined here.
-#
-# export MEDIAWIKI_ENVIRONMENT=mw-vagrant-host
-# export MEDIAWIKI_USER=Selenium_user2
-# bundle exec cucumber
-#
-mw-vagrant-host: &default
- user_factory: true
- mediawiki_url: http://127.0.0.1:8080/wiki/
-
-mw-vagrant-guest:
- user_factory: true
- mediawiki_url: http://127.0.0.1/wiki/
-
-local:
- mediawiki_user: Admin
- mediawiki_password: vagrant
- mediawiki_user_b: Selenium Echo user 2
- mediawiki_url: http://dev.wiki.local.wmftest.net:8080/wiki/
-
-beta:
- mediawiki_url: https://en.wikipedia.beta.wmflabs.org/wiki/
- mediawiki_user: Selenium_user
- mediawiki_user_b: Selenium Echo user 2
- # mediawiki_password: SET THIS IN THE ENVIRONMENT!
-
-test2:
- mediawiki_url: https://test2.wikipedia.org/wiki/
- mediawiki_user: Selenium_user
- mediawiki_user_b: Selenium Echo user 2
- # mediawiki_password: SET THIS IN THE ENVIRONMENT!
-
-integration:
- browser: chrome
- user_factory: true
- # mediawiki_url: THIS WILL BE SET BY JENKINS
-
-default: *default
diff --git a/Echo/tests/browser/features/no_javascript.feature b/Echo/tests/browser/features/no_javascript.feature
deleted file mode 100644
index a8b318ed..00000000
--- a/Echo/tests/browser/features/no_javascript.feature
+++ /dev/null
@@ -1,11 +0,0 @@
-@chrome @en.wikipedia.beta.wmflabs.org @firefox @localhost @vagrant
-Feature: Basic features for no-js functionality
-
- Background:
- Given I am using a nojs browser
-
- Scenario: Clicking alerts badge goes to Special:Notifications
- Given I am logged in
- When I click the alert badge
- And I wait for the page to load
- Then I am on Special Notifications page
diff --git a/Echo/tests/browser/features/notifications.feature b/Echo/tests/browser/features/notifications.feature
deleted file mode 100644
index 3d443a7d..00000000
--- a/Echo/tests/browser/features/notifications.feature
+++ /dev/null
@@ -1,22 +0,0 @@
-@chrome @en.wikipedia.beta.wmflabs.org @firefox @localhost @vagrant
-Feature: Testing notification types
-
- Background:
- Given I am logged in
- And all my notifications are read
-
- Scenario: Someone mentions me
- Given another user mentions me
- When I refresh the page
- Then the alert badge is showing unseen notifications
- And the alert badge value is "Alert (1)"
-
- @skip
- Scenario: Someone writes on my talk page
- Given another user writes on my talk page
- When I refresh the page
- Then the alert badge is showing unseen notifications
- And the alert badge value is "Alert (1)"
- When I click the alert badge
- And I see the alert popup
- Then there are "1" unread notifications in the alert popup
diff --git a/Echo/tests/browser/features/step_definition/badge_steps.rb b/Echo/tests/browser/features/step_definition/badge_steps.rb
deleted file mode 100644
index 82590cb1..00000000
--- a/Echo/tests/browser/features/step_definition/badge_steps.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-# Steps related to clicking and interacting with the badge
-# Work in both nojs and js version
-
-Given(/^I click the alert badge$/) do
- on(ArticlePage).alerts_element.when_present.click
-end
-
-Given(/^I click the notice badge$/) do
- on(ArticlePage).notices_element.when_present.click
-end
diff --git a/Echo/tests/browser/features/step_definition/no_javascript.rb b/Echo/tests/browser/features/step_definition/no_javascript.rb
deleted file mode 100644
index 5cf97b1b..00000000
--- a/Echo/tests/browser/features/step_definition/no_javascript.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# This test has no javascript
-# Therefore this test has no AJAX
-# Therefore it should run without any "when_present" clauses
-# If you need a "when_present" to make the test run, that is a bug
-
-Given(/^I am using a nojs browser$/) do
- # The following user-agent string contains:
- # SymbianOS: for RL to NOT load the modern experience
- # SMART-TV-SamsungBrowser: to bypass mobile-frontend and stay on the desktop site
- browser_factory.override(browser_user_agent: 'SymbianOS,SMART-TV-SamsungBrowser')
-end
-
-Given(/^I wait for the page to load$/) do
- # Wait for the page to load. We're technically clicking the <li> rather than <a>,
- # so the special-case implicit wait after clicking links doesn't kick in.
- browser.wait
-end
-
-Given(/^I am on Special Notifications page$/) do
- expect(on(SpecialNotificationsPage).firstHeading).to match('Notifications')
-end
diff --git a/Echo/tests/browser/features/step_definition/notifications_steps.rb b/Echo/tests/browser/features/step_definition/notifications_steps.rb
deleted file mode 100644
index 5557c5db..00000000
--- a/Echo/tests/browser/features/step_definition/notifications_steps.rb
+++ /dev/null
@@ -1,76 +0,0 @@
-Given(/^all my notifications are read$/) do
- clear_unread_notifications(@username)
-end
-
-Given(/^I refresh the page$/) do
- on(ArticlePage) do |page|
- page.refresh
- end
-end
-
-Given(/^another user mentions me$/) do
- message = '===Mention test===\nI am mentioning [[User:' + user(nil) +
- ']] in this page to test Echo notifications. ~~~~'
- as_user(:b) do
- api.create_page(
- @data_manager.get('Echo_test_page'),
- message
- )
- end
-end
-
-Given(/^another user writes on my talk page$/) do
- talk_page = "User_talk:#{user}"
- message = '===Talk page test===\n' +
- 'I am writing a message in your user page to test Echo notifications. ~~~~'
- as_user(:b) do
- api.create_page(talk_page, message)
- end
-end
-
-Given(/^the alert badge is showing unseen notifications$/) do
- on(ArticlePage) do |page|
- page.refresh_until do
- page.alerts.badge_unseen_element.exists?
- end
- end
-end
-
-Given(/^the notice badge is showing unseen notifications$/) do
- on(ArticlePage) do |page|
- page.refresh_until do
- page.notices.badge_unseen_element.exists?
- end
- end
-end
-
-Given(/^the alert badge value is "(.+)"$/) do |num|
- on(ArticlePage) do |page|
- page.refresh_until do
- # `.text` doesn't work for invisible elements, and Selenium thinks the badge is invisible
- page.alerts.badge_element.attribute('innerText') == num
- end
- end
-end
-
-Given(/^the notice badge value is "(.+)"$/) do |num|
- on(ArticlePage) do |page|
- page.refresh_until do
- page.notices.badge_element.attribute('innerText') == num
- end
- end
-end
-
-Given(/^there are "(.+)" unread notifications in the notice popup$/) do |num|
- on(ArticlePage) do |page|
- page.notices.when_loaded
- expect(page.notices.num_unread_notifications).to eq(num.to_i)
- end
-end
-
-Given(/^there are "(.+)" unread notifications in the alert popup$/) do |num|
- on(ArticlePage) do |page|
- page.alerts.when_loaded
- expect(page.alerts.num_unread_notifications).to eq(num.to_i)
- end
-end
diff --git a/Echo/tests/browser/features/step_definition/popup_steps.rb b/Echo/tests/browser/features/step_definition/popup_steps.rb
deleted file mode 100644
index e6c8f0f0..00000000
--- a/Echo/tests/browser/features/step_definition/popup_steps.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-Given(/^I see the alert popup$/) do
- on(ArticlePage) do |page|
- expect(page.alerts.title_element.when_present.text).to match('Alerts')
- end
-end
-
-Given(/^I see the message popup$/) do
- on(ArticlePage) do |page|
- expect(page.messages.title_element.when_present.text).to match('Messages')
- end
-end
diff --git a/Echo/tests/browser/features/support/components/notifications.rb b/Echo/tests/browser/features/support/components/notifications.rb
deleted file mode 100644
index 6f8d5ab8..00000000
--- a/Echo/tests/browser/features/support/components/notifications.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-class Notifications
- include PageObject
-
- link(:badge, css: '.mw-echo-notifications-badge')
- link(:badge_unseen, css: '.mw-echo-unseen-notifications')
- link(:mark_all_as_read, css: '.mw-echo-ui-notificationsListWidget-markAllReadButton > a')
- div(:popup, css: '.mw-echo-ui-notificationBadgeButtonPopupWidget-popup')
- span(:title, css: '.oo-ui-popupWidget-head > .oo-ui-labelElement-label')
- div(
- :notifications_container,
- css: '.mw-echo-ui-notificationsListWidget > .mw-echo-ui-notificationItemWidget')
-
- def when_loaded
- title_element.when_present
- notifications_container_element.when_present
- end
-
- def num_unread_notifications
- div_elements(css: '.mw-echo-ui-notificationItemWidget-unread').size
- end
-end
diff --git a/Echo/tests/browser/features/support/data_manager.rb b/Echo/tests/browser/features/support/data_manager.rb
deleted file mode 100644
index 0ff6d66c..00000000
--- a/Echo/tests/browser/features/support/data_manager.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-# Data manager for Echo tests
-class DataManager
- def initialize
- @data = {}
- end
-
- def get(part)
- @data[part] = "#{part}_#{Random.srand}" unless @data.key? part
- @data[part]
- end
-end
diff --git a/Echo/tests/browser/features/support/echo_api_helper.rb b/Echo/tests/browser/features/support/echo_api_helper.rb
deleted file mode 100644
index 77b7e5ab..00000000
--- a/Echo/tests/browser/features/support/echo_api_helper.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-module EchoAPIHelper
- def create_page_with_user(title, text, username)
- as_user(username) do
- api.create_page title, text
- end
- end
-
- def clear_unread_notifications(username)
- as_user(username) do
- api.action('echomarkread', token_type: 'csrf', all: '1')
- end
- end
-
- def update_seentime(username, notificationType)
- as_user(username) do
- api.action('echomarkseen', token_type: 'csrf', type: notificationType)
- end
- end
-
- def watch_page(username, pageTitle)
- as_user(username) do
- api.action('watch', token_type: 'watch', title: pageTitle)
- end
- end
-end
diff --git a/Echo/tests/browser/features/support/echo_pageobject_extension.rb b/Echo/tests/browser/features/support/echo_pageobject_extension.rb
deleted file mode 100644
index 8e18a6e6..00000000
--- a/Echo/tests/browser/features/support/echo_pageobject_extension.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-module PageObject
- def refresh_until(timeout = PageObject.default_page_wait, message = nil)
- platform.wait_until(timeout, message) do
- yield.tap do |result|
- refresh unless result
- end
- end
- end
-end
diff --git a/Echo/tests/browser/features/support/env.rb b/Echo/tests/browser/features/support/env.rb
deleted file mode 100644
index d7dbf3e0..00000000
--- a/Echo/tests/browser/features/support/env.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-require 'mediawiki_selenium/cucumber'
-require 'mediawiki_selenium/pages'
-require 'mediawiki_selenium/step_definitions'
-
-def env_or_default(key, default)
- ENV[key].nil? ? default : ENV[key].to_i
-end
-
-PageObject.default_page_wait = env_or_default 'PAGE_WAIT_TIMEOUT', 60
-PageObject.default_element_wait = env_or_default 'ELEMENT_WAIT_TIMEOUT', 60
diff --git a/Echo/tests/browser/features/support/hooks.rb b/Echo/tests/browser/features/support/hooks.rb
deleted file mode 100644
index 0d84341d..00000000
--- a/Echo/tests/browser/features/support/hooks.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-# Allow running of bundle exec cucumber --dry-run -f stepdefs
-require 'mediawiki_selenium'
-require 'page-object'
-require_relative 'echo_api_helper'
-require_relative 'echo_pageobject_extension'
-require_relative 'data_manager'
-
-World(EchoAPIHelper)
-
-Before { @data_manager = DataManager.new }
diff --git a/Echo/tests/browser/features/support/pages/article_page.rb b/Echo/tests/browser/features/support/pages/article_page.rb
deleted file mode 100644
index 25ffa043..00000000
--- a/Echo/tests/browser/features/support/pages/article_page.rb
+++ /dev/null
@@ -1,8 +0,0 @@
-class ArticlePage
- include PageObject
-
- li(:alerts, css: '#pt-notifications-alert')
- li(:notices, css: '#pt-notifications-notice')
- page_section(:alerts, Notifications, css: '#pt-notifications-alert')
- page_section(:notices, Notifications, css: '#pt-notifications-notice')
-end
diff --git a/Echo/tests/browser/features/support/pages/special_notifications_page.rb b/Echo/tests/browser/features/support/pages/special_notifications_page.rb
deleted file mode 100644
index 3f6f0c25..00000000
--- a/Echo/tests/browser/features/support/pages/special_notifications_page.rb
+++ /dev/null
@@ -1,8 +0,0 @@
-# Special:Notifications page
-class SpecialNotificationsPage
- include PageObject
-
- page_url 'Special:Notifications'
-
- h1(:firstHeading, css: '.firstHeading')
-end
diff --git a/Echo/tests/phpunit/AttributeManagerTest.php b/Echo/tests/phpunit/AttributeManagerTest.php
index f9b0c939..42ccb992 100644
--- a/Echo/tests/phpunit/AttributeManagerTest.php
+++ b/Echo/tests/phpunit/AttributeManagerTest.php
@@ -1,5 +1,8 @@
<?php
+/**
+ * @covers EchoAttributeManager
+ */
class EchoAttributeManagerTest extends MediaWikiTestCase {
public function testNewFromGlobalVars() {
@@ -55,7 +58,7 @@ class EchoAttributeManagerTest extends MediaWikiTestCase {
* @dataProvider getUserLocatorsProvider
*/
public function testGetUserLocators( $message, $expect, $type, $notifications ) {
- $manager = new EchoAttributeManager( $notifications, [], [], [], [] );
+ $manager = new EchoAttributeManager( $notifications, [], [], [] );
$result = $manager->getUserCallable( $type, EchoAttributeManager::ATTR_LOCATORS );
$this->assertEquals( $expect, $result, $message );
@@ -72,7 +75,7 @@ class EchoAttributeManagerTest extends MediaWikiTestCase {
'priority' => 10
]
];
- $manager = new EchoAttributeManager( $notif, $category, [], [], [] );
+ $manager = new EchoAttributeManager( $notif, $category, [], [] );
$this->assertTrue( $manager->getCategoryEligibility( $this->mockUser(), 'category_one' ) );
$category = [
'category_one' => [
@@ -82,7 +85,7 @@ class EchoAttributeManagerTest extends MediaWikiTestCase {
]
]
];
- $manager = new EchoAttributeManager( $notif, $category, [], [], [] );
+ $manager = new EchoAttributeManager( $notif, $category, [], [] );
$this->assertFalse( $manager->getCategoryEligibility( $this->mockUser(), 'category_one' ) );
}
@@ -97,10 +100,10 @@ class EchoAttributeManagerTest extends MediaWikiTestCase {
'priority' => 10
]
];
- $manager = new EchoAttributeManager( $notif, $category, [], [], [] );
+ $manager = new EchoAttributeManager( $notif, $category, [], [] );
$this->assertEquals( $manager->getNotificationCategory( 'event_one' ), 'category_one' );
- $manager = new EchoAttributeManager( $notif, [], [], [], [] );
+ $manager = new EchoAttributeManager( $notif, [], [], [] );
$this->assertEquals( $manager->getNotificationCategory( 'event_one' ), 'other' );
$notif = [
@@ -113,7 +116,7 @@ class EchoAttributeManagerTest extends MediaWikiTestCase {
'priority' => 10
]
];
- $manager = new EchoAttributeManager( $notif, $category, [], [], [] );
+ $manager = new EchoAttributeManager( $notif, $category, [], [] );
$this->assertEquals( $manager->getNotificationCategory( 'event_one' ), 'other' );
}
@@ -135,7 +138,7 @@ class EchoAttributeManagerTest extends MediaWikiTestCase {
],
'category_four' => []
];
- $manager = new EchoAttributeManager( $notif, $category, [], [], [] );
+ $manager = new EchoAttributeManager( $notif, $category, [], [] );
$this->assertEquals( 6, $manager->getCategoryPriority( 'category_one' ) );
$this->assertEquals( 10, $manager->getCategoryPriority( 'category_two' ) );
$this->assertEquals( 10, $manager->getCategoryPriority( 'category_three' ) );
@@ -169,7 +172,7 @@ class EchoAttributeManagerTest extends MediaWikiTestCase {
],
'category_four' => []
];
- $manager = new EchoAttributeManager( $notif, $category, [], [], [] );
+ $manager = new EchoAttributeManager( $notif, $category, [], [] );
$this->assertEquals( 6, $manager->getNotificationPriority( 'event_one' ) );
$this->assertEquals( 10, $manager->getNotificationPriority( 'event_two' ) );
$this->assertEquals( 10, $manager->getNotificationPriority( 'event_three' ) );
@@ -221,7 +224,7 @@ class EchoAttributeManagerTest extends MediaWikiTestCase {
* @dataProvider getEventsForSectionProvider
*/
public function testGetEventsForSection( $expected, $notificationTypes, $section, $message ) {
- $am = new EchoAttributeManager( $notificationTypes, [], [], [], [] );
+ $am = new EchoAttributeManager( $notificationTypes, [], [], [] );
$actual = $am->getEventsForSection( $section );
$this->assertEquals( $expected, $actual, $message );
}
@@ -255,8 +258,9 @@ class EchoAttributeManagerTest extends MediaWikiTestCase {
'priority' => 10,
],
];
- $manager = new EchoAttributeManager( $notif, $category, [], [], [] );
- $this->assertEquals( $manager->getUserEnabledEvents( $this->mockUser(), 'web' ), [ 'event_two', 'event_three' ] );
+ $manager = new EchoAttributeManager( $notif, $category, [], [] );
+ $this->assertEquals( $manager->getUserEnabledEvents( $this->mockUser(), 'web' ),
+ [ 'event_two', 'event_three' ] );
}
public function testGetUserEnabledEventsbySections() {
@@ -287,7 +291,7 @@ class EchoAttributeManagerTest extends MediaWikiTestCase {
'priority' => 10
],
];
- $manager = new EchoAttributeManager( $notif, $category, [], [], [] );
+ $manager = new EchoAttributeManager( $notif, $category, [], [] );
$expected = [ 'event_one', 'event_three', 'event_four' ];
$actual = $manager->getUserEnabledEventsBySections( $this->mockUser(), 'web', [ 'alert' ] );
sort( $expected );
@@ -301,7 +305,8 @@ class EchoAttributeManagerTest extends MediaWikiTestCase {
$this->assertEquals( $actual, $expected );
$expected = [ 'event_one', 'event_two', 'event_three', 'event_four' ];
- $actual = $manager->getUserEnabledEventsBySections( $this->mockUser(), 'web', [ 'message', 'alert' ] );
+ $actual = $manager->getUserEnabledEventsBySections( $this->mockUser(), 'web',
+ [ 'message', 'alert' ] );
sort( $expected );
sort( $actual );
$this->assertEquals( $actual, $expected );
@@ -352,8 +357,13 @@ class EchoAttributeManagerTest extends MediaWikiTestCase {
/**
* @dataProvider getEventsByCategoryProvider
*/
- public function testGetEventsByCategory( $message, $expectedMapping, $categories, $notifications ) {
- $am = new EchoAttributeManager( $notifications, $categories, [], [], [] );
+ public function testGetEventsByCategory(
+ $message,
+ $expectedMapping,
+ $categories,
+ $notifications
+ ) {
+ $am = new EchoAttributeManager( $notifications, $categories, [], [] );
$actualMapping = $am->getEventsByCategory();
$this->assertEquals( $expectedMapping, $actualMapping, $message );
}
@@ -398,8 +408,16 @@ class EchoAttributeManagerTest extends MediaWikiTestCase {
/**
@dataProvider isNotifyTypeAvailableForCategoryProvider
*/
- public function testIsNotifyTypeAvailableForCategory( $message, $expected, $categoryName, $notifyType, $defaultNotifyTypeAvailability, $notifyTypeAvailabilityByCategory ) {
- $am = new EchoAttributeManager( [], [], $defaultNotifyTypeAvailability, $notifyTypeAvailabilityByCategory, [] );
+ public function testIsNotifyTypeAvailableForCategory(
+ $message,
+ $expected,
+ $categoryName,
+ $notifyType,
+ $defaultNotifyTypeAvailability,
+ $notifyTypeAvailabilityByCategory
+ ) {
+ $am = new EchoAttributeManager( [], [], $defaultNotifyTypeAvailability,
+ $notifyTypeAvailabilityByCategory );
$actual = $am->isNotifyTypeAvailableForCategory( $categoryName, $notifyType );
$this->assertEquals( $expected, $actual, $message );
}
@@ -445,8 +463,14 @@ class EchoAttributeManagerTest extends MediaWikiTestCase {
/**
* @dataProvider isNotifyTypeDismissableForCategoryProvider
*/
- public function testIsNotifyTypeDismissableForCategory( $message, $expected, $categories, $categoryName, $notifyType ) {
- $am = new EchoAttributeManager( [], $categories, [], [], [] );
+ public function testIsNotifyTypeDismissableForCategory(
+ $message,
+ $expected,
+ $categories,
+ $categoryName,
+ $notifyType
+ ) {
+ $am = new EchoAttributeManager( [], $categories, [], [] );
$actual = $am->isNotifyTypeDismissableForCategory( $categoryName, $notifyType );
$this->assertEquals( $expected, $actual, $message );
}
diff --git a/Echo/tests/phpunit/BundlerTest.php b/Echo/tests/phpunit/BundlerTest.php
index bd2f4499..a4a2e258 100644
--- a/Echo/tests/phpunit/BundlerTest.php
+++ b/Echo/tests/phpunit/BundlerTest.php
@@ -1,5 +1,8 @@
<?php
+/**
+ * @covers Bundler
+ */
class BundlerTest extends MediaWikiTestCase {
public function testBundle() {
diff --git a/Echo/tests/phpunit/ContainmentSetTest.php b/Echo/tests/phpunit/ContainmentSetTest.php
index 077e235b..1f538291 100644
--- a/Echo/tests/phpunit/ContainmentSetTest.php
+++ b/Echo/tests/phpunit/ContainmentSetTest.php
@@ -1,7 +1,9 @@
<?php
/**
+ * @covers EchoContainmentSet
* @group Echo
+ * @group Database
*/
class ContainmentSetTest extends MediaWikiTestCase {
@@ -15,6 +17,9 @@ class ContainmentSetTest extends MediaWikiTestCase {
$list->addArray( [ 'whammo' ] );
$this->assertTrue( $list->contains( 'whammo' ) );
+
+ $list->addArray( [ 0 ] );
+ $this->assertFalse( $list->contains( 'baz' ) );
}
public function testCachedListInnerListIsOnlyCalledOnce() {
@@ -46,7 +51,7 @@ class ContainmentSetTest extends MediaWikiTestCase {
}
/**
- * @Database
+ * @group Database
*/
public function testOnWikiList() {
$this->editPage( 'User:Foo/Bar-baz', "abc\ndef\r\nghi\n\n\n" );
diff --git a/Echo/tests/phpunit/DiffParserTest.php b/Echo/tests/phpunit/DiffParserTest.php
index 14dc8a7d..aeecef67 100644
--- a/Echo/tests/phpunit/DiffParserTest.php
+++ b/Echo/tests/phpunit/DiffParserTest.php
@@ -1,6 +1,7 @@
<?php
/**
+ * @covers EchoDiffParser
* @group Echo
*/
class EchoDiffParserTest extends MediaWikiTestCase {
@@ -58,7 +59,7 @@ class EchoDiffParserTest extends MediaWikiTestCase {
],
[
- 'Adding content seperated by no change must generate multiple changes',
+ 'Adding content separated by no change must generate multiple changes',
// Expected change set
[
self::mockAction( 'add', 'b1', 3 ),
diff --git a/Echo/tests/phpunit/DiscussionParserTest.php b/Echo/tests/phpunit/DiscussionParserTest.php
index 35da3fae..391ff078 100644
--- a/Echo/tests/phpunit/DiscussionParserTest.php
+++ b/Echo/tests/phpunit/DiscussionParserTest.php
@@ -1,16 +1,17 @@
<?php
-use MediaWiki\MediaWikiServices;
-use Wikimedia\ScopedCallback;
+// phpcs:disable Generic.Files.LineLength -- Long html test examples
+
use Wikimedia\TestingAccessWrapper;
/**
+ * @covers EchoDiscussionParser
* @group Echo
* @group Database
*/
class EchoDiscussionParserTest extends MediaWikiTestCase {
/**
- * @var array
+ * @var string[]
*/
protected $tablesUsed = [ 'user', 'revision', 'ip_changes', 'text', 'page' ];
@@ -19,7 +20,7 @@ class EchoDiscussionParserTest extends MediaWikiTestCase {
* Can be setup one by one using the setupTestUser() method
* Or all at once using the setupAllTestUsers() method
*
- * @var array [username => [user preference => preference value]]
+ * @var array[] [username => [user preference => preference value]]
*/
protected $testUsers = [
'Werdna' => [
@@ -338,6 +339,23 @@ class EchoDiscussionParserTest extends MediaWikiTestCase {
'title' => 'MultipleSignatureMentions',
'expected' => [],
],
+ [
+ 'new' => 1234,
+ 'old' => 123,
+ 'username' => 'Admin',
+ 'lang' => 'en',
+ 'pages' => [],
+ 'title' => 'Pings in summary',
+ 'expected' => [
+ [
+ 'type' => 'mention-summary',
+ 'agent' => 'Admin',
+ 'section-title' => null,
+ ]
+ ],
+ 'precondition' => '',
+ 'summary' => 'Hey [[User:Werdna|Werdna]] and [[User:Jorm]], [[User:Admin]] here',
+ ],
];
}
@@ -345,7 +363,8 @@ class EchoDiscussionParserTest extends MediaWikiTestCase {
* @dataProvider generateEventsForRevisionData
*/
public function testGenerateEventsForRevision(
- $newId, $oldId, $username, $lang, $pages, $title, $expected, $precondition = ''
+ $newId, $oldId, $username, $lang, $pages, $title, $expected, $precondition = '',
+ $summary = ''
) {
if ( $precondition !== '' ) {
$result = $this->$precondition();
@@ -359,7 +378,7 @@ class EchoDiscussionParserTest extends MediaWikiTestCase {
$this->setupAllTestUsers();
$revision = $this->setupTestRevisionsForEventGeneration(
- $newId, $oldId, $username, $lang, $pages, $title
+ $newId, $oldId, $username, $lang, $pages, $title, $summary
);
$events = [];
$this->setupEventCallbackForEventGeneration(
@@ -373,10 +392,14 @@ class EchoDiscussionParserTest extends MediaWikiTestCase {
}
);
- // disable mention failure and success notifications
- $this->setMwGlobals( 'wgEchoMentionStatusNotifications', false );
+ $this->setMwGlobals( [
+ // disable mention failure and success notifications
+ 'wgEchoMentionStatusNotifications' => false,
+ // enable pings from summary
+ 'wgEchoMaxMentionsInEditSummary' => 5,
+ ] );
- EchoDiscussionParser::generateEventsForRevision( $revision );
+ EchoDiscussionParser::generateEventsForRevision( $revision, false );
$this->assertEquals( $expected, $events );
}
@@ -718,7 +741,7 @@ class EchoDiscussionParserTest extends MediaWikiTestCase {
// enable multiple sections mentions
$this->setMwGlobals( 'wgEchoMentionsOnMultipleSectionEdits', true );
- EchoDiscussionParser::generateEventsForRevision( $revision );
+ EchoDiscussionParser::generateEventsForRevision( $revision, false );
$this->assertEquals( $expected, $events );
}
@@ -920,39 +943,22 @@ TEXT
'wgEchoMaxMentionsCount' => 5
] );
- EchoDiscussionParser::generateEventsForRevision( $revision );
+ EchoDiscussionParser::generateEventsForRevision( $revision, false );
$this->assertEquals( $expected, $events );
}
- private function setupTestRevisionsForEventGeneration( $newId, $oldId, $username, $lang, $pages, $title ) {
- $langObj = Language::factory( $lang );
+ private function setupTestRevisionsForEventGeneration( $newId, $oldId, $username, $lang, $pages,
+ $title, $summary = ''
+ ) {
+ // Content language is used by the code that interprets the namespace part of titles
+ // (Title::getTitleParser), so should be the fake language ;)
+ $this->setContentLang( $lang );
$this->setMwGlobals( [
- // this global is used by the code that interprets the namespace part of
- // titles (Title::getTitleParser), so should be the fake language ;)
- 'wgContLang' => $langObj,
// this one allows Mediawiki:xyz pages to be set as messages
'wgUseDatabaseMessages' => true
] );
-
- // Since we reset the $wgContLang global, reset the TitleParser service
- $services = MediaWikiServices::getInstance();
- if ( is_callable( [ $services, 'getTitleParser' ] ) ) {
- // TODO: All of this should use $this->setService()
- $services->resetServiceForTesting( 'TitleParser' );
- $services->redefineService( 'TitleParser', function () use ( $langObj ) {
- global $wgLocalInterwikis;
- return new MediaWikiTitleCodec(
- $langObj,
- new GenderCache(),
- $wgLocalInterwikis
- );
- } );
- // Cleanup
- $lock = new ScopedCallback( function () use ( $services ) {
- $services->resetServiceForTesting( 'TitleParser' );
- } );
- }
+ $this->overrideMwServices();
// pages to be created: templates may be used to ping users (e.g.
// {{u|...}}) but if we don't have that template, it just won't work!
@@ -988,6 +994,7 @@ TEXT
'parent_id' => $oldId,
'text' => $newText,
'title' => $title,
+ 'comment' => $summary,
];
$revision = Revision::newFromRow( $row );
@@ -1501,9 +1508,13 @@ TEXT
];
}
- public static function getExemplarTimestamp() {
- $title = Title::newMainPage();
- $user = User::newFromName( 'Test' );
+ public function getExemplarTimestamp() {
+ $title = $this->getMockBuilder( Title::class )
+ ->getMock();
+
+ $user = $this->getMockBuilder( User::class )
+ ->getMock();
+
$options = new ParserOptions;
global $wgParser;
@@ -1795,7 +1806,7 @@ TEXT
}
protected function isParserFunctionsInstalled() {
- if ( class_exists( 'ExtParserFunctions' ) ) {
+ if ( ExtensionRegistry::getInstance()->isLoaded( 'ParserFunctions' ) ) {
return true;
} else {
return "ParserFunctions not enabled";
diff --git a/Echo/tests/phpunit/EchoDbFactoryTest.php b/Echo/tests/phpunit/EchoDbFactoryTest.php
index 18ac1170..337c92d3 100644
--- a/Echo/tests/phpunit/EchoDbFactoryTest.php
+++ b/Echo/tests/phpunit/EchoDbFactoryTest.php
@@ -1,5 +1,11 @@
<?php
+use Wikimedia\Rdbms\IDatabase;
+use Wikimedia\Rdbms\ILoadBalancer;
+
+/**
+ * @covers MWEchoDbFactory
+ */
class MWEchoDbFactoryTest extends MediaWikiTestCase {
public function testNewFromDefault() {
@@ -13,8 +19,8 @@ class MWEchoDbFactoryTest extends MediaWikiTestCase {
* @depends testNewFromDefault
*/
public function testGetEchoDb( MWEchoDbFactory $db ) {
- $this->assertInstanceOf( 'DatabaseBase', $db->getEchoDb( DB_MASTER ) );
- $this->assertInstanceOf( 'DatabaseBase', $db->getEchoDb( DB_SLAVE ) );
+ $this->assertInstanceOf( IDatabase::class, $db->getEchoDb( DB_MASTER ) );
+ $this->assertInstanceOf( IDatabase::class, $db->getEchoDb( DB_REPLICA ) );
}
/**
@@ -24,7 +30,7 @@ class MWEchoDbFactoryTest extends MediaWikiTestCase {
$reflection = new ReflectionClass( 'MWEchoDbFactory' );
$method = $reflection->getMethod( 'getLB' );
$method->setAccessible( true );
- $this->assertInstanceOf( 'LoadBalancer', $method->invoke( $db ) );
+ $this->assertInstanceOf( ILoadBalancer::class, $method->invoke( $db ) );
}
}
diff --git a/Echo/tests/phpunit/EchoHooksTest.php b/Echo/tests/phpunit/EchoHooksTest.php
new file mode 100644
index 00000000..d1f2ac56
--- /dev/null
+++ b/Echo/tests/phpunit/EchoHooksTest.php
@@ -0,0 +1,53 @@
+<?php
+
+class EchoHooksTest extends MediaWikiTestCase {
+ /**
+ * @covers \EchoHooks::onUserGetDefaultOptions()
+ */
+ public function testOnUserGetDefaultOptions() {
+ $this->setMwGlobals( [
+ 'wgEchoNotificationCategories' => [
+ 'emailuser' => [
+ 'priority' => 9,
+ 'tooltip' => 'echo-pref-tooltip-emailuser',
+ ],
+ 'mention' => [
+ 'priority' => 4,
+ 'tooltip' => 'echo-pref-tooltip-mention',
+ ],
+ 'system' => [
+ 'priority' => 9,
+ 'no-dismiss' => [
+ 'all'
+ ],
+ ],
+ 'some-custom-category' => [
+ 'priority' => 9001,
+ ],
+ ],
+ 'wgAllowHTMLEmail' => true,
+ ] );
+
+ $defaults = [
+ 'something' => 'unrelated',
+ // T174220: don't overwrite defaults set elsewhere
+ 'echo-subscriptions-web-mention' => false,
+ ];
+ EchoHooks::onUserGetDefaultOptions( $defaults );
+ self::assertEquals(
+ [
+ 'something' => 'unrelated',
+ 'echo-email-format' => 'html',
+ 'echo-subscriptions-email-mention' => false,
+ 'echo-subscriptions-web-mention' => false,
+ 'echo-subscriptions-email-emailuser' => false,
+ 'echo-subscriptions-web-emailuser' => true,
+ 'echo-subscriptions-email-system' => true,
+ 'echo-subscriptions-web-system' => true,
+ 'echo-subscriptions-email-some-custom-category' => false,
+ 'echo-subscriptions-web-some-custom-category' => true,
+ ],
+ $defaults
+ );
+ }
+}
diff --git a/Echo/tests/phpunit/EchoSummaryParserTest.php b/Echo/tests/phpunit/EchoSummaryParserTest.php
new file mode 100644
index 00000000..357036fc
--- /dev/null
+++ b/Echo/tests/phpunit/EchoSummaryParserTest.php
@@ -0,0 +1,68 @@
+<?php
+
+/**
+ * @group Echo
+ */
+class EchoSummaryParserTest extends MediaWikiTestCase {
+ private $existingUsers = [
+ 'Werdna',
+ 'Jorm',
+ 'Jim Carter',
+ ];
+ /**
+ * @covers EchoSummaryParser::parse
+ * @dataProvider provideParse
+ *
+ * @param string $summary
+ * @param string[] $expectedUsers
+ */
+ public function testParse( $summary, array $expectedUsers ) {
+ $parser = new EchoSummaryParser( function ( User $user ) {
+ if ( in_array( $user->getName(), $this->existingUsers ) ) {
+ return crc32( $user->getName() );
+ }
+ return 0;
+ } );
+
+ $users = $parser->parse( $summary );
+ foreach ( $users as $name => $user ) {
+ $this->assertType( User::class, $user );
+ $this->assertEquals( $name, $user->getName() );
+ }
+
+ $users = array_keys( $users );
+
+ $this->assertArrayEquals( $expectedUsers, $users );
+ }
+
+ public function provideParse() {
+ return [
+ [ '', [] ],
+ [ " \t\r\n ", [] ],
+ [ 'foo bar', [] ],
+ [ 'Werdna', [] ],
+ [ 'User:Werdna', [] ],
+ [ '[User:Werdna]', [] ],
+ [ '[[]]', [] ],
+ [ '[[:]]', [] ],
+ [ '[[|]]', [] ],
+ [ '[[:|]]', [] ],
+ [ '[[:|test]]', [] ],
+ [ '[[User:Nonexistent]]', [] ],
+ [ '/* [[User:Werdna */', [] ],
+ [ '[[User talk:Werdna]]', [] ],
+ [ '[[User:Werdna]]', [ 'Werdna' ] ],
+ [ 'this is [[ [[User:Werdna]] ]]', [ 'Werdna' ] ],
+ [ '[[User:Werdna|]]', [ 'Werdna' ] ],
+ [ '[[User:Werdna| ]]', [ 'Werdna' ] ],
+ [ '[[User:Werdna|Wer | d[n]a]]', [ 'Werdna' ] ],
+ [ '[[User:Werdna]][[User:Werdna]][[User:Werdna]]', [ 'Werdna' ] ],
+ [ '/**/[[User:Werdna]][[user:jorm]]', [ 'Werdna', 'Jorm' ] ],
+ [ '/* [[User:Werdna]] */ [[ user : jim_ Carter_]]', [ 'Jim Carter' ] ],
+ [ '[[User:/* Jorm */]][[User:/* remove me */Werdna]]', [] ],
+ [ '[[:User:Werdna]]', [] ],
+ [ '[[:User:Werdna|]]', [] ],
+ [ '[[:User:Werdna|foo]]', [] ],
+ ];
+ }
+}
diff --git a/Echo/tests/phpunit/NotifUserTest.php b/Echo/tests/phpunit/NotifUserTest.php
index d766a546..b25f3dc5 100644
--- a/Echo/tests/phpunit/NotifUserTest.php
+++ b/Echo/tests/phpunit/NotifUserTest.php
@@ -1,7 +1,9 @@
<?php
+
use MediaWiki\MediaWikiServices;
/**
+ * @covers MWEchoNotifUser
* @group Echo
*/
class MWEchoNotifUserTest extends MediaWikiTestCase {
@@ -33,45 +35,6 @@ class MWEchoNotifUserTest extends MediaWikiTestCase {
$this->assertInstanceOf( 'MWEchoNotifUser', $notifUser );
}
- public function testFlagCacheWithNewTalkNotification() {
- $notifUser = $this->newNotifUser();
-
- $notifUser->flagCacheWithNewTalkNotification();
- $this->assertEquals( '1', $this->cache->get( $notifUser->getTalkNotificationCacheKey() ) );
- }
-
- public function testFlagCacheWithNoTalkNotification() {
- $notifUser = $this->newNotifUser();
-
- $notifUser->flagCacheWithNoTalkNotification();
- $this->assertEquals( '0', $this->cache->get( $notifUser->getTalkNotificationCacheKey() ) );
- }
-
- public function testNotifCountHasReachedMax() {
- $notifUser = $this->newNotifUser();
-
- if ( $notifUser->getLocalNotificationCount() > MWEchoNotifUser::MAX_BADGE_COUNT ) {
- $this->assertTrue( $notifUser->notifCountHasReachedMax() );
- } else {
- $this->assertFalse( $notifUser->notifCountHasReachedMax() );
- }
- }
-
- public function testClearTalkNotification() {
- $notifUser = $this->newNotifUser();
-
- $notifUser->flagCacheWithNewTalkNotification();
-
- $hasMax = $notifUser->notifCountHasReachedMax();
-
- $notifUser->clearTalkNotification();
- if ( $hasMax ) {
- $this->assertEquals( '1', $this->cache->get( $notifUser->getTalkNotificationCacheKey() ) );
- } else {
- $this->assertEquals( '0', $this->cache->get( $notifUser->getTalkNotificationCacheKey() ) );
- }
- }
-
public function testGetEmailFormat() {
$user = User::newFromId( 2 );
$notifUser = MWEchoNotifUser::newFromUser( $user );
@@ -156,6 +119,12 @@ class MWEchoNotifUserTest extends MediaWikiTestCase {
$gateway->expects( $this->any() )
->method( 'markRead' )
->will( $this->returnValue( $dbResult['markRead'] ) );
+ $gateway->expects( $this->any() )
+ ->method( 'getDB' )
+ ->will( $this->returnValue(
+ $this->getMockBuilder( Database::class )
+ ->disableOriginalConstructor()->getMock()
+ ) );
return $gateway;
}
@@ -171,15 +140,10 @@ class MWEchoNotifUserTest extends MediaWikiTestCase {
return $mapper;
}
- public function mockEchoTargetPageMapper( array $result = [] ) {
- $mapper = $this->getMockBuilder( 'EchoTargetPageMapper' )
+ public function mockEchoTargetPageMapper() {
+ return $this->getMockBuilder( EchoTargetPageMapper::class )
->disableOriginalConstructor()
->getMock();
- $mapper->expects( $this->any() )
- ->method( 'deleteByUserEvents' )
- ->will( $this->returnValue( $result ) );
-
- return $mapper;
}
protected function mockEchoNotification() {
diff --git a/Echo/tests/phpunit/NotificationStructureTest.php b/Echo/tests/phpunit/NotificationStructureTest.php
new file mode 100644
index 00000000..17f5a5f3
--- /dev/null
+++ b/Echo/tests/phpunit/NotificationStructureTest.php
@@ -0,0 +1,40 @@
+<?php
+
+class NotificationStructureTest extends MediaWikiTestCase {
+ /**
+ * @coversNothing
+ * @dataProvider provideNotificationTypes
+ *
+ * @param string $type
+ * @param array $info
+ */
+ public function testNotificationTypes( $type, array $info ) {
+ if ( isset( $info['presentation-model'] ) ) {
+ self::assertTrue( class_exists( $info['presentation-model'] ),
+ "Presentation model class {$info['presentation-model']} for {$type} must exist"
+ );
+ }
+
+ if ( isset( $info['user-locators'] ) ) {
+ $locators = $info['user-locators'];
+ $locator = reset( $locators );
+ if ( is_array( $locator ) ) {
+ $locator = reset( $locator );
+ }
+ self::assertTrue( is_callable( $locator ),
+ 'User locator ' . print_r( $locator, true ) . " for {$type} must be callable"
+ );
+ }
+ }
+
+ public function provideNotificationTypes() {
+ global $wgEchoNotifications;
+
+ $result = [];
+ foreach ( $wgEchoNotifications as $type => $info ) {
+ $result[] = [ $type, $info ];
+ }
+
+ return $result;
+ }
+}
diff --git a/Echo/tests/NotificationsTest.php b/Echo/tests/phpunit/NotificationsTest.php
index cc7ddfe6..641e6bd0 100644
--- a/Echo/tests/NotificationsTest.php
+++ b/Echo/tests/phpunit/NotificationsTest.php
@@ -24,14 +24,15 @@ class NotificationsTest extends MediaWikiTestCase {
* @return EchoEvent
*/
public static function getLatestNotification( $user ) {
- $notifs = ApiEchoNotifications::getNotifications( $user );
- $index = array_keys( $notifs );
+ $notifMapper = new EchoNotificationMapper();
+ $notifs = $notifMapper->fetchUnreadByUser( $user, 1, '', [ 'user-rights' ] );
+ $notif = array_pop( $notifs );
- return EchoEvent::newFromID( $notifs[$index[0]]['id'] );
+ return $notif->getEvent();
}
/**
- * @covers EchoHooks::onUserRights
+ * @covers EchoHooks::onUserGroupsChanged
*/
public function testUserRightsNotif() {
$user = new User();
diff --git a/Echo/tests/phpunit/TalkPageFunctionalTest.php b/Echo/tests/phpunit/TalkPageFunctionalTest.php
index 4c80f2e0..f33e5020 100644
--- a/Echo/tests/phpunit/TalkPageFunctionalTest.php
+++ b/Echo/tests/phpunit/TalkPageFunctionalTest.php
@@ -2,22 +2,26 @@
/**
* @group Echo
- * @group DataBase
+ * @group Database
* @group medium
*/
class EchoTalkPageFunctionalTest extends ApiTestCase {
+ /**
+ * @var \Wikimedia\Rdbms\IDatabase
+ */
protected $dbr;
protected function setUp() {
parent::setUp();
- $this->dbr = MWEchoDbFactory::getDB( DB_SLAVE );
+ $this->dbr = MWEchoDbFactory::getDB( DB_REPLICA );
}
/**
* Creates and updates a user talk page a few times to ensure proper events are
* created. The user performing the edits is self::$users['sysop'].
* @group Broken
+ * @covers \EchoDiscussionParser
*/
public function testAddCommentsToTalkPage() {
$editor = self::$users['sysop']->getUser()->getName();
@@ -76,7 +80,7 @@ class EchoTalkPageFunctionalTest extends ApiTestCase {
}
/**
- * @return array All events in db sorted from oldest to newest
+ * @return \stdClass[] All events in db sorted from oldest to newest
*/
protected function fetchAllEvents() {
$res = $this->dbr->select( 'echo_event', [ '*' ], [], __METHOD__, [ 'ORDER BY' => 'event_id ASC' ] );
diff --git a/Echo/tests/phpunit/ThankYouEditTest.php b/Echo/tests/phpunit/ThankYouEditTest.php
index a573bdb1..5325c5cd 100644
--- a/Echo/tests/phpunit/ThankYouEditTest.php
+++ b/Echo/tests/phpunit/ThankYouEditTest.php
@@ -2,6 +2,7 @@
/**
* @group Echo
+ * @group Database
*/
class MWEchoThankYouEditTest extends MediaWikiTestCase {
@@ -17,6 +18,9 @@ class MWEchoThankYouEditTest extends MediaWikiTestCase {
$db->delete( 'echo_notification', '*', __METHOD__ );
}
+ /**
+ * @covers \EchoHooks::onPageContentSaveComplete
+ */
public function testFirstEdit() {
// setup
$this->deleteEchoData();
@@ -36,6 +40,9 @@ class MWEchoThankYouEditTest extends MediaWikiTestCase {
$this->assertEquals( 1, $notification->getEvent()->getExtraParam( 'editCount', 'not found' ) );
}
+ /**
+ * @covers \EchoHooks::onPageContentSaveComplete
+ */
public function testTenthEdit() {
// setup
$this->deleteEchoData();
diff --git a/Echo/tests/phpunit/UserLocatorTest.php b/Echo/tests/phpunit/UserLocatorTest.php
index f09f80a9..514c8226 100644
--- a/Echo/tests/phpunit/UserLocatorTest.php
+++ b/Echo/tests/phpunit/UserLocatorTest.php
@@ -1,7 +1,8 @@
<?php
/**
- * @Database
+ * @group Database
+ * @covers EchoUserLocator
*/
class EchoUserLocatorTest extends MediaWikiTestCase {
diff --git a/Echo/tests/phpunit/api/ApiEchoMarkReadTest.php b/Echo/tests/phpunit/api/ApiEchoMarkReadTest.php
index 135d1867..9c41ec37 100644
--- a/Echo/tests/phpunit/api/ApiEchoMarkReadTest.php
+++ b/Echo/tests/phpunit/api/ApiEchoMarkReadTest.php
@@ -4,15 +4,10 @@
* @group medium
* @group API
* @group Database
- * @covers ApiQuery
+ * @covers ApiEchoMarkRead
*/
class ApiEchoMarkReadTest extends ApiTestCase {
- protected function setUp() {
- parent::setUp();
- $this->doLogin();
- }
-
function getTokens() {
return $this->getTokenList( self::$users['sysop'] );
}
diff --git a/Echo/tests/phpunit/api/ApiEchoNotificationsTest.php b/Echo/tests/phpunit/api/ApiEchoNotificationsTest.php
index 9f86a6ef..cfcf5c90 100644
--- a/Echo/tests/phpunit/api/ApiEchoNotificationsTest.php
+++ b/Echo/tests/phpunit/api/ApiEchoNotificationsTest.php
@@ -3,7 +3,7 @@
/**
* @group medium
* @group API
- * @covers ApiQuery
+ * @covers ApiEchoNotifications
*/
class ApiEchoNotificationsTest extends ApiTestCase {
diff --git a/Echo/tests/phpunit/cache/TitleLocalCacheTest.php b/Echo/tests/phpunit/cache/TitleLocalCacheTest.php
index af255edb..fdd722d3 100644
--- a/Echo/tests/phpunit/cache/TitleLocalCacheTest.php
+++ b/Echo/tests/phpunit/cache/TitleLocalCacheTest.php
@@ -1,90 +1,85 @@
<?php
+use Wikimedia\TestingAccessWrapper;
+
+/**
+ * @covers EchoTitleLocalCache
+ * @group Database
+ */
class EchoTitleLocalCacheTest extends MediaWikiTestCase {
public function testCreate() {
$cache = EchoTitleLocalCache::create();
- $this->assertInstanceOf( 'EchoTitleLocalCache', $cache );
-
- return $cache;
+ $this->assertInstanceOf( EchoTitleLocalCache::class, $cache );
}
- /**
- * @depends testCreate
- */
- public function testAdd( $cache ) {
- $cache->clearAll();
+ public function testAdd() {
+ $cache = $this->getMockBuilder( EchoTitleLocalCache::class )
+ ->setMethods( [ 'resolve' ] )->getMock();
+
$cache->add( 1 );
- $this->assertEquals( count( $cache->getLookups() ), 1 );
- $this->assertArrayHasKey( 1, $cache->getLookups() );
+ $cache->add( 9 );
+
+ // Resolutions should be batched
+ $cache->expects( $this->exactly( 1 ) )->method( 'resolve' )
+ ->with( [ 1, 9 ] )->willReturn( [] );
+
+ // Trigger
+ $cache->get( 9 );
}
- /**
- * @depends testCreate
- */
- public function testGet( $cache ) {
- $map = new HashBagOStuff( [ 'maxKeys' => EchoLocalCache::TARGET_MAX_NUM ] );
- $titleIds = [];
+ public function testGet() {
+ $cache = $this->getMockBuilder( EchoTitleLocalCache::class )
+ ->setMethods( [ 'resolve' ] )->getMock();
+ $cachePriv = TestingAccessWrapper::newFromObject( $cache );
// First title included in cache
- $res = $this->insertPage( 'EchoTitleLocalCacheTest_testGet' );
- $titleIds[$res['id']] = $res['id'];
- $map->set( $res['id'], $res['title'] );
-
+ $res1 = $this->insertPage( 'EchoTitleLocalCacheTest_testGet1' );
+ $cachePriv->targets->set( $res1['id'], $res1['title'] );
// Second title not in internal cache, resolves from db.
- $res = $this->insertPage( 'EchoTitleLocalCacheTest_testGet2' );
- $titleIds[$res['id']] = $res['id'];
-
- $object = new \ReflectionObject( $cache );
-
- // Load our generated map in as the targets (known mapping from
- // title id to title object) into $cache
- $targets = $object->getProperty( 'targets' );
- $targets->setAccessible( true );
- $targets->setValue( $cache, $map );
-
- // Load both of the titles we are curious about into the list of titles
- // to be looked up
- $lookups = $object->getProperty( 'lookups' );
- $lookups->setAccessible( true );
- $lookups->setValue( $cache, $titleIds );
-
- // Requesting the first object, which is within the known targets, should
- // not resolve the pending lookups.
- $this->assertInstanceOf( 'Title', $cache->get( reset( $titleIds ) ) );
- $this->assertGreaterThan( 0, count( $cache->getLookups() ) );
-
- // Requesting the second object, which is not within the known targets, should
- // resolve the pending lookups and reset the list to lookup.
- $this->assertInstanceOf( 'Title', $cache->get( end( $titleIds ) ) );
- $this->assertEquals( 0, count( $cache->getLookups() ) );
+ $res2 = $this->insertPage( 'EchoTitleLocalCacheTest_testGet2' );
+ $cache->expects( $this->exactly( 1 ) )->method( 'resolve' )
+ ->with( [ $res2['id'] ] )
+ ->willReturn( [ $res2['id'] => $res2['title'] ] );
+
+ // Register demand for both
+ $cache->add( $res1['id'] );
+ $cache->add( $res2['id'] );
+
+ // Should not call resolve() for first title
+ $this->assertSame( $res1['title'], $cache->get( $res1['id'] ), 'First title' );
+
+ // Should resolve() for second title
+ $this->assertSame( $res2['title'], $cache->get( $res2['id'] ), 'Second title' );
}
- /**
- * @depends testCreate
- */
- public function testClearAll( $cache ) {
- $map = new HashBagOStuff( [ 'maxKeys' => EchoLocalCache::TARGET_MAX_NUM ] );
- $map->set( 1, $this->mockTitle() );
- $object = new \ReflectionObject( $cache );
- $targets = $object->getProperty( 'targets' );
- $targets->setAccessible( true );
- $targets->setValue( $cache, $map );
- $lookups = $object->getProperty( 'lookups' );
- $lookups->setAccessible( true );
- $lookups->setValue( $cache, [ '1' => '1', '2' => '2' ] );
+ public function testClearAll() {
+ $cache = $this->getMockBuilder( EchoTitleLocalCache::class )
+ ->setMethods( [ 'resolve' ] )->getMock();
+ // Add 1 to cache
+ $cachePriv = TestingAccessWrapper::newFromObject( $cache );
+ $cachePriv->targets->set( 1, $this->mockTitle() );
+ // Add 2 and 3 to demand
+ $cache->add( 2 );
+ $cache->add( 3 );
$cache->clearAll();
- $this->assertTrue( count( $cache->getLookups() ) == 0 );
- $this->assertEquals( false, $cache->getTargets()->get( 1 ) );
- $this->assertEquals( false, $cache->getTargets()->get( '1' ) );
+
+ $this->assertSame( null, $cache->get( 1 ), 'Cache was cleared' );
+
+ // Lookups batch was cleared
+ $cache->expects( $this->exactly( 1 ) )->method( 'resolve' )
+ ->with( [ 4 ] )
+ ->willReturn( [] );
+ $cache->add( 4 );
+ $cache->get( 4 );
}
/**
- * Mock object of Title
+ * @return Title
*/
protected function mockTitle() {
- $title = $this->getMockBuilder( 'Title' )
+ $title = $this->getMockBuilder( Title::class )
->disableOriginalConstructor()
->getMock();
diff --git a/Echo/tests/phpunit/controller/NotificationControllerTest.php b/Echo/tests/phpunit/controller/NotificationControllerTest.php
index 8a38a7e5..9e497024 100644
--- a/Echo/tests/phpunit/controller/NotificationControllerTest.php
+++ b/Echo/tests/phpunit/controller/NotificationControllerTest.php
@@ -1,5 +1,8 @@
<?php
+/**
+ * @covers EchoNotificationController
+ */
class NotificationControllerTest extends MediaWikiTestCase {
public function evaluateUserLocatorsProvider() {
diff --git a/Echo/tests/phpunit/gateway/UserNotificationGatewayTest.php b/Echo/tests/phpunit/gateway/UserNotificationGatewayTest.php
index 7e656e19..2cc4fd78 100644
--- a/Echo/tests/phpunit/gateway/UserNotificationGatewayTest.php
+++ b/Echo/tests/phpunit/gateway/UserNotificationGatewayTest.php
@@ -1,11 +1,14 @@
<?php
+/**
+ * @covers EchoUserNotificationGateway
+ */
class EchoUserNotificationGatewayTest extends MediaWikiTestCase {
public function testMarkRead() {
// no event ids to mark
$gateway = new EchoUserNotificationGateway( User::newFromId( 1 ), $this->mockMWEchoDbFactory() );
- $this->assertNull( $gateway->markRead( [] ) );
+ $this->assertFalse( $gateway->markRead( [] ) );
// successful update
$gateway = new EchoUserNotificationGateway( User::newFromId( 1 ), $this->mockMWEchoDbFactory( [ 'update' => true ] ) );
@@ -29,19 +32,19 @@ class EchoUserNotificationGatewayTest extends MediaWikiTestCase {
public function testGetNotificationCount() {
// unsuccessful select
$gateway = new EchoUserNotificationGateway( $this->mockUser(), $this->mockMWEchoDbFactory( [ 'selectRowCount' => 0 ] ) );
- $this->assertEquals( 0, $gateway->getCappedNotificationCount( DB_SLAVE, [ 'event_one' ] ) );
+ $this->assertEquals( 0, $gateway->getCappedNotificationCount( DB_REPLICA, [ 'event_one' ] ) );
// successful select of alert
$gateway = new EchoUserNotificationGateway( $this->mockUser(), $this->mockMWEchoDbFactory( [ 'selectRowCount' => 2 ] ) );
- $this->assertEquals( 2, $gateway->getCappedNotificationCount( DB_SLAVE, [ 'event_one', 'event_two' ] ) );
+ $this->assertEquals( 2, $gateway->getCappedNotificationCount( DB_REPLICA, [ 'event_one', 'event_two' ] ) );
// there is event, should return 0
$gateway = new EchoUserNotificationGateway( $this->mockUser(), $this->mockMWEchoDbFactory( [ 'selectRowCount' => 2 ] ) );
- $this->assertEquals( 0, $gateway->getCappedNotificationCount( DB_SLAVE, [] ) );
+ $this->assertEquals( 0, $gateway->getCappedNotificationCount( DB_REPLICA, [] ) );
// successful select
$gateway = new EchoUserNotificationGateway( $this->mockUser(), $this->mockMWEchoDbFactory( [ 'selectRowCount' => 3 ] ) );
- $this->assertEquals( 3, $gateway->getCappedNotificationCount( DB_SLAVE, [ 'event_one' ] ) );
+ $this->assertEquals( 3, $gateway->getCappedNotificationCount( DB_REPLICA, [ 'event_one' ] ) );
}
public function testGetUnreadNotifications() {
@@ -93,7 +96,8 @@ class EchoUserNotificationGatewayTest extends MediaWikiTestCase {
}
/**
- * Mock object of DatabaseMysql ( DatabaseBase )
+ * Returns a mock database object
+ * @return \Wikimedia\Rdbms\IDatabase
*/
protected function mockDb( array $dbResult = [] ) {
$dbResult += [
@@ -102,7 +106,7 @@ class EchoUserNotificationGatewayTest extends MediaWikiTestCase {
'selectRow' => '',
'selectRowCount' => '',
];
- $db = $this->getMockBuilder( 'DatabaseMysql' )
+ $db = $this->getMockBuilder( 'DatabaseMysqli' )
->disableOriginalConstructor()
->getMock();
$db->expects( $this->any() )
@@ -117,9 +121,10 @@ class EchoUserNotificationGatewayTest extends MediaWikiTestCase {
$db->expects( $this->any() )
->method( 'selectRowCount' )
->will( $this->returnValue( $dbResult['selectRowCount'] ) );
+ $numRows = is_array( $dbResult['select'] ) ? count( $dbResult['select'] ) : 0;
$db->expects( $this->any() )
->method( 'numRows' )
- ->will( $this->returnValue( count( $dbResult['select'] ) ) );
+ ->will( $this->returnValue( $numRows ) );
return $db;
}
diff --git a/Echo/tests/phpunit/iterator/FilteredSequentialIteratorTest.php b/Echo/tests/phpunit/iterator/FilteredSequentialIteratorTest.php
index b05e3229..7042d633 100644
--- a/Echo/tests/phpunit/iterator/FilteredSequentialIteratorTest.php
+++ b/Echo/tests/phpunit/iterator/FilteredSequentialIteratorTest.php
@@ -1,5 +1,9 @@
<?php
+/**
+ * @covers EchoCallbackIterator
+ * @covers EchoFilteredSequentialIterator
+ */
class FilteredSequentialIteratorTest extends MediaWikiTestCase {
public function testEchoCallbackIteratorDoesntBlowUp() {
diff --git a/Echo/tests/phpunit/maintenance/SupressionMaintenanceTest.php b/Echo/tests/phpunit/maintenance/SupressionMaintenanceTest.php
index 0a32d8af..029be88f 100644
--- a/Echo/tests/phpunit/maintenance/SupressionMaintenanceTest.php
+++ b/Echo/tests/phpunit/maintenance/SupressionMaintenanceTest.php
@@ -2,6 +2,7 @@
/**
* @group Echo
+ * @covers EchoSuppressionRowUpdateGenerator
*/
class SuppressionMaintenanceTest extends MediaWikiTestCase {
diff --git a/Echo/tests/phpunit/mapper/AbstractMapperTest.php b/Echo/tests/phpunit/mapper/AbstractMapperTest.php
index 5c3a5826..02194a02 100644
--- a/Echo/tests/phpunit/mapper/AbstractMapperTest.php
+++ b/Echo/tests/phpunit/mapper/AbstractMapperTest.php
@@ -1,5 +1,8 @@
<?php
+/**
+ * @covers EchoAbstractMapper
+ */
class EchoAbstractMapperTest extends MediaWikiTestCase {
public function testAttachListener() {
@@ -65,13 +68,3 @@ class EchoAbstractMapperTest extends MediaWikiTestCase {
}
}
-
-/**
- * Create a stub class for testing the abstract class
- */
-class EchoAbstractMapperStub extends EchoAbstractMapper {
-
- public function testMethod() {
- }
-
-}
diff --git a/Echo/tests/phpunit/mapper/EchoAbstractMapperStub.php b/Echo/tests/phpunit/mapper/EchoAbstractMapperStub.php
new file mode 100644
index 00000000..359e97ff
--- /dev/null
+++ b/Echo/tests/phpunit/mapper/EchoAbstractMapperStub.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * Create a stub class for testing the abstract class
+ */
+class EchoAbstractMapperStub extends EchoAbstractMapper {
+
+ public function testMethod() {
+ }
+
+}
diff --git a/Echo/tests/phpunit/mapper/EchoExecuteFirstArgumentStub.php b/Echo/tests/phpunit/mapper/EchoExecuteFirstArgumentStub.php
new file mode 100644
index 00000000..1e2889e7
--- /dev/null
+++ b/Echo/tests/phpunit/mapper/EchoExecuteFirstArgumentStub.php
@@ -0,0 +1,18 @@
+<?php
+
+class EchoExecuteFirstArgumentStub implements PHPUnit_Framework_MockObject_Stub {
+ public function invoke( PHPUnit_Framework_MockObject_Invocation $invocation ) {
+ if ( !$invocation instanceof PHPUnit_Framework_MockObject_Invocation_Static ) {
+ throw new PHPUnit_Framework_Exception( 'wrong invocation type' );
+ }
+ if ( !$invocation->arguments ) {
+ throw new PHPUnit_Framework_Exception( 'Method call must have an argument' );
+ }
+
+ return call_user_func( reset( $invocation->arguments ) );
+ }
+
+ public function toString() {
+ return 'return result of call_user_func on first invocation argument';
+ }
+}
diff --git a/Echo/tests/phpunit/mapper/EventMapperTest.php b/Echo/tests/phpunit/mapper/EventMapperTest.php
index e9528ca9..e81e183d 100644
--- a/Echo/tests/phpunit/mapper/EventMapperTest.php
+++ b/Echo/tests/phpunit/mapper/EventMapperTest.php
@@ -1,5 +1,8 @@
<?php
+/**
+ * @covers EchoEventMapper
+ */
class EchoEventMapperTest extends MediaWikiTestCase {
public function provideDataTestInsert() {
@@ -99,7 +102,8 @@ class EchoEventMapperTest extends MediaWikiTestCase {
}
/**
- * Mock object of DatabaseMysql ( DatabaseBase )
+ * Returns a mock database object
+ * @return \Wikimedia\Rdbms\IDatabase
*/
protected function mockDb( array $dbResult ) {
$dbResult += [
@@ -108,7 +112,7 @@ class EchoEventMapperTest extends MediaWikiTestCase {
'select' => '',
'selectRow' => ''
];
- $db = $this->getMockBuilder( 'DatabaseMysql' )
+ $db = $this->getMockBuilder( 'DatabaseMysqli' )
->disableOriginalConstructor()
->getMock();
$db->expects( $this->any() )
diff --git a/Echo/tests/phpunit/mapper/NotificationMapperTest.php b/Echo/tests/phpunit/mapper/NotificationMapperTest.php
index 420c0934..62359a9c 100644
--- a/Echo/tests/phpunit/mapper/NotificationMapperTest.php
+++ b/Echo/tests/phpunit/mapper/NotificationMapperTest.php
@@ -1,5 +1,8 @@
<?php
+/**
+ * @covers EchoNotificationMapper
+ */
class EchoNotificationMapperTest extends MediaWikiTestCase {
/**
@@ -39,8 +42,8 @@ class EchoNotificationMapperTest extends MediaWikiTestCase {
$notifMapper = new EchoNotificationMapper( $this->mockMWEchoDbFactory( [ 'select' => $dbResult ] ) );
$res = $notifMapper->fetchUnreadByUser( $this->mockUser(), 10, null, '', [ 'test_event' ] );
- $this->assertTrue( is_array( $res ) );
- $this->assertGreaterThan( 0, count( $res ) );
+ $this->assertInternalType( 'array', $res );
+ $this->assertNotEmpty( $res );
foreach ( $res as $row ) {
$this->assertInstanceOf( 'EchoNotification', $row );
}
@@ -90,8 +93,8 @@ class EchoNotificationMapperTest extends MediaWikiTestCase {
)
);
$res = $notifMapper->fetchByUser( $this->mockUser(), 10, '', [ 'test_event' ] );
- $this->assertTrue( is_array( $res ) );
- $this->assertGreaterThan( 0, count( $res ) );
+ $this->assertInternalType( 'array', $res );
+ $this->assertNotEmpty( $res );
foreach ( $res as $row ) {
$this->assertInstanceOf( 'EchoNotification', $row );
}
@@ -158,13 +161,36 @@ class EchoNotificationMapperTest extends MediaWikiTestCase {
}
public function testDeleteByUserEventOffset() {
- $dbResult = [ 'delete' => true ];
- $notifMapper = new EchoNotificationMapper( $this->mockMWEchoDbFactory( $dbResult ) );
- $this->assertTrue( $notifMapper->deleteByUserEventOffset( User::newFromId( 1 ), 500 ) );
+ $this->setMwGlobals( [ 'wgUpdateRowsPerQuery' => 4 ] );
+ $mockDb = $this->getMockBuilder( 'DatabaseMysqli' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ $mockDb->expects( $this->any() )
+ ->method( 'selectFieldValues' )
+ ->will( $this->returnValue( [ 1, 2, 3, 5, 8, 13, 21, 34, 55, 89 ] ) );
+ $mockDb->expects( $this->exactly( 3 ) )
+ ->method( 'delete' )
+ ->withConsecutive(
+ [
+ $this->equalTo( 'echo_notification' ),
+ $this->equalTo( [ 'notification_user' => 1, 'notification_event' => [ 1, 2, 3, 5 ] ] ),
+ $this->anything()
+ ],
+ [
+ $this->equalTo( 'echo_notification' ),
+ $this->equalTo( [ 'notification_user' => 1, 'notification_event' => [ 8, 13, 21, 34 ] ] ),
+ $this->anything()
+ ],
+ [
+ $this->equalTo( 'echo_notification' ),
+ $this->equalTo( [ 'notification_user' => 1, 'notification_event' => [ 55, 89 ] ] ),
+ $this->anything()
+ ]
+ )
+ ->will( $this->returnValue( true ) );
- $dbResult = [ 'delete' => false ];
- $notifMapper = new EchoNotificationMapper( $this->mockMWEchoDbFactory( $dbResult ) );
- $this->assertFalse( $notifMapper->deleteByUserEventOffset( User::newFromId( 1 ), 500 ) );
+ $notifMapper = new EchoNotificationMapper( $this->mockMWEchoDbFactory( $mockDb ) );
+ $this->assertTrue( $notifMapper->deleteByUserEventOffset( User::newFromId( 1 ), 500 ) );
}
/**
@@ -203,20 +229,23 @@ class EchoNotificationMapperTest extends MediaWikiTestCase {
/**
* Mock object of MWEchoDbFactory
+ * @param array|\Wikimedia\Rdbms\IDatabase $dbResultOrMockDb
*/
- protected function mockMWEchoDbFactory( $dbResult ) {
+ protected function mockMWEchoDbFactory( $dbResultOrMockDb ) {
+ $mockDb = is_array( $dbResultOrMockDb ) ? $this->mockDb( $dbResultOrMockDb ) : $dbResultOrMockDb;
$dbFactory = $this->getMockBuilder( 'MWEchoDbFactory' )
->disableOriginalConstructor()
->getMock();
$dbFactory->expects( $this->any() )
->method( 'getEchoDb' )
- ->will( $this->returnValue( $this->mockDb( $dbResult ) ) );
+ ->will( $this->returnValue( $mockDb ) );
return $dbFactory;
}
/**
- * Mock object of DatabaseMysql ( DatabaseBase )
+ * Returns a mock database object
+ * @return \Wikimedia\Rdbms\IDatabase
*/
protected function mockDb( array $dbResult ) {
$dbResult += [
@@ -226,7 +255,7 @@ class EchoNotificationMapperTest extends MediaWikiTestCase {
'delete' => ''
];
- $db = $this->getMockBuilder( 'DatabaseMysql' )
+ $db = $this->getMockBuilder( 'DatabaseMysqli' )
->disableOriginalConstructor()
->getMock();
$db->expects( $this->any() )
@@ -249,20 +278,3 @@ class EchoNotificationMapperTest extends MediaWikiTestCase {
}
}
-
-class EchoExecuteFirstArgumentStub implements PHPUnit_Framework_MockObject_Stub {
- public function invoke( PHPUnit_Framework_MockObject_Invocation $invocation ) {
- if ( !$invocation instanceof PHPUnit_Framework_MockObject_Invocation_Static ) {
- throw new PHPUnit_Framework_Exception( 'wrong invocation type' );
- }
- if ( !$invocation->arguments ) {
- throw new PHPUnit_Framework_Exception( 'Method call must have an argument' );
- }
-
- return call_user_func( reset( $invocation->arguments ) );
- }
-
- public function toString() {
- return 'return result of call_user_func on first invocation argument';
- }
-}
diff --git a/Echo/tests/phpunit/mapper/TargetPageMapperTest.php b/Echo/tests/phpunit/mapper/TargetPageMapperTest.php
index 522ee34d..aaba3e3c 100644
--- a/Echo/tests/phpunit/mapper/TargetPageMapperTest.php
+++ b/Echo/tests/phpunit/mapper/TargetPageMapperTest.php
@@ -1,5 +1,8 @@
<?php
+/**
+ * @covers EchoTargetPageMapper
+ */
class EchoTargetPageMapperTest extends MediaWikiTestCase {
public function provideDataTestInsert() {
@@ -35,16 +38,13 @@ class EchoTargetPageMapperTest extends MediaWikiTestCase {
* Mock object of EchoTargetPage
*/
protected function mockEchoTargetPage() {
- $target = $this->getMockBuilder( 'EchoTargetPage' )
+ $target = $this->getMockBuilder( EchoTargetPage::class )
->disableOriginalConstructor()
->getMock();
$target->expects( $this->any() )
->method( 'toDbArray' )
->will( $this->returnValue( [] ) );
$target->expects( $this->any() )
- ->method( 'getUser' )
- ->will( $this->returnValue( User::newFromId( 1 ) ) );
- $target->expects( $this->any() )
->method( 'getPageId' )
->will( $this->returnValue( 2 ) );
$target->expects( $this->any() )
@@ -69,7 +69,8 @@ class EchoTargetPageMapperTest extends MediaWikiTestCase {
}
/**
- * Mock object of DatabaseMysql ( DatabaseBase )
+ * Returns a mock database object
+ * @return \Wikimedia\Rdbms\IDatabase
*/
protected function mockDb( array $dbResult ) {
$dbResult += [
@@ -78,7 +79,7 @@ class EchoTargetPageMapperTest extends MediaWikiTestCase {
'select' => '',
'delete' => ''
];
- $db = $this->getMockBuilder( 'DatabaseMysql' )
+ $db = $this->getMockBuilder( 'DatabaseMysqli' )
->disableOriginalConstructor()
->getMock();
$db->expects( $this->any() )
diff --git a/Echo/tests/phpunit/model/NotificationTest.php b/Echo/tests/phpunit/model/NotificationTest.php
index d6d45c3e..92522303 100644
--- a/Echo/tests/phpunit/model/NotificationTest.php
+++ b/Echo/tests/phpunit/model/NotificationTest.php
@@ -1,5 +1,8 @@
<?php
+/**
+ * @covers EchoNotification
+ */
class EchoNotificationTest extends MediaWikiTestCase {
public function testNewFromRow() {
@@ -28,7 +31,7 @@ class EchoNotificationTest extends MediaWikiTestCase {
$notif = EchoNotification::newFromRow( (object)$row, [
EchoTargetPage::newFromRow( (object)$this->mockTargetPageRow() )
] );
- $this->assertGreaterThan( 0, count( $notif->getTargetPages() ) );
+ $this->assertNotEmpty( $notif->getTargetPages() );
foreach ( $notif->getTargetPages() as $targetPage ) {
$this->assertInstanceOf( 'EchoTargetPage', $targetPage );
}
diff --git a/Echo/tests/phpunit/model/TargetPageTest.php b/Echo/tests/phpunit/model/TargetPageTest.php
index a7f7c035..f925cfeb 100644
--- a/Echo/tests/phpunit/model/TargetPageTest.php
+++ b/Echo/tests/phpunit/model/TargetPageTest.php
@@ -1,5 +1,8 @@
<?php
+/**
+ * @covers EchoTargetPage
+ */
class EchoTargetPageTest extends MediaWikiTestCase {
public function testCreate() {
diff --git a/Echo/tests/phpunit/revision_txt/123.txt b/Echo/tests/phpunit/revision_txt/123.txt
new file mode 100644
index 00000000..257cc564
--- /dev/null
+++ b/Echo/tests/phpunit/revision_txt/123.txt
@@ -0,0 +1 @@
+foo
diff --git a/Echo/tests/phpunit/revision_txt/1234.txt b/Echo/tests/phpunit/revision_txt/1234.txt
new file mode 100644
index 00000000..d675fa44
--- /dev/null
+++ b/Echo/tests/phpunit/revision_txt/1234.txt
@@ -0,0 +1 @@
+foo bar
diff --git a/Echo/tests/qunit/.eslintrc.json b/Echo/tests/qunit/.eslintrc.json
new file mode 100644
index 00000000..348a1b7f
--- /dev/null
+++ b/Echo/tests/qunit/.eslintrc.json
@@ -0,0 +1,6 @@
+{
+ "extends": [
+ "wikimedia/qunit",
+ "../../.eslintrc.json"
+ ]
+}
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 66e259c6..22a4d59b 100644
--- a/Echo/tests/qunit/model/test_mw.echo.dm.BundleNotificationItem.js
+++ b/Echo/tests/qunit/model/test_mw.echo.dm.BundleNotificationItem.js
@@ -15,13 +15,13 @@
{ modelName: 'foo' }
);
- assert.equal(
+ assert.strictEqual(
bundle.getCount(),
5,
'Bundled items added to internal list'
);
- assert.equal(
+ assert.strictEqual(
bundle.getName(),
'foo',
'Bundle name stored'
@@ -33,13 +33,13 @@
'All ids present'
);
- assert.equal(
+ assert.strictEqual(
bundle.isRead(),
false,
'Bundle with all unread items is unread'
);
- assert.equal(
+ assert.strictEqual(
bundle.hasUnseen(),
true,
'Bundle has unseen items'
@@ -74,7 +74,7 @@
}
);
- assert.equal(
+ assert.strictEqual(
bundle.hasUnseen(),
true,
'Bundle has unseen'
@@ -85,20 +85,20 @@
bundledItems[ i ].toggleSeen( true );
}
- assert.equal(
+ assert.strictEqual(
bundle.hasUnseen(),
false,
'Bundle does not have unseen after all items marked as seen'
);
- assert.equal(
+ assert.strictEqual(
bundle.isRead(),
false,
'Bundle is unread'
);
// Mark one item as read
bundledItems[ 0 ].toggleRead( true );
- assert.equal(
+ assert.strictEqual(
bundle.isRead(),
false,
'Bundle is still unread if it has some unread items'
@@ -108,7 +108,7 @@
for ( i = 0; i < bundledItems.length; i++ ) {
bundledItems[ i ].toggleRead( true );
}
- assert.equal(
+ assert.strictEqual(
bundle.isRead(),
true,
'Bundle is marked as read if all items are read'
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 6073a1a5..add303e2 100644
--- a/Echo/tests/qunit/model/test_mw.echo.dm.CrossWikiNotificationItem.js
+++ b/Echo/tests/qunit/model/test_mw.echo.dm.CrossWikiNotificationItem.js
@@ -116,7 +116,7 @@
[ 'baz', 'bar', 'foo' ],
'Model source names exist in order'
);
- assert.equal(
+ assert.strictEqual(
model.hasUnseen(),
true,
'hasUnseen is true if there are unseen items in any group'
@@ -129,14 +129,14 @@
}
}
groupDefinitions[ 0 ].items[ 0 ].toggleSeen( false );
- assert.equal(
+ assert.strictEqual(
model.hasUnseen(),
true,
'hasUnseen is true even if only one item in one group is unseen'
);
groupDefinitions[ 0 ].items[ 0 ].toggleSeen( true );
- assert.equal(
+ assert.strictEqual(
model.hasUnseen(),
false,
'hasUnseen is false if there are no unseen items in any of the groups'
@@ -209,7 +209,7 @@
numUnseenItems = model.getItems().filter( function ( item ) {
return !item.isSeen();
} ).length;
- assert.equal(
+ assert.strictEqual(
numUnseenItems,
numAllItems,
'Starting state: all items are unseen'
@@ -221,7 +221,7 @@
numUnseenItems = model.getItems().filter( function ( item ) {
return !item.isSeen();
} ).length;
- assert.equal(
+ assert.strictEqual(
numUnseenItems,
numAllItems - groupDefinitions[ 0 ].items.length,
'Only some items are seen'
@@ -233,7 +233,7 @@
numUnseenItems = model.getItems().filter( function ( item ) {
return !item.isSeen();
} ).length;
- assert.equal(
+ assert.strictEqual(
numUnseenItems,
0,
'All items are seen'
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 c080e242..2bc8146c 100644
--- a/Echo/tests/qunit/model/test_mw.echo.dm.FiltersModel.js
+++ b/Echo/tests/qunit/model/test_mw.echo.dm.FiltersModel.js
@@ -52,28 +52,28 @@
QUnit.test( 'Changing filters', function ( assert ) {
var model = new mw.echo.dm.FiltersModel();
- assert.equal(
+ assert.strictEqual(
model.getReadState(),
'all',
'Initial value: all'
);
model.setReadState( 'unread' );
- assert.equal(
+ assert.strictEqual(
model.getReadState(),
'unread',
'Changing state (unread)'
);
model.setReadState( 'read' );
- assert.equal(
+ assert.strictEqual(
model.getReadState(),
'read',
'Changing state (read)'
);
model.setReadState( 'foo' );
- assert.equal(
+ assert.strictEqual(
model.getReadState(),
'read',
'Ignoring invalid state (foo)'
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 63c381e8..c30a8adc 100644
--- a/Echo/tests/qunit/model/test_mw.echo.dm.NotificationGroupsList.js
+++ b/Echo/tests/qunit/model/test_mw.echo.dm.NotificationGroupsList.js
@@ -4,7 +4,7 @@
QUnit.test( 'Constructing the model', function ( assert ) {
var model = new mw.echo.dm.NotificationGroupsList();
- assert.equal(
+ assert.strictEqual(
model.getTimestamp(),
0,
'Empty group has timestamp 0'
@@ -59,14 +59,14 @@
groupDefinitions[ i ].items
);
- assert.equal(
+ assert.strictEqual(
model.getItemCount(),
i + 1,
'Group number increases after addGroup ("' + groupDefinitions[ i ].name + '")'
);
group = model.getGroupByName( groupDefinitions[ i ].name );
- assert.equal(
+ assert.strictEqual(
group.getName(),
groupDefinitions[ i ].name,
'Group exists after addGroup ("' + groupDefinitions[ i ].name + '")'
@@ -76,12 +76,12 @@
// Remove group
model.removeGroup( groupDefinitions[ 0 ].name );
- assert.equal(
+ assert.strictEqual(
model.getItemCount(),
groupDefinitions.length - 1,
'Group number decreased after removeGroup'
);
- assert.equal(
+ assert.strictEqual(
model.getGroupByName( groupDefinitions[ 0 ] ),
null,
'Removed group is no longer in the list'
@@ -90,7 +90,7 @@
// Removing the last item from a group should remove the group
group = model.getGroupByName( 'baz' );
group.discardItems( groupDefinitions[ 2 ].items );
- assert.equal(
+ assert.strictEqual(
model.getGroupByName( 'baz' ),
null,
'Empty group is no longer in the list'
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 107d4fc0..02de8bc4 100644
--- a/Echo/tests/qunit/model/test_mw.echo.dm.NotificationsList.js
+++ b/Echo/tests/qunit/model/test_mw.echo.dm.NotificationsList.js
@@ -69,24 +69,24 @@
new mw.echo.dm.NotificationItem( 5, { type: 'message', timestamp: '201609190500', read: true, seen: false } )
];
- assert.equal(
+ assert.strictEqual(
model.getCount(),
0,
'Model list starts empty'
);
- assert.equal(
+ assert.strictEqual(
model.getTimestamp(),
'200101010000',
'Model timestamp is its default'
);
model.setItems( items );
- assert.equal(
+ assert.strictEqual(
model.getCount(),
6,
'Item list setup'
);
- assert.equal(
+ assert.strictEqual(
model.getTimestamp(),
'201609190100',
'Model timestamp is the latest unread item\'s timestamp'
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 53f9b9de..7c98fc6a 100644
--- a/Echo/tests/qunit/model/test_mw.echo.dm.SourcePagesModel.js
+++ b/Echo/tests/qunit/model/test_mw.echo.dm.SourcePagesModel.js
@@ -82,12 +82,12 @@
model.setAllSources( sources );
- assert.equal(
+ assert.strictEqual(
model.getCurrentSource(),
'local',
'Default source is local'
);
- assert.equal(
+ assert.strictEqual(
model.getCurrentPage(),
null,
'Default page is null'
@@ -97,12 +97,12 @@
[ 'local', 'hewiki' ],
'Source array includes all sources'
);
- assert.equal(
+ assert.strictEqual(
model.getSourceTitle( 'hewiki' ),
'Hebrew Wikipedia',
'Source title'
);
- assert.equal(
+ assert.strictEqual(
model.getSourceTotalCount( 'hewiki' ),
15,
'Source total count'
@@ -157,12 +157,12 @@
// Change source
model.setCurrentSourcePage( 'hewiki', 'User:Bar' );
- assert.equal(
+ assert.strictEqual(
model.getCurrentSource(),
'hewiki',
'Source changed successfully'
);
- assert.equal(
+ assert.strictEqual(
model.getCurrentPage(),
'User:Bar',
'Page changed successfully'
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 8b2662e1..42eb47aa 100644
--- a/Echo/tests/qunit/model/test_mw.echo.dm.UnreadNotificationCounter.js
+++ b/Echo/tests/qunit/model/test_mw.echo.dm.UnreadNotificationCounter.js
@@ -15,7 +15,7 @@
];
for ( i = 0; i < cases.length; i++ ) {
- assert.equal(
+ assert.strictEqual(
model.getCappedNotificationCount( cases[ i ].input ),
cases[ i ].output,
'Capped notifications count: ' +
@@ -27,29 +27,29 @@
QUnit.test( 'Estimate change', function ( assert ) {
var model = new mw.echo.dm.UnreadNotificationCounter(
- null,
- 'all', // type
- 99 // max
- );
+ null,
+ 'all', // type
+ 99 // max
+ );
// Set initial
model.setCount( 50 );
model.estimateChange( -10 );
- assert.equal(
+ assert.strictEqual(
model.getCount(),
40, // 50-10
'Estimation within range'
);
model.estimateChange( 70 );
- assert.equal(
+ assert.strictEqual(
model.getCount(),
100, // Estimation reached above cap - cap is set
'Estimation brings count to cap'
);
model.estimateChange( -10 );
- assert.equal(
+ assert.strictEqual(
model.getCount(),
100, // We are already above cap, count will not change
'Estimation while counter is outside of cap - no change'
diff --git a/Echo/tests/qunit/overlay/test_ext.echo.overlay.js b/Echo/tests/qunit/overlay/test_ext.echo.overlay.js
index 213ffddd..aa0518a1 100644
--- a/Echo/tests/qunit/overlay/test_ext.echo.overlay.js
+++ b/Echo/tests/qunit/overlay/test_ext.echo.overlay.js
@@ -1,6 +1,6 @@
( function ( $, mw ) {
QUnit.module( 'ext.echo.overlay', {
- setup: function () {
+ beforeEach: function () {
var ApiStub;
this.$badge = $( '<a class="mw-echo-notifications-badge mw-echo-unseen-notifications">1</a>' );
@@ -198,7 +198,7 @@
}
} );
- QUnit.test( 'mw.echo.overlay.buildOverlay', 7, function ( assert ) {
+ QUnit.test( 'mw.echo.overlay.buildOverlay', function ( assert ) {
var $overlay;
this.sandbox.stub( mw.echo.overlay, 'api', new this.ApiStub() );
mw.echo.overlay.buildOverlay( function ( $o ) {
@@ -216,7 +216,7 @@
false, 'The badge no longer indicates new messages.' );
} );
- QUnit.test( 'mw.echo.overlay.buildOverlay with messages', 5, function ( assert ) {
+ QUnit.test( 'mw.echo.overlay.buildOverlay with messages', function ( assert ) {
var $overlay;
this.sandbox.stub( mw.echo.overlay, 'api', new this.ApiStub( 'no-new-messages' ) );
mw.echo.overlay.buildOverlay( function ( $o ) {
@@ -232,7 +232,7 @@
false, 'The notification button class is updated with the default switch to alert tab.' );
} );
- QUnit.test( 'Switch tabs on overlay. 1 unread alert, no unread messages.', 7, function ( assert ) {
+ QUnit.test( 'Switch tabs on overlay. 1 unread alert, no unread messages.', function ( assert ) {
var $overlay, $tabs;
this.sandbox.stub( mw.echo.overlay, 'api', new this.ApiStub( 'no-new-messages' ) );
@@ -259,7 +259,7 @@
true, 'Second tab has active class .as it is the only clickable tab' );
} );
- QUnit.test( 'Unread message behaviour', 5, function ( assert ) {
+ QUnit.test( 'Unread message behaviour', function ( assert ) {
var $overlay;
this.sandbox.stub( mw.echo.overlay, 'api', new this.ApiStub( 'with-new-messages' ) );
@@ -282,7 +282,7 @@
'There are no notifications now so no need for button.' );
} );
- QUnit.test( 'Mark as read.', 8, function ( assert ) {
+ QUnit.test( 'Mark as read.', function ( assert ) {
var $overlay;
this.$badge.text( '8' );
this.sandbox.stub( mw.echo.overlay, 'api', new this.ApiStub( 'with-new-messages' ) );
@@ -311,7 +311,7 @@
assert.strictEqual( this.$badge.text(), '6', 'Now 6 unread notifications.' );
} );
- QUnit.test( 'Tabs when there is overflow.', 2, function ( assert ) {
+ QUnit.test( 'Tabs when there is overflow.', function ( assert ) {
var $overlay;
this.sandbox.stub( mw.echo.overlay, 'api', new this.ApiStub( 'with-new-messages', 50 ) );
mw.echo.overlay.buildOverlay( function ( $o ) {
@@ -324,7 +324,7 @@
assert.strictEqual( $overlay.find( '.mw-echo-unread' ).length, 8, 'There are 8 unread notifications.' );
} );
- QUnit.test( 'Switching tabs visibility', 4, function ( assert ) {
+ QUnit.test( 'Switching tabs visibility', function ( assert ) {
var $overlay;
this.sandbox.stub( mw.echo.overlay, 'api', new this.ApiStub( 'with-new-messages' ) );
diff --git a/Echo/tests/rspec/README.md b/Echo/tests/rspec/README.md
deleted file mode 100644
index 5cf77fbf..00000000
--- a/Echo/tests/rspec/README.md
+++ /dev/null
@@ -1,7 +0,0 @@
-# Usage
-
- vagrant up
- vagrant roles enable echo flow wikimediaflow
- vagrant provision
- bundle install
- bundle exec rake spec
diff --git a/Echo/tests/rspec/notification_spec.rb b/Echo/tests/rspec/notification_spec.rb
deleted file mode 100644
index ff4b9a63..00000000
--- a/Echo/tests/rspec/notification_spec.rb
+++ /dev/null
@@ -1,55 +0,0 @@
-require 'mediawiki_api'
-
-describe 'Echo' do
- before(:all) do
- if ENV['JENKINS_HOME']
- # jenkins
- @mediawiki_api = "#{ENV['MW_SERVER']}#{ENV['MW_SCRIPT_PATH']}/api.php"
- @admin_username = 'WikiAdmin'
- @admin_password = 'testpass'
- else
- # mediawiki-vagrant
- @mediawiki_api = 'http://127.0.0.1:8080/w/api.php'
- @admin_username = 'Admin'
- @admin_password = 'vagrant'
- end
-
- @client = MediawikiApi::Client.new @mediawiki_api
- end
-
- before(:each) do
- @client.log_in @admin_username, @admin_password
-
- require 'securerandom'
- @random_username = "U#{SecureRandom.hex(5)}"
- @random_password = SecureRandom.hex(5)
- end
-
- it 'should notify a new user with welcome message' do
- @client.create_account(@random_username, @random_password)
-
- @client.log_in @random_username, @random_password
- notifications = @client.query(meta: 'notifications').data['notifications']['list']
-
- welcome_notification = notifications.first
- expect(welcome_notification['type']).to eq 'welcome'
- expect(welcome_notification['agent']['name']).to eq @random_username
- expect(welcome_notification['timestamp']['date']).to eq 'Today'
- end
-
- it 'should notify user about mention on wikitext page' do
- @client.create_account(@random_username, @random_password)
-
- page = SecureRandom.hex(5).capitalize
- @client.edit(title: page, text: "[[User:#{@random_username}]] ~~~~")
-
- @client.log_in @random_username, @random_password
- notifications = @client.query(meta: 'notifications').data['notifications']['list']
-
- mention_notification = notifications.last
- expect(mention_notification['type']).to eq 'mention'
- expect(mention_notification['agent']['name']).to eq @admin_username
- expect(mention_notification['title']['full']).to eq page
- end
-
-end
diff --git a/Echo/tests/selenium/.eslintrc.json b/Echo/tests/selenium/.eslintrc.json
new file mode 100644
index 00000000..5efe15d0
--- /dev/null
+++ b/Echo/tests/selenium/.eslintrc.json
@@ -0,0 +1,14 @@
+{
+ "extends": "wikimedia",
+ "env": {
+ "es6": true,
+ "mocha": true,
+ "node": true
+ },
+ "globals": {
+ "browser": false
+ },
+ "rules": {
+ "no-console": 0
+ }
+}
diff --git a/Echo/tests/selenium/README.md b/Echo/tests/selenium/README.md
new file mode 100644
index 00000000..59fa8eb4
--- /dev/null
+++ b/Echo/tests/selenium/README.md
@@ -0,0 +1,42 @@
+# Selenium tests
+
+Please see tests/selenium/README.md file in mediawiki/core repository, usually at mediawiki/vagrant/mediawiki folder.
+
+## Setup
+
+Set up MediaWiki-Vagrant:
+
+ cd mediawiki/vagrant
+ vagrant up
+ vagrant roles enable echo
+ vagrant provision
+ cd mediawiki
+ npm install
+
+## Start Chromedriver and run all tests
+
+Run both mediawiki/core and extension tests from mediawiki/core repository (usually at mediawiki/vagrant/mediawiki folder):
+
+ npm run selenium
+
+## Start Chromedriver
+
+To run only some tests, you first have to start Chromedriver in one terminal tab (or window):
+
+ chromedriver --url-base=wd/hub --port=4444
+
+## Run test(s) from one file
+
+Then, in another terminal tab (or window) run this from mediawiki/core repository (usually at mediawiki/vagrant/mediawiki folder):
+
+ ./node_modules/.bin/wdio tests/selenium/wdio.conf.js --spec extensions/EXTENSION-NAME/tests/selenium/specs/FILE-NAME.js
+
+`wdio` is a dependency of mediawiki/core that you have installed with `npm install`.
+
+## Run specific test(s)
+
+To run only test(s) which name contains string TEST-NAME, run this from mediawiki/core repository (usually at mediawiki/vagrant/mediawiki folder):
+
+ ./node_modules/.bin/wdio tests/selenium/wdio.conf.js --spec extensions/EXTENSION-NAME/tests/selenium/specs/FILE-NAME.js --mochaOpts.grep TEST-NAME
+
+Make sure Chromedriver is running when executing the above command.
diff --git a/Echo/tests/selenium/pageobjects/echo.page.js b/Echo/tests/selenium/pageobjects/echo.page.js
new file mode 100644
index 00000000..13a68e97
--- /dev/null
+++ b/Echo/tests/selenium/pageobjects/echo.page.js
@@ -0,0 +1,10 @@
+'use strict';
+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' ); }
+
+}
+module.exports = new EchoPage();
diff --git a/Echo/tests/selenium/specs/echo.js b/Echo/tests/selenium/specs/echo.js
new file mode 100644
index 00000000..790109d0
--- /dev/null
+++ b/Echo/tests/selenium/specs/echo.js
@@ -0,0 +1,18 @@
+'use strict';
+
+var assert = require( 'assert' ),
+ EchoPage = require( '../pageobjects/echo.page' ),
+ UserLoginPage = require( 'wdio-mediawiki/LoginPage' );
+
+describe( 'Echo', function () {
+
+ it( 'alerts and notices are visible after logging in', function () {
+
+ UserLoginPage.login( browser.options.username, browser.options.password );
+
+ assert( EchoPage.alerts.isExisting() );
+ assert( EchoPage.notices.isExisting() );
+
+ } );
+
+} );
diff --git a/Echo/tests/selenium/wdio.conf.js b/Echo/tests/selenium/wdio.conf.js
new file mode 100644
index 00000000..3b58beb6
--- /dev/null
+++ b/Echo/tests/selenium/wdio.conf.js
@@ -0,0 +1,88 @@
+/**
+ * See also: http://webdriver.io/guide/testrunner/configurationfile.html
+ */
+const fs = require( 'fs' ),
+ saveScreenshot = require( 'wdio-mediawiki' ).saveScreenshot;
+
+exports.config = {
+ // ======
+ // Custom WDIO config specific to MediaWiki
+ // ======
+ // Use in a test as `browser.options.<key>`.
+ // Defaults are for convenience with MediaWiki-Vagrant
+
+ // Wiki admin
+ username: process.env.MEDIAWIKI_USER || 'Admin',
+ password: process.env.MEDIAWIKI_PASSWORD || 'vagrant',
+
+ // Base for browser.url() and Page#openTitle()
+ baseUrl: ( process.env.MW_SERVER || 'http://127.0.0.1:8080' ) + (
+ process.env.MW_SCRIPT_PATH || '/w'
+ ),
+
+ // ==================
+ // Test Files
+ // ==================
+ specs: [
+ __dirname + '/specs/*.js'
+ ],
+
+ // ============
+ // Capabilities
+ // ============
+ capabilities: [ {
+ // https://sites.google.com/a/chromium.org/chromedriver/capabilities
+ browserName: 'chrome',
+ maxInstances: 1,
+ 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
+ args: [
+ ...( process.env.DISPLAY ? [] : [ '--headless' ] ),
+ // Chrome sandbox does not work in Docker
+ ...( fs.existsSync( '/.dockerenv' ) ? [ '--no-sandbox' ] : [] )
+ ]
+ }
+ } ],
+
+ // ===================
+ // Test Configurations
+ // ===================
+
+ // Level of verbosity: silent | verbose | command | data | result | error
+ logLevel: 'error',
+
+ // Setting this enables automatic screenshots for when a browser command fails
+ // It is also used by afterTest for capturig failed assertions.
+ screenshotPath: process.env.LOG_DIR || __dirname + '/log',
+
+ // Default timeout for each waitFor* command.
+ waitforTimeout: 10 * 1000,
+
+ // See also: http://webdriver.io/guide/testrunner/reporters.html
+ reporters: [ 'spec' ],
+
+ // See also: http://mochajs.org
+ mochaOpts: {
+ ui: 'bdd',
+ timeout: 60 * 1000
+ },
+
+ // =====
+ // Hooks
+ // =====
+
+ /**
+ * Save a screenshot when test fails.
+ *
+ * @param {Object} test Mocha Test object
+ */
+ afterTest: function ( test ) {
+ var filePath;
+ if ( !test.passed ) {
+ filePath = saveScreenshot( test.title );
+ console.log( '\n\tScreenshot: ' + filePath + '\n' );
+ }
+ }
+};