diff options
Diffstat (limited to 'core/tests')
24 files changed, 330 insertions, 41 deletions
diff --git a/core/tests/Drupal/FunctionalTests/Bootstrap/UncaughtExceptionTest.php b/core/tests/Drupal/FunctionalTests/Bootstrap/UncaughtExceptionTest.php index 80fd287751c5..aac21dcff875 100644 --- a/core/tests/Drupal/FunctionalTests/Bootstrap/UncaughtExceptionTest.php +++ b/core/tests/Drupal/FunctionalTests/Bootstrap/UncaughtExceptionTest.php @@ -203,6 +203,7 @@ class UncaughtExceptionTest extends BrowserTestBase { switch ($this->container->get('database')->driver()) { case 'pgsql': case 'mysql': + case 'mysqli': $this->expectedExceptionMessage = $incorrect_username; break; diff --git a/core/tests/Drupal/FunctionalTests/Core/Recipe/StandardRecipeTest.php b/core/tests/Drupal/FunctionalTests/Core/Recipe/StandardRecipeTest.php index 4bf46e8d4911..68a793f8771f 100644 --- a/core/tests/Drupal/FunctionalTests/Core/Recipe/StandardRecipeTest.php +++ b/core/tests/Drupal/FunctionalTests/Core/Recipe/StandardRecipeTest.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace Drupal\FunctionalTests\Core\Recipe; +use Drupal\Core\Extension\ModuleExtensionList; use Drupal\shortcut\Entity\Shortcut; use Drupal\Tests\standard\Functional\StandardTest; use Drupal\user\RoleInterface; @@ -35,7 +36,12 @@ class StandardRecipeTest extends StandardTest { $theme_installer->uninstall(['claro', 'olivero']); // Determine which modules to uninstall. - $uninstall = array_diff(array_keys(\Drupal::moduleHandler()->getModuleList()), ['user', 'system', 'path_alias', \Drupal::database()->getProvider()]); + // If the database module has dependencies, they are expected too. + $database_module_extension = \Drupal::service(ModuleExtensionList::class)->get(\Drupal::database()->getProvider()); + $database_modules = $database_module_extension->requires ? array_keys($database_module_extension->requires) : []; + $database_modules[] = \Drupal::database()->getProvider(); + $keep = array_merge(['user', 'system', 'path_alias'], $database_modules); + $uninstall = array_diff(array_keys(\Drupal::moduleHandler()->getModuleList()), $keep); foreach (['shortcut', 'field_config', 'filter_format', 'field_storage_config'] as $entity_type) { $storage = \Drupal::entityTypeManager()->getStorage($entity_type); $storage->delete($storage->loadMultiple()); diff --git a/core/tests/Drupal/FunctionalTests/ExistingDrupal8StyleDatabaseConnectionInSettingsPhpTest.php b/core/tests/Drupal/FunctionalTests/ExistingDrupal8StyleDatabaseConnectionInSettingsPhpTest.php index 01c694b4ef4b..fd7bfeecd38c 100644 --- a/core/tests/Drupal/FunctionalTests/ExistingDrupal8StyleDatabaseConnectionInSettingsPhpTest.php +++ b/core/tests/Drupal/FunctionalTests/ExistingDrupal8StyleDatabaseConnectionInSettingsPhpTest.php @@ -26,7 +26,7 @@ class ExistingDrupal8StyleDatabaseConnectionInSettingsPhpTest extends BrowserTes $driver = Database::getConnection()->driver(); if (!in_array($driver, ['mysql', 'pgsql', 'sqlite'])) { - $this->markTestSkipped("This test does not support the {$driver} database driver."); + $this->markTestSkipped("This test is only relevant for database drivers that were available in Drupal prior to database drivers becoming part of modules. The {$driver} database driver is not qualifying."); } $filename = $this->siteDirectory . '/settings.php'; diff --git a/core/tests/Drupal/FunctionalTests/Installer/InstallerExistingConfigTestBase.php b/core/tests/Drupal/FunctionalTests/Installer/InstallerExistingConfigTestBase.php index 2ac3ae778a4b..f7c949637547 100644 --- a/core/tests/Drupal/FunctionalTests/Installer/InstallerExistingConfigTestBase.php +++ b/core/tests/Drupal/FunctionalTests/Installer/InstallerExistingConfigTestBase.php @@ -7,6 +7,7 @@ namespace Drupal\FunctionalTests\Installer; use Drupal\Component\Serialization\Yaml; use Drupal\Core\Archiver\ArchiveTar; use Drupal\Core\Database\Database; +use Drupal\Core\Extension\ModuleExtensionList; use Drupal\Core\Installer\Form\SelectProfileForm; /** @@ -99,8 +100,11 @@ abstract class InstallerExistingConfigTestBase extends InstallerTestBase { // modules that can not be uninstalled in the core.extension configuration. if (file_exists($config_sync_directory . '/core.extension.yml')) { $core_extension = Yaml::decode(file_get_contents($config_sync_directory . '/core.extension.yml')); - $module = Database::getConnection()->getProvider(); - if ($module !== 'core') { + // If the database module has dependencies, they are expected too. + $database_module_extension = \Drupal::service(ModuleExtensionList::class)->get(Database::getConnection()->getProvider()); + $database_modules = $database_module_extension->requires ? array_keys($database_module_extension->requires) : []; + $database_modules[] = Database::getConnection()->getProvider(); + foreach ($database_modules as $module) { $core_extension['module'][$module] = 0; $core_extension['module'] = module_config_sort($core_extension['module']); } diff --git a/core/tests/Drupal/FunctionalTests/Update/UpdatePathTestBase.php b/core/tests/Drupal/FunctionalTests/Update/UpdatePathTestBase.php index 8b2c4b493e4b..3ee78e553654 100644 --- a/core/tests/Drupal/FunctionalTests/Update/UpdatePathTestBase.php +++ b/core/tests/Drupal/FunctionalTests/Update/UpdatePathTestBase.php @@ -137,6 +137,16 @@ abstract class UpdatePathTestBase extends BrowserTestBase { // Load the database(s). foreach ($this->databaseDumpFiles as $file) { + // Determine the version of the database dump if specified. + $matches = []; + $dumpVersion = preg_match('/drupal-(\d+\.\d+\.\d+)\./', $file, $matches) === 1 ? $matches[1] : NULL; + + // If the db driver is mysqli, we do not need to run the update tests for + // db dumps prior to 11.2 when the module was introduced. + if (Database::getConnection()->getProvider() === 'mysqli' && $dumpVersion && version_compare($dumpVersion, '11.2.0', '<')) { + $this->markTestSkipped("The mysqli driver was introduced in Drupal 11.2, skip update tests from database at version {$dumpVersion}"); + } + if (str_ends_with($file, '.gz')) { $file = "compress.zlib://$file"; } diff --git a/core/tests/Drupal/KernelTests/Core/Asset/AttachedAssetsTest.php b/core/tests/Drupal/KernelTests/Core/Asset/AttachedAssetsTest.php index 6dd535e88f95..809e54737b7c 100644 --- a/core/tests/Drupal/KernelTests/Core/Asset/AttachedAssetsTest.php +++ b/core/tests/Drupal/KernelTests/Core/Asset/AttachedAssetsTest.php @@ -467,4 +467,26 @@ class AttachedAssetsTest extends KernelTestBase { $this->assertStringContainsString('<script src="' . str_replace('&', '&', $this->fileUrlGenerator->generateString('core/modules/system/tests/modules/common_test/querystring.js?arg1=value1&arg2=value2')) . '&' . $query_string . '"></script>', $rendered_js, 'JavaScript file with query string gets version query string correctly appended.'); } + /** + * Test settings can be loaded even when libraries are not. + */ + public function testAttachedSettingsWithoutLibraries(): void { + $assets = new AttachedAssets(); + + // First test with no libraries will return no settings. + $assets->setSettings(['test' => 'foo']); + $js = $this->assetResolver->getJsAssets($assets, TRUE, \Drupal::languageManager()->getCurrentLanguage())[1]; + $this->assertArrayNotHasKey('drupalSettings', $js); + + // Second test with a warm cache. + $js = $this->assetResolver->getJsAssets($assets, TRUE, \Drupal::languageManager()->getCurrentLanguage())[1]; + $this->assertArrayNotHasKey('drupalSettings', $js); + + // Now test with different settings when drupalSettings is already loaded. + $assets->setSettings(['test' => 'bar']); + $assets->setAlreadyLoadedLibraries(['core/drupalSettings']); + $js = $this->assetResolver->getJsAssets($assets, TRUE, \Drupal::languageManager()->getCurrentLanguage())[1]; + $this->assertSame('bar', $js['drupalSettings']['data']['test']); + } + } diff --git a/core/tests/Drupal/KernelTests/Core/Database/BasicSyntaxTest.php b/core/tests/Drupal/KernelTests/Core/Database/BasicSyntaxTest.php index 079009dc7a56..8725f647e8d1 100644 --- a/core/tests/Drupal/KernelTests/Core/Database/BasicSyntaxTest.php +++ b/core/tests/Drupal/KernelTests/Core/Database/BasicSyntaxTest.php @@ -63,18 +63,6 @@ class BasicSyntaxTest extends DatabaseTestBase { } /** - * Tests string concatenation with separator, with field values. - */ - public function testConcatWsFields(): void { - $result = $this->connection->query("SELECT CONCAT_WS('-', :a1, [name], :a2, [age]) FROM {test} WHERE [age] = :age", [ - ':a1' => 'name', - ':a2' => 'age', - ':age' => 25, - ]); - $this->assertSame('name-John-age-25', $result->fetchField()); - } - - /** * Tests escaping of LIKE wildcards. */ public function testLikeEscape(): void { diff --git a/core/tests/Drupal/KernelTests/Core/Database/DriverSpecificSyntaxTestBase.php b/core/tests/Drupal/KernelTests/Core/Database/DriverSpecificSyntaxTestBase.php index 7723d872cc12..e18336205398 100644 --- a/core/tests/Drupal/KernelTests/Core/Database/DriverSpecificSyntaxTestBase.php +++ b/core/tests/Drupal/KernelTests/Core/Database/DriverSpecificSyntaxTestBase.php @@ -43,4 +43,16 @@ abstract class DriverSpecificSyntaxTestBase extends DriverSpecificDatabaseTestBa $this->assertSame('[square]', $result->fetchField()); } + /** + * Tests string concatenation with separator, with field values. + */ + public function testConcatWsFields(): void { + $result = $this->connection->query("SELECT CONCAT_WS('-', :a1, [name], :a2, [age]) FROM {test} WHERE [age] = :age", [ + ':a1' => 'name', + ':a2' => 'age', + ':age' => 25, + ]); + $this->assertSame('name-John-age-25', $result->fetchField()); + } + } diff --git a/core/tests/Drupal/KernelTests/Core/Entity/EntityDefinitionUpdateMultipleTypesTest.php b/core/tests/Drupal/KernelTests/Core/Entity/EntityDefinitionUpdateMultipleTypesTest.php index 5e708fbbc2ff..a914752e9f17 100644 --- a/core/tests/Drupal/KernelTests/Core/Entity/EntityDefinitionUpdateMultipleTypesTest.php +++ b/core/tests/Drupal/KernelTests/Core/Entity/EntityDefinitionUpdateMultipleTypesTest.php @@ -774,7 +774,7 @@ class EntityDefinitionUpdateMultipleTypesTest extends EntityKernelTestBase { $this->assertTrue($this->database->schema()->fieldExists('entity_test_update', 'new_base_field'), "New field 'new_base_field' has been created on the 'entity_test_update' table."); $this->assertTrue($this->database->schema()->indexExists('entity_test_update', 'entity_test_update_field__new_base_field'), "New index 'entity_test_update_field__new_base_field' has been created on the 'entity_test_update' table."); // Check index size in for MySQL. - if (Database::getConnection()->driver() == 'mysql') { + if (in_array(Database::getConnection()->driver(), ['mysql', 'mysqli'])) { $result = Database::getConnection()->query('SHOW INDEX FROM {entity_test_update} WHERE key_name = \'entity_test_update_field__new_base_field\' and column_name = \'new_base_field\'')->fetchObject(); $this->assertEquals(191, $result->Sub_part, 'The index length has been restricted to 191 characters for UTF8MB4 compatibility.'); } @@ -803,7 +803,7 @@ class EntityDefinitionUpdateMultipleTypesTest extends EntityKernelTestBase { $this->assertTrue($this->database->schema()->indexExists('entity_test_update', 'entity_test_update__type_index'), "New index 'entity_test_update__type_index' has been created on the 'entity_test_update' table."); // Check index size in for MySQL. - if (Database::getConnection()->driver() == 'mysql') { + if (in_array(Database::getConnection()->driver(), ['mysql', 'mysqli'])) { $result = Database::getConnection()->query('SHOW INDEX FROM {entity_test_update} WHERE key_name = \'entity_test_update__type_index\' and column_name = \'type\'')->fetchObject(); $this->assertEquals(191, $result->Sub_part, 'The index length has been restricted to 191 characters for UTF8MB4 compatibility.'); } diff --git a/core/tests/Drupal/KernelTests/Core/Test/PhpUnitApiFindAllClassFilesTest.php b/core/tests/Drupal/KernelTests/Core/Test/PhpUnitApiFindAllClassFilesTest.php index 2afb26f1b9e0..a8697cc84968 100644 --- a/core/tests/Drupal/KernelTests/Core/Test/PhpUnitApiFindAllClassFilesTest.php +++ b/core/tests/Drupal/KernelTests/Core/Test/PhpUnitApiFindAllClassFilesTest.php @@ -38,7 +38,7 @@ class PhpUnitApiFindAllClassFilesTest extends KernelTestBase { if (RunnerVersion::getMajor() >= 11) { $configurationFilePath .= \DIRECTORY_SEPARATOR . '.phpunit-next.xml'; } - $phpUnitTestDiscovery = new PhpUnitTestDiscovery($configurationFilePath); + $phpUnitTestDiscovery = PhpUnitTestDiscovery::instance()->setConfigurationFilePath($configurationFilePath); $phpUnitList = $phpUnitTestDiscovery->findAllClassFiles($extension, $directory); // Legacy TestDiscovery. diff --git a/core/tests/Drupal/KernelTests/Core/Test/PhpUnitApiGetTestClassesTest.php b/core/tests/Drupal/KernelTests/Core/Test/PhpUnitApiGetTestClassesTest.php index 81cdfc9c6c5f..caedbc0d2b62 100644 --- a/core/tests/Drupal/KernelTests/Core/Test/PhpUnitApiGetTestClassesTest.php +++ b/core/tests/Drupal/KernelTests/Core/Test/PhpUnitApiGetTestClassesTest.php @@ -38,7 +38,7 @@ class PhpUnitApiGetTestClassesTest extends KernelTestBase { if (RunnerVersion::getMajor() >= 11) { $configurationFilePath .= \DIRECTORY_SEPARATOR . '.phpunit-next.xml'; } - $phpUnitTestDiscovery = new PhpUnitTestDiscovery($configurationFilePath); + $phpUnitTestDiscovery = PhpUnitTestDiscovery::instance()->setConfigurationFilePath($configurationFilePath); $phpUnitList = $phpUnitTestDiscovery->getTestClasses($extension, $suites, $directory); // Legacy TestDiscovery. diff --git a/core/tests/Drupal/KernelTests/KernelTestBase.php b/core/tests/Drupal/KernelTests/KernelTestBase.php index 34aca08f15a9..c45e937d371e 100644 --- a/core/tests/Drupal/KernelTests/KernelTestBase.php +++ b/core/tests/Drupal/KernelTests/KernelTestBase.php @@ -439,7 +439,7 @@ abstract class KernelTestBase extends TestCase implements ServiceProviderInterfa throw new \Exception('There is no database connection so no tests can be run. You must provide a SIMPLETEST_DB environment variable to run PHPUnit based functional tests outside of run-tests.sh. See https://www.drupal.org/node/2116263#skipped-tests for more information.'); } else { - $database = Database::convertDbUrlToConnectionInfo($db_url, $this->root, TRUE); + $database = Database::convertDbUrlToConnectionInfo($db_url, TRUE); Database::addConnectionInfo('default', 'default', $database); } diff --git a/core/tests/Drupal/KernelTests/KernelTestBaseDatabaseDriverModuleTest.php b/core/tests/Drupal/KernelTests/KernelTestBaseDatabaseDriverModuleTest.php index e8dfc3be6f45..828b4ab54ec0 100644 --- a/core/tests/Drupal/KernelTests/KernelTestBaseDatabaseDriverModuleTest.php +++ b/core/tests/Drupal/KernelTests/KernelTestBaseDatabaseDriverModuleTest.php @@ -25,7 +25,7 @@ class KernelTestBaseDatabaseDriverModuleTest extends KernelTestBase { throw new \Exception('There is no database connection so no tests can be run. You must provide a SIMPLETEST_DB environment variable to run PHPUnit based functional tests outside of run-tests.sh. See https://www.drupal.org/node/2116263#skipped-tests for more information.'); } else { - $database = Database::convertDbUrlToConnectionInfo($db_url, $this->root); + $database = Database::convertDbUrlToConnectionInfo($db_url); if (in_array($database['driver'], ['mysql', 'pgsql'])) { // Change the used database driver to the one provided by the module diff --git a/core/tests/Drupal/KernelTests/Scripts/TestSiteApplicationTest.php b/core/tests/Drupal/KernelTests/Scripts/TestSiteApplicationTest.php index 02521bdda2f8..2f8b7309b520 100644 --- a/core/tests/Drupal/KernelTests/Scripts/TestSiteApplicationTest.php +++ b/core/tests/Drupal/KernelTests/Scripts/TestSiteApplicationTest.php @@ -286,7 +286,7 @@ class TestSiteApplicationTest extends KernelTestBase { * The database key of the added connection. */ protected function addTestDatabase($db_prefix): string { - $database = Database::convertDbUrlToConnectionInfo(getenv('SIMPLETEST_DB'), $this->root); + $database = Database::convertDbUrlToConnectionInfo(getenv('SIMPLETEST_DB')); $database['prefix'] = $db_prefix; $target = __CLASS__ . $db_prefix; Database::addConnectionInfo($target, 'default', $database); diff --git a/core/tests/Drupal/TestSite/Commands/TestSiteInstallCommand.php b/core/tests/Drupal/TestSite/Commands/TestSiteInstallCommand.php index 1459f0cdfee3..470d3ef92e22 100644 --- a/core/tests/Drupal/TestSite/Commands/TestSiteInstallCommand.php +++ b/core/tests/Drupal/TestSite/Commands/TestSiteInstallCommand.php @@ -280,18 +280,18 @@ class TestSiteInstallCommand extends Command { } /** - * {@inheritdoc} + * Changes the database connection to the prefixed one. */ - protected function changeDatabasePrefix() { + protected function changeDatabasePrefix(): void { // Ensure that we use the database from SIMPLETEST_DB environment variable. Database::removeConnection('default'); $this->changeDatabasePrefixTrait(); } /** - * {@inheritdoc} + * Generates a database prefix for the site installation. */ - protected function prepareDatabasePrefix() { + protected function prepareDatabasePrefix(): void { // Override this method so that we can force a lock to be created. $test_db = new TestDatabase(NULL, TRUE); $this->siteDirectory = $test_db->getTestSitePath(); diff --git a/core/tests/Drupal/TestSite/Commands/TestSiteTearDownCommand.php b/core/tests/Drupal/TestSite/Commands/TestSiteTearDownCommand.php index 3d80f3a1c178..7e601981d4c6 100644 --- a/core/tests/Drupal/TestSite/Commands/TestSiteTearDownCommand.php +++ b/core/tests/Drupal/TestSite/Commands/TestSiteTearDownCommand.php @@ -84,7 +84,7 @@ class TestSiteTearDownCommand extends Command { protected function tearDown(TestDatabase $test_database, $db_url): void { // Connect to the test database. $root = dirname(__DIR__, 5); - $database = Database::convertDbUrlToConnectionInfo($db_url, $root); + $database = Database::convertDbUrlToConnectionInfo($db_url); $database['prefix'] = $test_database->getDatabasePrefix(); Database::addConnectionInfo(__CLASS__, 'default', $database); diff --git a/core/tests/Drupal/Tests/Core/Ajax/AjaxResponseTest.php b/core/tests/Drupal/Tests/Core/Ajax/AjaxResponseTest.php index ab5fce6d191c..9dd5727f2a4b 100644 --- a/core/tests/Drupal/Tests/Core/Ajax/AjaxResponseTest.php +++ b/core/tests/Drupal/Tests/Core/Ajax/AjaxResponseTest.php @@ -5,6 +5,7 @@ declare(strict_types=1); namespace Drupal\Tests\Core\Ajax; use Drupal\Core\Ajax\AjaxResponse; +use Drupal\Core\Ajax\CommandInterface; use Drupal\Core\EventSubscriber\AjaxResponseSubscriber; use Drupal\Tests\UnitTestCase; use Symfony\Component\HttpFoundation\Request; @@ -98,4 +99,95 @@ class AjaxResponseTest extends UnitTestCase { $this->assertEquals('<textarea>[]</textarea>', $response->getContent()); } + /** + * Tests the mergeWith() method. + * + * @see \Drupal\Core\Ajax\AjaxResponse::mergeWith() + * + * @throws \PHPUnit\Framework\MockObject\Exception + */ + public function testMergeWithOtherAjaxResponse(): void { + $response = new AjaxResponse([]); + + $command_one = $this->createCommandMock('one'); + + $command_two = $this->createCommandMockWithSettingsAndLibrariesAttachments( + 'Drupal\Core\Ajax\HtmlCommand', [ + 'setting1' => 'value1', + 'setting2' => 'value2', + ], ['jquery', 'drupal'], 'two'); + $command_three = $this->createCommandMockWithSettingsAndLibrariesAttachments( + 'Drupal\Core\Ajax\InsertCommand', [ + 'setting1' => 'overridden', + 'setting3' => 'value3', + ], ['jquery', 'ajax'], 'three'); + + $response->addCommand($command_one); + $response->addCommand($command_two); + + $response2 = new AjaxResponse([]); + $response2->addCommand($command_three); + + $response->mergeWith($response2); + self::assertEquals([ + 'library' => ['jquery', 'drupal', 'jquery', 'ajax'], + 'drupalSettings' => [ + 'setting1' => 'overridden', + 'setting2' => 'value2', + 'setting3' => 'value3', + ], + ], $response->getAttachments()); + self::assertEquals([['command' => 'one'], ['command' => 'two'], ['command' => 'three']], $response->getCommands()); + } + + /** + * Creates a mock of a provided subclass of CommandInterface. + * + * Adds given settings and libraries to assets mock + * that is attached to the command mock. + * + * @param string $command_class_name + * The command class name to create the mock for. + * @param array|null $settings + * The settings to attach. + * @param array|null $libraries + * The libraries to attach. + * @param string $command_name + * The command name to pass to the mock. + */ + private function createCommandMockWithSettingsAndLibrariesAttachments( + string $command_class_name, + array|null $settings, + array|null $libraries, + string $command_name, + ): CommandInterface { + $command = $this->createMock($command_class_name); + $command->expects($this->once()) + ->method('render') + ->willReturn(['command' => $command_name]); + + $assets = $this->createMock('Drupal\Core\Asset\AttachedAssetsInterface'); + $assets->expects($this->once())->method('getLibraries')->willReturn($libraries); + $assets->expects($this->once())->method('getSettings')->willReturn($settings); + + $command->expects($this->once())->method('getAttachedAssets')->willReturn($assets); + + return $command; + } + + /** + * Creates a mock of the Drupal\Core\Ajax\CommandInterface. + * + * @param string $command_name + * The command name to pass to the mock. + */ + private function createCommandMock(string $command_name): CommandInterface { + $command = $this->createMock('Drupal\Core\Ajax\CommandInterface'); + $command->expects($this->once()) + ->method('render') + ->willReturn(['command' => $command_name]); + + return $command; + } + } diff --git a/core/tests/Drupal/Tests/Core/Asset/CssCollectionOptimizerLazyUnitTest.php b/core/tests/Drupal/Tests/Core/Asset/CssCollectionOptimizerLazyUnitTest.php index 798735a2c8a1..9dc1a0d113ee 100644 --- a/core/tests/Drupal/Tests/Core/Asset/CssCollectionOptimizerLazyUnitTest.php +++ b/core/tests/Drupal/Tests/Core/Asset/CssCollectionOptimizerLazyUnitTest.php @@ -148,4 +148,40 @@ class CssCollectionOptimizerLazyUnitTest extends UnitTestCase { self::assertStringEqualsFile(__DIR__ . '/css_test_files/css_license.css.optimized.aggregated.css', $aggregate); } + /** + * Test that external minified CSS assets do not trigger optimization. + * + * This ensures that fully external asset groups do not result in a + * CssOptimizer exception and are safely ignored. + */ + public function testExternalMinifiedCssAssetOptimizationIsSkipped(): void { + $mock_grouper = $this->createMock(AssetCollectionGrouperInterface::class); + $mock_optimizer = $this->createMock(AssetOptimizerInterface::class); + $mock_optimizer->expects($this->never())->method('optimize'); + + $optimizer = new CssCollectionOptimizerLazy( + $mock_grouper, + $mock_optimizer, + $this->createMock(ThemeManagerInterface::class), + $this->createMock(LibraryDependencyResolverInterface::class), + new RequestStack(), + $this->createMock(FileSystemInterface::class), + $this->createMock(ConfigFactoryInterface::class), + $this->createMock(FileUrlGeneratorInterface::class), + $this->createMock(TimeInterface::class), + $this->createMock(LanguageManagerInterface::class) + ); + $optimizer->optimizeGroup([ + 'items' => [ + [ + 'type' => 'external', + 'data' => __DIR__ . '/css_test_files/css_external.optimized.aggregated.css', + 'license' => FALSE, + 'preprocess' => TRUE, + 'minified' => TRUE, + ], + ], + ]); + } + } diff --git a/core/tests/Drupal/Tests/Core/Asset/css_test_files/css_external.optimized.aggregated.css b/core/tests/Drupal/Tests/Core/Asset/css_test_files/css_external.optimized.aggregated.css new file mode 100644 index 000000000000..dac82b6b80f6 --- /dev/null +++ b/core/tests/Drupal/Tests/Core/Asset/css_test_files/css_external.optimized.aggregated.css @@ -0,0 +1 @@ +/* Placeholder external CSS file. */ diff --git a/core/tests/Drupal/Tests/Core/Database/RowCountExceptionTest.php b/core/tests/Drupal/Tests/Core/Database/RowCountExceptionTest.php index 7ecc4518d714..569a6e3fd18e 100644 --- a/core/tests/Drupal/Tests/Core/Database/RowCountExceptionTest.php +++ b/core/tests/Drupal/Tests/Core/Database/RowCountExceptionTest.php @@ -27,7 +27,7 @@ class RowCountExceptionTest extends UnitTestCase { */ public static function providerTestExceptionMessage() { return [ - [static::DEFAULT_EXCEPTION_MESSAGE, ''], + [self::DEFAULT_EXCEPTION_MESSAGE, ''], ['test', 'test'], ]; } @@ -47,7 +47,7 @@ class RowCountExceptionTest extends UnitTestCase { */ public function testExceptionMessageNull(): void { $e = new RowCountException(NULL); - $this->assertSame(static::DEFAULT_EXCEPTION_MESSAGE, $e->getMessage()); + $this->assertSame(self::DEFAULT_EXCEPTION_MESSAGE, $e->getMessage()); } } diff --git a/core/tests/Drupal/Tests/Core/Database/UrlConversionTest.php b/core/tests/Drupal/Tests/Core/Database/UrlConversionTest.php index e36767d2f5a4..c74090fb599b 100644 --- a/core/tests/Drupal/Tests/Core/Database/UrlConversionTest.php +++ b/core/tests/Drupal/Tests/Core/Database/UrlConversionTest.php @@ -7,6 +7,7 @@ namespace Drupal\Tests\Core\Database; use Drupal\Core\Database\Database; use Drupal\Core\Extension\Exception\UnknownExtensionException; use Drupal\Tests\UnitTestCase; +use PHPUnit\Framework\Attributes\IgnoreDeprecations; // cspell:ignore dummydb @@ -31,7 +32,7 @@ class UrlConversionTest extends UnitTestCase { * @dataProvider providerConvertDbUrlToConnectionInfo */ public function testDbUrlToConnectionConversion($url, $database_array, $include_test_drivers): void { - $result = Database::convertDbUrlToConnectionInfo($url, $this->root, $include_test_drivers); + $result = Database::convertDbUrlToConnectionInfo($url, $include_test_drivers); $this->assertEquals($database_array, $result); } @@ -279,10 +280,10 @@ class UrlConversionTest extends UnitTestCase { * * @dataProvider providerInvalidArgumentsUrlConversion */ - public function testGetInvalidArgumentExceptionInUrlConversion($url, $root, $expected_exception_message): void { + public function testGetInvalidArgumentExceptionInUrlConversion($url, $expected_exception_message): void { $this->expectException(\InvalidArgumentException::class); $this->expectExceptionMessage($expected_exception_message); - Database::convertDbUrlToConnectionInfo($url, $root); + Database::convertDbUrlToConnectionInfo($url); } /** @@ -291,14 +292,12 @@ class UrlConversionTest extends UnitTestCase { * @return array * Array of arrays with the following elements: * - An invalid URL string. - * - Drupal root string. * - The expected exception message. */ public static function providerInvalidArgumentsUrlConversion() { return [ - ['foo', '', "Missing scheme in URL 'foo'"], - ['foo', 'bar', "Missing scheme in URL 'foo'"], - ['foo/bar/baz', 'bar2', "Missing scheme in URL 'foo/bar/baz'"], + ['foo', "Missing scheme in URL 'foo'"], + ['foo/bar/baz', "Missing scheme in URL 'foo/bar/baz'"], ]; } @@ -307,7 +306,7 @@ class UrlConversionTest extends UnitTestCase { */ public function testNoModuleSpecifiedDefaultsToDriverName(): void { $url = 'dummydb://test_user:test_pass@test_host/test_database'; - $connection_info = Database::convertDbUrlToConnectionInfo($url, $this->root, TRUE); + $connection_info = Database::convertDbUrlToConnectionInfo($url, TRUE); $expected = [ 'driver' => 'dummydb', 'username' => 'test_user', @@ -518,7 +517,7 @@ class UrlConversionTest extends UnitTestCase { $url = 'foo_bar_mysql://test_user:test_pass@test_host:3306/test_database?module=foo_bar'; $this->expectException(UnknownExtensionException::class); $this->expectExceptionMessage("The database_driver Drupal\\foo_bar\\Driver\\Database\\foo_bar_mysql does not exist."); - Database::convertDbUrlToConnectionInfo($url, $this->root, TRUE); + Database::convertDbUrlToConnectionInfo($url, TRUE); } /** @@ -528,7 +527,16 @@ class UrlConversionTest extends UnitTestCase { $url = 'driver_test_mysql://test_user:test_pass@test_host:3306/test_database?module=driver_test'; $this->expectException(UnknownExtensionException::class); $this->expectExceptionMessage("The database_driver Drupal\\driver_test\\Driver\\Database\\driver_test_mysql does not exist."); - Database::convertDbUrlToConnectionInfo($url, $this->root, TRUE); + Database::convertDbUrlToConnectionInfo($url, TRUE); + } + + /** + * @covers ::convertDbUrlToConnectionInfo + */ + #[IgnoreDeprecations] + public function testDeprecationOfRootParameter(): void { + $this->expectDeprecation('Passing a string $root value to Drupal\\Core\\Database\\Database::convertDbUrlToConnectionInfo() is deprecated in drupal:11.3.0 and will be removed in drupal:12.0.0. There is no replacement. See https://www.drupal.org/node/3511287'); + Database::convertDbUrlToConnectionInfo('sqlite://localhost/test_database', $this->root, TRUE); } } diff --git a/core/tests/Drupal/Tests/Core/Entity/EntityViewBuilderTest.php b/core/tests/Drupal/Tests/Core/Entity/EntityViewBuilderTest.php new file mode 100644 index 000000000000..29d3d17dba0f --- /dev/null +++ b/core/tests/Drupal/Tests/Core/Entity/EntityViewBuilderTest.php @@ -0,0 +1,80 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\Tests\Core\Entity; + +use Drupal\Core\Entity\Display\EntityViewDisplayInterface; +use Drupal\Core\Entity\EntityViewBuilder; +use Drupal\Core\Entity\FieldableEntityInterface; +use Drupal\Core\Extension\ModuleHandlerInterface; +use Drupal\Core\Field\FieldItemListInterface; +use Drupal\Tests\UnitTestCase; + +/** + * @coversDefaultClass \Drupal\Core\Entity\EntityViewBuilder + * @group Entity + */ +class EntityViewBuilderTest extends UnitTestCase { + + const string ENTITY_TYPE_ID = 'test_entity_type'; + + /** + * The entity view builder under test. + * + * @var \Drupal\Core\Entity\EntityViewBuilder + */ + protected EntityViewBuilder $viewBuilder; + + /** + * {@inheritdoc} + */ + protected function setUp(): void { + parent::setUp(); + $this->viewBuilder = new class() extends EntityViewBuilder { + + public function __construct() { + $this->entityTypeId = EntityViewBuilderTest::ENTITY_TYPE_ID; + } + + }; + } + + /** + * Tests build components using a mocked Iterator. + */ + public function testBuildComponents(): void { + $field_name = $this->randomMachineName(); + $bundle = $this->randomMachineName(); + $entity_id = mt_rand(20, 30); + $field_item_list = $this->createStub(FieldItemListInterface::class); + $item = new \stdClass(); + $this->setupMockIterator($field_item_list, [$item]); + $entity = $this->createConfiguredStub(FieldableEntityInterface::class, [ + 'bundle' => $bundle, + 'hasField' => TRUE, + 'get' => $field_item_list, + ]); + $formatter_result = [ + $entity_id => ['#' . $this->randomMachineName() => $this->randomString()], + ]; + $display = $this->createConfiguredStub(EntityViewDisplayInterface::class, [ + 'getComponents' => [$field_name => []], + 'buildMultiple' => $formatter_result, + ]); + $entities = [$entity_id => $entity]; + $displays = [$bundle => $display]; + $build = [$entity_id => []]; + $view_mode = $this->randomMachineName(); + // Assert the hook is invoked. + $module_handler = $this->createMock(ModuleHandlerInterface::class); + $module_handler->expects($this->once()) + ->method('invokeAll') + ->with('entity_prepare_view', [self::ENTITY_TYPE_ID, $entities, $displays, $view_mode]); + $this->viewBuilder->setModuleHandler($module_handler); + $this->viewBuilder->buildComponents($build, $entities, $displays, $view_mode); + $this->assertSame([], $item->_attributes); + $this->assertSame($formatter_result, $build); + } + +} diff --git a/core/tests/Drupal/Tests/Core/Test/TestSetupTraitTest.php b/core/tests/Drupal/Tests/Core/Test/TestSetupTraitTest.php index ba1d28a50c6d..5627d068aa77 100644 --- a/core/tests/Drupal/Tests/Core/Test/TestSetupTraitTest.php +++ b/core/tests/Drupal/Tests/Core/Test/TestSetupTraitTest.php @@ -29,7 +29,7 @@ class TestSetupTraitTest extends UnitTestCase { public function testChangeDatabasePrefix(): void { $root = dirname(__FILE__, 7); putenv('SIMPLETEST_DB=pgsql://user:pass@127.0.0.1/db'); - $connection_info = Database::convertDbUrlToConnectionInfo('mysql://user:pass@localhost/db', $root); + $connection_info = Database::convertDbUrlToConnectionInfo('mysql://user:pass@localhost/db'); Database::addConnectionInfo('default', 'default', $connection_info); $this->assertEquals('mysql', Database::getConnectionInfo()['default']['driver']); $this->assertEquals('localhost', Database::getConnectionInfo()['default']['host']); diff --git a/core/tests/Drupal/Tests/UnitTestCase.php b/core/tests/Drupal/Tests/UnitTestCase.php index 2257148d0698..b279bd1ed250 100644 --- a/core/tests/Drupal/Tests/UnitTestCase.php +++ b/core/tests/Drupal/Tests/UnitTestCase.php @@ -13,6 +13,7 @@ use Drupal\Core\StringTranslation\PluralTranslatableMarkup; use Drupal\TestTools\Extension\DeprecationBridge\ExpectDeprecationTrait; use Drupal\TestTools\Extension\Dump\DebugDump; use PHPUnit\Framework\Attributes\BeforeClass; +use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Prophecy\PhpUnit\ProphecyTrait; use Symfony\Component\VarDumper\VarDumper; @@ -210,4 +211,32 @@ abstract class UnitTestCase extends TestCase { return $class_resolver; } + /** + * Set up a traversable class mock to return specific items when iterated. + * + * Test doubles for types extending \Traversable are required to implement + * \Iterator which requires setting up five methods. Instead, this helper + * can be used. + * + * @param \PHPUnit\Framework\MockObject\MockObject&\Iterator $mock + * A mock object mocking a traversable class. + * @param array $items + * The items to return when this mock is iterated. + * + * @return \PHPUnit\Framework\MockObject\MockObject&\Iterator + * The same mock object ready to be iterated. + * + * @template T of \PHPUnit\Framework\MockObject\MockObject&\Iterator + * @phpstan-param T $mock + * @phpstan-return T + * @see https://github.com/sebastianbergmann/phpunit-mock-objects/issues/103 + */ + protected function setupMockIterator(MockObject&\Iterator $mock, array $items): MockObject&\Iterator { + $iterator = new \ArrayIterator($items); + foreach (get_class_methods(\Iterator::class) as $method) { + $mock->method($method)->willReturnCallback([$iterator, $method]); + } + return $mock; + } + } |