diff --git a/core/modules/block/tests/src/Kernel/BlockValidationTest.php b/core/modules/block/tests/src/Kernel/BlockValidationTest.php index 8d9e07ae1afc3a7f7f033a826466241ae0fa0280..c3c6142e3520a5662acdfcf52484787a629439af 100644 --- a/core/modules/block/tests/src/Kernel/BlockValidationTest.php +++ b/core/modules/block/tests/src/Kernel/BlockValidationTest.php @@ -36,7 +36,7 @@ protected function setUp(): void { */ public function testInvalidPluginId(): void { $this->entity->set('plugin', 'non_existent'); - $this->assertValidationErrors(["The 'non_existent' plugin does not exist."]); + $this->assertValidationErrors(['plugin' => "The 'non_existent' plugin does not exist."]); } } diff --git a/core/modules/editor/tests/src/Kernel/EditorValidationTest.php b/core/modules/editor/tests/src/Kernel/EditorValidationTest.php index c4f0562c4fdd492a9459e6a83c763b22f69ee072..670b7225c421faafdab292102cb524ed15f3f960 100644 --- a/core/modules/editor/tests/src/Kernel/EditorValidationTest.php +++ b/core/modules/editor/tests/src/Kernel/EditorValidationTest.php @@ -46,7 +46,7 @@ public function testInvalidDependencies(): void { $dependencies['config'] = []; $this->entity->set('dependencies', $dependencies); - $this->assertValidationErrors(['This text editor requires a text format.']); + $this->assertValidationErrors(['' => 'This text editor requires a text format.']); // Things look sort-of like `filter.format.*` should fail validation // because they don't exist. @@ -56,9 +56,9 @@ public function testInvalidDependencies(): void { ]; $this->entity->set('dependencies', $dependencies); $this->assertValidationErrors([ - 'This text editor requires a text format.', - "The 'filter.format' config does not exist.", - "The 'filter.format.' config does not exist.", + '' => 'This text editor requires a text format.', + 'dependencies.config.0' => "The 'filter.format' config does not exist.", + 'dependencies.config.1' => "The 'filter.format.' config does not exist.", ]); } @@ -67,7 +67,7 @@ public function testInvalidDependencies(): void { */ public function testInvalidPluginId(): void { $this->entity->setEditor('non_existent'); - $this->assertValidationErrors(["The 'non_existent' plugin does not exist."]); + $this->assertValidationErrors(['editor' => "The 'non_existent' plugin does not exist."]); } } diff --git a/core/modules/field/tests/src/Kernel/Entity/FieldConfigValidationTest.php b/core/modules/field/tests/src/Kernel/Entity/FieldConfigValidationTest.php index ee5cc5243757c496fe84ee98cc3b546797a535c8..fde68011cea0a42d8a175af0e90f54bcc36fc0f9 100644 --- a/core/modules/field/tests/src/Kernel/Entity/FieldConfigValidationTest.php +++ b/core/modules/field/tests/src/Kernel/Entity/FieldConfigValidationTest.php @@ -36,7 +36,7 @@ public function testInvalidDependencies(): void { $dependencies['config'] = []; $this->entity->set('dependencies', $dependencies); - $this->assertValidationErrors(['This field requires a field storage.']); + $this->assertValidationErrors(['' => 'This field requires a field storage.']); // Things look sort-of like `field.storage.*.*` should fail validation // because they don't exist. @@ -47,9 +47,9 @@ public function testInvalidDependencies(): void { ]; $this->entity->set('dependencies', $dependencies); $this->assertValidationErrors([ - "The 'field.storage.fake' config does not exist.", - "The 'field.storage.' config does not exist.", - "The 'field.storage.user.' config does not exist.", + 'dependencies.config.0' => "The 'field.storage.fake' config does not exist.", + 'dependencies.config.1' => "The 'field.storage.' config does not exist.", + 'dependencies.config.2' => "The 'field.storage.user.' config does not exist.", ]); } diff --git a/core/tests/Drupal/KernelTests/Core/Config/ConfigEntityValidationTestBase.php b/core/tests/Drupal/KernelTests/Core/Config/ConfigEntityValidationTestBase.php index e3dcdffc6423d98b34c25721ba0b393fb7235ecd..3512517f2554bfb5a092d6417a1ffc52df8c09ef 100644 --- a/core/tests/Drupal/KernelTests/Core/Config/ConfigEntityValidationTestBase.php +++ b/core/tests/Drupal/KernelTests/Core/Config/ConfigEntityValidationTestBase.php @@ -61,7 +61,7 @@ public function providerConfigDependenciesValidation(): array { 'fun_stuff' => ['star-trek.deep-space-nine'], ], [ - "'fun_stuff' is not a supported key.", + 'dependencies' => "'fun_stuff' is not a supported key.", ], ], 'empty string in config dependencies' => [ @@ -69,8 +69,10 @@ public function providerConfigDependenciesValidation(): array { 'config' => [''], ], [ - 'This value should not be blank.', - "The '' config does not exist.", + 'dependencies.config.0' => [ + 'This value should not be blank.', + "The '' config does not exist.", + ], ], ], 'non-existent config dependency' => [ @@ -78,7 +80,7 @@ public function providerConfigDependenciesValidation(): array { 'config' => ['fake_settings'], ], [ - "The 'fake_settings' config does not exist.", + 'dependencies.config.0' => "The 'fake_settings' config does not exist.", ], ], 'empty string in module dependencies' => [ @@ -86,8 +88,10 @@ public function providerConfigDependenciesValidation(): array { 'module' => [''], ], [ - 'This value should not be blank.', - "Module '' is not installed.", + 'dependencies.module.0' => [ + 'This value should not be blank.', + "Module '' is not installed.", + ], ], ], 'invalid module dependency' => [ @@ -95,8 +99,10 @@ public function providerConfigDependenciesValidation(): array { 'module' => ['invalid-module-name'], ], [ - 'This value is not valid.', - "Module 'invalid-module-name' is not installed.", + 'dependencies.module.0' => [ + 'This value is not valid.', + "Module 'invalid-module-name' is not installed.", + ], ], ], 'non-installed module dependency' => [ @@ -104,7 +110,7 @@ public function providerConfigDependenciesValidation(): array { 'module' => ['bad_judgment'], ], [ - "Module 'bad_judgment' is not installed.", + 'dependencies.module.0' => "Module 'bad_judgment' is not installed.", ], ], 'empty string in theme dependencies' => [ @@ -112,8 +118,10 @@ public function providerConfigDependenciesValidation(): array { 'theme' => [''], ], [ - 'This value should not be blank.', - "Theme '' is not installed.", + 'dependencies.theme.0' => [ + 'This value should not be blank.', + "Theme '' is not installed.", + ], ], ], 'invalid theme dependency' => [ @@ -121,8 +129,10 @@ public function providerConfigDependenciesValidation(): array { 'theme' => ['invalid-theme-name'], ], [ - 'This value is not valid.', - "Theme 'invalid-theme-name' is not installed.", + 'dependencies.theme.0' => [ + 'This value is not valid.', + "Theme 'invalid-theme-name' is not installed.", + ], ], ], 'non-installed theme dependency' => [ @@ -130,7 +140,7 @@ public function providerConfigDependenciesValidation(): array { 'theme' => ['ugly_theme'], ], [ - "Theme 'ugly_theme' is not installed.", + 'dependencies.theme.0' => "Theme 'ugly_theme' is not installed.", ], ], ]; @@ -141,8 +151,10 @@ public function providerConfigDependenciesValidation(): array { * * @param array[] $dependencies * The dependencies that should be added to the config entity under test. - * @param string[] $expected_messages - * The expected constraint violation messages. + * @param array<string, string|string[]> $expected_messages + * The expected validation error messages. Keys are property paths, values + * are the expected messages: a string if a single message is expected, an + * array of strings if multiple are expected. * * @dataProvider providerConfigDependenciesValidation */ @@ -154,7 +166,7 @@ public function testConfigDependenciesValidation(array $dependencies, array $exp // Add the dependencies we were given to the dependencies that may already // exist in the entity. - $dependencies = NestedArray::mergeDeep($this->entity->getDependencies(), $dependencies); + $dependencies = NestedArray::mergeDeep($dependencies, $this->entity->getDependencies()); $this->entity->set('dependencies', $dependencies); $this->assertValidationErrors($expected_messages); @@ -163,14 +175,23 @@ public function testConfigDependenciesValidation(array $dependencies, array $exp $this->entity->set('dependencies', [ 'enforced' => $dependencies, ]); - $this->assertValidationErrors($expected_messages); + // We now expect validation errors not at `dependencies.module.0`, but at + // `dependencies.enforced.module.0`. So reuse the same messages, but perform + // string replacement in the keys. + $expected_enforced_messages = array_combine( + str_replace('dependencies', 'dependencies.enforced', array_keys($expected_messages)), + array_values($expected_messages), + ); + $this->assertValidationErrors($expected_enforced_messages); } /** * Asserts a set of validation errors is raised when the entity is validated. * - * @param string[] $expected_messages - * The expected validation error messages. + * @param array<string, string|string[]> $expected_messages + * The expected validation error messages. Keys are property paths, values + * are the expected messages: a string if a single message is expected, an + * array of strings if multiple are expected. */ protected function assertValidationErrors(array $expected_messages): void { /** @var \Drupal\Core\TypedData\TypedDataManagerInterface $typed_data */ @@ -180,7 +201,17 @@ protected function assertValidationErrors(array $expected_messages): void { $actual_messages = []; foreach ($violations as $violation) { - $actual_messages[] = (string) $violation->getMessage(); + if (!isset($actual_messages[$violation->getPropertyPath()])) { + $actual_messages[$violation->getPropertyPath()] = (string) $violation->getMessage(); + } + else { + // Transform value from string to array. + if (is_string($actual_messages[$violation->getPropertyPath()])) { + $actual_messages[$violation->getPropertyPath()] = (array) $actual_messages[$violation->getPropertyPath()]; + } + // And append. + $actual_messages[$violation->getPropertyPath()][] = (string) $violation->getMessage(); + } } $this->assertSame($expected_messages, $actual_messages); }