first commit

This commit is contained in:
2024-07-15 12:33:27 +02:00
commit ce50ae282b
22084 changed files with 2623791 additions and 0 deletions

View File

@@ -0,0 +1,65 @@
<?php
declare(strict_types=1);
namespace Drupal\Tests\Traits\Core\Config;
use Drupal\Core\Config\Schema\SchemaIncompleteException;
/**
* Adds a test for the configuration schema checker use in tests.
*/
trait SchemaConfigListenerTestTrait {
/**
* Tests \Drupal\Core\Config\Development\ConfigSchemaChecker.
*/
public function testConfigSchemaChecker(): void {
// Test a non-existing schema.
$message = 'Expected SchemaIncompleteException thrown';
try {
$this->config('config_schema_test.schemaless')->set('foo', 'bar')->save();
$this->fail($message);
}
catch (SchemaIncompleteException $e) {
$this->assertEquals('No schema for config_schema_test.schemaless', $e->getMessage());
}
// Test a valid schema.
$message = 'Unexpected SchemaIncompleteException thrown';
$config = $this->config('config_test.types')->set('int', 10);
try {
$config->save();
}
catch (SchemaIncompleteException $e) {
$this->fail($message);
}
// Test a valid schema, where the value is accessed before saving. Ensures
// that overridden data is correctly reset after casting.
$message = 'Unexpected SchemaIncompleteException thrown';
$config = $this->config('config_test.types')->set('int', '10');
$config->get('int');
try {
$config->save();
}
catch (SchemaIncompleteException $e) {
$this->fail($message);
}
// Test an invalid schema.
$message = 'Expected SchemaIncompleteException thrown';
$config = $this->config('config_test.types')
->set('foo', 'bar')
->set('array', 1);
try {
$config->save();
$this->fail($message);
}
catch (SchemaIncompleteException $e) {
$this->assertEquals("Schema errors for config_test.types with the following errors: config_test.types:array variable type is integer but applied schema class is Drupal\Core\Config\Schema\Sequence, config_test.types:foo missing schema, 0 [foo] &#039;foo&#039; is not a supported key.", $e->getMessage());
}
}
}

View File

@@ -0,0 +1,19 @@
<?php
declare(strict_types=1);
namespace Drupal\Tests\Traits\Core;
/**
* Adds ability to run cron from tests.
*/
trait CronRunTrait {
/**
* Runs cron on the test site.
*/
protected function cronRun() {
$this->drupalGet('cron/' . \Drupal::state()->get('system.cron_key'));
}
}

View File

@@ -0,0 +1,61 @@
<?php
declare(strict_types=1);
namespace Drupal\Tests\Traits\Core;
/**
* Adds ability to convert a list of parameters into a stack of permutations.
*/
trait GeneratePermutationsTrait {
/**
* Converts a list of possible parameters into a stack of permutations.
*
* Takes a list of parameters containing possible values, and converts all of
* them into a list of items containing every possible permutation.
*
* Example:
* @code
* $parameters = [
* 'one' => [0, 1],
* 'two' => [2, 3],
* ];
* $permutations = $this->generatePermutations($parameters);
* // Result:
* $permutations == [
* ['one' => 0, 'two' => 2],
* ['one' => 1, 'two' => 2],
* ['one' => 0, 'two' => 3],
* ['one' => 1, 'two' => 3],
* ]
* @endcode
*
* @param array $parameters
* An associative array of parameters, keyed by parameter name, and whose
* values are arrays of parameter values.
*
* @return array[]
* A list of permutations, which is an array of arrays. Each inner array
* contains the full list of parameters that have been passed, but with a
* single value only.
*/
public static function generatePermutations(array $parameters) {
$all_permutations = [[]];
foreach ($parameters as $parameter => $values) {
$new_permutations = [];
// Iterate over all values of the parameter.
foreach ($values as $value) {
// Iterate over all existing permutations.
foreach ($all_permutations as $permutation) {
// Add the new parameter value to existing permutations.
$new_permutations[] = $permutation + [$parameter => $value];
}
}
// Replace the old permutations with the new permutations.
$all_permutations = $new_permutations;
}
return $all_permutations;
}
}

View File

