Add tests for RevisionList/RevisionItem classes

Fix RevisionItemBase::getId to actually return an int, as intended

Previously all four classes (RevisionItem, RevisionItemBase,
RevisionList, and RevisionListBase) had no coverage. Now:

+--------------------------------------------+-------+--------+
| Filename                                   | Old % | New %  |
+--------------------------------------------+-------+--------+
| includes/revisionlist/RevisionItem.php     | 0     |  46.77 |
| includes/revisionlist/RevisionItemBase.php | 0     |  70.27 |
| includes/revisionlist/RevisionList.php     | 0     | 100.00 |
| includes/revisionlist/RevisionListBase.php | 0     |  76.32 |
+--------------------------------------------+-------+--------+

Bug: T252076
Change-Id: I3da1ae350986ef6dc54a13ae9275b4c1d03f6e5b
This commit is contained in:
DannyS712 2020-05-06 21:47:34 +00:00 committed by James D. Forrester
parent e17780ebcf
commit 4a206f1f90
4 changed files with 247 additions and 1 deletions

View file

@ -93,7 +93,7 @@ abstract class RevisionItemBase {
*/
public function getId() {
$field = $this->getIdField();
return $this->row->$field;
return intval( $this->row->$field );
}
/**

View file

@ -0,0 +1,134 @@
<?php
use MediaWiki\MediaWikiServices;
use Wikimedia\Rdbms\FakeResultWrapper;
use Wikimedia\Rdbms\IDatabase;
/**
* @covers RevisionList
* @covers RevisionListBase
* @covers RevisionItem
* @covers RevisionItemBase
* @group Database
*
* @author DannyS712
*/
class RevisionListTest extends MediaWikiIntegrationTestCase {
public function setUp() : void {
parent::setUp();
$this->tablesUsed[] = 'revision';
$this->tablesUsed[] = 'page';
$this->tablesUsed[] = 'comment';
$this->tablesUsed[] = 'content';
$this->tablesUsed[] = 'user';
}
public function testGetType() {
$context = new RequestContext();
$title = Title::newFromText( __METHOD__ );
$revisionList = new RevisionList( $context, $title );
$this->assertSame(
'revision',
$revisionList->getType()
);
}
/**
* @dataProvider provideTestDoQuery
*/
public function testDoQuery( $filterIds ) {
$context = new RequestContext();
$title = $this->createMock( Title::class );
$title->expects( $this->once() )
->method( 'getArticleID' )
->willReturn( 123 );
$revisionList = new RevisionList( $context, $title );
$conds = [ 'rev_page' => 123 ];
if ( $filterIds !== false ) {
$revisionList->filterByIds( $filterIds );
$conds['rev_id'] = $filterIds;
}
$revQuery = MediaWikiServices::getInstance()
->getRevisionStore()
->getQueryInfo( [ 'page', 'user' ] );
$db = $this->createMock( IDatabase::class );
$db->expects( $this->once() )
->method( 'select' )
->with(
$this->equalTo( $revQuery['tables'] ),
$this->equalTo( $revQuery['fields'] ),
$this->equalTo( $conds ),
$this->equalTo( 'RevisionList::doQuery' ),
$this->equalTo( [ 'ORDER BY' => 'rev_id DESC' ] ),
$this->equalTo( $revQuery['joins'] )
)
->willReturn(
new FakeResultWrapper( [] )
);
$revisionList->doQuery( $db );
}
public function provideTestDoQuery() {
return [
'no filter' => [ false ],
'with filter' => [ [ 1, 2, 91 ] ],
];
}
public function testNewItem() {
// Need a row that is valid for RevisionFactory::newRevisionFromRow
$wikiPage = $this->getExistingTestPage( __METHOD__ );
$currentRevId = $wikiPage->getRevisionRecord()->getId();
$revQuery = MediaWikiServices::getInstance()
->getRevisionStore()
->getQueryInfo( [ 'page', 'user' ] );
$row = $this->db->selectRow(
$revQuery['tables'],
$revQuery['fields'],
[ 'rev_id' => $currentRevId ],
__METHOD__,
[],
$revQuery['joins']
);
$context = new RequestContext();
$context->setUser( $this->getTestSysop()->getUser() );
$title = Title::newFromText( __METHOD__ );
$revisionList = new RevisionList( $context, $title );
$revisionItem = $revisionList->newItem( $row );
$this->assertInstanceOf( RevisionItem::class, $revisionItem );
// Tests for RevisionItem getters
$this->assertSame( 'rev_id', $revisionItem->getIdField() );
$this->assertSame( 'rev_timestamp', $revisionItem->getTimestampField() );
$this->assertSame( 'rev_user', $revisionItem->getAuthorIdField() );
$this->assertSame( 'rev_user_text', $revisionItem->getAuthorNameField() );
// Tests for RevisionItemBase getters that are not overridden
$this->assertSame( $currentRevId, $revisionItem->getId() );
$this->assertSame( intval( $row->rev_user ), $revisionItem->getAuthorId() );
$this->assertSame( strval( $row->rev_user_text ), $revisionItem->getAuthorName() );
$this->assertSame(
wfTimestamp( TS_MW, $row->rev_timestamp ),
$revisionItem->getTimestamp()
);
// Text of the latest revision cannot be deleted, so it is always viewable
$this->assertTrue( $revisionItem->canView() );
$this->assertTrue( $revisionItem->canViewContent() );
$this->assertFalse( $revisionItem->isDeleted() );
}
}

View file

@ -0,0 +1,23 @@
<?php
/**
* @covers RevisionItemBase
*
* @author DannyS712
*/
class RevisionItemBaseTest extends MediaWikiUnitTestCase {
public function testConcreteMethods() {
// Test the concrete methods of the abstract RevisionItemBase class
$revisionItemBase = $this->getMockBuilder( RevisionItemBase::class )
->disableOriginalConstructor()
->getMockForAbstractClass();
$this->assertNull( $revisionItemBase->getIdField() );
$this->assertFalse( $revisionItemBase->getTimestampField() );
$this->assertFalse( $revisionItemBase->getAuthorIdField() );
$this->assertFalse( $revisionItemBase->getAuthorNameField() );
$this->assertFalse( $revisionItemBase->getAuthorActorField() );
}
}

View file

@ -0,0 +1,89 @@
<?php
use Wikimedia\Rdbms\IResultWrapper;
use Wikimedia\TestingAccessWrapper;
/**
* @covers RevisionListBase
*
* @author DannyS712
*/
class RevisionListBaseTest extends MediaWikiUnitTestCase {
public function testGetType() {
$revisionListBase = $this->getMockBuilder( RevisionListBase::class )
->disableOriginalConstructor()
->getMockForAbstractClass();
$this->assertNull( $revisionListBase->getType() );
}
public function testReset() {
$revisionListBase = $this->getMockBuilder( RevisionListBase::class )
->disableOriginalConstructor()
->getMockForAbstractClass();
$revisionItemBase = $this->getMockBuilder( RevisionItemBase::class )
->disableOriginalConstructor()
->getMockForAbstractClass();
// Actual contents aren't used
$fakeRow = (object)[ 'key' => 'val' ];
$resultWrapper = $this->getMockBuilder( IResultWrapper::class )
->disableOriginalConstructor()
->getMock();
$resultWrapper->expects( $this->once() )
->method( 'rewind' );
$resultWrapper->expects( $this->once() )
->method( 'current' )
->willReturn( $fakeRow );
$revisionListBase->expects( $this->once() )
->method( 'newItem' )
->with( $fakeRow )
->willReturn( $revisionItemBase );
// res is normally the result of a db query that uses wfGetDB and cannot
// be tested in a unit test
$mockAccess = TestingAccessWrapper::newFromObject( $revisionListBase );
$mockAccess->res = $resultWrapper;
$this->assertSame( $revisionItemBase, $revisionListBase->reset() );
$this->assertSame( $revisionItemBase, $revisionListBase->current() );
}
public function testResultWrapper() {
// Test methods that only depend on the result wrapper
$revisionListBase = $this->getMockBuilder( RevisionListBase::class )
->disableOriginalConstructor()
->getMockForAbstractClass();
$this->assertSame( 0, $revisionListBase->key() );
$this->assertFalse( $revisionListBase->valid() );
$this->assertSame( 0, $revisionListBase->length() );
$resultWrapper = $this->getMockBuilder( IResultWrapper::class )
->disableOriginalConstructor()
->getMock();
$resultWrapper->expects( $this->once() )
->method( 'key' )
->willReturn( 991 );
$resultWrapper->expects( $this->once() )
->method( 'valid' )
->willReturn( true );
$resultWrapper->expects( $this->once() )
->method( 'numRows' )
->willReturn( 457 );
// res is normally the result of a db query that uses wfGetDB and cannot
// be tested in a unit test
$mockAccess = TestingAccessWrapper::newFromObject( $revisionListBase );
$mockAccess->res = $resultWrapper;
$this->assertSame( 991, $revisionListBase->key() );
$this->assertTrue( $revisionListBase->valid() );
$this->assertSame( 457, $revisionListBase->length() );
}
}