mediawiki-extensions-Math/tests/phpunit/unit/MathWikibaseConnectorTestFactory.php

237 lines
8.2 KiB
PHP
Raw Normal View History

<?php
namespace MediaWiki\Extension\Math\Tests;
use DataValues\StringValue;
use MediaWiki\Config\ServiceOptions;
use MediaWiki\Extension\Math\MathFormatter;
use MediaWiki\Extension\Math\MathWikibaseConnector;
use MediaWiki\Language\Language;
use MediaWiki\Languages\LanguageFactory;
use MediaWiki\Languages\LanguageNameUtils;
use MediaWiki\Registration\ExtensionRegistry;
use MediaWiki\Site\Site;
use MediaWikiUnitTestCase;
use Psr\Log\LoggerInterface;
use TestLogger;
use Wikibase\Client\RepoLinker;
use Wikibase\DataModel\Entity\BasicEntityIdParser;
use Wikibase\DataModel\Entity\EntityId;
use Wikibase\DataModel\Entity\EntityIdParser;
use Wikibase\DataModel\Entity\EntityIdValue;
use Wikibase\DataModel\Entity\Item;
use Wikibase\DataModel\Entity\ItemId;
use Wikibase\DataModel\Entity\NumericPropertyId;
use Wikibase\DataModel\SiteLink;
use Wikibase\DataModel\Snak\PropertyValueSnak;
use Wikibase\DataModel\Snak\SnakList;
use Wikibase\DataModel\Statement\Statement;
use Wikibase\DataModel\Statement\StatementList;
use Wikibase\DataModel\Term\Term;
use Wikibase\Lib\Store\EntityRevision;
use Wikibase\Lib\Store\EntityRevisionLookup;
use Wikibase\Lib\Store\FallbackLabelDescriptionLookup;
use Wikibase\Lib\Store\FallbackLabelDescriptionLookupFactory;
use Wikibase\Lib\Store\StorageException;
class MathWikibaseConnectorTestFactory extends MediaWikiUnitTestCase {
public const EXAMPLE_URL = 'https://example.com/';
public const TEST_ITEMS = [
'Q1' => [ 'massenergy equivalence', 'physical law relating mass to energy', 'E = mc^2' ],
'Q2' => [ 'energy', 'measure for the ability of a system to do work', 'E' ],
'Q3' => [
'speed of light',
'speed at which all massless particles and associated fields travel in vacuum',
'c'
],
'Q4' => [
'mass',
'property of matter to resist changes of the state of motion and to attract other bodies',
'm'
]
];
public static function setUpBeforeClass(): void {
ExtensionRegistry::enableForTest();
if ( !ExtensionRegistry::getInstance()->isLoaded( 'WikibaseClient' ) ) {
self::markTestSkipped( 'WikibaseClient is not installed. Skipping tests.' );
}
ExtensionRegistry::disableForTest();
parent::setUpBeforeClass();
}
public function getWikibaseConnectorWithExistingItems(
EntityRevision $entityRevision,
bool $storageExceptionOnQ3 = false,
LoggerInterface $logger = null,
EntityIdParser $parser = null
): MathWikibaseConnector {
$revisionLookupMock = $this->createMock( EntityRevisionLookup::class );
$revisionLookupMock->method( 'getEntityRevision' )->willReturnCallback(
static function ( EntityId $entityId ) use ( $entityRevision, $storageExceptionOnQ3 ) {
if ( $storageExceptionOnQ3 && $entityId->getSerialization() === 'Q3' ) {
throw new StorageException( 'Test Exception' );
} else {
return $entityRevision;
}
}
);
$revisionLookupMock->expects( self::atLeastOnce() )
->method( 'getEntityRevision' );
$fallbackLabelDescriptionLookupFactoryMock = $this->createMock( FallbackLabelDescriptionLookupFactory::class );
$languageMock = $this->createMock( Language::class );
$languageFactoryMock = $this->createMock( LanguageFactory::class );
$languageFactoryMock->method( 'getLanguage' )
->with( 'en' )
->willReturn( $languageMock );
$languageNameUtilsMock = $this->createMock( LanguageNameUtils::class );
$languageNameUtilsMock->method( 'isValidCode' )
->with( 'en' )
->willReturn( true );
$fallbackLabelDescriptionLookupFactoryMock->method( 'newLabelDescriptionLookup' )
->with( $languageMock )
->willReturnCallback( [ $this, 'newLabelDescriptionLookup' ] );
return self::getWikibaseConnector(
$languageFactoryMock,
$languageNameUtilsMock,
$fallbackLabelDescriptionLookupFactoryMock,
$revisionLookupMock,
$logger,
$parser
);
}
public function getWikibaseConnector(
LanguageFactory $languageFactory = null,
LanguageNameUtils $languageNameUtils = null,
FallbackLabelDescriptionLookupFactory $labelDescriptionLookupFactory = null,
EntityRevisionLookup $entityRevisionLookupMock = null,
LoggerInterface $logger = null,
EntityIdParser $parser = null
): MathWikibaseConnector {
$labelDescriptionLookupFactory = $labelDescriptionLookupFactory ?:
$this->createMock( FallbackLabelDescriptionLookupFactory::class );
$entityRevisionLookup = $entityRevisionLookupMock ?:
$this->createMock( EntityRevisionLookup::class );
$languageFactory = $languageFactory ?: $this->createMock( LanguageFactory::class );
if ( !$languageNameUtils ) {
$languageNameUtils = $this->createMock( LanguageNameUtils::class );
$languageNameUtils->method( 'isValidCode' )->willReturn( true );
}
$site = $this->createMock( Site::class );
$site->method( 'getGlobalId' )->willReturn( '' );
$site->method( 'getPageUrl' )->willReturn( self::EXAMPLE_URL );
$repoConnector = $this->createMock( RepoLinker::class );
$repoConnector->method( 'getEntityUrl' )
->willReturnCallback( static function ( ItemId $itemId ) {
return self::EXAMPLE_URL . 'wiki/Special:EntityPage/' . $itemId->getSerialization();
} );
$mathFormatter = $this->createMock( MathFormatter::class );
$mathFormatter->method( 'format' )
->willReturnCallback( static function ( StringValue $value ) {
return self::getExpectedMathML( $value->getValue() );
} );
return new MathWikibaseConnector(
new ServiceOptions( MathWikibaseConnector::CONSTRUCTOR_OPTIONS, [
'MathWikibasePropertyIdHasPart' => 'P1',
'MathWikibasePropertyIdDefiningFormula' => 'P2',
'MathWikibasePropertyIdQuantitySymbol' => 'P3',
'MathWikibasePropertyIdInDefiningFormula' => 'P4',
'MathWikibasePropertyIdSymbolRepresents' => 'P5'
] ),
$repoConnector,
$languageFactory,
$languageNameUtils,
$entityRevisionLookup,
$labelDescriptionLookupFactory,
$site,
$parser ?: new BasicEntityIdParser(),
$mathFormatter,
$logger ?: new TestLogger()
);
}
public function setupMassEnergyEquivalenceItem(
bool $hasPartMode
) {
$partPropertyId = new NumericPropertyId( $hasPartMode ? 'P1' : 'P4' );
$symbolPropertyId = new NumericPropertyId( $hasPartMode ? 'P3' : 'P5' );
$items = [];
$statements = [];
foreach ( self::TEST_ITEMS as $key => $itemInfo ) {
$itemId = new ItemId( $key );
$items[ $key ] = new Item( $itemId );
$siteLinkMock = $this->createMock( SiteLink::class );
$siteLinkMock->method( 'getSiteId' )->willReturn( '' );
$siteLinkMock->method( 'getPageName' )->willReturn( '' );
$items[ $key ]->addSiteLink( $siteLinkMock );
if ( $key === 'Q1' ) {
continue;
}
$partSnak = new PropertyValueSnak(
$partPropertyId,
$hasPartMode ? new EntityIdValue( $items[ $key ]->getId() ) : new StringValue( $itemInfo[2] )
);
$partQualifier = new PropertyValueSnak(
$symbolPropertyId,
$hasPartMode ? new StringValue( $itemInfo[2] ) : new EntityIdValue( $items[ $key ]->getId() )
);
$statement = new Statement( $partSnak );
$statement->setQualifiers( new SnakList( [ $partQualifier ] ) );
$statements[] = $statement;
}
$mainFormulaValue = new StringValue( self::TEST_ITEMS[ 'Q1' ][2] );
$definingFormulaStatement = new Statement( new PropertyValueSnak(
new NumericPropertyId( 'P2' ),
$mainFormulaValue
) );
$statementList = new StatementList( ...$statements );
$statementList->addStatement( $definingFormulaStatement );
$items[ 'Q1' ]->setStatements( $statementList );
return $items[ 'Q1' ];
}
public function newLabelDescriptionLookup(): FallbackLabelDescriptionLookup {
$lookup = $this->createMock( FallbackLabelDescriptionLookup::class );
$lookup->method( 'getLabel' )
->willReturnCallback( static function ( EntityId $entityId ) {
if ( self::TEST_ITEMS[ $entityId->getSerialization() ] !== null ) {
return new Term( 'en', self::TEST_ITEMS[ $entityId->getSerialization() ][0] );
} else {
return null;
}
} );
$lookup->method( 'getDescription' )
->willReturnCallback( static function ( EntityId $entityId ) {
if ( self::TEST_ITEMS[ $entityId->getSerialization() ] !== null ) {
return new Term( 'en', self::TEST_ITEMS[ $entityId->getSerialization() ][1] );
} else {
return null;
}
} );
return $lookup;
}
public static function getExpectedMathML( $str ) {
return '<math>' . $str . '</math>';
}
}