3 namespace Drupal\Tests\Core\Config;
5 use Drupal\Core\DependencyInjection\ContainerBuilder;
6 use Drupal\Core\Render\Markup;
7 use Drupal\Tests\UnitTestCase;
8 use Drupal\Core\Config\Config;
9 use Drupal\Core\Config\ConfigValueException;
14 * @coversDefaultClass \Drupal\Core\Config\Config
18 * @see \Drupal\Core\Config\Config
20 class ConfigTest extends UnitTestCase {
25 * @var \Drupal\Core\Config\Config
32 * @var \Drupal\Core\Config\StorageInterface|\PHPUnit_Framework_MockObject_MockObject
39 * @var \Symfony\Component\EventDispatcher\EventDispatcherInterface|\PHPUnit_Framework_MockObject_MockObject
41 protected $eventDispatcher;
46 * @var \Drupal\Core\Config\TypedConfigManagerInterface|\PHPUnit_Framework_MockObject_MockObject
48 protected $typedConfig;
51 * The mocked cache tags invalidator.
53 * @var \Drupal\Core\Cache\CacheTagsInvalidatorInterface|\PHPUnit_Framework_MockObject_MockObject
55 protected $cacheTagsInvalidator;
57 protected function setUp() {
58 $this->storage = $this->getMock('Drupal\Core\Config\StorageInterface');
59 $this->eventDispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface');
60 $this->typedConfig = $this->getMock('\Drupal\Core\Config\TypedConfigManagerInterface');
61 $this->config = new Config('config.test', $this->storage, $this->eventDispatcher, $this->typedConfig);
62 $this->cacheTagsInvalidator = $this->getMock('Drupal\Core\Cache\CacheTagsInvalidatorInterface');
64 $container = new ContainerBuilder();
65 $container->set('cache_tags.invalidator', $this->cacheTagsInvalidator);
66 \Drupal::setContainer($container);
71 * @dataProvider setNameProvider
73 public function testSetName($name) {
75 $this->config->setName($name);
77 // Check that the name has been set correctly.
78 $this->assertEquals($name, $this->config->getName());
80 // Check that the name validates.
81 // Should throw \Drupal\Core\Config\ConfigNameException if invalid.
82 $this->config->validateName($name);
86 * Provides config names to test.
88 * @see \Drupal\Tests\Core\Config\ConfigTest::testSetName()
90 public function setNameProvider() {
92 // Valid name with dot.
98 'test.' . str_repeat('a', Config::MAX_NAME_LENGTH - 5),
106 public function testIsNew() {
107 // Config should be new by default.
108 $this->assertTrue($this->config->isNew());
110 // Config is no longer new once saved.
111 $this->config->save();
112 $this->assertFalse($this->config->isNew());
117 * @dataProvider nestedDataProvider
119 public function testSetData($data) {
120 $this->config->setData($data);
121 $this->assertEquals($data, $this->config->getRawData());
122 $this->assertConfigDataEquals($data);
127 * @dataProvider nestedDataProvider
129 public function testSaveNew($data) {
130 $this->cacheTagsInvalidator->expects($this->never())
131 ->method('invalidateTags');
134 $this->config->setData($data);
136 // Check that original data has not been set yet.
137 foreach ($data as $key => $value) {
138 $this->assertNull($this->config->getOriginal($key, FALSE));
141 // Save so that the original data is set.
142 $config = $this->config->save();
144 // Check that returned $config is instance of Config.
145 $this->assertInstanceOf('\Drupal\Core\Config\Config', $config);
147 // Check that the original data it saved.
148 $this->assertOriginalConfigDataEquals($data, TRUE);
153 * @dataProvider nestedDataProvider
155 public function testSaveExisting($data) {
156 $this->cacheTagsInvalidator->expects($this->once())
157 ->method('invalidateTags')
158 ->with(['config:config.test']);
161 $this->config->setData($data);
162 $this->config->save();
166 $new_data['a']['d'] = 2;
167 $this->config->setData($new_data);
168 $this->config->save();
169 $this->assertOriginalConfigDataEquals($new_data, TRUE);
173 * @covers ::setModuleOverride
174 * @covers ::setSettingsOverride
175 * @covers ::getOriginal
176 * @dataProvider overrideDataProvider
178 public function testOverrideData($data, $module_data, $setting_data) {
180 $this->config->setData($data);
182 // Check original data was set correctly.
183 $this->assertConfigDataEquals($data);
185 // Save so that the original data is stored.
186 $this->config->save();
188 // Set module override data and check value before and after save.
189 $this->config->setModuleOverride($module_data);
190 $this->assertConfigDataEquals($module_data);
191 $this->config->save();
192 $this->assertConfigDataEquals($module_data);
194 // Set setting override data and check value before and after save.
195 $this->config->setSettingsOverride($setting_data);
196 $this->assertConfigDataEquals($setting_data);
197 $this->config->save();
198 $this->assertConfigDataEquals($setting_data);
200 // Set module overrides again to ensure override order is correct.
201 $this->config->setModuleOverride($module_data);
203 // Setting data should be overriding module data.
204 $this->assertConfigDataEquals($setting_data);
205 $this->config->save();
206 $this->assertConfigDataEquals($setting_data);
208 // Check original data has not changed.
209 $this->assertOriginalConfigDataEquals($data, FALSE);
211 // Check setting overrides are returned with $apply_overrides = TRUE.
212 $this->assertOriginalConfigDataEquals($setting_data, TRUE);
214 // Check that $apply_overrides defaults to TRUE.
215 foreach ($setting_data as $key => $value) {
216 $config_value = $this->config->getOriginal($key);
217 $this->assertEquals($value, $config_value);
223 * @dataProvider nestedDataProvider
225 public function testSetValue($data) {
226 foreach ($data as $key => $value) {
227 $this->config->set($key, $value);
229 $this->assertConfigDataEquals($data);
235 public function testSetValidation() {
236 $this->setExpectedException(ConfigValueException::class);
237 $this->config->set('testData', ['dot.key' => 1]);
243 public function testSetIllegalOffsetValue() {
244 // Set a single value.
245 $this->config->set('testData', 1);
247 // Attempt to treat the single value as a nested item.
248 $this->setExpectedException(\PHPUnit_Framework_Error_Warning::class);
249 $this->config->set('testData.illegalOffset', 1);
253 * @covers ::initWithData
254 * @dataProvider nestedDataProvider
256 public function testInitWithData($data) {
257 $config = $this->config->initWithData($data);
259 // Should return the Config object.
260 $this->assertInstanceOf('\Drupal\Core\Config\Config', $config);
262 // Check config is not new.
263 $this->assertEquals(FALSE, $this->config->isNew());
265 // Check that data value was set correctly.
266 $this->assertConfigDataEquals($data);
268 // Check that original data was set.
269 $this->assertOriginalConfigDataEquals($data, TRUE);
271 // Check without applying overrides.
272 $this->assertOriginalConfigDataEquals($data, FALSE);
277 * @dataProvider simpleDataProvider
279 public function testClear($data) {
280 foreach ($data as $key => $value) {
281 // Check that values are cleared.
282 $this->config->set($key, $value);
283 $this->assertEquals($value, $this->config->get($key));
284 $this->config->clear($key);
285 $this->assertNull($this->config->get($key));
291 * @dataProvider nestedDataProvider
293 public function testNestedClear($data) {
294 foreach ($data as $key => $value) {
295 // Check that values are cleared.
296 $this->config->set($key, $value);
297 // Check each nested value.
298 foreach ($value as $nested_key => $nested_value) {
299 $full_nested_key = $key . '.' . $nested_key;
300 $this->assertEquals($nested_value, $this->config->get($full_nested_key));
301 $this->config->clear($full_nested_key);
302 $this->assertNull($this->config->get($full_nested_key));
309 * @dataProvider overrideDataProvider
311 public function testDelete($data, $module_data) {
312 $this->cacheTagsInvalidator->expects($this->once())
313 ->method('invalidateTags')
314 ->with(['config:config.test']);
317 foreach ($data as $key => $value) {
318 $this->config->set($key, $value);
321 $this->config->setModuleOverride($module_data);
324 $this->config->save();
326 // Check that original data is still correct.
327 $this->assertOriginalConfigDataEquals($data, FALSE);
329 // Check overrides have been set.
330 $this->assertConfigDataEquals($module_data);
331 $this->assertOriginalConfigDataEquals($module_data, TRUE);
333 // Check that config is new.
334 $this->assertFalse($this->config->isNew());
337 $this->config->delete();
339 // Check object properties have been reset.
340 $this->assertTrue($this->config->isNew());
341 foreach ($data as $key => $value) {
342 $this->assertEmpty($this->config->getOriginal($key, FALSE));
345 // Check that overrides have persisted.
346 foreach ($module_data as $key => $value) {
347 $this->assertConfigDataEquals($module_data);
348 $this->assertOriginalConfigDataEquals($module_data, TRUE);
354 * @dataProvider mergeDataProvider
356 public function testMerge($data, $data_to_merge, $merged_data) {
358 $this->config->setData($data);
361 $this->config->merge($data_to_merge);
363 // Check that data has merged correctly.
364 $this->assertEquals($merged_data, $this->config->getRawData());
368 * Provides data to test merges.
370 * @see \Drupal\Tests\Core\Config\ConfigTest::testMerge()
372 public function mergeDataProvider() {
376 ['a' => 1, 'b' => 2, 'c' => ['d' => 3]],
378 ['a' => 2, 'e' => 4, 'c' => ['f' => 5]],
380 ['a' => 2, 'b' => 2, 'c' => ['d' => 3, 'f' => 5], 'e' => 4],
386 * @covers ::validateName
387 * @dataProvider validateNameProvider
389 public function testValidateNameException($name, $exception_message) {
390 $this->setExpectedException('\Drupal\Core\Config\ConfigNameException', $exception_message);
391 $this->config->validateName($name);
395 * @covers ::getCacheTags
397 public function testGetCacheTags() {
398 $this->assertSame(['config:' . $this->config->getName()], $this->config->getCacheTags());
402 * Provides data to test name validation.
404 * @see \Drupal\Tests\Core\Config\ConfigTest::testValidateNameException()
406 public function validateNameProvider() {
408 // Name missing namespace (dot).
411 'Missing namespace in Config object name MissingNamespace.',
413 // Exceeds length (max length plus an extra dot).
415 str_repeat('a', Config::MAX_NAME_LENGTH) . ".",
416 'Config object name ' . str_repeat('a', Config::MAX_NAME_LENGTH) . '. exceeds maximum allowed length of ' . Config::MAX_NAME_LENGTH . ' characters.',
419 // Name must not contain : ? * < > " ' / \
420 foreach ([':', '?', '*', '<', '>', '"', "'", '/', '\\'] as $char) {
421 $name = 'name.' . $char;
424 "Invalid character in Config object name $name.",
431 * Provides override data.
433 * @see \Drupal\Tests\Core\Config\ConfigTest::testOverrideData()
434 * @see \Drupal\Tests\Core\Config\ConfigTest::testDelete()
436 public function overrideDataProvider() {
441 'a' => 'originalValue',
445 'a' => 'moduleValue',
447 // Setting overrides.
449 'a' => 'settingValue',
456 * Provides simple test data.
458 * @see \Drupal\Tests\Core\Config\ConfigTest::testClear()
460 public function simpleDataProvider() {
473 * Provides nested test data.
475 * @see \Drupal\Tests\Core\Config\ConfigTest::testSetData()
476 * @see \Drupal\Tests\Core\Config\ConfigTest::testSave()
477 * @see \Drupal\Tests\Core\Config\ConfigTest::testSetValue()
478 * @see \Drupal\Tests\Core\Config\ConfigTest::testInitWithData()
479 * @see \Drupal\Tests\Core\Config\ConfigTest::testNestedClear()
481 public function nestedDataProvider() {
500 * Asserts all config data equals $data provided.
503 * Config data to be checked.
505 public function assertConfigDataEquals($data) {
506 foreach ($data as $key => $value) {
507 $this->assertEquals($value, $this->config->get($key));
512 * Asserts all original config data equals $data provided.
515 * Config data to be checked.
516 * @param bool $apply_overrides
517 * Apply any overrides to the original data.
519 public function assertOriginalConfigDataEquals($data, $apply_overrides) {
520 foreach ($data as $key => $value) {
521 $config_value = $this->config->getOriginal($key, $apply_overrides);
522 $this->assertEquals($value, $config_value);
529 * @covers ::initWithData
531 public function testSafeStringHandling() {
532 // Safe strings are cast when using ::set().
533 $safe_string = Markup::create('bar');
534 $this->config->set('foo', $safe_string);
535 $this->assertSame('bar', $this->config->get('foo'));
536 $this->config->set('foo', ['bar' => $safe_string]);
537 $this->assertSame('bar', $this->config->get('foo.bar'));
539 // Safe strings are cast when using ::setData().
540 $this->config->setData(['bar' => $safe_string]);
541 $this->assertSame('bar', $this->config->get('bar'));
543 // Safe strings are not cast when using ::initWithData().
544 $this->config->initWithData(['bar' => $safe_string]);
545 $this->assertSame($safe_string, $this->config->get('bar'));