summaryrefslogtreecommitdiff
path: root/tests/phpunit/includes/changes
diff options
context:
space:
mode:
Diffstat (limited to 'tests/phpunit/includes/changes')
-rw-r--r--tests/phpunit/includes/changes/EnhancedChangesListTest.php132
-rw-r--r--tests/phpunit/includes/changes/OldChangesListTest.php187
-rw-r--r--tests/phpunit/includes/changes/RCCacheEntryFactoryTest.php331
-rw-r--r--tests/phpunit/includes/changes/RecentChangeTest.php286
-rw-r--r--tests/phpunit/includes/changes/TestRecentChangesHelper.php137
5 files changed, 1073 insertions, 0 deletions
diff --git a/tests/phpunit/includes/changes/EnhancedChangesListTest.php b/tests/phpunit/includes/changes/EnhancedChangesListTest.php
new file mode 100644
index 00000000..40a11d2d
--- /dev/null
+++ b/tests/phpunit/includes/changes/EnhancedChangesListTest.php
@@ -0,0 +1,132 @@
+<?php
+
+/**
+ * @covers EnhancedChangesList
+ *
+ * @group Database
+ *
+ * @licence GNU GPL v2+
+ * @author Katie Filbert < aude.wiki@gmail.com >
+ */
+class EnhancedChangesListTest extends MediaWikiLangTestCase {
+
+ /**
+ * @var TestRecentChangesHelper
+ */
+ private $testRecentChangesHelper;
+
+ public function __construct( $name = null, array $data = array(), $dataName = '' ) {
+ parent::__construct( $name, $data, $dataName );
+
+ $this->testRecentChangesHelper = new TestRecentChangesHelper();
+ }
+
+ public function testBeginRecentChangesList_styleModules() {
+ $enhancedChangesList = $this->newEnhancedChangesList();
+ $enhancedChangesList->beginRecentChangesList();
+
+ $styleModules = $enhancedChangesList->getOutput()->getModuleStyles();
+
+ $this->assertContains(
+ 'mediawiki.special.changeslist',
+ $styleModules,
+ 'has mediawiki.special.changeslist'
+ );
+
+ $this->assertContains(
+ 'mediawiki.special.changeslist.enhanced',
+ $styleModules,
+ 'has mediawiki.special.changeslist.enhanced'
+ );
+ }
+
+ public function testBeginRecentChangesList_jsModules() {
+ $enhancedChangesList = $this->newEnhancedChangesList();
+ $enhancedChangesList->beginRecentChangesList();
+
+ $modules = $enhancedChangesList->getOutput()->getModules();
+
+ $this->assertContains( 'jquery.makeCollapsible', $modules, 'has jquery.makeCollapsible' );
+ $this->assertContains( 'mediawiki.icon', $modules, 'has mediawiki.icon' );
+ }
+
+ public function testBeginRecentChangesList_html() {
+ $enhancedChangesList = $this->newEnhancedChangesList();
+ $html = $enhancedChangesList->beginRecentChangesList();
+
+ $this->assertEquals( '<div class="mw-changeslist">', $html );
+ }
+
+ /**
+ * @todo more tests
+ */
+ public function testRecentChangesLine() {
+ $enhancedChangesList = $this->newEnhancedChangesList();
+ $enhancedChangesList->beginRecentChangesList();
+
+ $recentChange = $this->getEditChange( '20131103092153' );
+ $html = $enhancedChangesList->recentChangesLine( $recentChange, false );
+
+ $this->assertInternalType( 'string', $html );
+
+ $recentChange2 = $this->getEditChange( '20131103092253' );
+ $html = $enhancedChangesList->recentChangesLine( $recentChange2, false );
+
+ $this->assertEquals( '', $html );
+ }
+
+ /**
+ * @todo more tests for actual formatting, this is more of a smoke test
+ */
+ public function testEndRecentChangesList() {
+ $enhancedChangesList = $this->newEnhancedChangesList();
+ $enhancedChangesList->beginRecentChangesList();
+
+ $recentChange = $this->getEditChange( '20131103092153' );
+ $enhancedChangesList->recentChangesLine( $recentChange, false );
+
+ $recentChange2 = $this->getEditChange( '20131103092253' );
+ $enhancedChangesList->recentChangesLine( $recentChange2, false );
+
+ $html = $enhancedChangesList->endRecentChangesList();
+
+ preg_match_all( '/td class="mw-enhanced-rc-nested"/', $html, $matches );
+ $this->assertCount( 2, $matches[0] );
+ }
+
+ /**
+ * @return EnhancedChangesList
+ */
+ private function newEnhancedChangesList() {
+ $user = User::newFromId( 0 );
+ $context = $this->testRecentChangesHelper->getTestContext( $user );
+
+ return new EnhancedChangesList( $context );
+ }
+
+ /**
+ * @return RecentChange
+ */
+ private function getEditChange( $timestamp ) {
+ $user = $this->getTestUser();
+ $recentChange = $this->testRecentChangesHelper->makeEditRecentChange(
+ $user, 'Cat', $timestamp, 5, 191, 190, 0, 0
+ );
+
+ return $recentChange;
+ }
+
+ /**
+ * @return User
+ */
+ private function getTestUser() {
+ $user = User::newFromName( 'TestRecentChangesUser' );
+
+ if ( !$user->getId() ) {
+ $user->addToDatabase();
+ }
+
+ return $user;
+ }
+
+}
diff --git a/tests/phpunit/includes/changes/OldChangesListTest.php b/tests/phpunit/includes/changes/OldChangesListTest.php
new file mode 100644
index 00000000..2ea9f33e
--- /dev/null
+++ b/tests/phpunit/includes/changes/OldChangesListTest.php
@@ -0,0 +1,187 @@
+<?php
+
+/**
+ * @covers OldChangesList
+ *
+ * @todo add tests to cover article link, timestamp, character difference,
+ * log entry, user tool links, direction marks, tags, rollback,
+ * watching users, and date header.
+ *
+ * @group Database
+ *
+ * @licence GNU GPL v2+
+ * @author Katie Filbert < aude.wiki@gmail.com >
+ */
+class OldChangesListTest extends MediaWikiLangTestCase {
+
+ /**
+ * @var TestRecentChangesHelper
+ */
+ private $testRecentChangesHelper;
+
+ public function __construct( $name = null, array $data = array(), $dataName = '' ) {
+ parent::__construct( $name, $data, $dataName );
+
+ $this->testRecentChangesHelper = new TestRecentChangesHelper();
+ }
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->setMwGlobals( array(
+ 'wgArticlePath' => '/wiki/$1',
+ 'wgLang' => Language::factory( 'qqx' )
+ ) );
+ }
+
+ /**
+ * @dataProvider recentChangesLine_CssForLineNumberProvider
+ */
+ public function testRecentChangesLine_CssForLineNumber( $expected, $linenumber, $message ) {
+ $oldChangesList = $this->getOldChangesList();
+ $recentChange = $this->getEditChange();
+
+ $line = $oldChangesList->recentChangesLine( $recentChange, false, $linenumber );
+
+ $this->assertRegExp( $expected, $line, $message );
+ }
+
+ public function recentChangesLine_CssForLineNumberProvider() {
+ return array(
+ array( '/mw-line-odd/', 1, 'odd line number' ),
+ array( '/mw-line-even/', 2, 'even line number' )
+ );
+ }
+
+ public function testRecentChangesLine_NotWatchedCssClass() {
+ $oldChangesList = $this->getOldChangesList();
+ $recentChange = $this->getEditChange();
+
+ $line = $oldChangesList->recentChangesLine( $recentChange, false, 1 );
+
+ $this->assertRegExp( '/mw-changeslist-line-not-watched/', $line );
+ }
+
+ public function testRecentChangesLine_WatchedCssClass() {
+ $oldChangesList = $this->getOldChangesList();
+ $recentChange = $this->getEditChange();
+
+ $line = $oldChangesList->recentChangesLine( $recentChange, true, 1 );
+
+ $this->assertRegExp( '/mw-changeslist-line-watched/', $line );
+ }
+
+ public function testRecentChangesLine_LogTitle() {
+ $oldChangesList = $this->getOldChangesList();
+ $recentChange = $this->getLogChange( 'delete', 'delete' );
+
+ $line = $oldChangesList->recentChangesLine( $recentChange, false, 1 );
+
+ $this->assertRegExp( '/href="\/wiki\/Special:Log\/delete/', $line, 'link has href attribute' );
+ $this->assertRegExp( '/title="Special:Log\/delete/', $line, 'link has title attribute' );
+ $this->assertRegExp( "/dellogpage/", $line, 'link text' );
+ }
+
+ public function testRecentChangesLine_DiffHistLinks() {
+ $oldChangesList = $this->getOldChangesList();
+ $recentChange = $this->getEditChange();
+
+ $line = $oldChangesList->recentChangesLine( $recentChange, false, 1 );
+
+ $this->assertRegExp(
+ '/title=Cat&amp;curid=20131103212153&amp;diff=5&amp;oldid=191/',
+ $line,
+ 'assert diff link'
+ );
+
+ $this->assertRegExp( '/tabindex="0"/', $line, 'assert tab index' );
+ $this->assertRegExp(
+ '/title=Cat&amp;curid=20131103212153&amp;action=history"/',
+ $line,
+ 'assert history link'
+ );
+ }
+
+ public function testRecentChangesLine_Flags() {
+ $oldChangesList = $this->getOldChangesList();
+ $recentChange = $this->getNewBotEditChange();
+
+ $line = $oldChangesList->recentChangesLine( $recentChange, false, 1 );
+
+ $this->assertContains(
+ "<abbr class='newpage' title='(recentchanges-label-newpage)'>(newpageletter)</abbr>",
+ $line,
+ 'new page flag'
+ );
+
+ $this->assertContains(
+ "<abbr class='botedit' title='(recentchanges-label-bot)'>(boteditletter)</abbr>",
+ $line,
+ 'bot flag'
+ );
+ }
+
+ public function testRecentChangesLine_Tags() {
+ $recentChange = $this->getEditChange();
+ $recentChange->mAttribs['ts_tags'] = 'vandalism,newbie';
+
+ $oldChangesList = $this->getOldChangesList();
+ $line = $oldChangesList->recentChangesLine( $recentChange, false, 1 );
+
+ $this->assertRegExp( '/<li class="[\w\s-]*mw-tag-vandalism[\w\s-]*">/', $line );
+ $this->assertRegExp( '/<li class="[\w\s-]*mw-tag-newbie[\w\s-]*">/', $line );
+ }
+
+ private function getNewBotEditChange() {
+ $user = $this->getTestUser();
+
+ $recentChange = $this->testRecentChangesHelper->makeNewBotEditRecentChange(
+ $user, 'Abc', '20131103212153', 5, 191, 190, 0, 0
+ );
+
+ return $recentChange;
+ }
+
+ private function getLogChange( $logType, $logAction ) {
+ $user = $this->getTestUser();
+
+ $recentChange = $this->testRecentChangesHelper->makeLogRecentChange(
+ $logType, $logAction, $user, 'Abc', '20131103212153', 0, 0
+ );
+
+ return $recentChange;
+ }
+
+ private function getEditChange() {
+ $user = $this->getTestUser();
+ $recentChange = $this->testRecentChangesHelper->makeEditRecentChange(
+ $user, 'Cat', '20131103212153', 5, 191, 190, 0, 0
+ );
+
+ return $recentChange;
+ }
+
+ private function getOldChangesList() {
+ $context = $this->getContext();
+ return new OldChangesList( $context );
+ }
+
+ private function getTestUser() {
+ $user = User::newFromName( 'TestRecentChangesUser' );
+
+ if ( !$user->getId() ) {
+ $user->addToDatabase();
+ }
+
+ return $user;
+ }
+
+ private function getContext() {
+ $user = $this->getTestUser();
+ $context = $this->testRecentChangesHelper->getTestContext( $user );
+ $context->setLanguage( Language::factory( 'qqx' ) );
+
+ return $context;
+ }
+
+}
diff --git a/tests/phpunit/includes/changes/RCCacheEntryFactoryTest.php b/tests/phpunit/includes/changes/RCCacheEntryFactoryTest.php
new file mode 100644
index 00000000..ee1a4d0e
--- /dev/null
+++ b/tests/phpunit/includes/changes/RCCacheEntryFactoryTest.php
@@ -0,0 +1,331 @@
+<?php
+
+/**
+ * @covers RCCacheEntryFactory
+ *
+ * @group Database
+ *
+ * @licence GNU GPL v2+
+ * @author Katie Filbert < aude.wiki@gmail.com >
+ */
+class RCCacheEntryFactoryTest extends MediaWikiLangTestCase {
+
+ /**
+ * @var TestRecentChangesHelper
+ */
+ private $testRecentChangesHelper;
+
+ public function __construct( $name = null, array $data = array(), $dataName = '' ) {
+ parent::__construct( $name, $data, $dataName );
+
+ $this->testRecentChangesHelper = new TestRecentChangesHelper();
+ }
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->setMwGlobals( array(
+ 'wgArticlePath' => '/wiki/$1'
+ ) );
+ }
+
+ /**
+ * @dataProvider editChangeProvider
+ */
+ public function testNewFromRecentChange( $expected, $context, $messages,
+ $recentChange, $watched
+ ) {
+ $cacheEntryFactory = new RCCacheEntryFactory( $context, $messages );
+ $cacheEntry = $cacheEntryFactory->newFromRecentChange( $recentChange, $watched );
+
+ $this->assertInstanceOf( 'RCCacheEntry', $cacheEntry );
+
+ $this->assertEquals( $watched, $cacheEntry->watched, 'watched' );
+ $this->assertEquals( $expected['timestamp'], $cacheEntry->timestamp, 'timestamp' );
+ $this->assertEquals(
+ $expected['numberofWatchingusers'], $cacheEntry->numberofWatchingusers,
+ 'watching users'
+ );
+ $this->assertEquals( $expected['unpatrolled'], $cacheEntry->unpatrolled, 'unpatrolled' );
+
+ $this->assertUserLinks( 'TestRecentChangesUser', $cacheEntry );
+ $this->assertTitleLink( 'Xyz', $cacheEntry );
+
+ $this->assertQueryLink( 'cur', $expected['cur'], $cacheEntry->curlink, 'cur link' );
+ $this->assertQueryLink( 'prev', $expected['diff'], $cacheEntry->lastlink, 'prev link' );
+ $this->assertQueryLink( 'diff', $expected['diff'], $cacheEntry->difflink, 'diff link' );
+ }
+
+ public function editChangeProvider() {
+ return array(
+ array(
+ array(
+ 'title' => 'Xyz',
+ 'user' => 'TestRecentChangesUser',
+ 'diff' => array( 'curid' => 5, 'diff' => 191, 'oldid' => 190 ),
+ 'cur' => array( 'curid' => 5, 'diff' => 0, 'oldid' => 191 ),
+ 'timestamp' => '21:21',
+ 'numberofWatchingusers' => 0,
+ 'unpatrolled' => false
+ ),
+ $this->getContext(),
+ $this->getMessages(),
+ $this->testRecentChangesHelper->makeEditRecentChange(
+ $this->getTestUser(),
+ 'Xyz',
+ 5, // curid
+ 191, // thisid
+ 190, // lastid
+ '20131103212153',
+ 0, // counter
+ 0 // number of watching users
+ ),
+ false
+ )
+ );
+ }
+
+ /**
+ * @dataProvider deleteChangeProvider
+ */
+ public function testNewForDeleteChange( $expected, $context, $messages, $recentChange, $watched ) {
+ $cacheEntryFactory = new RCCacheEntryFactory( $context, $messages );
+ $cacheEntry = $cacheEntryFactory->newFromRecentChange( $recentChange, $watched );
+
+ $this->assertInstanceOf( 'RCCacheEntry', $cacheEntry );
+
+ $this->assertEquals( $watched, $cacheEntry->watched, 'watched' );
+ $this->assertEquals( $expected['timestamp'], $cacheEntry->timestamp, 'timestamp' );
+ $this->assertEquals(
+ $expected['numberofWatchingusers'],
+ $cacheEntry->numberofWatchingusers, 'watching users'
+ );
+ $this->assertEquals( $expected['unpatrolled'], $cacheEntry->unpatrolled, 'unpatrolled' );
+
+ $this->assertDeleteLogLink( $cacheEntry );
+ $this->assertUserLinks( 'TestRecentChangesUser', $cacheEntry );
+
+ $this->assertEquals( 'cur', $cacheEntry->curlink, 'cur link for delete log or rev' );
+ $this->assertEquals( 'diff', $cacheEntry->difflink, 'diff link for delete log or rev' );
+ $this->assertEquals( 'prev', $cacheEntry->lastlink, 'pref link for delete log or rev' );
+ }
+
+ public function deleteChangeProvider() {
+ return array(
+ array(
+ array(
+ 'title' => 'Abc',
+ 'user' => 'TestRecentChangesUser',
+ 'timestamp' => '21:21',
+ 'numberofWatchingusers' => 0,
+ 'unpatrolled' => false
+ ),
+ $this->getContext(),
+ $this->getMessages(),
+ $this->testRecentChangesHelper->makeLogRecentChange(
+ 'delete',
+ 'delete',
+ $this->getTestUser(),
+ 'Abc',
+ '20131103212153',
+ 0, // counter
+ 0 // number of watching users
+ ),
+ false
+ )
+ );
+ }
+
+ /**
+ * @dataProvider revUserDeleteProvider
+ */
+ public function testNewForRevUserDeleteChange( $expected, $context, $messages,
+ $recentChange, $watched
+ ) {
+ $cacheEntryFactory = new RCCacheEntryFactory( $context, $messages );
+ $cacheEntry = $cacheEntryFactory->newFromRecentChange( $recentChange, $watched );
+
+ $this->assertInstanceOf( 'RCCacheEntry', $cacheEntry );
+
+ $this->assertEquals( $watched, $cacheEntry->watched, 'watched' );
+ $this->assertEquals( $expected['timestamp'], $cacheEntry->timestamp, 'timestamp' );
+ $this->assertEquals(
+ $expected['numberofWatchingusers'],
+ $cacheEntry->numberofWatchingusers, 'watching users'
+ );
+ $this->assertEquals( $expected['unpatrolled'], $cacheEntry->unpatrolled, 'unpatrolled' );
+
+ $this->assertRevDel( $cacheEntry );
+ $this->assertTitleLink( 'Zzz', $cacheEntry );
+
+ $this->assertEquals( 'cur', $cacheEntry->curlink, 'cur link for delete log or rev' );
+ $this->assertEquals( 'diff', $cacheEntry->difflink, 'diff link for delete log or rev' );
+ $this->assertEquals( 'prev', $cacheEntry->lastlink, 'pref link for delete log or rev' );
+ }
+
+ public function revUserDeleteProvider() {
+ return array(
+ array(
+ array(
+ 'title' => 'Zzz',
+ 'user' => 'TestRecentChangesUser',
+ 'diff' => '',
+ 'cur' => '',
+ 'timestamp' => '21:21',
+ 'numberofWatchingusers' => 0,
+ 'unpatrolled' => false
+ ),
+ $this->getContext(),
+ $this->getMessages(),
+ $this->testRecentChangesHelper->makeDeletedEditRecentChange(
+ $this->getTestUser(),
+ 'Zzz',
+ '20131103212153',
+ 191, // thisid
+ 190, // lastid
+ '20131103212153',
+ 0, // counter
+ 0 // number of watching users
+ ),
+ false
+ )
+ );
+ }
+
+ private function assertUserLinks( $user, $cacheEntry ) {
+ $this->assertTag(
+ array(
+ 'tag' => 'a',
+ 'attributes' => array(
+ 'class' => 'new mw-userlink'
+ ),
+ 'content' => $user
+ ),
+ $cacheEntry->userlink,
+ 'verify user link'
+ );
+
+ $this->assertTag(
+ array(
+ 'tag' => 'span',
+ 'attributes' => array(
+ 'class' => 'mw-usertoollinks'
+ ),
+ 'child' => array(
+ 'tag' => 'a',
+ 'content' => 'Talk',
+ )
+ ),
+ $cacheEntry->usertalklink,
+ 'verify user talk link'
+ );
+
+ $this->assertTag(
+ array(
+ 'tag' => 'span',
+ 'attributes' => array(
+ 'class' => 'mw-usertoollinks'
+ ),
+ 'child' => array(
+ 'tag' => 'a',
+ 'content' => 'contribs',
+ )
+ ),
+ $cacheEntry->usertalklink,
+ 'verify user tool links'
+ );
+ }
+
+ private function assertDeleteLogLink( $cacheEntry ) {
+ $this->assertTag(
+ array(
+ 'tag' => 'a',
+ 'attributes' => array(
+ 'href' => '/wiki/Special:Log/delete',
+ 'title' => 'Special:Log/delete'
+ ),
+ 'content' => 'Deletion log'
+ ),
+ $cacheEntry->link,
+ 'verify deletion log link'
+ );
+ }
+
+ private function assertRevDel( $cacheEntry ) {
+ $this->assertTag(
+ array(
+ 'tag' => 'span',
+ 'attributes' => array(
+ 'class' => 'history-deleted'
+ ),
+ 'content' => '(username removed)'
+ ),
+ $cacheEntry->userlink,
+ 'verify user link for change with deleted revision and user'
+ );
+ }
+
+ private function assertTitleLink( $title, $cacheEntry ) {
+ $this->assertTag(
+ array(
+ 'tag' => 'a',
+ 'attributes' => array(
+ 'href' => '/wiki/' . $title,
+ 'title' => $title
+ ),
+ 'content' => $title
+ ),
+ $cacheEntry->link,
+ 'verify title link'
+ );
+ }
+
+ private function assertQueryLink( $content, $params, $link ) {
+ $this->assertTag(
+ array(
+ 'tag' => 'a',
+ 'content' => $content
+ ),
+ $link,
+ 'assert query link element'
+ );
+
+ foreach ( $params as $key => $value ) {
+ $this->assertRegExp( '/' . $key . '=' . $value . '/', $link, "verify $key link params" );
+ }
+ }
+
+ private function getMessages() {
+ return array(
+ 'cur' => 'cur',
+ 'diff' => 'diff',
+ 'hist' => 'hist',
+ 'enhancedrc-history' => 'history',
+ 'last' => 'prev',
+ 'blocklink' => 'block',
+ 'history' => 'Page history',
+ 'semicolon-separator' => '; ',
+ 'pipe-separator' => ' | '
+ );
+ }
+
+ private function getTestUser() {
+ $user = User::newFromName( 'TestRecentChangesUser' );
+
+ if ( !$user->getId() ) {
+ $user->addToDatabase();
+ }
+
+ return $user;
+ }
+
+ private function getContext() {
+ $user = $this->getTestUser();
+ $context = $this->testRecentChangesHelper->getTestContext( $user );
+
+ $title = Title::newFromText( 'RecentChanges', NS_SPECIAL );
+ $context->setTitle( $title );
+
+ return $context;
+ }
+}
diff --git a/tests/phpunit/includes/changes/RecentChangeTest.php b/tests/phpunit/includes/changes/RecentChangeTest.php
new file mode 100644
index 00000000..98903f1e
--- /dev/null
+++ b/tests/phpunit/includes/changes/RecentChangeTest.php
@@ -0,0 +1,286 @@
+<?php
+
+/**
+ * @group Database
+ */
+class RecentChangeTest extends MediaWikiTestCase {
+ protected $title;
+ protected $target;
+ protected $user;
+ protected $user_comment;
+ protected $context;
+
+ public function __construct() {
+ parent::__construct();
+
+ $this->title = Title::newFromText( 'SomeTitle' );
+ $this->target = Title::newFromText( 'TestTarget' );
+ $this->user = User::newFromName( 'UserName' );
+
+ $this->user_comment = '<User comment about action>';
+ $this->context = RequestContext::newExtraneousContext( $this->title );
+ }
+
+ /**
+ * The testIrcMsgForAction* tests are supposed to cover the hacky
+ * LogFormatter::getIRCActionText / bug 34508
+ *
+ * Third parties bots listen to those messages. They are clever enough
+ * to fetch the i18n messages from the wiki and then analyze the IRC feed
+ * to reverse engineer the $1, $2 messages.
+ * One thing bots can not detect is when MediaWiki change the meaning of
+ * a message like what happened when we deployed 1.19. $1 became the user
+ * performing the action which broke basically all bots around.
+ *
+ * Should cover the following log actions (which are most commonly used by bots):
+ * - block/block
+ * - block/unblock
+ * - delete/delete
+ * - delete/restore
+ * - newusers/create
+ * - newusers/create2
+ * - newusers/autocreate
+ * - move/move
+ * - move/move_redir
+ * - protect/protect
+ * - protect/modifyprotect
+ * - protect/unprotect
+ * - upload/upload
+ *
+ * As well as the following Auto Edit Summaries:
+ * - blank
+ * - replace
+ * - rollback
+ * - undo
+ */
+
+ /**
+ * @covers LogFormatter::getIRCActionText
+ */
+ public function testIrcMsgForLogTypeBlock() {
+ $sep = $this->context->msg( 'colon-separator' )->text();
+
+ # block/block
+ $this->assertIRCComment(
+ $this->context->msg( 'blocklogentry', 'SomeTitle' )->plain() . $sep . $this->user_comment,
+ 'block', 'block',
+ array(),
+ $this->user_comment
+ );
+ # block/unblock
+ $this->assertIRCComment(
+ $this->context->msg( 'unblocklogentry', 'SomeTitle' )->plain() . $sep . $this->user_comment,
+ 'block', 'unblock',
+ array(),
+ $this->user_comment
+ );
+ }
+
+ /**
+ * @covers LogFormatter::getIRCActionText
+ */
+ public function testIrcMsgForLogTypeDelete() {
+ $sep = $this->context->msg( 'colon-separator' )->text();
+
+ # delete/delete
+ $this->assertIRCComment(
+ $this->context->msg( 'deletedarticle', 'SomeTitle' )->plain() . $sep . $this->user_comment,
+ 'delete', 'delete',
+ array(),
+ $this->user_comment
+ );
+
+ # delete/restore
+ $this->assertIRCComment(
+ $this->context->msg( 'undeletedarticle', 'SomeTitle' )->plain() . $sep . $this->user_comment,
+ 'delete', 'restore',
+ array(),
+ $this->user_comment
+ );
+ }
+
+ /**
+ * @covers LogFormatter::getIRCActionText
+ */
+ public function testIrcMsgForLogTypeNewusers() {
+ $this->assertIRCComment(
+ 'New user account',
+ 'newusers', 'newusers',
+ array()
+ );
+ $this->assertIRCComment(
+ 'New user account',
+ 'newusers', 'create',
+ array()
+ );
+ $this->assertIRCComment(
+ 'created new account SomeTitle',
+ 'newusers', 'create2',
+ array()
+ );
+ $this->assertIRCComment(
+ 'Account created automatically',
+ 'newusers', 'autocreate',
+ array()
+ );
+ }
+
+ /**
+ * @covers LogFormatter::getIRCActionText
+ */
+ public function testIrcMsgForLogTypeMove() {
+ $move_params = array(
+ '4::target' => $this->target->getPrefixedText(),
+ '5::noredir' => 0,
+ );
+ $sep = $this->context->msg( 'colon-separator' )->text();
+
+ # move/move
+ $this->assertIRCComment(
+ $this->context->msg( '1movedto2', 'SomeTitle', 'TestTarget' )
+ ->plain() . $sep . $this->user_comment,
+ 'move', 'move',
+ $move_params,
+ $this->user_comment
+ );
+
+ # move/move_redir
+ $this->assertIRCComment(
+ $this->context->msg( '1movedto2_redir', 'SomeTitle', 'TestTarget' )
+ ->plain() . $sep . $this->user_comment,
+ 'move', 'move_redir',
+ $move_params,
+ $this->user_comment
+ );
+ }
+
+ /**
+ * @covers LogFormatter::getIRCActionText
+ */
+ public function testIrcMsgForLogTypePatrol() {
+ # patrol/patrol
+ $this->assertIRCComment(
+ $this->context->msg( 'patrol-log-line', 'revision 777', '[[SomeTitle]]', '' )->plain(),
+ 'patrol', 'patrol',
+ array(
+ '4::curid' => '777',
+ '5::previd' => '666',
+ '6::auto' => 0,
+ )
+ );
+ }
+
+ /**
+ * @covers LogFormatter::getIRCActionText
+ */
+ public function testIrcMsgForLogTypeProtect() {
+ $protectParams = array(
+ '[edit=sysop] (indefinite) ‎[move=sysop] (indefinite)'
+ );
+ $sep = $this->context->msg( 'colon-separator' )->text();
+
+ # protect/protect
+ $this->assertIRCComment(
+ $this->context->msg( 'protectedarticle', 'SomeTitle ' . $protectParams[0] )
+ ->plain() . $sep . $this->user_comment,
+ 'protect', 'protect',
+ $protectParams,
+ $this->user_comment
+ );
+
+ # protect/unprotect
+ $this->assertIRCComment(
+ $this->context->msg( 'unprotectedarticle', 'SomeTitle' )->plain() . $sep . $this->user_comment,
+ 'protect', 'unprotect',
+ array(),
+ $this->user_comment
+ );
+
+ # protect/modify
+ $this->assertIRCComment(
+ $this->context->msg( 'modifiedarticleprotection', 'SomeTitle ' . $protectParams[0] )
+ ->plain() . $sep . $this->user_comment,
+ 'protect', 'modify',
+ $protectParams,
+ $this->user_comment
+ );
+ }
+
+ /**
+ * @covers LogFormatter::getIRCActionText
+ */
+ public function testIrcMsgForLogTypeUpload() {
+ $sep = $this->context->msg( 'colon-separator' )->text();
+
+ # upload/upload
+ $this->assertIRCComment(
+ $this->context->msg( 'uploadedimage', 'SomeTitle' )->plain() . $sep . $this->user_comment,
+ 'upload', 'upload',
+ array(),
+ $this->user_comment
+ );
+
+ # upload/overwrite
+ $this->assertIRCComment(
+ $this->context->msg( 'overwroteimage', 'SomeTitle' )->plain() . $sep . $this->user_comment,
+ 'upload', 'overwrite',
+ array(),
+ $this->user_comment
+ );
+ }
+
+ /**
+ * @todo Emulate these edits somehow and extract
+ * raw edit summary from RecentChange object
+ * --
+ */
+ /*
+ public function testIrcMsgForBlankingAES() {
+ // $this->context->msg( 'autosumm-blank', .. );
+ }
+
+ public function testIrcMsgForReplaceAES() {
+ // $this->context->msg( 'autosumm-replace', .. );
+ }
+
+ public function testIrcMsgForRollbackAES() {
+ // $this->context->msg( 'revertpage', .. );
+ }
+
+ public function testIrcMsgForUndoAES() {
+ // $this->context->msg( 'undo-summary', .. );
+ }
+ */
+
+ /**
+ * @param string $expected Expected IRC text without colors codes
+ * @param string $type Log type (move, delete, suppress, patrol ...)
+ * @param string $action A log type action
+ * @param array $params
+ * @param string $comment (optional) A comment for the log action
+ * @param string $msg (optional) A message for PHPUnit :-)
+ */
+ protected function assertIRCComment( $expected, $type, $action, $params,
+ $comment = null, $msg = ''
+ ) {
+ $logEntry = new ManualLogEntry( $type, $action );
+ $logEntry->setPerformer( $this->user );
+ $logEntry->setTarget( $this->title );
+ if ( $comment !== null ) {
+ $logEntry->setComment( $comment );
+ }
+ $logEntry->setParameters( $params );
+
+ $formatter = LogFormatter::newFromEntry( $logEntry );
+ $formatter->setContext( $this->context );
+
+ // Apply the same transformation as done in IRCColourfulRCFeedFormatter::getLine for rc_comment
+ $ircRcComment = IRCColourfulRCFeedFormatter::cleanupForIRC( $formatter->getIRCActionComment() );
+
+ $this->assertEquals(
+ $expected,
+ $ircRcComment,
+ $msg
+ );
+ }
+}
diff --git a/tests/phpunit/includes/changes/TestRecentChangesHelper.php b/tests/phpunit/includes/changes/TestRecentChangesHelper.php
new file mode 100644
index 00000000..ad643274
--- /dev/null
+++ b/tests/phpunit/includes/changes/TestRecentChangesHelper.php
@@ -0,0 +1,137 @@
+<?php
+
+/**
+ * Helper for generating test recent changes entries.
+ *
+ * @licence GNU GPL v2+
+ * @author Katie Filbert < aude.wiki@gmail.com >
+ */
+class TestRecentChangesHelper {
+
+ public function makeEditRecentChange( User $user, $titleText, $curid, $thisid, $lastid,
+ $timestamp, $counter, $watchingUsers
+ ) {
+
+ $attribs = array_merge(
+ $this->getDefaultAttributes( $titleText, $timestamp ),
+ array(
+ 'rc_user' => $user->getId(),
+ 'rc_user_text' => $user->getName(),
+ 'rc_this_oldid' => $thisid,
+ 'rc_last_oldid' => $lastid,
+ 'rc_cur_id' => $curid
+ )
+ );
+
+ return $this->makeRecentChange( $attribs, $counter, $watchingUsers );
+ }
+
+ public function makeLogRecentChange( $logType, $logAction, User $user, $titleText, $timestamp, $counter,
+ $watchingUsers
+ ) {
+ $attribs = array_merge(
+ $this->getDefaultAttributes( $titleText, $timestamp ),
+ array(
+ 'rc_cur_id' => 0,
+ 'rc_user' => $user->getId(),
+ 'rc_user_text' => $user->getName(),
+ 'rc_this_oldid' => 0,
+ 'rc_last_oldid' => 0,
+ 'rc_old_len' => null,
+ 'rc_new_len' => null,
+ 'rc_type' => 3,
+ 'rc_logid' => 25,
+ 'rc_log_type' => $logType,
+ 'rc_log_action' => $logAction,
+ 'rc_source' => 'mw.log'
+ )
+ );
+
+ return $this->makeRecentChange( $attribs, $counter, $watchingUsers );
+ }
+
+ public function makeDeletedEditRecentChange( User $user, $titleText, $timestamp, $curid,
+ $thisid, $lastid, $counter, $watchingUsers
+ ) {
+ $attribs = array_merge(
+ $this->getDefaultAttributes( $titleText, $timestamp ),
+ array(
+ 'rc_user' => $user->getId(),
+ 'rc_user_text' => $user->getName(),
+ 'rc_deleted' => 5,
+ 'rc_cur_id' => $curid,
+ 'rc_this_oldid' => $thisid,
+ 'rc_last_oldid' => $lastid
+ )
+ );
+
+ return $this->makeRecentChange( $attribs, $counter, $watchingUsers );
+ }
+
+ public function makeNewBotEditRecentChange( User $user, $titleText, $curid, $thisid, $lastid,
+ $timestamp, $counter, $watchingUsers
+ ) {
+
+ $attribs = array_merge(
+ $this->getDefaultAttributes( $titleText, $timestamp ),
+ array(
+ 'rc_user' => $user->getId(),
+ 'rc_user_text' => $user->getName(),
+ 'rc_this_oldid' => $thisid,
+ 'rc_last_oldid' => $lastid,
+ 'rc_cur_id' => $curid,
+ 'rc_type' => 1,
+ 'rc_bot' => 1,
+ 'rc_source' => 'mw.new'
+ )
+ );
+
+ return $this->makeRecentChange( $attribs, $counter, $watchingUsers );
+ }
+
+ private function makeRecentChange( $attribs, $counter, $watchingUsers ) {
+ $change = new RecentChange();
+ $change->setAttribs( $attribs );
+ $change->counter = $counter;
+ $change->numberofWatchingusers = $watchingUsers;
+
+ return $change;
+ }
+
+ private function getDefaultAttributes( $titleText, $timestamp ) {
+ return array(
+ 'rc_id' => 545,
+ 'rc_user' => 0,
+ 'rc_user_text' => '127.0.0.1',
+ 'rc_ip' => '127.0.0.1',
+ 'rc_title' => $titleText,
+ 'rc_namespace' => 0,
+ 'rc_timestamp' => $timestamp,
+ 'rc_old_len' => 212,
+ 'rc_new_len' => 188,
+ 'rc_comment' => '',
+ 'rc_minor' => 0,
+ 'rc_bot' => 0,
+ 'rc_type' => 0,
+ 'rc_patrolled' => 1,
+ 'rc_deleted' => 0,
+ 'rc_logid' => 0,
+ 'rc_log_type' => null,
+ 'rc_log_action' => '',
+ 'rc_params' => '',
+ 'rc_source' => 'mw.edit'
+ );
+ }
+
+ public function getTestContext( User $user ) {
+ $context = new RequestContext();
+ $context->setLanguage( Language::factory( 'en' ) );
+
+ $context->setUser( $user );
+
+ $title = Title::newFromText( 'RecentChanges', NS_SPECIAL );
+ $context->setTitle( $title );
+
+ return $context;
+ }
+}