@@ -0,0 +1,114 @@
<?php
declare(strict_types=1);
namespace Drupal\Tests\Traits\Core\Image;
use Drupal\Core\Image\ImageInterface;
use Drupal\Tests\TestFileCreationTrait;
/**
* Provides common methods for image toolkit kernel tests.
*
* The testing class must ensure that image_test.module is enabled.
*/
trait ToolkitTestTrait {
use TestFileCreationTrait {
getTestFiles as drupalGetTestFiles;
}
/**
* Resets/initializes the history of calls to the test toolkit functions.
*/
protected function imageTestReset(): void {
\Drupal::state()->delete('image_test.results');
}
/**
* Assert that all of the specified image toolkit operations were called once.
*
* @param string[] $expected
* String array containing the operation names, e.g. load, save, crop, etc.
*/
public function assertToolkitOperationsCalled(array $expected): void {
// If one of the image operations is expected, 'apply' should be expected as
// well.
$operations = [
'resize',
'rotate',
'crop',
'desaturate',
'create_new',
'scale',
'scale_and_crop',
'my_operation',
'convert',
'failing',
];
if (count(array_intersect($expected, $operations)) > 0 && !in_array('apply', $expected)) {
$expected[] = 'apply';
}
// Determine which operations were called.
$actual = array_keys(array_filter($this->imageTestGetAllCalls()));
// Determine if there were any expected that were not called.
$uncalled = array_diff($expected, $actual);
$this->assertEmpty($uncalled);
// Determine if there were any unexpected calls. If all unexpected calls are
// operations and apply was expected, we do not count it as an error.
$unexpected = array_diff($actual, $expected);
$assert = !(count($unexpected) && (!in_array('apply', $expected) || count(array_intersect($unexpected, $operations)) !== count($unexpected)));
$this->assertTrue($assert);
}
/**
* Gets an array of calls to the 'test' toolkit.
*
* @return array
* An array keyed by operation name ('parseFile', 'save', 'settings',
* 'resize', 'rotate', 'crop', 'desaturate') with values being arrays of
* parameters passed to each call.
*/
protected function imageTestGetAllCalls(): array {
return \Drupal::state()->get('image_test.results', []);
}
/**
* Sets up an image with the custom toolkit.
*
* @return \Drupal\Core\Image\ImageInterface
* The image object.
*/
protected function getImage(): ImageInterface {
$image_factory = \Drupal::service('image.factory');
$file = current($this->drupalGetTestFiles('image'));
$image = $image_factory->get($file->uri, 'test');
$this->assertTrue($image->isValid());
return $image;
}
/**
* Asserts the effect processing of an image effect plugin.
*
* @param string[] $expected_operations
* String array containing the operation names, e.g. load, save, crop, etc.
* @param string $effect_name
* The name of the image effect to test.
* @param array $data
* The data to be passed to the image effect.
*/
protected function assertImageEffect(array $expected_operations, string $effect_name, array $data): void {
$effect = $this->imageEffectPluginManager->createInstance($effect_name, ['data' => $data]);
$image = $this->getImage();
$this->imageTestReset();
// The test toolkit does not actually implement the operation plugins,
// therefore the calls to TestToolkit::apply() will fail. That's not a
// problem here, we are not testing the actual operations.
$this->assertFalse($effect->applyEffect($image));
$this->assertToolkitOperationsCalled($expected_operations);
}
}

View File

@@ -0,0 +1,120 @@
<?php
declare(strict_types=1);
namespace Drupal\Tests\Traits\Core;
use Drupal\Core\Language\LanguageInterface;
/**
* Provides methods to create and assert path_alias entities.
*
* This trait is meant to be used only by test classes.
*/
trait PathAliasTestTrait {
/**
* Creates a new path alias.
*
* @param string $path
* The system path.
* @param string $alias
* The alias for the system path.
* @param string $langcode
* (optional) A language code for the path alias. Defaults to
* \Drupal\Core\Language\LanguageInterface::LANGCODE_NOT_SPECIFIED.
*
* @return \Drupal\path_alias\PathAliasInterface
* A path alias entity.
*/
protected function createPathAlias($path, $alias, $langcode = LanguageInterface::LANGCODE_NOT_SPECIFIED) {
/** @var \Drupal\path_alias\PathAliasInterface $path_alias */
$path_alias = \Drupal::entityTypeManager()->getStorage('path_alias')->create([
'path' => $path,
'alias' => $alias,
'langcode' => $langcode,
]);
$path_alias->save();
return $path_alias;
}
/**
* Gets the first result from a 'load by properties' storage call.
*
* @param array $conditions
* An array of query conditions.
*
* @return \Drupal\path_alias\PathAliasInterface|null
* A path alias entity or NULL.
*/
protected function loadPathAliasByConditions($conditions) {
$storage = \Drupal::entityTypeManager()->getStorage('path_alias');
$query = $storage->getQuery()->accessCheck(FALSE);
foreach ($conditions as $field => $value) {
$query->condition($field, $value);
}
$entities = $storage->loadMultiple($query->execute());
return $entities ? reset($entities) : NULL;
}
/**
* Asserts that a path alias exists in the storage.
*
* @param string $alias
* The path alias.
* @param string|null $langcode
* (optional) The language code of the path alias.
* @param string|null $path
* (optional) The system path of the path alias.
* @param string|null $message
* (optional) A message to display with the assertion.
*/
protected function assertPathAliasExists($alias, $langcode = NULL, $path = NULL, $message = '') {
$query = \Drupal::entityTypeManager()
->getStorage('path_alias')
->getQuery()
->accessCheck(FALSE);
$query->condition('alias', $alias, '=');
if ($langcode) {
$query->condition('langcode', $langcode, '=');
}
if ($path) {
$query->condition('path', $path, '=');
}
$query->count();
$this->assertTrue((bool) $query->execute(), $message);
}
/**
* Asserts that a path alias does not exist in the storage.
*
* @param string $alias
* The path alias.
* @param string|null $langcode
* (optional) The language code of the path alias.
* @param string|null $path
* (optional) The system path of the path alias.
* @param string|null $message
* (optional) A message to display with the assertion.
*/
protected function assertPathAliasNotExists($alias, $langcode = NULL, $path = NULL, $message = '') {
$query = \Drupal::entityTypeManager()
->getStorage('path_alias')
->getQuery()
->accessCheck(FALSE);
$query->condition('alias', $alias, '=');
if ($langcode) {
$query->condition('langcode', $langcode, '=');
}
if ($path) {
$query->condition('path', $path, '=');
}
$query->count();
$this->assertFalse((bool) $query->execute(), $message);
}
}

