Skip to content
Snippets Groups Projects
Commit d2eb0235 authored by catch's avatar catch
Browse files

Issue #3130107 by stefanos.petrakis, rpayanm, smustgrave, jungle: Extend unit...

Issue #3130107 by stefanos.petrakis, rpayanm, smustgrave, jungle: Extend unit test coverage for LanguageNegotiationContentEntity
parent d8408c2c
Branches
Tags
54 merge requests!54479.5.x SF update,!5014Issue #3071143: Table Render Array Example Is Incorrect,!4868Issue #1428520: Improve menu parent link selection,!4686Issue #3292350: file_validate_image_resolution does not update file size after resizing,!4594Applying patch for Views Global Text area field to allow extra HTML tags. As video, source and iframe tag is not rendering. Due to which Media embedded video and remote-video not rendering in Views Global Text area field.,!4289Issue #1344552 by marcingy, Niklas Fiekas, Ravi.J, aleevas, Eduardo Morales...,!4114Issue #2707291: Disable body-level scrolling when a dialog is open as a modal,!4034Issue #3308432: The link on the Image tag is redirecting to an undefined page from the node preview screen.,!4022Update String overrides example in default.settings.php,!3948Issue #3358600: [meta] Fix PHPStan L1 errors "Variable $foo might not be defined.",!3878Removed unused condition head title for views,!38582585169-10.1.x,!3825Issue #2972573: randomMachineName() should conform to processMachineName() pattern,!3818Issue #2140179: $entity->original gets stale between updates,!3770Issue #3318112: Move "Block layout" from Structure to Appearance,!3742Issue #3328429: Create item list field formatter for displaying ordered and unordered lists,!3731Claro: role=button on status report items,!3699Resolve #2953566 "Allow entities to",!3668Resolve #3347842 "Deprecate the trusted",!3651Issue #3347736: Create new SDC component for Olivero (header-search),!3546refactored dialog.pcss file,!3531Issue #3336994: StringFormatter always displays links to entity even if the user in context does not have access,!3502Issue #3335308: Confusing behavior with FormState::setFormState and FormState::setMethod,!3452Issue #3332701: Refactor Claro's tablesort-indicator stylesheet,!3451Issue #2410579: Allows setting the current language programmatically.,!3355Issue #3209129: Scrolling problems when adding a block via layout builder,!3228Issue #2920678: Add config validation for the allowed characters of machine names,!3226Issue #2987537: Custom menu link entity type should not declare "bundle" entity key,!3154Fixes #2987987 - CSRF token validation broken on routes with optional parameters.,!3147Issue #3328457: Replace most substr($a, $i) where $i is negative with str_ends_with(),!3146Issue #3328456: Replace substr($a, 0, $i) with str_starts_with(),!3133core/modules/system/css/components/hidden.module.css,!31312878513-10.1.x,!3009Issue #3323252: Add @method PhpDoc for EntityStorageInterface descendants,!2964Issue #2865710 : Dependencies from only one instance of a widget are used in display modes,!2812Issue #3312049: [Followup] Fix Drupal.Commenting.FunctionComment.MissingReturnType returns for NULL,!2614Issue #2981326: Replace non-test usages of \Drupal::logger() with IoC injection,!2378Issue #2875033: Optimize joins and table selection in SQL entity query implementation,!2334Issue #3228209: Add hasRole() method to AccountInterface,!2062Issue #3246454: Add weekly granularity to views date sort,!1591Issue #3199697: Add JSON:API Translation experimental module,!1255Issue #3238922: Refactor (if feasible) uses of the jQuery serialize function to use vanillaJS,!1105Issue #3025039: New non translatable field on translatable content throws error,!1073issue #3191727: Focus states on mobile second level navigation items fixed,!10223132456: Fix issue where views instances are emptied before an ajax request is complete,!877Issue #2708101: Default value for link text is not saved,!844Resolve #3036010 "Updaters",!673Issue #3214208: FinishResponseSubscriber could create duplicate headers,!617Issue #3043725: Provide a Entity Handler for user cancelation,!579Issue #2230909: Simple decimals fail to pass validation,!560Move callback classRemove outside of the loop,!555Issue #3202493,!485Sets the autocomplete attribute for username/password input field on login form.,!30Issue #3182188: Updates composer usage to point at ./vendor/bin/composer
......@@ -2,15 +2,18 @@
namespace Drupal\Tests\language\Unit\Plugin\LanguageNegotiation;
use Symfony\Component\HttpFoundation\Request;
use Drupal\Core\Cache\Context\CacheContextsManager;
use Drupal\Core\DependencyInjection\ContainerBuilder;
use Drupal\Core\Entity\EntityTypeManager;
use Drupal\Core\Language\LanguageInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Render\BubbleableMetadata;
use Drupal\Core\Url;
use Drupal\language\ConfigurableLanguageManagerInterface;
use Drupal\Tests\UnitTestCase;
use Drupal\language\Plugin\LanguageNegotiation\LanguageNegotiationContentEntity;
use Symfony\Component\HttpFoundation\ParameterBag;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\ServerBag;
use Symfony\Component\Routing\Route;
/**
* Tests the LanguageNegotiationContentEntity plugin class.
......@@ -19,7 +22,7 @@
* @coversDefaultClass \Drupal\language\Plugin\LanguageNegotiation\LanguageNegotiationContentEntity
* @see \Drupal\language\Plugin\LanguageNegotiation\LanguageNegotiationContentEntity
*/
class LanguageNegotiationContentEntityTest extends UnitTestCase {
class LanguageNegotiationContentEntityTest extends LanguageNegotiationTestBase {
/**
* An array of mock LanguageInterface objects.
......@@ -36,11 +39,11 @@ class LanguageNegotiationContentEntityTest extends UnitTestCase {
protected $languageManager;
/**
* A mock object implementing the AccountInterface.
*
* @var \Drupal\Core\Session\AccountInterface
* {@inheritdoc}
*/
protected $user;
protected function getPluginClass(): string {
return LanguageNegotiationContentEntity::class;
}
/**
* {@inheritdoc}
......@@ -53,32 +56,39 @@ protected function setUp(): void {
$language_de->expects($this->any())
->method('getId')
->will($this->returnValue('de'));
$language_de->expects($this->any())
->method('getName')
->will($this->returnValue('German'));
$language_en = $this->createMock(LanguageInterface::class);
$language_en->expects($this->any())
->method('getId')
->will($this->returnValue('en'));
$languages = [
$language_en->expects($this->any())
->method('getName')
->will($this->returnValue('English'));
$this->languages = [
'de' => $language_de,
'en' => $language_en,
];
$this->languages = $languages;
$language_manager = $this->getMockBuilder(ConfigurableLanguageManagerInterface::class)
->getMock();
$language_manager = $this->createMock(ConfigurableLanguageManagerInterface::class);
$language_manager->expects($this->any())
->method('getLanguages')
->will($this->returnValue($languages));
->will($this->returnValue($this->languages));
$language_manager->expects($this->any())
->method('getNativeLanguages')
->will($this->returnValue($this->languages));
$this->languageManager = $language_manager;
$this->user = $this->getMockBuilder(AccountInterface::class)
->getMock();
$container = new ContainerBuilder();
$cache_contexts_manager = $this->getMockBuilder(CacheContextsManager::class)
->disableOriginalConstructor()
->getMock();
$cache_contexts_manager = $this->createMock(CacheContextsManager::class);
$cache_contexts_manager->method('assertValidTokens')->willReturn(TRUE);
$container = new ContainerBuilder();
$container->set('cache_contexts_manager', $cache_contexts_manager);
$entityTypeManager = $this->createMock(EntityTypeManager::class);
$container->set('entity_type.manager', $entityTypeManager);
\Drupal::setContainer($container);
}
......@@ -86,32 +96,148 @@ protected function setUp(): void {
* @covers ::getLangcode
*/
public function testGetLangcode() {
$entityTypeManagerMock = $this->getMockBuilder(EntityTypeManager::class)
->disableOriginalConstructor()
->getMock();
$languageNegotiationContentEntity = new LanguageNegotiationContentEntity($entityTypeManagerMock);
$languageNegotiationContentEntity->setLanguageManager($this->languageManager);
$languageNegotiationContentEntity = $this->createLanguageNegotiationPlugin();
// Case 1: NULL request object argument.
$this->assertNull($languageNegotiationContentEntity->getLangcode());
// Case 1: Empty request.
$this->assertEquals(NULL, $languageNegotiationContentEntity->getLangcode());
// Case 2: A request object is available, but the languageManager is not
// set.
$request = Request::create('/foo', 'GET');
$this->assertNull($languageNegotiationContentEntity->getLangcode($request));
// Case 2: A request is available, but the languageManager is not set and
// the static::QUERY_PARAMETER is not provided as a named parameter.
$request = Request::create('/de/foo', 'GET');
$request->query = new ParameterBag();
$this->assertEquals(NULL, $languageNegotiationContentEntity->getLangcode($request));
// Case 3: A request object is available, but static::QUERY_PARAMETER is
// set to a non-enabled language.
$request = Request::create('/foo', 'GET',
[LanguageNegotiationContentEntity::QUERY_PARAMETER => 'it']);
// Case 3: A request is available, the languageManager is set, but the
// static::QUERY_PARAMETER is not provided as a named parameter.
$languageNegotiationContentEntity->setLanguageManager($this->languageManager);
$this->assertEquals(NULL, $languageNegotiationContentEntity->getLangcode($request));
// Case 4: A request is available, the languageManager is set and the
// static::QUERY_PARAMETER is provided as a named parameter.
$expectedLangcode = 'de';
$request->query->set(LanguageNegotiationContentEntity::QUERY_PARAMETER, $expectedLangcode);
$this->assertEquals($expectedLangcode, $languageNegotiationContentEntity->getLangcode($request));
// Case 5: A request is available, the languageManager is set and the
// static::QUERY_PARAMETER is provided as a named parameter with a given
// langcode that is not one of the system supported ones.
$unknownLangcode = 'xx';
$request->query->set(LanguageNegotiationContentEntity::QUERY_PARAMETER, $unknownLangcode);
$this->assertNull($languageNegotiationContentEntity->getLangcode($request));
}
// Case 4: A request object is available and static::QUERY_PARAMETER is
// set to an enabled language.
$request = Request::create('/foo', 'GET',
[LanguageNegotiationContentEntity::QUERY_PARAMETER => 'de']);
$this->assertSame('de', $languageNegotiationContentEntity->getLangcode($request));
/**
* @covers ::processOutbound
*/
public function testProcessOutbound() {
// Case 1: Not all processing conditions are met.
$languageNegotiationContentEntityMock = $this->createPartialMock($this->getPluginClass(),
['hasLowerLanguageNegotiationWeight', 'meetsContentEntityRoutesCondition']);
$languageNegotiationContentEntityMock->expects($this->exactly(2))
->method('hasLowerLanguageNegotiationWeight')
->willReturnOnConsecutiveCalls(
FALSE,
TRUE
);
$languageNegotiationContentEntityMock->expects($this->once())
->method('meetsContentEntityRoutesCondition')
->willReturnOnConsecutiveCalls(
FALSE
);
$options = [];
$path = $this->randomMachineName();
// Case 1a: Empty request.
$this->assertEquals($path, $languageNegotiationContentEntityMock->processOutbound($path));
$request = Request::create('/foo', 'GET');
$request->server = new ServerBag();
// Case 1b: Missing the route key in $options.
$this->assertEquals($path, $languageNegotiationContentEntityMock->processOutbound($path, $options, $request));
$options = ['route' => $this->createMock(Route::class)];
// Case 1c: hasLowerLanguageNegotiationWeight() returns FALSE.
$this->assertEquals($path, $languageNegotiationContentEntityMock->processOutbound($path, $options, $request));
// Case 1d: meetsContentEntityRoutesCondition() returns FALSE.
$this->assertEquals($path, $languageNegotiationContentEntityMock->processOutbound($path, $options, $request));
// Case 2: Cannot figure out the langcode.
$languageNegotiationContentEntityMock = $this->createPartialMock($this->getPluginClass(),
['hasLowerLanguageNegotiationWeight', 'meetsContentEntityRoutesCondition', 'getLangcode']);
$languageNegotiationContentEntityMock->expects($this->any())
->method('hasLowerLanguageNegotiationWeight')
->will($this->returnValue(TRUE));
$languageNegotiationContentEntityMock->expects($this->any())
->method('meetsContentEntityRoutesCondition')
->will($this->returnValue(TRUE));
$languageNegotiationContentEntityMock->expects($this->exactly(2))
->method('getLangcode')
->willReturnOnConsecutiveCalls(
NULL,
'de'
);
$this->assertEquals($path, $languageNegotiationContentEntityMock->processOutbound($path, $options, $request));
// Case 3: Can figure out the langcode.
// Case 3a: via $options['language'].
$options['language'] = $this->languages['en'];
$options['query'] = NULL;
$bubbleableMetadataMock = $this->createMock(BubbleableMetadata::class);
$bubbleableMetadataMock->expects($this->exactly(3))
->method('addCacheContexts')
->with(['url.query_args:' . LanguageNegotiationContentEntity::QUERY_PARAMETER]);
$this->assertEquals($path, $languageNegotiationContentEntityMock->processOutbound($path, $options, $request, $bubbleableMetadataMock));
$this->assertFalse(isset($options['language']));
$this->assertTrue(isset($options['query'][LanguageNegotiationContentEntity::QUERY_PARAMETER]));
$this->assertEquals('en', $options['query'][LanguageNegotiationContentEntity::QUERY_PARAMETER]);
// Case 3a1: via $options['language'] with an additional $options['query'][static::QUERY_PARAMETER].
$options['language'] = $this->languages['en'];
$options['query'][LanguageNegotiationContentEntity::QUERY_PARAMETER] = 'xx';
$this->assertEquals($path, $languageNegotiationContentEntityMock->processOutbound($path, $options, $request, $bubbleableMetadataMock));
$this->assertFalse(isset($options['language']));
$this->assertEquals('xx', $options['query'][LanguageNegotiationContentEntity::QUERY_PARAMETER]);
// Case 3b: via getLangcode().
unset($options['query'][LanguageNegotiationContentEntity::QUERY_PARAMETER]);
$this->assertEquals($path, $languageNegotiationContentEntityMock->processOutbound($path, $options, $request, $bubbleableMetadataMock));
$this->assertEquals('de', $options['query'][LanguageNegotiationContentEntity::QUERY_PARAMETER]);
}
/**
* @covers ::getLanguageSwitchLinks
*/
public function testGetLanguageSwitchLinks() {
$languageNegotiationContentEntity = $this->createLanguageNegotiationPlugin();
$languageNegotiationContentEntity->setLanguageManager($this->languageManager);
$request = Request::create('/foo', 'GET', ['param1' => 'xyz']);
$url = Url::fromUri('base:' . $this->randomMachineName());
$expectedLanguageSwitchLinksArray = [
'de' => [
'url' => $url,
'title' => $this->languages['de']->getName(),
'attributes' => ['class' => ['language-link']],
'query' => [
LanguageNegotiationContentEntity::QUERY_PARAMETER => 'de',
'param1' => 'xyz',
],
],
'en' => [
'url' => $url,
'title' => $this->languages['en']->getName(),
'attributes' => ['class' => ['language-link']],
'query' => [
LanguageNegotiationContentEntity::QUERY_PARAMETER => 'en',
'param1' => 'xyz',
],
],
];
$providedLanguageSwitchLinksArray = $languageNegotiationContentEntity->getLanguageSwitchLinks($request, $this->randomMachineName(), $url);
$this->assertEquals(
$expectedLanguageSwitchLinksArray,
$providedLanguageSwitchLinksArray
);
}
}
<?php
namespace Drupal\Tests\language\Unit\Plugin\LanguageNegotiation;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Tests\UnitTestCase;
/**
* Base class used for testing the various LanguageNegotiation plugins.
*
* @group language
*/
abstract class LanguageNegotiationTestBase extends UnitTestCase {
/**
* Returns the plugin class to use for creating the language negotiation plugin.
*
* @return string
* The plugin class name.
*/
abstract protected function getPluginClass(): string;
/**
* Creates a @LanguageNegotiation plugin using the factory ::create method.
*
* @return \Drupal\language\LanguageNegotiationMethodInterface
*/
protected function createLanguageNegotiationPlugin(array $configuration = [], $plugin_definition = NULL) {
$class = $this->getPluginClass();
$this->assertTrue(in_array(ContainerFactoryPluginInterface::class, class_implements($class)));
return $class::create(\Drupal::getContainer(), $configuration, $class::METHOD_ID, $plugin_definition);
}
}
  • catch @catch

    mentioned in commit afa61a59

    ·

    mentioned in commit afa61a59

    Toggle commit list
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment