mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/Math
synced 2024-11-23 15:16:56 +00:00
REST API endpoint for popups
Implement a rest API endpoint that displays the popup that is currently only shown on a special page. Code was revived from Idd22057a88312bf1a1cb5546d0a6edca5678d80d Bug: T288076 Bug: T233099 Change-Id: I65fcbf25ac5818f6c649daf494c719921247e8f5
This commit is contained in:
parent
a4174e2ecd
commit
951dec1fab
|
@ -4,11 +4,13 @@ use MediaWiki\Config\ServiceOptions;
|
|||
use MediaWiki\Extension\Math\InputCheck\InputCheckFactory;
|
||||
use MediaWiki\Extension\Math\Math;
|
||||
use MediaWiki\Extension\Math\MathConfig;
|
||||
use MediaWiki\Extension\Math\MathFormatter;
|
||||
use MediaWiki\Extension\Math\MathWikibaseConnector;
|
||||
use MediaWiki\Extension\Math\Render\RendererFactory;
|
||||
use MediaWiki\Logger\LoggerFactory;
|
||||
use MediaWiki\MediaWikiServices;
|
||||
use Wikibase\Client\WikibaseClient;
|
||||
use Wikibase\Lib\Formatters\SnakFormatter;
|
||||
|
||||
return [
|
||||
'Math.CheckerFactory' => static function ( MediaWikiServices $services ): InputCheckFactory {
|
||||
|
@ -48,6 +50,7 @@ return [
|
|||
WikibaseClient::getFallbackLabelDescriptionLookupFactory( $services ),
|
||||
WikibaseClient::getSite( $services ),
|
||||
WikibaseClient::getEntityIdParser( $services ),
|
||||
new MathFormatter( SnakFormatter::FORMAT_HTML ),
|
||||
LoggerFactory::getInstance( 'Math' )
|
||||
);
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
},
|
||||
"TestAutoloadClasses": {
|
||||
"DummyPropertyDataTypeLookup": "tests/phpunit/DummyPropertyDataTypeLookup.php",
|
||||
"MediaWiki\\Extension\\Math\\Tests\\MathWikibaseConnectorTestFactory": "tests/phpunit/unit/MathWikibaseConnectorTestFactory.php",
|
||||
"MediaWiki\\Extension\\Math\\Tests\\MathMockHttpTrait": "tests/phpunit/MathMockHttpTrait.php"
|
||||
},
|
||||
"DefaultUserOptions": {
|
||||
|
@ -351,5 +352,17 @@
|
|||
"ServiceWiringFiles": [
|
||||
"ServiceWiring.php"
|
||||
],
|
||||
"RestRoutes": [
|
||||
{
|
||||
"path": "/math/v0/popup/html/{qid}",
|
||||
"method": "GET",
|
||||
"class": "MediaWiki\\Extension\\Math\\Rest\\Popup",
|
||||
"services": [
|
||||
"Math.WikibaseConnector",
|
||||
"LanguageFactory",
|
||||
"TitleFactory"
|
||||
]
|
||||
}
|
||||
],
|
||||
"manifest_version": 2
|
||||
}
|
||||
|
|
8813
package-lock.json
generated
8813
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -4,14 +4,17 @@
|
|||
"scripts": {
|
||||
"test": "grunt test",
|
||||
"selenium-daily": "npm run selenium-test",
|
||||
"selenium-test": "wdio tests/selenium/wdio.conf.js"
|
||||
"selenium-test": "wdio tests/selenium/wdio.conf.js",
|
||||
"api-testing": "mocha tests/api-testing"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@wdio/cli": "7.16.13",
|
||||
"@wdio/dot-reporter": "7.16.13",
|
||||
"@wdio/junit-reporter": "7.16.13",
|
||||
"@wdio/local-runner": "7.16.13",
|
||||
"@wdio/mocha-framework": "7.16.13",
|
||||
"@wdio/spec-reporter": "7.16.13",
|
||||
"api-testing": "^1.4.2",
|
||||
"eslint-config-wikimedia": "0.22.1",
|
||||
"grunt": "1.5.2",
|
||||
"grunt-banana-checker": "0.9.0",
|
||||
|
|
|
@ -60,6 +60,9 @@ class MathWikibaseConnector {
|
|||
/** @var FallbackLabelDescriptionLookupFactory */
|
||||
private $labelDescriptionLookupFactory;
|
||||
|
||||
/** @var MathFormatter */
|
||||
private $mathFormatter;
|
||||
|
||||
/** @var EntityIdParser */
|
||||
private $idParser;
|
||||
|
||||
|
@ -86,6 +89,7 @@ class MathWikibaseConnector {
|
|||
* @param FallbackLabelDescriptionLookupFactory $labelDescriptionLookupFactory
|
||||
* @param Site $site
|
||||
* @param EntityIdParser $entityIdParser
|
||||
* @param MathFormatter $mathFormatter
|
||||
* @param LoggerInterface $logger
|
||||
*/
|
||||
public function __construct(
|
||||
|
@ -96,6 +100,7 @@ class MathWikibaseConnector {
|
|||
FallbackLabelDescriptionLookupFactory $labelDescriptionLookupFactory,
|
||||
Site $site,
|
||||
EntityIdParser $entityIdParser,
|
||||
MathFormatter $mathFormatter,
|
||||
LoggerInterface $logger
|
||||
) {
|
||||
$options->assertRequiredOptions( self::CONSTRUCTOR_OPTIONS );
|
||||
|
@ -105,6 +110,7 @@ class MathWikibaseConnector {
|
|||
$this->labelDescriptionLookupFactory = $labelDescriptionLookupFactory;
|
||||
$this->site = $site;
|
||||
$this->idParser = $entityIdParser;
|
||||
$this->mathFormatter = $mathFormatter;
|
||||
$this->logger = $logger;
|
||||
|
||||
$this->propertyIdHasPart = $this->loadPropertyId(
|
||||
|
@ -160,7 +166,7 @@ class MathWikibaseConnector {
|
|||
* @throws InvalidArgumentException if the language code does not exist or the given
|
||||
* id does not exist
|
||||
*/
|
||||
public function fetchWikibaseFromId( $qid, $langCode ): MathWikibaseInfo {
|
||||
public function fetchWikibaseFromId( string $qid, string $langCode ): MathWikibaseInfo {
|
||||
try {
|
||||
$lang = $this->languageFactory->getLanguage( $langCode );
|
||||
} catch ( MWException $e ) {
|
||||
|
@ -182,7 +188,7 @@ class MathWikibaseConnector {
|
|||
}
|
||||
|
||||
$entity = $entityRevision->getEntity();
|
||||
$output = new MathWikibaseInfo( $entityId );
|
||||
$output = new MathWikibaseInfo( $entityId, $this->mathFormatter );
|
||||
|
||||
if ( $entity instanceof Item ) {
|
||||
$this->fetchLabelDescription( $output, $langLookup );
|
||||
|
@ -292,7 +298,7 @@ class MathWikibaseConnector {
|
|||
$entityIdValue = $dataVal->getValue();
|
||||
if ( $entityIdValue instanceof EntityIdValue ) {
|
||||
$innerEntityId = $entityIdValue->getEntityId();
|
||||
$innerInfo = new MathWikibaseInfo( $innerEntityId );
|
||||
$innerInfo = new MathWikibaseInfo( $innerEntityId, $output->getFormatter() );
|
||||
$this->fetchLabelDescription( $innerInfo, $langLookup );
|
||||
$url = $this->fetchPageUrl( $innerEntityId );
|
||||
if ( $url ) {
|
||||
|
|
|
@ -47,9 +47,13 @@ class MathWikibaseInfo {
|
|||
*/
|
||||
private $url;
|
||||
|
||||
public function __construct( EntityId $entityId ) {
|
||||
/**
|
||||
* @param EntityId $entityId
|
||||
* @param MathFormatter|null $mathFormatter to format math equations. Default format is HTML.
|
||||
*/
|
||||
public function __construct( EntityId $entityId, MathFormatter $mathFormatter = null ) {
|
||||
$this->id = $entityId;
|
||||
$this->mathFormatter = new MathFormatter( SnakFormatter::FORMAT_HTML );
|
||||
$this->mathFormatter = $mathFormatter ?: new MathFormatter( SnakFormatter::FORMAT_HTML );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -77,7 +81,7 @@ class MathWikibaseInfo {
|
|||
* @param MathWikibaseInfo $info
|
||||
*/
|
||||
public function addHasPartElement( MathWikibaseInfo $info ) {
|
||||
array_push( $this->hasParts, $info );
|
||||
$this->hasParts[] = $info;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -147,6 +151,13 @@ class MathWikibaseInfo {
|
|||
return $this->url;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return MathFormatter
|
||||
*/
|
||||
public function getFormatter() {
|
||||
return $this->mathFormatter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does this info object has elements?
|
||||
* @return bool true if there are elements otherwise false
|
||||
|
|
115
src/Rest/Popup.php
Normal file
115
src/Rest/Popup.php
Normal file
|
@ -0,0 +1,115 @@
|
|||
<?php
|
||||
|
||||
namespace MediaWiki\Extension\Math\Rest;
|
||||
|
||||
use Html;
|
||||
use MediaWiki\Extension\Math\MathWikibaseConnector;
|
||||
use MediaWiki\Extension\Math\MathWikibaseInfo;
|
||||
use MediaWiki\Languages\LanguageFactory;
|
||||
use MediaWiki\Rest\Response;
|
||||
use MediaWiki\Rest\SimpleHandler;
|
||||
use MWException;
|
||||
use Title;
|
||||
use TitleFactory;
|
||||
use Wikimedia\ParamValidator\ParamValidator;
|
||||
|
||||
class Popup extends SimpleHandler {
|
||||
|
||||
/** @var MathWikibaseConnector */
|
||||
private $wikibase;
|
||||
|
||||
/** @var LanguageFactory */
|
||||
private $languageFactory;
|
||||
|
||||
/** @var Title|null */
|
||||
private $specialPageTitle;
|
||||
|
||||
/**
|
||||
* @param MathWikibaseConnector $wikibase
|
||||
* @param LanguageFactory $languageFactory
|
||||
* @param TitleFactory $titleFactory
|
||||
*/
|
||||
public function __construct(
|
||||
MathWikibaseConnector $wikibase,
|
||||
LanguageFactory $languageFactory,
|
||||
TitleFactory $titleFactory
|
||||
) {
|
||||
$this->wikibase = $wikibase;
|
||||
$this->languageFactory = $languageFactory;
|
||||
$this->specialPageTitle = $titleFactory->newFromText( 'Special:MathWikibase' );
|
||||
}
|
||||
|
||||
public function run( int $qid ): Response {
|
||||
$uselang = $this->getRequest()->getHeaderLine( 'Accept-Language' );
|
||||
if ( $uselang === '' ) {
|
||||
$uselang = 'en';
|
||||
}
|
||||
$rf = $this->getResponseFactory();
|
||||
try {
|
||||
$langObj = $this->languageFactory->getLanguage( $uselang );
|
||||
} catch ( MWException $e ) {
|
||||
return $rf->createHttpError( 400, [ 'message' => 'Invalid language code.' ] );
|
||||
}
|
||||
|
||||
try {
|
||||
$info = $this->wikibase->fetchWikibaseFromId( "Q{$qid}", $uselang );
|
||||
} catch ( \InvalidArgumentException $exception ) {
|
||||
return $rf->createHttpError( 400, [ 'message' => $exception->getMessage() ] );
|
||||
}
|
||||
|
||||
$html = $this->buildHTMLRepresentation( $info );
|
||||
|
||||
$response = [
|
||||
'title' => $info->getLabel(),
|
||||
'contentmodel' => 'html',
|
||||
'pagelanguagedir' => $langObj->getDir(),
|
||||
'pagelanguage' => $langObj->getCode(),
|
||||
'pagelanguagehtmlcode' => $langObj->getHtmlCode(),
|
||||
'extract' => $html
|
||||
];
|
||||
|
||||
if ( $this->specialPageTitle ) {
|
||||
$response = array_merge( $response, [
|
||||
'canonicalurl' => $this->specialPageTitle->getLocalURL( [ 'qid' => "Q{$qid}" ] ),
|
||||
'fullurl' => $this->specialPageTitle->getFullURL( [ 'qid' => "Q{$qid}" ] )
|
||||
] );
|
||||
}
|
||||
|
||||
return $rf->createJson( $response );
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates an HTML string from the given data.
|
||||
* @param MathWikibaseInfo $info an info object generated by fetchWikibaseFromId
|
||||
* @return string an HTML representation of the given info object
|
||||
*/
|
||||
private function buildHTMLRepresentation( MathWikibaseInfo $info ): string {
|
||||
$output =
|
||||
Html::openElement( "div",
|
||||
[ "style" =>
|
||||
"width: 100%; display: flex; flex-direction: column;
|
||||
align-items: flex-start; flex-wrap: wrap;" ] );
|
||||
$output .= Html::element( "span", [
|
||||
"style" => "font-weight: bold; text-transform: capitalize;"
|
||||
], $info->getLabel() );
|
||||
$output .= Html::element( "span", [ "style" => "font-size: small" ], " (" . $info->getDescription() . ")" );
|
||||
if ( $info->hasParts() ) {
|
||||
$output .= Html::rawElement( "div",
|
||||
[ "style" => "width: 100%; display: flex; justify-content: left; padding-top: 5px;" ],
|
||||
$info->generateSmallTableOfParts() );
|
||||
}
|
||||
$output .= Html::closeElement( "div" );
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
public function getParamSettings() {
|
||||
return [
|
||||
'qid' => [
|
||||
self::PARAM_SOURCE => 'path',
|
||||
ParamValidator::PARAM_TYPE => 'integer',
|
||||
ParamValidator::PARAM_REQUIRED => true,
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
|
@ -178,7 +178,7 @@ class SpecialMathWikibase extends SpecialPage {
|
|||
->plain();
|
||||
$output->addHTML( self::createHTMLHeader( $header ) );
|
||||
|
||||
if ( $info->getSymbol() ) {
|
||||
if ( $info->getFormattedSymbol() ) {
|
||||
$math = $info->getFormattedSymbol();
|
||||
$formulaInfo = new Message( 'math-wikibase-formula-header-format' );
|
||||
$formulaInfo->rawParams(
|
||||
|
@ -251,7 +251,7 @@ class SpecialMathWikibase extends SpecialPage {
|
|||
* Check whether Wikibase is available or not
|
||||
* @return bool
|
||||
*/
|
||||
public static function isWikibaseAvailable() {
|
||||
public static function isWikibaseAvailable(): bool {
|
||||
return ExtensionRegistry::getInstance()->isLoaded( 'WikibaseClient' );
|
||||
}
|
||||
}
|
||||
|
|
14
tests/api-testing/.eslintrc.json
Normal file
14
tests/api-testing/.eslintrc.json
Normal file
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"root": true,
|
||||
"extends": [
|
||||
"wikimedia/server",
|
||||
"wikimedia/node",
|
||||
"wikimedia/language/es2017"
|
||||
],
|
||||
"env": {
|
||||
"mocha": true
|
||||
},
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 2018
|
||||
}
|
||||
}
|
21
tests/api-testing/popupTest.js
Normal file
21
tests/api-testing/popupTest.js
Normal file
|
@ -0,0 +1,21 @@
|
|||
'use strict';
|
||||
|
||||
const { assert, REST } = require( 'api-testing' );
|
||||
|
||||
describe( 'Math popup endpoint test', () => {
|
||||
const client = new REST( 'rest.php/math/v0' );
|
||||
|
||||
it( 'should get a 400 response for bad value of hash param', async () => {
|
||||
const { status, body } = await client.get( '/popup/html/thebadvalue' );
|
||||
assert.strictEqual( status, 400 );
|
||||
assert.strictEqual( body.httpReason, 'Bad Request' );
|
||||
assert.include( body.messageTranslations.en, 'thebadvalue' );
|
||||
} );
|
||||
|
||||
it( 'should get a 400 response for a malformed item ID starting with Q', async () => {
|
||||
const { status, body } = await client.get( '/popup/html/Q1' );
|
||||
assert.strictEqual( status, 400 );
|
||||
assert.strictEqual( body.httpReason, 'Bad Request' );
|
||||
assert.include( body.messageTranslations.en, 'Q1' );
|
||||
} );
|
||||
} );
|
|
@ -3,61 +3,25 @@
|
|||
namespace MediaWiki\Extension\Math\Tests;
|
||||
|
||||
use DataValues\StringValue;
|
||||
use Language;
|
||||
use MediaWiki\Config\ServiceOptions;
|
||||
use MediaWiki\Extension\Math\MathWikibaseConnector;
|
||||
use MediaWiki\Languages\LanguageFactory;
|
||||
use MediaWiki\Logger\LoggerFactory;
|
||||
use MediaWikiUnitTestCase;
|
||||
use MWException;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Site;
|
||||
use TestLogger;
|
||||
use Wikibase\Client\RepoLinker;
|
||||
use Wikibase\DataAccess\DatabaseEntitySource;
|
||||
use Wikibase\DataAccess\EntitySourceDefinitions;
|
||||
use Wikibase\DataModel\Entity\BasicEntityIdParser;
|
||||
use Wikibase\DataModel\Entity\EntityId;
|
||||
use Wikibase\DataModel\Entity\EntityIdParser;
|
||||
use Wikibase\DataModel\Entity\EntityIdParsingException;
|
||||
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;
|
||||
use Wikibase\Lib\SubEntityTypesMapper;
|
||||
|
||||
/**
|
||||
* @covers \MediaWiki\Extension\Math\MathWikibaseConnector
|
||||
*/
|
||||
class MathWikibaseConnectorTest extends MediaWikiUnitTestCase {
|
||||
|
||||
private const EXAMPLE_URL = 'https://example.com/';
|
||||
|
||||
private const TEST_ITEMS = [
|
||||
'Q1' => [ 'mass–energy 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'
|
||||
]
|
||||
];
|
||||
class MathWikibaseConnectorTest extends MathWikibaseConnectorTestFactory {
|
||||
|
||||
public function testGetUrl() {
|
||||
$mathWikibase = $this->getWikibaseConnector();
|
||||
|
@ -184,6 +148,7 @@ class MathWikibaseConnectorTest extends MediaWikiUnitTestCase {
|
|||
$this->assertCount( 0, $wikibaseInfo->getParts() );
|
||||
$this->assertFalse( $wikibaseInfo->hasParts() );
|
||||
$this->assertNull( $wikibaseInfo->getSymbol() );
|
||||
$this->assertNull( $wikibaseInfo->getFormattedSymbol() );
|
||||
}
|
||||
|
||||
public function testFetchItemWithFormula() {
|
||||
|
@ -203,6 +168,10 @@ class MathWikibaseConnectorTest extends MediaWikiUnitTestCase {
|
|||
$wikibaseInfo = $wikibaseConnector->fetchWikibaseFromId( 'Q1', 'en' );
|
||||
$this->assertFalse( $wikibaseInfo->hasParts() );
|
||||
$this->assertEquals( $formulaValue, $wikibaseInfo->getSymbol() );
|
||||
$this->assertEquals(
|
||||
$this->getExpectedMathML( $formulaValue->getValue() ),
|
||||
$wikibaseInfo->getFormattedSymbol()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -215,7 +184,9 @@ class MathWikibaseConnectorTest extends MediaWikiUnitTestCase {
|
|||
$this->assertEquals( $item->getId(), $wikibaseInfo->getId() );
|
||||
$this->assertEquals( self::TEST_ITEMS[ 'Q1' ][0], $wikibaseInfo->getLabel() );
|
||||
$this->assertEquals( self::TEST_ITEMS[ 'Q1' ][1], $wikibaseInfo->getDescription() );
|
||||
$this->assertEquals( self::TEST_ITEMS[ 'Q1' ][2], $wikibaseInfo->getSymbol()->getValue() );
|
||||
$mathFormula = self::TEST_ITEMS[ 'Q1' ][2];
|
||||
$this->assertEquals( $mathFormula, $wikibaseInfo->getSymbol()->getValue() );
|
||||
$this->assertEquals( $this->getExpectedMathML( $mathFormula ), $wikibaseInfo->getFormattedSymbol() );
|
||||
|
||||
$this->assertTrue( $wikibaseInfo->hasParts() );
|
||||
$parts = $wikibaseInfo->getParts();
|
||||
|
@ -224,7 +195,9 @@ class MathWikibaseConnectorTest extends MediaWikiUnitTestCase {
|
|||
$key = $part->getId()->getSerialization();
|
||||
$this->assertEquals( self::TEST_ITEMS[ $key ][0], $part->getLabel() );
|
||||
$this->assertEquals( self::TEST_ITEMS[ $key ][1], $part->getDescription() );
|
||||
$this->assertEquals( self::TEST_ITEMS[ $key ][2], $part->getSymbol()->getValue() );
|
||||
$mathFormula = self::TEST_ITEMS[ $key ][2];
|
||||
$this->assertEquals( $mathFormula, $part->getSymbol()->getValue() );
|
||||
$this->assertEquals( $this->getExpectedMathML( $mathFormula ), $part->getFormattedSymbol() );
|
||||
$this->assertEquals( self::EXAMPLE_URL, $part->getUrl() );
|
||||
}
|
||||
}
|
||||
|
@ -270,174 +243,4 @@ class MathWikibaseConnectorTest extends MediaWikiUnitTestCase {
|
|||
[ $this->setupMassEnergyEquivalenceItem( false ) ],
|
||||
];
|
||||
}
|
||||
|
||||
private 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' ];
|
||||
}
|
||||
|
||||
private function newConnector(): RepoLinker {
|
||||
return new RepoLinker(
|
||||
new EntitySourceDefinitions(
|
||||
[
|
||||
new DatabaseEntitySource(
|
||||
'test',
|
||||
'testdb',
|
||||
[ 'item' => [ 'namespaceId' => 123, 'slot' => 'main' ] ],
|
||||
self::EXAMPLE_URL . 'entity',
|
||||
'',
|
||||
'',
|
||||
''
|
||||
)
|
||||
],
|
||||
new SubEntityTypesMapper( [] )
|
||||
),
|
||||
self::EXAMPLE_URL,
|
||||
'/wiki/$1',
|
||||
'' );
|
||||
}
|
||||
|
||||
private 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( $this->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 );
|
||||
$fallbackLabelDescriptionLookupFactoryMock->method( 'newLabelDescriptionLookup' )
|
||||
->with( $languageMock )
|
||||
->willReturnCallback( [ $this, 'newLabelDescriptionLookup' ] );
|
||||
|
||||
return $this->getWikibaseConnector(
|
||||
$languageFactoryMock,
|
||||
$fallbackLabelDescriptionLookupFactoryMock,
|
||||
$revisionLookupMock,
|
||||
$logger,
|
||||
$parser
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param LanguageFactory|null $languageFactory
|
||||
* @param FallbackLabelDescriptionLookupFactory|null $labelDescriptionLookupFactory
|
||||
* @param EntityRevisionLookup|null $entityRevisionLookupMock
|
||||
* @param LoggerInterface|null $logger
|
||||
* @param EntityIdParser|null $parser
|
||||
* @return MathWikibaseConnector
|
||||
*/
|
||||
public function getWikibaseConnector(
|
||||
LanguageFactory $languageFactory = 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 );
|
||||
$site = $this->createMock( Site::class );
|
||||
$site->method( 'getGlobalId' )->willReturn( '' );
|
||||
$site->method( 'getPageUrl' )->willReturn( self::EXAMPLE_URL );
|
||||
return new MathWikibaseConnector(
|
||||
new ServiceOptions( MathWikibaseConnector::CONSTRUCTOR_OPTIONS, [
|
||||
'MathWikibasePropertyIdHasPart' => 'P1',
|
||||
'MathWikibasePropertyIdDefiningFormula' => 'P2',
|
||||
'MathWikibasePropertyIdQuantitySymbol' => 'P3',
|
||||
'MathWikibasePropertyIdInDefiningFormula' => 'P4',
|
||||
'MathWikibasePropertyIdSymbolRepresents' => 'P5'
|
||||
] ),
|
||||
$this->newConnector(),
|
||||
$languageFactory,
|
||||
$entityRevisionLookup,
|
||||
$labelDescriptionLookupFactory,
|
||||
$site,
|
||||
$parser ?: new BasicEntityIdParser(),
|
||||
$logger ?: new TestLogger()
|
||||
);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
214
tests/phpunit/unit/MathWikibaseConnectorTestFactory.php
Normal file
214
tests/phpunit/unit/MathWikibaseConnectorTestFactory.php
Normal file
|
@ -0,0 +1,214 @@
|
|||
<?php
|
||||
|
||||
namespace MediaWiki\Extension\Math\Tests;
|
||||
|
||||
use DataValues\StringValue;
|
||||
use Language;
|
||||
use MediaWiki\Config\ServiceOptions;
|
||||
use MediaWiki\Extension\Math\MathFormatter;
|
||||
use MediaWiki\Extension\Math\MathWikibaseConnector;
|
||||
use MediaWiki\Languages\LanguageFactory;
|
||||
use MediaWikiUnitTestCase;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Site;
|
||||
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' => [ 'mass–energy 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 function getWikibaseConnectorWithExistingItems(
|
||||
EntityRevision $entityRevision,
|
||||
bool $storageExceptionOnQ3 = false,
|
||||
LoggerInterface $logger = null,
|
||||
EntityIdParser $parser = null
|
||||
): MathWikibaseConnector {
|
||||
$revisionLookupMock = self::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 = self::createMock( FallbackLabelDescriptionLookupFactory::class );
|
||||
$languageMock = self::createMock( Language::class );
|
||||
$languageFactoryMock = self::createMock( LanguageFactory::class );
|
||||
$languageFactoryMock->method( 'getLanguage' )
|
||||
->with( 'en' )
|
||||
->willReturn( $languageMock );
|
||||
$fallbackLabelDescriptionLookupFactoryMock->method( 'newLabelDescriptionLookup' )
|
||||
->with( $languageMock )
|
||||
->willReturnCallback( [ $this, 'newLabelDescriptionLookup' ] );
|
||||
|
||||
return self::getWikibaseConnector(
|
||||
$languageFactoryMock,
|
||||
$fallbackLabelDescriptionLookupFactoryMock,
|
||||
$revisionLookupMock,
|
||||
$logger,
|
||||
$parser
|
||||
);
|
||||
}
|
||||
|
||||
public function getWikibaseConnector(
|
||||
LanguageFactory $languageFactory = null,
|
||||
FallbackLabelDescriptionLookupFactory $labelDescriptionLookupFactory = null,
|
||||
EntityRevisionLookup $entityRevisionLookupMock = null,
|
||||
LoggerInterface $logger = null,
|
||||
EntityIdParser $parser = null
|
||||
): MathWikibaseConnector {
|
||||
$labelDescriptionLookupFactory = $labelDescriptionLookupFactory ?:
|
||||
self::createMock( FallbackLabelDescriptionLookupFactory::class );
|
||||
|
||||
$entityRevisionLookup = $entityRevisionLookupMock ?:
|
||||
self::createMock( EntityRevisionLookup::class );
|
||||
|
||||
$languageFactory = $languageFactory ?: self::createMock( LanguageFactory::class );
|
||||
|
||||
$site = self::createMock( Site::class );
|
||||
$site->method( 'getGlobalId' )->willReturn( '' );
|
||||
$site->method( 'getPageUrl' )->willReturn( self::EXAMPLE_URL );
|
||||
|
||||
$repoConnector = self::createMock( RepoLinker::class );
|
||||
$repoConnector->method( 'getEntityUrl' )
|
||||
->willReturnCallback( static function ( ItemId $itemId ) {
|
||||
return self::EXAMPLE_URL . 'wiki/Special:EntityPage/' . $itemId->serialize();
|
||||
} );
|
||||
|
||||
$mathFormatter = self::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,
|
||||
$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 = self::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 = self::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>';
|
||||
}
|
||||
}
|
136
tests/phpunit/unit/PopupTest.php
Normal file
136
tests/phpunit/unit/PopupTest.php
Normal file
|
@ -0,0 +1,136 @@
|
|||
<?php
|
||||
|
||||
namespace MediaWiki\Extension\Math\Tests;
|
||||
|
||||
use MediaWiki\Extension\Math\Rest\Popup;
|
||||
use MediaWiki\Languages\LanguageFactory;
|
||||
use MediaWiki\Rest\Handler;
|
||||
use MediaWiki\Rest\HttpException;
|
||||
use MediaWiki\Rest\RequestData;
|
||||
use MediaWiki\Tests\Rest\Handler\HandlerTestTrait;
|
||||
use Title;
|
||||
use Wikibase\DataModel\Entity\Item;
|
||||
use Wikibase\Lib\Store\EntityRevision;
|
||||
use Wikimedia\ParamValidator\ParamValidator;
|
||||
|
||||
/**
|
||||
* @covers \MediaWiki\Extension\Math\Rest\Popup
|
||||
*/
|
||||
class PopupTest extends MathWikibaseConnectorTestFactory {
|
||||
|
||||
use HandlerTestTrait;
|
||||
|
||||
public function testNonExistingId() {
|
||||
$popupHandler = $this->getPopup();
|
||||
$response = $this->executeHandler( $popupHandler, $this->getRequest( '1', 'en' ) );
|
||||
$this->assertEquals( 400, $response->getStatusCode() );
|
||||
$data = json_decode( $response->getBody(), true );
|
||||
$this->assertEquals( 'Non-existing Wikibase ID.', $data[ 'message' ] );
|
||||
}
|
||||
|
||||
public function testParameterSettingsSetup() {
|
||||
$popupHandler = $this->getPopup();
|
||||
$this->assertSame( [ 'qid' => [
|
||||
HANDLER::PARAM_SOURCE => 'path',
|
||||
ParamValidator::PARAM_TYPE => 'integer',
|
||||
ParamValidator::PARAM_REQUIRED => true,
|
||||
] ], $popupHandler->getParamSettings() );
|
||||
}
|
||||
|
||||
public function testValidationExceptionForMalformedId() {
|
||||
$popupHandler = $this->getPopup();
|
||||
$this->initHandler( $popupHandler, $this->getRequest( 'Q1', 'en' ) );
|
||||
$this->expectException( HttpException::class );
|
||||
$this->validateHandler( $popupHandler );
|
||||
}
|
||||
|
||||
public function testInvalidLanguage() {
|
||||
$languageFactoryMock = $this->createMock( LanguageFactory::class );
|
||||
$languageFactoryMock->expects( $this->once() )
|
||||
->method( 'getLanguage' )
|
||||
->with( 'tmp' )
|
||||
->willThrowException( new \MWException() );
|
||||
|
||||
$popupHandler = $this->getPopup( $languageFactoryMock );
|
||||
$response = $this->executeHandler( $popupHandler, $this->getRequest( '1', 'tmp' ) );
|
||||
$this->assertEquals( 400, $response->getStatusCode() );
|
||||
$data = json_decode( $response->getBody(), true );
|
||||
$this->assertEquals( 'Invalid language code.', $data[ 'message' ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider provideItemSetups
|
||||
*/
|
||||
public function testExistingId( Item $item ) {
|
||||
$popupHandler = $this->getPopup( null, $item );
|
||||
|
||||
$request = $this->getRequest( '1', 'en' );
|
||||
$data = $this->executeHandlerAndGetBodyData( $popupHandler, $request );
|
||||
|
||||
$this->assertArrayHasKey( 'title', $data );
|
||||
$this->assertArrayHasKey( 'canonicalurl', $data );
|
||||
$this->assertArrayHasKey( 'fullurl', $data );
|
||||
$this->assertArrayHasKey( 'contentmodel', $data );
|
||||
$this->assertArrayHasKey( 'pagelanguagedir', $data );
|
||||
$this->assertArrayHasKey( 'pagelanguage', $data );
|
||||
$this->assertArrayHasKey( 'pagelanguagehtmlcode', $data );
|
||||
$this->assertArrayHasKey( 'extract', $data );
|
||||
|
||||
$this->assertEquals( 'mass–energy equivalence', $data[ 'title' ] );
|
||||
$this->assertEquals( 'special/Q1', $data[ 'canonicalurl' ] );
|
||||
$this->assertEquals( 'special/Q1', $data[ 'fullurl' ] );
|
||||
$this->assertEquals( 'html', $data[ 'contentmodel' ] );
|
||||
|
||||
$html = $data[ 'extract' ];
|
||||
|
||||
// popup contains formula label and description
|
||||
$this->assertStringContainsString( self::TEST_ITEMS[ 'Q1' ][0], $html );
|
||||
$this->assertStringContainsString( self::TEST_ITEMS[ 'Q1' ][1], $html );
|
||||
|
||||
// popup contains formula and labels of each element
|
||||
foreach ( self::TEST_ITEMS as $key => $part ) {
|
||||
if ( $key === 'Q1' ) {
|
||||
// the formula itself is not shown in the popup, only its elements
|
||||
continue;
|
||||
}
|
||||
$this->assertStringContainsString( $part[0], $html );
|
||||
$this->assertStringContainsString( self::getExpectedMathML( $part[2] ), $html );
|
||||
}
|
||||
}
|
||||
|
||||
private function getRequest( $id, $lang ): RequestData {
|
||||
return new RequestData( [
|
||||
'pathParams' => [ 'qid' => $id ],
|
||||
'headers' => [
|
||||
'Accept-Language' => $lang
|
||||
]
|
||||
] );
|
||||
}
|
||||
|
||||
private function getPopup(
|
||||
LanguageFactory $languageFactoryMock = null,
|
||||
Item $item = null
|
||||
): Popup {
|
||||
$languageFactoryMock = $languageFactoryMock ?: $this->createMock( LanguageFactory::class );
|
||||
$mathWikibaseConnectorMock = $item ?
|
||||
$this->getWikibaseConnectorWithExistingItems( new EntityRevision( $item ) ) :
|
||||
$this->getWikibaseConnector( $languageFactoryMock );
|
||||
|
||||
$titleMock = $this->createMock( Title::class );
|
||||
$titleMock->method( 'getLocalURL' )->willReturn( 'special/Q1' );
|
||||
$titleMock->method( 'getFullURL' )->willReturn( 'special/Q1' );
|
||||
$titleFactoryMock = $this->createMock( \TitleFactory::class );
|
||||
$titleFactoryMock->expects( $this->once() )
|
||||
->method( 'newFromText' )
|
||||
->willReturn( $titleMock );
|
||||
|
||||
return new Popup( $mathWikibaseConnectorMock, $languageFactoryMock, $titleFactoryMock );
|
||||
}
|
||||
|
||||
public function provideItemSetups(): array {
|
||||
return [
|
||||
[ $this->setupMassEnergyEquivalenceItem( true ) ],
|
||||
[ $this->setupMassEnergyEquivalenceItem( false ) ],
|
||||
];
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue