This repository has been archived on 2023-08-20. You can view files and clone it, but cannot push or open issues or pull requests.
symfony/src/Symfony/Component/Form/Tests/SimpleFormTest.php

1143 lines
35 KiB
PHP
Raw Normal View History

<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests;
2018-07-26 10:03:18 +01:00
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\Form\Exception\TransformationFailedException;
use Symfony\Component\Form\Form;
use Symfony\Component\Form\FormConfigBuilder;
use Symfony\Component\Form\FormError;
2018-07-26 10:03:18 +01:00
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\Tests\Fixtures\FixedDataTransformer;
use Symfony\Component\Form\Tests\Fixtures\FixedFilterListener;
2018-07-26 10:03:18 +01:00
use Symfony\Component\PropertyAccess\PropertyPath;
class SimpleFormTest_Countable implements \Countable
{
private $count;
public function __construct($count)
{
$this->count = $count;
}
public function count()
{
return $this->count;
}
}
class SimpleFormTest_Traversable implements \IteratorAggregate
{
private $iterator;
public function __construct($count)
{
2019-01-16 09:39:14 +00:00
$this->iterator = new \ArrayIterator($count > 0 ? array_fill(0, $count, 'Foo') : []);
}
public function getIterator()
{
return $this->iterator;
}
}
class SimpleFormTest extends AbstractFormTest
{
2019-03-12 20:16:42 +00:00
/**
* @dataProvider provideFormNames
*/
public function testGetPropertyPath($name, $propertyPath)
{
$config = new FormConfigBuilder($name, null, $this->dispatcher);
$form = new Form($config);
2019-04-06 15:32:25 +01:00
$this->assertEquals($propertyPath, $form->getPropertyPath());
2019-03-12 20:16:42 +00:00
}
public function provideFormNames()
{
yield [null, null];
yield ['', null];
2019-04-06 15:32:25 +01:00
yield ['0', new PropertyPath('0')];
yield [0, new PropertyPath('0')];
yield ['name', new PropertyPath('name')];
2019-03-12 20:16:42 +00:00
}
public function testDataIsInitializedToConfiguredValue()
{
2019-01-16 09:39:14 +00:00
$model = new FixedDataTransformer([
'default' => 'foo',
2019-01-16 09:39:14 +00:00
]);
$view = new FixedDataTransformer([
'foo' => 'bar',
2019-01-16 09:39:14 +00:00
]);
$config = new FormConfigBuilder('name', null, $this->dispatcher);
$config->addViewTransformer($view);
$config->addModelTransformer($model);
$config->setData('default');
$form = new Form($config);
$this->assertSame('default', $form->getData());
$this->assertSame('foo', $form->getNormData());
$this->assertSame('bar', $form->getViewData());
}
/**
* @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
2019-03-12 20:16:42 +00:00
* @expectedExceptionMessage Unable to transform data for property path "name": No mapping for value "arg"
*/
public function testDataTransformationFailure()
{
2019-01-16 09:39:14 +00:00
$model = new FixedDataTransformer([
'default' => 'foo',
2019-01-16 09:39:14 +00:00
]);
$view = new FixedDataTransformer([
'foo' => 'bar',
2019-01-16 09:39:14 +00:00
]);
$config = new FormConfigBuilder('name', null, $this->dispatcher);
$config->addViewTransformer($view);
$config->addModelTransformer($model);
$config->setData('arg');
$form = new Form($config);
$form->getData();
}
// https://github.com/symfony/symfony/commit/d4f4038f6daf7cf88ca7c7ab089473cce5ebf7d8#commitcomment-1632879
public function testDataIsInitializedFromSubmit()
{
$mock = $this->getMockBuilder('\stdClass')
2019-01-16 09:39:14 +00:00
->setMethods(['preSetData', 'preSubmit'])
->getMock();
$mock->expects($this->at(0))
->method('preSetData');
$mock->expects($this->at(1))
->method('preSubmit');
$config = new FormConfigBuilder('name', null, $this->dispatcher);
2019-01-16 09:39:14 +00:00
$config->addEventListener(FormEvents::PRE_SET_DATA, [$mock, 'preSetData']);
$config->addEventListener(FormEvents::PRE_SUBMIT, [$mock, 'preSubmit']);
$form = new Form($config);
// no call to setData() or similar where the object would be
// initialized otherwise
$form->submit('foobar');
}
// https://github.com/symfony/symfony/pull/7789
public function testFalseIsConvertedToNull()
{
$mock = $this->getMockBuilder('\stdClass')
2019-01-16 09:39:14 +00:00
->setMethods(['preSubmit'])
->getMock();
$mock->expects($this->once())
->method('preSubmit')
->with($this->callback(function ($event) {
return null === $event->getData();
}));
$config = new FormConfigBuilder('name', null, $this->dispatcher);
2019-01-16 09:39:14 +00:00
$config->addEventListener(FormEvents::PRE_SUBMIT, [$mock, 'preSubmit']);
$form = new Form($config);
$form->submit(false);
$this->assertTrue($form->isValid());
$this->assertNull($form->getData());
}
/**
* @expectedException \Symfony\Component\Form\Exception\AlreadySubmittedException
*/
public function testSubmitThrowsExceptionIfAlreadySubmitted()
{
2019-01-16 09:39:14 +00:00
$this->form->submit([]);
$this->form->submit([]);
}
public function testSubmitIsIgnoredIfDisabled()
{
$form = $this->getBuilder()
->setDisabled(true)
->setData('initial')
->getForm();
$form->submit('new');
$this->assertEquals('initial', $form->getData());
$this->assertTrue($form->isSubmitted());
}
public function testNeverRequiredIfParentNotRequired()
{
$parent = $this->getBuilder()->setRequired(false)->getForm();
$child = $this->getBuilder()->setRequired(true)->getForm();
$child->setParent($parent);
$this->assertFalse($child->isRequired());
}
public function testRequired()
{
$parent = $this->getBuilder()->setRequired(true)->getForm();
$child = $this->getBuilder()->setRequired(true)->getForm();
$child->setParent($parent);
$this->assertTrue($child->isRequired());
}
public function testNotRequired()
{
$parent = $this->getBuilder()->setRequired(true)->getForm();
$child = $this->getBuilder()->setRequired(false)->getForm();
$child->setParent($parent);
$this->assertFalse($child->isRequired());
}
/**
* @dataProvider getDisabledStates
*/
public function testAlwaysDisabledIfParentDisabled($parentDisabled, $disabled, $result)
{
$parent = $this->getBuilder()->setDisabled($parentDisabled)->getForm();
$child = $this->getBuilder()->setDisabled($disabled)->getForm();
$child->setParent($parent);
$this->assertSame($result, $child->isDisabled());
}
public function getDisabledStates()
{
2019-01-16 09:39:14 +00:00
return [
// parent, button, result
2019-01-16 09:39:14 +00:00
[true, true, true],
[true, false, true],
[false, true, true],
[false, false, false],
];
}
public function testGetRootReturnsRootOfParent()
{
$root = $this->createForm();
$parent = $this->createForm();
$parent->setParent($root);
$this->form->setParent($parent);
$this->assertSame($root, $this->form->getRoot());
}
public function testGetRootReturnsSelfIfNoParent()
{
$this->assertSame($this->form, $this->form->getRoot());
}
public function testEmptyIfEmptyArray()
{
2019-01-16 09:39:14 +00:00
$this->form->setData([]);
$this->assertTrue($this->form->isEmpty());
}
public function testEmptyIfEmptyCountable()
{
$this->form = new Form(new FormConfigBuilder('name', __NAMESPACE__.'\SimpleFormTest_Countable', $this->dispatcher));
$this->form->setData(new SimpleFormTest_Countable(0));
$this->assertTrue($this->form->isEmpty());
}
public function testNotEmptyIfFilledCountable()
{
$this->form = new Form(new FormConfigBuilder('name', __NAMESPACE__.'\SimpleFormTest_Countable', $this->dispatcher));
$this->form->setData(new SimpleFormTest_Countable(1));
$this->assertFalse($this->form->isEmpty());
}
public function testEmptyIfEmptyTraversable()
{
$this->form = new Form(new FormConfigBuilder('name', __NAMESPACE__.'\SimpleFormTest_Traversable', $this->dispatcher));
$this->form->setData(new SimpleFormTest_Traversable(0));
$this->assertTrue($this->form->isEmpty());
}
public function testNotEmptyIfFilledTraversable()
{
$this->form = new Form(new FormConfigBuilder('name', __NAMESPACE__.'\SimpleFormTest_Traversable', $this->dispatcher));
$this->form->setData(new SimpleFormTest_Traversable(1));
$this->assertFalse($this->form->isEmpty());
}
public function testEmptyIfNull()
{
$this->form->setData(null);
$this->assertTrue($this->form->isEmpty());
}
public function testEmptyIfEmptyString()
{
$this->form->setData('');
$this->assertTrue($this->form->isEmpty());
}
public function testNotEmptyIfText()
{
$this->form->setData('foobar');
$this->assertFalse($this->form->isEmpty());
}
public function testValidIfSubmitted()
{
$form = $this->getBuilder()->getForm();
$form->submit('foobar');
$this->assertTrue($form->isValid());
}
public function testValidIfSubmittedAndDisabled()
{
$form = $this->getBuilder()->setDisabled(true)->getForm();
$form->submit('foobar');
$this->assertTrue($form->isValid());
}
/**
* @group legacy
* @expectedDeprecation Call Form::isValid() with an unsubmitted form %s.
*/
public function testNotValidIfNotSubmitted()
{
$this->assertFalse($this->form->isValid());
}
public function testNotValidIfErrors()
{
$form = $this->getBuilder()->getForm();
$form->submit('foobar');
$form->addError(new FormError('Error!'));
$this->assertFalse($form->isValid());
}
public function testHasErrors()
{
$this->form->addError(new FormError('Error!'));
$this->assertCount(1, $this->form->getErrors());
}
public function testHasNoErrors()
{
$this->assertCount(0, $this->form->getErrors());
}
/**
* @expectedException \Symfony\Component\Form\Exception\AlreadySubmittedException
*/
public function testSetParentThrowsExceptionIfAlreadySubmitted()
{
2019-01-16 09:39:14 +00:00
$this->form->submit([]);
$this->form->setParent($this->getBuilder('parent')->getForm());
}
public function testSubmitted()
{
$form = $this->getBuilder()->getForm();
$form->submit('foobar');
$this->assertTrue($form->isSubmitted());
}
public function testNotSubmitted()
{
$this->assertFalse($this->form->isSubmitted());
}
/**
* @expectedException \Symfony\Component\Form\Exception\AlreadySubmittedException
*/
public function testSetDataThrowsExceptionIfAlreadySubmitted()
{
2019-01-16 09:39:14 +00:00
$this->form->submit([]);
$this->form->setData(null);
}
public function testSetDataClonesObjectIfNotByReference()
{
$data = new \stdClass();
$form = $this->getBuilder('name', null, '\stdClass')->setByReference(false)->getForm();
$form->setData($data);
$this->assertNotSame($data, $form->getData());
$this->assertEquals($data, $form->getData());
}
public function testSetDataDoesNotCloneObjectIfByReference()
{
$data = new \stdClass();
$form = $this->getBuilder('name', null, '\stdClass')->setByReference(true)->getForm();
$form->setData($data);
$this->assertSame($data, $form->getData());
}
public function testSetDataExecutesTransformationChain()
{
// use real event dispatcher now
$form = $this->getBuilder('name', new EventDispatcher())
2019-01-16 09:39:14 +00:00
->addEventSubscriber(new FixedFilterListener([
'preSetData' => [
'app' => 'filtered',
2019-01-16 09:39:14 +00:00
],
]))
->addModelTransformer(new FixedDataTransformer([
'' => '',
'filtered' => 'norm',
2019-01-16 09:39:14 +00:00
]))
->addViewTransformer(new FixedDataTransformer([
'' => '',
'norm' => 'client',
2019-01-16 09:39:14 +00:00
]))
->getForm();
$form->setData('app');
$this->assertEquals('filtered', $form->getData());
$this->assertEquals('norm', $form->getNormData());
$this->assertEquals('client', $form->getViewData());
}
public function testSetDataExecutesViewTransformersInOrder()
{
$form = $this->getBuilder()
2019-01-16 09:39:14 +00:00
->addViewTransformer(new FixedDataTransformer([
'' => '',
'first' => 'second',
2019-01-16 09:39:14 +00:00
]))
->addViewTransformer(new FixedDataTransformer([
'' => '',
'second' => 'third',
2019-01-16 09:39:14 +00:00
]))
->getForm();
$form->setData('first');
$this->assertEquals('third', $form->getViewData());
}
public function testSetDataExecutesModelTransformersInReverseOrder()
{
$form = $this->getBuilder()
2019-01-16 09:39:14 +00:00
->addModelTransformer(new FixedDataTransformer([
'' => '',
'second' => 'third',
2019-01-16 09:39:14 +00:00
]))
->addModelTransformer(new FixedDataTransformer([
'' => '',
'first' => 'second',
2019-01-16 09:39:14 +00:00
]))
->getForm();
$form->setData('first');
$this->assertEquals('third', $form->getNormData());
}
/*
* When there is no data transformer, the data must have the same format
* in all three representations
*/
public function testSetDataConvertsScalarToStringIfNoTransformer()
{
$form = $this->getBuilder()->getForm();
$form->setData(1);
$this->assertSame('1', $form->getData());
$this->assertSame('1', $form->getNormData());
$this->assertSame('1', $form->getViewData());
}
/*
* Data in client format should, if possible, always be a string to
* facilitate differentiation between '0' and ''
*/
public function testSetDataConvertsScalarToStringIfOnlyModelTransformer()
{
$form = $this->getBuilder()
2019-01-16 09:39:14 +00:00
->addModelTransformer(new FixedDataTransformer([
'' => '',
1 => 23,
2019-01-16 09:39:14 +00:00
]))
->getForm();
$form->setData(1);
$this->assertSame(1, $form->getData());
$this->assertSame(23, $form->getNormData());
$this->assertSame('23', $form->getViewData());
}
/*
* NULL remains NULL in app and norm format to remove the need to treat
2012-07-16 20:54:46 +01:00
* empty values and NULL explicitly in the application
*/
public function testSetDataConvertsNullToStringIfNoTransformer()
{
$form = $this->getBuilder()->getForm();
$form->setData(null);
$this->assertNull($form->getData());
$this->assertNull($form->getNormData());
$this->assertSame('', $form->getViewData());
}
public function testSetDataIsIgnoredIfDataIsLocked()
{
$form = $this->getBuilder()
->setData('default')
->setDataLocked(true)
->getForm();
$form->setData('foobar');
$this->assertSame('default', $form->getData());
}
public function testPreSetDataChangesDataIfDataIsLocked()
2017-02-01 21:47:52 +00:00
{
$config = new FormConfigBuilder('name', null, $this->dispatcher);
$config
->setData('default')
->setDataLocked(true)
->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) {
2017-02-01 21:47:52 +00:00
$event->setData('foobar');
});
$form = new Form($config);
$this->assertSame('foobar', $form->getData());
$this->assertSame('foobar', $form->getNormData());
$this->assertSame('foobar', $form->getViewData());
2017-02-01 21:47:52 +00:00
}
public function testSubmitConvertsEmptyToNullIfNoTransformer()
{
$form = $this->getBuilder()->getForm();
$form->submit('');
$this->assertNull($form->getData());
$this->assertNull($form->getNormData());
$this->assertSame('', $form->getViewData());
}
public function testSubmitExecutesTransformationChain()
{
// use real event dispatcher now
$form = $this->getBuilder('name', new EventDispatcher())
2019-01-16 09:39:14 +00:00
->addEventSubscriber(new FixedFilterListener([
'preSubmit' => [
'client' => 'filteredclient',
2019-01-16 09:39:14 +00:00
],
'onSubmit' => [
'norm' => 'filterednorm',
2019-01-16 09:39:14 +00:00
],
]))
->addViewTransformer(new FixedDataTransformer([
'' => '',
// direction is reversed!
'norm' => 'filteredclient',
2014-09-21 19:53:12 +01:00
'filterednorm' => 'cleanedclient',
2019-01-16 09:39:14 +00:00
]))
->addModelTransformer(new FixedDataTransformer([
'' => '',
// direction is reversed!
'app' => 'filterednorm',
2019-01-16 09:39:14 +00:00
]))
->getForm();
$form->submit('client');
$this->assertEquals('app', $form->getData());
$this->assertEquals('filterednorm', $form->getNormData());
$this->assertEquals('cleanedclient', $form->getViewData());
}
public function testSubmitExecutesViewTransformersInReverseOrder()
{
$form = $this->getBuilder()
2019-01-16 09:39:14 +00:00
->addViewTransformer(new FixedDataTransformer([
'' => '',
'third' => 'second',
2019-01-16 09:39:14 +00:00
]))
->addViewTransformer(new FixedDataTransformer([
'' => '',
'second' => 'first',
2019-01-16 09:39:14 +00:00
]))
->getForm();
$form->submit('first');
$this->assertEquals('third', $form->getNormData());
}
public function testSubmitExecutesModelTransformersInOrder()
{
$form = $this->getBuilder()
2019-01-16 09:39:14 +00:00
->addModelTransformer(new FixedDataTransformer([
'' => '',
'second' => 'first',
2019-01-16 09:39:14 +00:00
]))
->addModelTransformer(new FixedDataTransformer([
'' => '',
'third' => 'second',
2019-01-16 09:39:14 +00:00
]))
->getForm();
$form->submit('first');
$this->assertEquals('third', $form->getData());
}
public function testSynchronizedByDefault()
{
$this->assertTrue($this->form->isSynchronized());
}
public function testSynchronizedAfterSubmission()
{
$this->form->submit('foobar');
$this->assertTrue($this->form->isSynchronized());
}
public function testNotSynchronizedIfViewReverseTransformationFailed()
{
$transformer = $this->getDataTransformer();
$transformer->expects($this->once())
->method('reverseTransform')
2018-12-22 19:54:00 +00:00
->willThrowException(new TransformationFailedException());
$form = $this->getBuilder()
->addViewTransformer($transformer)
->getForm();
$form->submit('foobar');
$this->assertFalse($form->isSynchronized());
}
public function testNotSynchronizedIfModelReverseTransformationFailed()
{
$transformer = $this->getDataTransformer();
$transformer->expects($this->once())
->method('reverseTransform')
2018-12-22 19:54:00 +00:00
->willThrowException(new TransformationFailedException());
$form = $this->getBuilder()
->addModelTransformer($transformer)
->getForm();
$form->submit('foobar');
$this->assertFalse($form->isSynchronized());
}
public function testEmptyDataCreatedBeforeTransforming()
{
$form = $this->getBuilder()
->setEmptyData('foo')
2019-01-16 09:39:14 +00:00
->addViewTransformer(new FixedDataTransformer([
2016-10-30 09:34:06 +00:00
'' => '',
// direction is reversed!
'bar' => 'foo',
2019-01-16 09:39:14 +00:00
]))
->getForm();
$form->submit('');
$this->assertEquals('bar', $form->getData());
}
public function testEmptyDataFromClosure()
{
$form = $this->getBuilder()
2014-12-03 22:04:33 +00:00
->setEmptyData(function ($form) {
2016-10-30 09:34:06 +00:00
// the form instance is passed to the closure to allow use
// of form data when creating the empty value
$this->assertInstanceOf('Symfony\Component\Form\FormInterface', $form);
2016-10-30 09:34:06 +00:00
return 'foo';
})
2019-01-16 09:39:14 +00:00
->addViewTransformer(new FixedDataTransformer([
2016-10-30 09:34:06 +00:00
'' => '',
// direction is reversed!
'bar' => 'foo',
2019-01-16 09:39:14 +00:00
]))
->getForm();
$form->submit('');
$this->assertEquals('bar', $form->getData());
}
public function testSubmitResetsErrors()
{
$this->form->addError(new FormError('Error!'));
$this->form->submit('foobar');
$this->assertCount(0, $this->form->getErrors());
}
public function testCreateView()
{
2016-12-19 09:02:29 +00:00
$type = $this->getMockBuilder('Symfony\Component\Form\ResolvedFormTypeInterface')->getMock();
$view = $this->getMockBuilder('Symfony\Component\Form\FormView')->getMock();
$form = $this->getBuilder()->setType($type)->getForm();
$type->expects($this->once())
->method('createView')
->with($form)
->willReturn($view);
$this->assertSame($view, $form->createView());
}
public function testCreateViewWithParent()
{
2016-12-19 09:02:29 +00:00
$type = $this->getMockBuilder('Symfony\Component\Form\ResolvedFormTypeInterface')->getMock();
$view = $this->getMockBuilder('Symfony\Component\Form\FormView')->getMock();
$parentType = $this->getMockBuilder('Symfony\Component\Form\ResolvedFormTypeInterface')->getMock();
$parentForm = $this->getBuilder()->setType($parentType)->getForm();
2016-12-19 09:02:29 +00:00
$parentView = $this->getMockBuilder('Symfony\Component\Form\FormView')->getMock();
$form = $this->getBuilder()->setType($type)->getForm();
$form->setParent($parentForm);
$parentType->expects($this->once())
->method('createView')
->willReturn($parentView);
$type->expects($this->once())
->method('createView')
->with($form, $parentView)
->willReturn($view);
$this->assertSame($view, $form->createView());
}
public function testCreateViewWithExplicitParent()
{
2016-12-19 09:02:29 +00:00
$type = $this->getMockBuilder('Symfony\Component\Form\ResolvedFormTypeInterface')->getMock();
$view = $this->getMockBuilder('Symfony\Component\Form\FormView')->getMock();
$parentView = $this->getMockBuilder('Symfony\Component\Form\FormView')->getMock();
$form = $this->getBuilder()->setType($type)->getForm();
$type->expects($this->once())
->method('createView')
->with($form, $parentView)
->willReturn($view);
$this->assertSame($view, $form->createView($parentView));
}
public function testFormCanHaveEmptyName()
{
$form = $this->getBuilder('')->getForm();
$this->assertEquals('', $form->getName());
}
2012-08-26 20:12:48 +01:00
public function testSetNullParentWorksWithEmptyName()
{
$form = $this->getBuilder('')->getForm();
$form->setParent(null);
$this->assertNull($form->getParent());
}
/**
* @expectedException \Symfony\Component\Form\Exception\LogicException
* @expectedExceptionMessage A form with an empty name cannot have a parent form.
*/
public function testFormCannotHaveEmptyNameNotInRootLevel()
{
$this->getBuilder()
->setCompound(true)
->setDataMapper($this->getDataMapper())
->add($this->getBuilder(''))
->getForm();
}
public function testGetPropertyPathReturnsConfiguredPath()
{
$form = $this->getBuilder()->setPropertyPath('address.street')->getForm();
$this->assertEquals(new PropertyPath('address.street'), $form->getPropertyPath());
}
// see https://github.com/symfony/symfony/issues/3903
public function testGetPropertyPathDefaultsToNameIfParentHasDataClass()
{
$parent = $this->getBuilder(null, null, 'stdClass')
->setCompound(true)
->setDataMapper($this->getDataMapper())
->getForm();
$form = $this->getBuilder('name')->getForm();
$parent->add($form);
$this->assertEquals(new PropertyPath('name'), $form->getPropertyPath());
}
// see https://github.com/symfony/symfony/issues/3903
public function testGetPropertyPathDefaultsToIndexedNameIfParentDataClassIsNull()
{
$parent = $this->getBuilder()
->setCompound(true)
->setDataMapper($this->getDataMapper())
->getForm();
$form = $this->getBuilder('name')->getForm();
$parent->add($form);
$this->assertEquals(new PropertyPath('[name]'), $form->getPropertyPath());
}
public function testGetPropertyPathDefaultsToNameIfFirstParentWithoutInheritDataHasDataClass()
{
$grandParent = $this->getBuilder(null, null, 'stdClass')
->setCompound(true)
->setDataMapper($this->getDataMapper())
->getForm();
$parent = $this->getBuilder()
->setCompound(true)
->setDataMapper($this->getDataMapper())
->setInheritData(true)
->getForm();
$form = $this->getBuilder('name')->getForm();
$grandParent->add($parent);
$parent->add($form);
$this->assertEquals(new PropertyPath('name'), $form->getPropertyPath());
}
public function testGetPropertyPathDefaultsToIndexedNameIfDataClassOfFirstParentWithoutInheritDataIsNull()
{
$grandParent = $this->getBuilder()
->setCompound(true)
->setDataMapper($this->getDataMapper())
->getForm();
$parent = $this->getBuilder()
->setCompound(true)
->setDataMapper($this->getDataMapper())
->setInheritData(true)
->getForm();
$form = $this->getBuilder('name')->getForm();
$grandParent->add($parent);
$parent->add($form);
$this->assertEquals(new PropertyPath('[name]'), $form->getPropertyPath());
}
public function testViewDataMayBeObjectIfDataClassIsNull()
{
$object = new \stdClass();
$config = new FormConfigBuilder('name', null, $this->dispatcher);
2019-01-16 09:39:14 +00:00
$config->addViewTransformer(new FixedDataTransformer([
'' => '',
'foo' => $object,
2019-01-16 09:39:14 +00:00
]));
$form = new Form($config);
$form->setData('foo');
$this->assertSame($object, $form->getViewData());
}
public function testViewDataMayBeArrayAccessIfDataClassIsNull()
{
2016-12-19 09:02:29 +00:00
$arrayAccess = $this->getMockBuilder('\ArrayAccess')->getMock();
$config = new FormConfigBuilder('name', null, $this->dispatcher);
2019-01-16 09:39:14 +00:00
$config->addViewTransformer(new FixedDataTransformer([
'' => '',
'foo' => $arrayAccess,
2019-01-16 09:39:14 +00:00
]));
$form = new Form($config);
$form->setData('foo');
$this->assertSame($arrayAccess, $form->getViewData());
}
/**
* @expectedException \Symfony\Component\Form\Exception\LogicException
*/
public function testViewDataMustBeObjectIfDataClassIsSet()
{
$config = new FormConfigBuilder('name', 'stdClass', $this->dispatcher);
2019-01-16 09:39:14 +00:00
$config->addViewTransformer(new FixedDataTransformer([
'' => '',
2019-01-16 09:39:14 +00:00
'foo' => ['bar' => 'baz'],
]));
$form = new Form($config);
$form->setData('foo');
}
/**
* @expectedException \Symfony\Component\Form\Exception\RuntimeException
* @expectedExceptionMessage A cycle was detected. Listeners to the PRE_SET_DATA event must not call setData(). You should call setData() on the FormEvent object instead.
*/
public function testSetDataCannotInvokeItself()
{
// Cycle detection to prevent endless loops
$config = new FormConfigBuilder('name', 'stdClass', $this->dispatcher);
$config->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) {
$event->getForm()->setData('bar');
});
$form = new Form($config);
$form->setData('foo');
}
public function testSubmittingWrongDataIsIgnored()
{
2017-03-18 09:10:35 +00:00
$called = 0;
$child = $this->getBuilder('child', $this->dispatcher);
2017-03-18 09:10:35 +00:00
$child->addEventListener(FormEvents::PRE_SUBMIT, function () use (&$called) {
++$called;
});
$parent = $this->getBuilder('parent', new EventDispatcher())
->setCompound(true)
->setDataMapper($this->getDataMapper())
->add($child)
->getForm();
$parent->submit('not-an-array');
2017-03-18 09:10:35 +00:00
$this->assertSame(0, $called, 'PRE_SUBMIT event listeners are not called for wrong data');
}
public function testHandleRequestForwardsToRequestHandler()
2012-12-30 15:38:36 +00:00
{
2016-12-19 09:02:29 +00:00
$handler = $this->getMockBuilder('Symfony\Component\Form\RequestHandlerInterface')->getMock();
2012-12-30 15:38:36 +00:00
$form = $this->getBuilder()
->setRequestHandler($handler)
2012-12-30 15:38:36 +00:00
->getForm();
$handler->expects($this->once())
->method('handleRequest')
2012-12-30 15:38:36 +00:00
->with($this->identicalTo($form), 'REQUEST');
$this->assertSame($form, $form->handleRequest('REQUEST'));
2012-12-30 15:38:36 +00:00
}
public function testFormInheritsParentData()
{
$child = $this->getBuilder('child')
->setInheritData(true);
$parent = $this->getBuilder('parent')
->setCompound(true)
->setDataMapper($this->getDataMapper())
->setData('foo')
2019-01-16 09:39:14 +00:00
->addModelTransformer(new FixedDataTransformer([
'foo' => 'norm[foo]',
2019-01-16 09:39:14 +00:00
]))
->addViewTransformer(new FixedDataTransformer([
'norm[foo]' => 'view[foo]',
2019-01-16 09:39:14 +00:00
]))
->add($child)
->getForm();
$this->assertSame('foo', $parent->get('child')->getData());
$this->assertSame('norm[foo]', $parent->get('child')->getNormData());
$this->assertSame('view[foo]', $parent->get('child')->getViewData());
}
/**
* @expectedException \Symfony\Component\Form\Exception\RuntimeException
*/
public function testInheritDataDisallowsSetData()
{
$form = $this->getBuilder()
->setInheritData(true)
->getForm();
$form->setData('foo');
}
/**
* @expectedException \Symfony\Component\Form\Exception\RuntimeException
*/
public function testGetDataRequiresParentToBeSetIfInheritData()
{
$form = $this->getBuilder()
->setInheritData(true)
->getForm();
$form->getData();
}
/**
* @expectedException \Symfony\Component\Form\Exception\RuntimeException
*/
public function testGetNormDataRequiresParentToBeSetIfInheritData()
{
$form = $this->getBuilder()
->setInheritData(true)
->getForm();
$form->getNormData();
}
/**
* @expectedException \Symfony\Component\Form\Exception\RuntimeException
*/
public function testGetViewDataRequiresParentToBeSetIfInheritData()
{
$form = $this->getBuilder()
->setInheritData(true)
->getForm();
$form->getViewData();
}
public function testPostSubmitDataIsNullIfInheritData()
{
$form = $this->getBuilder()
2014-12-03 22:04:33 +00:00
->addEventListener(FormEvents::POST_SUBMIT, function (FormEvent $event) {
$this->assertNull($event->getData());
})
->setInheritData(true)
->getForm();
$form->submit('foo');
}
public function testSubmitIsNeverFiredIfInheritData()
{
2017-03-18 09:10:35 +00:00
$called = 0;
$form = $this->getBuilder()
2017-03-18 09:10:35 +00:00
->addEventListener(FormEvents::SUBMIT, function () use (&$called) {
++$called;
})
->setInheritData(true)
->getForm();
$form->submit('foo');
2017-03-18 09:10:35 +00:00
$this->assertSame(0, $called, 'The SUBMIT event is not fired when data are inherited from the parent form');
}
public function testInitializeSetsDefaultData()
{
$config = $this->getBuilder()->setData('DEFAULT')->getFormConfig();
2019-01-16 09:39:14 +00:00
$form = $this->getMockBuilder('Symfony\Component\Form\Form')->setMethods(['setData'])->setConstructorArgs([$config])->getMock();
$form->expects($this->once())
->method('setData')
->with($this->identicalTo('DEFAULT'));
/* @var Form $form */
$form->initialize();
}
/**
* @expectedException \Symfony\Component\Form\Exception\RuntimeException
*/
public function testInitializeFailsIfParent()
{
$parent = $this->getBuilder()->setRequired(false)->getForm();
$child = $this->getBuilder()->setRequired(true)->getForm();
$child->setParent($parent);
$child->initialize();
}
/**
* @expectedException \Symfony\Component\Form\Exception\RuntimeException
* @expectedExceptionMessage A cycle was detected. Listeners to the PRE_SET_DATA event must not call getData() if the form data has not already been set. You should call getData() on the FormEvent object instead.
*/
public function testCannotCallGetDataInPreSetDataListenerIfDataHasNotAlreadyBeenSet()
{
$config = new FormConfigBuilder('name', 'stdClass', $this->dispatcher);
$config->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) {
$event->getForm()->getData();
});
$form = new Form($config);
$form->setData('foo');
}
/**
* @expectedException \Symfony\Component\Form\Exception\RuntimeException
* @expectedExceptionMessage A cycle was detected. Listeners to the PRE_SET_DATA event must not call getNormData() if the form data has not already been set.
*/
public function testCannotCallGetNormDataInPreSetDataListener()
{
$config = new FormConfigBuilder('name', 'stdClass', $this->dispatcher);
$config->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) {
$event->getForm()->getNormData();
});
$form = new Form($config);
$form->setData('foo');
}
/**
* @expectedException \Symfony\Component\Form\Exception\RuntimeException
* @expectedExceptionMessage A cycle was detected. Listeners to the PRE_SET_DATA event must not call getViewData() if the form data has not already been set.
*/
public function testCannotCallGetViewDataInPreSetDataListener()
{
$config = new FormConfigBuilder('name', 'stdClass', $this->dispatcher);
$config->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) {
$event->getForm()->getViewData();
});
$form = new Form($config);
$form->setData('foo');
}
protected function createForm()
{
return $this->getBuilder()->getForm();
}
}