|
13 | 13 |
|
14 | 14 | use PHPUnit\Framework\MockObject\MockObject;
|
15 | 15 | use PHPUnit\Framework\TestCase;
|
| 16 | +use Symfony\Component\EventDispatcher\EventDispatcher; |
| 17 | +use Symfony\Component\Form\Extension\Core\CoreExtension; |
| 18 | +use Symfony\Component\Form\Extension\Core\DataMapper\PropertyPathMapper; |
| 19 | +use Symfony\Component\Form\Extension\Core\Type\CollectionType; |
| 20 | +use Symfony\Component\Form\Extension\Core\Type\FormType; |
| 21 | +use Symfony\Component\Form\Extension\Core\Type\TextType; |
16 | 22 | use Symfony\Component\Form\Extension\DataCollector\FormDataCollector;
|
17 | 23 | use Symfony\Component\Form\Form;
|
18 | 24 | use Symfony\Component\Form\FormBuilder;
|
| 25 | +use Symfony\Component\Form\FormFactory; |
| 26 | +use Symfony\Component\Form\FormInterface; |
| 27 | +use Symfony\Component\Form\FormRegistry; |
19 | 28 | use Symfony\Component\Form\FormView;
|
| 29 | +use Symfony\Component\Form\ResolvedFormTypeFactory; |
20 | 30 |
|
21 | 31 | class FormDataCollectorTest extends TestCase
|
22 | 32 | {
|
@@ -69,9 +79,9 @@ protected function setUp()
|
69 | 79 | {
|
70 | 80 | $this->dataExtractor = $this->getMockBuilder('Symfony\Component\Form\Extension\DataCollector\FormDataExtractorInterface')->getMock();
|
71 | 81 | $this->dataCollector = new FormDataCollector($this->dataExtractor);
|
72 |
| - $this->dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcherInterface')->getMock(); |
73 |
| - $this->factory = $this->getMockBuilder('Symfony\Component\Form\FormFactoryInterface')->getMock(); |
74 |
| - $this->dataMapper = $this->getMockBuilder('Symfony\Component\Form\DataMapperInterface')->getMock(); |
| 82 | + $this->dispatcher = new EventDispatcher(); |
| 83 | + $this->factory = new FormFactory(new FormRegistry([new CoreExtension()], new ResolvedFormTypeFactory())); |
| 84 | + $this->dataMapper = new PropertyPathMapper(); |
75 | 85 | $this->form = $this->createForm('name');
|
76 | 86 | $this->childForm = $this->createForm('child');
|
77 | 87 | $this->view = new FormView();
|
@@ -726,6 +736,56 @@ public function testReset()
|
726 | 736 | );
|
727 | 737 | }
|
728 | 738 |
|
| 739 | + public function testCollectMissingDataFromChildFormAddedOnFormEvents() |
| 740 | + { |
| 741 | + $form = $this->factory->createNamedBuilder('root', FormType::class, ['items' => null]) |
| 742 | + ->add('items', CollectionType::class, [ |
| 743 | + 'entry_type' => TextType::class, |
| 744 | + 'allow_add' => true, |
| 745 | + // data is locked and modelData (null) is different to the |
| 746 | + // configured data, so modifications of the configured data |
| 747 | + // won't be allowed at this point. It also means *_SET_DATA |
| 748 | + // events won't dispatched either. Therefore, no child form |
| 749 | + // is created during the mapping of data to the form. |
| 750 | + 'data' => ['foo'], |
| 751 | + ]) |
| 752 | + ->getForm() |
| 753 | + ; |
| 754 | + $this->dataExtractor->expects($extractConfiguration = $this->exactly(4)) |
| 755 | + ->method('extractConfiguration') |
| 756 | + ->willReturn([]) |
| 757 | + ; |
| 758 | + $this->dataExtractor->expects($extractDefaultData = $this->exactly(4)) |
| 759 | + ->method('extractDefaultData') |
| 760 | + ->willReturnCallback(static function (FormInterface $form) { |
| 761 | + // this simulate the call in extractDefaultData() method |
| 762 | + // where (if defaultDataSet is false) it fires *_SET_DATA |
| 763 | + // events, adding the form related to the configured data |
| 764 | + $form->getNormData(); |
| 765 | + |
| 766 | + return []; |
| 767 | + }) |
| 768 | + ; |
| 769 | + $this->dataExtractor->expects($this->exactly(4)) |
| 770 | + ->method('extractSubmittedData') |
| 771 | + ->willReturn([]) |
| 772 | + ; |
| 773 | + |
| 774 | + $this->dataCollector->collectConfiguration($form); |
| 775 | + $this->assertSame(2, $extractConfiguration->getInvocationCount(), 'only "root" and "items" forms were collected, the "items" children do not exist yet.'); |
| 776 | + |
| 777 | + $this->dataCollector->collectDefaultData($form); |
| 778 | + $this->assertSame(3, $extractConfiguration->getInvocationCount(), 'extracted missing configuration of the "items" children ["0" => foo].'); |
| 779 | + $this->assertSame(3, $extractDefaultData->getInvocationCount()); |
| 780 | + $this->assertSame(['foo'], $form->get('items')->getData()); |
| 781 | + |
| 782 | + $form->submit(['items' => ['foo', 'bar']]); |
| 783 | + $this->dataCollector->collectSubmittedData($form); |
| 784 | + $this->assertSame(4, $extractConfiguration->getInvocationCount(), 'extracted missing configuration of the "items" children ["1" => bar].'); |
| 785 | + $this->assertSame(4, $extractDefaultData->getInvocationCount(), 'extracted missing default data of the "items" children ["1" => bar].'); |
| 786 | + $this->assertSame(['foo', 'bar'], $form->get('items')->getData()); |
| 787 | + } |
| 788 | + |
729 | 789 | private function createForm($name)
|
730 | 790 | {
|
731 | 791 | $builder = new FormBuilder($name, null, $this->dispatcher, $this->factory);
|
|
0 commit comments