wiki.techinc.nl/tests/phpunit/unit/parser/Parsoid/LanguageVariantConverterUnitTest.php
Amir Sarabadani 09b18a8f4c Reorg: Move Title-related classes to title/
These three classes:
 - TitleArray
 - TitleArrayFromResult
 - TitleFactory

We need to move these and the rest of files under title/ to Title/ (and
namespace them) but the patch will become way too big given that Title class is
also one of them.

Bug: T321882
Change-Id: Iac1688172ee457348a08a470c86e047571feb8e0
2022-11-26 09:30:32 +00:00

423 lines
12 KiB
PHP

<?php
namespace MediaWiki\Parser\Parsoid;
use Language;
use MediaWiki\Languages\LanguageFactory;
use MediaWiki\Page\PageIdentity;
use MediaWiki\Page\PageIdentityValue;
use MediaWiki\Parser\Parsoid\Config\PageConfig;
use MediaWiki\Parser\Parsoid\Config\PageConfigFactory;
use MediaWiki\Parser\Parsoid\Config\SiteConfig;
use MediaWiki\Title\TitleFactory;
use MediaWikiUnitTestCase;
use PHPUnit\Framework\MockObject\MockObject;
use Title;
use Wikimedia\Parsoid\Core\PageBundle;
use Wikimedia\Parsoid\Parsoid;
/**
* @covers MediaWiki\Parser\Parsoid\LanguageVariantConverter
*/
class LanguageVariantConverterUnitTest extends MediaWikiUnitTestCase {
/** @dataProvider provideSetConfig */
public function testSetConfig( bool $shouldPageConfigFactoryBeUsed ) {
// Decide what should be called and what should not be
$shouldParsoidBeUsed = true;
$isLanguageConversionEnabled = true;
// Set expected language codes
$pageBundleLanguageCode = 'zh';
$titleLanguageCode = 'zh-hans';
$targetLanguageCode = 'zh-hans';
$sourceLanguageCode = null;
// Create mocks
$parsoidSettings = [];
$pageConfigMock = $this->getPageConfigMock();
$pageBundleMock = $this->getPageBundleMock( $pageBundleLanguageCode );
$languageVariantConverter = $this->getLanguageVariantConverter(
$shouldParsoidBeUsed,
$shouldPageConfigFactoryBeUsed,
$isLanguageConversionEnabled,
$pageBundleLanguageCode,
null,
$titleLanguageCode,
$targetLanguageCode,
$sourceLanguageCode,
$parsoidSettings
);
if ( !$shouldPageConfigFactoryBeUsed ) {
$languageVariantConverter->setPageConfig( $pageConfigMock );
}
$languageVariantConverter->convertPageBundleVariant( $pageBundleMock, $targetLanguageCode );
}
public function provideSetConfig() {
yield 'PageConfigFactory should not be used if PageConfig is set' => [ false ];
yield 'PageConfigFactory should be used if PageConfig is not set' => [ true ];
}
/** @dataProvider provideSourceLanguage */
public function testSourceLanguage(
?string $pageBundleLanguageCode,
?string $titleLanguageCode,
?string $contentLanguageOverride,
?string $sourceLanguageCode,
?string $expectedSourceCode
) {
// Decide what should be called and what should not be
$shouldParsoidBeUsed = true;
$shouldPageConfigFactoryBeUsed = true;
$isLanguageConversionEnabled = true;
// Set expected language codes
$titleLanguageCode = $titleLanguageCode ?? 'en';
$targetLanguageCode = 'en-us';
$parsoidSettings = [];
// Create mocks
if ( $pageBundleLanguageCode ) {
$pageBundleMock = $this->getPageBundleMock( $pageBundleLanguageCode );
} else {
$pageBundleMock = $this->getPageBundleMockWithoutLanguage();
}
$languageVariantConverter = $this->getLanguageVariantConverter(
$shouldParsoidBeUsed,
$shouldPageConfigFactoryBeUsed,
$isLanguageConversionEnabled,
$pageBundleLanguageCode,
$contentLanguageOverride,
$titleLanguageCode,
$targetLanguageCode,
$expectedSourceCode,
$parsoidSettings
);
$languageVariantConverter->convertPageBundleVariant( $pageBundleMock, $targetLanguageCode, $sourceLanguageCode );
}
public function provideSourceLanguage() {
yield 'content-language in PageBundle' => [
'sr-el', // PageBundle content-language
null, // Title PageLanguage
null, // PageLanguage override
'sr-ec', // explicit source
'sr-ec' // expected source
];
yield 'content-language but no source language' => [
'en', // PageBundle content-language
null, // Title PageLanguage
null, // PageLanguage override
null, // explicit source
null // expected source
];
yield 'content-language is variant' => [
'en-ca', // PageBundle content-language
null, // Title PageLanguage
null, // PageLanguage override
null, // explicit source
'en-ca' // expected source
];
yield 'Source variant is given' => [
null, // PageBundle content-language
null, // Title PageLanguage
null, // PageLanguage override
'en-ca', // explicit source
'en-ca' // expected source
];
yield 'Source variant is a base language' => [
null, // PageBundle content-language
null, // Title PageLanguage
null, // PageLanguage override
'en', // explicit source
null // expected source
];
yield 'Page language override is variant' => [
null, // PageBundle content-language
null, // PageBundle content-language
'en-ca', // PageLanguage override
'en-ca', // explicit source
'en-ca' // expected source
];
}
/** @dataProvider provideSiteConfiguration */
public function testSiteConfiguration(
bool $isLanguageConversionEnabled,
bool $shouldParsoidBeUsed,
bool $shouldPageConfigFactoryBeUsed
) {
// Set expected language codes
$pageBundleLanguageCode = 'zh';
$titleLanguageCode = 'zh-hans';
$targetLanguageCode = 'zh-hans';
$sourceLanguageCode = null;
// Create mocks
$parsoidSettings = [];
$pageBundleMock = $this->getPageBundleMock( $pageBundleLanguageCode );
$languageVariantConverter = $this->getLanguageVariantConverter(
$shouldParsoidBeUsed,
$shouldPageConfigFactoryBeUsed,
$isLanguageConversionEnabled,
$pageBundleLanguageCode,
null,
$titleLanguageCode,
$targetLanguageCode,
$sourceLanguageCode,
$parsoidSettings
);
$languageVariantConverter->convertPageBundleVariant( $pageBundleMock, $targetLanguageCode );
}
public function provideSiteConfiguration() {
$isLanguageConversionEnabled = false;
$shouldParsoidBeUsed = false;
$shouldPageConfigFactoryBeUsed = false;
yield 'If language conversion is disabled, parsoid and page config factory should not be used' =>
[ $isLanguageConversionEnabled, $shouldParsoidBeUsed, $shouldPageConfigFactoryBeUsed ];
$isLanguageConversionEnabled = true;
$shouldParsoidBeUsed = true;
$shouldPageConfigFactoryBeUsed = true;
yield 'If language conversion is enabled, parsoid and page config factory should be used' =>
[ $isLanguageConversionEnabled, $shouldParsoidBeUsed, $shouldPageConfigFactoryBeUsed ];
}
/**
* @param bool $shouldParsoidBeUsed
* @param bool $shouldPageConfigFactoryBeUsed
* @param bool $isLanguageConversionEnabled
* @param string|null $pageBundleLanguageCode
* @param string|null $contentLanguageOverride
* @param string $titleLanguageCode
* @param string $targetLanguageCode
* @param string|null $sourceLanguageCode
* @param array $parsoidSettings
*
* @return LanguageVariantConverter
*/
private function getLanguageVariantConverter(
bool $shouldParsoidBeUsed,
bool $shouldPageConfigFactoryBeUsed,
bool $isLanguageConversionEnabled,
?string $pageBundleLanguageCode,
?string $contentLanguageOverride,
string $titleLanguageCode,
string $targetLanguageCode,
?string $sourceLanguageCode,
array $parsoidSettings
): LanguageVariantConverter {
// If Content language is set, use language from there,
// If PageBundle language code is set, use that
// Else, fallback to title page language
$pageLanguageCode = $contentLanguageOverride ?? $pageBundleLanguageCode ?? $titleLanguageCode;
// The page language code should not be a variant
$pageLanguageCode = preg_replace( '/-.*$/', '', $pageLanguageCode );
$shouldSiteConfigBeUsed = true;
$parsoidSettings = [];
$pageIdentityValue = new PageIdentityValue( 1, NS_MAIN, 'hello_world', PageIdentity::LOCAL );
// Create the necessary mocks
$pageConfigMock = $this->getPageConfigMock();
$pageConfigFactoryMock = $this->getPageConfigFactoryMock(
$shouldPageConfigFactoryBeUsed,
// Expected arguments to PageConfigFactory mock
[ $pageIdentityValue, null, null, null, $pageLanguageCode, $parsoidSettings ],
$pageConfigMock
);
$pageBundleMock = $this->getPageBundleMock( $pageBundleLanguageCode );
$siteConfigMock = $this->getSiteConfigMock(
$shouldSiteConfigBeUsed, $pageLanguageCode, $isLanguageConversionEnabled
);
$titleFactoryMock = $this->getTitleFactoryMock( $pageIdentityValue, $titleLanguageCode );
$languageFactoryMock = $this->getLanguageFactoryMock();
$parsoidMock = $this->getParsoidMock(
$shouldParsoidBeUsed,
[
$pageConfigMock,
'variant',
$pageBundleMock,
[ 'variant' => [ 'source' => $sourceLanguageCode, 'target' => $targetLanguageCode ] ]
]
);
$languageVariantConverter = new LanguageVariantConverter(
$pageIdentityValue,
$pageConfigFactoryMock,
$parsoidMock,
$parsoidSettings,
$siteConfigMock,
$titleFactoryMock,
$languageFactoryMock
);
if ( $contentLanguageOverride ) {
$languageVariantConverter->setPageLanguageOverride( $contentLanguageOverride );
}
return $languageVariantConverter;
}
// Mock methods follow
/**
* @param bool $shouldBeCalled
* @param array $arguments
* @param PageConfig $pageConfig
*
* @return MockObject|PageConfigFactory
*/
private function getPageConfigFactoryMock( bool $shouldBeCalled, array $arguments, PageConfig $pageConfig ) {
$mock = $this->createMock( PageConfigFactory::class );
if ( $shouldBeCalled ) {
$mock->expects( $this->once() )
->method( 'create' )
->with( ...$arguments )
->willReturn( $pageConfig );
} else {
$mock->expects( $this->never() )
->method( 'create' );
}
return $mock;
}
/**
* @param bool $shouldBeCalled
* @param array $arguments
*
* @return MockObject|Parsoid
*/
private function getParsoidMock( bool $shouldBeCalled, array $arguments ) {
$mock = $this->createMock( Parsoid::class );
if ( $shouldBeCalled ) {
$mock->expects( $this->once() )
->method( 'pb2pb' )
->with( ...$arguments );
} else {
$mock->expects( $this->never() )
->method( 'pb2pb' );
}
return $mock;
}
/**
* @param bool $shouldBeCalled
* @param string $baseLanguageCode
* @param bool $isLanguageConversionEnabled
*
* @return MockObject|SiteConfig
*/
private function getSiteConfigMock(
bool $shouldBeCalled,
string $baseLanguageCode,
bool $isLanguageConversionEnabled
) {
$mock = $this->createMock( SiteConfig::class );
if ( $shouldBeCalled ) {
$mock->expects( $this->once() )
->method( 'langConverterEnabledForLanguage' )
->with( $baseLanguageCode )
->willReturn( $isLanguageConversionEnabled );
} else {
$mock->expects( $this->never() )
->method( 'langConverterEnabledForLanguage' );
}
return $mock;
}
/**
* @param PageIdentity $pageIdentity
* @param string $languageCode
*
* @return MockObject|TitleFactory
*/
private function getTitleFactoryMock( PageIdentity $pageIdentity, string $languageCode ) {
$languageMock = $this->getLanguageMock( $languageCode );
$titleMock = $this->createMock( Title::class );
$titleMock->method( 'getPageLanguage' )
->willReturn( $languageMock );
$mock = $this->createMock( TitleFactory::class );
$mock->expects( $this->once() )
->method( 'castFromPageIdentity' )
->willReturn( $titleMock )
->with( $pageIdentity );
return $mock;
}
/**
* @return MockObject|LanguageFactory
*/
private function getLanguageFactoryMock() {
$mock = $this->createMock( LanguageFactory::class );
$mock->method( 'getLanguage' )
->willReturnCallback( function ( $code ) {
return $this->getLanguageMock( $code );
} );
$mock->method( 'getParentLanguage' )
->willReturnCallback( function ( $code ) {
$code = preg_replace( '/-.*$/', '', $code );
return $this->getLanguageMock( $code );
} );
return $mock;
}
/**
* @return MockObject|PageBundle
*/
private function getPageBundleMockWithoutLanguage() {
return $this->getPageBundleMock( null );
}
/**
* @param string|null $languageCode
*
* @return MockObject|PageBundle
*/
private function getPageBundleMock( ?string $languageCode ) {
$mock = $this->createMock( PageBundle::class );
$mock->headers = [
'content-language' => $languageCode
];
return $mock;
}
/**
* @return MockObject|PageConfig
*/
private function getPageConfigMock() {
$mock = $this->createNoOpMock( PageConfig::class, [ 'setVariant' ] );
return $mock;
}
/**
* @param string $languageCode
*
* @return MockObject|Language
*/
private function getLanguageMock( $languageCode ): Language {
$languageMock = $this->createMock( Language::class );
$languageMock->method( 'getCode' )
->willReturn( $languageCode );
return $languageMock;
}
}