3 namespace Drupal\KernelTests\Config;
5 use Drupal\Core\Config\Schema\SequenceDataDefinition;
6 use Drupal\Core\Config\Schema\TypedConfigInterface;
7 use Drupal\Core\TypedData\ComplexDataDefinitionInterface;
8 use Drupal\Core\TypedData\ComplexDataInterface;
9 use Drupal\Core\TypedData\Type\IntegerInterface;
10 use Drupal\Core\TypedData\Type\StringInterface;
11 use Drupal\KernelTests\KernelTestBase;
12 use Symfony\Component\Validator\ConstraintViolationListInterface;
15 * Tests config validation mechanism.
19 class TypedConfigTest extends KernelTestBase {
24 public static $modules = ['config_test'];
29 protected function setUp() {
32 $this->installConfig('config_test');
36 * Verifies that the Typed Data API is implemented correctly.
38 public function testTypedDataAPI() {
39 /** @var \Drupal\Core\Config\TypedConfigManagerInterface $typed_config_manager */
40 $typed_config_manager = \Drupal::service('config.typed');
41 /** @var \Drupal\Core\Config\Schema\TypedConfigInterface $typed_config */
42 $typed_config = $typed_config_manager->get('config_test.validation');
45 $string_data = $typed_config->get('llama');
46 $this->assertInstanceOf(StringInterface::class, $string_data);
47 $this->assertEquals('llama', $string_data->getValue());
50 $mapping = $typed_config->get('cat');
51 /** @var \Drupal\Core\TypedData\ComplexDataInterface $mapping */
52 $this->assertInstanceOf(ComplexDataInterface::class, $mapping);
53 $this->assertInstanceOf(StringInterface::class, $mapping->get('type'));
54 $this->assertEquals('kitten', $mapping->get('type')->getValue());
55 $this->assertInstanceOf(IntegerInterface::class, $mapping->get('count'));
56 $this->assertEquals(2, $mapping->get('count')->getValue());
57 // Verify the item metadata is available.
58 $this->assertInstanceOf(ComplexDataDefinitionInterface::class, $mapping->getDataDefinition());
59 $this->assertArrayHasKey('type', $mapping->getProperties());
60 $this->assertArrayHasKey('count', $mapping->getProperties());
62 // Test accessing sequences.
63 $sequence = $typed_config->get('giraffe');
64 /** @var \Drupal\Core\TypedData\ListInterface $sequence */
65 $this->assertInstanceOf(ComplexDataInterface::class, $sequence);
66 $this->assertInstanceOf(StringInterface::class, $sequence->get('hum1'));
67 $this->assertEquals('hum1', $sequence->get('hum1')->getValue());
68 $this->assertEquals('hum2', $sequence->get('hum2')->getValue());
69 $this->assertEquals(2, count($sequence->getIterator()));
70 // Verify the item metadata is available.
71 $this->assertInstanceOf(SequenceDataDefinition::class, $sequence->getDataDefinition());
73 // Test accessing typed config objects for simple config and config
75 $typed_config_manager = \Drupal::service('config.typed');
76 $typed_config = $typed_config_manager->createFromNameAndData('config_test.validation', \Drupal::configFactory()->get('config_test.validation')->get());
77 $this->assertInstanceOf(TypedConfigInterface::class, $typed_config);
78 $this->assertEquals(['llama', 'cat', 'giraffe', 'uuid', '_core'], array_keys($typed_config->getElements()));
80 $config_test_entity = \Drupal::entityTypeManager()->getStorage('config_test')->create([
84 'style' => 'test_style',
87 $typed_config = $typed_config_manager->createFromNameAndData($config_test_entity->getConfigDependencyName(), $config_test_entity->toArray());
88 $this->assertInstanceOf(TypedConfigInterface::class, $typed_config);
89 $this->assertEquals(['uuid', 'langcode', 'status', 'dependencies', 'id', 'label', 'weight', 'style', 'size', 'size_value', 'protected_property'], array_keys($typed_config->getElements()));
93 * Tests config validation via the Typed Data API.
95 public function testSimpleConfigValidation() {
96 $config = \Drupal::configFactory()->getEditable('config_test.validation');
97 /** @var \Drupal\Core\Config\TypedConfigManagerInterface $typed_config_manager */
98 $typed_config_manager = \Drupal::service('config.typed');
99 /** @var \Drupal\Core\Config\Schema\TypedConfigInterface $typed_config */
100 $typed_config = $typed_config_manager->get('config_test.validation');
102 $result = $typed_config->validate();
103 $this->assertInstanceOf(ConstraintViolationListInterface::class, $result);
104 $this->assertEmpty($result);
106 // Test constraints on primitive types.
107 $config->set('llama', 'elephant');
110 $typed_config = $typed_config_manager->get('config_test.validation');
111 $result = $typed_config->validate();
112 // Its not a valid llama anymore.
113 $this->assertCount(1, $result);
114 $this->assertEquals('no valid llama', $result->get(0)->getMessage());
116 // Test constraints on mapping.
117 $config->set('llama', 'llama');
118 $config->set('cat.type', 'nyans');
121 $typed_config = $typed_config_manager->get('config_test.validation');
122 $result = $typed_config->validate();
123 $this->assertEmpty($result);
125 // Test constrains on nested mapping.
126 $config->set('cat.type', 'miaus');
129 $typed_config = $typed_config_manager->get('config_test.validation');
130 $result = $typed_config->validate();
131 $this->assertCount(1, $result);
132 $this->assertEquals('no valid cat', $result->get(0)->getMessage());
134 // Test constrains on sequences elements.
135 $config->set('cat.type', 'nyans');
136 $config->set('giraffe', ['muh', 'hum2']);
138 $typed_config = $typed_config_manager->get('config_test.validation');
139 $result = $typed_config->validate();
140 $this->assertCount(1, $result);
141 $this->assertEquals('Giraffes just hum', $result->get(0)->getMessage());
143 // Test constrains on the sequence itself.
144 $config->set('giraffe', ['hum', 'hum2', 'invalid-key' => 'hum']);
147 $typed_config = $typed_config_manager->get('config_test.validation');
148 $result = $typed_config->validate();
149 $this->assertCount(1, $result);
150 $this->assertEquals('giraffe', $result->get(0)->getPropertyPath());
151 $this->assertEquals('Invalid giraffe key.', $result->get(0)->getMessage());
153 // Validates mapping.
154 $typed_config = $typed_config_manager->get('config_test.validation');
155 $value = $typed_config->getValue();
156 unset($value['giraffe']);
157 $value['elephant'] = 'foo';
158 $value['zebra'] = 'foo';
159 $typed_config->setValue($value);
160 $result = $typed_config->validate();
161 $this->assertCount(1, $result);
162 $this->assertEquals('', $result->get(0)->getPropertyPath());
163 $this->assertEquals('Unexpected keys: elephant, zebra', $result->get(0)->getMessage());