212 lines
7.7 KiB
PHP
212 lines
7.7 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
|
|
namespace Esun3d\LanguageUrlStoreResolver\Test\Unit\Model;
|
|
|
|
use Magento\Store\Model\Store;
|
|
use Magento\Store\Model\StoreManagerInterface;
|
|
use Magento\Store\Model\Website;
|
|
use PHPUnit\Framework\TestCase;
|
|
use Esun3d\LanguageUrlStoreResolver\Model\LanguageResolver;
|
|
use Esun3d\LanguageUrlStoreResolver\Model\RequestPathProcessor;
|
|
use Esun3d\LanguageUrlStoreResolver\Model\StoreCodeMapper;
|
|
use Esun3d\LanguageUrlStoreResolver\Model\StoreViewRegistry;
|
|
|
|
class LanguageAndPathTest extends TestCase
|
|
{
|
|
/**
|
|
* @var StoreViewRegistry|\PHPUnit\Framework\MockObject\MockObject
|
|
*/
|
|
private $storeViewRegistry;
|
|
|
|
/** @var StoreManagerInterface|\PHPUnit\Framework\MockObject\MockObject */
|
|
private $storeManager;
|
|
|
|
protected function setUp(): void
|
|
{
|
|
$this->storeViewRegistry = $this->createMock(StoreViewRegistry::class);
|
|
$this->storeViewRegistry->method('isKnownLanguage')->willReturnCallback(static function (string $language): bool {
|
|
return in_array($language, ['en', 'de'], true);
|
|
});
|
|
$this->storeViewRegistry->method('isKnownStoreCode')->willReturnCallback(static function (string $storeCode): bool {
|
|
return in_array($storeCode, ['en_US', 'en_DE', 'de_US', 'de_DE'], true);
|
|
});
|
|
$this->storeViewRegistry->method('getLanguageByStoreCode')->willReturnCallback(static function (string $storeCode): ?string {
|
|
$map = [
|
|
'en_US' => 'en',
|
|
'en_DE' => 'en',
|
|
'de_US' => 'de',
|
|
'de_DE' => 'de',
|
|
];
|
|
|
|
return $map[$storeCode] ?? null;
|
|
});
|
|
$this->storeViewRegistry->method('getDefaultStoreCodeForLanguage')->willReturnCallback(
|
|
static function (string $language): ?string {
|
|
$map = [
|
|
'en' => 'en_US',
|
|
'de' => 'de_US',
|
|
];
|
|
|
|
return $map[$language] ?? null;
|
|
}
|
|
);
|
|
$this->storeViewRegistry->method('isLanguageInWebsite')->willReturnCallback(
|
|
static fn(string $language, int $websiteId): bool =>
|
|
$websiteId === 1 && in_array($language, ['en', 'de'], true)
|
|
);
|
|
$this->storeViewRegistry->method('isStoreCodeInWebsite')->willReturnCallback(
|
|
static fn(string $storeCode, int $websiteId): bool =>
|
|
$websiteId === 1 && in_array($storeCode, ['en_US', 'en_DE', 'de_US', 'de_DE'], true)
|
|
);
|
|
$this->storeViewRegistry->method('getStoreCodeForLanguageInWebsite')->willReturnCallback(
|
|
static function (string $language, int $websiteId): ?string {
|
|
if ($websiteId !== 1) {
|
|
return null;
|
|
}
|
|
|
|
return ['en' => 'en_US', 'de' => 'de_US'][$language] ?? null;
|
|
}
|
|
);
|
|
|
|
$defaultStore = $this->createMock(Store::class);
|
|
$defaultStore->method('getCode')->willReturn('en_US');
|
|
$website = $this->createMock(Website::class);
|
|
$website->method('getId')->willReturn(1);
|
|
$website->method('getDefaultStore')->willReturn($defaultStore);
|
|
$this->storeManager = $this->createMock(StoreManagerInterface::class);
|
|
$this->storeManager->method('getWebsite')->willReturn($website);
|
|
}
|
|
|
|
/**
|
|
* @dataProvider productPathProvider
|
|
*/
|
|
public function testResolvesLanguageFromProductPath(string $pathInfo, ?string $expectedLanguage): void
|
|
{
|
|
$resolver = new LanguageResolver($this->storeViewRegistry, $this->storeManager);
|
|
|
|
self::assertSame($expectedLanguage, $resolver->resolveFromPath($pathInfo));
|
|
}
|
|
|
|
/**
|
|
* @return mixed[]
|
|
*/
|
|
public static function productPathProvider(): array
|
|
{
|
|
return [
|
|
'english product path' => ['/en/product-a', 'en'],
|
|
'german product path' => ['/de/product-a', 'de'],
|
|
'english language root' => ['/en', 'en'],
|
|
'real store code is not language' => ['/en_US/product-a', null],
|
|
'unsupported prefix' => ['/fr/product-a', null],
|
|
];
|
|
}
|
|
|
|
/**
|
|
* @dataProvider stripProductPathProvider
|
|
*/
|
|
public function testStripsLanguagePrefixBeforeUrlRewrite(string $pathInfo, string $expectedPathInfo): void
|
|
{
|
|
$processor = new RequestPathProcessor(new LanguageResolver($this->storeViewRegistry, $this->storeManager));
|
|
|
|
self::assertSame($expectedPathInfo, $processor->stripLanguagePrefix($pathInfo));
|
|
}
|
|
|
|
/**
|
|
* @return mixed[]
|
|
*/
|
|
public static function stripProductPathProvider(): array
|
|
{
|
|
return [
|
|
'english product path' => ['/en/product-a', '/product-a'],
|
|
'german product path' => ['/de/product-a', '/product-a'],
|
|
'nested product path' => ['/de/category/product-a', '/category/product-a'],
|
|
'language root' => ['/en', '/'],
|
|
'non language path unchanged' => ['/product-a', '/product-a'],
|
|
];
|
|
}
|
|
|
|
/**
|
|
* @dataProvider replaceProductPathProvider
|
|
*/
|
|
public function testReplacesLanguagePrefixForMarketSwitch(string $pathInfo, string $language, string $expectedPathInfo): void
|
|
{
|
|
$processor = new RequestPathProcessor(new LanguageResolver($this->storeViewRegistry, $this->storeManager));
|
|
|
|
self::assertSame($expectedPathInfo, $processor->replaceLanguagePrefix($pathInfo, $language));
|
|
}
|
|
|
|
/**
|
|
* @return mixed[]
|
|
*/
|
|
public static function replaceProductPathProvider(): array
|
|
{
|
|
return [
|
|
'german product path switches to english' => [
|
|
'/de/privacy-policy-cookie-restriction-mode/',
|
|
'en',
|
|
'/en/privacy-policy-cookie-restriction-mode/',
|
|
],
|
|
'english product path switches to german' => [
|
|
'/en/product-a',
|
|
'de',
|
|
'/de/product-a',
|
|
],
|
|
'language root keeps trailing slash' => [
|
|
'/de/',
|
|
'en',
|
|
'/en/',
|
|
],
|
|
];
|
|
}
|
|
|
|
/**
|
|
* @dataProvider storeMappingProvider
|
|
*/
|
|
public function testMapsProductPathLanguageAndMarketToRealStoreCode(
|
|
string $language,
|
|
?string $market,
|
|
?string $expectedStoreCode
|
|
): void {
|
|
$mapper = new StoreCodeMapper($this->storeViewRegistry, $this->storeManager);
|
|
|
|
self::assertSame($expectedStoreCode, $mapper->map($language, $market));
|
|
}
|
|
|
|
/**
|
|
* @return mixed[]
|
|
*/
|
|
public static function storeMappingProvider(): array
|
|
{
|
|
return [
|
|
'english US product path' => ['en', 'en_US', 'en_US'],
|
|
'english DE product path' => ['en', 'en_DE', 'en_DE'],
|
|
'german US product path' => ['de', 'de_US', 'de_US'],
|
|
'german DE product path' => ['de', 'de_DE', 'de_DE'],
|
|
'english path ignores german market and uses default' => ['en', 'de_DE', 'en_US'],
|
|
'unknown language has no default' => ['fr', null, null],
|
|
];
|
|
}
|
|
|
|
public function testUsesLanguageSpecificDefaultStoreFromRegistry(): void
|
|
{
|
|
$mapper = new StoreCodeMapper($this->storeViewRegistry, $this->storeManager);
|
|
|
|
self::assertSame('en_US', $mapper->getDefaultStoreCodeForLanguage('en'));
|
|
self::assertSame('de_US', $mapper->getDefaultStoreCodeForLanguage('de'));
|
|
}
|
|
|
|
public function testUsesCurrentWebsiteWhenLanguageExistsInMultipleWebsites(): void
|
|
{
|
|
$registry = $this->createMock(StoreViewRegistry::class);
|
|
$registry->expects(self::once())
|
|
->method('getStoreCodeForLanguageInWebsite')
|
|
->with('de', 1)
|
|
->willReturn('de_EU');
|
|
|
|
$mapper = new StoreCodeMapper($registry, $this->storeManager);
|
|
|
|
self::assertSame('de_EU', $mapper->getDefaultStoreCodeForLanguage('de'));
|
|
}
|
|
}
|