View File

@@ -0,0 +1,68 @@
<?php
declare(strict_types=1);
namespace Drupal\Tests\Traits;
/**
* Converts deprecation warnings added by PHPUnit to silenced deprecations.
*
* This trait exists to allow Drupal to run tests with multiple versions of
* PHPUnit without failing due to PHPUnit's deprecation warnings.
*
* @internal
*/
trait PhpUnitWarnings {
/**
* Deprecation warnings from PHPUnit to raise with @trigger_error().
*
* Add any PHPUnit deprecations that should be handled as deprecation warnings
* (rather than unconditional failures) for core and contrib.
*
* @var string[]
*/
private static $deprecationWarnings = [
// Warning for testing.
'Test warning for \Drupal\Tests\PhpUnitWarningsTest::testAddWarning()',
// PHPUnit 9.
'assertFileNotExists() is deprecated and will be removed in PHPUnit 10. Refactor your code to use assertFileDoesNotExist() instead.',
'assertRegExp() is deprecated and will be removed in PHPUnit 10. Refactor your code to use assertMatchesRegularExpression() instead.',
'assertNotRegExp() is deprecated and will be removed in PHPUnit 10. Refactor your code to use assertDoesNotMatchRegularExpression() instead.',
'assertDirectoryNotExists() is deprecated and will be removed in PHPUnit 10. Refactor your code to use assertDirectoryDoesNotExist() instead.',
'Support for using expectException() with PHPUnit\\Framework\\Error\\Warning is deprecated and will be removed in PHPUnit 10. Use expectWarning() instead.',
'Support for using expectException() with PHPUnit\\Framework\\Error\\Error is deprecated and will be removed in PHPUnit 10. Use expectError() instead.',
'assertDirectoryNotIsWritable() is deprecated and will be removed in PHPUnit 10. Refactor your code to use assertDirectoryIsNotWritable() instead.',
'assertFileNotIsWritable() is deprecated and will be removed in PHPUnit 10. Refactor your code to use assertFileIsNotWritable() instead.',
// cspell:disable-next-line
'The at() matcher has been deprecated. It will be removed in PHPUnit 10. Please refactor your test to not rely on the order in which methods are invoked.',
// PHPUnit 9.6.
'Expecting E_WARNING and E_USER_WARNING is deprecated and will no longer be possible in PHPUnit 10.',
'Expecting E_ERROR and E_USER_ERROR is deprecated and will no longer be possible in PHPUnit 10.',
'assertObjectHasAttribute() is deprecated and will be removed in PHPUnit 10. Refactor your test to use assertObjectHasProperty() instead.',
'assertObjectNotHasAttribute() is deprecated and will be removed in PHPUnit 10. Refactor your test to use assertObjectNotHasProperty() instead.',
];
/**
* Converts PHPUnit deprecation warnings to E_USER_DEPRECATED.
*
* @param string $warning
* The warning message raised in tests.
*
* @see \PHPUnit\Framework\TestCase::addWarning()
*
* @internal
*/
public function addWarning(string $warning): void {
if (in_array($warning, self::$deprecationWarnings, TRUE)) {
// Convert listed PHPUnit deprecations into E_USER_DEPRECATED and prevent
// each from being raised as a test warning.
@trigger_error($warning, E_USER_DEPRECATED);
return;
}
// Otherwise, let the parent raise any warning not specifically listed.
parent::addWarning($warning);
}
}