4 * This file is part of the Symfony package.
6 * (c) Fabien Potencier <fabien@symfony.com>
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
12 namespace Symfony\Component\Config\Tests\Definition\Builder;
14 use PHPUnit\Framework\TestCase;
15 use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
16 use Symfony\Component\Config\Definition\Builder\ScalarNodeDefinition;
17 use Symfony\Component\Config\Definition\Exception\InvalidDefinitionException;
18 use Symfony\Component\Config\Definition\Processor;
20 class ArrayNodeDefinitionTest extends TestCase
22 public function testAppendingSomeNode()
24 $parent = new ArrayNodeDefinition('root');
25 $child = new ScalarNodeDefinition('child');
29 ->scalarNode('foo')->end()
30 ->scalarNode('bar')->end()
34 $this->assertCount(3, $this->getField($parent, 'children'));
35 $this->assertContains($child, $this->getField($parent, 'children'));
39 * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidDefinitionException
40 * @dataProvider providePrototypeNodeSpecificCalls
42 public function testPrototypeNodeSpecificOption($method, $args)
44 $node = new ArrayNodeDefinition('root');
46 \call_user_func_array(array($node, $method), $args);
51 public function providePrototypeNodeSpecificCalls()
54 array('defaultValue', array(array())),
55 array('addDefaultChildrenIfNoneSet', array()),
56 array('requiresAtLeastOneElement', array()),
57 array('useAttributeAsKey', array('foo')),
62 * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidDefinitionException
64 public function testConcreteNodeSpecificOption()
66 $node = new ArrayNodeDefinition('root');
68 ->addDefaultsIfNotSet()
75 * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidDefinitionException
77 public function testPrototypeNodesCantHaveADefaultValueWhenUsingDefaultChildren()
79 $node = new ArrayNodeDefinition('root');
81 ->defaultValue(array())
82 ->addDefaultChildrenIfNoneSet('foo')
88 public function testPrototypedArrayNodeDefaultWhenUsingDefaultChildren()
90 $node = new ArrayNodeDefinition('root');
92 ->addDefaultChildrenIfNoneSet()
95 $tree = $node->getNode();
96 $this->assertEquals(array(array()), $tree->getDefaultValue());
100 * @dataProvider providePrototypedArrayNodeDefaults
102 public function testPrototypedArrayNodeDefault($args, $shouldThrowWhenUsingAttrAsKey, $shouldThrowWhenNotUsingAttrAsKey, $defaults)
104 $node = new ArrayNodeDefinition('root');
106 ->addDefaultChildrenIfNoneSet($args)
111 $tree = $node->getNode();
112 $this->assertFalse($shouldThrowWhenNotUsingAttrAsKey);
113 $this->assertEquals($defaults, $tree->getDefaultValue());
114 } catch (InvalidDefinitionException $e) {
115 $this->assertTrue($shouldThrowWhenNotUsingAttrAsKey);
118 $node = new ArrayNodeDefinition('root');
120 ->useAttributeAsKey('attr')
121 ->addDefaultChildrenIfNoneSet($args)
126 $tree = $node->getNode();
127 $this->assertFalse($shouldThrowWhenUsingAttrAsKey);
128 $this->assertEquals($defaults, $tree->getDefaultValue());
129 } catch (InvalidDefinitionException $e) {
130 $this->assertTrue($shouldThrowWhenUsingAttrAsKey);
134 public function providePrototypedArrayNodeDefaults()
137 array(null, true, false, array(array())),
138 array(2, true, false, array(array(), array())),
139 array('2', false, true, array('2' => array())),
140 array('foo', false, true, array('foo' => array())),
141 array(array('foo'), false, true, array('foo' => array())),
142 array(array('foo', 'bar'), false, true, array('foo' => array(), 'bar' => array())),
146 public function testNestedPrototypedArrayNodes()
148 $nodeDefinition = new ArrayNodeDefinition('root');
150 ->addDefaultChildrenIfNoneSet()
154 $node = $nodeDefinition->getNode();
156 $this->assertInstanceOf('Symfony\Component\Config\Definition\PrototypedArrayNode', $node);
157 $this->assertInstanceOf('Symfony\Component\Config\Definition\PrototypedArrayNode', $node->getPrototype());
160 public function testEnabledNodeDefaults()
162 $node = new ArrayNodeDefinition('root');
166 ->scalarNode('foo')->defaultValue('bar')->end()
169 $this->assertEquals(array('enabled' => false, 'foo' => 'bar'), $node->getNode()->getDefaultValue());
173 * @dataProvider getEnableableNodeFixtures
175 public function testTrueEnableEnabledNode($expected, $config, $message)
177 $processor = new Processor();
178 $node = new ArrayNodeDefinition('root');
182 ->scalarNode('foo')->defaultValue('bar')->end()
187 $processor->process($node->getNode(), $config),
192 public function testCanBeDisabled()
194 $node = new ArrayNodeDefinition('root');
195 $node->canBeDisabled();
197 $this->assertTrue($this->getField($node, 'addDefaults'));
198 $this->assertEquals(array('enabled' => false), $this->getField($node, 'falseEquivalent'));
199 $this->assertEquals(array('enabled' => true), $this->getField($node, 'trueEquivalent'));
200 $this->assertEquals(array('enabled' => true), $this->getField($node, 'nullEquivalent'));
202 $nodeChildren = $this->getField($node, 'children');
203 $this->assertArrayHasKey('enabled', $nodeChildren);
205 $enabledNode = $nodeChildren['enabled'];
206 $this->assertTrue($this->getField($enabledNode, 'default'));
207 $this->assertTrue($this->getField($enabledNode, 'defaultValue'));
210 public function testIgnoreExtraKeys()
212 $node = new ArrayNodeDefinition('root');
214 $this->assertFalse($this->getField($node, 'ignoreExtraKeys'));
216 $result = $node->ignoreExtraKeys();
218 $this->assertEquals($node, $result);
219 $this->assertTrue($this->getField($node, 'ignoreExtraKeys'));
222 public function testNormalizeKeys()
224 $node = new ArrayNodeDefinition('root');
226 $this->assertTrue($this->getField($node, 'normalizeKeys'));
228 $result = $node->normalizeKeys(false);
230 $this->assertEquals($node, $result);
231 $this->assertFalse($this->getField($node, 'normalizeKeys'));
234 public function testPrototypeVariable()
236 $node = new ArrayNodeDefinition('root');
237 $this->assertEquals($node->prototype('variable'), $node->variablePrototype());
240 public function testPrototypeScalar()
242 $node = new ArrayNodeDefinition('root');
243 $this->assertEquals($node->prototype('scalar'), $node->scalarPrototype());
246 public function testPrototypeBoolean()
248 $node = new ArrayNodeDefinition('root');
249 $this->assertEquals($node->prototype('boolean'), $node->booleanPrototype());
252 public function testPrototypeInteger()
254 $node = new ArrayNodeDefinition('root');
255 $this->assertEquals($node->prototype('integer'), $node->integerPrototype());
258 public function testPrototypeFloat()
260 $node = new ArrayNodeDefinition('root');
261 $this->assertEquals($node->prototype('float'), $node->floatPrototype());
264 public function testPrototypeArray()
266 $node = new ArrayNodeDefinition('root');
267 $this->assertEquals($node->prototype('array'), $node->arrayPrototype());
270 public function testPrototypeEnum()
272 $node = new ArrayNodeDefinition('root');
273 $this->assertEquals($node->prototype('enum'), $node->enumPrototype());
276 public function getEnableableNodeFixtures()
279 array(array('enabled' => true, 'foo' => 'bar'), array(true), 'true enables an enableable node'),
280 array(array('enabled' => true, 'foo' => 'bar'), array(null), 'null enables an enableable node'),
281 array(array('enabled' => true, 'foo' => 'bar'), array(array('enabled' => true)), 'An enableable node can be enabled'),
282 array(array('enabled' => true, 'foo' => 'baz'), array(array('foo' => 'baz')), 'any configuration enables an enableable node'),
283 array(array('enabled' => false, 'foo' => 'baz'), array(array('foo' => 'baz', 'enabled' => false)), 'An enableable node can be disabled'),
284 array(array('enabled' => false, 'foo' => 'bar'), array(false), 'false disables an enableable node'),
288 public function testRequiresAtLeastOneElement()
290 $node = new ArrayNodeDefinition('root');
292 ->requiresAtLeastOneElement()
293 ->integerPrototype();
295 $node->getNode()->finalize(array(1));
297 $this->addToAssertionCount(1);
302 * @expectedDeprecation Using Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition::cannotBeEmpty() at path "root" has no effect, consider requiresAtLeastOneElement() instead. In 4.0 both methods will behave the same.
304 public function testCannotBeEmpty()
306 $node = new ArrayNodeDefinition('root');
309 ->integerPrototype();
311 $node->getNode()->finalize(array());
314 public function testSetDeprecated()
316 $node = new ArrayNodeDefinition('root');
319 ->arrayNode('foo')->setDeprecated('The "%path%" node is deprecated.')->end()
322 $deprecatedNode = $node->getNode()->getChildren()['foo'];
324 $this->assertTrue($deprecatedNode->isDeprecated());
325 $this->assertSame('The "root.foo" node is deprecated.', $deprecatedNode->getDeprecationMessage($deprecatedNode->getName(), $deprecatedNode->getPath()));
330 * @expectedDeprecation ->cannotBeEmpty() is not applicable to concrete nodes at path "root". In 4.0 it will throw an exception.
332 public function testCannotBeEmptyOnConcreteNode()
334 $node = new ArrayNodeDefinition('root');
335 $node->cannotBeEmpty();
337 $node->getNode()->finalize(array());
340 protected function getField($object, $field)
342 $reflection = new \ReflectionProperty($object, $field);
343 $reflection->setAccessible(true);
345 return $reflection->getValue($object);