From 4f5b44bd3bd490309eb2ba7b44df4769816ba729 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20L=C5=93uillet?= Date: Sat, 3 Aug 2013 19:26:54 +0200 Subject: twig implementation --- .../Component/Form/Tests/AbstractDivLayoutTest.php | 732 ++++++++ .../Component/Form/Tests/AbstractExtensionTest.php | 43 + .../Component/Form/Tests/AbstractFormTest.php | 147 ++ .../Component/Form/Tests/AbstractLayoutTest.php | 1876 ++++++++++++++++++++ .../Form/Tests/AbstractRequestHandlerTest.php | 280 +++ .../Form/Tests/AbstractTableLayoutTest.php | 509 ++++++ .../Form/Tests/CompoundFormPerformanceTest.php | 48 + .../Component/Form/Tests/CompoundFormTest.php | 759 ++++++++ .../Extension/Core/ChoiceList/ChoiceListTest.php | 200 +++ .../Core/ChoiceList/LazyChoiceListTest.php | 116 ++ .../Core/ChoiceList/ObjectChoiceListTest.php | 212 +++ .../Core/ChoiceList/SimpleChoiceListTest.php | 188 ++ .../Core/DataMapper/PropertyPathMapperTest.php | 319 ++++ .../ArrayToPartsTransformerTest.php | 149 ++ .../BooleanToStringTransformerTest.php | 60 + .../ChoiceToValueTransformerTest.php | 76 + .../ChoicesToValuesTransformerTest.php | 76 + .../DataTransformer/DataTransformerChainTest.php | 53 + .../Core/DataTransformer/DateTimeTestCase.php | 20 + .../DateTimeToArrayTransformerTest.php | 512 ++++++ .../DateTimeToLocalizedStringTransformerTest.php | 275 +++ .../DateTimeToRfc3339TransformerTest.php | 132 ++ .../DateTimeToStringTransformerTest.php | 181 ++ .../DateTimeToTimestampTransformerTest.php | 104 ++ .../IntegerToLocalizedStringTransformerTest.php | 115 ++ .../MoneyToLocalizedStringTransformerTest.php | 74 + .../NumberToLocalizedStringTransformerTest.php | 393 ++++ .../PercentToLocalizedStringTransformerTest.php | 114 ++ .../ValueToDuplicatesTransformerTest.php | 120 ++ .../EventListener/FixRadioInputListenerTest.php | 106 ++ .../EventListener/FixUrlProtocolListenerTest.php | 61 + .../Core/EventListener/Fixtures/randomhash | Bin 0 -> 35 bytes .../MergeCollectionListenerArrayObjectTest.php | 27 + .../MergeCollectionListenerArrayTest.php | 27 + ...ergeCollectionListenerCustomArrayObjectTest.php | 28 + .../EventListener/MergeCollectionListenerTest.php | 259 +++ .../Core/EventListener/ResizeFormListenerTest.php | 255 +++ .../Core/EventListener/TrimListenerTest.php | 79 + .../Tests/Extension/Core/Type/BaseTypeTest.php | 135 ++ .../Tests/Extension/Core/Type/ButtonTypeTest.php | 28 + .../Tests/Extension/Core/Type/CheckboxTypeTest.php | 162 ++ .../Core/Type/ChoiceTypePerformanceTest.php | 38 + .../Tests/Extension/Core/Type/ChoiceTypeTest.php | 949 ++++++++++ .../Extension/Core/Type/CollectionTypeTest.php | 200 +++ .../Tests/Extension/Core/Type/CountryTypeTest.php | 52 + .../Tests/Extension/Core/Type/CurrencyTypeTest.php | 37 + .../Tests/Extension/Core/Type/DateTimeTypeTest.php | 477 +++++ .../Tests/Extension/Core/Type/DateTypeTest.php | 781 ++++++++ .../Tests/Extension/Core/Type/FileTypeTest.php | 83 + .../Tests/Extension/Core/Type/FormTypeTest.php | 578 ++++++ .../Tests/Extension/Core/Type/IntegerTypeTest.php | 34 + .../Tests/Extension/Core/Type/LanguageTypeTest.php | 47 + .../Tests/Extension/Core/Type/LocaleTypeTest.php | 36 + .../Tests/Extension/Core/Type/MoneyTypeTest.php | 59 + .../Tests/Extension/Core/Type/NumberTypeTest.php | 63 + .../Tests/Extension/Core/Type/PasswordTypeTest.php | 51 + .../Tests/Extension/Core/Type/RepeatedTypeTest.php | 149 ++ .../Tests/Extension/Core/Type/SubmitTypeTest.php | 54 + .../Tests/Extension/Core/Type/TimeTypeTest.php | 649 +++++++ .../Tests/Extension/Core/Type/TimezoneTypeTest.php | 30 + .../Tests/Extension/Core/Type/TypeTestCase.php | 21 + .../Form/Tests/Extension/Core/Type/UrlTypeTest.php | 61 + .../Csrf/CsrfProvider/DefaultCsrfProviderTest.php | 81 + .../Csrf/CsrfProvider/SessionCsrfProviderTest.php | 75 + .../EventListener/CsrfValidationListenerTest.php | 78 + .../Csrf/Type/FormTypeCsrfExtensionTest.php | 301 ++++ .../EventListener/BindRequestListenerTest.php | 286 +++ .../HttpFoundationRequestHandlerTest.php | 54 + .../Validator/Constraints/FormValidatorTest.php | 748 ++++++++ .../EventListener/ValidationListenerTest.php | 145 ++ .../Type/FormTypeValidatorExtensionTest.php | 85 + .../Extension/Validator/Type/TypeTestCase.php | 49 + .../Extension/Validator/Util/ServerParamsTest.php | 46 + .../ViolationMapper/ViolationMapperTest.php | 1481 +++++++++++++++ .../ViolationMapper/ViolationPathTest.php | 245 +++ .../Form/Tests/Fixtures/AlternatingRowType.php | 27 + .../Component/Form/Tests/Fixtures/Author.php | 71 + .../Component/Form/Tests/Fixtures/AuthorType.php | 30 + .../Form/Tests/Fixtures/CustomArrayObject.php | 70 + .../Form/Tests/Fixtures/FixedDataTransformer.php | 45 + .../Form/Tests/Fixtures/FixedFilterListener.php | 66 + .../Component/Form/Tests/Fixtures/FooSubType.php | 32 + .../Fixtures/FooSubTypeWithParentInstance.php | 32 + .../Component/Form/Tests/Fixtures/FooType.php | 32 + .../Form/Tests/Fixtures/FooTypeBarExtension.php | 35 + .../Form/Tests/Fixtures/FooTypeBazExtension.php | 28 + .../Form/Tests/Fixtures/TestExtension.php | 72 + .../form/Symfony/Component/Form/Tests/Fixtures/foo | 0 .../Component/Form/Tests/FormBuilderTest.php | 232 +++ .../Component/Form/Tests/FormConfigTest.php | 148 ++ .../Form/Tests/FormFactoryBuilderTest.php | 59 + .../Component/Form/Tests/FormFactoryTest.php | 506 ++++++ .../Form/Tests/FormIntegrationTestCase.php | 21 + .../Form/Tests/FormPerformanceTestCase.php | 21 + .../Component/Form/Tests/FormRegistryTest.php | 243 +++ .../Component/Form/Tests/FormRendererTest.php | 27 + .../Component/Form/Tests/Guess/GuessTest.php | 36 + .../Form/Tests/NativeRequestHandlerTest.php | 219 +++ .../Component/Form/Tests/ResolvedFormTypeTest.php | 280 +++ .../Component/Form/Tests/SimpleFormTest.php | 1045 +++++++++++ 100 files changed, 20550 insertions(+) create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/AbstractDivLayoutTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/AbstractExtensionTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/AbstractFormTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/AbstractLayoutTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/AbstractRequestHandlerTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/AbstractTableLayoutTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/CompoundFormPerformanceTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/CompoundFormTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/ChoiceList/ChoiceListTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/ChoiceList/LazyChoiceListTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/ChoiceList/ObjectChoiceListTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/ChoiceList/SimpleChoiceListTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/DataMapper/PropertyPathMapperTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/ArrayToPartsTransformerTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/BooleanToStringTransformerTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/ChoiceToValueTransformerTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/ChoicesToValuesTransformerTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DataTransformerChainTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeTestCase.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToArrayTransformerTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformerTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToRfc3339TransformerTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToStringTransformerTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToTimestampTransformerTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformerTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformerTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/NumberToLocalizedStringTransformerTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/PercentToLocalizedStringTransformerTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/ValueToDuplicatesTransformerTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/EventListener/FixRadioInputListenerTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/EventListener/FixUrlProtocolListenerTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/EventListener/Fixtures/randomhash create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/EventListener/MergeCollectionListenerArrayObjectTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/EventListener/MergeCollectionListenerArrayTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/EventListener/MergeCollectionListenerCustomArrayObjectTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/EventListener/MergeCollectionListenerTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/EventListener/TrimListenerTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/BaseTypeTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/ButtonTypeTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/CheckboxTypeTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypePerformanceTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypeTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/CollectionTypeTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/CountryTypeTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/CurrencyTypeTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/DateTimeTypeTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/DateTypeTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/FileTypeTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/FormTypeTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/IntegerTypeTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/LanguageTypeTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/LocaleTypeTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/MoneyTypeTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/NumberTypeTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/PasswordTypeTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/RepeatedTypeTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/SubmitTypeTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/TimeTypeTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/TimezoneTypeTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/TypeTestCase.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/UrlTypeTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Csrf/CsrfProvider/DefaultCsrfProviderTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Csrf/CsrfProvider/SessionCsrfProviderTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Extension/HttpFoundation/EventListener/BindRequestListenerTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Extension/HttpFoundation/HttpFoundationRequestHandlerTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Validator/EventListener/ValidationListenerTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Validator/Type/FormTypeValidatorExtensionTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Validator/Type/TypeTestCase.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Validator/Util/ServerParamsTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Validator/ViolationMapper/ViolationPathTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Fixtures/AlternatingRowType.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Fixtures/Author.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Fixtures/AuthorType.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Fixtures/CustomArrayObject.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Fixtures/FixedDataTransformer.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Fixtures/FixedFilterListener.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Fixtures/FooSubType.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Fixtures/FooSubTypeWithParentInstance.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Fixtures/FooType.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Fixtures/FooTypeBarExtension.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Fixtures/FooTypeBazExtension.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Fixtures/TestExtension.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Fixtures/foo create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/FormBuilderTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/FormConfigTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/FormFactoryBuilderTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/FormFactoryTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/FormIntegrationTestCase.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/FormPerformanceTestCase.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/FormRegistryTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/FormRendererTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/Guess/GuessTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/NativeRequestHandlerTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/ResolvedFormTypeTest.php create mode 100644 vendor/symfony/form/Symfony/Component/Form/Tests/SimpleFormTest.php (limited to 'vendor/symfony/form/Symfony/Component/Form/Tests') diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/AbstractDivLayoutTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/AbstractDivLayoutTest.php new file mode 100644 index 00000000..ee9ed8f2 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/AbstractDivLayoutTest.php @@ -0,0 +1,732 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests; + +use Symfony\Component\Form\FormError; +use Symfony\Component\Form\Tests\Fixtures\AlternatingRowType; + +abstract class AbstractDivLayoutTest extends AbstractLayoutTest +{ + public function testRow() + { + $form = $this->factory->createNamed('name', 'text'); + $form->addError(new FormError('[trans]Error![/trans]')); + $view = $form->createView(); + $html = $this->renderRow($view); + + $this->assertMatchesXpath($html, +'/div + [ + ./label[@for="name"] + /following-sibling::ul + [./li[.="[trans]Error![/trans]"]] + [count(./li)=1] + /following-sibling::input[@id="name"] + ] +' + ); + } + + public function testRowOverrideVariables() + { + $view = $this->factory->createNamed('name', 'text')->createView(); + $html = $this->renderRow($view, array( + 'attr' => array('class' => 'my&class'), + 'label' => 'foo&bar', + 'label_attr' => array('class' => 'my&label&class'), + )); + + $this->assertMatchesXpath($html, +'/div + [ + ./label[@for="name"][@class="my&label&class required"][.="[trans]foo&bar[/trans]"] + /following-sibling::input[@id="name"][@class="my&class"] + ] +' + ); + } + + public function testRepeatedRow() + { + $form = $this->factory->createNamed('name', 'repeated'); + $form->addError(new FormError('[trans]Error![/trans]')); + $view = $form->createView(); + $html = $this->renderRow($view); + + // The errors of the form are not rendered by intention! + // In practice, repeated fields cannot have errors as all errors + // on them are mapped to the first child. + // (see RepeatedTypeValidatorExtension) + + $this->assertMatchesXpath($html, +'/div + [ + ./label[@for="name_first"] + /following-sibling::input[@id="name_first"] + ] +/following-sibling::div + [ + ./label[@for="name_second"] + /following-sibling::input[@id="name_second"] + ] +' + ); + } + + public function testButtonRow() + { + $form = $this->factory->createNamed('name', 'button'); + $view = $form->createView(); + $html = $this->renderRow($view); + + $this->assertMatchesXpath($html, +'/div + [ + ./button[@type="button"][@name="name"] + ] + [count(//label)=0] +' + ); + } + + public function testRest() + { + $view = $this->factory->createNamedBuilder('name', 'form') + ->add('field1', 'text') + ->add('field2', 'repeated') + ->add('field3', 'text') + ->add('field4', 'text') + ->getForm() + ->createView(); + + // Render field2 row -> does not implicitly call renderWidget because + // it is a repeated field! + $this->renderRow($view['field2']); + + // Render field3 widget + $this->renderWidget($view['field3']); + + // Rest should only contain field1 and field4 + $html = $this->renderRest($view); + + $this->assertMatchesXpath($html, +'/div + [ + ./label[@for="name_field1"] + /following-sibling::input[@type="text"][@id="name_field1"] + ] +/following-sibling::div + [ + ./label[@for="name_field4"] + /following-sibling::input[@type="text"][@id="name_field4"] + ] + [count(../div)=2] + [count(..//label)=2] + [count(..//input)=3] +/following-sibling::input + [@type="hidden"] + [@id="name__token"] +' + ); + } + + public function testRestWithChildrenForms() + { + $child1 = $this->factory->createNamedBuilder('child1', 'form') + ->add('field1', 'text') + ->add('field2', 'text'); + + $child2 = $this->factory->createNamedBuilder('child2', 'form') + ->add('field1', 'text') + ->add('field2', 'text'); + + $view = $this->factory->createNamedBuilder('parent', 'form') + ->add($child1) + ->add($child2) + ->getForm() + ->createView(); + + // Render child1.field1 row + $this->renderRow($view['child1']['field1']); + + // Render child2.field2 widget (remember that widget don't render label) + $this->renderWidget($view['child2']['field2']); + + // Rest should only contain child1.field2 and child2.field1 + $html = $this->renderRest($view); + + $this->assertMatchesXpath($html, +'/div + [ + ./label[not(@for)] + /following-sibling::div[@id="parent_child1"] + [ + ./div + [ + ./label[@for="parent_child1_field2"] + /following-sibling::input[@id="parent_child1_field2"] + ] + ] + ] + +/following-sibling::div + [ + ./label[not(@for)] + /following-sibling::div[@id="parent_child2"] + [ + ./div + [ + ./label[@for="parent_child2_field1"] + /following-sibling::input[@id="parent_child2_field1"] + ] + ] + ] + [count(//label)=4] + [count(//input[@type="text"])=2] +/following-sibling::input[@type="hidden"][@id="parent__token"] +' + ); + } + + public function testRestAndRepeatedWithRow() + { + $view = $this->factory->createNamedBuilder('name', 'form') + ->add('first', 'text') + ->add('password', 'repeated') + ->getForm() + ->createView(); + + $this->renderRow($view['password']); + + $html = $this->renderRest($view); + + $this->assertMatchesXpath($html, +'/div + [ + ./label[@for="name_first"] + /following-sibling::input[@type="text"][@id="name_first"] + ] + [count(.//input)=1] +/following-sibling::input + [@type="hidden"] + [@id="name__token"] +' + ); + } + + public function testRestAndRepeatedWithRowPerChild() + { + $view = $this->factory->createNamedBuilder('name', 'form') + ->add('first', 'text') + ->add('password', 'repeated') + ->getForm() + ->createView(); + + $this->renderRow($view['password']['first']); + $this->renderRow($view['password']['second']); + + $html = $this->renderRest($view); + + $this->assertMatchesXpath($html, +'/div + [ + ./label[@for="name_first"] + /following-sibling::input[@type="text"][@id="name_first"] + ] + [count(.//input)=1] + [count(.//label)=1] +/following-sibling::input + [@type="hidden"] + [@id="name__token"] +' + ); + } + + public function testRestAndRepeatedWithWidgetPerChild() + { + $view = $this->factory->createNamedBuilder('name', 'form') + ->add('first', 'text') + ->add('password', 'repeated') + ->getForm() + ->createView(); + + // The password form is considered as rendered as all its children + // are rendered + $this->renderWidget($view['password']['first']); + $this->renderWidget($view['password']['second']); + + $html = $this->renderRest($view); + + $this->assertMatchesXpath($html, +'/div + [ + ./label[@for="name_first"] + /following-sibling::input[@type="text"][@id="name_first"] + ] + [count(//input)=2] + [count(//label)=1] +/following-sibling::input + [@type="hidden"] + [@id="name__token"] +' + ); + } + + public function testCollection() + { + $form = $this->factory->createNamed('name', 'collection', array('a', 'b'), array( + 'type' => 'text', + )); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/div + [ + ./div[./input[@type="text"][@value="a"]] + /following-sibling::div[./input[@type="text"][@value="b"]] + ] + [count(./div[./input])=2] +' + ); + } + + // https://github.com/symfony/symfony/issues/5038 + public function testCollectionWithAlternatingRowTypes() + { + $data = array( + array('title' => 'a'), + array('title' => 'b'), + ); + $form = $this->factory->createNamed('name', 'collection', $data, array( + 'type' => new AlternatingRowType(), + )); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/div + [ + ./div[./div/div/input[@type="text"][@value="a"]] + /following-sibling::div[./div/div/textarea[.="b"]] + ] + [count(./div[./div/div/input])=1] + [count(./div[./div/div/textarea])=1] +' + ); + } + + public function testEmptyCollection() + { + $form = $this->factory->createNamed('name', 'collection', array(), array( + 'type' => 'text', + )); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/div + [./input[@type="hidden"][@id="name__token"]] + [count(./div)=0] +' + ); + } + + public function testCollectionRow() + { + $collection = $this->factory->createNamedBuilder( + 'collection', + 'collection', + array('a', 'b'), + array('type' => 'text') + ); + + $form = $this->factory->createNamedBuilder('form', 'form') + ->add($collection) + ->getForm(); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/div + [ + ./div + [ + ./label[not(@for)] + /following-sibling::div + [ + ./div + [ + ./label[@for="form_collection_0"] + /following-sibling::input[@type="text"][@value="a"] + ] + /following-sibling::div + [ + ./label[@for="form_collection_1"] + /following-sibling::input[@type="text"][@value="b"] + ] + ] + ] + /following-sibling::input[@type="hidden"][@id="form__token"] + ] + [count(.//input)=3] +' + ); + } + + public function testForm() + { + $form = $this->factory->createNamedBuilder('name', 'form') + ->setMethod('PUT') + ->setAction('http://example.com') + ->add('firstName', 'text') + ->add('lastName', 'text') + ->getForm(); + + // include ampersands everywhere to validate escaping + $html = $this->renderForm($form->createView(), array( + 'id' => 'my&id', + 'attr' => array('class' => 'my&class'), + )); + + $this->assertMatchesXpath($html, +'/form + [ + ./input[@type="hidden"][@name="_method"][@value="PUT"] + /following-sibling::div + [ + ./div + [ + ./label[@for="name_firstName"] + /following-sibling::input[@type="text"][@id="name_firstName"] + ] + /following-sibling::div + [ + ./label[@for="name_lastName"] + /following-sibling::input[@type="text"][@id="name_lastName"] + ] + /following-sibling::input[@type="hidden"][@id="name__token"] + ] + [count(.//input)=3] + [@id="my&id"] + [@class="my&class"] + ] + [@method="post"] + [@action="http://example.com"] + [@class="my&class"] +' + ); + } + + public function testFormWidget() + { + $form = $this->factory->createNamedBuilder('name', 'form') + ->add('firstName', 'text') + ->add('lastName', 'text') + ->getForm(); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/div + [ + ./div + [ + ./label[@for="name_firstName"] + /following-sibling::input[@type="text"][@id="name_firstName"] + ] + /following-sibling::div + [ + ./label[@for="name_lastName"] + /following-sibling::input[@type="text"][@id="name_lastName"] + ] + /following-sibling::input[@type="hidden"][@id="name__token"] + ] + [count(.//input)=3] +' + ); + } + + // https://github.com/symfony/symfony/issues/2308 + public function testNestedFormError() + { + $form = $this->factory->createNamedBuilder('name', 'form') + ->add($this->factory + ->createNamedBuilder('child', 'form', null, array('error_bubbling' => false)) + ->add('grandChild', 'form') + ) + ->getForm(); + + $form->get('child')->addError(new FormError('[trans]Error![/trans]')); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/div + [ + ./div/label + /following-sibling::ul[./li[.="[trans]Error![/trans]"]] + ] + [count(.//li[.="[trans]Error![/trans]"])=1] +' + ); + } + + public function testCsrf() + { + $this->csrfProvider->expects($this->any()) + ->method('generateCsrfToken') + ->will($this->returnValue('foo&bar')); + + $form = $this->factory->createNamedBuilder('name', 'form') + ->add($this->factory + // No CSRF protection on nested forms + ->createNamedBuilder('child', 'form') + ->add($this->factory->createNamedBuilder('grandchild', 'text')) + ) + ->getForm(); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/div + [ + ./div + /following-sibling::input[@type="hidden"][@id="name__token"][@value="foo&bar"] + ] + [count(.//input[@type="hidden"])=1] +' + ); + } + + public function testRepeated() + { + $form = $this->factory->createNamed('name', 'repeated', 'foobar', array( + 'type' => 'text', + )); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/div + [ + ./div + [ + ./label[@for="name_first"] + /following-sibling::input[@type="text"][@id="name_first"] + ] + /following-sibling::div + [ + ./label[@for="name_second"] + /following-sibling::input[@type="text"][@id="name_second"] + ] + /following-sibling::input[@type="hidden"][@id="name__token"] + ] + [count(.//input)=3] +' + ); + } + + public function testRepeatedWithCustomOptions() + { + $form = $this->factory->createNamed('name', 'repeated', null, array( + // the global required value cannot be overridden + 'first_options' => array('label' => 'Test', 'required' => false), + 'second_options' => array('label' => 'Test2') + )); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/div + [ + ./div + [ + ./label[@for="name_first"][.="[trans]Test[/trans]"] + /following-sibling::input[@type="text"][@id="name_first"][@required="required"] + ] + /following-sibling::div + [ + ./label[@for="name_second"][.="[trans]Test2[/trans]"] + /following-sibling::input[@type="text"][@id="name_second"][@required="required"] + ] + /following-sibling::input[@type="hidden"][@id="name__token"] + ] + [count(.//input)=3] +' + ); + } + + public function testSearchInputName() + { + $form = $this->factory->createNamedBuilder('full', 'form') + ->add('name', 'search') + ->getForm(); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/div + [ + ./div + [ + ./label[@for="full_name"] + /following-sibling::input[@type="search"][@id="full_name"][@name="full[name]"] + ] + /following-sibling::input[@type="hidden"][@id="full__token"] + ] + [count(//input)=2] +' + ); + } + + public function testLabelHasNoId() + { + $form = $this->factory->createNamed('name', 'text'); + $html = $this->renderRow($form->createView()); + + $this->assertMatchesXpath($html, +'/div + [ + ./label[@for="name"][not(@id)] + /following-sibling::input[@id="name"] + ] +' + ); + } + + public function testLabelIsNotRenderedWhenSetToFalse() + { + $form = $this->factory->createNamed('name', 'text', null, array( + 'label' => false + )); + $html = $this->renderRow($form->createView()); + + $this->assertMatchesXpath($html, +'/div + [ + ./input[@id="name"] + ] + [count(//label)=0] +' + ); + } + + /** + * @dataProvider themeBlockInheritanceProvider + */ + public function testThemeBlockInheritance($theme) + { + $view = $this->factory + ->createNamed('name', 'email') + ->createView() + ; + + $this->setTheme($view, $theme); + + $this->assertMatchesXpath( + $this->renderWidget($view), + '/input[@type="email"][@rel="theme"]' + ); + } + + /** + * @dataProvider themeInheritanceProvider + */ + public function testThemeInheritance($parentTheme, $childTheme) + { + $child = $this->factory->createNamedBuilder('child', 'form') + ->add('field', 'text'); + + $view = $this->factory->createNamedBuilder('parent', 'form') + ->add('field', 'text') + ->add($child) + ->getForm() + ->createView() + ; + + $this->setTheme($view, $parentTheme); + $this->setTheme($view['child'], $childTheme); + + $this->assertWidgetMatchesXpath($view, array(), +'/div + [ + ./div + [ + ./label[.="parent"] + /following-sibling::input[@type="text"] + ] + /following-sibling::div + [ + ./label[.="child"] + /following-sibling::div + [ + ./div + [ + ./label[.="child"] + /following-sibling::input[@type="text"] + ] + ] + ] + /following-sibling::input[@type="hidden"] + ] +' + ); + } + + /** + * The block "_name_child_label" should be overridden in the theme of the + * implemented driver. + */ + public function testCollectionRowWithCustomBlock() + { + $collection = array('one', 'two', 'three'); + $form = $this->factory->createNamedBuilder('name', 'collection', $collection) + ->getForm(); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/div + [ + ./div[./label[.="Custom label: [trans]0[/trans]"]] + /following-sibling::div[./label[.="Custom label: [trans]1[/trans]"]] + /following-sibling::div[./label[.="Custom label: [trans]2[/trans]"]] + ] +' + ); + } + + public function testFormEndWithRest() + { + $view = $this->factory->createNamedBuilder('name', 'form') + ->add('field1', 'text') + ->add('field2', 'text') + ->getForm() + ->createView(); + + $this->renderWidget($view['field1']); + + // Rest should only contain field2 + $html = $this->renderEnd($view); + + // Insert the start tag, the end tag should be rendered by the helper + $this->assertMatchesXpath('
' . $html, +'/form + [ + ./div + [ + ./label[@for="name_field2"] + /following-sibling::input[@type="text"][@id="name_field2"] + ] + /following-sibling::input + [@type="hidden"] + [@id="name__token"] + ] +' + ); + } + + public function testFormEndWithoutRest() + { + $view = $this->factory->createNamedBuilder('name', 'form') + ->add('field1', 'text') + ->add('field2', 'text') + ->getForm() + ->createView(); + + $this->renderWidget($view['field1']); + + // Rest should only contain field2, but isn't rendered + $html = $this->renderEnd($view, array('render_rest' => false)); + + $this->assertEquals('
', $html); + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/AbstractExtensionTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/AbstractExtensionTest.php new file mode 100644 index 00000000..c16cb221 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/AbstractExtensionTest.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests; + +use Symfony\Component\Form\AbstractExtension; +use Symfony\Component\Form\Tests\Fixtures\FooType; + +class AbstractExtensionTest extends \PHPUnit_Framework_TestCase +{ + public function testHasType() + { + $loader = new ConcreteExtension(); + $this->assertTrue($loader->hasType('foo')); + $this->assertFalse($loader->hasType('bar')); + } + + public function testGetType() + { + $loader = new ConcreteExtension(); + $this->assertInstanceOf('Symfony\Component\Form\Tests\Fixtures\FooType', $loader->getType('foo')); + } +} + +class ConcreteExtension extends AbstractExtension +{ + protected function loadTypes() + { + return array(new FooType()); + } + + protected function loadTypeGuesser() + { + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/AbstractFormTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/AbstractFormTest.php new file mode 100644 index 00000000..29118187 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/AbstractFormTest.php @@ -0,0 +1,147 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests; + +use Symfony\Component\Form\FormBuilder; +use Symfony\Component\EventDispatcher\EventDispatcher; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; + +abstract class AbstractFormTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var EventDispatcherInterface + */ + protected $dispatcher; + + /** + * @var \Symfony\Component\Form\FormFactoryInterface + */ + protected $factory; + + /** + * @var \Symfony\Component\Form\FormInterface + */ + protected $form; + + protected function setUp() + { + if (!class_exists('Symfony\Component\EventDispatcher\EventDispatcher')) { + $this->markTestSkipped('The "EventDispatcher" component is not available'); + } + + // We need an actual dispatcher to use the deprecated + // bindRequest() method + $this->dispatcher = new EventDispatcher(); + $this->factory = $this->getMock('Symfony\Component\Form\FormFactoryInterface'); + $this->form = $this->createForm(); + } + + protected function tearDown() + { + $this->dispatcher = null; + $this->factory = null; + $this->form = null; + } + + /** + * @return \Symfony\Component\Form\FormInterface + */ + abstract protected function createForm(); + + /** + * @param string $name + * @param EventDispatcherInterface $dispatcher + * @param string $dataClass + * + * @return FormBuilder + */ + protected function getBuilder($name = 'name', EventDispatcherInterface $dispatcher = null, $dataClass = null) + { + return new FormBuilder($name, $dataClass, $dispatcher ?: $this->dispatcher, $this->factory); + } + + /** + * @param string $name + * + * @return \PHPUnit_Framework_MockObject_MockObject + */ + protected function getMockForm($name = 'name') + { + $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); + $config = $this->getMock('Symfony\Component\Form\FormConfigInterface'); + + $form->expects($this->any()) + ->method('getName') + ->will($this->returnValue($name)); + $form->expects($this->any()) + ->method('getConfig') + ->will($this->returnValue($config)); + + return $form; + } + + /** + * @param string $name + * + * @return \PHPUnit_Framework_MockObject_MockObject + */ + protected function getValidForm($name) + { + $form = $this->getMockForm($name); + + $form->expects($this->any()) + ->method('isValid') + ->will($this->returnValue(true)); + + return $form; + } + + /** + * @param string $name + * + * @return \PHPUnit_Framework_MockObject_MockObject + */ + protected function getInvalidForm($name) + { + $form = $this->getMockForm($name); + + $form->expects($this->any()) + ->method('isValid') + ->will($this->returnValue(false)); + + return $form; + } + + /** + * @return \PHPUnit_Framework_MockObject_MockObject + */ + protected function getDataMapper() + { + return $this->getMock('Symfony\Component\Form\DataMapperInterface'); + } + + /** + * @return \PHPUnit_Framework_MockObject_MockObject + */ + protected function getDataTransformer() + { + return $this->getMock('Symfony\Component\Form\DataTransformerInterface'); + } + + /** + * @return \PHPUnit_Framework_MockObject_MockObject + */ + protected function getFormValidator() + { + return $this->getMock('Symfony\Component\Form\FormValidatorInterface'); + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/AbstractLayoutTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/AbstractLayoutTest.php new file mode 100644 index 00000000..8f632a2b --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/AbstractLayoutTest.php @@ -0,0 +1,1876 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests; + +use Symfony\Component\Form\FormError; +use Symfony\Component\Form\FormView; +use Symfony\Component\Form\Extension\Csrf\CsrfExtension; + +abstract class AbstractLayoutTest extends \Symfony\Component\Form\Test\FormIntegrationTestCase +{ + protected $csrfProvider; + + protected function setUp() + { + if (!extension_loaded('intl')) { + $this->markTestSkipped('The "intl" extension is not available'); + } + + \Locale::setDefault('en'); + + $this->csrfProvider = $this->getMock('Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface'); + + parent::setUp(); + } + + protected function getExtensions() + { + return array( + new CsrfExtension($this->csrfProvider), + ); + } + + protected function tearDown() + { + $this->csrfProvider = null; + + parent::tearDown(); + } + + protected function assertXpathNodeValue(\DomElement $element, $expression, $nodeValue) + { + $xpath = new \DOMXPath($element->ownerDocument); + $nodeList = $xpath->evaluate($expression); + $this->assertEquals(1, $nodeList->length); + $this->assertEquals($nodeValue, $nodeList->item(0)->nodeValue); + } + + protected function assertMatchesXpath($html, $expression, $count = 1) + { + $dom = new \DomDocument('UTF-8'); + try { + // Wrap in node so we can load HTML with multiple tags at + // the top level + $dom->loadXml(''.$html.''); + } catch (\Exception $e) { + $this->fail(sprintf( + "Failed loading HTML:\n\n%s\n\nError: %s", + $html, + $e->getMessage() + )); + } + $xpath = new \DOMXPath($dom); + $nodeList = $xpath->evaluate('/root'.$expression); + + if ($nodeList->length != $count) { + $dom->formatOutput = true; + $this->fail(sprintf( + "Failed asserting that \n\n%s\n\nmatches exactly %s. Matches %s in \n\n%s", + $expression, + $count == 1 ? 'once' : $count.' times', + $nodeList->length == 1 ? 'once' : $nodeList->length.' times', + // strip away and + substr($dom->saveHTML(), 6, -8) + )); + } + } + + protected function assertWidgetMatchesXpath(FormView $view, array $vars, $xpath) + { + // include ampersands everywhere to validate escaping + $html = $this->renderWidget($view, array_merge(array( + 'id' => 'my&id', + 'attr' => array('class' => 'my&class'), + ), $vars)); + + $xpath = trim($xpath).' + [@id="my&id"] + [@class="my&class"]'; + + $this->assertMatchesXpath($html, $xpath); + } + + abstract protected function renderForm(FormView $view, array $vars = array()); + + abstract protected function renderEnctype(FormView $view); + + abstract protected function renderLabel(FormView $view, $label = null, array $vars = array()); + + abstract protected function renderErrors(FormView $view); + + abstract protected function renderWidget(FormView $view, array $vars = array()); + + abstract protected function renderRow(FormView $view, array $vars = array()); + + abstract protected function renderRest(FormView $view, array $vars = array()); + + abstract protected function renderStart(FormView $view, array $vars = array()); + + abstract protected function renderEnd(FormView $view, array $vars = array()); + + abstract protected function setTheme(FormView $view, array $themes); + + public function testEnctype() + { + $form = $this->factory->createNamedBuilder('name', 'form') + ->add('file', 'file') + ->getForm(); + + $this->assertEquals('enctype="multipart/form-data"', $this->renderEnctype($form->createView())); + } + + public function testNoEnctype() + { + $form = $this->factory->createNamedBuilder('name', 'form') + ->add('text', 'text') + ->getForm(); + + $this->assertEquals('', $this->renderEnctype($form->createView())); + } + + public function testLabel() + { + $form = $this->factory->createNamed('name', 'text'); + $view = $form->createView(); + $this->renderWidget($view, array('label' => 'foo')); + $html = $this->renderLabel($view); + + $this->assertMatchesXpath($html, +'/label + [@for="name"] + [.="[trans]Name[/trans]"] +' + ); + } + + public function testLabelOnForm() + { + $form = $this->factory->createNamed('name', 'date'); + $view = $form->createView(); + $this->renderWidget($view, array('label' => 'foo')); + $html = $this->renderLabel($view); + + $this->assertMatchesXpath($html, +'/label + [@class="required"] + [.="[trans]Name[/trans]"] +' + ); + } + + public function testLabelWithCustomTextPassedAsOption() + { + $form = $this->factory->createNamed('name', 'text', null, array( + 'label' => 'Custom label', + )); + $html = $this->renderLabel($form->createView()); + + $this->assertMatchesXpath($html, +'/label + [@for="name"] + [.="[trans]Custom label[/trans]"] +' + ); + } + + public function testLabelWithCustomTextPassedDirectly() + { + $form = $this->factory->createNamed('name', 'text'); + $html = $this->renderLabel($form->createView(), 'Custom label'); + + $this->assertMatchesXpath($html, +'/label + [@for="name"] + [.="[trans]Custom label[/trans]"] +' + ); + } + + public function testLabelWithCustomTextPassedAsOptionAndDirectly() + { + $form = $this->factory->createNamed('name', 'text', null, array( + 'label' => 'Custom label', + )); + $html = $this->renderLabel($form->createView(), 'Overridden label'); + + $this->assertMatchesXpath($html, +'/label + [@for="name"] + [.="[trans]Overridden label[/trans]"] +' + ); + } + + public function testLabelDoesNotRenderFieldAttributes() + { + $form = $this->factory->createNamed('name', 'text'); + $html = $this->renderLabel($form->createView(), null, array( + 'attr' => array( + 'class' => 'my&class' + ), + )); + + $this->assertMatchesXpath($html, +'/label + [@for="name"] + [@class="required"] +' + ); + } + + public function testLabelWithCustomAttributesPassedDirectly() + { + $form = $this->factory->createNamed('name', 'text'); + $html = $this->renderLabel($form->createView(), null, array( + 'label_attr' => array( + 'class' => 'my&class' + ), + )); + + $this->assertMatchesXpath($html, +'/label + [@for="name"] + [@class="my&class required"] +' + ); + } + + public function testLabelWithCustomTextAndCustomAttributesPassedDirectly() + { + $form = $this->factory->createNamed('name', 'text'); + $html = $this->renderLabel($form->createView(), 'Custom label', array( + 'label_attr' => array( + 'class' => 'my&class' + ), + )); + + $this->assertMatchesXpath($html, +'/label + [@for="name"] + [@class="my&class required"] + [.="[trans]Custom label[/trans]"] +' + ); + } + + // https://github.com/symfony/symfony/issues/5029 + public function testLabelWithCustomTextAsOptionAndCustomAttributesPassedDirectly() + { + $form = $this->factory->createNamed('name', 'text', null, array( + 'label' => 'Custom label', + )); + $html = $this->renderLabel($form->createView(), null, array( + 'label_attr' => array( + 'class' => 'my&class' + ), + )); + + $this->assertMatchesXpath($html, + '/label + [@for="name"] + [@class="my&class required"] + [.="[trans]Custom label[/trans]"] +' + ); + } + + public function testErrors() + { + $form = $this->factory->createNamed('name', 'text'); + $form->addError(new FormError('[trans]Error 1[/trans]')); + $form->addError(new FormError('[trans]Error 2[/trans]')); + $view = $form->createView(); + $html = $this->renderErrors($view); + + $this->assertMatchesXpath($html, +'/ul + [ + ./li[.="[trans]Error 1[/trans]"] + /following-sibling::li[.="[trans]Error 2[/trans]"] + ] + [count(./li)=2] +' + ); + } + + public function testWidgetById() + { + $form = $this->factory->createNamed('text_id', 'text'); + $html = $this->renderWidget($form->createView()); + + $this->assertMatchesXpath($html, +'/div + [ + ./input + [@type="text"] + [@id="text_id"] + ] + [@id="container"] +' + ); + } + + public function testCheckedCheckbox() + { + $form = $this->factory->createNamed('name', 'checkbox', true); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/input + [@type="checkbox"] + [@name="name"] + [@checked="checked"] + [@value="1"] +' + ); + } + + public function testUncheckedCheckbox() + { + $form = $this->factory->createNamed('name', 'checkbox', false); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/input + [@type="checkbox"] + [@name="name"] + [not(@checked)] +' + ); + } + + public function testCheckboxWithValue() + { + $form = $this->factory->createNamed('name', 'checkbox', false, array( + 'value' => 'foo&bar', + )); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/input + [@type="checkbox"] + [@name="name"] + [@value="foo&bar"] +' + ); + } + + public function testSingleChoice() + { + $form = $this->factory->createNamed('name', 'choice', '&a', array( + 'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'), + 'multiple' => false, + 'expanded' => false, + )); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/select + [@name="name"] + [@required="required"] + [ + ./option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] + /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] + ] + [count(./option)=2] +' + ); + } + + public function testSingleChoiceWithPreferred() + { + $form = $this->factory->createNamed('name', 'choice', '&a', array( + 'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'), + 'preferred_choices' => array('&b'), + 'multiple' => false, + 'expanded' => false, + )); + + $this->assertWidgetMatchesXpath($form->createView(), array('separator' => '-- sep --'), +'/select + [@name="name"] + [@required="required"] + [ + ./option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] + /following-sibling::option[@disabled="disabled"][not(@selected)][.="-- sep --"] + /following-sibling::option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] + ] + [count(./option)=3] +' + ); + } + + public function testSingleChoiceWithPreferredAndNoSeparator() + { + $form = $this->factory->createNamed('name', 'choice', '&a', array( + 'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'), + 'preferred_choices' => array('&b'), + 'multiple' => false, + 'expanded' => false, + )); + + $this->assertWidgetMatchesXpath($form->createView(), array('separator' => null), +'/select + [@name="name"] + [@required="required"] + [ + ./option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] + /following-sibling::option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] + ] + [count(./option)=2] +' + ); + } + + public function testSingleChoiceWithPreferredAndBlankSeparator() + { + $form = $this->factory->createNamed('name', 'choice', '&a', array( + 'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'), + 'preferred_choices' => array('&b'), + 'multiple' => false, + 'expanded' => false, + )); + + $this->assertWidgetMatchesXpath($form->createView(), array('separator' => ''), +'/select + [@name="name"] + [@required="required"] + [ + ./option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] + /following-sibling::option[@disabled="disabled"][not(@selected)][.=""] + /following-sibling::option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] + ] + [count(./option)=3] +' + ); + } + + public function testChoiceWithOnlyPreferred() + { + $form = $this->factory->createNamed('name', 'choice', '&a', array( + 'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'), + 'preferred_choices' => array('&a', '&b'), + 'multiple' => false, + 'expanded' => false, + )); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/select + [count(./option)=2] +' + ); + } + + public function testSingleChoiceNonRequired() + { + $form = $this->factory->createNamed('name', 'choice', '&a', array( + 'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'), + 'required' => false, + 'multiple' => false, + 'expanded' => false, + )); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/select + [@name="name"] + [not(@required)] + [ + ./option[@value=""][.="[trans][/trans]"] + /following-sibling::option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] + /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] + ] + [count(./option)=3] +' + ); + } + + public function testSingleChoiceNonRequiredNoneSelected() + { + $form = $this->factory->createNamed('name', 'choice', null, array( + 'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'), + 'required' => false, + 'multiple' => false, + 'expanded' => false, + )); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/select + [@name="name"] + [not(@required)] + [ + ./option[@value=""][.="[trans][/trans]"] + /following-sibling::option[@value="&a"][not(@selected)][.="[trans]Choice&A[/trans]"] + /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] + ] + [count(./option)=3] +' + ); + } + + public function testSingleChoiceWithNonRequiredEmptyValue() + { + $form = $this->factory->createNamed('name', 'choice', '&a', array( + 'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'), + 'multiple' => false, + 'expanded' => false, + 'required' => false, + 'empty_value' => 'Select&Anything&Not&Me', + )); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/select + [@name="name"] + [not(@required)] + [ + ./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Select&Anything&Not&Me[/trans]"] + /following-sibling::option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] + /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] + ] + [count(./option)=3] +' + ); + } + + public function testSingleChoiceRequiredWithEmptyValue() + { + $form = $this->factory->createNamed('name', 'choice', '&a', array( + 'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'), + 'required' => true, + 'multiple' => false, + 'expanded' => false, + 'empty_value' => 'Test&Me' + )); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/select + [@name="name"] + [@required="required"] + [ + ./option[not(@value)][not(@selected)][@disabled][.="[trans]Test&Me[/trans]"] + /following-sibling::option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] + /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] + ] + [count(./option)=3] +' + ); + } + + public function testSingleChoiceRequiredWithEmptyValueViaView() + { + $form = $this->factory->createNamed('name', 'choice', '&a', array( + 'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'), + 'required' => true, + 'multiple' => false, + 'expanded' => false, + )); + + $this->assertWidgetMatchesXpath($form->createView(), array('empty_value' => ''), +'/select + [@name="name"] + [@required="required"] + [ + ./option[not(@value)][not(@selected)][@disabled][.="[trans][/trans]"] + /following-sibling::option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] + /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] + ] + [count(./option)=3] +' + ); + } + + public function testSingleChoiceGrouped() + { + $form = $this->factory->createNamed('name', 'choice', '&a', array( + 'choices' => array( + 'Group&1' => array('&a' => 'Choice&A', '&b' => 'Choice&B'), + 'Group&2' => array('&c' => 'Choice&C'), + ), + 'multiple' => false, + 'expanded' => false, + )); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/select + [@name="name"] + [./optgroup[@label="[trans]Group&1[/trans]"] + [ + ./option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] + /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] + ] + [count(./option)=2] + ] + [./optgroup[@label="[trans]Group&2[/trans]"] + [./option[@value="&c"][not(@selected)][.="[trans]Choice&C[/trans]"]] + [count(./option)=1] + ] + [count(./optgroup)=2] +' + ); + } + + public function testMultipleChoice() + { + $form = $this->factory->createNamed('name', 'choice', array('&a'), array( + 'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'), + 'multiple' => true, + 'expanded' => false, + )); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/select + [@name="name[]"] + [@multiple="multiple"] + [ + ./option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] + /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] + ] + [count(./option)=2] +' + ); + } + + public function testMultipleChoiceSkipsEmptyValue() + { + $form = $this->factory->createNamed('name', 'choice', array('&a'), array( + 'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'), + 'multiple' => true, + 'expanded' => false, + 'empty_value' => 'Test&Me' + )); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/select + [@name="name[]"] + [@multiple="multiple"] + [ + ./option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] + /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] + ] + [count(./option)=2] +' + ); + } + + public function testMultipleChoiceNonRequired() + { + $form = $this->factory->createNamed('name', 'choice', array('&a'), array( + 'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'), + 'required' => false, + 'multiple' => true, + 'expanded' => false, + )); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/select + [@name="name[]"] + [@multiple="multiple"] + [ + ./option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] + /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] + ] + [count(./option)=2] +' + ); + } + + public function testSingleChoiceExpanded() + { + $form = $this->factory->createNamed('name', 'choice', '&a', array( + 'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'), + 'multiple' => false, + 'expanded' => true, + )); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/div + [ + ./input[@type="radio"][@name="name"][@id="name_0"][@value="&a"][@checked] + /following-sibling::label[@for="name_0"][.="[trans]Choice&A[/trans]"] + /following-sibling::input[@type="radio"][@name="name"][@id="name_1"][@value="&b"][not(@checked)] + /following-sibling::label[@for="name_1"][.="[trans]Choice&B[/trans]"] + /following-sibling::input[@type="hidden"][@id="name__token"] + ] + [count(./input)=3] +' + ); + } + + public function testSingleChoiceExpandedWithEmptyValue() + { + $form = $this->factory->createNamed('name', 'choice', '&a', array( + 'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'), + 'multiple' => false, + 'expanded' => true, + 'empty_value' => 'Test&Me' + )); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/div + [ + ./input[@type="radio"][@name="name"][@id="name_placeholder"][not(@checked)] + /following-sibling::label[@for="name_placeholder"][.="[trans]Test&Me[/trans]"] + /following-sibling::input[@type="radio"][@name="name"][@id="name_0"][@checked] + /following-sibling::label[@for="name_0"][.="[trans]Choice&A[/trans]"] + /following-sibling::input[@type="radio"][@name="name"][@id="name_1"][not(@checked)] + /following-sibling::label[@for="name_1"][.="[trans]Choice&B[/trans]"] + /following-sibling::input[@type="hidden"][@id="name__token"] + ] + [count(./input)=4] +' + ); + } + + public function testSingleChoiceExpandedWithBooleanValue() + { + $form = $this->factory->createNamed('name', 'choice', true, array( + 'choices' => array('1' => 'Choice&A', '0' => 'Choice&B'), + 'multiple' => false, + 'expanded' => true, + )); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/div + [ + ./input[@type="radio"][@name="name"][@id="name_0"][@checked] + /following-sibling::label[@for="name_0"][.="[trans]Choice&A[/trans]"] + /following-sibling::input[@type="radio"][@name="name"][@id="name_1"][not(@checked)] + /following-sibling::label[@for="name_1"][.="[trans]Choice&B[/trans]"] + /following-sibling::input[@type="hidden"][@id="name__token"] + ] + [count(./input)=3] +' + ); + } + + public function testMultipleChoiceExpanded() + { + $form = $this->factory->createNamed('name', 'choice', array('&a', '&c'), array( + 'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B', '&c' => 'Choice&C'), + 'multiple' => true, + 'expanded' => true, + 'required' => true, + )); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/div + [ + ./input[@type="checkbox"][@name="name[]"][@id="name_0"][@checked][not(@required)] + /following-sibling::label[@for="name_0"][.="[trans]Choice&A[/trans]"] + /following-sibling::input[@type="checkbox"][@name="name[]"][@id="name_1"][not(@checked)][not(@required)] + /following-sibling::label[@for="name_1"][.="[trans]Choice&B[/trans]"] + /following-sibling::input[@type="checkbox"][@name="name[]"][@id="name_2"][@checked][not(@required)] + /following-sibling::label[@for="name_2"][.="[trans]Choice&C[/trans]"] + /following-sibling::input[@type="hidden"][@id="name__token"] + ] + [count(./input)=4] +' + ); + } + + public function testCountry() + { + $form = $this->factory->createNamed('name', 'country', 'AT'); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/select + [@name="name"] + [./option[@value="AT"][@selected="selected"][.="[trans]Austria[/trans]"]] + [count(./option)>200] +' + ); + } + + public function testCountryWithEmptyValue() + { + $form = $this->factory->createNamed('name', 'country', 'AT', array( + 'empty_value' => 'Select&Country', + 'required' => false, + )); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/select + [@name="name"] + [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Select&Country[/trans]"]] + [./option[@value="AT"][@selected="selected"][.="[trans]Austria[/trans]"]] + [count(./option)>201] +' + ); + } + + public function testDateTime() + { + $form = $this->factory->createNamed('name', 'datetime', '2011-02-03 04:05:06', array( + 'input' => 'string', + 'with_seconds' => false, + )); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/div + [ + ./div + [@id="name_date"] + [ + ./select + [@id="name_date_month"] + [./option[@value="2"][@selected="selected"]] + /following-sibling::select + [@id="name_date_day"] + [./option[@value="3"][@selected="selected"]] + /following-sibling::select + [@id="name_date_year"] + [./option[@value="2011"][@selected="selected"]] + ] + /following-sibling::div + [@id="name_time"] + [ + ./select + [@id="name_time_hour"] + [./option[@value="4"][@selected="selected"]] + /following-sibling::select + [@id="name_time_minute"] + [./option[@value="5"][@selected="selected"]] + ] + ] + [count(.//select)=5] +' + ); + } + + public function testDateTimeWithEmptyValueGlobal() + { + $form = $this->factory->createNamed('name', 'datetime', null, array( + 'input' => 'string', + 'empty_value' => 'Change&Me', + 'required' => false, + )); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/div + [ + ./div + [@id="name_date"] + [ + ./select + [@id="name_date_month"] + [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]] + /following-sibling::select + [@id="name_date_day"] + [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]] + /following-sibling::select + [@id="name_date_year"] + [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]] + ] + /following-sibling::div + [@id="name_time"] + [ + ./select + [@id="name_time_hour"] + [./option[@value=""][.="[trans]Change&Me[/trans]"]] + /following-sibling::select + [@id="name_time_minute"] + [./option[@value=""][.="[trans]Change&Me[/trans]"]] + ] + ] + [count(.//select)=5] +' + ); + } + + public function testDateTimeWithEmptyValueOnTime() + { + $data = array('year' => '2011', 'month' => '2', 'day' => '3', 'hour' => '', 'minute' => ''); + + $form = $this->factory->createNamed('name', 'datetime', $data, array( + 'input' => 'array', + 'empty_value' => array('hour' => 'Change&Me', 'minute' => 'Change&Me'), + 'required' => false, + )); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/div + [ + ./div + [@id="name_date"] + [ + ./select + [@id="name_date_month"] + [./option[@value="2"][@selected="selected"]] + /following-sibling::select + [@id="name_date_day"] + [./option[@value="3"][@selected="selected"]] + /following-sibling::select + [@id="name_date_year"] + [./option[@value="2011"][@selected="selected"]] + ] + /following-sibling::div + [@id="name_time"] + [ + ./select + [@id="name_time_hour"] + [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]] + /following-sibling::select + [@id="name_time_minute"] + [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]] + ] + ] + [count(.//select)=5] +' + ); + } + + public function testDateTimeWithSeconds() + { + $form = $this->factory->createNamed('name', 'datetime', '2011-02-03 04:05:06', array( + 'input' => 'string', + 'with_seconds' => true, + )); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/div + [ + ./div + [@id="name_date"] + [ + ./select + [@id="name_date_month"] + [./option[@value="2"][@selected="selected"]] + /following-sibling::select + [@id="name_date_day"] + [./option[@value="3"][@selected="selected"]] + /following-sibling::select + [@id="name_date_year"] + [./option[@value="2011"][@selected="selected"]] + ] + /following-sibling::div + [@id="name_time"] + [ + ./select + [@id="name_time_hour"] + [./option[@value="4"][@selected="selected"]] + /following-sibling::select + [@id="name_time_minute"] + [./option[@value="5"][@selected="selected"]] + /following-sibling::select + [@id="name_time_second"] + [./option[@value="6"][@selected="selected"]] + ] + ] + [count(.//select)=6] +' + ); + } + + public function testDateTimeSingleText() + { + $form = $this->factory->createNamed('name', 'datetime', '2011-02-03 04:05:06', array( + 'input' => 'string', + 'date_widget' => 'single_text', + 'time_widget' => 'single_text', + )); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/div + [ + ./input + [@type="date"] + [@id="name_date"] + [@name="name[date]"] + [@value="2011-02-03"] + /following-sibling::input + [@type="time"] + [@id="name_time"] + [@name="name[time]"] + [@value="04:05"] + ] +' + ); + } + + public function testDateTimeWithWidgetSingleText() + { + $form = $this->factory->createNamed('name', 'datetime', '2011-02-03 04:05:06', array( + 'input' => 'string', + 'widget' => 'single_text', + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', + )); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/input + [@type="datetime"] + [@name="name"] + [@value="2011-02-03T04:05:06Z"] +' + ); + } + + public function testDateTimeWithWidgetSingleTextIgnoreDateAndTimeWidgets() + { + $form = $this->factory->createNamed('name', 'datetime', '2011-02-03 04:05:06', array( + 'input' => 'string', + 'date_widget' => 'choice', + 'time_widget' => 'choice', + 'widget' => 'single_text', + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', + )); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/input + [@type="datetime"] + [@name="name"] + [@value="2011-02-03T04:05:06Z"] +' + ); + } + + public function testDateChoice() + { + $form = $this->factory->createNamed('name', 'date', '2011-02-03', array( + 'input' => 'string', + 'widget' => 'choice', + )); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/div + [ + ./select + [@id="name_month"] + [./option[@value="2"][@selected="selected"]] + /following-sibling::select + [@id="name_day"] + [./option[@value="3"][@selected="selected"]] + /following-sibling::select + [@id="name_year"] + [./option[@value="2011"][@selected="selected"]] + ] + [count(./select)=3] +' + ); + } + + public function testDateChoiceWithEmptyValueGlobal() + { + $form = $this->factory->createNamed('name', 'date', null, array( + 'input' => 'string', + 'widget' => 'choice', + 'empty_value' => 'Change&Me', + 'required' => false, + )); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/div + [ + ./select + [@id="name_month"] + [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]] + /following-sibling::select + [@id="name_day"] + [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]] + /following-sibling::select + [@id="name_year"] + [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]] + ] + [count(./select)=3] +' + ); + } + + public function testDateChoiceWithEmptyValueOnYear() + { + $form = $this->factory->createNamed('name', 'date', null, array( + 'input' => 'string', + 'widget' => 'choice', + 'required' => false, + 'empty_value' => array('year' => 'Change&Me'), + )); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/div + [ + ./select + [@id="name_month"] + [./option[@value="1"]] + /following-sibling::select + [@id="name_day"] + [./option[@value="1"]] + /following-sibling::select + [@id="name_year"] + [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]] + ] + [count(./select)=3] +' + ); + } + + public function testDateText() + { + $form = $this->factory->createNamed('name', 'date', '2011-02-03', array( + 'input' => 'string', + 'widget' => 'text', + )); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/div + [ + ./input + [@id="name_month"] + [@type="text"] + [@value="2"] + /following-sibling::input + [@id="name_day"] + [@type="text"] + [@value="3"] + /following-sibling::input + [@id="name_year"] + [@type="text"] + [@value="2011"] + ] + [count(./input)=3] +' + ); + } + + public function testDateSingleText() + { + $form = $this->factory->createNamed('name', 'date', '2011-02-03', array( + 'input' => 'string', + 'widget' => 'single_text', + )); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/input + [@type="date"] + [@name="name"] + [@value="2011-02-03"] +' + ); + } + + public function testDateErrorBubbling() + { + $form = $this->factory->createNamedBuilder('form', 'form') + ->add('date', 'date') + ->getForm(); + $form->get('date')->addError(new FormError('[trans]Error![/trans]')); + $view = $form->createView(); + + $this->assertEmpty($this->renderErrors($view)); + $this->assertNotEmpty($this->renderErrors($view['date'])); + } + + public function testBirthDay() + { + $form = $this->factory->createNamed('name', 'birthday', '2000-02-03', array( + 'input' => 'string', + )); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/div + [ + ./select + [@id="name_month"] + [./option[@value="2"][@selected="selected"]] + /following-sibling::select + [@id="name_day"] + [./option[@value="3"][@selected="selected"]] + /following-sibling::select + [@id="name_year"] + [./option[@value="2000"][@selected="selected"]] + ] + [count(./select)=3] +' + ); + } + + public function testBirthDayWithEmptyValue() + { + $form = $this->factory->createNamed('name', 'birthday', '1950-01-01', array( + 'input' => 'string', + 'empty_value' => '', + 'required' => false, + )); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/div + [ + ./select + [@id="name_month"] + [./option[@value=""][not(@selected)][not(@disabled)][.="[trans][/trans]"]] + [./option[@value="1"][@selected="selected"]] + /following-sibling::select + [@id="name_day"] + [./option[@value=""][not(@selected)][not(@disabled)][.="[trans][/trans]"]] + [./option[@value="1"][@selected="selected"]] + /following-sibling::select + [@id="name_year"] + [./option[@value=""][not(@selected)][not(@disabled)][.="[trans][/trans]"]] + [./option[@value="1950"][@selected="selected"]] + ] + [count(./select)=3] +' + ); + } + + public function testEmail() + { + $form = $this->factory->createNamed('name', 'email', 'foo&bar'); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/input + [@type="email"] + [@name="name"] + [@value="foo&bar"] + [not(@maxlength)] +' + ); + } + + public function testEmailWithMaxLength() + { + $form = $this->factory->createNamed('name', 'email', 'foo&bar', array( + 'max_length' => 123, + )); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/input + [@type="email"] + [@name="name"] + [@value="foo&bar"] + [@maxlength="123"] +' + ); + } + + public function testFile() + { + $form = $this->factory->createNamed('name', 'file'); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/input + [@type="file"] +' + ); + } + + public function testHidden() + { + $form = $this->factory->createNamed('name', 'hidden', 'foo&bar'); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/input + [@type="hidden"] + [@name="name"] + [@value="foo&bar"] +' + ); + } + + public function testReadOnly() + { + $form = $this->factory->createNamed('name', 'text', null, array( + 'read_only' => true, + )); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/input + [@type="text"] + [@name="name"] + [@readonly="readonly"] +' + ); + } + + public function testDisabled() + { + $form = $this->factory->createNamed('name', 'text', null, array( + 'disabled' => true, + )); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/input + [@type="text"] + [@name="name"] + [@disabled="disabled"] +' + ); + } + + public function testInteger() + { + $form = $this->factory->createNamed('name', 'integer', 123); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/input + [@type="number"] + [@name="name"] + [@value="123"] +' + ); + } + + public function testLanguage() + { + $form = $this->factory->createNamed('name', 'language', 'de'); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/select + [@name="name"] + [./option[@value="de"][@selected="selected"][.="[trans]German[/trans]"]] + [count(./option)>200] +' + ); + } + + public function testLocale() + { + $form = $this->factory->createNamed('name', 'locale', 'de_AT'); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/select + [@name="name"] + [./option[@value="de_AT"][@selected="selected"][.="[trans]German (Austria)[/trans]"]] + [count(./option)>200] +' + ); + } + + public function testMoney() + { + $form = $this->factory->createNamed('name', 'money', 1234.56, array( + 'currency' => 'EUR', + )); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/input + [@type="text"] + [@name="name"] + [@value="1234.56"] + [contains(.., "€")] +' + ); + } + + public function testNumber() + { + $form = $this->factory->createNamed('name', 'number', 1234.56); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/input + [@type="text"] + [@name="name"] + [@value="1234.56"] +' + ); + } + + public function testPassword() + { + $form = $this->factory->createNamed('name', 'password', 'foo&bar'); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/input + [@type="password"] + [@name="name"] +' + ); + } + + public function testPasswordSubmittedWithNotAlwaysEmpty() + { + $form = $this->factory->createNamed('name', 'password', null, array( + 'always_empty' => false, + )); + $form->submit('foo&bar'); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/input + [@type="password"] + [@name="name"] + [@value="foo&bar"] +' + ); + } + + public function testPasswordWithMaxLength() + { + $form = $this->factory->createNamed('name', 'password', 'foo&bar', array( + 'max_length' => 123, + )); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/input + [@type="password"] + [@name="name"] + [@maxlength="123"] +' + ); + } + + public function testPercent() + { + $form = $this->factory->createNamed('name', 'percent', 0.1); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/input + [@type="text"] + [@name="name"] + [@value="10"] + [contains(.., "%")] +' + ); + } + + public function testCheckedRadio() + { + $form = $this->factory->createNamed('name', 'radio', true); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/input + [@type="radio"] + [@name="name"] + [@checked="checked"] + [@value="1"] +' + ); + } + + public function testUncheckedRadio() + { + $form = $this->factory->createNamed('name', 'radio', false); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/input + [@type="radio"] + [@name="name"] + [not(@checked)] +' + ); + } + + public function testRadioWithValue() + { + $form = $this->factory->createNamed('name', 'radio', false, array( + 'value' => 'foo&bar', + )); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/input + [@type="radio"] + [@name="name"] + [@value="foo&bar"] +' + ); + } + + public function testTextarea() + { + $form = $this->factory->createNamed('name', 'textarea', 'foo&bar', array( + 'pattern' => 'foo', + )); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/textarea + [@name="name"] + [not(@pattern)] + [.="foo&bar"] +' + ); + } + + public function testText() + { + $form = $this->factory->createNamed('name', 'text', 'foo&bar'); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/input + [@type="text"] + [@name="name"] + [@value="foo&bar"] + [not(@maxlength)] +' + ); + } + + public function testTextWithMaxLength() + { + $form = $this->factory->createNamed('name', 'text', 'foo&bar', array( + 'max_length' => 123, + )); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/input + [@type="text"] + [@name="name"] + [@value="foo&bar"] + [@maxlength="123"] +' + ); + } + + public function testSearch() + { + $form = $this->factory->createNamed('name', 'search', 'foo&bar'); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/input + [@type="search"] + [@name="name"] + [@value="foo&bar"] + [not(@maxlength)] +' + ); + } + + public function testTime() + { + $form = $this->factory->createNamed('name', 'time', '04:05:06', array( + 'input' => 'string', + 'with_seconds' => false, + )); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/div + [ + ./select + [@id="name_hour"] + [not(@size)] + [./option[@value="4"][@selected="selected"]] + /following-sibling::select + [@id="name_minute"] + [not(@size)] + [./option[@value="5"][@selected="selected"]] + ] + [count(./select)=2] +' + ); + } + + public function testTimeWithSeconds() + { + $form = $this->factory->createNamed('name', 'time', '04:05:06', array( + 'input' => 'string', + 'with_seconds' => true, + )); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/div + [ + ./select + [@id="name_hour"] + [not(@size)] + [./option[@value="4"][@selected="selected"]] + [count(./option)>23] + /following-sibling::select + [@id="name_minute"] + [not(@size)] + [./option[@value="5"][@selected="selected"]] + [count(./option)>59] + /following-sibling::select + [@id="name_second"] + [not(@size)] + [./option[@value="6"][@selected="selected"]] + [count(./option)>59] + ] + [count(./select)=3] +' + ); + } + + public function testTimeText() + { + $form = $this->factory->createNamed('name', 'time', '04:05:06', array( + 'input' => 'string', + 'widget' => 'text', + )); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/div + [ + ./input + [@type="text"] + [@id="name_hour"] + [@name="name[hour]"] + [@value="04"] + [@size="1"] + [@required="required"] + /following-sibling::input + [@type="text"] + [@id="name_minute"] + [@name="name[minute]"] + [@value="05"] + [@size="1"] + [@required="required"] + ] + [count(./input)=2] +' + ); + } + + public function testTimeSingleText() + { + $form = $this->factory->createNamed('name', 'time', '04:05:06', array( + 'input' => 'string', + 'widget' => 'single_text', + )); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/input + [@type="time"] + [@name="name"] + [@value="04:05"] + [not(@size)] +' + ); + } + + public function testTimeWithEmptyValueGlobal() + { + $form = $this->factory->createNamed('name', 'time', null, array( + 'input' => 'string', + 'empty_value' => 'Change&Me', + 'required' => false, + )); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/div + [ + ./select + [@id="name_hour"] + [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]] + [count(./option)>24] + /following-sibling::select + [@id="name_minute"] + [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]] + [count(./option)>60] + ] + [count(./select)=2] +' + ); + } + + public function testTimeWithEmptyValueOnYear() + { + $form = $this->factory->createNamed('name', 'time', null, array( + 'input' => 'string', + 'required' => false, + 'empty_value' => array('hour' => 'Change&Me'), + )); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/div + [ + ./select + [@id="name_hour"] + [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]] + [count(./option)>24] + /following-sibling::select + [@id="name_minute"] + [./option[@value="1"]] + [count(./option)>59] + ] + [count(./select)=2] +' + ); + } + + public function testTimeErrorBubbling() + { + $form = $this->factory->createNamedBuilder('form', 'form') + ->add('time', 'time') + ->getForm(); + $form->get('time')->addError(new FormError('[trans]Error![/trans]')); + $view = $form->createView(); + + $this->assertEmpty($this->renderErrors($view)); + $this->assertNotEmpty($this->renderErrors($view['time'])); + } + + public function testTimezone() + { + $form = $this->factory->createNamed('name', 'timezone', 'Europe/Vienna'); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/select + [@name="name"] + [@required="required"] + [./optgroup + [@label="[trans]Europe[/trans]"] + [./option[@value="Europe/Vienna"][@selected="selected"][.="[trans]Vienna[/trans]"]] + ] + [count(./optgroup)>10] + [count(.//option)>200] +' + ); + } + + public function testTimezoneWithEmptyValue() + { + $form = $this->factory->createNamed('name', 'timezone', null, array( + 'empty_value' => 'Select&Timezone', + 'required' => false, + )); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/select + [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Select&Timezone[/trans]"]] + [count(./optgroup)>10] + [count(.//option)>201] +' + ); + } + + public function testUrl() + { + $url = 'http://www.google.com?foo1=bar1&foo2=bar2'; + $form = $this->factory->createNamed('name', 'url', $url); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/input + [@type="url"] + [@name="name"] + [@value="http://www.google.com?foo1=bar1&foo2=bar2"] +' + ); + } + + public function testCollectionPrototype() + { + $form = $this->factory->createNamedBuilder('name', 'form', array('items' => array('one', 'two', 'three'))) + ->add('items', 'collection', array('allow_add' => true)) + ->getForm() + ->createView(); + + $html = $this->renderWidget($form); + + $this->assertMatchesXpath($html, + '//div[@id="name_items"][@data-prototype] + | + //table[@id="name_items"][@data-prototype]' + ); + } + + public function testEmptyRootFormName() + { + $form = $this->factory->createNamedBuilder('', 'form') + ->add('child', 'text') + ->getForm(); + + $this->assertMatchesXpath($this->renderWidget($form->createView()), + '//input[@type="hidden"][@id="_token"][@name="_token"] + | + //input[@type="text"][@id="child"][@name="child"]' + , 2); + } + + public function testButton() + { + $form = $this->factory->createNamed('name', 'button'); + + $this->assertWidgetMatchesXpath($form->createView(), array(), + '/button[@type="button"][@name="name"][.="[trans]Name[/trans]"]' + ); + } + + public function testButtonLabelIsEmpty() + { + $form = $this->factory->createNamed('name', 'button'); + + $this->assertSame('', $this->renderLabel($form->createView())); + } + + public function testSubmit() + { + $form = $this->factory->createNamed('name', 'submit'); + + $this->assertWidgetMatchesXpath($form->createView(), array(), + '/button[@type="submit"][@name="name"]' + ); + } + + public function testReset() + { + $form = $this->factory->createNamed('name', 'reset'); + + $this->assertWidgetMatchesXpath($form->createView(), array(), + '/button[@type="reset"][@name="name"]' + ); + } + + public function testStartTag() + { + $form = $this->factory->create('form', null, array( + 'method' => 'get', + 'action' => 'http://example.com/directory' + )); + + $html = $this->renderStart($form->createView()); + + $this->assertSame('
', $html); + } + + public function testStartTagForPutRequest() + { + $form = $this->factory->create('form', null, array( + 'method' => 'put', + 'action' => 'http://example.com/directory' + )); + + $html = $this->renderStart($form->createView()); + + $this->assertMatchesXpath($html . '
', +'/form + [./input[@type="hidden"][@name="_method"][@value="PUT"]] + [@method="post"] + [@action="http://example.com/directory"]' + ); + } + + public function testStartTagWithOverriddenVars() + { + $form = $this->factory->create('form', null, array( + 'method' => 'put', + 'action' => 'http://example.com/directory', + )); + + $html = $this->renderStart($form->createView(), array( + 'method' => 'post', + 'action' => 'http://foo.com/directory' + )); + + $this->assertSame('
', $html); + } + + public function testStartTagForMultipartForm() + { + $form = $this->factory->createBuilder('form', null, array( + 'method' => 'get', + 'action' => 'http://example.com/directory' + )) + ->add('file', 'file') + ->getForm(); + + $html = $this->renderStart($form->createView()); + + $this->assertSame('', $html); + } + + public function testStartTagWithExtraAttributes() + { + $form = $this->factory->create('form', null, array( + 'method' => 'get', + 'action' => 'http://example.com/directory' + )); + + $html = $this->renderStart($form->createView(), array( + 'attr' => array('class' => 'foobar'), + )); + + $this->assertSame('', $html); + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/AbstractRequestHandlerTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/AbstractRequestHandlerTest.php new file mode 100644 index 00000000..cef8f3bf --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/AbstractRequestHandlerTest.php @@ -0,0 +1,280 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests; + +/** + * @author Bernhard Schussek + */ +abstract class AbstractRequestHandlerTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Symfony\Component\Form\RequestHandlerInterface + */ + protected $requestHandler; + + protected $request; + + protected function setUp() + { + $this->requestHandler = $this->getRequestHandler(); + $this->request = null; + } + + public function methodExceptGetProvider() + { + return array( + array('POST'), + array('PUT'), + array('DELETE'), + array('PATCH'), + ); + } + + public function methodProvider() + { + return array_merge(array( + array('GET'), + ), $this->methodExceptGetProvider()); + } + + /** + * @dataProvider methodProvider + */ + public function testSubmitIfNameInRequest($method) + { + $form = $this->getMockForm('param1', $method); + + $this->setRequestData($method, array( + 'param1' => 'DATA', + )); + + $form->expects($this->once()) + ->method('submit') + ->with('DATA', 'PATCH' !== $method); + + $this->requestHandler->handleRequest($form, $this->request); + } + + /** + * @dataProvider methodProvider + */ + public function testDoNotSubmitIfWrongRequestMethod($method) + { + $form = $this->getMockForm('param1', $method); + + $otherMethod = 'POST' === $method ? 'PUT' : 'POST'; + + $this->setRequestData($otherMethod, array( + 'param1' => 'DATA', + )); + + $form->expects($this->never()) + ->method('submit'); + + $this->requestHandler->handleRequest($form, $this->request); + } + + /** + * @dataProvider methodExceptGetProvider + */ + public function testSubmitSimpleFormWithNullIfNameNotInRequestAndNotGetRequest($method) + { + $form = $this->getMockForm('param1', $method, false); + + $this->setRequestData($method, array( + 'paramx' => array(), + )); + + $form->expects($this->once()) + ->method('submit') + ->with($this->identicalTo(null), 'PATCH' !== $method); + + $this->requestHandler->handleRequest($form, $this->request); + } + + /** + * @dataProvider methodExceptGetProvider + */ + public function testSubmitCompoundFormWithArrayIfNameNotInRequestAndNotGetRequest($method) + { + $form = $this->getMockForm('param1', $method, true); + + $this->setRequestData($method, array( + 'paramx' => array(), + )); + + $form->expects($this->once()) + ->method('submit') + ->with($this->identicalTo(array()), 'PATCH' !== $method); + + $this->requestHandler->handleRequest($form, $this->request); + } + + public function testDoNotSubmitIfNameNotInRequestAndGetRequest() + { + $form = $this->getMockForm('param1', 'GET'); + + $this->setRequestData('GET', array( + 'paramx' => array(), + )); + + $form->expects($this->never()) + ->method('submit'); + + $this->requestHandler->handleRequest($form, $this->request); + } + + /** + * @dataProvider methodProvider + */ + public function testSubmitFormWithEmptyNameIfAtLeastOneFieldInRequest($method) + { + $form = $this->getMockForm('', $method); + $form->expects($this->any()) + ->method('all') + ->will($this->returnValue(array( + 'param1' => $this->getMockForm('param1'), + 'param2' => $this->getMockForm('param2'), + ))); + + $this->setRequestData($method, $requestData = array( + 'param1' => 'submitted value', + 'paramx' => 'submitted value', + )); + + $form->expects($this->once()) + ->method('submit') + ->with($requestData, 'PATCH' !== $method); + + $this->requestHandler->handleRequest($form, $this->request); + } + + /** + * @dataProvider methodProvider + */ + public function testDoNotSubmitFormWithEmptyNameIfNoFieldInRequest($method) + { + $form = $this->getMockForm('', $method); + $form->expects($this->any()) + ->method('all') + ->will($this->returnValue(array( + 'param1' => $this->getMockForm('param1'), + 'param2' => $this->getMockForm('param2'), + ))); + + $this->setRequestData($method, array( + 'paramx' => 'submitted value', + )); + + $form->expects($this->never()) + ->method('submit'); + + $this->requestHandler->handleRequest($form, $this->request); + } + + /** + * @dataProvider methodExceptGetProvider + */ + public function testMergeParamsAndFiles($method) + { + $form = $this->getMockForm('param1', $method); + $file = $this->getMockFile(); + + $this->setRequestData($method, array( + 'param1' => array( + 'field1' => 'DATA', + ), + ), array( + 'param1' => array( + 'field2' => $file, + ), + )); + + $form->expects($this->once()) + ->method('submit') + ->with(array( + 'field1' => 'DATA', + 'field2' => $file, + ), 'PATCH' !== $method); + + $this->requestHandler->handleRequest($form, $this->request); + } + + /** + * @dataProvider methodExceptGetProvider + */ + public function testParamTakesPrecedenceOverFile($method) + { + $form = $this->getMockForm('param1', $method); + $file = $this->getMockFile(); + + $this->setRequestData($method, array( + 'param1' => 'DATA', + ), array( + 'param1' => $file, + )); + + $form->expects($this->once()) + ->method('submit') + ->with('DATA', 'PATCH' !== $method); + + $this->requestHandler->handleRequest($form, $this->request); + } + + /** + * @dataProvider methodExceptGetProvider + */ + public function testSubmitFileIfNoParam($method) + { + $form = $this->getMockForm('param1', $method); + $file = $this->getMockFile(); + + $this->setRequestData($method, array( + 'param1' => null, + ), array( + 'param1' => $file, + )); + + $form->expects($this->once()) + ->method('submit') + ->with($file, 'PATCH' !== $method); + + $this->requestHandler->handleRequest($form, $this->request); + } + + abstract protected function setRequestData($method, $data, $files = array()); + + abstract protected function getRequestHandler(); + + abstract protected function getMockFile(); + + protected function getMockForm($name, $method = null, $compound = true) + { + $config = $this->getMock('Symfony\Component\Form\FormConfigInterface'); + $config->expects($this->any()) + ->method('getMethod') + ->will($this->returnValue($method)); + $config->expects($this->any()) + ->method('getCompound') + ->will($this->returnValue($compound)); + + $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); + $form->expects($this->any()) + ->method('getName') + ->will($this->returnValue($name)); + $form->expects($this->any()) + ->method('getConfig') + ->will($this->returnValue($config)); + + return $form; + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/AbstractTableLayoutTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/AbstractTableLayoutTest.php new file mode 100644 index 00000000..5c911951 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/AbstractTableLayoutTest.php @@ -0,0 +1,509 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests; + +use Symfony\Component\Form\FormError; + +abstract class AbstractTableLayoutTest extends AbstractLayoutTest +{ + public function testRow() + { + $form = $this->factory->createNamed('name', 'text'); + $form->addError(new FormError('[trans]Error![/trans]')); + $view = $form->createView(); + $html = $this->renderRow($view); + + $this->assertMatchesXpath($html, +'/tr + [ + ./td + [./label[@for="name"]] + /following-sibling::td + [ + ./ul + [./li[.="[trans]Error![/trans]"]] + [count(./li)=1] + /following-sibling::input[@id="name"] + ] + ] +' + ); + } + + public function testLabelIsNotRenderedWhenSetToFalse() + { + $form = $this->factory->createNamed('name', 'text', null, array( + 'label' => false + )); + $html = $this->renderRow($form->createView()); + + $this->assertMatchesXpath($html, +'/tr + [ + ./td + [count(//label)=0] + /following-sibling::td + [./input[@id="name"]] + ] +' + ); + } + + public function testRepeatedRow() + { + $form = $this->factory->createNamed('name', 'repeated'); + $html = $this->renderRow($form->createView()); + + $this->assertMatchesXpath($html, +'/tr + [ + ./td + [./label[@for="name_first"]] + /following-sibling::td + [./input[@id="name_first"]] + ] +/following-sibling::tr + [ + ./td + [./label[@for="name_second"]] + /following-sibling::td + [./input[@id="name_second"]] + ] +/following-sibling::tr[@style="display: none"] + [./td[@colspan="2"]/input + [@type="hidden"] + [@id="name__token"] + ] + [count(../tr)=3] +' + ); + } + + public function testRepeatedRowWithErrors() + { + $form = $this->factory->createNamed('name', 'repeated'); + $form->addError(new FormError('[trans]Error![/trans]')); + $view = $form->createView(); + $html = $this->renderRow($view); + + // The errors of the form are not rendered by intention! + // In practice, repeated fields cannot have errors as all errors + // on them are mapped to the first child. + // (see RepeatedTypeValidatorExtension) + + $this->assertMatchesXpath($html, +'/tr + [ + ./td + [./label[@for="name_first"]] + /following-sibling::td + [./input[@id="name_first"]] + ] +/following-sibling::tr + [ + ./td + [./label[@for="name_second"]] + /following-sibling::td + [./input[@id="name_second"]] + ] +/following-sibling::tr[@style="display: none"] + [./td[@colspan="2"]/input + [@type="hidden"] + [@id="name__token"] + ] + [count(../tr)=3] +' + ); + } + + public function testButtonRow() + { + $form = $this->factory->createNamed('name', 'button'); + $view = $form->createView(); + $html = $this->renderRow($view); + + $this->assertMatchesXpath($html, +'/tr + [ + ./td + [.=""] + /following-sibling::td + [./button[@type="button"][@name="name"]] + ] + [count(//label)=0] +' + ); + } + + public function testRest() + { + $view = $this->factory->createNamedBuilder('name', 'form') + ->add('field1', 'text') + ->add('field2', 'repeated') + ->add('field3', 'text') + ->add('field4', 'text') + ->getForm() + ->createView(); + + // Render field2 row -> does not implicitly call renderWidget because + // it is a repeated field! + $this->renderRow($view['field2']); + + // Render field3 widget + $this->renderWidget($view['field3']); + + // Rest should only contain field1 and field4 + $html = $this->renderRest($view); + + $this->assertMatchesXpath($html, +'/tr + [ + ./td + [./label[@for="name_field1"]] + /following-sibling::td + [./input[@id="name_field1"]] + ] +/following-sibling::tr + [ + ./td + [./label[@for="name_field4"]] + /following-sibling::td + [./input[@id="name_field4"]] + ] + [count(../tr)=3] + [count(..//label)=2] + [count(..//input)=3] +/following-sibling::tr[@style="display: none"] + [./td[@colspan="2"]/input + [@type="hidden"] + [@id="name__token"] + ] +' + ); + } + + public function testCollection() + { + $form = $this->factory->createNamed('name', 'collection', array('a', 'b'), array( + 'type' => 'text', + )); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/table + [ + ./tr[./td/input[@type="text"][@value="a"]] + /following-sibling::tr[./td/input[@type="text"][@value="b"]] + /following-sibling::tr[@style="display: none"][./td[@colspan="2"]/input[@type="hidden"][@id="name__token"]] + ] + [count(./tr[./td/input])=3] +' + ); + } + + public function testEmptyCollection() + { + $form = $this->factory->createNamed('name', 'collection', array(), array( + 'type' => 'text', + )); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/table + [./tr[@style="display: none"][./td[@colspan="2"]/input[@type="hidden"][@id="name__token"]]] + [count(./tr[./td/input])=1] +' + ); + } + + public function testForm() + { + $view = $this->factory->createNamedBuilder('name', 'form') + ->setMethod('PUT') + ->setAction('http://example.com') + ->add('firstName', 'text') + ->add('lastName', 'text') + ->getForm() + ->createView(); + + $html = $this->renderForm($view, array( + 'id' => 'my&id', + 'attr' => array('class' => 'my&class'), + )); + + $this->assertMatchesXpath($html, +'/form + [ + ./input[@type="hidden"][@name="_method"][@value="PUT"] + /following-sibling::table + [ + ./tr + [ + ./td + [./label[@for="name_firstName"]] + /following-sibling::td + [./input[@id="name_firstName"]] + ] + /following-sibling::tr + [ + ./td + [./label[@for="name_lastName"]] + /following-sibling::td + [./input[@id="name_lastName"]] + ] + /following-sibling::tr[@style="display: none"] + [./td[@colspan="2"]/input + [@type="hidden"] + [@id="name__token"] + ] + ] + [count(.//input)=3] + [@id="my&id"] + [@class="my&class"] + ] + [@method="post"] + [@action="http://example.com"] + [@class="my&class"] +' + ); + } + + public function testFormWidget() + { + $view = $this->factory->createNamedBuilder('name', 'form') + ->add('firstName', 'text') + ->add('lastName', 'text') + ->getForm() + ->createView(); + + $this->assertWidgetMatchesXpath($view, array(), +'/table + [ + ./tr + [ + ./td + [./label[@for="name_firstName"]] + /following-sibling::td + [./input[@id="name_firstName"]] + ] + /following-sibling::tr + [ + ./td + [./label[@for="name_lastName"]] + /following-sibling::td + [./input[@id="name_lastName"]] + ] + /following-sibling::tr[@style="display: none"] + [./td[@colspan="2"]/input + [@type="hidden"] + [@id="name__token"] + ] + ] + [count(.//input)=3] +' + ); + } + + // https://github.com/symfony/symfony/issues/2308 + public function testNestedFormError() + { + $form = $this->factory->createNamedBuilder('name', 'form') + ->add($this->factory + ->createNamedBuilder('child', 'form', null, array('error_bubbling' => false)) + ->add('grandChild', 'form') + ) + ->getForm(); + + $form->get('child')->addError(new FormError('[trans]Error![/trans]')); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/table + [ + ./tr/td/ul[./li[.="[trans]Error![/trans]"]] + /following-sibling::table[@id="name_child"] + ] + [count(.//li[.="[trans]Error![/trans]"])=1] +' + ); + } + + public function testCsrf() + { + $this->csrfProvider->expects($this->any()) + ->method('generateCsrfToken') + ->will($this->returnValue('foo&bar')); + + $form = $this->factory->createNamedBuilder('name', 'form') + ->add($this->factory + // No CSRF protection on nested forms + ->createNamedBuilder('child', 'form') + ->add($this->factory->createNamedBuilder('grandchild', 'text')) + ) + ->getForm(); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/table + [ + ./tr[@style="display: none"] + [./td[@colspan="2"]/input + [@type="hidden"] + [@id="name__token"] + ] + ] + [count(.//input[@type="hidden"])=1] +' + ); + } + + public function testRepeated() + { + $form = $this->factory->createNamed('name', 'repeated', 'foobar', array( + 'type' => 'text', + )); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/table + [ + ./tr + [ + ./td + [./label[@for="name_first"]] + /following-sibling::td + [./input[@type="text"][@id="name_first"]] + ] + /following-sibling::tr + [ + ./td + [./label[@for="name_second"]] + /following-sibling::td + [./input[@type="text"][@id="name_second"]] + ] + /following-sibling::tr[@style="display: none"] + [./td[@colspan="2"]/input + [@type="hidden"] + [@id="name__token"] + ] + ] + [count(.//input)=3] +' + ); + } + + public function testRepeatedWithCustomOptions() + { + $form = $this->factory->createNamed('name', 'repeated', 'foobar', array( + 'type' => 'password', + 'first_options' => array('label' => 'Test', 'required' => false), + 'second_options' => array('label' => 'Test2') + )); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/table + [ + ./tr + [ + ./td + [./label[@for="name_first"][.="[trans]Test[/trans]"]] + /following-sibling::td + [./input[@type="password"][@id="name_first"][@required="required"]] + ] + /following-sibling::tr + [ + ./td + [./label[@for="name_second"][.="[trans]Test2[/trans]"]] + /following-sibling::td + [./input[@type="password"][@id="name_second"][@required="required"]] + ] + /following-sibling::tr[@style="display: none"] + [./td[@colspan="2"]/input + [@type="hidden"] + [@id="name__token"] + ] + ] + [count(.//input)=3] +' + ); + } + + /** + * The block "_name_child_label" should be overridden in the theme of the + * implemented driver. + */ + public function testCollectionRowWithCustomBlock() + { + $collection = array('one', 'two', 'three'); + $form = $this->factory->createNamedBuilder('name', 'collection', $collection) + ->getForm(); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/table + [ + ./tr[./td/label[.="Custom label: [trans]0[/trans]"]] + /following-sibling::tr[./td/label[.="Custom label: [trans]1[/trans]"]] + /following-sibling::tr[./td/label[.="Custom label: [trans]2[/trans]"]] + ] +' + ); + } + + public function testFormEndWithRest() + { + $view = $this->factory->createNamedBuilder('name', 'form') + ->add('field1', 'text') + ->add('field2', 'text') + ->getForm() + ->createView(); + + $this->renderWidget($view['field1']); + + // Rest should only contain field2 + $html = $this->renderEnd($view); + + // Insert the start tag, the end tag should be rendered by the helper + // Unfortunately this is not valid HTML, because the surrounding table + // tag is missing. If someone renders a form with table layout + // manually, she should call form_rest() explicitly within the + // tag. + $this->assertMatchesXpath('' . $html, +'/form + [ + ./tr + [ + ./td + [./label[@for="name_field2"]] + /following-sibling::td + [./input[@id="name_field2"]] + ] + /following-sibling::tr[@style="display: none"] + [./td[@colspan="2"]/input + [@type="hidden"] + [@id="name__token"] + ] + ] +' + ); + } + + public function testFormEndWithoutRest() + { + $view = $this->factory->createNamedBuilder('name', 'form') + ->add('field1', 'text') + ->add('field2', 'text') + ->getForm() + ->createView(); + + $this->renderWidget($view['field1']); + + // Rest should only contain field2, but isn't rendered + $html = $this->renderEnd($view, array('render_rest' => false)); + + $this->assertEquals('', $html); + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/CompoundFormPerformanceTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/CompoundFormPerformanceTest.php new file mode 100644 index 00000000..73c602c5 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/CompoundFormPerformanceTest.php @@ -0,0 +1,48 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests; + +/** + * @author Bernhard Schussek + */ +class CompoundFormPerformanceTest extends \Symfony\Component\Form\Tests\FormPerformanceTestCase +{ + /** + * Create a compound form multiple times, as happens in a collection form + * + * @group benchmark + */ + public function testArrayBasedForm() + { + $this->setMaxRunningTime(1); + + for ($i = 0; $i < 40; ++$i) { + $form = $this->factory->createBuilder('form') + ->add('firstName', 'text') + ->add('lastName', 'text') + ->add('gender', 'choice', array( + 'choices' => array('male' => 'Male', 'female' => 'Female'), + 'required' => false, + )) + ->add('age', 'number') + ->add('birthDate', 'birthday') + ->add('city', 'choice', array( + // simulate 300 different cities + 'choices' => range(1, 300), + )) + ->getForm(); + + // load the form into a view + $form->createView(); + } + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/CompoundFormTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/CompoundFormTest.php new file mode 100644 index 00000000..b240d2d0 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/CompoundFormTest.php @@ -0,0 +1,759 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests; + +use Symfony\Component\Form\Extension\HttpFoundation\HttpFoundationRequestHandler; +use Symfony\Component\Form\FormError; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\File\UploadedFile; +use Symfony\Component\Form\Tests\Fixtures\FixedDataTransformer; + +class CompoundFormTest extends AbstractFormTest +{ + public function testValidIfAllChildrenAreValid() + { + $this->form->add($this->getValidForm('firstName')); + $this->form->add($this->getValidForm('lastName')); + + $this->form->submit(array( + 'firstName' => 'Bernhard', + 'lastName' => 'Schussek', + )); + + $this->assertTrue($this->form->isValid()); + } + + public function testInvalidIfChildIsInvalid() + { + $this->form->add($this->getValidForm('firstName')); + $this->form->add($this->getInvalidForm('lastName')); + + $this->form->submit(array( + 'firstName' => 'Bernhard', + 'lastName' => 'Schussek', + )); + + $this->assertFalse($this->form->isValid()); + } + + public function testSubmitForwardsNullIfValueIsMissing() + { + $child = $this->getMockForm('firstName'); + + $this->form->add($child); + + $child->expects($this->once()) + ->method('submit') + ->with($this->equalTo(null)); + + $this->form->submit(array()); + } + + public function testSubmitDoesNotForwardNullIfNotClearMissing() + { + $child = $this->getMockForm('firstName'); + + $this->form->add($child); + + $child->expects($this->never()) + ->method('submit'); + + $this->form->submit(array(), false); + } + + public function testClearMissingFlagIsForwarded() + { + $child = $this->getMockForm('firstName'); + + $this->form->add($child); + + $child->expects($this->once()) + ->method('submit') + ->with($this->equalTo('foo'), false); + + $this->form->submit(array('firstName' => 'foo'), false); + } + + public function testCloneChildren() + { + $child = $this->getBuilder('child')->getForm(); + $this->form->add($child); + + $clone = clone $this->form; + + $this->assertNotSame($this->form, $clone); + $this->assertNotSame($child, $clone['child']); + } + + public function testNotEmptyIfChildNotEmpty() + { + $child = $this->getMockForm(); + $child->expects($this->once()) + ->method('isEmpty') + ->will($this->returnValue(false)); + + $this->form->setData(null); + $this->form->add($child); + + $this->assertFalse($this->form->isEmpty()); + } + + public function testValidIfSubmittedAndDisabledWithChildren() + { + $this->factory->expects($this->once()) + ->method('createNamedBuilder') + ->with('name', 'text', null, array()) + ->will($this->returnValue($this->getBuilder('name'))); + + $form = $this->getBuilder('person') + ->setDisabled(true) + ->setCompound(true) + ->setDataMapper($this->getDataMapper()) + ->add('name', 'text') + ->getForm(); + $form->submit(array('name' => 'Jacques Doe')); + + $this->assertTrue($form->isValid()); + } + + public function testNotValidIfChildNotValid() + { + $child = $this->getMockForm(); + $child->expects($this->once()) + ->method('isValid') + ->will($this->returnValue(false)); + + $this->form->add($child); + $this->form->submit(array()); + + $this->assertFalse($this->form->isValid()); + } + + public function testAdd() + { + $child = $this->getBuilder('foo')->getForm(); + $this->form->add($child); + + $this->assertTrue($this->form->has('foo')); + $this->assertSame($this->form, $child->getParent()); + $this->assertSame(array('foo' => $child), $this->form->all()); + } + + public function testAddUsingNameAndType() + { + $child = $this->getBuilder('foo')->getForm(); + + $this->factory->expects($this->once()) + ->method('createNamed') + ->with('foo', 'text', null, array( + 'bar' => 'baz', + 'auto_initialize' => false, + )) + ->will($this->returnValue($child)); + + $this->form->add('foo', 'text', array('bar' => 'baz')); + + $this->assertTrue($this->form->has('foo')); + $this->assertSame($this->form, $child->getParent()); + $this->assertSame(array('foo' => $child), $this->form->all()); + } + + public function testAddUsingIntegerNameAndType() + { + $child = $this->getBuilder(0)->getForm(); + + $this->factory->expects($this->once()) + ->method('createNamed') + ->with('0', 'text', null, array( + 'bar' => 'baz', + 'auto_initialize' => false, + )) + ->will($this->returnValue($child)); + + // in order to make casting unnecessary + $this->form->add(0, 'text', array('bar' => 'baz')); + + $this->assertTrue($this->form->has(0)); + $this->assertSame($this->form, $child->getParent()); + $this->assertSame(array(0 => $child), $this->form->all()); + } + + public function testAddUsingNameButNoType() + { + $this->form = $this->getBuilder('name', null, '\stdClass') + ->setCompound(true) + ->setDataMapper($this->getDataMapper()) + ->getForm(); + + $child = $this->getBuilder('foo')->getForm(); + + $this->factory->expects($this->once()) + ->method('createForProperty') + ->with('\stdClass', 'foo') + ->will($this->returnValue($child)); + + $this->form->add('foo'); + + $this->assertTrue($this->form->has('foo')); + $this->assertSame($this->form, $child->getParent()); + $this->assertSame(array('foo' => $child), $this->form->all()); + } + + public function testAddUsingNameButNoTypeAndOptions() + { + $this->form = $this->getBuilder('name', null, '\stdClass') + ->setCompound(true) + ->setDataMapper($this->getDataMapper()) + ->getForm(); + + $child = $this->getBuilder('foo')->getForm(); + + $this->factory->expects($this->once()) + ->method('createForProperty') + ->with('\stdClass', 'foo', null, array( + 'bar' => 'baz', + 'auto_initialize' => false, + )) + ->will($this->returnValue($child)); + + $this->form->add('foo', null, array('bar' => 'baz')); + + $this->assertTrue($this->form->has('foo')); + $this->assertSame($this->form, $child->getParent()); + $this->assertSame(array('foo' => $child), $this->form->all()); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\AlreadySubmittedException + */ + public function testAddThrowsExceptionIfAlreadySubmitted() + { + $this->form->submit(array()); + $this->form->add($this->getBuilder('foo')->getForm()); + } + + public function testRemove() + { + $child = $this->getBuilder('foo')->getForm(); + $this->form->add($child); + $this->form->remove('foo'); + + $this->assertNull($child->getParent()); + $this->assertCount(0, $this->form); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\AlreadySubmittedException + */ + public function testRemoveThrowsExceptionIfAlreadySubmitted() + { + $this->form->add($this->getBuilder('foo')->setCompound(false)->getForm()); + $this->form->submit(array('foo' => 'bar')); + $this->form->remove('foo'); + } + + public function testRemoveIgnoresUnknownName() + { + $this->form->remove('notexisting'); + } + + public function testArrayAccess() + { + $child = $this->getBuilder('foo')->getForm(); + + $this->form[] = $child; + + $this->assertTrue(isset($this->form['foo'])); + $this->assertSame($child, $this->form['foo']); + + unset($this->form['foo']); + + $this->assertFalse(isset($this->form['foo'])); + } + + public function testCountable() + { + $this->form->add($this->getBuilder('foo')->getForm()); + $this->form->add($this->getBuilder('bar')->getForm()); + + $this->assertCount(2, $this->form); + } + + public function testIterator() + { + $this->form->add($this->getBuilder('foo')->getForm()); + $this->form->add($this->getBuilder('bar')->getForm()); + + $this->assertSame($this->form->all(), iterator_to_array($this->form)); + } + + public function testAddMapsViewDataToFormIfInitialized() + { + $test = $this; + $mapper = $this->getDataMapper(); + $form = $this->getBuilder() + ->setCompound(true) + ->setDataMapper($mapper) + ->addViewTransformer(new FixedDataTransformer(array( + '' => '', + 'foo' => 'bar', + ))) + ->setData('foo') + ->getForm(); + + $child = $this->getBuilder()->getForm(); + $mapper->expects($this->once()) + ->method('mapDataToForms') + ->with('bar', $this->isInstanceOf('\RecursiveIteratorIterator')) + ->will($this->returnCallback(function ($data, \RecursiveIteratorIterator $iterator) use ($child, $test) { + $test->assertInstanceOf('Symfony\Component\Form\Util\InheritDataAwareIterator', $iterator->getInnerIterator()); + $test->assertSame(array($child), iterator_to_array($iterator)); + })); + + $form->initialize(); + $form->add($child); + } + + public function testAddDoesNotMapViewDataToFormIfNotInitialized() + { + $mapper = $this->getDataMapper(); + $form = $this->getBuilder() + ->setCompound(true) + ->setDataMapper($mapper) + ->getForm(); + + $child = $this->getBuilder()->getForm(); + $mapper->expects($this->never()) + ->method('mapDataToForms'); + + $form->add($child); + } + + public function testAddDoesNotMapViewDataToFormIfInheritData() + { + $mapper = $this->getDataMapper(); + $form = $this->getBuilder() + ->setCompound(true) + ->setDataMapper($mapper) + ->setInheritData(true) + ->getForm(); + + $child = $this->getBuilder()->getForm(); + $mapper->expects($this->never()) + ->method('mapDataToForms'); + + $form->initialize(); + $form->add($child); + } + + public function testSetDataMapsViewDataToChildren() + { + $test = $this; + $mapper = $this->getDataMapper(); + $form = $this->getBuilder() + ->setCompound(true) + ->setDataMapper($mapper) + ->addViewTransformer(new FixedDataTransformer(array( + '' => '', + 'foo' => 'bar', + ))) + ->getForm(); + + $form->add($child1 = $this->getBuilder('firstName')->getForm()); + $form->add($child2 = $this->getBuilder('lastName')->getForm()); + + $mapper->expects($this->once()) + ->method('mapDataToForms') + ->with('bar', $this->isInstanceOf('\RecursiveIteratorIterator')) + ->will($this->returnCallback(function ($data, \RecursiveIteratorIterator $iterator) use ($child1, $child2, $test) { + $test->assertInstanceOf('Symfony\Component\Form\Util\InheritDataAwareIterator', $iterator->getInnerIterator()); + $test->assertSame(array('firstName' => $child1, 'lastName' => $child2), iterator_to_array($iterator)); + })); + + $form->setData('foo'); + } + + public function testSubmitMapsSubmittedChildrenOntoExistingViewData() + { + $test = $this; + $mapper = $this->getDataMapper(); + $form = $this->getBuilder() + ->setCompound(true) + ->setDataMapper($mapper) + ->addViewTransformer(new FixedDataTransformer(array( + '' => '', + 'foo' => 'bar', + ))) + ->setData('foo') + ->getForm(); + + $form->add($child1 = $this->getBuilder('firstName')->setCompound(false)->getForm()); + $form->add($child2 = $this->getBuilder('lastName')->setCompound(false)->getForm()); + + $mapper->expects($this->once()) + ->method('mapFormsToData') + ->with($this->isInstanceOf('\RecursiveIteratorIterator'), 'bar') + ->will($this->returnCallback(function (\RecursiveIteratorIterator $iterator) use ($child1, $child2, $test) { + $test->assertInstanceOf('Symfony\Component\Form\Util\InheritDataAwareIterator', $iterator->getInnerIterator()); + $test->assertSame(array('firstName' => $child1, 'lastName' => $child2), iterator_to_array($iterator)); + $test->assertEquals('Bernhard', $child1->getData()); + $test->assertEquals('Schussek', $child2->getData()); + })); + + $form->submit(array( + 'firstName' => 'Bernhard', + 'lastName' => 'Schussek', + )); + } + + public function testMapFormsToDataIsNotInvokedIfInheritData() + { + $mapper = $this->getDataMapper(); + $form = $this->getBuilder() + ->setCompound(true) + ->setDataMapper($mapper) + ->setInheritData(true) + ->addViewTransformer(new FixedDataTransformer(array( + '' => '', + 'foo' => 'bar', + ))) + ->getForm(); + + $form->add($child1 = $this->getBuilder('firstName')->setCompound(false)->getForm()); + $form->add($child2 = $this->getBuilder('lastName')->setCompound(false)->getForm()); + + $mapper->expects($this->never()) + ->method('mapFormsToData'); + + $form->submit(array( + 'firstName' => 'Bernhard', + 'lastName' => 'Schussek', + )); + } + + /* + * https://github.com/symfony/symfony/issues/4480 + */ + public function testSubmitRestoresViewDataIfCompoundAndEmpty() + { + $mapper = $this->getDataMapper(); + $object = new \stdClass(); + $form = $this->getBuilder('name', null, 'stdClass') + ->setCompound(true) + ->setDataMapper($mapper) + ->setData($object) + ->getForm(); + + $form->submit(array()); + + $this->assertSame($object, $form->getData()); + } + + public function testSubmitMapsSubmittedChildrenOntoEmptyData() + { + $test = $this; + $mapper = $this->getDataMapper(); + $object = new \stdClass(); + $form = $this->getBuilder() + ->setCompound(true) + ->setDataMapper($mapper) + ->setEmptyData($object) + ->setData(null) + ->getForm(); + + $form->add($child = $this->getBuilder('name')->setCompound(false)->getForm()); + + $mapper->expects($this->once()) + ->method('mapFormsToData') + ->with($this->isInstanceOf('\RecursiveIteratorIterator'), $object) + ->will($this->returnCallback(function (\RecursiveIteratorIterator $iterator) use ($child, $test) { + $test->assertInstanceOf('Symfony\Component\Form\Util\InheritDataAwareIterator', $iterator->getInnerIterator()); + $test->assertSame(array('name' => $child), iterator_to_array($iterator)); + })); + + $form->submit(array( + 'name' => 'Bernhard', + )); + } + + public function requestMethodProvider() + { + return array( + array('POST'), + array('PUT'), + array('DELETE'), + array('PATCH'), + ); + } + + /** + * @dataProvider requestMethodProvider + */ + public function testSubmitPostOrPutRequest($method) + { + if (!class_exists('Symfony\Component\HttpFoundation\Request')) { + $this->markTestSkipped('The "HttpFoundation" component is not available'); + } + + $path = tempnam(sys_get_temp_dir(), 'sf2'); + touch($path); + + $values = array( + 'author' => array( + 'name' => 'Bernhard', + 'image' => array('filename' => 'foobar.png'), + ), + ); + + $files = array( + 'author' => array( + 'error' => array('image' => UPLOAD_ERR_OK), + 'name' => array('image' => 'upload.png'), + 'size' => array('image' => 123), + 'tmp_name' => array('image' => $path), + 'type' => array('image' => 'image/png'), + ), + ); + + $request = new Request(array(), $values, array(), array(), $files, array( + 'REQUEST_METHOD' => $method, + )); + + $form = $this->getBuilder('author') + ->setMethod($method) + ->setCompound(true) + ->setDataMapper($this->getDataMapper()) + ->setRequestHandler(new HttpFoundationRequestHandler()) + ->getForm(); + $form->add($this->getBuilder('name')->getForm()); + $form->add($this->getBuilder('image')->getForm()); + + $form->handleRequest($request); + + $file = new UploadedFile($path, 'upload.png', 'image/png', 123, UPLOAD_ERR_OK); + + $this->assertEquals('Bernhard', $form['name']->getData()); + $this->assertEquals($file, $form['image']->getData()); + + unlink($path); + } + + /** + * @dataProvider requestMethodProvider + */ + public function testSubmitPostOrPutRequestWithEmptyRootFormName($method) + { + if (!class_exists('Symfony\Component\HttpFoundation\Request')) { + $this->markTestSkipped('The "HttpFoundation" component is not available'); + } + + $path = tempnam(sys_get_temp_dir(), 'sf2'); + touch($path); + + $values = array( + 'name' => 'Bernhard', + 'extra' => 'data', + ); + + $files = array( + 'image' => array( + 'error' => UPLOAD_ERR_OK, + 'name' => 'upload.png', + 'size' => 123, + 'tmp_name' => $path, + 'type' => 'image/png', + ), + ); + + $request = new Request(array(), $values, array(), array(), $files, array( + 'REQUEST_METHOD' => $method, + )); + + $form = $this->getBuilder('') + ->setMethod($method) + ->setCompound(true) + ->setDataMapper($this->getDataMapper()) + ->setRequestHandler(new HttpFoundationRequestHandler()) + ->getForm(); + $form->add($this->getBuilder('name')->getForm()); + $form->add($this->getBuilder('image')->getForm()); + + $form->handleRequest($request); + + $file = new UploadedFile($path, 'upload.png', 'image/png', 123, UPLOAD_ERR_OK); + + $this->assertEquals('Bernhard', $form['name']->getData()); + $this->assertEquals($file, $form['image']->getData()); + $this->assertEquals(array('extra' => 'data'), $form->getExtraData()); + + unlink($path); + } + + /** + * @dataProvider requestMethodProvider + */ + public function testSubmitPostOrPutRequestWithSingleChildForm($method) + { + if (!class_exists('Symfony\Component\HttpFoundation\Request')) { + $this->markTestSkipped('The "HttpFoundation" component is not available'); + } + + $path = tempnam(sys_get_temp_dir(), 'sf2'); + touch($path); + + $files = array( + 'image' => array( + 'error' => UPLOAD_ERR_OK, + 'name' => 'upload.png', + 'size' => 123, + 'tmp_name' => $path, + 'type' => 'image/png', + ), + ); + + $request = new Request(array(), array(), array(), array(), $files, array( + 'REQUEST_METHOD' => $method, + )); + + $form = $this->getBuilder('image') + ->setMethod($method) + ->setRequestHandler(new HttpFoundationRequestHandler()) + ->getForm(); + + $form->handleRequest($request); + + $file = new UploadedFile($path, 'upload.png', 'image/png', 123, UPLOAD_ERR_OK); + + $this->assertEquals($file, $form->getData()); + + unlink($path); + } + + /** + * @dataProvider requestMethodProvider + */ + public function testSubmitPostOrPutRequestWithSingleChildFormUploadedFile($method) + { + if (!class_exists('Symfony\Component\HttpFoundation\Request')) { + $this->markTestSkipped('The "HttpFoundation" component is not available'); + } + + $path = tempnam(sys_get_temp_dir(), 'sf2'); + touch($path); + + $values = array( + 'name' => 'Bernhard', + ); + + $request = new Request(array(), $values, array(), array(), array(), array( + 'REQUEST_METHOD' => $method, + )); + + $form = $this->getBuilder('name') + ->setMethod($method) + ->setRequestHandler(new HttpFoundationRequestHandler()) + ->getForm(); + + $form->handleRequest($request); + + $this->assertEquals('Bernhard', $form->getData()); + + unlink($path); + } + + public function testSubmitGetRequest() + { + if (!class_exists('Symfony\Component\HttpFoundation\Request')) { + $this->markTestSkipped('The "HttpFoundation" component is not available'); + } + + $values = array( + 'author' => array( + 'firstName' => 'Bernhard', + 'lastName' => 'Schussek', + ), + ); + + $request = new Request($values, array(), array(), array(), array(), array( + 'REQUEST_METHOD' => 'GET', + )); + + $form = $this->getBuilder('author') + ->setMethod('GET') + ->setCompound(true) + ->setDataMapper($this->getDataMapper()) + ->setRequestHandler(new HttpFoundationRequestHandler()) + ->getForm(); + $form->add($this->getBuilder('firstName')->getForm()); + $form->add($this->getBuilder('lastName')->getForm()); + + $form->handleRequest($request); + + $this->assertEquals('Bernhard', $form['firstName']->getData()); + $this->assertEquals('Schussek', $form['lastName']->getData()); + } + + public function testSubmitGetRequestWithEmptyRootFormName() + { + if (!class_exists('Symfony\Component\HttpFoundation\Request')) { + $this->markTestSkipped('The "HttpFoundation" component is not available'); + } + + $values = array( + 'firstName' => 'Bernhard', + 'lastName' => 'Schussek', + 'extra' => 'data' + ); + + $request = new Request($values, array(), array(), array(), array(), array( + 'REQUEST_METHOD' => 'GET', + )); + + $form = $this->getBuilder('') + ->setMethod('GET') + ->setCompound(true) + ->setDataMapper($this->getDataMapper()) + ->setRequestHandler(new HttpFoundationRequestHandler()) + ->getForm(); + $form->add($this->getBuilder('firstName')->getForm()); + $form->add($this->getBuilder('lastName')->getForm()); + + $form->handleRequest($request); + + $this->assertEquals('Bernhard', $form['firstName']->getData()); + $this->assertEquals('Schussek', $form['lastName']->getData()); + $this->assertEquals(array('extra' => 'data'), $form->getExtraData()); + } + + public function testGetErrorsAsStringDeep() + { + $parent = $this->getBuilder() + ->setCompound(true) + ->setDataMapper($this->getDataMapper()) + ->getForm(); + + $this->form->addError(new FormError('Error!')); + + $parent->add($this->form); + $parent->add($this->getBuilder('foo')->getForm()); + + $this->assertEquals("name:\n ERROR: Error!\nfoo:\n No errors\n", $parent->getErrorsAsString()); + } + + protected function createForm() + { + return $this->getBuilder() + ->setCompound(true) + ->setDataMapper($this->getDataMapper()) + ->getForm(); + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/ChoiceList/ChoiceListTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/ChoiceList/ChoiceListTest.php new file mode 100644 index 00000000..63eae9bf --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/ChoiceList/ChoiceListTest.php @@ -0,0 +1,200 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Core\ChoiceList; + +use Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceList; +use Symfony\Component\Form\Extension\Core\View\ChoiceView; + +class ChoiceListTest extends \PHPUnit_Framework_TestCase +{ + private $obj1; + + private $obj2; + + private $obj3; + + private $obj4; + + private $list; + + protected function setUp() + { + parent::setUp(); + + $this->obj1 = new \stdClass(); + $this->obj2 = new \stdClass(); + $this->obj3 = new \stdClass(); + $this->obj4 = new \stdClass(); + + $this->list = new ChoiceList( + array( + 'Group 1' => array($this->obj1, $this->obj2), + 'Group 2' => array($this->obj3, $this->obj4), + ), + array( + 'Group 1' => array('A', 'B'), + 'Group 2' => array('C', 'D'), + ), + array($this->obj2, $this->obj3) + ); + } + + protected function tearDown() + { + parent::tearDown(); + + $this->obj1 = null; + $this->obj2 = null; + $this->obj3 = null; + $this->obj4 = null; + $this->list = null; + } + + public function testInitArray() + { + $this->list = new ChoiceList( + array($this->obj1, $this->obj2, $this->obj3, $this->obj4), + array('A', 'B', 'C', 'D'), + array($this->obj2) + ); + + $this->assertSame(array($this->obj1, $this->obj2, $this->obj3, $this->obj4), $this->list->getChoices()); + $this->assertSame(array('0', '1', '2', '3'), $this->list->getValues()); + $this->assertEquals(array(1 => new ChoiceView($this->obj2, '1', 'B')), $this->list->getPreferredViews()); + $this->assertEquals(array(0 => new ChoiceView($this->obj1, '0', 'A'), 2 => new ChoiceView($this->obj3, '2', 'C'), 3 => new ChoiceView($this->obj4, '3', 'D')), $this->list->getRemainingViews()); + } + + /** + * Necessary for interoperability with MongoDB cursors or ORM relations as + * choices parameter. A choice itself that is an object implementing \Traversable + * is not treated as hierarchical structure, but as-is. + */ + public function testInitNestedTraversable() + { + $traversableChoice = new \ArrayIterator(array($this->obj3, $this->obj4)); + + $this->list = new ChoiceList( + new \ArrayIterator(array( + 'Group' => array($this->obj1, $this->obj2), + 'Not a Group' => $traversableChoice + )), + array( + 'Group' => array('A', 'B'), + 'Not a Group' => 'C', + ), + array($this->obj2) + ); + + $this->assertSame(array($this->obj1, $this->obj2, $traversableChoice), $this->list->getChoices()); + $this->assertSame(array('0', '1', '2'), $this->list->getValues()); + $this->assertEquals(array( + 'Group' => array(1 => new ChoiceView($this->obj2, '1', 'B')) + ), $this->list->getPreferredViews()); + $this->assertEquals(array( + 'Group' => array(0 => new ChoiceView($this->obj1, '0', 'A')), + 2 => new ChoiceView($traversableChoice, '2', 'C') + ), $this->list->getRemainingViews()); + } + + public function testInitNestedArray() + { + $this->assertSame(array($this->obj1, $this->obj2, $this->obj3, $this->obj4), $this->list->getChoices()); + $this->assertSame(array('0', '1', '2', '3'), $this->list->getValues()); + $this->assertEquals(array( + 'Group 1' => array(1 => new ChoiceView($this->obj2, '1', 'B')), + 'Group 2' => array(2 => new ChoiceView($this->obj3, '2', 'C')) + ), $this->list->getPreferredViews()); + $this->assertEquals(array( + 'Group 1' => array(0 => new ChoiceView($this->obj1, '0', 'A')), + 'Group 2' => array(3 => new ChoiceView($this->obj4, '3', 'D')) + ), $this->list->getRemainingViews()); + } + + public function testGetIndicesForChoices() + { + $choices = array($this->obj2, $this->obj3); + $this->assertSame(array(1, 2), $this->list->getIndicesForChoices($choices)); + } + + public function testGetIndicesForChoicesIgnoresNonExistingChoices() + { + $choices = array($this->obj2, $this->obj3, 'foobar'); + $this->assertSame(array(1, 2), $this->list->getIndicesForChoices($choices)); + } + + public function testGetIndicesForValues() + { + // values and indices are always the same + $values = array('1', '2'); + $this->assertSame(array(1, 2), $this->list->getIndicesForValues($values)); + } + + public function testGetIndicesForValuesIgnoresNonExistingValues() + { + $values = array('1', '2', '5'); + $this->assertSame(array(1, 2), $this->list->getIndicesForValues($values)); + } + + public function testGetChoicesForValues() + { + $values = array('1', '2'); + $this->assertSame(array($this->obj2, $this->obj3), $this->list->getChoicesForValues($values)); + } + + public function testGetChoicesForValuesCorrectOrderingOfResult() + { + $values = array('2', '1'); + $this->assertSame(array($this->obj3, $this->obj2), $this->list->getChoicesForValues($values)); + } + + public function testGetChoicesForValuesIgnoresNonExistingValues() + { + $values = array('1', '2', '5'); + $this->assertSame(array($this->obj2, $this->obj3), $this->list->getChoicesForValues($values)); + } + + public function testGetValuesForChoices() + { + $choices = array($this->obj2, $this->obj3); + $this->assertSame(array('1', '2'), $this->list->getValuesForChoices($choices)); + } + + public function testGetValuesForChoicesIgnoresNonExistingChoices() + { + $choices = array($this->obj2, $this->obj3, 'foobar'); + $this->assertSame(array('1', '2'), $this->list->getValuesForChoices($choices)); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testNonMatchingLabels() + { + $this->list = new ChoiceList( + array($this->obj1, $this->obj2), + array('A') + ); + } + + public function testLabelsContainingNull() + { + $this->list = new ChoiceList( + array($this->obj1, $this->obj2), + array('A', null) + ); + + $this->assertEquals( + array(0 => new ChoiceView($this->obj1, '0', 'A'), 1 => new ChoiceView($this->obj2, '1', null)), + $this->list->getRemainingViews() + ); + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/ChoiceList/LazyChoiceListTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/ChoiceList/LazyChoiceListTest.php new file mode 100644 index 00000000..bcd309e0 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/ChoiceList/LazyChoiceListTest.php @@ -0,0 +1,116 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Core\ChoiceList; + +use Symfony\Component\Form\Extension\Core\ChoiceList\SimpleChoiceList; +use Symfony\Component\Form\Extension\Core\ChoiceList\LazyChoiceList; +use Symfony\Component\Form\Extension\Core\View\ChoiceView; + +class LazyChoiceListTest extends \PHPUnit_Framework_TestCase +{ + private $list; + + protected function setUp() + { + parent::setUp(); + + $this->list = new LazyChoiceListTest_Impl(new SimpleChoiceList(array( + 'a' => 'A', + 'b' => 'B', + 'c' => 'C', + ), array('b'))); + } + + protected function tearDown() + { + parent::tearDown(); + + $this->list = null; + } + + public function testGetChoices() + { + $this->assertSame(array(0 => 'a', 1 => 'b', 2 => 'c'), $this->list->getChoices()); + } + + public function testGetValues() + { + $this->assertSame(array(0 => 'a', 1 => 'b', 2 => 'c'), $this->list->getValues()); + } + + public function testGetPreferredViews() + { + $this->assertEquals(array(1 => new ChoiceView('b', 'b', 'B')), $this->list->getPreferredViews()); + } + + public function testGetRemainingViews() + { + $this->assertEquals(array(0 => new ChoiceView('a', 'a', 'A'), 2 => new ChoiceView('c', 'c', 'C')), $this->list->getRemainingViews()); + } + + public function testGetIndicesForChoices() + { + $choices = array('b', 'c'); + $this->assertSame(array(1, 2), $this->list->getIndicesForChoices($choices)); + } + + public function testGetIndicesForValues() + { + $values = array('b', 'c'); + $this->assertSame(array(1, 2), $this->list->getIndicesForValues($values)); + } + + public function testGetChoicesForValues() + { + $values = array('b', 'c'); + $this->assertSame(array('b', 'c'), $this->list->getChoicesForValues($values)); + } + + public function testGetValuesForChoices() + { + $choices = array('b', 'c'); + $this->assertSame(array('b', 'c'), $this->list->getValuesForChoices($choices)); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\InvalidArgumentException + */ + public function testLoadChoiceListShouldReturnChoiceList() + { + $list = new LazyChoiceListTest_InvalidImpl(); + + $list->getChoices(); + } +} + +class LazyChoiceListTest_Impl extends LazyChoiceList +{ + private $choiceList; + + public function __construct($choiceList) + { + $this->choiceList = $choiceList; + } + + protected function loadChoiceList() + { + return $this->choiceList; + } +} + +class LazyChoiceListTest_InvalidImpl extends LazyChoiceList +{ + protected function loadChoiceList() + { + return new \stdClass(); + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/ChoiceList/ObjectChoiceListTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/ChoiceList/ObjectChoiceListTest.php new file mode 100644 index 00000000..69c5aa0f --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/ChoiceList/ObjectChoiceListTest.php @@ -0,0 +1,212 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Core\ChoiceList; + +use Symfony\Component\Form\Extension\Core\ChoiceList\ObjectChoiceList; +use Symfony\Component\Form\Extension\Core\View\ChoiceView; + +class ObjectChoiceListTest_EntityWithToString +{ + private $property; + + public function __construct($property) + { + $this->property = $property; + } + + public function __toString() + { + return $this->property; + } +} + +class ObjectChoiceListTest extends \PHPUnit_Framework_TestCase +{ + private $obj1; + + private $obj2; + + private $obj3; + + private $obj4; + + /** + * @var ObjectChoiceList + */ + private $list; + + protected function setUp() + { + parent::setUp(); + + $this->obj1 = (object) array('name' => 'A'); + $this->obj2 = (object) array('name' => 'B'); + $this->obj3 = (object) array('name' => 'C'); + $this->obj4 = (object) array('name' => 'D'); + + $this->list = new ObjectChoiceList( + array( + 'Group 1' => array($this->obj1, $this->obj2), + 'Group 2' => array($this->obj3, $this->obj4), + ), + 'name', + array($this->obj2, $this->obj3) + ); + } + + protected function tearDown() + { + parent::tearDown(); + + $this->obj1 = null; + $this->obj2 = null; + $this->obj3 = null; + $this->obj4 = null; + $this->list = null; + } + + public function testInitArray() + { + $this->list = new ObjectChoiceList( + array($this->obj1, $this->obj2, $this->obj3, $this->obj4), + 'name', + array($this->obj2) + ); + + $this->assertSame(array($this->obj1, $this->obj2, $this->obj3, $this->obj4), $this->list->getChoices()); + $this->assertSame(array('0', '1', '2', '3'), $this->list->getValues()); + $this->assertEquals(array(1 => new ChoiceView($this->obj2, '1', 'B')), $this->list->getPreferredViews()); + $this->assertEquals(array(0 => new ChoiceView($this->obj1, '0', 'A'), 2 => new ChoiceView($this->obj3, '2', 'C'), 3 => new ChoiceView($this->obj4, '3', 'D')), $this->list->getRemainingViews()); + } + + public function testInitNestedArray() + { + $this->assertSame(array($this->obj1, $this->obj2, $this->obj3, $this->obj4), $this->list->getChoices()); + $this->assertSame(array('0', '1', '2', '3'), $this->list->getValues()); + $this->assertEquals(array( + 'Group 1' => array(1 => new ChoiceView($this->obj2, '1', 'B')), + 'Group 2' => array(2 => new ChoiceView($this->obj3, '2', 'C')) + ), $this->list->getPreferredViews()); + $this->assertEquals(array( + 'Group 1' => array(0 => new ChoiceView($this->obj1, '0', 'A')), + 'Group 2' => array(3 => new ChoiceView($this->obj4, '3', 'D')) + ), $this->list->getRemainingViews()); + } + + public function testInitArrayWithGroupPath() + { + $this->obj1 = (object) array('name' => 'A', 'category' => 'Group 1'); + $this->obj2 = (object) array('name' => 'B', 'category' => 'Group 1'); + $this->obj3 = (object) array('name' => 'C', 'category' => 'Group 2'); + $this->obj4 = (object) array('name' => 'D', 'category' => 'Group 2'); + + // Objects with NULL groups are not grouped + $obj5 = (object) array('name' => 'E', 'category' => null); + + // Objects without the group property are not grouped either + // see https://github.com/symfony/symfony/commit/d9b7abb7c7a0f28e0ce970afc5e305dce5dccddf + $obj6 = (object) array('name' => 'F'); + + $this->list = new ObjectChoiceList( + array($this->obj1, $this->obj2, $this->obj3, $this->obj4, $obj5, $obj6), + 'name', + array($this->obj2, $this->obj3), + 'category' + ); + + $this->assertSame(array($this->obj1, $this->obj2, $this->obj3, $this->obj4, $obj5, $obj6), $this->list->getChoices()); + $this->assertSame(array('0', '1', '2', '3', '4', '5'), $this->list->getValues()); + $this->assertEquals(array( + 'Group 1' => array(1 => new ChoiceView($this->obj2, '1', 'B')), + 'Group 2' => array(2 => new ChoiceView($this->obj3, '2', 'C')) + ), $this->list->getPreferredViews()); + $this->assertEquals(array( + 'Group 1' => array(0 => new ChoiceView($this->obj1, '0', 'A')), + 'Group 2' => array(3 => new ChoiceView($this->obj4, '3', 'D')), + 4 => new ChoiceView($obj5, '4', 'E'), + 5 => new ChoiceView($obj6, '5', 'F'), + ), $this->list->getRemainingViews()); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testInitArrayWithGroupPathThrowsExceptionIfNestedArray() + { + $this->obj1 = (object) array('name' => 'A', 'category' => 'Group 1'); + $this->obj2 = (object) array('name' => 'B', 'category' => 'Group 1'); + $this->obj3 = (object) array('name' => 'C', 'category' => 'Group 2'); + $this->obj4 = (object) array('name' => 'D', 'category' => 'Group 2'); + + new ObjectChoiceList( + array( + 'Group 1' => array($this->obj1, $this->obj2), + 'Group 2' => array($this->obj3, $this->obj4), + ), + 'name', + array($this->obj2, $this->obj3), + 'category' + ); + } + + public function testInitArrayWithValuePath() + { + $this->obj1 = (object) array('name' => 'A', 'id' => 10); + $this->obj2 = (object) array('name' => 'B', 'id' => 20); + $this->obj3 = (object) array('name' => 'C', 'id' => 30); + $this->obj4 = (object) array('name' => 'D', 'id' => 40); + + $this->list = new ObjectChoiceList( + array($this->obj1, $this->obj2, $this->obj3, $this->obj4), + 'name', + array($this->obj2, $this->obj3), + null, + 'id' + ); + + $this->assertSame(array($this->obj1, $this->obj2, $this->obj3, $this->obj4), $this->list->getChoices()); + $this->assertSame(array('10', '20', '30', '40'), $this->list->getValues()); + $this->assertEquals(array(1 => new ChoiceView($this->obj2, '20', 'B'), 2 => new ChoiceView($this->obj3, '30', 'C')), $this->list->getPreferredViews()); + $this->assertEquals(array(0 => new ChoiceView($this->obj1, '10', 'A'), 3 => new ChoiceView($this->obj4, '40', 'D')), $this->list->getRemainingViews()); + } + + public function testInitArrayUsesToString() + { + $this->obj1 = new ObjectChoiceListTest_EntityWithToString('A'); + $this->obj2 = new ObjectChoiceListTest_EntityWithToString('B'); + $this->obj3 = new ObjectChoiceListTest_EntityWithToString('C'); + $this->obj4 = new ObjectChoiceListTest_EntityWithToString('D'); + + $this->list = new ObjectChoiceList( + array($this->obj1, $this->obj2, $this->obj3, $this->obj4) + ); + + $this->assertSame(array($this->obj1, $this->obj2, $this->obj3, $this->obj4), $this->list->getChoices()); + $this->assertSame(array('0', '1', '2', '3'), $this->list->getValues()); + $this->assertEquals(array(0 => new ChoiceView($this->obj1, '0', 'A'), 1 => new ChoiceView($this->obj2, '1', 'B'), 2 => new ChoiceView($this->obj3, '2', 'C'), 3 => new ChoiceView($this->obj4, '3', 'D')), $this->list->getRemainingViews()); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\StringCastException + */ + public function testInitArrayThrowsExceptionIfToStringNotFound() + { + $this->obj1 = new ObjectChoiceListTest_EntityWithToString('A'); + $this->obj2 = new ObjectChoiceListTest_EntityWithToString('B'); + $this->obj3 = (object) array('name' => 'C'); + $this->obj4 = new ObjectChoiceListTest_EntityWithToString('D'); + + new ObjectChoiceList( + array($this->obj1, $this->obj2, $this->obj3, $this->obj4) + ); + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/ChoiceList/SimpleChoiceListTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/ChoiceList/SimpleChoiceListTest.php new file mode 100644 index 00000000..69d27a18 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/ChoiceList/SimpleChoiceListTest.php @@ -0,0 +1,188 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Core\ChoiceList; + +use Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceList; +use Symfony\Component\Form\Extension\Core\ChoiceList\SimpleChoiceList; +use Symfony\Component\Form\Extension\Core\View\ChoiceView; + +class SimpleChoiceListTest extends \PHPUnit_Framework_TestCase +{ + private $list; + + private $numericList; + + protected function setUp() + { + parent::setUp(); + + $choices = array( + 'Group 1' => array('a' => 'A', 'b' => 'B'), + 'Group 2' => array('c' => 'C', 'd' => 'D'), + ); + $numericChoices = array( + 'Group 1' => array(0 => 'A', 1 => 'B'), + 'Group 2' => array(2 => 'C', 3 => 'D'), + ); + + $this->list = new SimpleChoiceList($choices, array('b', 'c')); + + // Use COPY_CHOICE strategy to test for the various associated problems + $this->numericList = new SimpleChoiceList($numericChoices, array(1, 2)); + } + + protected function tearDown() + { + parent::tearDown(); + + $this->list = null; + $this->numericList = null; + } + + public function testInitArray() + { + $choices = array('a' => 'A', 'b' => 'B', 'c' => 'C'); + $this->list = new SimpleChoiceList($choices, array('b')); + + $this->assertSame(array(0 => 'a', 1 => 'b', 2 => 'c'), $this->list->getChoices()); + $this->assertSame(array(0 => 'a', 1 => 'b', 2 => 'c'), $this->list->getValues()); + $this->assertEquals(array(1 => new ChoiceView('b', 'b', 'B')), $this->list->getPreferredViews()); + $this->assertEquals(array(0 => new ChoiceView('a', 'a', 'A'), 2 => new ChoiceView('c', 'c', 'C')), $this->list->getRemainingViews()); + } + + public function testInitNestedArray() + { + $this->assertSame(array(0 => 'a', 1 => 'b', 2 => 'c', 3 => 'd'), $this->list->getChoices()); + $this->assertSame(array(0 => 'a', 1 => 'b', 2 => 'c', 3 => 'd'), $this->list->getValues()); + $this->assertEquals(array( + 'Group 1' => array(1 => new ChoiceView('b', 'b', 'B')), + 'Group 2' => array(2 => new ChoiceView('c', 'c', 'C')) + ), $this->list->getPreferredViews()); + $this->assertEquals(array( + 'Group 1' => array(0 => new ChoiceView('a', 'a', 'A')), + 'Group 2' => array(3 => new ChoiceView('d', 'd', 'D')) + ), $this->list->getRemainingViews()); + } + + public function testGetIndicesForChoices() + { + $choices = array('b', 'c'); + $this->assertSame(array(1, 2), $this->list->getIndicesForChoices($choices)); + } + + public function testGetIndicesForChoicesIgnoresNonExistingChoices() + { + $choices = array('b', 'c', 'foobar'); + $this->assertSame(array(1, 2), $this->list->getIndicesForChoices($choices)); + } + + public function testGetIndicesForChoicesDealsWithNumericChoices() + { + // Pass choices as strings although they are integers + $choices = array('0', '1'); + $this->assertSame(array(0, 1), $this->numericList->getIndicesForChoices($choices)); + } + + public function testGetIndicesForValues() + { + $values = array('b', 'c'); + $this->assertSame(array(1, 2), $this->list->getIndicesForValues($values)); + } + + public function testGetIndicesForValuesIgnoresNonExistingValues() + { + $values = array('b', 'c', '100'); + $this->assertSame(array(1, 2), $this->list->getIndicesForValues($values)); + } + + public function testGetIndicesForValuesDealsWithNumericValues() + { + // Pass values as strings although they are integers + $values = array('0', '1'); + $this->assertSame(array(0, 1), $this->numericList->getIndicesForValues($values)); + } + + public function testGetChoicesForValues() + { + $values = array('b', 'c'); + $this->assertSame(array('b', 'c'), $this->list->getChoicesForValues($values)); + } + + public function testGetChoicesForValuesIgnoresNonExistingValues() + { + $values = array('b', 'c', '100'); + $this->assertSame(array('b', 'c'), $this->list->getChoicesForValues($values)); + } + + public function testGetChoicesForValuesDealsWithNumericValues() + { + // Pass values as strings although they are integers + $values = array('0', '1'); + $this->assertSame(array(0, 1), $this->numericList->getChoicesForValues($values)); + } + + public function testGetValuesForChoices() + { + $choices = array('b', 'c'); + $this->assertSame(array('b', 'c'), $this->list->getValuesForChoices($choices)); + } + + public function testGetValuesForChoicesIgnoresNonExistingValues() + { + $choices = array('b', 'c', 'foobar'); + $this->assertSame(array('b', 'c'), $this->list->getValuesForChoices($choices)); + } + + public function testGetValuesForChoicesDealsWithNumericValues() + { + // Pass values as strings although they are integers + $values = array('0', '1'); + + $this->assertSame(array('0', '1'), $this->numericList->getValuesForChoices($values)); + } + + /** + * @dataProvider dirtyValuesProvider + */ + public function testGetValuesForChoicesDealsWithDirtyValues($choice, $value) + { + $choices = array( + '0' => 'Zero', + '1' => 'One', + '' => 'Empty', + '1.23' => 'Float', + 'foo' => 'Foo', + 'foo10' => 'Foo 10', + ); + + // use COPY_CHOICE strategy to test the problems + $this->list = new SimpleChoiceList($choices, array()); + + $this->assertSame(array($value), $this->list->getValuesForChoices(array($choice))); + } + + public function dirtyValuesProvider() + { + return array( + array(0, '0'), + array('0', '0'), + array('1', '1'), + array(false, '0'), + array(true, '1'), + array('', ''), + array(null, ''), + array('1.23', '1.23'), + array('foo', 'foo'), + array('foo10', 'foo10'), + ); + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/DataMapper/PropertyPathMapperTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/DataMapper/PropertyPathMapperTest.php new file mode 100644 index 00000000..ee2e3351 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/DataMapper/PropertyPathMapperTest.php @@ -0,0 +1,319 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Core\DataMapper; + +use Symfony\Component\Form\FormConfigBuilder; +use Symfony\Component\Form\FormConfigInterface; +use Symfony\Component\Form\Extension\Core\DataMapper\PropertyPathMapper; + +class PropertyPathMapperTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var PropertyPathMapper + */ + private $mapper; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + private $dispatcher; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + private $propertyAccessor; + + protected function setUp() + { + if (!class_exists('Symfony\Component\EventDispatcher\Event')) { + $this->markTestSkipped('The "EventDispatcher" component is not available'); + } + + if (!class_exists('Symfony\Component\PropertyAccess\PropertyAccess')) { + $this->markTestSkipped('The "PropertyAccess" component is not available'); + } + + $this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); + $this->propertyAccessor = $this->getMock('Symfony\Component\PropertyAccess\PropertyAccessorInterface'); + $this->mapper = new PropertyPathMapper($this->propertyAccessor); + } + + /** + * @param $path + * @return \PHPUnit_Framework_MockObject_MockObject + */ + private function getPropertyPath($path) + { + return $this->getMockBuilder('Symfony\Component\PropertyAccess\PropertyPath') + ->setConstructorArgs(array($path)) + ->setMethods(array('getValue', 'setValue')) + ->getMock(); + } + + /** + * @param FormConfigInterface $config + * @param Boolean $synchronized + * @return \PHPUnit_Framework_MockObject_MockObject + */ + private function getForm(FormConfigInterface $config, $synchronized = true) + { + $form = $this->getMockBuilder('Symfony\Component\Form\Form') + ->setConstructorArgs(array($config)) + ->setMethods(array('isSynchronized')) + ->getMock(); + + $form->expects($this->any()) + ->method('isSynchronized') + ->will($this->returnValue($synchronized)); + + return $form; + } + + /** + * @return \PHPUnit_Framework_MockObject_MockObject + */ + private function getDataMapper() + { + return $this->getMock('Symfony\Component\Form\DataMapperInterface'); + } + + public function testMapDataToFormsPassesObjectRefIfByReference() + { + $car = new \stdClass(); + $engine = new \stdClass(); + $propertyPath = $this->getPropertyPath('engine'); + + $this->propertyAccessor->expects($this->once()) + ->method('getValue') + ->with($car, $propertyPath) + ->will($this->returnValue($engine)); + + $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher); + $config->setByReference(true); + $config->setPropertyPath($propertyPath); + $form = $this->getForm($config); + + $this->mapper->mapDataToForms($car, array($form)); + + // Can't use isIdentical() above because mocks always clone their + // arguments which can't be disabled in PHPUnit 3.6 + $this->assertSame($engine, $form->getData()); + } + + public function testMapDataToFormsPassesObjectCloneIfNotByReference() + { + $car = new \stdClass(); + $engine = new \stdClass(); + $propertyPath = $this->getPropertyPath('engine'); + + $this->propertyAccessor->expects($this->once()) + ->method('getValue') + ->with($car, $propertyPath) + ->will($this->returnValue($engine)); + + $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher); + $config->setByReference(false); + $config->setPropertyPath($propertyPath); + $form = $this->getForm($config); + + $this->mapper->mapDataToForms($car, array($form)); + + $this->assertNotSame($engine, $form->getData()); + $this->assertEquals($engine, $form->getData()); + } + + public function testMapDataToFormsIgnoresEmptyPropertyPath() + { + $car = new \stdClass(); + + $config = new FormConfigBuilder(null, '\stdClass', $this->dispatcher); + $config->setByReference(true); + $form = $this->getForm($config); + + $this->assertNull($form->getPropertyPath()); + + $this->mapper->mapDataToForms($car, array($form)); + + $this->assertNull($form->getData()); + } + + public function testMapDataToFormsIgnoresUnmapped() + { + $car = new \stdClass(); + $propertyPath = $this->getPropertyPath('engine'); + + $this->propertyAccessor->expects($this->never()) + ->method('getValue'); + + $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher); + $config->setByReference(true); + $config->setMapped(false); + $config->setPropertyPath($propertyPath); + $form = $this->getForm($config); + + $this->mapper->mapDataToForms($car, array($form)); + + $this->assertNull($form->getData()); + } + + public function testMapDataToFormsIgnoresEmptyData() + { + $propertyPath = $this->getPropertyPath('engine'); + + $this->propertyAccessor->expects($this->never()) + ->method('getValue'); + + $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher); + $config->setByReference(true); + $config->setPropertyPath($propertyPath); + $form = $this->getForm($config); + + $this->mapper->mapDataToForms(null, array($form)); + + $this->assertNull($form->getData()); + } + + public function testMapFormsToDataWritesBackIfNotByReference() + { + $car = new \stdClass(); + $engine = new \stdClass(); + $propertyPath = $this->getPropertyPath('engine'); + + $this->propertyAccessor->expects($this->once()) + ->method('setValue') + ->with($car, $propertyPath, $engine); + + $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher); + $config->setByReference(false); + $config->setPropertyPath($propertyPath); + $config->setData($engine); + $form = $this->getForm($config); + + $this->mapper->mapFormsToData(array($form), $car); + } + + public function testMapFormsToDataWritesBackIfByReferenceButNoReference() + { + $car = new \stdClass(); + $engine = new \stdClass(); + $propertyPath = $this->getPropertyPath('engine'); + + $this->propertyAccessor->expects($this->once()) + ->method('setValue') + ->with($car, $propertyPath, $engine); + + $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher); + $config->setByReference(true); + $config->setPropertyPath($propertyPath); + $config->setData($engine); + $form = $this->getForm($config); + + $this->mapper->mapFormsToData(array($form), $car); + } + + public function testMapFormsToDataWritesBackIfByReferenceAndReference() + { + $car = new \stdClass(); + $engine = new \stdClass(); + $propertyPath = $this->getPropertyPath('engine'); + + // $car already contains the reference of $engine + $this->propertyAccessor->expects($this->once()) + ->method('getValue') + ->with($car, $propertyPath) + ->will($this->returnValue($engine)); + + $this->propertyAccessor->expects($this->never()) + ->method('setValue'); + + $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher); + $config->setByReference(true); + $config->setPropertyPath($propertyPath); + $config->setData($engine); + $form = $this->getForm($config); + + $this->mapper->mapFormsToData(array($form), $car); + } + + public function testMapFormsToDataIgnoresUnmapped() + { + $car = new \stdClass(); + $engine = new \stdClass(); + $propertyPath = $this->getPropertyPath('engine'); + + $this->propertyAccessor->expects($this->never()) + ->method('setValue'); + + $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher); + $config->setByReference(true); + $config->setPropertyPath($propertyPath); + $config->setData($engine); + $config->setMapped(false); + $form = $this->getForm($config); + + $this->mapper->mapFormsToData(array($form), $car); + } + + public function testMapFormsToDataIgnoresEmptyData() + { + $car = new \stdClass(); + $propertyPath = $this->getPropertyPath('engine'); + + $this->propertyAccessor->expects($this->never()) + ->method('setValue'); + + $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher); + $config->setByReference(true); + $config->setPropertyPath($propertyPath); + $config->setData(null); + $form = $this->getForm($config); + + $this->mapper->mapFormsToData(array($form), $car); + } + + public function testMapFormsToDataIgnoresUnsynchronized() + { + $car = new \stdClass(); + $engine = new \stdClass(); + $propertyPath = $this->getPropertyPath('engine'); + + $this->propertyAccessor->expects($this->never()) + ->method('setValue'); + + $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher); + $config->setByReference(true); + $config->setPropertyPath($propertyPath); + $config->setData($engine); + $form = $this->getForm($config, false); + + $this->mapper->mapFormsToData(array($form), $car); + } + + public function testMapFormsToDataIgnoresDisabled() + { + $car = new \stdClass(); + $engine = new \stdClass(); + $propertyPath = $this->getPropertyPath('engine'); + + $this->propertyAccessor->expects($this->never()) + ->method('setValue'); + + $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher); + $config->setByReference(true); + $config->setPropertyPath($propertyPath); + $config->setData($engine); + $config->setDisabled(true); + $form = $this->getForm($config); + + $this->mapper->mapFormsToData(array($form), $car); + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/ArrayToPartsTransformerTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/ArrayToPartsTransformerTest.php new file mode 100644 index 00000000..bafe5c09 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/ArrayToPartsTransformerTest.php @@ -0,0 +1,149 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; + +use Symfony\Component\Form\Extension\Core\DataTransformer\ArrayToPartsTransformer; + +class ArrayToPartsTransformerTest extends \PHPUnit_Framework_TestCase +{ + private $transformer; + + protected function setUp() + { + $this->transformer = new ArrayToPartsTransformer(array( + 'first' => array('a', 'b', 'c'), + 'second' => array('d', 'e', 'f'), + )); + } + + protected function tearDown() + { + $this->transformer = null; + } + + public function testTransform() + { + $input = array( + 'a' => '1', + 'b' => '2', + 'c' => '3', + 'd' => '4', + 'e' => '5', + 'f' => '6', + ); + + $output = array( + 'first' => array( + 'a' => '1', + 'b' => '2', + 'c' => '3', + ), + 'second' => array( + 'd' => '4', + 'e' => '5', + 'f' => '6', + ), + ); + + $this->assertSame($output, $this->transformer->transform($input)); + } + + public function testTransformEmpty() + { + $output = array( + 'first' => null, + 'second' => null, + ); + + $this->assertSame($output, $this->transformer->transform(null)); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testTransformRequiresArray() + { + $this->transformer->transform('12345'); + } + + public function testReverseTransform() + { + $input = array( + 'first' => array( + 'a' => '1', + 'b' => '2', + 'c' => '3', + ), + 'second' => array( + 'd' => '4', + 'e' => '5', + 'f' => '6', + ), + ); + + $output = array( + 'a' => '1', + 'b' => '2', + 'c' => '3', + 'd' => '4', + 'e' => '5', + 'f' => '6', + ); + + $this->assertSame($output, $this->transformer->reverseTransform($input)); + } + + public function testReverseTransformCompletelyEmpty() + { + $input = array( + 'first' => '', + 'second' => '', + ); + + $this->assertNull($this->transformer->reverseTransform($input)); + } + + public function testReverseTransformCompletelyNull() + { + $input = array( + 'first' => null, + 'second' => null, + ); + + $this->assertNull($this->transformer->reverseTransform($input)); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testReverseTransformPartiallyNull() + { + $input = array( + 'first' => array( + 'a' => '1', + 'b' => '2', + 'c' => '3', + ), + 'second' => null, + ); + + $this->transformer->reverseTransform($input); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testReverseTransformRequiresArray() + { + $this->transformer->reverseTransform('12345'); + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/BooleanToStringTransformerTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/BooleanToStringTransformerTest.php new file mode 100644 index 00000000..41f8f956 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/BooleanToStringTransformerTest.php @@ -0,0 +1,60 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; + +use Symfony\Component\Form\Extension\Core\DataTransformer\BooleanToStringTransformer; + +class BooleanToStringTransformerTest extends \PHPUnit_Framework_TestCase +{ + const TRUE_VALUE = '1'; + + protected $transformer; + + protected function setUp() + { + $this->transformer = new BooleanToStringTransformer(self::TRUE_VALUE); + } + + protected function tearDown() + { + $this->transformer = null; + } + + public function testTransform() + { + $this->assertEquals(self::TRUE_VALUE, $this->transformer->transform(true)); + $this->assertNull($this->transformer->transform(false)); + $this->assertNull($this->transformer->transform(null)); + } + + public function testTransformExpectsBoolean() + { + $this->setExpectedException('Symfony\Component\Form\Exception\TransformationFailedException'); + + $this->transformer->transform('1'); + } + + public function testReverseTransformExpectsString() + { + $this->setExpectedException('Symfony\Component\Form\Exception\TransformationFailedException'); + + $this->transformer->reverseTransform(1); + } + + public function testReverseTransform() + { + $this->assertTrue($this->transformer->reverseTransform(self::TRUE_VALUE)); + $this->assertTrue($this->transformer->reverseTransform('foobar')); + $this->assertTrue($this->transformer->reverseTransform('')); + $this->assertFalse($this->transformer->reverseTransform(null)); + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/ChoiceToValueTransformerTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/ChoiceToValueTransformerTest.php new file mode 100644 index 00000000..bbae0621 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/ChoiceToValueTransformerTest.php @@ -0,0 +1,76 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; + +use Symfony\Component\Form\Extension\Core\ChoiceList\SimpleChoiceList; +use Symfony\Component\Form\Extension\Core\DataTransformer\ChoiceToValueTransformer; + +class ChoiceToValueTransformerTest extends \PHPUnit_Framework_TestCase +{ + protected $transformer; + + protected function setUp() + { + $list = new SimpleChoiceList(array('' => 'A', 0 => 'B', 1 => 'C')); + $this->transformer = new ChoiceToValueTransformer($list); + } + + protected function tearDown() + { + $this->transformer = null; + } + + public function transformProvider() + { + return array( + // more extensive test set can be found in FormUtilTest + array(0, '0'), + array(false, '0'), + array('', ''), + ); + } + + /** + * @dataProvider transformProvider + */ + public function testTransform($in, $out) + { + $this->assertSame($out, $this->transformer->transform($in)); + } + + public function reverseTransformProvider() + { + return array( + // values are expected to be valid choice keys already and stay + // the same + array('0', 0), + array('', null), + array(null, null), + ); + } + + /** + * @dataProvider reverseTransformProvider + */ + public function testReverseTransform($in, $out) + { + $this->assertSame($out, $this->transformer->reverseTransform($in)); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testReverseTransformExpectsScalar() + { + $this->transformer->reverseTransform(array()); + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/ChoicesToValuesTransformerTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/ChoicesToValuesTransformerTest.php new file mode 100644 index 00000000..57297193 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/ChoicesToValuesTransformerTest.php @@ -0,0 +1,76 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; + +use Symfony\Component\Form\Extension\Core\ChoiceList\SimpleChoiceList; + +use Symfony\Component\Form\Extension\Core\DataTransformer\ChoicesToValuesTransformer; + +class ChoicesToValuesTransformerTest extends \PHPUnit_Framework_TestCase +{ + protected $transformer; + + protected function setUp() + { + $list = new SimpleChoiceList(array(0 => 'A', 1 => 'B', 2 => 'C')); + $this->transformer = new ChoicesToValuesTransformer($list); + } + + protected function tearDown() + { + $this->transformer = null; + } + + public function testTransform() + { + // Value strategy in SimpleChoiceList is to copy and convert to string + $in = array(0, 1, 2); + $out = array('0', '1', '2'); + + $this->assertSame($out, $this->transformer->transform($in)); + } + + public function testTransformNull() + { + $this->assertSame(array(), $this->transformer->transform(null)); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testTransformExpectsArray() + { + $this->transformer->transform('foobar'); + } + + public function testReverseTransform() + { + // values are expected to be valid choices and stay the same + $in = array('0', '1', '2'); + $out = array(0, 1, 2); + + $this->assertSame($out, $this->transformer->reverseTransform($in)); + } + + public function testReverseTransformNull() + { + $this->assertSame(array(), $this->transformer->reverseTransform(null)); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testReverseTransformExpectsArray() + { + $this->transformer->reverseTransform('foobar'); + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DataTransformerChainTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DataTransformerChainTest.php new file mode 100644 index 00000000..2ee2f22d --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DataTransformerChainTest.php @@ -0,0 +1,53 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; + +use Symfony\Component\Form\Extension\Core\DataTransformer\DataTransformerChain; + +class DataTransformerChainTest extends \PHPUnit_Framework_TestCase +{ + public function testTransform() + { + $transformer1 = $this->getMock('Symfony\Component\Form\DataTransformerInterface'); + $transformer1->expects($this->once()) + ->method('transform') + ->with($this->identicalTo('foo')) + ->will($this->returnValue('bar')); + $transformer2 = $this->getMock('Symfony\Component\Form\DataTransformerInterface'); + $transformer2->expects($this->once()) + ->method('transform') + ->with($this->identicalTo('bar')) + ->will($this->returnValue('baz')); + + $chain = new DataTransformerChain(array($transformer1, $transformer2)); + + $this->assertEquals('baz', $chain->transform('foo')); + } + + public function testReverseTransform() + { + $transformer2 = $this->getMock('Symfony\Component\Form\DataTransformerInterface'); + $transformer2->expects($this->once()) + ->method('reverseTransform') + ->with($this->identicalTo('foo')) + ->will($this->returnValue('bar')); + $transformer1 = $this->getMock('Symfony\Component\Form\DataTransformerInterface'); + $transformer1->expects($this->once()) + ->method('reverseTransform') + ->with($this->identicalTo('bar')) + ->will($this->returnValue('baz')); + + $chain = new DataTransformerChain(array($transformer1, $transformer2)); + + $this->assertEquals('baz', $chain->reverseTransform('foo')); + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeTestCase.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeTestCase.php new file mode 100644 index 00000000..f7722c49 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeTestCase.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; + +abstract class DateTimeTestCase extends \PHPUnit_Framework_TestCase +{ + public static function assertDateTimeEquals(\DateTime $expected, \DateTime $actual) + { + self::assertEquals($expected->format('c'), $actual->format('c')); + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToArrayTransformerTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToArrayTransformerTest.php new file mode 100644 index 00000000..4898b88d --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToArrayTransformerTest.php @@ -0,0 +1,512 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; + +use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToArrayTransformer; + +class DateTimeToArrayTransformerTest extends DateTimeTestCase +{ + public function testTransform() + { + $transformer = new DateTimeToArrayTransformer('UTC', 'UTC'); + + $input = new \DateTime('2010-02-03 04:05:06 UTC'); + + $output = array( + 'year' => '2010', + 'month' => '2', + 'day' => '3', + 'hour' => '4', + 'minute' => '5', + 'second' => '6', + ); + + $this->assertSame($output, $transformer->transform($input)); + } + + public function testTransformEmpty() + { + $transformer = new DateTimeToArrayTransformer(); + + $output = array( + 'year' => '', + 'month' => '', + 'day' => '', + 'hour' => '', + 'minute' => '', + 'second' => '', + ); + + $this->assertSame($output, $transformer->transform(null)); + } + + public function testTransformEmptyWithFields() + { + $transformer = new DateTimeToArrayTransformer(null, null, array('year', 'minute', 'second')); + + $output = array( + 'year' => '', + 'minute' => '', + 'second' => '', + ); + + $this->assertSame($output, $transformer->transform(null)); + } + + public function testTransformWithFields() + { + $transformer = new DateTimeToArrayTransformer('UTC', 'UTC', array('year', 'month', 'minute', 'second')); + + $input = new \DateTime('2010-02-03 04:05:06 UTC'); + + $output = array( + 'year' => '2010', + 'month' => '2', + 'minute' => '5', + 'second' => '6', + ); + + $this->assertSame($output, $transformer->transform($input)); + } + + public function testTransformWithPadding() + { + $transformer = new DateTimeToArrayTransformer('UTC', 'UTC', null, true); + + $input = new \DateTime('2010-02-03 04:05:06 UTC'); + + $output = array( + 'year' => '2010', + 'month' => '02', + 'day' => '03', + 'hour' => '04', + 'minute' => '05', + 'second' => '06', + ); + + $this->assertSame($output, $transformer->transform($input)); + } + + public function testTransformDifferentTimezones() + { + $transformer = new DateTimeToArrayTransformer('America/New_York', 'Asia/Hong_Kong'); + + $input = new \DateTime('2010-02-03 04:05:06 America/New_York'); + + $dateTime = new \DateTime('2010-02-03 04:05:06 America/New_York'); + $dateTime->setTimezone(new \DateTimeZone('Asia/Hong_Kong')); + $output = array( + 'year' => (string) (int) $dateTime->format('Y'), + 'month' => (string) (int) $dateTime->format('m'), + 'day' => (string) (int) $dateTime->format('d'), + 'hour' => (string) (int) $dateTime->format('H'), + 'minute' => (string) (int) $dateTime->format('i'), + 'second' => (string) (int) $dateTime->format('s'), + ); + + $this->assertSame($output, $transformer->transform($input)); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testTransformRequiresDateTime() + { + $transformer = new DateTimeToArrayTransformer(); + $transformer->reverseTransform('12345'); + } + + public function testReverseTransform() + { + $transformer = new DateTimeToArrayTransformer('UTC', 'UTC'); + + $input = array( + 'year' => '2010', + 'month' => '2', + 'day' => '3', + 'hour' => '4', + 'minute' => '5', + 'second' => '6', + ); + + $output = new \DateTime('2010-02-03 04:05:06 UTC'); + + $this->assertDateTimeEquals($output, $transformer->reverseTransform($input)); + } + + public function testReverseTransformWithSomeZero() + { + $transformer = new DateTimeToArrayTransformer('UTC', 'UTC'); + + $input = array( + 'year' => '2010', + 'month' => '2', + 'day' => '3', + 'hour' => '4', + 'minute' => '0', + 'second' => '0', + ); + + $output = new \DateTime('2010-02-03 04:00:00 UTC'); + + $this->assertDateTimeEquals($output, $transformer->reverseTransform($input)); + } + + public function testReverseTransformCompletelyEmpty() + { + $transformer = new DateTimeToArrayTransformer(); + + $input = array( + 'year' => '', + 'month' => '', + 'day' => '', + 'hour' => '', + 'minute' => '', + 'second' => '', + ); + + $this->assertNull($transformer->reverseTransform($input)); + } + + public function testReverseTransformCompletelyEmptySubsetOfFields() + { + $transformer = new DateTimeToArrayTransformer(null, null, array('year', 'month', 'day')); + + $input = array( + 'year' => '', + 'month' => '', + 'day' => '', + ); + + $this->assertNull($transformer->reverseTransform($input)); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testReverseTransformPartiallyEmptyYear() + { + $transformer = new DateTimeToArrayTransformer(); + $transformer->reverseTransform(array( + 'month' => '2', + 'day' => '3', + 'hour' => '4', + 'minute' => '5', + 'second' => '6', + )); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testReverseTransformPartiallyEmptyMonth() + { + $transformer = new DateTimeToArrayTransformer(); + $transformer->reverseTransform(array( + 'year' => '2010', + 'day' => '3', + 'hour' => '4', + 'minute' => '5', + 'second' => '6', + )); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testReverseTransformPartiallyEmptyDay() + { + $transformer = new DateTimeToArrayTransformer(); + $transformer->reverseTransform(array( + 'year' => '2010', + 'month' => '2', + 'hour' => '4', + 'minute' => '5', + 'second' => '6', + )); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testReverseTransformPartiallyEmptyHour() + { + $transformer = new DateTimeToArrayTransformer(); + $transformer->reverseTransform(array( + 'year' => '2010', + 'month' => '2', + 'day' => '3', + 'minute' => '5', + 'second' => '6', + )); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testReverseTransformPartiallyEmptyMinute() + { + $transformer = new DateTimeToArrayTransformer(); + $transformer->reverseTransform(array( + 'year' => '2010', + 'month' => '2', + 'day' => '3', + 'hour' => '4', + 'second' => '6', + )); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testReverseTransformPartiallyEmptySecond() + { + $transformer = new DateTimeToArrayTransformer(); + $transformer->reverseTransform(array( + 'year' => '2010', + 'month' => '2', + 'day' => '3', + 'hour' => '4', + 'minute' => '5', + )); + } + + public function testReverseTransformNull() + { + $transformer = new DateTimeToArrayTransformer(); + + $this->assertNull($transformer->reverseTransform(null)); + } + + public function testReverseTransformDifferentTimezones() + { + $transformer = new DateTimeToArrayTransformer('America/New_York', 'Asia/Hong_Kong'); + + $input = array( + 'year' => '2010', + 'month' => '2', + 'day' => '3', + 'hour' => '4', + 'minute' => '5', + 'second' => '6', + ); + + $output = new \DateTime('2010-02-03 04:05:06 Asia/Hong_Kong'); + $output->setTimezone(new \DateTimeZone('America/New_York')); + + $this->assertDateTimeEquals($output, $transformer->reverseTransform($input)); + } + + public function testReverseTransformToDifferentTimezone() + { + $transformer = new DateTimeToArrayTransformer('Asia/Hong_Kong', 'UTC'); + + $input = array( + 'year' => '2010', + 'month' => '2', + 'day' => '3', + 'hour' => '4', + 'minute' => '5', + 'second' => '6', + ); + + $output = new \DateTime('2010-02-03 04:05:06 UTC'); + $output->setTimezone(new \DateTimeZone('Asia/Hong_Kong')); + + $this->assertDateTimeEquals($output, $transformer->reverseTransform($input)); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testReverseTransformRequiresArray() + { + $transformer = new DateTimeToArrayTransformer(); + $transformer->reverseTransform('12345'); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testReverseTransformWithNegativeYear() + { + $transformer = new DateTimeToArrayTransformer(); + $transformer->reverseTransform(array( + 'year' => '-1', + 'month' => '2', + 'day' => '3', + 'hour' => '4', + 'minute' => '5', + 'second' => '6', + )); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testReverseTransformWithNegativeMonth() + { + $transformer = new DateTimeToArrayTransformer(); + $transformer->reverseTransform(array( + 'year' => '2010', + 'month' => '-1', + 'day' => '3', + 'hour' => '4', + 'minute' => '5', + 'second' => '6', + )); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testReverseTransformWithNegativeDay() + { + $transformer = new DateTimeToArrayTransformer(); + $transformer->reverseTransform(array( + 'year' => '2010', + 'month' => '2', + 'day' => '-1', + 'hour' => '4', + 'minute' => '5', + 'second' => '6', + )); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testReverseTransformWithNegativeHour() + { + $transformer = new DateTimeToArrayTransformer(); + $transformer->reverseTransform(array( + 'year' => '2010', + 'month' => '2', + 'day' => '3', + 'hour' => '-1', + 'minute' => '5', + 'second' => '6', + )); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testReverseTransformWithNegativeMinute() + { + $transformer = new DateTimeToArrayTransformer(); + $transformer->reverseTransform(array( + 'year' => '2010', + 'month' => '2', + 'day' => '3', + 'hour' => '4', + 'minute' => '-1', + 'second' => '6', + )); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testReverseTransformWithNegativeSecond() + { + $transformer = new DateTimeToArrayTransformer(); + $transformer->reverseTransform(array( + 'year' => '2010', + 'month' => '2', + 'day' => '3', + 'hour' => '4', + 'minute' => '5', + 'second' => '-1', + )); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testReverseTransformWithInvalidMonth() + { + $transformer = new DateTimeToArrayTransformer(); + $transformer->reverseTransform(array( + 'year' => '2010', + 'month' => '13', + 'day' => '3', + 'hour' => '4', + 'minute' => '5', + 'second' => '6', + )); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testReverseTransformWithInvalidDay() + { + $transformer = new DateTimeToArrayTransformer(); + $transformer->reverseTransform(array( + 'year' => '2010', + 'month' => '2', + 'day' => '31', + 'hour' => '4', + 'minute' => '5', + 'second' => '6', + )); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testReverseTransformWithStringDay() + { + $transformer = new DateTimeToArrayTransformer(); + $transformer->reverseTransform(array( + 'year' => '2010', + 'month' => '2', + 'day' => 'bazinga', + 'hour' => '4', + 'minute' => '5', + 'second' => '6', + )); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testReverseTransformWithStringMonth() + { + $transformer = new DateTimeToArrayTransformer(); + $transformer->reverseTransform(array( + 'year' => '2010', + 'month' => 'bazinga', + 'day' => '31', + 'hour' => '4', + 'minute' => '5', + 'second' => '6', + )); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testReverseTransformWithStringYear() + { + $transformer = new DateTimeToArrayTransformer(); + $transformer->reverseTransform(array( + 'year' => 'bazinga', + 'month' => '2', + 'day' => '31', + 'hour' => '4', + 'minute' => '5', + 'second' => '6', + )); + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformerTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformerTest.php new file mode 100644 index 00000000..cb50fc36 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformerTest.php @@ -0,0 +1,275 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; + +use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToLocalizedStringTransformer; +use Symfony\Component\Intl\Util\IntlTestHelper; + +class DateTimeToLocalizedStringTransformerTest extends DateTimeTestCase +{ + protected $dateTime; + protected $dateTimeWithoutSeconds; + + protected function setUp() + { + parent::setUp(); + + // Since we test against "de_AT", we need the full implementation + IntlTestHelper::requireFullIntl($this); + + \Locale::setDefault('de_AT'); + + $this->dateTime = new \DateTime('2010-02-03 04:05:06 UTC'); + $this->dateTimeWithoutSeconds = new \DateTime('2010-02-03 04:05:00 UTC'); + } + + protected function tearDown() + { + $this->dateTime = null; + $this->dateTimeWithoutSeconds = null; + } + + public static function assertEquals($expected, $actual, $message = '', $delta = 0, $maxDepth = 10, $canonicalize = false, $ignoreCase = false) + { + if ($expected instanceof \DateTime && $actual instanceof \DateTime) { + $expected = $expected->format('c'); + $actual = $actual->format('c'); + } + + parent::assertEquals($expected, $actual, $message, $delta, $maxDepth, $canonicalize, $ignoreCase); + } + + public function dataProvider() + { + return array( + array(\IntlDateFormatter::SHORT, null, null, '03.02.10 04:05', '2010-02-03 04:05:00 UTC'), + array(\IntlDateFormatter::MEDIUM, null, null, '03.02.2010 04:05', '2010-02-03 04:05:00 UTC'), + array(\IntlDateFormatter::LONG, null, null, '03. Februar 2010 04:05', '2010-02-03 04:05:00 UTC'), + array(\IntlDateFormatter::FULL, null, null, 'Mittwoch, 03. Februar 2010 04:05', '2010-02-03 04:05:00 UTC'), + array(\IntlDateFormatter::SHORT, \IntlDateFormatter::NONE, null, '03.02.10', '2010-02-03 00:00:00 UTC'), + array(\IntlDateFormatter::MEDIUM, \IntlDateFormatter::NONE, null, '03.02.2010', '2010-02-03 00:00:00 UTC'), + array(\IntlDateFormatter::LONG, \IntlDateFormatter::NONE, null, '03. Februar 2010', '2010-02-03 00:00:00 UTC'), + array(\IntlDateFormatter::FULL, \IntlDateFormatter::NONE, null, 'Mittwoch, 03. Februar 2010', '2010-02-03 00:00:00 UTC'), + array(null, \IntlDateFormatter::SHORT, null, '03.02.2010 04:05', '2010-02-03 04:05:00 UTC'), + array(null, \IntlDateFormatter::MEDIUM, null, '03.02.2010 04:05:06', '2010-02-03 04:05:06 UTC'), + array(null, \IntlDateFormatter::LONG, null, '03.02.2010 04:05:06 GMT', '2010-02-03 04:05:06 UTC'), + // see below for extra test case for time format FULL + array(\IntlDateFormatter::NONE, \IntlDateFormatter::SHORT, null, '04:05', '1970-01-01 04:05:00 UTC'), + array(\IntlDateFormatter::NONE, \IntlDateFormatter::MEDIUM, null, '04:05:06', '1970-01-01 04:05:06 UTC'), + array(\IntlDateFormatter::NONE, \IntlDateFormatter::LONG, null, '04:05:06 GMT', '1970-01-01 04:05:06 UTC'), + array(null, null, 'yyyy-MM-dd HH:mm:00', '2010-02-03 04:05:00', '2010-02-03 04:05:00 UTC'), + array(null, null, 'yyyy-MM-dd HH:mm', '2010-02-03 04:05', '2010-02-03 04:05:00 UTC'), + array(null, null, 'yyyy-MM-dd HH', '2010-02-03 04', '2010-02-03 04:00:00 UTC'), + array(null, null, 'yyyy-MM-dd', '2010-02-03', '2010-02-03 00:00:00 UTC'), + array(null, null, 'yyyy-MM', '2010-02', '2010-02-01 00:00:00 UTC'), + array(null, null, 'yyyy', '2010', '2010-01-01 00:00:00 UTC'), + array(null, null, 'dd-MM-yyyy', '03-02-2010', '2010-02-03 00:00:00 UTC'), + array(null, null, 'HH:mm:ss', '04:05:06', '1970-01-01 04:05:06 UTC'), + array(null, null, 'HH:mm:00', '04:05:00', '1970-01-01 04:05:00 UTC'), + array(null, null, 'HH:mm', '04:05', '1970-01-01 04:05:00 UTC'), + array(null, null, 'HH', '04', '1970-01-01 04:00:00 UTC'), + ); + } + + /** + * @dataProvider dataProvider + */ + public function testTransform($dateFormat, $timeFormat, $pattern, $output, $input) + { + $transformer = new DateTimeToLocalizedStringTransformer( + 'UTC', + 'UTC', + $dateFormat, + $timeFormat, + \IntlDateFormatter::GREGORIAN, + $pattern + ); + + $input = new \DateTime($input); + + $this->assertEquals($output, $transformer->transform($input)); + } + + public function testTransformFullTime() + { + $transformer = new DateTimeToLocalizedStringTransformer('UTC', 'UTC', null, \IntlDateFormatter::FULL); + + $this->assertEquals('03.02.2010 04:05:06 GMT', $transformer->transform($this->dateTime)); + } + + public function testTransformToDifferentLocale() + { + \Locale::setDefault('en_US'); + + $transformer = new DateTimeToLocalizedStringTransformer('UTC', 'UTC'); + + $this->assertEquals('Feb 3, 2010, 4:05 AM', $transformer->transform($this->dateTime)); + } + + public function testTransformEmpty() + { + $transformer = new DateTimeToLocalizedStringTransformer(); + + $this->assertSame('', $transformer->transform(null)); + } + + public function testTransformWithDifferentTimezones() + { + $transformer = new DateTimeToLocalizedStringTransformer('America/New_York', 'Asia/Hong_Kong'); + + $input = new \DateTime('2010-02-03 04:05:06 America/New_York'); + + $dateTime = clone $input; + $dateTime->setTimezone(new \DateTimeZone('Asia/Hong_Kong')); + + $this->assertEquals($dateTime->format('d.m.Y H:i'), $transformer->transform($input)); + } + + public function testTransformWithDifferentPatterns() + { + $transformer = new DateTimeToLocalizedStringTransformer('UTC', 'UTC', \IntlDateFormatter::FULL, \IntlDateFormatter::FULL, \IntlDateFormatter::GREGORIAN, 'MM*yyyy*dd HH|mm|ss'); + + $this->assertEquals('02*2010*03 04|05|06', $transformer->transform($this->dateTime)); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testTransformRequiresValidDateTime() + { + $transformer = new DateTimeToLocalizedStringTransformer(); + $transformer->transform('2010-01-01'); + } + + public function testTransformWrapsIntlErrors() + { + $transformer = new DateTimeToLocalizedStringTransformer(); + + // HOW TO REPRODUCE? + + //$this->setExpectedException('Symfony\Component\Form\Extension\Core\DataTransformer\Transdate_formationFailedException'); + + //$transformer->transform(1.5); + } + + /** + * @dataProvider dataProvider + */ + public function testReverseTransform($dateFormat, $timeFormat, $pattern, $input, $output) + { + $transformer = new DateTimeToLocalizedStringTransformer( + 'UTC', + 'UTC', + $dateFormat, + $timeFormat, + \IntlDateFormatter::GREGORIAN, + $pattern + ); + + $output = new \DateTime($output); + + $this->assertEquals($output, $transformer->reverseTransform($input)); + } + + public function testReverseTransformFullTime() + { + $transformer = new DateTimeToLocalizedStringTransformer('UTC', 'UTC', null, \IntlDateFormatter::FULL); + + $this->assertDateTimeEquals($this->dateTime, $transformer->reverseTransform('03.02.2010 04:05:06 GMT+00:00')); + } + + public function testReverseTransformFromDifferentLocale() + { + \Locale::setDefault('en_US'); + + $transformer = new DateTimeToLocalizedStringTransformer('UTC', 'UTC'); + + $this->assertDateTimeEquals($this->dateTimeWithoutSeconds, $transformer->reverseTransform('Feb 3, 2010, 04:05 AM')); + } + + public function testReverseTransformWithDifferentTimezones() + { + $transformer = new DateTimeToLocalizedStringTransformer('America/New_York', 'Asia/Hong_Kong'); + + $dateTime = new \DateTime('2010-02-03 04:05:00 Asia/Hong_Kong'); + $dateTime->setTimezone(new \DateTimeZone('America/New_York')); + + $this->assertDateTimeEquals($dateTime, $transformer->reverseTransform('03.02.2010 04:05')); + } + + public function testReverseTransformWithDifferentPatterns() + { + $transformer = new DateTimeToLocalizedStringTransformer('UTC', 'UTC', \IntlDateFormatter::FULL, \IntlDateFormatter::FULL, \IntlDateFormatter::GREGORIAN, 'MM*yyyy*dd HH|mm|ss'); + + $this->assertDateTimeEquals($this->dateTime, $transformer->reverseTransform('02*2010*03 04|05|06')); + } + + public function testReverseTransformEmpty() + { + $transformer = new DateTimeToLocalizedStringTransformer(); + + $this->assertNull($transformer->reverseTransform('')); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testReverseTransformRequiresString() + { + $transformer = new DateTimeToLocalizedStringTransformer(); + $transformer->reverseTransform(12345); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testReverseTransformWrapsIntlErrors() + { + $transformer = new DateTimeToLocalizedStringTransformer(); + $transformer->reverseTransform('12345'); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException + */ + public function testValidateDateFormatOption() + { + new DateTimeToLocalizedStringTransformer(null, null, 'foobar'); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException + */ + public function testValidateTimeFormatOption() + { + new DateTimeToLocalizedStringTransformer(null, null, null, 'foobar'); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testReverseTransformWithNonExistingDate() + { + $transformer = new DateTimeToLocalizedStringTransformer('UTC', 'UTC', \IntlDateFormatter::SHORT); + + $this->assertDateTimeEquals($this->dateTimeWithoutSeconds, $transformer->reverseTransform('31.04.10 04:05')); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testReverseTransformOutOfTimestampRange() + { + $transformer = new DateTimeToLocalizedStringTransformer('UTC', 'UTC'); + $transformer->reverseTransform('1789-07-14'); + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToRfc3339TransformerTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToRfc3339TransformerTest.php new file mode 100644 index 00000000..98aeb772 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToRfc3339TransformerTest.php @@ -0,0 +1,132 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; + +use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToRfc3339Transformer; + +class DateTimeToRfc3339TransformerTest extends DateTimeTestCase +{ + protected $dateTime; + protected $dateTimeWithoutSeconds; + + protected function setUp() + { + parent::setUp(); + + $this->dateTime = new \DateTime('2010-02-03 04:05:06 UTC'); + $this->dateTimeWithoutSeconds = new \DateTime('2010-02-03 04:05:00 UTC'); + } + + protected function tearDown() + { + $this->dateTime = null; + $this->dateTimeWithoutSeconds = null; + } + + public static function assertEquals($expected, $actual, $message = '', $delta = 0, $maxDepth = 10, $canonicalize = FALSE, $ignoreCase = FALSE) + { + if ($expected instanceof \DateTime && $actual instanceof \DateTime) { + $expected = $expected->format('c'); + $actual = $actual->format('c'); + } + + parent::assertEquals($expected, $actual, $message, $delta, $maxDepth, $canonicalize, $ignoreCase); + } + + public function allProvider() + { + return array( + array('UTC', 'UTC', '2010-02-03 04:05:06 UTC', '2010-02-03T04:05:06Z'), + array('UTC', 'UTC', null, ''), + array('America/New_York', 'Asia/Hong_Kong', '2010-02-03 04:05:06 America/New_York', '2010-02-03T17:05:06+08:00'), + array('America/New_York', 'Asia/Hong_Kong', null, ''), + array('UTC', 'Asia/Hong_Kong', '2010-02-03 04:05:06 UTC', '2010-02-03T12:05:06+08:00'), + array('America/New_York', 'UTC', '2010-02-03 04:05:06 America/New_York', '2010-02-03T09:05:06Z'), + ); + } + + public function transformProvider() + { + return $this->allProvider(); + } + + public function reverseTransformProvider() + { + return array_merge($this->allProvider(), array( + // format without seconds, as appears in some browsers + array('UTC', 'UTC', '2010-02-03 04:05:00 UTC', '2010-02-03T04:05Z'), + array('America/New_York', 'Asia/Hong_Kong', '2010-02-03 04:05:00 America/New_York', '2010-02-03T17:05+08:00'), + )); + } + + /** + * @dataProvider transformProvider + */ + public function testTransform($fromTz, $toTz, $from, $to) + { + $transformer = new DateTimeToRfc3339Transformer($fromTz, $toTz); + + $this->assertSame($to, $transformer->transform(null !== $from ? new \DateTime($from) : null)); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testTransformRequiresValidDateTime() + { + $transformer = new DateTimeToRfc3339Transformer(); + $transformer->transform('2010-01-01'); + } + + /** + * @dataProvider reverseTransformProvider + */ + public function testReverseTransform($toTz, $fromTz, $to, $from) + { + $transformer = new DateTimeToRfc3339Transformer($toTz, $fromTz); + + if (null !== $to) { + $this->assertDateTimeEquals(new \DateTime($to), $transformer->reverseTransform($from)); + } else { + $this->assertSame($to, $transformer->reverseTransform($from)); + } + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testReverseTransformRequiresString() + { + $transformer = new DateTimeToRfc3339Transformer(); + $transformer->reverseTransform(12345); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testReverseTransformWithNonExistingDate() + { + $transformer = new DateTimeToRfc3339Transformer('UTC', 'UTC'); + + $transformer->reverseTransform('2010-04-31T04:05Z'); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testReverseTransformExpectsValidDateString() + { + $transformer = new DateTimeToRfc3339Transformer('UTC', 'UTC'); + + $transformer->reverseTransform('2010-2010-2010'); + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToStringTransformerTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToStringTransformerTest.php new file mode 100644 index 00000000..987df1d8 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToStringTransformerTest.php @@ -0,0 +1,181 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; + +use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToStringTransformer; + +class DateTimeToStringTransformerTest extends DateTimeTestCase +{ + public function dataProvider() + { + $data = array( + array('Y-m-d H:i:s', '2010-02-03 16:05:06', '2010-02-03 16:05:06 UTC'), + array('Y-m-d H:i:00', '2010-02-03 16:05:00', '2010-02-03 16:05:00 UTC'), + array('Y-m-d H:i', '2010-02-03 16:05', '2010-02-03 16:05:00 UTC'), + array('Y-m-d H', '2010-02-03 16', '2010-02-03 16:00:00 UTC'), + array('Y-m-d', '2010-02-03', '2010-02-03 00:00:00 UTC'), + array('Y-m', '2010-12', '2010-12-01 00:00:00 UTC'), + array('Y', '2010', '2010-01-01 00:00:00 UTC'), + array('d-m-Y', '03-02-2010', '2010-02-03 00:00:00 UTC'), + array('H:i:s', '16:05:06', '1970-01-01 16:05:06 UTC'), + array('H:i:00', '16:05:00', '1970-01-01 16:05:00 UTC'), + array('H:i', '16:05', '1970-01-01 16:05:00 UTC'), + array('H', '16', '1970-01-01 16:00:00 UTC'), + + // different day representations + array('Y-m-j', '2010-02-3', '2010-02-03 00:00:00 UTC'), + array('z', '33', '1970-02-03 00:00:00 UTC'), + + // not bijective + // this will not work as php will use actual date to replace missing info + // and after change of date will lookup for closest Wednesday + // i.e. value: 2010-02, php value: 2010-02-(today i.e. 20), parsed date: 2010-02-24 + //array('Y-m-D', '2010-02-Wed', '2010-02-03 00:00:00 UTC'), + //array('Y-m-l', '2010-02-Wednesday', '2010-02-03 00:00:00 UTC'), + + // different month representations + array('Y-n-d', '2010-2-03', '2010-02-03 00:00:00 UTC'), + array('Y-M-d', '2010-Feb-03', '2010-02-03 00:00:00 UTC'), + array('Y-F-d', '2010-February-03', '2010-02-03 00:00:00 UTC'), + + // different year representations + array('y-m-d', '10-02-03', '2010-02-03 00:00:00 UTC'), + + // different time representations + array('G:i:s', '16:05:06', '1970-01-01 16:05:06 UTC'), + array('g:i:s a', '4:05:06 pm', '1970-01-01 16:05:06 UTC'), + array('h:i:s a', '04:05:06 pm', '1970-01-01 16:05:06 UTC'), + + // seconds since unix + array('U', '1265213106', '2010-02-03 16:05:06 UTC'), + ); + + // This test will fail < 5.3.9 - see https://bugs.php.net/51994 + if (version_compare(phpversion(), '5.3.9', '>=')) { + $data[] = array('Y-z', '2010-33', '2010-02-03 00:00:00 UTC'); + } + + return $data; + } + + /** + * @dataProvider dataProvider + */ + public function testTransform($format, $output, $input) + { + $transformer = new DateTimeToStringTransformer('UTC', 'UTC', $format); + + $input = new \DateTime($input); + + $this->assertEquals($output, $transformer->transform($input)); + } + + public function testTransformEmpty() + { + $transformer = new DateTimeToStringTransformer(); + + $this->assertSame('', $transformer->transform(null)); + } + + public function testTransformWithDifferentTimezones() + { + $transformer = new DateTimeToStringTransformer('Asia/Hong_Kong', 'America/New_York', 'Y-m-d H:i:s'); + + $input = new \DateTime('2010-02-03 12:05:06 America/New_York'); + $output = $input->format('Y-m-d H:i:s'); + $input->setTimezone(new \DateTimeZone('Asia/Hong_Kong')); + + $this->assertEquals($output, $transformer->transform($input)); + } + + public function testTransformExpectsDateTime() + { + $transformer = new DateTimeToStringTransformer(); + + $this->setExpectedException('Symfony\Component\Form\Exception\TransformationFailedException'); + + $transformer->transform('1234'); + } + + /** + * @dataProvider dataProvider + */ + public function testReverseTransformUsingPipe($format, $input, $output) + { + if (version_compare(phpversion(), '5.3.7', '<')) { + $this->markTestSkipped('Pipe usage requires PHP 5.3.7 or newer.'); + } + + $reverseTransformer = new DateTimeToStringTransformer('UTC', 'UTC', $format, true); + + $output = new \DateTime($output); + + $this->assertDateTimeEquals($output, $reverseTransformer->reverseTransform($input)); + } + + /** + * @dataProvider dataProvider + */ + public function testReverseTransformWithoutUsingPipe($format, $input, $output) + { + $reverseTransformer = new DateTimeToStringTransformer('UTC', 'UTC', $format, false); + + $output = new \DateTime($output); + + $this->assertDateTimeEquals($output, $reverseTransformer->reverseTransform($input)); + } + + public function testReverseTransformEmpty() + { + $reverseTransformer = new DateTimeToStringTransformer(); + + $this->assertNull($reverseTransformer->reverseTransform('')); + } + + public function testReverseTransformWithDifferentTimezones() + { + $reverseTransformer = new DateTimeToStringTransformer('America/New_York', 'Asia/Hong_Kong', 'Y-m-d H:i:s'); + + $output = new \DateTime('2010-02-03 16:05:06 Asia/Hong_Kong'); + $input = $output->format('Y-m-d H:i:s'); + $output->setTimeZone(new \DateTimeZone('America/New_York')); + + $this->assertDateTimeEquals($output, $reverseTransformer->reverseTransform($input)); + } + + public function testReverseTransformExpectsString() + { + $reverseTransformer = new DateTimeToStringTransformer(); + + $this->setExpectedException('Symfony\Component\Form\Exception\TransformationFailedException'); + + $reverseTransformer->reverseTransform(1234); + } + + public function testReverseTransformExpectsValidDateString() + { + $reverseTransformer = new DateTimeToStringTransformer(); + + $this->setExpectedException('Symfony\Component\Form\Exception\TransformationFailedException'); + + $reverseTransformer->reverseTransform('2010-2010-2010'); + } + + public function testReverseTransformWithNonExistingDate() + { + $reverseTransformer = new DateTimeToStringTransformer(); + + $this->setExpectedException('Symfony\Component\Form\Exception\TransformationFailedException'); + + $reverseTransformer->reverseTransform('2010-04-31'); + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToTimestampTransformerTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToTimestampTransformerTest.php new file mode 100644 index 00000000..b54f0c4c --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToTimestampTransformerTest.php @@ -0,0 +1,104 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; + +use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToTimestampTransformer; + +class DateTimeToTimestampTransformerTest extends DateTimeTestCase +{ + public function testTransform() + { + $transformer = new DateTimeToTimestampTransformer('UTC', 'UTC'); + + $input = new \DateTime('2010-02-03 04:05:06 UTC'); + $output = $input->format('U'); + + $this->assertEquals($output, $transformer->transform($input)); + } + + public function testTransformEmpty() + { + $transformer = new DateTimeToTimestampTransformer(); + + $this->assertNull($transformer->transform(null)); + } + + public function testTransformWithDifferentTimezones() + { + $transformer = new DateTimeToTimestampTransformer('Asia/Hong_Kong', 'America/New_York'); + + $input = new \DateTime('2010-02-03 04:05:06 America/New_York'); + $output = $input->format('U'); + $input->setTimezone(new \DateTimeZone('Asia/Hong_Kong')); + + $this->assertEquals($output, $transformer->transform($input)); + } + + public function testTransformFromDifferentTimezone() + { + $transformer = new DateTimeToTimestampTransformer('Asia/Hong_Kong', 'UTC'); + + $input = new \DateTime('2010-02-03 04:05:06 Asia/Hong_Kong'); + + $dateTime = clone $input; + $dateTime->setTimezone(new \DateTimeZone('UTC')); + $output = $dateTime->format('U'); + + $this->assertEquals($output, $transformer->transform($input)); + } + + public function testTransformExpectsDateTime() + { + $transformer = new DateTimeToTimestampTransformer(); + + $this->setExpectedException('Symfony\Component\Form\Exception\TransformationFailedException'); + + $transformer->transform('1234'); + } + + public function testReverseTransform() + { + $reverseTransformer = new DateTimeToTimestampTransformer('UTC', 'UTC'); + + $output = new \DateTime('2010-02-03 04:05:06 UTC'); + $input = $output->format('U'); + + $this->assertDateTimeEquals($output, $reverseTransformer->reverseTransform($input)); + } + + public function testReverseTransformEmpty() + { + $reverseTransformer = new DateTimeToTimestampTransformer(); + + $this->assertNull($reverseTransformer->reverseTransform(null)); + } + + public function testReverseTransformWithDifferentTimezones() + { + $reverseTransformer = new DateTimeToTimestampTransformer('Asia/Hong_Kong', 'America/New_York'); + + $output = new \DateTime('2010-02-03 04:05:06 America/New_York'); + $input = $output->format('U'); + $output->setTimezone(new \DateTimeZone('Asia/Hong_Kong')); + + $this->assertDateTimeEquals($output, $reverseTransformer->reverseTransform($input)); + } + + public function testReverseTransformExpectsValidTimestamp() + { + $reverseTransformer = new DateTimeToTimestampTransformer(); + + $this->setExpectedException('Symfony\Component\Form\Exception\TransformationFailedException'); + + $reverseTransformer->reverseTransform('2010-2010-2010'); + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformerTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformerTest.php new file mode 100644 index 00000000..a90fa91b --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformerTest.php @@ -0,0 +1,115 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; + +use Symfony\Component\Form\Extension\Core\DataTransformer\IntegerToLocalizedStringTransformer; +use Symfony\Component\Intl\Util\IntlTestHelper; + +class IntegerToLocalizedStringTransformerTest extends \PHPUnit_Framework_TestCase +{ + protected function setUp() + { + parent::setUp(); + + // Since we test against "de_AT", we need the full implementation + IntlTestHelper::requireFullIntl($this); + + \Locale::setDefault('de_AT'); + } + + public function testReverseTransform() + { + $transformer = new IntegerToLocalizedStringTransformer(); + + $this->assertEquals(1, $transformer->reverseTransform('1')); + $this->assertEquals(1, $transformer->reverseTransform('1,5')); + $this->assertEquals(1234, $transformer->reverseTransform('1234,5')); + $this->assertEquals(12345, $transformer->reverseTransform('12345,912')); + } + + public function testReverseTransformEmpty() + { + $transformer = new IntegerToLocalizedStringTransformer(); + + $this->assertNull($transformer->reverseTransform('')); + } + + public function testReverseTransformWithGrouping() + { + $transformer = new IntegerToLocalizedStringTransformer(null, true); + + $this->assertEquals(1234, $transformer->reverseTransform('1.234,5')); + $this->assertEquals(12345, $transformer->reverseTransform('12.345,912')); + $this->assertEquals(1234, $transformer->reverseTransform('1234,5')); + $this->assertEquals(12345, $transformer->reverseTransform('12345,912')); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testReverseTransformExpectsString() + { + $transformer = new IntegerToLocalizedStringTransformer(); + + $transformer->reverseTransform(1); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testReverseTransformExpectsValidNumber() + { + $transformer = new IntegerToLocalizedStringTransformer(); + + $transformer->reverseTransform('foo'); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testReverseTransformDisallowsNaN() + { + $transformer = new IntegerToLocalizedStringTransformer(); + + $transformer->reverseTransform('NaN'); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testReverseTransformDisallowsNaN2() + { + $transformer = new IntegerToLocalizedStringTransformer(); + + $transformer->reverseTransform('nan'); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testReverseTransformDisallowsInfinity() + { + $transformer = new IntegerToLocalizedStringTransformer(); + + $transformer->reverseTransform('∞'); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testReverseTransformDisallowsNegativeInfinity() + { + $transformer = new IntegerToLocalizedStringTransformer(); + + $transformer->reverseTransform('-∞'); + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformerTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformerTest.php new file mode 100644 index 00000000..8b91fe10 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformerTest.php @@ -0,0 +1,74 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; + +use Symfony\Component\Form\Extension\Core\DataTransformer\MoneyToLocalizedStringTransformer; +use Symfony\Component\Intl\Util\IntlTestHelper; + +class MoneyToLocalizedStringTransformerTest extends \PHPUnit_Framework_TestCase +{ + protected function setUp() + { + parent::setUp(); + + // Since we test against "de_AT", we need the full implementation + IntlTestHelper::requireFullIntl($this); + + \Locale::setDefault('de_AT'); + } + + public function testTransform() + { + $transformer = new MoneyToLocalizedStringTransformer(null, null, null, 100); + + $this->assertEquals('1,23', $transformer->transform(123)); + } + + public function testTransformExpectsNumeric() + { + $transformer = new MoneyToLocalizedStringTransformer(null, null, null, 100); + + $this->setExpectedException('Symfony\Component\Form\Exception\TransformationFailedException'); + + $transformer->transform('abcd'); + } + + public function testTransformEmpty() + { + $transformer = new MoneyToLocalizedStringTransformer(); + + $this->assertSame('', $transformer->transform(null)); + } + + public function testReverseTransform() + { + $transformer = new MoneyToLocalizedStringTransformer(null, null, null, 100); + + $this->assertEquals(123, $transformer->reverseTransform('1,23')); + } + + public function testReverseTransformExpectsString() + { + $transformer = new MoneyToLocalizedStringTransformer(null, null, null, 100); + + $this->setExpectedException('Symfony\Component\Form\Exception\TransformationFailedException'); + + $transformer->reverseTransform(12345); + } + + public function testReverseTransformEmpty() + { + $transformer = new MoneyToLocalizedStringTransformer(); + + $this->assertNull($transformer->reverseTransform('')); + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/NumberToLocalizedStringTransformerTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/NumberToLocalizedStringTransformerTest.php new file mode 100644 index 00000000..c58e3f60 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/NumberToLocalizedStringTransformerTest.php @@ -0,0 +1,393 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; + +use Symfony\Component\Form\Extension\Core\DataTransformer\NumberToLocalizedStringTransformer; +use Symfony\Component\Intl\Util\IntlTestHelper; + +class NumberToLocalizedStringTransformerTest extends \PHPUnit_Framework_TestCase +{ + protected function setUp() + { + parent::setUp(); + + // Since we test against "de_AT", we need the full implementation + IntlTestHelper::requireFullIntl($this); + + \Locale::setDefault('de_AT'); + } + + public function provideTransformations() + { + return array( + array(null, '', 'de_AT'), + array(1, '1', 'de_AT'), + array(1.5, '1,5', 'de_AT'), + array(1234.5, '1234,5', 'de_AT'), + array(12345.912, '12345,912', 'de_AT'), + array(1234.5, '1234,5', 'ru'), + array(1234.5, '1234,5', 'fi'), + ); + } + + /** + * @dataProvider provideTransformations + */ + public function testTransform($from, $to, $locale) + { + \Locale::setDefault($locale); + + $transformer = new NumberToLocalizedStringTransformer(); + + $this->assertSame($to, $transformer->transform($from)); + } + + public function provideTransformationsWithGrouping() + { + return array( + array(1234.5, '1.234,5', 'de_AT'), + array(12345.912, '12.345,912', 'de_AT'), + array(1234.5, '1 234,5', 'fr'), + array(1234.5, '1 234,5', 'ru'), + array(1234.5, '1 234,5', 'fi'), + ); + } + + /** + * @dataProvider provideTransformationsWithGrouping + */ + public function testTransformWithGrouping($from, $to, $locale) + { + \Locale::setDefault($locale); + + $transformer = new NumberToLocalizedStringTransformer(null, true); + + $this->assertSame($to, $transformer->transform($from)); + } + + public function testTransformWithPrecision() + { + $transformer = new NumberToLocalizedStringTransformer(2); + + $this->assertEquals('1234,50', $transformer->transform(1234.5)); + $this->assertEquals('678,92', $transformer->transform(678.916)); + } + + public function testTransformWithRoundingMode() + { + $transformer = new NumberToLocalizedStringTransformer(null, null, NumberToLocalizedStringTransformer::ROUND_DOWN); + $this->assertEquals('1234,547', $transformer->transform(1234.547), '->transform() only applies rounding mode if precision set'); + + $transformer = new NumberToLocalizedStringTransformer(2, null, NumberToLocalizedStringTransformer::ROUND_DOWN); + $this->assertEquals('1234,54', $transformer->transform(1234.547), '->transform() rounding-mode works'); + + } + + /** + * @dataProvider provideTransformations + */ + public function testReverseTransform($to, $from, $locale) + { + \Locale::setDefault($locale); + + $transformer = new NumberToLocalizedStringTransformer(); + + $this->assertEquals($to, $transformer->reverseTransform($from)); + } + + /** + * @dataProvider provideTransformationsWithGrouping + */ + public function testReverseTransformWithGrouping($to, $from, $locale) + { + \Locale::setDefault($locale); + + $transformer = new NumberToLocalizedStringTransformer(null, true); + + $this->assertEquals($to, $transformer->reverseTransform($from)); + } + + // https://github.com/symfony/symfony/issues/7609 + public function testReverseTransformWithGroupingAndFixedSpaces() + { + if (!extension_loaded('mbstring')) { + $this->markTestSkipped('The "mbstring" extension is required for this test.'); + } + + \Locale::setDefault('ru'); + + $transformer = new NumberToLocalizedStringTransformer(null, true); + + $this->assertEquals(1234.5, $transformer->reverseTransform("1\xc2\xa0234,5")); + } + + public function testReverseTransformWithGroupingButWithoutGroupSeparator() + { + $transformer = new NumberToLocalizedStringTransformer(null, true); + + // omit group separator + $this->assertEquals(1234.5, $transformer->reverseTransform('1234,5')); + $this->assertEquals(12345.912, $transformer->reverseTransform('12345,912')); + } + + public function testDecimalSeparatorMayBeDotIfGroupingSeparatorIsNotDot() + { + \Locale::setDefault('fr'); + $transformer = new NumberToLocalizedStringTransformer(null, true); + + // completely valid format + $this->assertEquals(1234.5, $transformer->reverseTransform('1 234,5')); + // accept dots + $this->assertEquals(1234.5, $transformer->reverseTransform('1 234.5')); + // omit group separator + $this->assertEquals(1234.5, $transformer->reverseTransform('1234,5')); + $this->assertEquals(1234.5, $transformer->reverseTransform('1234.5')); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testDecimalSeparatorMayNotBeDotIfGroupingSeparatorIsDot() + { + $transformer = new NumberToLocalizedStringTransformer(null, true); + + $transformer->reverseTransform('1.234.5'); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testDecimalSeparatorMayNotBeDotIfGroupingSeparatorIsDotWithNoGroupSep() + { + $transformer = new NumberToLocalizedStringTransformer(null, true); + + $transformer->reverseTransform('1234.5'); + } + + public function testDecimalSeparatorMayBeDotIfGroupingSeparatorIsDotButNoGroupingUsed() + { + \Locale::setDefault('fr'); + $transformer = new NumberToLocalizedStringTransformer(); + + $this->assertEquals(1234.5, $transformer->reverseTransform('1234,5')); + $this->assertEquals(1234.5, $transformer->reverseTransform('1234.5')); + } + + public function testDecimalSeparatorMayBeCommaIfGroupingSeparatorIsNotComma() + { + \Locale::setDefault('bg'); + $transformer = new NumberToLocalizedStringTransformer(null, true); + + // completely valid format + $this->assertEquals(1234.5, $transformer->reverseTransform('1 234.5')); + // accept commas + $this->assertEquals(1234.5, $transformer->reverseTransform('1 234,5')); + // omit group separator + $this->assertEquals(1234.5, $transformer->reverseTransform('1234.5')); + $this->assertEquals(1234.5, $transformer->reverseTransform('1234,5')); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testDecimalSeparatorMayNotBeCommaIfGroupingSeparatorIsComma() + { + \Locale::setDefault('en'); + $transformer = new NumberToLocalizedStringTransformer(null, true); + + $transformer->reverseTransform('1,234,5'); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testDecimalSeparatorMayNotBeCommaIfGroupingSeparatorIsCommaWithNoGroupSep() + { + \Locale::setDefault('en'); + $transformer = new NumberToLocalizedStringTransformer(null, true); + + $transformer->reverseTransform('1234,5'); + } + + public function testDecimalSeparatorMayBeCommaIfGroupingSeparatorIsCommaButNoGroupingUsed() + { + \Locale::setDefault('en'); + $transformer = new NumberToLocalizedStringTransformer(); + + $this->assertEquals(1234.5, $transformer->reverseTransform('1234,5')); + $this->assertEquals(1234.5, $transformer->reverseTransform('1234.5')); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testTransformExpectsNumeric() + { + $transformer = new NumberToLocalizedStringTransformer(); + + $transformer->transform('foo'); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testReverseTransformExpectsString() + { + $transformer = new NumberToLocalizedStringTransformer(); + + $transformer->reverseTransform(1); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testReverseTransformExpectsValidNumber() + { + $transformer = new NumberToLocalizedStringTransformer(); + + $transformer->reverseTransform('foo'); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + * @link https://github.com/symfony/symfony/issues/3161 + */ + public function testReverseTransformDisallowsNaN() + { + $transformer = new NumberToLocalizedStringTransformer(); + + $transformer->reverseTransform('NaN'); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testReverseTransformDisallowsNaN2() + { + $transformer = new NumberToLocalizedStringTransformer(); + + $transformer->reverseTransform('nan'); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testReverseTransformDisallowsInfinity() + { + $transformer = new NumberToLocalizedStringTransformer(); + + $transformer->reverseTransform('∞'); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testReverseTransformDisallowsInfinity2() + { + $transformer = new NumberToLocalizedStringTransformer(); + + $transformer->reverseTransform('∞,123'); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testReverseTransformDisallowsNegativeInfinity() + { + $transformer = new NumberToLocalizedStringTransformer(); + + $transformer->reverseTransform('-∞'); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testReverseTransformDisallowsLeadingExtraCharacters() + { + $transformer = new NumberToLocalizedStringTransformer(); + + $transformer->reverseTransform('foo123'); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + * @expectedExceptionMessage The number contains unrecognized characters: "foo3" + */ + public function testReverseTransformDisallowsCenteredExtraCharacters() + { + $transformer = new NumberToLocalizedStringTransformer(); + + $transformer->reverseTransform('12foo3'); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + * @expectedExceptionMessage The number contains unrecognized characters: "foo8" + */ + public function testReverseTransformDisallowsCenteredExtraCharactersMultibyte() + { + if (!extension_loaded('mbstring')) { + $this->markTestSkipped('The "mbstring" extension is required for this test.'); + } + + \Locale::setDefault('ru'); + + $transformer = new NumberToLocalizedStringTransformer(null, true); + + $transformer->reverseTransform("12\xc2\xa0345,67foo8"); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + * @expectedExceptionMessage The number contains unrecognized characters: "foo8" + */ + public function testReverseTransformIgnoresTrailingSpacesInExceptionMessage() + { + if (!extension_loaded('mbstring')) { + $this->markTestSkipped('The "mbstring" extension is required for this test.'); + } + + \Locale::setDefault('ru'); + + $transformer = new NumberToLocalizedStringTransformer(null, true); + + $transformer->reverseTransform("12\xc2\xa0345,67foo8 \xc2\xa0\t"); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + * @expectedExceptionMessage The number contains unrecognized characters: "foo" + */ + public function testReverseTransformDisallowsTrailingExtraCharacters() + { + $transformer = new NumberToLocalizedStringTransformer(); + + $transformer->reverseTransform('123foo'); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + * @expectedExceptionMessage The number contains unrecognized characters: "foo" + */ + public function testReverseTransformDisallowsTrailingExtraCharactersMultibyte() + { + if (!extension_loaded('mbstring')) { + $this->markTestSkipped('The "mbstring" extension is required for this test.'); + } + + \Locale::setDefault('ru'); + + $transformer = new NumberToLocalizedStringTransformer(null, true); + + $transformer->reverseTransform("12\xc2\xa0345,678foo"); + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/PercentToLocalizedStringTransformerTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/PercentToLocalizedStringTransformerTest.php new file mode 100644 index 00000000..104941c9 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/PercentToLocalizedStringTransformerTest.php @@ -0,0 +1,114 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; + +use Symfony\Component\Form\Extension\Core\DataTransformer\PercentToLocalizedStringTransformer; +use Symfony\Component\Intl\Util\IntlTestHelper; + +class PercentToLocalizedStringTransformerTest extends \PHPUnit_Framework_TestCase +{ + protected function setUp() + { + parent::setUp(); + + // Since we test against "de_AT", we need the full implementation + IntlTestHelper::requireFullIntl($this); + + \Locale::setDefault('de_AT'); + } + + public function testTransform() + { + $transformer = new PercentToLocalizedStringTransformer(); + + $this->assertEquals('10', $transformer->transform(0.1)); + $this->assertEquals('15', $transformer->transform(0.15)); + $this->assertEquals('12', $transformer->transform(0.1234)); + $this->assertEquals('200', $transformer->transform(2)); + } + + public function testTransformEmpty() + { + $transformer = new PercentToLocalizedStringTransformer(); + + $this->assertEquals('', $transformer->transform(null)); + } + + public function testTransformWithInteger() + { + $transformer = new PercentToLocalizedStringTransformer(null, 'integer'); + + $this->assertEquals('0', $transformer->transform(0.1)); + $this->assertEquals('1', $transformer->transform(1)); + $this->assertEquals('15', $transformer->transform(15)); + $this->assertEquals('16', $transformer->transform(15.9)); + } + + public function testTransformWithPrecision() + { + $transformer = new PercentToLocalizedStringTransformer(2); + + $this->assertEquals('12,34', $transformer->transform(0.1234)); + } + + public function testReverseTransform() + { + $transformer = new PercentToLocalizedStringTransformer(); + + $this->assertEquals(0.1, $transformer->reverseTransform('10')); + $this->assertEquals(0.15, $transformer->reverseTransform('15')); + $this->assertEquals(0.12, $transformer->reverseTransform('12')); + $this->assertEquals(2, $transformer->reverseTransform('200')); + } + + public function testReverseTransformEmpty() + { + $transformer = new PercentToLocalizedStringTransformer(); + + $this->assertNull($transformer->reverseTransform('')); + } + + public function testReverseTransformWithInteger() + { + $transformer = new PercentToLocalizedStringTransformer(null, 'integer'); + + $this->assertEquals(10, $transformer->reverseTransform('10')); + $this->assertEquals(15, $transformer->reverseTransform('15')); + $this->assertEquals(12, $transformer->reverseTransform('12')); + $this->assertEquals(200, $transformer->reverseTransform('200')); + } + + public function testReverseTransformWithPrecision() + { + $transformer = new PercentToLocalizedStringTransformer(2); + + $this->assertEquals(0.1234, $transformer->reverseTransform('12,34')); + } + + public function testTransformExpectsNumeric() + { + $transformer = new PercentToLocalizedStringTransformer(); + + $this->setExpectedException('Symfony\Component\Form\Exception\TransformationFailedException'); + + $transformer->transform('foo'); + } + + public function testReverseTransformExpectsString() + { + $transformer = new PercentToLocalizedStringTransformer(); + + $this->setExpectedException('Symfony\Component\Form\Exception\TransformationFailedException'); + + $transformer->reverseTransform(1); + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/ValueToDuplicatesTransformerTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/ValueToDuplicatesTransformerTest.php new file mode 100644 index 00000000..2c5298da --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/ValueToDuplicatesTransformerTest.php @@ -0,0 +1,120 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; + +use Symfony\Component\Form\Extension\Core\DataTransformer\ValueToDuplicatesTransformer; + +class ValueToDuplicatesTransformerTest extends \PHPUnit_Framework_TestCase +{ + private $transformer; + + protected function setUp() + { + $this->transformer = new ValueToDuplicatesTransformer(array('a', 'b', 'c')); + } + + protected function tearDown() + { + $this->transformer = null; + } + + public function testTransform() + { + $output = array( + 'a' => 'Foo', + 'b' => 'Foo', + 'c' => 'Foo', + ); + + $this->assertSame($output, $this->transformer->transform('Foo')); + } + + public function testTransformEmpty() + { + $output = array( + 'a' => null, + 'b' => null, + 'c' => null, + ); + + $this->assertSame($output, $this->transformer->transform(null)); + } + + public function testReverseTransform() + { + $input = array( + 'a' => 'Foo', + 'b' => 'Foo', + 'c' => 'Foo', + ); + + $this->assertSame('Foo', $this->transformer->reverseTransform($input)); + } + + public function testReverseTransformCompletelyEmpty() + { + $input = array( + 'a' => '', + 'b' => '', + 'c' => '', + ); + + $this->assertNull($this->transformer->reverseTransform($input)); + } + + public function testReverseTransformCompletelyNull() + { + $input = array( + 'a' => null, + 'b' => null, + 'c' => null, + ); + + $this->assertNull($this->transformer->reverseTransform($input)); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testReverseTransformPartiallyNull() + { + $input = array( + 'a' => 'Foo', + 'b' => 'Foo', + 'c' => null, + ); + + $this->transformer->reverseTransform($input); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testReverseTransformDifferences() + { + $input = array( + 'a' => 'Foo', + 'b' => 'Bar', + 'c' => 'Foo', + ); + + $this->transformer->reverseTransform($input); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testReverseTransformRequiresArray() + { + $this->transformer->reverseTransform('12345'); + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/EventListener/FixRadioInputListenerTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/EventListener/FixRadioInputListenerTest.php new file mode 100644 index 00000000..a5d5c78a --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/EventListener/FixRadioInputListenerTest.php @@ -0,0 +1,106 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Core\EventListener; + +use Symfony\Component\Form\FormEvent; +use Symfony\Component\Form\Extension\Core\EventListener\FixRadioInputListener; +use Symfony\Component\Form\Extension\Core\ChoiceList\SimpleChoiceList; + +class FixRadioInputListenerTest extends \PHPUnit_Framework_TestCase +{ + private $choiceList; + + protected function setUp() + { + if (!class_exists('Symfony\Component\EventDispatcher\EventDispatcher')) { + $this->markTestSkipped('The "EventDispatcher" component is not available'); + } + + parent::setUp(); + + $this->choiceList = new SimpleChoiceList(array('' => 'Empty', 0 => 'A', 1 => 'B')); + } + + protected function tearDown() + { + parent::tearDown(); + + $listener = null; + } + + public function testFixRadio() + { + $data = '1'; + $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); + $event = new FormEvent($form, $data); + + $listener = new FixRadioInputListener($this->choiceList, true); + $listener->preSubmit($event); + + // Indices in SimpleChoiceList are zero-based generated integers + $this->assertEquals(array(2 => '1'), $event->getData()); + } + + public function testFixZero() + { + $data = '0'; + $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); + $event = new FormEvent($form, $data); + + $listener = new FixRadioInputListener($this->choiceList, true); + $listener->preSubmit($event); + + // Indices in SimpleChoiceList are zero-based generated integers + $this->assertEquals(array(1 => '0'), $event->getData()); + } + + public function testFixEmptyString() + { + $data = ''; + $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); + $event = new FormEvent($form, $data); + + $listener = new FixRadioInputListener($this->choiceList, true); + $listener->preSubmit($event); + + // Indices in SimpleChoiceList are zero-based generated integers + $this->assertEquals(array(0 => ''), $event->getData()); + } + + public function testConvertEmptyStringToPlaceholderIfNotFound() + { + $list = new SimpleChoiceList(array(0 => 'A', 1 => 'B')); + + $data = ''; + $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); + $event = new FormEvent($form, $data); + + $listener = new FixRadioInputListener($list, true); + $listener->preSubmit($event); + + $this->assertEquals(array('placeholder' => ''), $event->getData()); + } + + public function testDontConvertEmptyStringToPlaceholderIfNoPlaceholderUsed() + { + $list = new SimpleChoiceList(array(0 => 'A', 1 => 'B')); + + $data = ''; + $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); + $event = new FormEvent($form, $data); + + $listener = new FixRadioInputListener($list, false); + $listener->preSubmit($event); + + $this->assertEquals(array(), $event->getData()); + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/EventListener/FixUrlProtocolListenerTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/EventListener/FixUrlProtocolListenerTest.php new file mode 100644 index 00000000..2b84e4fd --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/EventListener/FixUrlProtocolListenerTest.php @@ -0,0 +1,61 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Core\EventListener; + +use Symfony\Component\Form\FormEvent; +use Symfony\Component\Form\Extension\Core\EventListener\FixUrlProtocolListener; + +class FixUrlProtocolListenerTest extends \PHPUnit_Framework_TestCase +{ + protected function setUp() + { + if (!class_exists('Symfony\Component\EventDispatcher\EventDispatcher')) { + $this->markTestSkipped('The "EventDispatcher" component is not available'); + } + } + + public function testFixHttpUrl() + { + $data = "www.symfony.com"; + $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); + $event = new FormEvent($form, $data); + + $filter = new FixUrlProtocolListener('http'); + $filter->onSubmit($event); + + $this->assertEquals('http://www.symfony.com', $event->getData()); + } + + public function testSkipKnownUrl() + { + $data = "http://www.symfony.com"; + $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); + $event = new FormEvent($form, $data); + + $filter = new FixUrlProtocolListener('http'); + $filter->onSubmit($event); + + $this->assertEquals('http://www.symfony.com', $event->getData()); + } + + public function testSkipOtherProtocol() + { + $data = "ftp://www.symfony.com"; + $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); + $event = new FormEvent($form, $data); + + $filter = new FixUrlProtocolListener('http'); + $filter->onSubmit($event); + + $this->assertEquals('ftp://www.symfony.com', $event->getData()); + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/EventListener/Fixtures/randomhash b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/EventListener/Fixtures/randomhash new file mode 100644 index 00000000..b636f4b8 Binary files /dev/null and b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/EventListener/Fixtures/randomhash differ diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/EventListener/MergeCollectionListenerArrayObjectTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/EventListener/MergeCollectionListenerArrayObjectTest.php new file mode 100644 index 00000000..6f46c9d7 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/EventListener/MergeCollectionListenerArrayObjectTest.php @@ -0,0 +1,27 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Core\EventListener; + +use Symfony\Component\Form\FormBuilder; + +class MergeCollectionListenerArrayObjectTest extends MergeCollectionListenerTest +{ + protected function getData(array $data) + { + return new \ArrayObject($data); + } + + protected function getBuilder($name = 'name') + { + return new FormBuilder($name, '\ArrayObject', $this->dispatcher, $this->factory); + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/EventListener/MergeCollectionListenerArrayTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/EventListener/MergeCollectionListenerArrayTest.php new file mode 100644 index 00000000..c0f3d597 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/EventListener/MergeCollectionListenerArrayTest.php @@ -0,0 +1,27 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Core\EventListener; + +use Symfony\Component\Form\FormBuilder; + +class MergeCollectionListenerArrayTest extends MergeCollectionListenerTest +{ + protected function getData(array $data) + { + return $data; + } + + protected function getBuilder($name = 'name') + { + return new FormBuilder($name, null, $this->dispatcher, $this->factory); + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/EventListener/MergeCollectionListenerCustomArrayObjectTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/EventListener/MergeCollectionListenerCustomArrayObjectTest.php new file mode 100644 index 00000000..5eb6c7b9 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/EventListener/MergeCollectionListenerCustomArrayObjectTest.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Core\EventListener; + +use Symfony\Component\Form\Tests\Fixtures\CustomArrayObject; +use Symfony\Component\Form\FormBuilder; + +class MergeCollectionListenerCustomArrayObjectTest extends MergeCollectionListenerTest +{ + protected function getData(array $data) + { + return new CustomArrayObject($data); + } + + protected function getBuilder($name = 'name') + { + return new FormBuilder($name, 'Symfony\Component\Form\Tests\Fixtures\CustomArrayObject', $this->dispatcher, $this->factory); + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/EventListener/MergeCollectionListenerTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/EventListener/MergeCollectionListenerTest.php new file mode 100644 index 00000000..dbd28c6b --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/EventListener/MergeCollectionListenerTest.php @@ -0,0 +1,259 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Core\EventListener; + +use Symfony\Component\Form\FormEvent; +use Symfony\Component\Form\Extension\Core\EventListener\MergeCollectionListener; + +abstract class MergeCollectionListenerTest extends \PHPUnit_Framework_TestCase +{ + protected $dispatcher; + protected $factory; + protected $form; + + protected function setUp() + { + if (!class_exists('Symfony\Component\EventDispatcher\EventDispatcher')) { + $this->markTestSkipped('The "EventDispatcher" component is not available'); + } + + $this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); + $this->factory = $this->getMock('Symfony\Component\Form\FormFactoryInterface'); + $this->form = $this->getForm('axes'); + } + + protected function tearDown() + { + $this->dispatcher = null; + $this->factory = null; + $this->form = null; + } + + abstract protected function getBuilder($name = 'name'); + + protected function getForm($name = 'name', $propertyPath = null) + { + $propertyPath = $propertyPath ?: $name; + + return $this->getBuilder($name)->setAttribute('property_path', $propertyPath)->getForm(); + } + + protected function getMockForm() + { + return $this->getMock('Symfony\Component\Form\Test\FormInterface'); + } + + public function getBooleanMatrix1() + { + return array( + array(true), + array(false), + ); + } + + public function getBooleanMatrix2() + { + return array( + array(true, true), + array(true, false), + array(false, true), + array(false, false), + ); + } + + abstract protected function getData(array $data); + + /** + * @dataProvider getBooleanMatrix1 + */ + public function testAddExtraEntriesIfAllowAdd($allowDelete) + { + $originalData = $this->getData(array(1 => 'second')); + $newData = $this->getData(array(0 => 'first', 1 => 'second', 2 => 'third')); + + $listener = new MergeCollectionListener(true, $allowDelete); + + $this->form->setData($originalData); + + $event = new FormEvent($this->form, $newData); + $listener->onSubmit($event); + + // The original object was modified + if (is_object($originalData)) { + $this->assertSame($originalData, $event->getData()); + } + + // The original object matches the new object + $this->assertEquals($newData, $event->getData()); + } + + /** + * @dataProvider getBooleanMatrix1 + */ + public function testAddExtraEntriesIfAllowAddDontOverwriteExistingIndices($allowDelete) + { + $originalData = $this->getData(array(1 => 'first')); + $newData = $this->getData(array(0 => 'first', 1 => 'second')); + + $listener = new MergeCollectionListener(true, $allowDelete); + + $this->form->setData($originalData); + + $event = new FormEvent($this->form, $newData); + $listener->onSubmit($event); + + // The original object was modified + if (is_object($originalData)) { + $this->assertSame($originalData, $event->getData()); + } + + // The original object matches the new object + $this->assertEquals($this->getData(array(1 => 'first', 2 => 'second')), $event->getData()); + } + + /** + * @dataProvider getBooleanMatrix1 + */ + public function testDoNothingIfNotAllowAdd($allowDelete) + { + $originalDataArray = array(1 => 'second'); + $originalData = $this->getData($originalDataArray); + $newData = $this->getData(array(0 => 'first', 1 => 'second', 2 => 'third')); + + $listener = new MergeCollectionListener(false, $allowDelete); + + $this->form->setData($originalData); + + $event = new FormEvent($this->form, $newData); + $listener->onSubmit($event); + + // We still have the original object + if (is_object($originalData)) { + $this->assertSame($originalData, $event->getData()); + } + + // Nothing was removed + $this->assertEquals($this->getData($originalDataArray), $event->getData()); + } + + /** + * @dataProvider getBooleanMatrix1 + */ + public function testRemoveMissingEntriesIfAllowDelete($allowAdd) + { + $originalData = $this->getData(array(0 => 'first', 1 => 'second', 2 => 'third')); + $newData = $this->getData(array(1 => 'second')); + + $listener = new MergeCollectionListener($allowAdd, true); + + $this->form->setData($originalData); + + $event = new FormEvent($this->form, $newData); + $listener->onSubmit($event); + + // The original object was modified + if (is_object($originalData)) { + $this->assertSame($originalData, $event->getData()); + } + + // The original object matches the new object + $this->assertEquals($newData, $event->getData()); + } + + /** + * @dataProvider getBooleanMatrix1 + */ + public function testDoNothingIfNotAllowDelete($allowAdd) + { + $originalDataArray = array(0 => 'first', 1 => 'second', 2 => 'third'); + $originalData = $this->getData($originalDataArray); + $newData = $this->getData(array(1 => 'second')); + + $listener = new MergeCollectionListener($allowAdd, false); + + $this->form->setData($originalData); + + $event = new FormEvent($this->form, $newData); + $listener->onSubmit($event); + + // We still have the original object + if (is_object($originalData)) { + $this->assertSame($originalData, $event->getData()); + } + + // Nothing was removed + $this->assertEquals($this->getData($originalDataArray), $event->getData()); + } + + /** + * @dataProvider getBooleanMatrix2 + * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException + */ + public function testRequireArrayOrTraversable($allowAdd, $allowDelete) + { + $newData = 'no array or traversable'; + $event = new FormEvent($this->form, $newData); + $listener = new MergeCollectionListener($allowAdd, $allowDelete); + $listener->onSubmit($event); + } + + public function testDealWithNullData() + { + $originalData = $this->getData(array(0 => 'first', 1 => 'second', 2 => 'third')); + $newData = null; + + $listener = new MergeCollectionListener(false, false); + + $this->form->setData($originalData); + + $event = new FormEvent($this->form, $newData); + $listener->onSubmit($event); + + $this->assertSame($originalData, $event->getData()); + } + + /** + * @dataProvider getBooleanMatrix1 + */ + public function testDealWithNullOriginalDataIfAllowAdd($allowDelete) + { + $originalData = null; + $newData = $this->getData(array(0 => 'first', 1 => 'second', 2 => 'third')); + + $listener = new MergeCollectionListener(true, $allowDelete); + + $this->form->setData($originalData); + + $event = new FormEvent($this->form, $newData); + $listener->onSubmit($event); + + $this->assertSame($newData, $event->getData()); + } + + /** + * @dataProvider getBooleanMatrix1 + */ + public function testDontDealWithNullOriginalDataIfNotAllowAdd($allowDelete) + { + $originalData = null; + $newData = $this->getData(array(0 => 'first', 1 => 'second', 2 => 'third')); + + $listener = new MergeCollectionListener(false, $allowDelete); + + $this->form->setData($originalData); + + $event = new FormEvent($this->form, $newData); + $listener->onSubmit($event); + + $this->assertNull($event->getData()); + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php new file mode 100644 index 00000000..1367b3ef --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php @@ -0,0 +1,255 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Core\EventListener; + +use Symfony\Component\Form\Extension\Core\EventListener\ResizeFormListener; +use Symfony\Component\Form\FormBuilder; +use Symfony\Component\Form\FormEvent; + +class ResizeFormListenerTest extends \PHPUnit_Framework_TestCase +{ + private $dispatcher; + private $factory; + private $form; + + protected function setUp() + { + if (!class_exists('Symfony\Component\EventDispatcher\EventDispatcher')) { + $this->markTestSkipped('The "EventDispatcher" component is not available'); + } + + $this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); + $this->factory = $this->getMock('Symfony\Component\Form\FormFactoryInterface'); + $this->form = $this->getBuilder() + ->setCompound(true) + ->setDataMapper($this->getDataMapper()) + ->getForm(); + } + + protected function tearDown() + { + $this->dispatcher = null; + $this->factory = null; + $this->form = null; + } + + protected function getBuilder($name = 'name') + { + return new FormBuilder($name, null, $this->dispatcher, $this->factory); + } + + protected function getForm($name = 'name') + { + return $this->getBuilder($name)->getForm(); + } + + /** + * @return \PHPUnit_Framework_MockObject_MockObject + */ + private function getDataMapper() + { + return $this->getMock('Symfony\Component\Form\DataMapperInterface'); + } + + protected function getMockForm() + { + return $this->getMock('Symfony\Component\Form\Test\FormInterface'); + } + + public function testPreSetDataResizesForm() + { + $this->form->add($this->getForm('0')); + $this->form->add($this->getForm('1')); + + $this->factory->expects($this->at(0)) + ->method('createNamed') + ->with(1, 'text', null, array('property_path' => '[1]', 'max_length' => 10, 'auto_initialize' => false)) + ->will($this->returnValue($this->getForm('1'))); + $this->factory->expects($this->at(1)) + ->method('createNamed') + ->with(2, 'text', null, array('property_path' => '[2]', 'max_length' => 10, 'auto_initialize' => false)) + ->will($this->returnValue($this->getForm('2'))); + + $data = array(1 => 'string', 2 => 'string'); + $event = new FormEvent($this->form, $data); + $listener = new ResizeFormListener('text', array('max_length' => '10'), false, false); + $listener->preSetData($event); + + $this->assertFalse($this->form->has('0')); + $this->assertTrue($this->form->has('1')); + $this->assertTrue($this->form->has('2')); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException + */ + public function testPreSetDataRequiresArrayOrTraversable() + { + $data = 'no array or traversable'; + $event = new FormEvent($this->form, $data); + $listener = new ResizeFormListener('text', array(), false, false); + $listener->preSetData($event); + } + + public function testPreSetDataDealsWithNullData() + { + $this->factory->expects($this->never())->method('createNamed'); + + $data = null; + $event = new FormEvent($this->form, $data); + $listener = new ResizeFormListener('text', array(), false, false); + $listener->preSetData($event); + } + + public function testPreSubmitResizesUpIfAllowAdd() + { + $this->form->add($this->getForm('0')); + + $this->factory->expects($this->once()) + ->method('createNamed') + ->with(1, 'text', null, array('property_path' => '[1]', 'max_length' => 10, 'auto_initialize' => false)) + ->will($this->returnValue($this->getForm('1'))); + + $data = array(0 => 'string', 1 => 'string'); + $event = new FormEvent($this->form, $data); + $listener = new ResizeFormListener('text', array('max_length' => 10), true, false); + $listener->preSubmit($event); + + $this->assertTrue($this->form->has('0')); + $this->assertTrue($this->form->has('1')); + } + + public function testPreSubmitResizesDownIfAllowDelete() + { + $this->form->add($this->getForm('0')); + $this->form->add($this->getForm('1')); + + $data = array(0 => 'string'); + $event = new FormEvent($this->form, $data); + $listener = new ResizeFormListener('text', array(), false, true); + $listener->preSubmit($event); + + $this->assertTrue($this->form->has('0')); + $this->assertFalse($this->form->has('1')); + } + + // fix for https://github.com/symfony/symfony/pull/493 + public function testPreSubmitRemovesZeroKeys() + { + $this->form->add($this->getForm('0')); + + $data = array(); + $event = new FormEvent($this->form, $data); + $listener = new ResizeFormListener('text', array(), false, true); + $listener->preSubmit($event); + + $this->assertFalse($this->form->has('0')); + } + + public function testPreSubmitDoesNothingIfNotAllowAddNorAllowDelete() + { + $this->form->add($this->getForm('0')); + $this->form->add($this->getForm('1')); + + $data = array(0 => 'string', 2 => 'string'); + $event = new FormEvent($this->form, $data); + $listener = new ResizeFormListener('text', array(), false, false); + $listener->preSubmit($event); + + $this->assertTrue($this->form->has('0')); + $this->assertTrue($this->form->has('1')); + $this->assertFalse($this->form->has('2')); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException + */ + public function testPreSubmitRequiresArrayOrTraversable() + { + $data = 'no array or traversable'; + $event = new FormEvent($this->form, $data); + $listener = new ResizeFormListener('text', array(), false, false); + $listener->preSubmit($event); + } + + public function testPreSubmitDealsWithNullData() + { + $this->form->add($this->getForm('1')); + + $data = null; + $event = new FormEvent($this->form, $data); + $listener = new ResizeFormListener('text', array(), false, true); + $listener->preSubmit($event); + + $this->assertFalse($this->form->has('1')); + } + + // fixes https://github.com/symfony/symfony/pull/40 + public function testPreSubmitDealsWithEmptyData() + { + $this->form->add($this->getForm('1')); + + $data = ''; + $event = new FormEvent($this->form, $data); + $listener = new ResizeFormListener('text', array(), false, true); + $listener->preSubmit($event); + + $this->assertFalse($this->form->has('1')); + } + + public function testOnSubmitNormDataRemovesEntriesMissingInTheFormIfAllowDelete() + { + $this->form->add($this->getForm('1')); + + $data = array(0 => 'first', 1 => 'second', 2 => 'third'); + $event = new FormEvent($this->form, $data); + $listener = new ResizeFormListener('text', array(), false, true); + $listener->onSubmit($event); + + $this->assertEquals(array(1 => 'second'), $event->getData()); + } + + public function testOnSubmitNormDataDoesNothingIfNotAllowDelete() + { + $this->form->add($this->getForm('1')); + + $data = array(0 => 'first', 1 => 'second', 2 => 'third'); + $event = new FormEvent($this->form, $data); + $listener = new ResizeFormListener('text', array(), false, false); + $listener->onSubmit($event); + + $this->assertEquals($data, $event->getData()); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException + */ + public function testOnSubmitNormDataRequiresArrayOrTraversable() + { + $data = 'no array or traversable'; + $event = new FormEvent($this->form, $data); + $listener = new ResizeFormListener('text', array(), false, false); + $listener->onSubmit($event); + } + + public function testOnSubmitNormDataDealsWithNullData() + { + $this->form->add($this->getForm('1')); + + $data = null; + $event = new FormEvent($this->form, $data); + $listener = new ResizeFormListener('text', array(), false, true); + $listener->onSubmit($event); + + $this->assertEquals(array(), $event->getData()); + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/EventListener/TrimListenerTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/EventListener/TrimListenerTest.php new file mode 100644 index 00000000..4e368933 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/EventListener/TrimListenerTest.php @@ -0,0 +1,79 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Core\EventListener; + +use Symfony\Component\Form\FormEvent; +use Symfony\Component\Form\Extension\Core\EventListener\TrimListener; + +class TrimListenerTest extends \PHPUnit_Framework_TestCase +{ + protected function setUp() + { + if (!class_exists('Symfony\Component\EventDispatcher\EventDispatcher')) { + $this->markTestSkipped('The "EventDispatcher" component is not available'); + } + } + + public function testTrim() + { + $data = " Foo! "; + $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); + $event = new FormEvent($form, $data); + + $filter = new TrimListener(); + $filter->preSubmit($event); + + $this->assertEquals('Foo!', $event->getData()); + } + + public function testTrimSkipNonStrings() + { + $data = 1234; + $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); + $event = new FormEvent($form, $data); + + $filter = new TrimListener(); + $filter->preSubmit($event); + + $this->assertSame(1234, $event->getData()); + } + + /** + * @dataProvider codePointProvider + */ + public function testTrimUtf8($chars) + { + if (!function_exists('mb_check_encoding')) { + $this->markTestSkipped('The "mb_check_encoding" function is not available'); + } + + $data = mb_convert_encoding(pack('H*', implode('', $chars)), 'UTF-8', 'UCS-2BE'); + $data = $data."ab\ncd".$data; + + $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); + $event = new FormEvent($form, $data); + + $filter = new TrimListener(); + $filter->preSubmit($event); + + $this->assertSame("ab\ncd", $event->getData(), 'TrimListener should trim character(s): '.implode(', ', $chars)); + } + + public function codePointProvider() + { + return array( + 'General category: Separator' => array(array('0020', '00A0', '1680', '180E', '2000', '2001', '2002', '2003', '2004', '2005', '2006', '2007', '2008', '2009', '200A', '2028', '2029', '202F', '205F', '3000')), + 'General category: Other, control' => array(array('0009', '000A', '000B', '000C', '000D', '0085')), + //'General category: Other, format. ZERO WIDTH SPACE' => array(array('200B')), + ); + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/BaseTypeTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/BaseTypeTest.php new file mode 100644 index 00000000..bfa1e218 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/BaseTypeTest.php @@ -0,0 +1,135 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Core\Type; + +/** + * @author Bernhard Schussek + */ +abstract class BaseTypeTest extends \Symfony\Component\Form\Test\TypeTestCase +{ + public function testPassDisabledAsOption() + { + $form = $this->factory->create($this->getTestedType(), null, array('disabled' => true)); + + $this->assertTrue($form->isDisabled()); + } + + public function testPassIdAndNameToView() + { + $view = $this->factory->createNamed('name', $this->getTestedType()) + ->createView(); + + $this->assertEquals('name', $view->vars['id']); + $this->assertEquals('name', $view->vars['name']); + $this->assertEquals('name', $view->vars['full_name']); + } + + public function testStripLeadingUnderscoresAndDigitsFromId() + { + $view = $this->factory->createNamed('_09name', $this->getTestedType()) + ->createView(); + + $this->assertEquals('name', $view->vars['id']); + $this->assertEquals('_09name', $view->vars['name']); + $this->assertEquals('_09name', $view->vars['full_name']); + } + + public function testPassIdAndNameToViewWithParent() + { + $view = $this->factory->createNamedBuilder('parent', 'form') + ->add('child', $this->getTestedType()) + ->getForm() + ->createView(); + + $this->assertEquals('parent_child', $view['child']->vars['id']); + $this->assertEquals('child', $view['child']->vars['name']); + $this->assertEquals('parent[child]', $view['child']->vars['full_name']); + } + + public function testPassIdAndNameToViewWithGrandParent() + { + $builder = $this->factory->createNamedBuilder('parent', 'form') + ->add('child', 'form'); + $builder->get('child')->add('grand_child', $this->getTestedType()); + $view = $builder->getForm()->createView(); + + $this->assertEquals('parent_child_grand_child', $view['child']['grand_child']->vars['id']); + $this->assertEquals('grand_child', $view['child']['grand_child']->vars['name']); + $this->assertEquals('parent[child][grand_child]', $view['child']['grand_child']->vars['full_name']); + } + + public function testPassTranslationDomainToView() + { + $form = $this->factory->create($this->getTestedType(), null, array( + 'translation_domain' => 'domain', + )); + $view = $form->createView(); + + $this->assertSame('domain', $view->vars['translation_domain']); + } + + public function testInheritTranslationDomainFromParent() + { + $view = $this->factory + ->createNamedBuilder('parent', 'form', null, array( + 'translation_domain' => 'domain', + )) + ->add('child', $this->getTestedType()) + ->getForm() + ->createView(); + + $this->assertEquals('domain', $view['child']->vars['translation_domain']); + } + + public function testPreferOwnTranslationDomain() + { + $view = $this->factory + ->createNamedBuilder('parent', 'form', null, array( + 'translation_domain' => 'parent_domain', + )) + ->add('child', $this->getTestedType(), array( + 'translation_domain' => 'domain', + )) + ->getForm() + ->createView(); + + $this->assertEquals('domain', $view['child']->vars['translation_domain']); + } + + public function testDefaultTranslationDomain() + { + $view = $this->factory->createNamedBuilder('parent', 'form') + ->add('child', $this->getTestedType()) + ->getForm() + ->createView(); + + $this->assertEquals('messages', $view['child']->vars['translation_domain']); + } + + public function testPassLabelToView() + { + $form = $this->factory->createNamed('__test___field', $this->getTestedType(), null, array('label' => 'My label')); + $view = $form->createView(); + + $this->assertSame('My label', $view->vars['label']); + } + + public function testPassMultipartFalseToView() + { + $form = $this->factory->create($this->getTestedType()); + $view = $form->createView(); + + $this->assertFalse($view->vars['multipart']); + } + + abstract protected function getTestedType(); +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/ButtonTypeTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/ButtonTypeTest.php new file mode 100644 index 00000000..55835e77 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/ButtonTypeTest.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Core\Type; + +/** + * @author Bernhard Schussek + */ +class ButtonTypeTest extends BaseTypeTest +{ + public function testCreateButtonInstances() + { + $this->assertInstanceOf('Symfony\Component\Form\Button', $this->factory->create('button')); + } + + protected function getTestedType() + { + return 'button'; + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/CheckboxTypeTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/CheckboxTypeTest.php new file mode 100644 index 00000000..c782adab --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/CheckboxTypeTest.php @@ -0,0 +1,162 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Core\Type; + +use Symfony\Component\Form\CallbackTransformer; + +class CheckboxTypeTest extends \Symfony\Component\Form\Test\TypeTestCase +{ + public function testPassValueToView() + { + $form = $this->factory->create('checkbox', null, array('value' => 'foobar')); + $view = $form->createView(); + + $this->assertEquals('foobar', $view->vars['value']); + } + + public function testCheckedIfDataTrue() + { + $form = $this->factory->create('checkbox'); + $form->setData(true); + $view = $form->createView(); + + $this->assertTrue($view->vars['checked']); + } + + public function testCheckedIfDataTrueWithEmptyValue() + { + $form = $this->factory->create('checkbox', null, array('value' => '')); + $form->setData(true); + $view = $form->createView(); + + $this->assertTrue($view->vars['checked']); + } + + public function testNotCheckedIfDataFalse() + { + $form = $this->factory->create('checkbox'); + $form->setData(false); + $view = $form->createView(); + + $this->assertFalse($view->vars['checked']); + } + + public function testSubmitWithValueChecked() + { + $form = $this->factory->create('checkbox', null, array( + 'value' => 'foobar', + )); + $form->submit('foobar'); + + $this->assertTrue($form->getData()); + $this->assertEquals('foobar', $form->getViewData()); + } + + public function testSubmitWithRandomValueChecked() + { + $form = $this->factory->create('checkbox', null, array( + 'value' => 'foobar', + )); + $form->submit('krixikraxi'); + + $this->assertTrue($form->getData()); + $this->assertEquals('foobar', $form->getViewData()); + } + + public function testSubmitWithValueUnchecked() + { + $form = $this->factory->create('checkbox', null, array( + 'value' => 'foobar', + )); + $form->submit(null); + + $this->assertFalse($form->getData()); + $this->assertNull($form->getViewData()); + } + + public function testSubmitWithEmptyValueChecked() + { + $form = $this->factory->create('checkbox', null, array( + 'value' => '', + )); + $form->submit(''); + + $this->assertTrue($form->getData()); + $this->assertSame('', $form->getViewData()); + } + + public function testSubmitWithEmptyValueUnchecked() + { + $form = $this->factory->create('checkbox', null, array( + 'value' => '', + )); + $form->submit(null); + + $this->assertFalse($form->getData()); + $this->assertNull($form->getViewData()); + } + + public function testBindWithEmptyValueAndFalseUnchecked() + { + $form = $this->factory->create('checkbox', null, array( + 'value' => '', + )); + $form->bind(false); + + $this->assertFalse($form->getData()); + $this->assertNull($form->getViewData()); + } + + public function testBindWithEmptyValueAndTrueChecked() + { + $form = $this->factory->create('checkbox', null, array( + 'value' => '', + )); + $form->bind(true); + + $this->assertTrue($form->getData()); + $this->assertSame('', $form->getViewData()); + } + + /** + * @dataProvider provideTransformedData + */ + public function testTransformedData($data, $expected) + { + // present a binary status field as a checkbox + $transformer = new CallbackTransformer( + function ($value) { + return 'expedited' == $value; + }, + function ($value) { + return $value ? 'expedited' : 'standard'; + } + ); + + $form = $this->builder + ->create('expedited_shipping', 'checkbox') + ->addModelTransformer($transformer) + ->getForm(); + $form->setData($data); + $view = $form->createView(); + + $this->assertEquals($expected, $view->vars['checked']); + } + + public function provideTransformedData() + { + return array( + array('expedited', true), + array('standard', false), + ); + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypePerformanceTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypePerformanceTest.php new file mode 100644 index 00000000..0685946f --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypePerformanceTest.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Core\Type; + +use Symfony\Component\Form\Test\FormPerformanceTestCase; + +/** + * @author Bernhard Schussek + */ +class ChoiceTypePerformanceTest extends FormPerformanceTestCase +{ + /** + * This test case is realistic in collection forms where each + * row contains the same choice field. + * + * @group benchmark + */ + public function testSameChoiceFieldCreatedMultipleTimes() + { + $this->setMaxRunningTime(1); + $choices = range(1, 300); + + for ($i = 0; $i < 100; ++$i) { + $this->factory->create('choice', rand(1, 400), array( + 'choices' => $choices, + )); + } + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypeTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypeTest.php new file mode 100644 index 00000000..219e8181 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypeTest.php @@ -0,0 +1,949 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Core\Type; + +use Symfony\Component\Form\Extension\Core\ChoiceList\ObjectChoiceList; +use Symfony\Component\Form\Extension\Core\View\ChoiceView; + +class ChoiceTypeTest extends \Symfony\Component\Form\Test\TypeTestCase +{ + private $choices = array( + 'a' => 'Bernhard', + 'b' => 'Fabien', + 'c' => 'Kris', + 'd' => 'Jon', + 'e' => 'Roman', + ); + + private $numericChoices = array( + 0 => 'Bernhard', + 1 => 'Fabien', + 2 => 'Kris', + 3 => 'Jon', + 4 => 'Roman', + ); + + private $objectChoices; + + protected $groupedChoices = array( + 'Symfony' => array( + 'a' => 'Bernhard', + 'b' => 'Fabien', + 'c' => 'Kris', + ), + 'Doctrine' => array( + 'd' => 'Jon', + 'e' => 'Roman', + ) + ); + + protected function setUp() + { + parent::setUp(); + + $this->objectChoices = array( + (object) array('id' => 1, 'name' => 'Bernhard'), + (object) array('id' => 2, 'name' => 'Fabien'), + (object) array('id' => 3, 'name' => 'Kris'), + (object) array('id' => 4, 'name' => 'Jon'), + (object) array('id' => 5, 'name' => 'Roman'), + ); + } + + protected function tearDown() + { + parent::tearDown(); + + $this->objectChoices = null; + } + + /** + * @expectedException \PHPUnit_Framework_Error + */ + public function testChoicesOptionExpectsArray() + { + $this->factory->create('choice', null, array( + 'choices' => new \ArrayObject(), + )); + } + + /** + * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException + */ + public function testChoiceListOptionExpectsChoiceListInterface() + { + $this->factory->create('choice', null, array( + 'choice_list' => array('foo' => 'foo'), + )); + } + + public function testChoiceListAndChoicesCanBeEmpty() + { + $this->factory->create('choice'); + } + + public function testExpandedChoicesOptionsTurnIntoChildren() + { + $form = $this->factory->create('choice', null, array( + 'expanded' => true, + 'choices' => $this->choices, + )); + + $this->assertCount(count($this->choices), $form, 'Each choice should become a new field'); + } + + public function testPlaceholderPresentOnNonRequiredExpandedSingleChoice() + { + $form = $this->factory->create('choice', null, array( + 'multiple' => false, + 'expanded' => true, + 'required' => false, + 'choices' => $this->choices, + )); + + $this->assertTrue(isset($form['placeholder'])); + $this->assertCount(count($this->choices) + 1, $form, 'Each choice should become a new field'); + } + + public function testPlaceholderNotPresentIfRequired() + { + $form = $this->factory->create('choice', null, array( + 'multiple' => false, + 'expanded' => true, + 'required' => true, + 'choices' => $this->choices, + )); + + $this->assertFalse(isset($form['placeholder'])); + $this->assertCount(count($this->choices), $form, 'Each choice should become a new field'); + } + + public function testPlaceholderNotPresentIfMultiple() + { + $form = $this->factory->create('choice', null, array( + 'multiple' => true, + 'expanded' => true, + 'required' => false, + 'choices' => $this->choices, + )); + + $this->assertFalse(isset($form['placeholder'])); + $this->assertCount(count($this->choices), $form, 'Each choice should become a new field'); + } + + public function testPlaceholderNotPresentIfEmptyChoice() + { + $form = $this->factory->create('choice', null, array( + 'multiple' => false, + 'expanded' => true, + 'required' => false, + 'choices' => array( + '' => 'Empty', + 1 => 'Not empty', + ), + )); + + $this->assertFalse(isset($form['placeholder'])); + $this->assertCount(2, $form, 'Each choice should become a new field'); + } + + public function testExpandedChoicesOptionsAreFlattened() + { + $form = $this->factory->create('choice', null, array( + 'expanded' => true, + 'choices' => $this->groupedChoices, + )); + + $flattened = array(); + foreach ($this->groupedChoices as $choices) { + $flattened = array_merge($flattened, array_keys($choices)); + } + + $this->assertCount($form->count(), $flattened, 'Each nested choice should become a new field, not the groups'); + + foreach ($flattened as $value => $choice) { + $this->assertTrue($form->has($value), 'Flattened choice is named after it\'s value'); + } + } + + public function testExpandedCheckboxesAreNeverRequired() + { + $form = $this->factory->create('choice', null, array( + 'multiple' => true, + 'expanded' => true, + 'required' => true, + 'choices' => $this->choices, + )); + + foreach ($form as $child) { + $this->assertFalse($child->isRequired()); + } + } + + public function testExpandedRadiosAreRequiredIfChoiceChildIsRequired() + { + $form = $this->factory->create('choice', null, array( + 'multiple' => false, + 'expanded' => true, + 'required' => true, + 'choices' => $this->choices, + )); + + foreach ($form as $child) { + $this->assertTrue($child->isRequired()); + } + } + + public function testExpandedRadiosAreNotRequiredIfChoiceChildIsNotRequired() + { + $form = $this->factory->create('choice', null, array( + 'multiple' => false, + 'expanded' => true, + 'required' => false, + 'choices' => $this->choices, + )); + + foreach ($form as $child) { + $this->assertFalse($child->isRequired()); + } + } + + public function testSubmitSingleNonExpanded() + { + $form = $this->factory->create('choice', null, array( + 'multiple' => false, + 'expanded' => false, + 'choices' => $this->choices, + )); + + $form->submit('b'); + + $this->assertEquals('b', $form->getData()); + $this->assertEquals('b', $form->getViewData()); + } + + public function testSubmitSingleNonExpandedObjectChoices() + { + $form = $this->factory->create('choice', null, array( + 'multiple' => false, + 'expanded' => false, + 'choice_list' => new ObjectChoiceList( + $this->objectChoices, + // label path + 'name', + array(), + null, + // value path + 'id' + ), + )); + + // "id" value of the second entry + $form->submit('2'); + + $this->assertEquals($this->objectChoices[1], $form->getData()); + $this->assertEquals('2', $form->getViewData()); + } + + public function testSubmitMultipleNonExpanded() + { + $form = $this->factory->create('choice', null, array( + 'multiple' => true, + 'expanded' => false, + 'choices' => $this->choices, + )); + + $form->submit(array('a', 'b')); + + $this->assertEquals(array('a', 'b'), $form->getData()); + $this->assertEquals(array('a', 'b'), $form->getViewData()); + } + + public function testSubmitMultipleNonExpandedObjectChoices() + { + $form = $this->factory->create('choice', null, array( + 'multiple' => true, + 'expanded' => false, + 'choice_list' => new ObjectChoiceList( + $this->objectChoices, + // label path + 'name', + array(), + null, + // value path + 'id' + ), + )); + + $form->submit(array('2', '3')); + + $this->assertEquals(array($this->objectChoices[1], $this->objectChoices[2]), $form->getData()); + $this->assertEquals(array('2', '3'), $form->getViewData()); + } + + public function testSubmitSingleExpandedRequired() + { + $form = $this->factory->create('choice', null, array( + 'multiple' => false, + 'expanded' => true, + 'required' => true, + 'choices' => $this->choices, + )); + + $form->submit('b'); + + $this->assertSame('b', $form->getData()); + $this->assertSame(array( + 0 => false, + 1 => true, + 2 => false, + 3 => false, + 4 => false, + ), $form->getViewData()); + + $this->assertFalse($form[0]->getData()); + $this->assertTrue($form[1]->getData()); + $this->assertFalse($form[2]->getData()); + $this->assertFalse($form[3]->getData()); + $this->assertFalse($form[4]->getData()); + $this->assertNull($form[0]->getViewData()); + $this->assertSame('b', $form[1]->getViewData()); + $this->assertNull($form[2]->getViewData()); + $this->assertNull($form[3]->getViewData()); + $this->assertNull($form[4]->getViewData()); + } + + public function testSubmitSingleExpandedNonRequired() + { + $form = $this->factory->create('choice', null, array( + 'multiple' => false, + 'expanded' => true, + 'required' => false, + 'choices' => $this->choices, + )); + + $form->submit('b'); + + $this->assertSame('b', $form->getData()); + $this->assertSame(array( + 0 => false, + 1 => true, + 2 => false, + 3 => false, + 4 => false, + 'placeholder' => false, + ), $form->getViewData()); + + $this->assertFalse($form['placeholder']->getData()); + $this->assertFalse($form[0]->getData()); + $this->assertTrue($form[1]->getData()); + $this->assertFalse($form[2]->getData()); + $this->assertFalse($form[3]->getData()); + $this->assertFalse($form[4]->getData()); + $this->assertNull($form['placeholder']->getViewData()); + $this->assertNull($form[0]->getViewData()); + $this->assertSame('b', $form[1]->getViewData()); + $this->assertNull($form[2]->getViewData()); + $this->assertNull($form[3]->getViewData()); + $this->assertNull($form[4]->getViewData()); + } + + public function testSubmitSingleExpandedRequiredNothingChecked() + { + $form = $this->factory->create('choice', null, array( + 'multiple' => false, + 'expanded' => true, + 'required' => true, + 'choices' => $this->choices, + )); + + $form->submit(null); + + $this->assertNull($form->getData()); + $this->assertSame(array( + 0 => false, + 1 => false, + 2 => false, + 3 => false, + 4 => false, + ), $form->getViewData()); + + $this->assertFalse($form[0]->getData()); + $this->assertFalse($form[1]->getData()); + $this->assertFalse($form[2]->getData()); + $this->assertFalse($form[3]->getData()); + $this->assertFalse($form[4]->getData()); + $this->assertNull($form[0]->getViewData()); + $this->assertNull($form[1]->getViewData()); + $this->assertNull($form[2]->getViewData()); + $this->assertNull($form[3]->getViewData()); + $this->assertNull($form[4]->getViewData()); + } + + public function testSubmitSingleExpandedNonRequiredNothingChecked() + { + $form = $this->factory->create('choice', null, array( + 'multiple' => false, + 'expanded' => true, + 'required' => false, + 'choices' => $this->choices, + )); + + $form->submit(null); + + $this->assertNull($form->getData()); + $this->assertSame(array( + 0 => false, + 1 => false, + 2 => false, + 3 => false, + 4 => false, + 'placeholder' => true, + ), $form->getViewData()); + + $this->assertTrue($form['placeholder']->getData()); + $this->assertFalse($form[0]->getData()); + $this->assertFalse($form[1]->getData()); + $this->assertFalse($form[2]->getData()); + $this->assertFalse($form[3]->getData()); + $this->assertFalse($form[4]->getData()); + $this->assertSame('', $form['placeholder']->getViewData()); + $this->assertNull($form[0]->getViewData()); + $this->assertNull($form[1]->getViewData()); + $this->assertNull($form[2]->getViewData()); + $this->assertNull($form[3]->getViewData()); + $this->assertNull($form[4]->getViewData()); + } + + public function testSubmitFalseToSingleExpandedRequiredDoesNotProduceExtraChildrenError() + { + $form = $this->factory->create('choice', null, array( + 'multiple' => false, + 'expanded' => true, + 'required' => true, + 'choices' => $this->choices, + )); + + $form->submit(false); + + $this->assertEmpty($form->getExtraData()); + $this->assertNull($form->getData()); + } + + public function testSubmitFalseToSingleExpandedNonRequiredDoesNotProduceExtraChildrenError() + { + $form = $this->factory->create('choice', null, array( + 'multiple' => false, + 'expanded' => true, + 'required' => false, + 'choices' => $this->choices, + )); + + $form->submit(false); + + $this->assertEmpty($form->getExtraData()); + $this->assertNull($form->getData()); + } + + public function testSubmitSingleExpandedWithEmptyChild() + { + $form = $this->factory->create('choice', null, array( + 'multiple' => false, + 'expanded' => true, + 'choices' => array( + '' => 'Empty', + 1 => 'Not empty', + ), + )); + + $form->submit(''); + + $this->assertNull($form->getData()); + $this->assertTrue($form[0]->getData()); + $this->assertFalse($form[1]->getData()); + $this->assertSame('', $form[0]->getViewData()); + $this->assertNull($form[1]->getViewData()); + } + + public function testSubmitSingleExpandedObjectChoices() + { + $form = $this->factory->create('choice', null, array( + 'multiple' => false, + 'expanded' => true, + 'choice_list' => new ObjectChoiceList( + $this->objectChoices, + // label path + 'name', + array(), + null, + // value path + 'id' + ), + )); + + $form->submit('2'); + + $this->assertSame($this->objectChoices[1], $form->getData()); + $this->assertFalse($form[0]->getData()); + $this->assertTrue($form[1]->getData()); + $this->assertFalse($form[2]->getData()); + $this->assertFalse($form[3]->getData()); + $this->assertFalse($form[4]->getData()); + $this->assertNull($form[0]->getViewData()); + $this->assertSame('2', $form[1]->getViewData()); + $this->assertNull($form[2]->getViewData()); + $this->assertNull($form[3]->getViewData()); + $this->assertNull($form[4]->getViewData()); + } + + public function testSubmitSingleExpandedNumericChoices() + { + $form = $this->factory->create('choice', null, array( + 'multiple' => false, + 'expanded' => true, + 'choices' => $this->numericChoices, + )); + + $form->submit('1'); + + $this->assertSame(1, $form->getData()); + $this->assertFalse($form[0]->getData()); + $this->assertTrue($form[1]->getData()); + $this->assertFalse($form[2]->getData()); + $this->assertFalse($form[3]->getData()); + $this->assertFalse($form[4]->getData()); + $this->assertNull($form[0]->getViewData()); + $this->assertSame('1', $form[1]->getViewData()); + $this->assertNull($form[2]->getViewData()); + $this->assertNull($form[3]->getViewData()); + $this->assertNull($form[4]->getViewData()); + } + + public function testSubmitMultipleExpanded() + { + $form = $this->factory->create('choice', null, array( + 'multiple' => true, + 'expanded' => true, + 'choices' => $this->choices, + )); + + $form->submit(array('a', 'c')); + + $this->assertSame(array('a', 'c'), $form->getData()); + $this->assertTrue($form[0]->getData()); + $this->assertFalse($form[1]->getData()); + $this->assertTrue($form[2]->getData()); + $this->assertFalse($form[3]->getData()); + $this->assertFalse($form[4]->getData()); + $this->assertSame('a', $form[0]->getViewData()); + $this->assertNull($form[1]->getViewData()); + $this->assertSame('c', $form[2]->getViewData()); + $this->assertNull($form[3]->getViewData()); + $this->assertNull($form[4]->getViewData()); + } + + public function testSubmitMultipleExpandedEmpty() + { + $form = $this->factory->create('choice', null, array( + 'multiple' => true, + 'expanded' => true, + 'choices' => $this->choices, + )); + + $form->submit(array()); + + $this->assertSame(array(), $form->getData()); + $this->assertFalse($form[0]->getData()); + $this->assertFalse($form[1]->getData()); + $this->assertFalse($form[2]->getData()); + $this->assertFalse($form[3]->getData()); + $this->assertFalse($form[4]->getData()); + $this->assertNull($form[0]->getViewData()); + $this->assertNull($form[1]->getViewData()); + $this->assertNull($form[2]->getViewData()); + $this->assertNull($form[3]->getViewData()); + $this->assertNull($form[4]->getViewData()); + } + + public function testSubmitMultipleExpandedWithEmptyChild() + { + $form = $this->factory->create('choice', null, array( + 'multiple' => true, + 'expanded' => true, + 'choices' => array( + '' => 'Empty', + 1 => 'Not Empty', + 2 => 'Not Empty 2', + ) + )); + + $form->submit(array('', '2')); + + $this->assertSame(array('', 2), $form->getData()); + $this->assertTrue($form[0]->getData()); + $this->assertFalse($form[1]->getData()); + $this->assertTrue($form[2]->getData()); + $this->assertSame('', $form[0]->getViewData()); + $this->assertNull($form[1]->getViewData()); + $this->assertSame('2', $form[2]->getViewData()); + } + + public function testSubmitMultipleExpandedObjectChoices() + { + $form = $this->factory->create('choice', null, array( + 'multiple' => true, + 'expanded' => true, + 'choice_list' => new ObjectChoiceList( + $this->objectChoices, + // label path + 'name', + array(), + null, + // value path + 'id' + ), + )); + + $form->submit(array('1', '2')); + + $this->assertSame(array($this->objectChoices[0], $this->objectChoices[1]), $form->getData()); + $this->assertTrue($form[0]->getData()); + $this->assertTrue($form[1]->getData()); + $this->assertFalse($form[2]->getData()); + $this->assertFalse($form[3]->getData()); + $this->assertFalse($form[4]->getData()); + $this->assertSame('1', $form[0]->getViewData()); + $this->assertSame('2', $form[1]->getViewData()); + $this->assertNull($form[2]->getViewData()); + $this->assertNull($form[3]->getViewData()); + $this->assertNull($form[4]->getViewData()); + } + + public function testSubmitMultipleExpandedNumericChoices() + { + $form = $this->factory->create('choice', null, array( + 'multiple' => true, + 'expanded' => true, + 'choices' => $this->numericChoices, + )); + + $form->submit(array('1', '2')); + + $this->assertSame(array(1, 2), $form->getData()); + $this->assertFalse($form[0]->getData()); + $this->assertTrue($form[1]->getData()); + $this->assertTrue($form[2]->getData()); + $this->assertFalse($form[3]->getData()); + $this->assertFalse($form[4]->getData()); + $this->assertNull($form[0]->getViewData()); + $this->assertSame('1', $form[1]->getViewData()); + $this->assertSame('2', $form[2]->getViewData()); + $this->assertNull($form[3]->getViewData()); + $this->assertNull($form[4]->getViewData()); + } + + /* + * We need this functionality to create choice fields for Boolean types, + * e.g. false => 'No', true => 'Yes' + */ + public function testSetDataSingleNonExpandedAcceptsBoolean() + { + $form = $this->factory->create('choice', null, array( + 'multiple' => false, + 'expanded' => false, + 'choices' => $this->numericChoices, + )); + + $form->setData(false); + + $this->assertFalse($form->getData()); + $this->assertEquals('0', $form->getViewData()); + } + + public function testSetDataMultipleNonExpandedAcceptsBoolean() + { + $form = $this->factory->create('choice', null, array( + 'multiple' => true, + 'expanded' => false, + 'choices' => $this->numericChoices, + )); + + $form->setData(array(false, true)); + + $this->assertEquals(array(false, true), $form->getData()); + $this->assertEquals(array('0', '1'), $form->getViewData()); + } + + public function testPassRequiredToView() + { + $form = $this->factory->create('choice', null, array( + 'choices' => $this->choices, + )); + $view = $form->createView(); + + $this->assertTrue($view->vars['required']); + } + + public function testPassNonRequiredToView() + { + $form = $this->factory->create('choice', null, array( + 'required' => false, + 'choices' => $this->choices, + )); + $view = $form->createView(); + + $this->assertFalse($view->vars['required']); + } + + public function testPassMultipleToView() + { + $form = $this->factory->create('choice', null, array( + 'multiple' => true, + 'choices' => $this->choices, + )); + $view = $form->createView(); + + $this->assertTrue($view->vars['multiple']); + } + + public function testPassExpandedToView() + { + $form = $this->factory->create('choice', null, array( + 'expanded' => true, + 'choices' => $this->choices, + )); + $view = $form->createView(); + + $this->assertTrue($view->vars['expanded']); + } + + public function testEmptyValueIsNullByDefaultIfRequired() + { + $form = $this->factory->create('choice', null, array( + 'multiple' => false, + 'required' => true, + 'choices' => $this->choices, + )); + $view = $form->createView(); + + $this->assertNull($view->vars['empty_value']); + } + + public function testEmptyValueIsEmptyStringByDefaultIfNotRequired() + { + $form = $this->factory->create('choice', null, array( + 'multiple' => false, + 'required' => false, + 'choices' => $this->choices, + )); + $view = $form->createView(); + + $this->assertSame('', $view->vars['empty_value']); + } + + /** + * @dataProvider getOptionsWithEmptyValue + */ + public function testPassEmptyValueToView($multiple, $expanded, $required, $emptyValue, $viewValue) + { + $form = $this->factory->create('choice', null, array( + 'multiple' => $multiple, + 'expanded' => $expanded, + 'required' => $required, + 'empty_value' => $emptyValue, + 'choices' => $this->choices, + )); + $view = $form->createView(); + + $this->assertEquals($viewValue, $view->vars['empty_value']); + } + + /** + * @dataProvider getOptionsWithEmptyValue + */ + public function testDontPassEmptyValueIfContainedInChoices($multiple, $expanded, $required, $emptyValue, $viewValue) + { + $form = $this->factory->create('choice', null, array( + 'multiple' => $multiple, + 'expanded' => $expanded, + 'required' => $required, + 'empty_value' => $emptyValue, + 'choices' => array('a' => 'A', '' => 'Empty'), + )); + $view = $form->createView(); + + $this->assertNull($view->vars['empty_value']); + } + + public function getOptionsWithEmptyValue() + { + return array( + // single non-expanded + array(false, false, false, 'foobar', 'foobar'), + array(false, false, false, '', ''), + array(false, false, false, null, null), + array(false, false, false, false, null), + array(false, false, true, 'foobar', 'foobar'), + array(false, false, true, '', ''), + array(false, false, true, null, null), + array(false, false, true, false, null), + // single expanded + array(false, true, false, 'foobar', 'foobar'), + // radios should never have an empty label + array(false, true, false, '', 'None'), + array(false, true, false, null, null), + array(false, true, false, false, null), + array(false, true, true, 'foobar', 'foobar'), + // radios should never have an empty label + array(false, true, true, '', 'None'), + array(false, true, true, null, null), + array(false, true, true, false, null), + // multiple non-expanded + array(true, false, false, 'foobar', null), + array(true, false, false, '', null), + array(true, false, false, null, null), + array(true, false, false, false, null), + array(true, false, true, 'foobar', null), + array(true, false, true, '', null), + array(true, false, true, null, null), + array(true, false, true, false, null), + // multiple expanded + array(true, true, false, 'foobar', null), + array(true, true, false, '', null), + array(true, true, false, null, null), + array(true, true, false, false, null), + array(true, true, true, 'foobar', null), + array(true, true, true, '', null), + array(true, true, true, null, null), + array(true, true, true, false, null), + ); + } + + public function testPassChoicesToView() + { + $choices = array('a' => 'A', 'b' => 'B', 'c' => 'C', 'd' => 'D'); + $form = $this->factory->create('choice', null, array( + 'choices' => $choices, + )); + $view = $form->createView(); + + $this->assertEquals(array( + new ChoiceView('a', 'a', 'A'), + new ChoiceView('b', 'b', 'B'), + new ChoiceView('c', 'c', 'C'), + new ChoiceView('d', 'd', 'D'), + ), $view->vars['choices']); + } + + public function testPassPreferredChoicesToView() + { + $choices = array('a' => 'A', 'b' => 'B', 'c' => 'C', 'd' => 'D'); + $form = $this->factory->create('choice', null, array( + 'choices' => $choices, + 'preferred_choices' => array('b', 'd'), + )); + $view = $form->createView(); + + $this->assertEquals(array( + 0 => new ChoiceView('a', 'a', 'A'), + 2 => new ChoiceView('c', 'c', 'C'), + ), $view->vars['choices']); + $this->assertEquals(array( + 1 => new ChoiceView('b', 'b', 'B'), + 3 => new ChoiceView('d', 'd', 'D'), + ), $view->vars['preferred_choices']); + } + + public function testPassHierarchicalChoicesToView() + { + $form = $this->factory->create('choice', null, array( + 'choices' => $this->groupedChoices, + 'preferred_choices' => array('b', 'd'), + )); + $view = $form->createView(); + + $this->assertEquals(array( + 'Symfony' => array( + 0 => new ChoiceView('a', 'a', 'Bernhard'), + 2 => new ChoiceView('c', 'c', 'Kris'), + ), + 'Doctrine' => array( + 4 => new ChoiceView('e', 'e', 'Roman'), + ), + ), $view->vars['choices']); + $this->assertEquals(array( + 'Symfony' => array( + 1 => new ChoiceView('b', 'b', 'Fabien'), + ), + 'Doctrine' => array( + 3 => new ChoiceView('d', 'd', 'Jon'), + ), + ), $view->vars['preferred_choices']); + } + + public function testPassChoiceDataToView() + { + $obj1 = (object) array('value' => 'a', 'label' => 'A'); + $obj2 = (object) array('value' => 'b', 'label' => 'B'); + $obj3 = (object) array('value' => 'c', 'label' => 'C'); + $obj4 = (object) array('value' => 'd', 'label' => 'D'); + $form = $this->factory->create('choice', null, array( + 'choice_list' => new ObjectChoiceList(array($obj1, $obj2, $obj3, $obj4), 'label', array(), null, 'value'), + )); + $view = $form->createView(); + + $this->assertEquals(array( + new ChoiceView($obj1, 'a', 'A'), + new ChoiceView($obj2, 'b', 'B'), + new ChoiceView($obj3, 'c', 'C'), + new ChoiceView($obj4, 'd', 'D'), + ), $view->vars['choices']); + } + + public function testAdjustFullNameForMultipleNonExpanded() + { + $form = $this->factory->createNamed('name', 'choice', null, array( + 'multiple' => true, + 'expanded' => false, + 'choices' => $this->choices, + )); + $view = $form->createView(); + + $this->assertSame('name[]', $view->vars['full_name']); + } + + // https://github.com/symfony/symfony/issues/3298 + public function testInitializeWithEmptyChoices() + { + $this->factory->createNamed('name', 'choice', null, array( + 'choices' => array(), + )); + } + + public function testInitializeWithDefaultObjectChoice() + { + $obj1 = (object) array('value' => 'a', 'label' => 'A'); + $obj2 = (object) array('value' => 'b', 'label' => 'B'); + $obj3 = (object) array('value' => 'c', 'label' => 'C'); + $obj4 = (object) array('value' => 'd', 'label' => 'D'); + + $form = $this->factory->create('choice', null, array( + 'choice_list' => new ObjectChoiceList(array($obj1, $obj2, $obj3, $obj4), 'label', array(), null, 'value'), + // Used to break because "data_class" was inferred, which needs to + // remain null in every case (because it refers to the view format) + 'data' => $obj3, + )); + + // Trigger data initialization + $form->getViewData(); + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/CollectionTypeTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/CollectionTypeTest.php new file mode 100644 index 00000000..be3ad9db --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/CollectionTypeTest.php @@ -0,0 +1,200 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Core\Type; + +use Symfony\Component\Form\Form; + +class CollectionTypeTest extends \Symfony\Component\Form\Test\TypeTestCase +{ + public function testContainsNoChildByDefault() + { + $form = $this->factory->create('collection', null, array( + 'type' => 'text', + )); + + $this->assertCount(0, $form); + } + + public function testSetDataAdjustsSize() + { + $form = $this->factory->create('collection', null, array( + 'type' => 'text', + 'options' => array( + 'max_length' => 20, + ), + )); + $form->setData(array('foo@foo.com', 'foo@bar.com')); + + $this->assertInstanceOf('Symfony\Component\Form\Form', $form[0]); + $this->assertInstanceOf('Symfony\Component\Form\Form', $form[1]); + $this->assertCount(2, $form); + $this->assertEquals('foo@foo.com', $form[0]->getData()); + $this->assertEquals('foo@bar.com', $form[1]->getData()); + $this->assertEquals(20, $form[0]->getConfig()->getOption('max_length')); + $this->assertEquals(20, $form[1]->getConfig()->getOption('max_length')); + + $form->setData(array('foo@baz.com')); + $this->assertInstanceOf('Symfony\Component\Form\Form', $form[0]); + $this->assertFalse(isset($form[1])); + $this->assertCount(1, $form); + $this->assertEquals('foo@baz.com', $form[0]->getData()); + $this->assertEquals(20, $form[0]->getConfig()->getOption('max_length')); + } + + public function testThrowsExceptionIfObjectIsNotTraversable() + { + $form = $this->factory->create('collection', null, array( + 'type' => 'text', + )); + $this->setExpectedException('Symfony\Component\Form\Exception\UnexpectedTypeException'); + $form->setData(new \stdClass()); + } + + public function testNotResizedIfSubmittedWithMissingData() + { + $form = $this->factory->create('collection', null, array( + 'type' => 'text', + )); + $form->setData(array('foo@foo.com', 'bar@bar.com')); + $form->submit(array('foo@bar.com')); + + $this->assertTrue($form->has('0')); + $this->assertTrue($form->has('1')); + $this->assertEquals('foo@bar.com', $form[0]->getData()); + $this->assertEquals('', $form[1]->getData()); + } + + public function testResizedDownIfSubmittedWithMissingDataAndAllowDelete() + { + $form = $this->factory->create('collection', null, array( + 'type' => 'text', + 'allow_delete' => true, + )); + $form->setData(array('foo@foo.com', 'bar@bar.com')); + $form->submit(array('foo@foo.com')); + + $this->assertTrue($form->has('0')); + $this->assertFalse($form->has('1')); + $this->assertEquals('foo@foo.com', $form[0]->getData()); + $this->assertEquals(array('foo@foo.com'), $form->getData()); + } + + public function testNotResizedIfSubmittedWithExtraData() + { + $form = $this->factory->create('collection', null, array( + 'type' => 'text', + )); + $form->setData(array('foo@bar.com')); + $form->submit(array('foo@foo.com', 'bar@bar.com')); + + $this->assertTrue($form->has('0')); + $this->assertFalse($form->has('1')); + $this->assertEquals('foo@foo.com', $form[0]->getData()); + } + + public function testResizedUpIfSubmittedWithExtraDataAndAllowAdd() + { + $form = $this->factory->create('collection', null, array( + 'type' => 'text', + 'allow_add' => true, + )); + $form->setData(array('foo@bar.com')); + $form->submit(array('foo@bar.com', 'bar@bar.com')); + + $this->assertTrue($form->has('0')); + $this->assertTrue($form->has('1')); + $this->assertEquals('foo@bar.com', $form[0]->getData()); + $this->assertEquals('bar@bar.com', $form[1]->getData()); + $this->assertEquals(array('foo@bar.com', 'bar@bar.com'), $form->getData()); + } + + public function testAllowAddButNoPrototype() + { + $form = $this->factory->create('collection', null, array( + 'type' => 'form', + 'allow_add' => true, + 'prototype' => false, + )); + + $this->assertFalse($form->has('__name__')); + } + + public function testPrototypeMultipartPropagation() + { + $form = $this->factory + ->create('collection', null, array( + 'type' => 'file', + 'allow_add' => true, + 'prototype' => true, + )) + ; + + $this->assertTrue($form->createView()->vars['multipart']); + } + + public function testGetDataDoesNotContainsPrototypeNameBeforeDataAreSet() + { + $form = $this->factory->create('collection', array(), array( + 'type' => 'file', + 'prototype' => true, + 'allow_add' => true, + )); + + $data = $form->getData(); + $this->assertFalse(isset($data['__name__'])); + } + + public function testGetDataDoesNotContainsPrototypeNameAfterDataAreSet() + { + $form = $this->factory->create('collection', array(), array( + 'type' => 'file', + 'allow_add' => true, + 'prototype' => true, + )); + + $form->setData(array('foobar.png')); + $data = $form->getData(); + $this->assertFalse(isset($data['__name__'])); + } + + public function testPrototypeNameOption() + { + $form = $this->factory->create('collection', null, array( + 'type' => 'form', + 'prototype' => true, + 'allow_add' => true, + )); + + $this->assertSame('__name__', $form->getConfig()->getAttribute('prototype')->getName(), '__name__ is the default'); + + $form = $this->factory->create('collection', null, array( + 'type' => 'form', + 'prototype' => true, + 'allow_add' => true, + 'prototype_name' => '__test__', + )); + + $this->assertSame('__test__', $form->getConfig()->getAttribute('prototype')->getName()); + } + + public function testPrototypeDefaultLabel() + { + $form = $this->factory->create('collection', array(), array( + 'type' => 'file', + 'allow_add' => true, + 'prototype' => true, + 'prototype_name' => '__test__', + )); + + $this->assertSame('__test__label__', $form->createView()->vars['prototype']->vars['label']); + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/CountryTypeTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/CountryTypeTest.php new file mode 100644 index 00000000..1d56e2a0 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/CountryTypeTest.php @@ -0,0 +1,52 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Core\Type; + +use Symfony\Component\Form\Extension\Core\View\ChoiceView; +use Symfony\Component\Intl\Util\IntlTestHelper; + +class CountryTypeTest extends TypeTestCase +{ + protected function setUp() + { + IntlTestHelper::requireIntl($this); + + parent::setUp(); + } + + public function testCountriesAreSelectable() + { + $form = $this->factory->create('country'); + $view = $form->createView(); + $choices = $view->vars['choices']; + + // Don't check objects for identity + $this->assertContains(new ChoiceView('DE', 'DE', 'Germany'), $choices, '', false, false); + $this->assertContains(new ChoiceView('GB', 'GB', 'United Kingdom'), $choices, '', false, false); + $this->assertContains(new ChoiceView('US', 'US', 'United States'), $choices, '', false, false); + $this->assertContains(new ChoiceView('FR', 'FR', 'France'), $choices, '', false, false); + $this->assertContains(new ChoiceView('MY', 'MY', 'Malaysia'), $choices, '', false, false); + } + + public function testUnknownCountryIsNotIncluded() + { + $form = $this->factory->create('country', 'country'); + $view = $form->createView(); + $choices = $view->vars['choices']; + + foreach ($choices as $choice) { + if ('ZZ' === $choice->value) { + $this->fail('Should not contain choice "ZZ"'); + } + } + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/CurrencyTypeTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/CurrencyTypeTest.php new file mode 100644 index 00000000..b0eb6dc0 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/CurrencyTypeTest.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Core\Type; + +use Symfony\Component\Form\Extension\Core\View\ChoiceView; +use Symfony\Component\Intl\Util\IntlTestHelper; + +class CurrencyTypeTest extends TypeTestCase +{ + protected function setUp() + { + IntlTestHelper::requireIntl($this); + + parent::setUp(); + } + + public function testCurrenciesAreSelectable() + { + $form = $this->factory->create('currency'); + $view = $form->createView(); + $choices = $view->vars['choices']; + + $this->assertContains(new ChoiceView('EUR', 'EUR', 'Euro'), $choices, '', false, false); + $this->assertContains(new ChoiceView('USD', 'USD', 'US Dollar'), $choices, '', false, false); + $this->assertContains(new ChoiceView('SIT', 'SIT', 'Slovenian Tolar'), $choices, '', false, false); + } + +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/DateTimeTypeTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/DateTimeTypeTest.php new file mode 100644 index 00000000..b9c1ebad --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/DateTimeTypeTest.php @@ -0,0 +1,477 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Core\Type; + +use Symfony\Component\Form\FormError; +use Symfony\Component\Intl\Util\IntlTestHelper; + +class DateTimeTypeTest extends TypeTestCase +{ + protected function setUp() + { + IntlTestHelper::requireIntl($this); + + parent::setUp(); + } + + public function testSubmitDateTime() + { + $form = $this->factory->create('datetime', null, array( + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', + 'date_widget' => 'choice', + 'time_widget' => 'choice', + 'input' => 'datetime', + )); + + $form->submit(array( + 'date' => array( + 'day' => '2', + 'month' => '6', + 'year' => '2010', + ), + 'time' => array( + 'hour' => '3', + 'minute' => '4', + ), + )); + + $dateTime = new \DateTime('2010-06-02 03:04:00 UTC'); + + $this->assertDateTimeEquals($dateTime, $form->getData()); + } + + public function testSubmitString() + { + $form = $this->factory->create('datetime', null, array( + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', + 'input' => 'string', + 'date_widget' => 'choice', + 'time_widget' => 'choice', + )); + + $form->submit(array( + 'date' => array( + 'day' => '2', + 'month' => '6', + 'year' => '2010', + ), + 'time' => array( + 'hour' => '3', + 'minute' => '4', + ), + )); + + $this->assertEquals('2010-06-02 03:04:00', $form->getData()); + } + + public function testSubmitTimestamp() + { + $form = $this->factory->create('datetime', null, array( + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', + 'input' => 'timestamp', + 'date_widget' => 'choice', + 'time_widget' => 'choice', + )); + + $form->submit(array( + 'date' => array( + 'day' => '2', + 'month' => '6', + 'year' => '2010', + ), + 'time' => array( + 'hour' => '3', + 'minute' => '4', + ), + )); + + $dateTime = new \DateTime('2010-06-02 03:04:00 UTC'); + + $this->assertEquals($dateTime->format('U'), $form->getData()); + } + + public function testSubmitWithoutMinutes() + { + $form = $this->factory->create('datetime', null, array( + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', + 'date_widget' => 'choice', + 'time_widget' => 'choice', + 'input' => 'datetime', + 'with_minutes' => false, + )); + + $form->setData(new \DateTime('2010-06-02 03:04:05 UTC')); + + $input = array( + 'date' => array( + 'day' => '2', + 'month' => '6', + 'year' => '2010', + ), + 'time' => array( + 'hour' => '3', + ), + ); + + $form->submit($input); + + $this->assertDateTimeEquals(new \DateTime('2010-06-02 03:00:00 UTC'), $form->getData()); + } + + public function testSubmitWithSeconds() + { + $form = $this->factory->create('datetime', null, array( + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', + 'date_widget' => 'choice', + 'time_widget' => 'choice', + 'input' => 'datetime', + 'with_seconds' => true, + )); + + $form->setData(new \DateTime('2010-06-02 03:04:05 UTC')); + + $input = array( + 'date' => array( + 'day' => '2', + 'month' => '6', + 'year' => '2010', + ), + 'time' => array( + 'hour' => '3', + 'minute' => '4', + 'second' => '5', + ), + ); + + $form->submit($input); + + $this->assertDateTimeEquals(new \DateTime('2010-06-02 03:04:05 UTC'), $form->getData()); + } + + public function testSubmitDifferentTimezones() + { + $form = $this->factory->create('datetime', null, array( + 'model_timezone' => 'America/New_York', + 'view_timezone' => 'Pacific/Tahiti', + 'date_widget' => 'choice', + 'time_widget' => 'choice', + 'input' => 'string', + 'with_seconds' => true, + )); + + $dateTime = new \DateTime('2010-06-02 03:04:05 Pacific/Tahiti'); + + $form->submit(array( + 'date' => array( + 'day' => (int) $dateTime->format('d'), + 'month' => (int) $dateTime->format('m'), + 'year' => (int) $dateTime->format('Y'), + ), + 'time' => array( + 'hour' => (int) $dateTime->format('H'), + 'minute' => (int) $dateTime->format('i'), + 'second' => (int) $dateTime->format('s'), + ), + )); + + $dateTime->setTimezone(new \DateTimeZone('America/New_York')); + + $this->assertEquals($dateTime->format('Y-m-d H:i:s'), $form->getData()); + } + + public function testSubmitDifferentTimezonesDateTime() + { + $form = $this->factory->create('datetime', null, array( + 'model_timezone' => 'America/New_York', + 'view_timezone' => 'Pacific/Tahiti', + 'widget' => 'single_text', + 'input' => 'datetime', + )); + + $outputTime = new \DateTime('2010-06-02 03:04:00 Pacific/Tahiti'); + + $form->submit('2010-06-02T03:04:00-10:00'); + + $outputTime->setTimezone(new \DateTimeZone('America/New_York')); + + $this->assertDateTimeEquals($outputTime, $form->getData()); + $this->assertEquals('2010-06-02T03:04:00-10:00', $form->getViewData()); + } + + public function testSubmitStringSingleText() + { + $form = $this->factory->create('datetime', null, array( + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', + 'input' => 'string', + 'widget' => 'single_text', + )); + + $form->submit('2010-06-02T03:04:00Z'); + + $this->assertEquals('2010-06-02 03:04:00', $form->getData()); + $this->assertEquals('2010-06-02T03:04:00Z', $form->getViewData()); + } + + public function testSubmitStringSingleTextWithSeconds() + { + $form = $this->factory->create('datetime', null, array( + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', + 'input' => 'string', + 'widget' => 'single_text', + 'with_seconds' => true, + )); + + $form->submit('2010-06-02T03:04:05Z'); + + $this->assertEquals('2010-06-02 03:04:05', $form->getData()); + $this->assertEquals('2010-06-02T03:04:05Z', $form->getViewData()); + } + + public function testSubmitDifferentPattern() + { + $form = $this->factory->create('datetime', null, array( + 'date_format' => 'MM*yyyy*dd', + 'date_widget' => 'single_text', + 'time_widget' => 'single_text', + 'input' => 'datetime', + )); + + $dateTime = new \DateTime('2010-06-02 03:04'); + + $form->submit(array( + 'date' => '06*2010*02', + 'time' => '03:04', + )); + + $this->assertDateTimeEquals($dateTime, $form->getData()); + } + + // Bug fix + public function testInitializeWithDateTime() + { + // Throws an exception if "data_class" option is not explicitly set + // to null in the type + $this->factory->create('datetime', new \DateTime()); + } + + public function testSingleTextWidgetShouldUseTheRightInputType() + { + $form = $this->factory->create('datetime', null, array( + 'widget' => 'single_text', + )); + + $view = $form->createView(); + $this->assertEquals('datetime', $view->vars['type']); + } + + public function testPassDefaultEmptyValueToViewIfNotRequired() + { + $form = $this->factory->create('datetime', null, array( + 'required' => false, + 'with_seconds' => true, + )); + + $view = $form->createView(); + $this->assertSame('', $view['date']['year']->vars['empty_value']); + $this->assertSame('', $view['date']['month']->vars['empty_value']); + $this->assertSame('', $view['date']['day']->vars['empty_value']); + $this->assertSame('', $view['time']['hour']->vars['empty_value']); + $this->assertSame('', $view['time']['minute']->vars['empty_value']); + $this->assertSame('', $view['time']['second']->vars['empty_value']); + } + + public function testPassNoEmptyValueToViewIfRequired() + { + $form = $this->factory->create('datetime', null, array( + 'required' => true, + 'with_seconds' => true, + )); + + $view = $form->createView(); + $this->assertNull($view['date']['year']->vars['empty_value']); + $this->assertNull($view['date']['month']->vars['empty_value']); + $this->assertNull($view['date']['day']->vars['empty_value']); + $this->assertNull($view['time']['hour']->vars['empty_value']); + $this->assertNull($view['time']['minute']->vars['empty_value']); + $this->assertNull($view['time']['second']->vars['empty_value']); + } + + public function testPassEmptyValueAsString() + { + $form = $this->factory->create('datetime', null, array( + 'empty_value' => 'Empty', + 'with_seconds' => true, + )); + + $view = $form->createView(); + $this->assertSame('Empty', $view['date']['year']->vars['empty_value']); + $this->assertSame('Empty', $view['date']['month']->vars['empty_value']); + $this->assertSame('Empty', $view['date']['day']->vars['empty_value']); + $this->assertSame('Empty', $view['time']['hour']->vars['empty_value']); + $this->assertSame('Empty', $view['time']['minute']->vars['empty_value']); + $this->assertSame('Empty', $view['time']['second']->vars['empty_value']); + } + + public function testPassEmptyValueAsArray() + { + $form = $this->factory->create('datetime', null, array( + 'empty_value' => array( + 'year' => 'Empty year', + 'month' => 'Empty month', + 'day' => 'Empty day', + 'hour' => 'Empty hour', + 'minute' => 'Empty minute', + 'second' => 'Empty second', + ), + 'with_seconds' => true, + )); + + $view = $form->createView(); + $this->assertSame('Empty year', $view['date']['year']->vars['empty_value']); + $this->assertSame('Empty month', $view['date']['month']->vars['empty_value']); + $this->assertSame('Empty day', $view['date']['day']->vars['empty_value']); + $this->assertSame('Empty hour', $view['time']['hour']->vars['empty_value']); + $this->assertSame('Empty minute', $view['time']['minute']->vars['empty_value']); + $this->assertSame('Empty second', $view['time']['second']->vars['empty_value']); + } + + public function testPassEmptyValueAsPartialArrayAddEmptyIfNotRequired() + { + $form = $this->factory->create('datetime', null, array( + 'required' => false, + 'empty_value' => array( + 'year' => 'Empty year', + 'day' => 'Empty day', + 'hour' => 'Empty hour', + 'second' => 'Empty second', + ), + 'with_seconds' => true, + )); + + $view = $form->createView(); + $this->assertSame('Empty year', $view['date']['year']->vars['empty_value']); + $this->assertSame('', $view['date']['month']->vars['empty_value']); + $this->assertSame('Empty day', $view['date']['day']->vars['empty_value']); + $this->assertSame('Empty hour', $view['time']['hour']->vars['empty_value']); + $this->assertSame('', $view['time']['minute']->vars['empty_value']); + $this->assertSame('Empty second', $view['time']['second']->vars['empty_value']); + } + + public function testPassEmptyValueAsPartialArrayAddNullIfRequired() + { + $form = $this->factory->create('datetime', null, array( + 'required' => true, + 'empty_value' => array( + 'year' => 'Empty year', + 'day' => 'Empty day', + 'hour' => 'Empty hour', + 'second' => 'Empty second', + ), + 'with_seconds' => true, + )); + + $view = $form->createView(); + $this->assertSame('Empty year', $view['date']['year']->vars['empty_value']); + $this->assertNull($view['date']['month']->vars['empty_value']); + $this->assertSame('Empty day', $view['date']['day']->vars['empty_value']); + $this->assertSame('Empty hour', $view['time']['hour']->vars['empty_value']); + $this->assertNull($view['time']['minute']->vars['empty_value']); + $this->assertSame('Empty second', $view['time']['second']->vars['empty_value']); + } + + public function testPassHtml5TypeIfSingleTextAndHtml5Format() + { + $form = $this->factory->create('datetime', null, array( + 'widget' => 'single_text', + )); + + $view = $form->createView(); + $this->assertSame('datetime', $view->vars['type']); + } + + public function testDontPassHtml5TypeIfNotHtml5Format() + { + $form = $this->factory->create('datetime', null, array( + 'widget' => 'single_text', + 'format' => 'yyyy-MM-dd HH:mm', + )); + + $view = $form->createView(); + $this->assertFalse(isset($view->vars['type'])); + } + + public function testDontPassHtml5TypeIfNotSingleText() + { + $form = $this->factory->create('datetime', null, array( + 'widget' => 'text', + )); + + $view = $form->createView(); + $this->assertFalse(isset($view->vars['type'])); + } + + public function testDateTypeChoiceErrorsBubbleUp() + { + $error = new FormError('Invalid!'); + $form = $this->factory->create('datetime', null); + + $form['date']->addError($error); + + $this->assertSame(array(), $form['date']->getErrors()); + $this->assertSame(array($error), $form->getErrors()); + } + + public function testDateTypeSingleTextErrorsBubbleUp() + { + $error = new FormError('Invalid!'); + $form = $this->factory->create('datetime', null, array( + 'date_widget' => 'single_text' + )); + + $form['date']->addError($error); + + $this->assertSame(array(), $form['date']->getErrors()); + $this->assertSame(array($error), $form->getErrors()); + } + + public function testTimeTypeChoiceErrorsBubbleUp() + { + $error = new FormError('Invalid!'); + $form = $this->factory->create('datetime', null); + + $form['time']->addError($error); + + $this->assertSame(array(), $form['time']->getErrors()); + $this->assertSame(array($error), $form->getErrors()); + } + + public function testTimeTypeSingleTextErrorsBubbleUp() + { + $error = new FormError('Invalid!'); + $form = $this->factory->create('datetime', null, array( + 'time_widget' => 'single_text' + )); + + $form['time']->addError($error); + + $this->assertSame(array(), $form['time']->getErrors()); + $this->assertSame(array($error), $form->getErrors()); + } + +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/DateTypeTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/DateTypeTest.php new file mode 100644 index 00000000..2aa155e7 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/DateTypeTest.php @@ -0,0 +1,781 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Core\Type; + +use Symfony\Component\Form\Extension\Core\View\ChoiceView; +use Symfony\Component\Form\FormError; +use Symfony\Component\Intl\Util\IntlTestHelper; + +class DateTypeTest extends TypeTestCase +{ + protected function setUp() + { + parent::setUp(); + + // we test against "de_AT", so we need the full implementation + IntlTestHelper::requireFullIntl($this); + + \Locale::setDefault('de_AT'); + } + + /** + * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException + */ + public function testInvalidWidgetOption() + { + $this->factory->create('date', null, array( + 'widget' => 'fake_widget', + )); + } + + /** + * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException + */ + public function testInvalidInputOption() + { + $this->factory->create('date', null, array( + 'input' => 'fake_input', + )); + } + + public function testSubmitFromSingleTextDateTimeWithDefaultFormat() + { + $form = $this->factory->create('date', null, array( + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', + 'widget' => 'single_text', + 'input' => 'datetime', + )); + + $form->submit('2010-06-02'); + + $this->assertDateTimeEquals(new \DateTime('2010-06-02 UTC'), $form->getData()); + $this->assertEquals('2010-06-02', $form->getViewData()); + } + + public function testSubmitFromSingleTextDateTime() + { + $form = $this->factory->create('date', null, array( + 'format' => \IntlDateFormatter::MEDIUM, + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', + 'widget' => 'single_text', + 'input' => 'datetime', + )); + + $form->submit('2.6.2010'); + + $this->assertDateTimeEquals(new \DateTime('2010-06-02 UTC'), $form->getData()); + $this->assertEquals('02.06.2010', $form->getViewData()); + } + + public function testSubmitFromSingleTextString() + { + $form = $this->factory->create('date', null, array( + 'format' => \IntlDateFormatter::MEDIUM, + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', + 'widget' => 'single_text', + 'input' => 'string', + )); + + $form->submit('2.6.2010'); + + $this->assertEquals('2010-06-02', $form->getData()); + $this->assertEquals('02.06.2010', $form->getViewData()); + } + + public function testSubmitFromSingleTextTimestamp() + { + $form = $this->factory->create('date', null, array( + 'format' => \IntlDateFormatter::MEDIUM, + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', + 'widget' => 'single_text', + 'input' => 'timestamp', + )); + + $form->submit('2.6.2010'); + + $dateTime = new \DateTime('2010-06-02 UTC'); + + $this->assertEquals($dateTime->format('U'), $form->getData()); + $this->assertEquals('02.06.2010', $form->getViewData()); + } + + public function testSubmitFromSingleTextRaw() + { + $form = $this->factory->create('date', null, array( + 'format' => \IntlDateFormatter::MEDIUM, + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', + 'widget' => 'single_text', + 'input' => 'array', + )); + + $form->submit('2.6.2010'); + + $output = array( + 'day' => '2', + 'month' => '6', + 'year' => '2010', + ); + + $this->assertEquals($output, $form->getData()); + $this->assertEquals('02.06.2010', $form->getViewData()); + } + + public function testSubmitFromText() + { + $form = $this->factory->create('date', null, array( + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', + 'widget' => 'text', + )); + + $text = array( + 'day' => '2', + 'month' => '6', + 'year' => '2010', + ); + + $form->submit($text); + + $dateTime = new \DateTime('2010-06-02 UTC'); + + $this->assertDateTimeEquals($dateTime, $form->getData()); + $this->assertEquals($text, $form->getViewData()); + } + + public function testSubmitFromChoice() + { + $form = $this->factory->create('date', null, array( + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', + 'widget' => 'choice', + )); + + $text = array( + 'day' => '2', + 'month' => '6', + 'year' => '2010', + ); + + $form->submit($text); + + $dateTime = new \DateTime('2010-06-02 UTC'); + + $this->assertDateTimeEquals($dateTime, $form->getData()); + $this->assertEquals($text, $form->getViewData()); + } + + public function testSubmitFromChoiceEmpty() + { + $form = $this->factory->create('date', null, array( + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', + 'widget' => 'choice', + 'required' => false, + )); + + $text = array( + 'day' => '', + 'month' => '', + 'year' => '', + ); + + $form->submit($text); + + $this->assertNull($form->getData()); + $this->assertEquals($text, $form->getViewData()); + } + + public function testSubmitFromInputDateTimeDifferentPattern() + { + $form = $this->factory->create('date', null, array( + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', + 'format' => 'MM*yyyy*dd', + 'widget' => 'single_text', + 'input' => 'datetime', + )); + + $form->submit('06*2010*02'); + + $this->assertDateTimeEquals(new \DateTime('2010-06-02 UTC'), $form->getData()); + $this->assertEquals('06*2010*02', $form->getViewData()); + } + + public function testSubmitFromInputStringDifferentPattern() + { + $form = $this->factory->create('date', null, array( + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', + 'format' => 'MM*yyyy*dd', + 'widget' => 'single_text', + 'input' => 'string', + )); + + $form->submit('06*2010*02'); + + $this->assertEquals('2010-06-02', $form->getData()); + $this->assertEquals('06*2010*02', $form->getViewData()); + } + + public function testSubmitFromInputTimestampDifferentPattern() + { + $form = $this->factory->create('date', null, array( + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', + 'format' => 'MM*yyyy*dd', + 'widget' => 'single_text', + 'input' => 'timestamp', + )); + + $form->submit('06*2010*02'); + + $dateTime = new \DateTime('2010-06-02 UTC'); + + $this->assertEquals($dateTime->format('U'), $form->getData()); + $this->assertEquals('06*2010*02', $form->getViewData()); + } + + public function testSubmitFromInputRawDifferentPattern() + { + $form = $this->factory->create('date', null, array( + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', + 'format' => 'MM*yyyy*dd', + 'widget' => 'single_text', + 'input' => 'array', + )); + + $form->submit('06*2010*02'); + + $output = array( + 'day' => '2', + 'month' => '6', + 'year' => '2010', + ); + + $this->assertEquals($output, $form->getData()); + $this->assertEquals('06*2010*02', $form->getViewData()); + } + + /** + * @dataProvider provideDateFormats + */ + public function testDatePatternWithFormatOption($format, $pattern) + { + $form = $this->factory->create('date', null, array( + 'format' => $format, + )); + + $view = $form->createView(); + + $this->assertEquals($pattern, $view->vars['date_pattern']); + } + + public function provideDateFormats() + { + return array( + array('dMy', '{{ day }}{{ month }}{{ year }}'), + array('d-M-yyyy', '{{ day }}-{{ month }}-{{ year }}'), + array('M d y', '{{ month }} {{ day }} {{ year }}'), + ); + } + + /** + * This test is to check that the strings '0', '1', '2', '3' are no accepted + * as valid IntlDateFormatter constants for FULL, LONG, MEDIUM or SHORT respectively. + * + * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException + */ + public function testThrowExceptionIfFormatIsNoPattern() + { + $this->factory->create('date', null, array( + 'format' => '0', + 'widget' => 'single_text', + 'input' => 'string', + )); + } + + /** + * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException + */ + public function testThrowExceptionIfFormatDoesNotContainYearMonthAndDay() + { + $this->factory->create('date', null, array( + 'months' => array(6, 7), + 'format' => 'yy', + )); + } + + /** + * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException + */ + public function testThrowExceptionIfFormatIsNoConstant() + { + $this->factory->create('date', null, array( + 'format' => 105, + )); + } + + /** + * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException + */ + public function testThrowExceptionIfFormatIsInvalid() + { + $this->factory->create('date', null, array( + 'format' => array(), + )); + } + + public function testSetDataWithDifferentTimezones() + { + $form = $this->factory->create('date', null, array( + 'format' => \IntlDateFormatter::MEDIUM, + 'model_timezone' => 'America/New_York', + 'view_timezone' => 'Pacific/Tahiti', + 'input' => 'string', + 'widget' => 'single_text', + )); + + $form->setData('2010-06-02'); + + $this->assertEquals('01.06.2010', $form->getViewData()); + } + + public function testSetDataWithDifferentTimezonesDateTime() + { + $form = $this->factory->create('date', null, array( + 'format' => \IntlDateFormatter::MEDIUM, + 'model_timezone' => 'America/New_York', + 'view_timezone' => 'Pacific/Tahiti', + 'input' => 'datetime', + 'widget' => 'single_text', + )); + + $dateTime = new \DateTime('2010-06-02 America/New_York'); + + $form->setData($dateTime); + + $this->assertDateTimeEquals($dateTime, $form->getData()); + $this->assertEquals('01.06.2010', $form->getViewData()); + } + + public function testYearsOption() + { + $form = $this->factory->create('date', null, array( + 'years' => array(2010, 2011), + )); + + $view = $form->createView(); + + $this->assertEquals(array( + new ChoiceView('2010', '2010', '2010'), + new ChoiceView('2011', '2011', '2011'), + ), $view['year']->vars['choices']); + } + + public function testMonthsOption() + { + $form = $this->factory->create('date', null, array( + 'months' => array(6, 7), + )); + + $view = $form->createView(); + + $this->assertEquals(array( + new ChoiceView('6', '6', '06'), + new ChoiceView('7', '7', '07'), + ), $view['month']->vars['choices']); + } + + public function testMonthsOptionShortFormat() + { + $form = $this->factory->create('date', null, array( + 'months' => array(1, 4), + 'format' => 'dd.MMM.yy', + )); + + $view = $form->createView(); + + $this->assertEquals(array( + new ChoiceView('1', '1', 'Jän'), + new ChoiceView('4', '4', 'Apr.') + ), $view['month']->vars['choices']); + } + + public function testMonthsOptionLongFormat() + { + $form = $this->factory->create('date', null, array( + 'months' => array(1, 4), + 'format' => 'dd.MMMM.yy', + )); + + $view = $form->createView(); + + $this->assertEquals(array( + new ChoiceView('1', '1', 'Jänner'), + new ChoiceView('4', '4', 'April'), + ), $view['month']->vars['choices']); + } + + public function testMonthsOptionLongFormatWithDifferentTimezone() + { + $form = $this->factory->create('date', null, array( + 'months' => array(1, 4), + 'format' => 'dd.MMMM.yy', + )); + + $view = $form->createView(); + + $this->assertEquals(array( + new ChoiceView('1', '1', 'Jänner'), + new ChoiceView('4', '4', 'April'), + ), $view['month']->vars['choices']); + } + + public function testIsDayWithinRangeReturnsTrueIfWithin() + { + $form = $this->factory->create('date', null, array( + 'days' => array(6, 7), + )); + + $view = $form->createView(); + + $this->assertEquals(array( + new ChoiceView('6', '6', '06'), + new ChoiceView('7', '7', '07'), + ), $view['day']->vars['choices']); + } + + public function testIsPartiallyFilledReturnsFalseIfSingleText() + { + $this->markTestIncomplete('Needs to be reimplemented using validators'); + + $form = $this->factory->create('date', null, array( + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', + 'widget' => 'single_text', + )); + + $form->submit('7.6.2010'); + + $this->assertFalse($form->isPartiallyFilled()); + } + + public function testIsPartiallyFilledReturnsFalseIfChoiceAndCompletelyEmpty() + { + $this->markTestIncomplete('Needs to be reimplemented using validators'); + + $form = $this->factory->create('date', null, array( + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', + 'widget' => 'choice', + )); + + $form->submit(array( + 'day' => '', + 'month' => '', + 'year' => '', + )); + + $this->assertFalse($form->isPartiallyFilled()); + } + + public function testIsPartiallyFilledReturnsFalseIfChoiceAndCompletelyFilled() + { + $this->markTestIncomplete('Needs to be reimplemented using validators'); + + $form = $this->factory->create('date', null, array( + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', + 'widget' => 'choice', + )); + + $form->submit(array( + 'day' => '2', + 'month' => '6', + 'year' => '2010', + )); + + $this->assertFalse($form->isPartiallyFilled()); + } + + public function testIsPartiallyFilledReturnsTrueIfChoiceAndDayEmpty() + { + $this->markTestIncomplete('Needs to be reimplemented using validators'); + + $form = $this->factory->create('date', null, array( + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', + 'widget' => 'choice', + )); + + $form->submit(array( + 'day' => '', + 'month' => '6', + 'year' => '2010', + )); + + $this->assertTrue($form->isPartiallyFilled()); + } + + public function testPassDatePatternToView() + { + $form = $this->factory->create('date'); + $view = $form->createView(); + + $this->assertSame('{{ day }}{{ month }}{{ year }}', $view->vars['date_pattern']); + } + + public function testPassDatePatternToViewDifferentFormat() + { + $form = $this->factory->create('date', null, array( + 'format' => \IntlDateFormatter::LONG, + )); + + $view = $form->createView(); + + $this->assertSame('{{ day }}{{ month }}{{ year }}', $view->vars['date_pattern']); + } + + public function testPassDatePatternToViewDifferentPattern() + { + $form = $this->factory->create('date', null, array( + 'format' => 'MMyyyydd' + )); + + $view = $form->createView(); + + $this->assertSame('{{ month }}{{ year }}{{ day }}', $view->vars['date_pattern']); + } + + public function testPassDatePatternToViewDifferentPatternWithSeparators() + { + $form = $this->factory->create('date', null, array( + 'format' => 'MM*yyyy*dd' + )); + + $view = $form->createView(); + + $this->assertSame('{{ month }}*{{ year }}*{{ day }}', $view->vars['date_pattern']); + } + + public function testDontPassDatePatternIfText() + { + $form = $this->factory->create('date', null, array( + 'widget' => 'single_text', + )); + $view = $form->createView(); + + $this->assertFalse(isset($view->vars['date_pattern'])); + } + + public function testPassWidgetToView() + { + $form = $this->factory->create('date', null, array( + 'widget' => 'single_text', + )); + $view = $form->createView(); + + $this->assertSame('single_text', $view->vars['widget']); + } + + // Bug fix + public function testInitializeWithDateTime() + { + // Throws an exception if "data_class" option is not explicitly set + // to null in the type + $this->factory->create('date', new \DateTime()); + } + + public function testSingleTextWidgetShouldUseTheRightInputType() + { + $form = $this->factory->create('date', null, array( + 'widget' => 'single_text', + )); + + $view = $form->createView(); + $this->assertEquals('date', $view->vars['type']); + } + + public function testPassDefaultEmptyValueToViewIfNotRequired() + { + $form = $this->factory->create('date', null, array( + 'required' => false, + )); + + $view = $form->createView(); + $this->assertSame('', $view['year']->vars['empty_value']); + $this->assertSame('', $view['month']->vars['empty_value']); + $this->assertSame('', $view['day']->vars['empty_value']); + } + + public function testPassNoEmptyValueToViewIfRequired() + { + $form = $this->factory->create('date', null, array( + 'required' => true, + )); + + $view = $form->createView(); + $this->assertNull($view['year']->vars['empty_value']); + $this->assertNull($view['month']->vars['empty_value']); + $this->assertNull($view['day']->vars['empty_value']); + } + + public function testPassEmptyValueAsString() + { + $form = $this->factory->create('date', null, array( + 'empty_value' => 'Empty', + )); + + $view = $form->createView(); + $this->assertSame('Empty', $view['year']->vars['empty_value']); + $this->assertSame('Empty', $view['month']->vars['empty_value']); + $this->assertSame('Empty', $view['day']->vars['empty_value']); + } + + public function testPassEmptyValueAsArray() + { + $form = $this->factory->create('date', null, array( + 'empty_value' => array( + 'year' => 'Empty year', + 'month' => 'Empty month', + 'day' => 'Empty day', + ), + )); + + $view = $form->createView(); + $this->assertSame('Empty year', $view['year']->vars['empty_value']); + $this->assertSame('Empty month', $view['month']->vars['empty_value']); + $this->assertSame('Empty day', $view['day']->vars['empty_value']); + } + + public function testPassEmptyValueAsPartialArrayAddEmptyIfNotRequired() + { + $form = $this->factory->create('date', null, array( + 'required' => false, + 'empty_value' => array( + 'year' => 'Empty year', + 'day' => 'Empty day', + ), + )); + + $view = $form->createView(); + $this->assertSame('Empty year', $view['year']->vars['empty_value']); + $this->assertSame('', $view['month']->vars['empty_value']); + $this->assertSame('Empty day', $view['day']->vars['empty_value']); + } + + public function testPassEmptyValueAsPartialArrayAddNullIfRequired() + { + $form = $this->factory->create('date', null, array( + 'required' => true, + 'empty_value' => array( + 'year' => 'Empty year', + 'day' => 'Empty day', + ), + )); + + $view = $form->createView(); + $this->assertSame('Empty year', $view['year']->vars['empty_value']); + $this->assertNull($view['month']->vars['empty_value']); + $this->assertSame('Empty day', $view['day']->vars['empty_value']); + } + + public function testPassHtml5TypeIfSingleTextAndHtml5Format() + { + $form = $this->factory->create('date', null, array( + 'widget' => 'single_text', + )); + + $view = $form->createView(); + $this->assertSame('date', $view->vars['type']); + } + + public function testDontPassHtml5TypeIfNotHtml5Format() + { + $form = $this->factory->create('date', null, array( + 'widget' => 'single_text', + 'format' => \IntlDateFormatter::MEDIUM, + )); + + $view = $form->createView(); + $this->assertFalse(isset($view->vars['type'])); + } + + public function testDontPassHtml5TypeIfNotSingleText() + { + $form = $this->factory->create('date', null, array( + 'widget' => 'text', + )); + + $view = $form->createView(); + $this->assertFalse(isset($view->vars['type'])); + } + + public function provideCompoundWidgets() + { + return array( + array('text'), + array('choice'), + ); + } + + /** + * @dataProvider provideCompoundWidgets + */ + public function testYearErrorsBubbleUp($widget) + { + $error = new FormError('Invalid!'); + $form = $this->factory->create('date', null, array( + 'widget' => $widget, + )); + $form['year']->addError($error); + + $this->assertSame(array(), $form['year']->getErrors()); + $this->assertSame(array($error), $form->getErrors()); + } + + /** + * @dataProvider provideCompoundWidgets + */ + public function testMonthErrorsBubbleUp($widget) + { + $error = new FormError('Invalid!'); + $form = $this->factory->create('date', null, array( + 'widget' => $widget, + )); + $form['month']->addError($error); + + $this->assertSame(array(), $form['month']->getErrors()); + $this->assertSame(array($error), $form->getErrors()); + } + + /** + * @dataProvider provideCompoundWidgets + */ + public function testDayErrorsBubbleUp($widget) + { + $error = new FormError('Invalid!'); + $form = $this->factory->create('date', null, array( + 'widget' => $widget, + )); + $form['day']->addError($error); + + $this->assertSame(array(), $form['day']->getErrors()); + $this->assertSame(array($error), $form->getErrors()); + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/FileTypeTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/FileTypeTest.php new file mode 100644 index 00000000..63556eb5 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/FileTypeTest.php @@ -0,0 +1,83 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Core\Type; + +class FileTypeTest extends \Symfony\Component\Form\Test\TypeTestCase +{ + // https://github.com/symfony/symfony/pull/5028 + public function testSetData() + { + $form = $this->factory->createBuilder('file')->getForm(); + $data = $this->createUploadedFileMock('abcdef', 'original.jpg', true); + + $form->setData($data); + + $this->assertSame($data, $form->getData()); + } + + public function testSubmit() + { + $form = $this->factory->createBuilder('file')->getForm(); + $data = $this->createUploadedFileMock('abcdef', 'original.jpg', true); + + $form->submit($data); + + $this->assertSame($data, $form->getData()); + } + + // https://github.com/symfony/symfony/issues/6134 + public function testSubmitEmpty() + { + $form = $this->factory->createBuilder('file')->getForm(); + + $form->submit(null); + + $this->assertNull($form->getData()); + } + + public function testDontPassValueToView() + { + $form = $this->factory->create('file'); + $form->submit(array( + 'file' => $this->createUploadedFileMock('abcdef', 'original.jpg', true), + )); + $view = $form->createView(); + + $this->assertEquals('', $view->vars['value']); + } + + private function createUploadedFileMock($name, $originalName, $valid) + { + $file = $this + ->getMockBuilder('Symfony\Component\HttpFoundation\File\UploadedFile') + ->disableOriginalConstructor() + ->getMock() + ; + $file + ->expects($this->any()) + ->method('getBasename') + ->will($this->returnValue($name)) + ; + $file + ->expects($this->any()) + ->method('getClientOriginalName') + ->will($this->returnValue($originalName)) + ; + $file + ->expects($this->any()) + ->method('isValid') + ->will($this->returnValue($valid)) + ; + + return $file; + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/FormTypeTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/FormTypeTest.php new file mode 100644 index 00000000..cced82f4 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/FormTypeTest.php @@ -0,0 +1,578 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Core\Type; + +use Symfony\Component\PropertyAccess\PropertyPath; +use Symfony\Component\Form\Form; +use Symfony\Component\Form\CallbackTransformer; +use Symfony\Component\Form\Tests\Fixtures\Author; +use Symfony\Component\Form\Tests\Fixtures\FixedDataTransformer; +use Symfony\Component\Form\FormError; + +class FormTest_AuthorWithoutRefSetter +{ + protected $reference; + + protected $referenceCopy; + + public function __construct($reference) + { + $this->reference = $reference; + $this->referenceCopy = $reference; + } + + // The returned object should be modified by reference without having + // to provide a setReference() method + public function getReference() + { + return $this->reference; + } + + // The returned object is a copy, so setReferenceCopy() must be used + // to update it + public function getReferenceCopy() + { + return is_object($this->referenceCopy) ? clone $this->referenceCopy : $this->referenceCopy; + } + + public function setReferenceCopy($reference) + { + $this->referenceCopy = $reference; + } +} + +class FormTypeTest extends BaseTypeTest +{ + public function testCreateFormInstances() + { + $this->assertInstanceOf('Symfony\Component\Form\Form', $this->factory->create('form')); + } + + public function testPassRequiredAsOption() + { + $form = $this->factory->create('form', null, array('required' => false)); + + $this->assertFalse($form->isRequired()); + + $form = $this->factory->create('form', null, array('required' => true)); + + $this->assertTrue($form->isRequired()); + } + + public function testSubmittedDataIsTrimmedBeforeTransforming() + { + $form = $this->factory->createBuilder('form') + ->addViewTransformer(new FixedDataTransformer(array( + null => '', + 'reverse[a]' => 'a', + ))) + ->setCompound(false) + ->getForm(); + + $form->submit(' a '); + + $this->assertEquals('a', $form->getViewData()); + $this->assertEquals('reverse[a]', $form->getData()); + } + + public function testSubmittedDataIsNotTrimmedBeforeTransformingIfNoTrimming() + { + $form = $this->factory->createBuilder('form', null, array('trim' => false)) + ->addViewTransformer(new FixedDataTransformer(array( + null => '', + 'reverse[ a ]' => ' a ', + ))) + ->setCompound(false) + ->getForm(); + + $form->submit(' a '); + + $this->assertEquals(' a ', $form->getViewData()); + $this->assertEquals('reverse[ a ]', $form->getData()); + } + + public function testNonReadOnlyFormWithReadOnlyParentIsReadOnly() + { + $view = $this->factory->createNamedBuilder('parent', 'form', null, array('read_only' => true)) + ->add('child', 'form') + ->getForm() + ->createView(); + + $this->assertTrue($view['child']->vars['read_only']); + } + + public function testReadOnlyFormWithNonReadOnlyParentIsReadOnly() + { + $view = $this->factory->createNamedBuilder('parent', 'form') + ->add('child', 'form', array('read_only' => true)) + ->getForm() + ->createView(); + + $this->assertTrue($view['child']->vars['read_only']); + } + + public function testNonReadOnlyFormWithNonReadOnlyParentIsNotReadOnly() + { + $view = $this->factory->createNamedBuilder('parent', 'form') + ->add('child', 'form') + ->getForm() + ->createView(); + + $this->assertFalse($view['child']->vars['read_only']); + } + + public function testPassMaxLengthToView() + { + $form = $this->factory->create('form', null, array('max_length' => 10)); + $view = $form->createView(); + + $this->assertSame(10, $view->vars['max_length']); + } + + public function testSubmitWithEmptyDataCreatesObjectIfClassAvailable() + { + $builder = $this->factory->createBuilder('form', null, array( + 'data_class' => 'Symfony\Component\Form\Tests\Fixtures\Author', + 'required' => false, + )); + $builder->add('firstName', 'text'); + $builder->add('lastName', 'text'); + $form = $builder->getForm(); + + $form->setData(null); + // partially empty, still an object is created + $form->submit(array('firstName' => 'Bernhard', 'lastName' => '')); + + $author = new Author(); + $author->firstName = 'Bernhard'; + $author->setLastName(''); + + $this->assertEquals($author, $form->getData()); + } + + public function testSubmitWithEmptyDataCreatesObjectIfInitiallySubmittedWithObject() + { + $builder = $this->factory->createBuilder('form', null, array( + // data class is inferred from the passed object + 'data' => new Author(), + 'required' => false, + )); + $builder->add('firstName', 'text'); + $builder->add('lastName', 'text'); + $form = $builder->getForm(); + + $form->setData(null); + // partially empty, still an object is created + $form->submit(array('firstName' => 'Bernhard', 'lastName' => '')); + + $author = new Author(); + $author->firstName = 'Bernhard'; + $author->setLastName(''); + + $this->assertEquals($author, $form->getData()); + } + + public function testSubmitWithEmptyDataCreatesArrayIfDataClassIsNull() + { + $builder = $this->factory->createBuilder('form', null, array( + 'data_class' => null, + 'required' => false, + )); + $builder->add('firstName', 'text'); + $form = $builder->getForm(); + + $form->setData(null); + $form->submit(array('firstName' => 'Bernhard')); + + $this->assertSame(array('firstName' => 'Bernhard'), $form->getData()); + } + + public function testSubmitEmptyWithEmptyDataCreatesNoObjectIfNotRequired() + { + $builder = $this->factory->createBuilder('form', null, array( + 'data_class' => 'Symfony\Component\Form\Tests\Fixtures\Author', + 'required' => false, + )); + $builder->add('firstName', 'text'); + $builder->add('lastName', 'text'); + $form = $builder->getForm(); + + $form->setData(null); + $form->submit(array('firstName' => '', 'lastName' => '')); + + $this->assertNull($form->getData()); + } + + public function testSubmitEmptyWithEmptyDataCreatesObjectIfRequired() + { + $builder = $this->factory->createBuilder('form', null, array( + 'data_class' => 'Symfony\Component\Form\Tests\Fixtures\Author', + 'required' => true, + )); + $builder->add('firstName', 'text'); + $builder->add('lastName', 'text'); + $form = $builder->getForm(); + + $form->setData(null); + $form->submit(array('firstName' => '', 'lastName' => '')); + + $this->assertEquals(new Author(), $form->getData()); + } + + /* + * We need something to write the field values into + */ + public function testSubmitWithEmptyDataStoresArrayIfNoClassAvailable() + { + $form = $this->factory->createBuilder('form') + ->add('firstName', 'text') + ->getForm(); + + $form->setData(null); + $form->submit(array('firstName' => 'Bernhard')); + + $this->assertSame(array('firstName' => 'Bernhard'), $form->getData()); + } + + public function testSubmitWithEmptyDataPassesEmptyStringToTransformerIfNotCompound() + { + $form = $this->factory->createBuilder('form') + ->addViewTransformer(new FixedDataTransformer(array( + // required for the initial, internal setData(null) + null => 'null', + // required to test that submit(null) is converted to '' + 'empty' => '', + ))) + ->setCompound(false) + ->getForm(); + + $form->submit(null); + + $this->assertSame('empty', $form->getData()); + } + + public function testSubmitWithEmptyDataUsesEmptyDataOption() + { + $author = new Author(); + + $builder = $this->factory->createBuilder('form', null, array( + 'data_class' => 'Symfony\Component\Form\Tests\Fixtures\Author', + 'empty_data' => $author, + )); + $builder->add('firstName', 'text'); + $form = $builder->getForm(); + + $form->submit(array('firstName' => 'Bernhard')); + + $this->assertSame($author, $form->getData()); + $this->assertEquals('Bernhard', $author->firstName); + } + + public function provideZeros() + { + return array( + array(0, '0'), + array('0', '0'), + array('00000', '00000'), + ); + } + + /** + * @dataProvider provideZeros + * @see https://github.com/symfony/symfony/issues/1986 + */ + public function testSetDataThroughParamsWithZero($data, $dataAsString) + { + $form = $this->factory->create('form', null, array( + 'data' => $data, + 'compound' => false, + )); + $view = $form->createView(); + + $this->assertFalse($form->isEmpty()); + + $this->assertSame($dataAsString, $view->vars['value']); + $this->assertSame($dataAsString, $form->getData()); + } + + /** + * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException + */ + public function testAttributesException() + { + $this->factory->create('form', null, array('attr' => '')); + } + + public function testNameCanBeEmptyString() + { + $form = $this->factory->createNamed('', 'form'); + + $this->assertEquals('', $form->getName()); + } + + public function testSubformDoesntCallSetters() + { + $author = new FormTest_AuthorWithoutRefSetter(new Author()); + + $builder = $this->factory->createBuilder('form', $author); + $builder->add('reference', 'form', array( + 'data_class' => 'Symfony\Component\Form\Tests\Fixtures\Author', + )); + $builder->get('reference')->add('firstName', 'text'); + $form = $builder->getForm(); + + $form->submit(array( + // reference has a getter, but not setter + 'reference' => array( + 'firstName' => 'Foo', + ) + )); + + $this->assertEquals('Foo', $author->getReference()->firstName); + } + + public function testSubformCallsSettersIfTheObjectChanged() + { + // no reference + $author = new FormTest_AuthorWithoutRefSetter(null); + $newReference = new Author(); + + $builder = $this->factory->createBuilder('form', $author); + $builder->add('referenceCopy', 'form', array( + 'data_class' => 'Symfony\Component\Form\Tests\Fixtures\Author', + )); + $builder->get('referenceCopy')->add('firstName', 'text'); + $form = $builder->getForm(); + + $form['referenceCopy']->setData($newReference); // new author object + + $form->submit(array( + // referenceCopy has a getter that returns a copy + 'referenceCopy' => array( + 'firstName' => 'Foo', + ) + )); + + $this->assertEquals('Foo', $author->getReferenceCopy()->firstName); + } + + public function testSubformCallsSettersIfByReferenceIsFalse() + { + $author = new FormTest_AuthorWithoutRefSetter(new Author()); + + $builder = $this->factory->createBuilder('form', $author); + $builder->add('referenceCopy', 'form', array( + 'data_class' => 'Symfony\Component\Form\Tests\Fixtures\Author', + 'by_reference' => false + )); + $builder->get('referenceCopy')->add('firstName', 'text'); + $form = $builder->getForm(); + + $form->submit(array( + // referenceCopy has a getter that returns a copy + 'referenceCopy' => array( + 'firstName' => 'Foo', + ) + )); + + // firstName can only be updated if setReferenceCopy() was called + $this->assertEquals('Foo', $author->getReferenceCopy()->firstName); + } + + public function testSubformCallsSettersIfReferenceIsScalar() + { + $author = new FormTest_AuthorWithoutRefSetter('scalar'); + + $builder = $this->factory->createBuilder('form', $author); + $builder->add('referenceCopy', 'form'); + $builder->get('referenceCopy')->addViewTransformer(new CallbackTransformer( + function () {}, + function ($value) { // reverseTransform + + return 'foobar'; + } + )); + $form = $builder->getForm(); + + $form->submit(array( + 'referenceCopy' => array(), // doesn't matter actually + )); + + // firstName can only be updated if setReferenceCopy() was called + $this->assertEquals('foobar', $author->getReferenceCopy()); + } + + public function testSubformAlwaysInsertsIntoArrays() + { + $ref1 = new Author(); + $ref2 = new Author(); + $author = array('referenceCopy' => $ref1); + + $builder = $this->factory->createBuilder('form'); + $builder->setData($author); + $builder->add('referenceCopy', 'form'); + $builder->get('referenceCopy')->addViewTransformer(new CallbackTransformer( + function () {}, + function ($value) use ($ref2) { // reverseTransform + + return $ref2; + } + )); + $form = $builder->getForm(); + + $form->submit(array( + 'referenceCopy' => array('a' => 'b'), // doesn't matter actually + )); + + // the new reference was inserted into the array + $author = $form->getData(); + $this->assertSame($ref2, $author['referenceCopy']); + } + + public function testPassMultipartTrueIfAnyChildIsMultipartToView() + { + $view = $this->factory->createBuilder('form') + ->add('foo', 'text') + ->add('bar', 'file') + ->getForm() + ->createView(); + + $this->assertTrue($view->vars['multipart']); + } + + public function testViewIsNotRenderedByDefault() + { + $view = $this->factory->createBuilder('form') + ->add('foo', 'form') + ->getForm() + ->createView(); + + $this->assertFalse($view->isRendered()); + } + + public function testErrorBubblingIfCompound() + { + $form = $this->factory->create('form', null, array( + 'compound' => true, + )); + + $this->assertTrue($form->getConfig()->getErrorBubbling()); + } + + public function testNoErrorBubblingIfNotCompound() + { + $form = $this->factory->create('form', null, array( + 'compound' => false, + )); + + $this->assertFalse($form->getConfig()->getErrorBubbling()); + } + + public function testOverrideErrorBubbling() + { + $form = $this->factory->create('form', null, array( + 'compound' => false, + 'error_bubbling' => true, + )); + + $this->assertTrue($form->getConfig()->getErrorBubbling()); + } + + public function testPropertyPath() + { + $form = $this->factory->create('form', null, array( + 'property_path' => 'foo', + )); + + $this->assertEquals(new PropertyPath('foo'), $form->getPropertyPath()); + $this->assertTrue($form->getConfig()->getMapped()); + } + + public function testPropertyPathNullImpliesDefault() + { + $form = $this->factory->createNamed('name', 'form', null, array( + 'property_path' => null, + )); + + $this->assertEquals(new PropertyPath('name'), $form->getPropertyPath()); + $this->assertTrue($form->getConfig()->getMapped()); + } + + public function testNotMapped() + { + $form = $this->factory->create('form', null, array( + 'property_path' => 'foo', + 'mapped' => false, + )); + + $this->assertEquals(new PropertyPath('foo'), $form->getPropertyPath()); + $this->assertFalse($form->getConfig()->getMapped()); + } + + public function testViewValidNotSubmitted() + { + $form = $this->factory->create('form'); + $view = $form->createView(); + $this->assertTrue($view->vars['valid']); + } + + public function testViewNotValidSubmitted() + { + $form = $this->factory->create('form'); + $form->submit(array()); + $form->addError(new FormError('An error')); + $view = $form->createView(); + $this->assertFalse($view->vars['valid']); + } + + public function testDataOptionSupersedesSetDataCalls() + { + $form = $this->factory->create('form', null, array( + 'data' => 'default', + 'compound' => false, + )); + + $form->setData('foobar'); + + $this->assertSame('default', $form->getData()); + } + + public function testNormDataIsPassedToView() + { + $view = $this->factory->createBuilder('form') + ->addViewTransformer(new FixedDataTransformer(array( + 'foo' => 'bar', + ))) + ->setData('foo') + ->getForm() + ->createView(); + + $this->assertSame('foo', $view->vars['data']); + $this->assertSame('bar', $view->vars['value']); + } + + // https://github.com/symfony/symfony/issues/6862 + public function testPassZeroLabelToView() + { + $view = $this->factory->create('form', null, array( + 'label' => '0' + )) + ->createView(); + + $this->assertSame('0', $view->vars['label']); + } + + protected function getTestedType() + { + return 'form'; + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/IntegerTypeTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/IntegerTypeTest.php new file mode 100644 index 00000000..998bbe01 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/IntegerTypeTest.php @@ -0,0 +1,34 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Core\Type; + +use Symfony\Component\Intl\Util\IntlTestHelper; + +class IntegerTypeTest extends TypeTestCase +{ + protected function setUp() + { + IntlTestHelper::requireIntl($this); + + parent::setUp(); + } + + public function testSubmitCastsToInteger() + { + $form = $this->factory->create('integer'); + + $form->submit('1.678'); + + $this->assertSame(1, $form->getData()); + $this->assertSame('1', $form->getViewData()); + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/LanguageTypeTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/LanguageTypeTest.php new file mode 100644 index 00000000..24434b21 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/LanguageTypeTest.php @@ -0,0 +1,47 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Core\Type; + +use Symfony\Component\Form\Extension\Core\View\ChoiceView; +use Symfony\Component\Intl\Util\IntlTestHelper; + +class LanguageTypeTest extends TypeTestCase +{ + protected function setUp() + { + IntlTestHelper::requireIntl($this); + + parent::setUp(); + } + + public function testCountriesAreSelectable() + { + $form = $this->factory->create('language'); + $view = $form->createView(); + $choices = $view->vars['choices']; + + $this->assertContains(new ChoiceView('en', 'en', 'English'), $choices, '', false, false); + $this->assertContains(new ChoiceView('en_GB', 'en_GB', 'British English'), $choices, '', false, false); + $this->assertContains(new ChoiceView('en_US', 'en_US', 'U.S. English'), $choices, '', false, false); + $this->assertContains(new ChoiceView('fr', 'fr', 'French'), $choices, '', false, false); + $this->assertContains(new ChoiceView('my', 'my', 'Burmese'), $choices, '', false, false); + } + + public function testMultipleLanguagesIsNotIncluded() + { + $form = $this->factory->create('language', 'language'); + $view = $form->createView(); + $choices = $view->vars['choices']; + + $this->assertNotContains(new ChoiceView('mul', 'mul', 'Mehrsprachig'), $choices, '', false, false); + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/LocaleTypeTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/LocaleTypeTest.php new file mode 100644 index 00000000..e402cb4b --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/LocaleTypeTest.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Core\Type; + +use Symfony\Component\Form\Extension\Core\View\ChoiceView; +use Symfony\Component\Intl\Util\IntlTestHelper; + +class LocaleTypeTest extends TypeTestCase +{ + protected function setUp() + { + IntlTestHelper::requireIntl($this); + + parent::setUp(); + } + + public function testLocalesAreSelectable() + { + $form = $this->factory->create('locale'); + $view = $form->createView(); + $choices = $view->vars['choices']; + + $this->assertContains(new ChoiceView('en', 'en', 'English'), $choices, '', false, false); + $this->assertContains(new ChoiceView('en_GB', 'en_GB', 'English (United Kingdom)'), $choices, '', false, false); + $this->assertContains(new ChoiceView('zh_Hant_MO', 'zh_Hant_MO', 'Chinese (Traditional, Macau SAR China)'), $choices, '', false, false); + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/MoneyTypeTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/MoneyTypeTest.php new file mode 100644 index 00000000..97fc37fa --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/MoneyTypeTest.php @@ -0,0 +1,59 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Core\Type; + +use Symfony\Component\Intl\Util\IntlTestHelper; + +class MoneyTypeTest extends TypeTestCase +{ + protected function setUp() + { + // we test against different locales, so we need the full + // implementation + IntlTestHelper::requireFullIntl($this); + + parent::setUp(); + } + + public function testPassMoneyPatternToView() + { + \Locale::setDefault('de_DE'); + + $form = $this->factory->create('money'); + $view = $form->createView(); + + $this->assertSame('{{ widget }} €', $view->vars['money_pattern']); + } + + public function testMoneyPatternWorksForYen() + { + \Locale::setDefault('en_US'); + + $form = $this->factory->create('money', null, array('currency' => 'JPY')); + $view = $form->createView(); + $this->assertTrue((Boolean) strstr($view->vars['money_pattern'], '¥')); + } + + // https://github.com/symfony/symfony/issues/5458 + public function testPassDifferentPatternsForDifferentCurrencies() + { + \Locale::setDefault('de_DE'); + + $form1 = $this->factory->create('money', null, array('currency' => 'GBP')); + $form2 = $this->factory->create('money', null, array('currency' => 'EUR')); + $view1 = $form1->createView(); + $view2 = $form2->createView(); + + $this->assertSame('{{ widget }} £', $view1->vars['money_pattern']); + $this->assertSame('{{ widget }} €', $view2->vars['money_pattern']); + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/NumberTypeTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/NumberTypeTest.php new file mode 100644 index 00000000..e5b3dd74 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/NumberTypeTest.php @@ -0,0 +1,63 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Core\Type; + +use Symfony\Component\Intl\Util\IntlTestHelper; + +class NumberTypeTest extends TypeTestCase +{ + protected function setUp() + { + parent::setUp(); + + // we test against "de_DE", so we need the full implementation + IntlTestHelper::requireFullIntl($this); + + \Locale::setDefault('de_DE'); + } + + public function testDefaultFormatting() + { + $form = $this->factory->create('number'); + $form->setData('12345.67890'); + $view = $form->createView(); + + $this->assertSame('12345,679', $view->vars['value']); + } + + public function testDefaultFormattingWithGrouping() + { + $form = $this->factory->create('number', null, array('grouping' => true)); + $form->setData('12345.67890'); + $view = $form->createView(); + + $this->assertSame('12.345,679', $view->vars['value']); + } + + public function testDefaultFormattingWithPrecision() + { + $form = $this->factory->create('number', null, array('precision' => 2)); + $form->setData('12345.67890'); + $view = $form->createView(); + + $this->assertSame('12345,68', $view->vars['value']); + } + + public function testDefaultFormattingWithRounding() + { + $form = $this->factory->create('number', null, array('precision' => 0, 'rounding_mode' => \NumberFormatter::ROUND_UP)); + $form->setData('12345.54321'); + $view = $form->createView(); + + $this->assertSame('12346', $view->vars['value']); + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/PasswordTypeTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/PasswordTypeTest.php new file mode 100644 index 00000000..bccb6f7b --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/PasswordTypeTest.php @@ -0,0 +1,51 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Core\Type; + +class PasswordTypeTest extends \Symfony\Component\Form\Test\TypeTestCase +{ + public function testEmptyIfNotSubmitted() + { + $form = $this->factory->create('password'); + $form->setData('pAs5w0rd'); + $view = $form->createView(); + + $this->assertSame('', $view->vars['value']); + } + + public function testEmptyIfSubmitted() + { + $form = $this->factory->create('password'); + $form->submit('pAs5w0rd'); + $view = $form->createView(); + + $this->assertSame('', $view->vars['value']); + } + + public function testNotEmptyIfSubmittedAndNotAlwaysEmpty() + { + $form = $this->factory->create('password', null, array('always_empty' => false)); + $form->submit('pAs5w0rd'); + $view = $form->createView(); + + $this->assertSame('pAs5w0rd', $view->vars['value']); + } + + public function testNotTrimmed() + { + $form = $this->factory->create('password', null); + $form->submit(' pAs5w0rd '); + $data = $form->getData(); + + $this->assertSame(' pAs5w0rd ', $data); + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/RepeatedTypeTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/RepeatedTypeTest.php new file mode 100644 index 00000000..9e125d78 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/RepeatedTypeTest.php @@ -0,0 +1,149 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Core\Type; + +class RepeatedTypeTest extends \Symfony\Component\Form\Test\TypeTestCase +{ + protected $form; + + protected function setUp() + { + parent::setUp(); + + $this->form = $this->factory->create('repeated', null, array( + 'type' => 'text', + )); + $this->form->setData(null); + } + + public function testSetData() + { + $this->form->setData('foobar'); + + $this->assertEquals('foobar', $this->form['first']->getData()); + $this->assertEquals('foobar', $this->form['second']->getData()); + } + + public function testSetOptions() + { + $form = $this->factory->create('repeated', null, array( + 'type' => 'text', + 'options' => array('label' => 'Global'), + )); + + $this->assertEquals('Global', $form['first']->getConfig()->getOption('label')); + $this->assertEquals('Global', $form['second']->getConfig()->getOption('label')); + $this->assertTrue($form['first']->isRequired()); + $this->assertTrue($form['second']->isRequired()); + } + + public function testSetOptionsPerChild() + { + $form = $this->factory->create('repeated', null, array( + // the global required value cannot be overridden + 'type' => 'text', + 'first_options' => array('label' => 'Test', 'required' => false), + 'second_options' => array('label' => 'Test2') + )); + + $this->assertEquals('Test', $form['first']->getConfig()->getOption('label')); + $this->assertEquals('Test2', $form['second']->getConfig()->getOption('label')); + $this->assertTrue($form['first']->isRequired()); + $this->assertTrue($form['second']->isRequired()); + } + + public function testSetRequired() + { + $form = $this->factory->create('repeated', null, array( + 'required' => false, + 'type' => 'text', + )); + + $this->assertFalse($form['first']->isRequired()); + $this->assertFalse($form['second']->isRequired()); + } + + public function testSetErrorBubblingToTrue() + { + $form = $this->factory->create('repeated', null, array( + 'error_bubbling' => true, + )); + + $this->assertTrue($form->getConfig()->getOption('error_bubbling')); + $this->assertTrue($form['first']->getConfig()->getOption('error_bubbling')); + $this->assertTrue($form['second']->getConfig()->getOption('error_bubbling')); + } + + public function testSetErrorBubblingToFalse() + { + $form = $this->factory->create('repeated', null, array( + 'error_bubbling' => false, + )); + + $this->assertFalse($form->getConfig()->getOption('error_bubbling')); + $this->assertFalse($form['first']->getConfig()->getOption('error_bubbling')); + $this->assertFalse($form['second']->getConfig()->getOption('error_bubbling')); + } + + public function testSetErrorBubblingIndividually() + { + $form = $this->factory->create('repeated', null, array( + 'error_bubbling' => true, + 'options' => array('error_bubbling' => false), + 'second_options' => array('error_bubbling' => true), + )); + + $this->assertTrue($form->getConfig()->getOption('error_bubbling')); + $this->assertFalse($form['first']->getConfig()->getOption('error_bubbling')); + $this->assertTrue($form['second']->getConfig()->getOption('error_bubbling')); + } + + public function testSetOptionsPerChildAndOverwrite() + { + $form = $this->factory->create('repeated', null, array( + 'type' => 'text', + 'options' => array('label' => 'Label'), + 'second_options' => array('label' => 'Second label') + )); + + $this->assertEquals('Label', $form['first']->getConfig()->getOption('label')); + $this->assertEquals('Second label', $form['second']->getConfig()->getOption('label')); + $this->assertTrue($form['first']->isRequired()); + $this->assertTrue($form['second']->isRequired()); + } + + public function testSubmitUnequal() + { + $input = array('first' => 'foo', 'second' => 'bar'); + + $this->form->submit($input); + + $this->assertEquals('foo', $this->form['first']->getViewData()); + $this->assertEquals('bar', $this->form['second']->getViewData()); + $this->assertFalse($this->form->isSynchronized()); + $this->assertEquals($input, $this->form->getViewData()); + $this->assertNull($this->form->getData()); + } + + public function testSubmitEqual() + { + $input = array('first' => 'foo', 'second' => 'foo'); + + $this->form->submit($input); + + $this->assertEquals('foo', $this->form['first']->getViewData()); + $this->assertEquals('foo', $this->form['second']->getViewData()); + $this->assertTrue($this->form->isSynchronized()); + $this->assertEquals($input, $this->form->getViewData()); + $this->assertEquals('foo', $this->form->getData()); + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/SubmitTypeTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/SubmitTypeTest.php new file mode 100644 index 00000000..8cc72281 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/SubmitTypeTest.php @@ -0,0 +1,54 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Core\Type; + +/** + * @author Bernhard Schussek + */ +class SubmitTypeTest extends TypeTestCase +{ + public function testCreateSubmitButtonInstances() + { + $this->assertInstanceOf('Symfony\Component\Form\SubmitButton', $this->factory->create('submit')); + } + + public function testNotClickedByDefault() + { + $button = $this->factory->create('submit'); + + $this->assertFalse($button->isClicked()); + } + + public function testNotClickedIfSubmittedWithNull() + { + $button = $this->factory->create('submit'); + $button->submit(null); + + $this->assertFalse($button->isClicked()); + } + + public function testClickedIfSubmittedWithEmptyString() + { + $button = $this->factory->create('submit'); + $button->submit(''); + + $this->assertTrue($button->isClicked()); + } + + public function testClickedIfSubmittedWithUnemptyString() + { + $button = $this->factory->create('submit'); + $button->submit('foo'); + + $this->assertTrue($button->isClicked()); + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/TimeTypeTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/TimeTypeTest.php new file mode 100644 index 00000000..9bdfe156 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/TimeTypeTest.php @@ -0,0 +1,649 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Core\Type; + +use Symfony\Component\Form\Extension\Core\View\ChoiceView; +use Symfony\Component\Form\FormError; +use Symfony\Component\Intl\Util\IntlTestHelper; + +class TimeTypeTest extends TypeTestCase +{ + protected function setUp() + { + IntlTestHelper::requireIntl($this); + + parent::setUp(); + } + + public function testSubmitDateTime() + { + $form = $this->factory->create('time', null, array( + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', + 'input' => 'datetime', + )); + + $input = array( + 'hour' => '3', + 'minute' => '4', + ); + + $form->submit($input); + + $dateTime = new \DateTime('1970-01-01 03:04:00 UTC'); + + $this->assertEquals($dateTime, $form->getData()); + $this->assertEquals($input, $form->getViewData()); + } + + public function testSubmitString() + { + $form = $this->factory->create('time', null, array( + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', + 'input' => 'string', + )); + + $input = array( + 'hour' => '3', + 'minute' => '4', + ); + + $form->submit($input); + + $this->assertEquals('03:04:00', $form->getData()); + $this->assertEquals($input, $form->getViewData()); + } + + public function testSubmitTimestamp() + { + $form = $this->factory->create('time', null, array( + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', + 'input' => 'timestamp', + )); + + $input = array( + 'hour' => '3', + 'minute' => '4', + ); + + $form->submit($input); + + $dateTime = new \DateTime('1970-01-01 03:04:00 UTC'); + + $this->assertEquals($dateTime->format('U'), $form->getData()); + $this->assertEquals($input, $form->getViewData()); + } + + public function testSubmitArray() + { + $form = $this->factory->create('time', null, array( + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', + 'input' => 'array', + )); + + $input = array( + 'hour' => '3', + 'minute' => '4', + ); + + $form->submit($input); + + $this->assertEquals($input, $form->getData()); + $this->assertEquals($input, $form->getViewData()); + } + + public function testSubmitDatetimeSingleText() + { + $form = $this->factory->create('time', null, array( + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', + 'input' => 'datetime', + 'widget' => 'single_text', + )); + + $form->submit('03:04'); + + $this->assertEquals(new \DateTime('1970-01-01 03:04:00 UTC'), $form->getData()); + $this->assertEquals('03:04', $form->getViewData()); + } + + public function testSubmitDatetimeSingleTextWithoutMinutes() + { + $form = $this->factory->create('time', null, array( + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', + 'input' => 'datetime', + 'widget' => 'single_text', + 'with_minutes' => false, + )); + + $form->submit('03'); + + $this->assertEquals(new \DateTime('1970-01-01 03:00:00 UTC'), $form->getData()); + $this->assertEquals('03', $form->getViewData()); + } + + public function testSubmitArraySingleText() + { + $form = $this->factory->create('time', null, array( + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', + 'input' => 'array', + 'widget' => 'single_text', + )); + + $data = array( + 'hour' => '3', + 'minute' => '4', + ); + + $form->submit('03:04'); + + $this->assertEquals($data, $form->getData()); + $this->assertEquals('03:04', $form->getViewData()); + } + + public function testSubmitArraySingleTextWithoutMinutes() + { + $form = $this->factory->create('time', null, array( + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', + 'input' => 'array', + 'widget' => 'single_text', + 'with_minutes' => false, + )); + + $data = array( + 'hour' => '3', + ); + + $form->submit('03'); + + $this->assertEquals($data, $form->getData()); + $this->assertEquals('03', $form->getViewData()); + } + + public function testSubmitArraySingleTextWithSeconds() + { + $form = $this->factory->create('time', null, array( + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', + 'input' => 'array', + 'widget' => 'single_text', + 'with_seconds' => true, + )); + + $data = array( + 'hour' => '3', + 'minute' => '4', + 'second' => '5', + ); + + $form->submit('03:04:05'); + + $this->assertEquals($data, $form->getData()); + $this->assertEquals('03:04:05', $form->getViewData()); + } + + public function testSubmitStringSingleText() + { + $form = $this->factory->create('time', null, array( + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', + 'input' => 'string', + 'widget' => 'single_text', + )); + + $form->submit('03:04'); + + $this->assertEquals('03:04:00', $form->getData()); + $this->assertEquals('03:04', $form->getViewData()); + } + + public function testSubmitStringSingleTextWithoutMinutes() + { + $form = $this->factory->create('time', null, array( + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', + 'input' => 'string', + 'widget' => 'single_text', + 'with_minutes' => false, + )); + + $form->submit('03'); + + $this->assertEquals('03:00:00', $form->getData()); + $this->assertEquals('03', $form->getViewData()); + } + + public function testSetDataWithoutMinutes() + { + $form = $this->factory->create('time', null, array( + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', + 'input' => 'datetime', + 'with_minutes' => false, + )); + + $form->setData(new \DateTime('03:04:05 UTC')); + + $this->assertEquals(array('hour' => 3), $form->getViewData()); + } + + public function testSetDataWithSeconds() + { + $form = $this->factory->create('time', null, array( + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', + 'input' => 'datetime', + 'with_seconds' => true, + )); + + $form->setData(new \DateTime('03:04:05 UTC')); + + $this->assertEquals(array('hour' => 3, 'minute' => 4, 'second' => 5), $form->getViewData()); + } + + public function testSetDataDifferentTimezones() + { + $form = $this->factory->create('time', null, array( + 'model_timezone' => 'America/New_York', + 'view_timezone' => 'Asia/Hong_Kong', + 'input' => 'string', + 'with_seconds' => true, + )); + + $dateTime = new \DateTime('2013-01-01 12:04:05'); + $dateTime->setTimezone(new \DateTimeZone('America/New_York')); + + $form->setData($dateTime->format('H:i:s')); + + $outputTime = clone $dateTime; + $outputTime->setTimezone(new \DateTimeZone('Asia/Hong_Kong')); + + $displayedData = array( + 'hour' => (int) $outputTime->format('H'), + 'minute' => (int) $outputTime->format('i'), + 'second' => (int) $outputTime->format('s') + ); + + $this->assertEquals($displayedData, $form->getViewData()); + } + + public function testSetDataDifferentTimezonesDateTime() + { + $form = $this->factory->create('time', null, array( + 'model_timezone' => 'America/New_York', + 'view_timezone' => 'Asia/Hong_Kong', + 'input' => 'datetime', + 'with_seconds' => true, + )); + + $dateTime = new \DateTime('12:04:05'); + $dateTime->setTimezone(new \DateTimeZone('America/New_York')); + + $form->setData($dateTime); + + $outputTime = clone $dateTime; + $outputTime->setTimezone(new \DateTimeZone('Asia/Hong_Kong')); + + $displayedData = array( + 'hour' => (int) $outputTime->format('H'), + 'minute' => (int) $outputTime->format('i'), + 'second' => (int) $outputTime->format('s') + ); + + $this->assertDateTimeEquals($dateTime, $form->getData()); + $this->assertEquals($displayedData, $form->getViewData()); + } + + public function testHoursOption() + { + $form = $this->factory->create('time', null, array( + 'hours' => array(6, 7), + )); + + $view = $form->createView(); + + $this->assertEquals(array( + new ChoiceView('6', '6', '06'), + new ChoiceView('7', '7', '07'), + ), $view['hour']->vars['choices']); + } + + public function testIsMinuteWithinRangeReturnsTrueIfWithin() + { + $form = $this->factory->create('time', null, array( + 'minutes' => array(6, 7), + )); + + $view = $form->createView(); + + $this->assertEquals(array( + new ChoiceView('6', '6', '06'), + new ChoiceView('7', '7', '07'), + ), $view['minute']->vars['choices']); + } + + public function testIsSecondWithinRangeReturnsTrueIfWithin() + { + $form = $this->factory->create('time', null, array( + 'seconds' => array(6, 7), + 'with_seconds' => true, + )); + + $view = $form->createView(); + + $this->assertEquals(array( + new ChoiceView('6', '6', '06'), + new ChoiceView('7', '7', '07'), + ), $view['second']->vars['choices']); + } + + public function testIsPartiallyFilledReturnsFalseIfCompletelyEmpty() + { + $this->markTestIncomplete('Needs to be reimplemented using validators'); + + $form = $this->factory->create('time', null, array( + 'widget' => 'choice', + )); + + $form->submit(array( + 'hour' => '', + 'minute' => '', + )); + + $this->assertFalse($form->isPartiallyFilled()); + } + + public function testIsPartiallyFilledReturnsFalseIfCompletelyEmptyWithSeconds() + { + $this->markTestIncomplete('Needs to be reimplemented using validators'); + + $form = $this->factory->create('time', null, array( + 'widget' => 'choice', + 'with_seconds' => true, + )); + + $form->submit(array( + 'hour' => '', + 'minute' => '', + 'second' => '', + )); + + $this->assertFalse($form->isPartiallyFilled()); + } + + public function testIsPartiallyFilledReturnsFalseIfCompletelyFilled() + { + $this->markTestIncomplete('Needs to be reimplemented using validators'); + + $form = $this->factory->create('time', null, array( + 'widget' => 'choice', + )); + + $form->submit(array( + 'hour' => '0', + 'minute' => '0', + )); + + $this->assertFalse($form->isPartiallyFilled()); + } + + public function testIsPartiallyFilledReturnsFalseIfCompletelyFilledWithSeconds() + { + $this->markTestIncomplete('Needs to be reimplemented using validators'); + + $form = $this->factory->create('time', null, array( + 'widget' => 'choice', + 'with_seconds' => true, + )); + + $form->submit(array( + 'hour' => '0', + 'minute' => '0', + 'second' => '0', + )); + + $this->assertFalse($form->isPartiallyFilled()); + } + + public function testIsPartiallyFilledReturnsTrueIfChoiceAndHourEmpty() + { + $this->markTestIncomplete('Needs to be reimplemented using validators'); + + $form = $this->factory->create('time', null, array( + 'widget' => 'choice', + 'with_seconds' => true, + )); + + $form->submit(array( + 'hour' => '', + 'minute' => '0', + 'second' => '0', + )); + + $this->assertTrue($form->isPartiallyFilled()); + } + + public function testIsPartiallyFilledReturnsTrueIfChoiceAndMinuteEmpty() + { + $this->markTestIncomplete('Needs to be reimplemented using validators'); + + $form = $this->factory->create('time', null, array( + 'widget' => 'choice', + 'with_seconds' => true, + )); + + $form->submit(array( + 'hour' => '0', + 'minute' => '', + 'second' => '0', + )); + + $this->assertTrue($form->isPartiallyFilled()); + } + + public function testIsPartiallyFilledReturnsTrueIfChoiceAndSecondsEmpty() + { + $this->markTestIncomplete('Needs to be reimplemented using validators'); + + $form = $this->factory->create('time', null, array( + 'widget' => 'choice', + 'with_seconds' => true, + )); + + $form->submit(array( + 'hour' => '0', + 'minute' => '0', + 'second' => '', + )); + + $this->assertTrue($form->isPartiallyFilled()); + } + + // Bug fix + public function testInitializeWithDateTime() + { + // Throws an exception if "data_class" option is not explicitly set + // to null in the type + $this->factory->create('time', new \DateTime()); + } + + public function testSingleTextWidgetShouldUseTheRightInputType() + { + $form = $this->factory->create('time', null, array( + 'widget' => 'single_text', + )); + + $view = $form->createView(); + $this->assertEquals('time', $view->vars['type']); + } + + public function testPassDefaultEmptyValueToViewIfNotRequired() + { + $form = $this->factory->create('time', null, array( + 'required' => false, + 'with_seconds' => true, + )); + + $view = $form->createView(); + $this->assertSame('', $view['hour']->vars['empty_value']); + $this->assertSame('', $view['minute']->vars['empty_value']); + $this->assertSame('', $view['second']->vars['empty_value']); + } + + public function testPassNoEmptyValueToViewIfRequired() + { + $form = $this->factory->create('time', null, array( + 'required' => true, + 'with_seconds' => true, + )); + + $view = $form->createView(); + $this->assertNull($view['hour']->vars['empty_value']); + $this->assertNull($view['minute']->vars['empty_value']); + $this->assertNull($view['second']->vars['empty_value']); + } + + public function testPassEmptyValueAsString() + { + $form = $this->factory->create('time', null, array( + 'empty_value' => 'Empty', + 'with_seconds' => true, + )); + + $view = $form->createView(); + $this->assertSame('Empty', $view['hour']->vars['empty_value']); + $this->assertSame('Empty', $view['minute']->vars['empty_value']); + $this->assertSame('Empty', $view['second']->vars['empty_value']); + } + + public function testPassEmptyValueAsArray() + { + $form = $this->factory->create('time', null, array( + 'empty_value' => array( + 'hour' => 'Empty hour', + 'minute' => 'Empty minute', + 'second' => 'Empty second', + ), + 'with_seconds' => true, + )); + + $view = $form->createView(); + $this->assertSame('Empty hour', $view['hour']->vars['empty_value']); + $this->assertSame('Empty minute', $view['minute']->vars['empty_value']); + $this->assertSame('Empty second', $view['second']->vars['empty_value']); + } + + public function testPassEmptyValueAsPartialArrayAddEmptyIfNotRequired() + { + $form = $this->factory->create('time', null, array( + 'required' => false, + 'empty_value' => array( + 'hour' => 'Empty hour', + 'second' => 'Empty second', + ), + 'with_seconds' => true, + )); + + $view = $form->createView(); + $this->assertSame('Empty hour', $view['hour']->vars['empty_value']); + $this->assertSame('', $view['minute']->vars['empty_value']); + $this->assertSame('Empty second', $view['second']->vars['empty_value']); + } + + public function testPassEmptyValueAsPartialArrayAddNullIfRequired() + { + $form = $this->factory->create('time', null, array( + 'required' => true, + 'empty_value' => array( + 'hour' => 'Empty hour', + 'second' => 'Empty second', + ), + 'with_seconds' => true, + )); + + $view = $form->createView(); + $this->assertSame('Empty hour', $view['hour']->vars['empty_value']); + $this->assertNull($view['minute']->vars['empty_value']); + $this->assertSame('Empty second', $view['second']->vars['empty_value']); + } + + public function provideCompoundWidgets() + { + return array( + array('text'), + array('choice'), + ); + } + + /** + * @dataProvider provideCompoundWidgets + */ + public function testHourErrorsBubbleUp($widget) + { + $error = new FormError('Invalid!'); + $form = $this->factory->create('time', null, array( + 'widget' => $widget, + )); + $form['hour']->addError($error); + + $this->assertSame(array(), $form['hour']->getErrors()); + $this->assertSame(array($error), $form->getErrors()); + } + + /** + * @dataProvider provideCompoundWidgets + */ + public function testMinuteErrorsBubbleUp($widget) + { + $error = new FormError('Invalid!'); + $form = $this->factory->create('time', null, array( + 'widget' => $widget, + )); + $form['minute']->addError($error); + + $this->assertSame(array(), $form['minute']->getErrors()); + $this->assertSame(array($error), $form->getErrors()); + } + + /** + * @dataProvider provideCompoundWidgets + */ + public function testSecondErrorsBubbleUp($widget) + { + $error = new FormError('Invalid!'); + $form = $this->factory->create('time', null, array( + 'widget' => $widget, + 'with_seconds' => true, + )); + $form['second']->addError($error); + + $this->assertSame(array(), $form['second']->getErrors()); + $this->assertSame(array($error), $form->getErrors()); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\InvalidConfigurationException + */ + public function testInitializeWithSecondsAndWithoutMinutes() + { + $this->factory->create('time', null, array( + 'with_minutes' => false, + 'with_seconds' => true, + )); + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/TimezoneTypeTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/TimezoneTypeTest.php new file mode 100644 index 00000000..81df20cb --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/TimezoneTypeTest.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Core\Type; + +use Symfony\Component\Form\Extension\Core\View\ChoiceView; + +class TimezoneTypeTest extends \Symfony\Component\Form\Test\TypeTestCase +{ + public function testTimezonesAreSelectable() + { + $form = $this->factory->create('timezone'); + $view = $form->createView(); + $choices = $view->vars['choices']; + + $this->assertArrayHasKey('Africa', $choices); + $this->assertContains(new ChoiceView('Africa/Kinshasa', 'Africa/Kinshasa', 'Kinshasa'), $choices['Africa'], '', false, false); + + $this->assertArrayHasKey('America', $choices); + $this->assertContains(new ChoiceView('America/New_York', 'America/New_York', 'New York'), $choices['America'], '', false, false); + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/TypeTestCase.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/TypeTestCase.php new file mode 100644 index 00000000..733546e3 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/TypeTestCase.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Core\Type; + +use Symfony\Component\Form\Test\TypeTestCase as BaseTypeTestCase; + +/** + * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use Symfony\Component\Form\Test\TypeTestCase instead. + */ +abstract class TypeTestCase extends BaseTypeTestCase +{ +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/UrlTypeTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/UrlTypeTest.php new file mode 100644 index 00000000..254b2a8e --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Core/Type/UrlTypeTest.php @@ -0,0 +1,61 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Core\Type; + +class UrlTypeTest extends TypeTestCase +{ + public function testSubmitAddsDefaultProtocolIfNoneIsIncluded() + { + $form = $this->factory->create('url', 'name'); + + $form->submit('www.domain.com'); + + $this->assertSame('http://www.domain.com', $form->getData()); + $this->assertSame('http://www.domain.com', $form->getViewData()); + } + + public function testSubmitAddsNoDefaultProtocolIfAlreadyIncluded() + { + $form = $this->factory->create('url', null, array( + 'default_protocol' => 'http', + )); + + $form->submit('ftp://www.domain.com'); + + $this->assertSame('ftp://www.domain.com', $form->getData()); + $this->assertSame('ftp://www.domain.com', $form->getViewData()); + } + + public function testSubmitAddsNoDefaultProtocolIfEmpty() + { + $form = $this->factory->create('url', null, array( + 'default_protocol' => 'http', + )); + + $form->submit(''); + + $this->assertNull($form->getData()); + $this->assertSame('', $form->getViewData()); + } + + public function testSubmitAddsNoDefaultProtocolIfSetToNull() + { + $form = $this->factory->create('url', null, array( + 'default_protocol' => null, + )); + + $form->submit('www.domain.com'); + + $this->assertSame('www.domain.com', $form->getData()); + $this->assertSame('www.domain.com', $form->getViewData()); + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Csrf/CsrfProvider/DefaultCsrfProviderTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Csrf/CsrfProvider/DefaultCsrfProviderTest.php new file mode 100644 index 00000000..a99b5444 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Csrf/CsrfProvider/DefaultCsrfProviderTest.php @@ -0,0 +1,81 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Csrf\CsrfProvider; + +use Symfony\Component\Form\Extension\Csrf\CsrfProvider\DefaultCsrfProvider; + +/** + * @runTestsInSeparateProcesses + */ +class DefaultCsrfProviderTest extends \PHPUnit_Framework_TestCase +{ + protected $provider; + + public static function setUpBeforeClass() + { + ini_set('session.save_handler', 'files'); + ini_set('session.save_path', sys_get_temp_dir()); + } + + protected function setUp() + { + $this->provider = new DefaultCsrfProvider('SECRET'); + } + + protected function tearDown() + { + $this->provider = null; + } + + public function testGenerateCsrfToken() + { + session_start(); + + $token = $this->provider->generateCsrfToken('foo'); + + $this->assertEquals(sha1('SECRET'.'foo'.session_id()), $token); + } + + public function testGenerateCsrfTokenOnUnstartedSession() + { + session_id('touti'); + + if (!version_compare(PHP_VERSION, '5.4', '>=')) { + $this->markTestSkipped('This test requires PHP >= 5.4'); + } + + $this->assertSame(PHP_SESSION_NONE, session_status()); + + $token = $this->provider->generateCsrfToken('foo'); + + $this->assertEquals(sha1('SECRET'.'foo'.session_id()), $token); + $this->assertSame(PHP_SESSION_ACTIVE, session_status()); + } + + public function testIsCsrfTokenValidSucceeds() + { + session_start(); + + $token = sha1('SECRET'.'foo'.session_id()); + + $this->assertTrue($this->provider->isCsrfTokenValid('foo', $token)); + } + + public function testIsCsrfTokenValidFails() + { + session_start(); + + $token = sha1('SECRET'.'bar'.session_id()); + + $this->assertFalse($this->provider->isCsrfTokenValid('foo', $token)); + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Csrf/CsrfProvider/SessionCsrfProviderTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Csrf/CsrfProvider/SessionCsrfProviderTest.php new file mode 100644 index 00000000..1dcc6b4c --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Csrf/CsrfProvider/SessionCsrfProviderTest.php @@ -0,0 +1,75 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Csrf\CsrfProvider; + +use Symfony\Component\Form\Extension\Csrf\CsrfProvider\SessionCsrfProvider; + +class SessionCsrfProviderTest extends \PHPUnit_Framework_TestCase +{ + protected $provider; + protected $session; + + protected function setUp() + { + if (!class_exists('Symfony\Component\HttpFoundation\Session\Session')) { + $this->markTestSkipped('The "HttpFoundation" component is not available'); + } + + $this->session = $this->getMock( + 'Symfony\Component\HttpFoundation\Session\Session', + array(), + array(), + '', + false // don't call constructor + ); + $this->provider = new SessionCsrfProvider($this->session, 'SECRET'); + } + + protected function tearDown() + { + $this->provider = null; + $this->session = null; + } + + public function testGenerateCsrfToken() + { + $this->session->expects($this->once()) + ->method('getId') + ->will($this->returnValue('ABCDEF')); + + $token = $this->provider->generateCsrfToken('foo'); + + $this->assertEquals(sha1('SECRET'.'foo'.'ABCDEF'), $token); + } + + public function testIsCsrfTokenValidSucceeds() + { + $this->session->expects($this->once()) + ->method('getId') + ->will($this->returnValue('ABCDEF')); + + $token = sha1('SECRET'.'foo'.'ABCDEF'); + + $this->assertTrue($this->provider->isCsrfTokenValid('foo', $token)); + } + + public function testIsCsrfTokenValidFails() + { + $this->session->expects($this->once()) + ->method('getId') + ->will($this->returnValue('ABCDEF')); + + $token = sha1('SECRET'.'bar'.'ABCDEF'); + + $this->assertFalse($this->provider->isCsrfTokenValid('foo', $token)); + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php new file mode 100644 index 00000000..0bcfe74e --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php @@ -0,0 +1,78 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Csrf\EventListener; + +use Symfony\Component\Form\FormBuilder; +use Symfony\Component\Form\FormEvent; +use Symfony\Component\Form\Extension\Csrf\EventListener\CsrfValidationListener; + +class CsrfValidationListenerTest extends \PHPUnit_Framework_TestCase +{ + protected $dispatcher; + protected $factory; + protected $csrfProvider; + + protected function setUp() + { + if (!class_exists('Symfony\Component\EventDispatcher\EventDispatcher')) { + $this->markTestSkipped('The "EventDispatcher" component is not available'); + } + + $this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); + $this->factory = $this->getMock('Symfony\Component\Form\FormFactoryInterface'); + $this->csrfProvider = $this->getMock('Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface'); + $this->form = $this->getBuilder('post') + ->setDataMapper($this->getDataMapper()) + ->getForm(); + } + + protected function tearDown() + { + $this->dispatcher = null; + $this->factory = null; + $this->csrfProvider = null; + $this->form = null; + } + + protected function getBuilder($name = 'name') + { + return new FormBuilder($name, null, $this->dispatcher, $this->factory, array('compound' => true)); + } + + protected function getForm($name = 'name') + { + return $this->getBuilder($name)->getForm(); + } + + protected function getDataMapper() + { + return $this->getMock('Symfony\Component\Form\DataMapperInterface'); + } + + protected function getMockForm() + { + return $this->getMock('Symfony\Component\Form\Test\FormInterface'); + } + + // https://github.com/symfony/symfony/pull/5838 + public function testStringFormData() + { + $data = "XP4HUzmHPi"; + $event = new FormEvent($this->form, $data); + + $validation = new CsrfValidationListener('csrf', $this->csrfProvider, 'unknown', 'Invalid.'); + $validation->preSubmit($event); + + // Validate accordingly + $this->assertSame($data, $event->getData()); + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.php new file mode 100644 index 00000000..0a1f0dc4 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.php @@ -0,0 +1,301 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Csrf\Type; + +use Symfony\Component\Form\AbstractType; +use Symfony\Component\Form\FormBuilderInterface; +use Symfony\Component\Form\FormError; +use Symfony\Component\Form\Test\TypeTestCase; +use Symfony\Component\Form\Extension\Csrf\CsrfExtension; + +class FormTypeCsrfExtensionTest_ChildType extends AbstractType +{ + public function buildForm(FormBuilderInterface $builder, array $options) + { + // The form needs a child in order to trigger CSRF protection by + // default + $builder->add('name', 'text'); + } + + public function getName() + { + return 'csrf_collection_test'; + } +} + +class FormTypeCsrfExtensionTest extends TypeTestCase +{ + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $csrfProvider; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $translator; + + protected function setUp() + { + $this->csrfProvider = $this->getMock('Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface'); + $this->translator = $this->getMock('Symfony\Component\Translation\TranslatorInterface'); + + parent::setUp(); + } + + protected function tearDown() + { + $this->csrfProvider = null; + $this->translator = null; + + parent::tearDown(); + } + + protected function getExtensions() + { + return array_merge(parent::getExtensions(), array( + new CsrfExtension($this->csrfProvider, $this->translator), + )); + } + + public function testCsrfProtectionByDefaultIfRootAndCompound() + { + $view = $this->factory + ->create('form', null, array( + 'csrf_field_name' => 'csrf', + 'compound' => true, + )) + ->createView(); + + $this->assertTrue(isset($view['csrf'])); + } + + public function testNoCsrfProtectionByDefaultIfCompoundButNotRoot() + { + $view = $this->factory + ->createNamedBuilder('root', 'form') + ->add($this->factory + ->createNamedBuilder('form', 'form', null, array( + 'csrf_field_name' => 'csrf', + 'compound' => true, + )) + ) + ->getForm() + ->get('form') + ->createView(); + + $this->assertFalse(isset($view['csrf'])); + } + + public function testNoCsrfProtectionByDefaultIfRootButNotCompound() + { + $view = $this->factory + ->create('form', null, array( + 'csrf_field_name' => 'csrf', + 'compound' => false, + )) + ->createView(); + + $this->assertFalse(isset($view['csrf'])); + } + + public function testCsrfProtectionCanBeDisabled() + { + $view = $this->factory + ->create('form', null, array( + 'csrf_field_name' => 'csrf', + 'csrf_protection' => false, + 'compound' => true, + )) + ->createView(); + + $this->assertFalse(isset($view['csrf'])); + } + + public function testGenerateCsrfToken() + { + $this->csrfProvider->expects($this->once()) + ->method('generateCsrfToken') + ->with('%INTENTION%') + ->will($this->returnValue('token')); + + $view = $this->factory + ->create('form', null, array( + 'csrf_field_name' => 'csrf', + 'csrf_provider' => $this->csrfProvider, + 'intention' => '%INTENTION%', + 'compound' => true, + )) + ->createView(); + + $this->assertEquals('token', $view['csrf']->vars['value']); + } + + public function provideBoolean() + { + return array( + array(true), + array(false), + ); + } + + /** + * @dataProvider provideBoolean + */ + public function testValidateTokenOnSubmitIfRootAndCompound($valid) + { + $this->csrfProvider->expects($this->once()) + ->method('isCsrfTokenValid') + ->with('%INTENTION%', 'token') + ->will($this->returnValue($valid)); + + $form = $this->factory + ->createBuilder('form', null, array( + 'csrf_field_name' => 'csrf', + 'csrf_provider' => $this->csrfProvider, + 'intention' => '%INTENTION%', + 'compound' => true, + )) + ->add('child', 'text') + ->getForm(); + + $form->submit(array( + 'child' => 'foobar', + 'csrf' => 'token', + )); + + // Remove token from data + $this->assertSame(array('child' => 'foobar'), $form->getData()); + + // Validate accordingly + $this->assertSame($valid, $form->isValid()); + } + + public function testFailIfRootAndCompoundAndTokenMissing() + { + $this->csrfProvider->expects($this->never()) + ->method('isCsrfTokenValid'); + + $form = $this->factory + ->createBuilder('form', null, array( + 'csrf_field_name' => 'csrf', + 'csrf_provider' => $this->csrfProvider, + 'intention' => '%INTENTION%', + 'compound' => true, + )) + ->add('child', 'text') + ->getForm(); + + $form->submit(array( + 'child' => 'foobar', + // token is missing + )); + + // Remove token from data + $this->assertSame(array('child' => 'foobar'), $form->getData()); + + // Validate accordingly + $this->assertFalse($form->isValid()); + } + + public function testDontValidateTokenIfCompoundButNoRoot() + { + $this->csrfProvider->expects($this->never()) + ->method('isCsrfTokenValid'); + + $form = $this->factory + ->createNamedBuilder('root', 'form') + ->add($this->factory + ->createNamedBuilder('form', 'form', null, array( + 'csrf_field_name' => 'csrf', + 'csrf_provider' => $this->csrfProvider, + 'intention' => '%INTENTION%', + 'compound' => true, + )) + ) + ->getForm() + ->get('form'); + + $form->submit(array( + 'child' => 'foobar', + 'csrf' => 'token', + )); + } + + public function testDontValidateTokenIfRootButNotCompound() + { + $this->csrfProvider->expects($this->never()) + ->method('isCsrfTokenValid'); + + $form = $this->factory + ->create('form', null, array( + 'csrf_field_name' => 'csrf', + 'csrf_provider' => $this->csrfProvider, + 'intention' => '%INTENTION%', + 'compound' => false, + )); + + $form->submit(array( + 'csrf' => 'token', + )); + } + + public function testNoCsrfProtectionOnPrototype() + { + $prototypeView = $this->factory + ->create('collection', null, array( + 'type' => new FormTypeCsrfExtensionTest_ChildType(), + 'options' => array( + 'csrf_field_name' => 'csrf', + ), + 'prototype' => true, + 'allow_add' => true, + )) + ->createView() + ->vars['prototype']; + + $this->assertFalse(isset($prototypeView['csrf'])); + $this->assertCount(1, $prototypeView); + } + + public function testsTranslateCustomErrorMessage() + { + $this->csrfProvider->expects($this->once()) + ->method('isCsrfTokenValid') + ->with('%INTENTION%', 'token') + ->will($this->returnValue(false)); + + $this->translator->expects($this->once()) + ->method('trans') + ->with('Foobar') + ->will($this->returnValue('[trans]Foobar[/trans]')); + + $form = $this->factory + ->createBuilder('form', null, array( + 'csrf_field_name' => 'csrf', + 'csrf_provider' => $this->csrfProvider, + 'csrf_message' => 'Foobar', + 'intention' => '%INTENTION%', + 'compound' => true, + )) + ->getForm(); + + $form->submit(array( + 'csrf' => 'token', + )); + + $errors = $form->getErrors(); + + $this->assertGreaterThan(0, count($errors)); + $this->assertEquals(new FormError('[trans]Foobar[/trans]'), $errors[0]); + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/HttpFoundation/EventListener/BindRequestListenerTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/HttpFoundation/EventListener/BindRequestListenerTest.php new file mode 100644 index 00000000..2ff072b2 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/HttpFoundation/EventListener/BindRequestListenerTest.php @@ -0,0 +1,286 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\HttpFoundation\EventListener; + +use Symfony\Component\Form\Extension\HttpFoundation\EventListener\BindRequestListener; +use Symfony\Component\Form\Form; +use Symfony\Component\Form\FormConfigBuilder; +use Symfony\Component\Form\FormEvent; +use Symfony\Component\Form\Test\DeprecationErrorHandler; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\File\UploadedFile; + +/** + * @author Bernhard Schussek + */ +class BindRequestListenerTest extends \PHPUnit_Framework_TestCase +{ + private $values; + + private $filesPlain; + + private $filesNested; + + /** + * @var UploadedFile + */ + private $uploadedFile; + + protected function setUp() + { + $path = tempnam(sys_get_temp_dir(), 'sf2'); + touch($path); + + $this->values = array( + 'name' => 'Bernhard', + 'image' => array('filename' => 'foobar.png'), + ); + + $this->filesPlain = array( + 'image' => array( + 'error' => UPLOAD_ERR_OK, + 'name' => 'upload.png', + 'size' => 123, + 'tmp_name' => $path, + 'type' => 'image/png' + ), + ); + + $this->filesNested = array( + 'error' => array('image' => UPLOAD_ERR_OK), + 'name' => array('image' => 'upload.png'), + 'size' => array('image' => 123), + 'tmp_name' => array('image' => $path), + 'type' => array('image' => 'image/png'), + ); + + $this->uploadedFile = new UploadedFile($path, 'upload.png', 'image/png', 123, UPLOAD_ERR_OK); + } + + protected function tearDown() + { + unlink($this->uploadedFile->getRealPath()); + } + + public function requestMethodProvider() + { + return array( + array('POST'), + array('PUT'), + array('DELETE'), + array('PATCH'), + ); + } + + /** + * @dataProvider requestMethodProvider + */ + public function testSubmitRequest($method) + { + if (!class_exists('Symfony\Component\HttpFoundation\Request')) { + $this->markTestSkipped('The "HttpFoundation" component is not available'); + } + + $values = array('author' => $this->values); + $files = array('author' => $this->filesNested); + $request = new Request(array(), $values, array(), array(), $files, array( + 'REQUEST_METHOD' => $method, + )); + + $dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); + $config = new FormConfigBuilder('author', null, $dispatcher); + $form = new Form($config); + $event = new FormEvent($form, $request); + + $listener = new BindRequestListener(); + DeprecationErrorHandler::preBind($listener, $event); + + $this->assertEquals(array( + 'name' => 'Bernhard', + 'image' => $this->uploadedFile, + ), $event->getData()); + } + + /** + * @dataProvider requestMethodProvider + */ + public function testSubmitRequestWithEmptyName($method) + { + if (!class_exists('Symfony\Component\HttpFoundation\Request')) { + $this->markTestSkipped('The "HttpFoundation" component is not available'); + } + + $request = new Request(array(), $this->values, array(), array(), $this->filesPlain, array( + 'REQUEST_METHOD' => $method, + )); + + $dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); + $config = new FormConfigBuilder('', null, $dispatcher); + $form = new Form($config); + $event = new FormEvent($form, $request); + + $listener = new BindRequestListener(); + DeprecationErrorHandler::preBind($listener, $event); + + $this->assertEquals(array( + 'name' => 'Bernhard', + 'image' => $this->uploadedFile, + ), $event->getData()); + } + + /** + * @dataProvider requestMethodProvider + */ + public function testSubmitEmptyRequestToCompoundForm($method) + { + if (!class_exists('Symfony\Component\HttpFoundation\Request')) { + $this->markTestSkipped('The "HttpFoundation" component is not available'); + } + + $request = new Request(array(), array(), array(), array(), array(), array( + 'REQUEST_METHOD' => $method, + )); + + $dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); + $config = new FormConfigBuilder('author', null, $dispatcher); + $config->setCompound(true); + $config->setDataMapper($this->getMock('Symfony\Component\Form\DataMapperInterface')); + $form = new Form($config); + $event = new FormEvent($form, $request); + + $listener = new BindRequestListener(); + DeprecationErrorHandler::preBind($listener, $event); + + // Default to empty array + $this->assertEquals(array(), $event->getData()); + } + + /** + * @dataProvider requestMethodProvider + */ + public function testSubmitEmptyRequestToSimpleForm($method) + { + if (!class_exists('Symfony\Component\HttpFoundation\Request')) { + $this->markTestSkipped('The "HttpFoundation" component is not available'); + } + + $request = new Request(array(), array(), array(), array(), array(), array( + 'REQUEST_METHOD' => $method, + )); + + $dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); + $config = new FormConfigBuilder('author', null, $dispatcher); + $config->setCompound(false); + $form = new Form($config); + $event = new FormEvent($form, $request); + + $listener = new BindRequestListener(); + DeprecationErrorHandler::preBind($listener, $event); + + // Default to null + $this->assertNull($event->getData()); + } + + public function testSubmitGetRequest() + { + if (!class_exists('Symfony\Component\HttpFoundation\Request')) { + $this->markTestSkipped('The "HttpFoundation" component is not available'); + } + + $values = array('author' => $this->values); + $request = new Request($values, array(), array(), array(), array(), array( + 'REQUEST_METHOD' => 'GET', + )); + + $dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); + $config = new FormConfigBuilder('author', null, $dispatcher); + $form = new Form($config); + $event = new FormEvent($form, $request); + + $listener = new BindRequestListener(); + DeprecationErrorHandler::preBind($listener, $event); + + $this->assertEquals(array( + 'name' => 'Bernhard', + 'image' => array('filename' => 'foobar.png'), + ), $event->getData()); + } + + public function testSubmitGetRequestWithEmptyName() + { + if (!class_exists('Symfony\Component\HttpFoundation\Request')) { + $this->markTestSkipped('The "HttpFoundation" component is not available'); + } + + $request = new Request($this->values, array(), array(), array(), array(), array( + 'REQUEST_METHOD' => 'GET', + )); + + $dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); + $config = new FormConfigBuilder('', null, $dispatcher); + $form = new Form($config); + $event = new FormEvent($form, $request); + + $listener = new BindRequestListener(); + DeprecationErrorHandler::preBind($listener, $event); + + $this->assertEquals(array( + 'name' => 'Bernhard', + 'image' => array('filename' => 'foobar.png'), + ), $event->getData()); + } + + public function testSubmitEmptyGetRequestToCompoundForm() + { + if (!class_exists('Symfony\Component\HttpFoundation\Request')) { + $this->markTestSkipped('The "HttpFoundation" component is not available'); + } + + $request = new Request(array(), array(), array(), array(), array(), array( + 'REQUEST_METHOD' => 'GET', + )); + + $dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); + $config = new FormConfigBuilder('author', null, $dispatcher); + $config->setCompound(true); + $config->setDataMapper($this->getMock('Symfony\Component\Form\DataMapperInterface')); + $form = new Form($config); + $event = new FormEvent($form, $request); + + $listener = new BindRequestListener(); + DeprecationErrorHandler::preBind($listener, $event); + + $this->assertEquals(array(), $event->getData()); + } + + public function testSubmitEmptyGetRequestToSimpleForm() + { + if (!class_exists('Symfony\Component\HttpFoundation\Request')) { + $this->markTestSkipped('The "HttpFoundation" component is not available'); + } + + $request = new Request(array(), array(), array(), array(), array(), array( + 'REQUEST_METHOD' => 'GET', + )); + + $dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); + $config = new FormConfigBuilder('author', null, $dispatcher); + $config->setCompound(false); + $form = new Form($config); + $event = new FormEvent($form, $request); + + $listener = new BindRequestListener(); + DeprecationErrorHandler::preBind($listener, $event); + + $this->assertNull($event->getData()); + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/HttpFoundation/HttpFoundationRequestHandlerTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/HttpFoundation/HttpFoundationRequestHandlerTest.php new file mode 100644 index 00000000..2d5cf776 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/HttpFoundation/HttpFoundationRequestHandlerTest.php @@ -0,0 +1,54 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\HttpFoundation; + +use Symfony\Component\Form\Extension\HttpFoundation\HttpFoundationRequestHandler; +use Symfony\Component\Form\Tests\AbstractRequestHandlerTest; +use Symfony\Component\HttpFoundation\Request; + +/** + * @author Bernhard Schussek + */ +class HttpFoundationRequestHandlerTest extends AbstractRequestHandlerTest +{ + /** + * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException + */ + public function testRequestShouldNotBeNull() + { + $this->requestHandler->handleRequest($this->getMockForm('name', 'GET')); + } + /** + * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException + */ + public function testRequestShouldBeInstanceOfRequest() + { + $this->requestHandler->handleRequest($this->getMockForm('name', 'GET'), new \stdClass()); + } + + protected function setRequestData($method, $data, $files = array()) + { + $this->request = Request::create('http://localhost', $method, $data, array(), $files); + } + + protected function getRequestHandler() + { + return new HttpFoundationRequestHandler(); + } + + protected function getMockFile() + { + return $this->getMockBuilder('Symfony\Component\HttpFoundation\File\UploadedFile') + ->disableOriginalConstructor() + ->getMock(); + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorTest.php new file mode 100644 index 00000000..a8bdde8a --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorTest.php @@ -0,0 +1,748 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Validator\Constraints; + +use Symfony\Component\Form\FormBuilder; +use Symfony\Component\Form\Exception\TransformationFailedException; +use Symfony\Component\Form\CallbackTransformer; +use Symfony\Component\Form\FormInterface; +use Symfony\Component\Form\Extension\Validator\Constraints\Form; +use Symfony\Component\Form\Extension\Validator\Constraints\FormValidator; +use Symfony\Component\Form\SubmitButtonBuilder; +use Symfony\Component\Validator\Constraint; +use Symfony\Component\Validator\Constraints\NotNull; +use Symfony\Component\Validator\Constraints\NotBlank; + +/** + * @author Bernhard Schussek + */ +class FormValidatorTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + private $dispatcher; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + private $factory; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + private $serverParams; + + /** + * @var FormValidator + */ + private $validator; + + protected function setUp() + { + if (!class_exists('Symfony\Component\EventDispatcher\Event')) { + $this->markTestSkipped('The "EventDispatcher" component is not available'); + } + + $this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); + $this->factory = $this->getMock('Symfony\Component\Form\FormFactoryInterface'); + $this->serverParams = $this->getMock( + 'Symfony\Component\Form\Extension\Validator\Util\ServerParams', + array('getNormalizedIniPostMaxSize', 'getContentLength') + ); + $this->validator = new FormValidator($this->serverParams); + } + + public function testValidate() + { + $context = $this->getMockExecutionContext(); + $object = $this->getMock('\stdClass'); + $options = array('validation_groups' => array('group1', 'group2')); + $form = $this->getBuilder('name', '\stdClass', $options) + ->setData($object) + ->getForm(); + + $context->expects($this->at(0)) + ->method('validate') + ->with($object, 'data', 'group1', true); + $context->expects($this->at(1)) + ->method('validate') + ->with($object, 'data', 'group2', true); + + $this->validator->initialize($context); + $this->validator->validate($form, new Form()); + } + + public function testValidateConstraints() + { + $context = $this->getMockExecutionContext(); + $object = $this->getMock('\stdClass'); + $constraint1 = new NotNull(array('groups' => array('group1', 'group2'))); + $constraint2 = new NotBlank(array('groups' => 'group2')); + + $options = array( + 'validation_groups' => array('group1', 'group2'), + 'constraints' => array($constraint1, $constraint2), + ); + $form = $this->getBuilder('name', '\stdClass', $options) + ->setData($object) + ->getForm(); + + // First default constraints + $context->expects($this->at(0)) + ->method('validate') + ->with($object, 'data', 'group1', true); + $context->expects($this->at(1)) + ->method('validate') + ->with($object, 'data', 'group2', true); + + // Then custom constraints + $context->expects($this->at(2)) + ->method('validateValue') + ->with($object, $constraint1, 'data', 'group1'); + $context->expects($this->at(3)) + ->method('validateValue') + ->with($object, $constraint2, 'data', 'group2'); + + $this->validator->initialize($context); + $this->validator->validate($form, new Form()); + } + + public function testDontValidateIfParentWithoutCascadeValidation() + { + $context = $this->getMockExecutionContext(); + $object = $this->getMock('\stdClass'); + + $parent = $this->getBuilder('parent', null, array('cascade_validation' => false)) + ->setCompound(true) + ->setDataMapper($this->getDataMapper()) + ->getForm(); + $options = array('validation_groups' => array('group1', 'group2')); + $form = $this->getBuilder('name', '\stdClass', $options)->getForm(); + $parent->add($form); + + $form->setData($object); + + $context->expects($this->never()) + ->method('validate'); + + $this->validator->initialize($context); + $this->validator->validate($form, new Form()); + } + + public function testValidateConstraintsEvenIfNoCascadeValidation() + { + $context = $this->getMockExecutionContext(); + $object = $this->getMock('\stdClass'); + $constraint1 = new NotNull(array('groups' => array('group1', 'group2'))); + $constraint2 = new NotBlank(array('groups' => 'group2')); + + $parent = $this->getBuilder('parent', null, array('cascade_validation' => false)) + ->setCompound(true) + ->setDataMapper($this->getDataMapper()) + ->getForm(); + $options = array( + 'validation_groups' => array('group1', 'group2'), + 'constraints' => array($constraint1, $constraint2), + ); + $form = $this->getBuilder('name', '\stdClass', $options) + ->setData($object) + ->getForm(); + $parent->add($form); + + $context->expects($this->at(0)) + ->method('validateValue') + ->with($object, $constraint1, 'data', 'group1'); + $context->expects($this->at(1)) + ->method('validateValue') + ->with($object, $constraint2, 'data', 'group2'); + + $this->validator->initialize($context); + $this->validator->validate($form, new Form()); + } + + public function testDontValidateIfNoValidationGroups() + { + $context = $this->getMockExecutionContext(); + $object = $this->getMock('\stdClass'); + + $form = $this->getBuilder('name', '\stdClass', array( + 'validation_groups' => array(), + )) + ->setData($object) + ->getForm(); + + $form->setData($object); + + $context->expects($this->never()) + ->method('validate'); + + $this->validator->initialize($context); + $this->validator->validate($form, new Form()); + } + + public function testDontValidateConstraintsIfNoValidationGroups() + { + $context = $this->getMockExecutionContext(); + $object = $this->getMock('\stdClass'); + $constraint1 = $this->getMock('Symfony\Component\Validator\Constraint'); + $constraint2 = $this->getMock('Symfony\Component\Validator\Constraint'); + + $options = array( + 'validation_groups' => array(), + 'constraints' => array($constraint1, $constraint2), + ); + $form = $this->getBuilder('name', '\stdClass', $options) + ->setData($object) + ->getForm(); + + // Launch transformer + $form->submit(array()); + + $context->expects($this->never()) + ->method('validate'); + + $this->validator->initialize($context); + $this->validator->validate($form, new Form()); + } + + public function testDontValidateIfNotSynchronized() + { + $context = $this->getMockExecutionContext(); + $object = $this->getMock('\stdClass'); + + $form = $this->getBuilder('name', '\stdClass', array( + 'invalid_message' => 'invalid_message_key', + // Invalid message parameters must be supported, because the + // invalid message can be a translation key + // see https://github.com/symfony/symfony/issues/5144 + 'invalid_message_parameters' => array('{{ foo }}' => 'bar'), + )) + ->setData($object) + ->addViewTransformer(new CallbackTransformer( + function ($data) { return $data; }, + function () { throw new TransformationFailedException(); } + )) + ->getForm(); + + // Launch transformer + $form->submit('foo'); + + $context->expects($this->never()) + ->method('validate'); + + $context->expects($this->once()) + ->method('addViolation') + ->with( + 'invalid_message_key', + array('{{ value }}' => 'foo', '{{ foo }}' => 'bar'), + 'foo' + ); + $context->expects($this->never()) + ->method('addViolationAt'); + + $this->validator->initialize($context); + $this->validator->validate($form, new Form()); + } + + public function testAddInvalidErrorEvenIfNoValidationGroups() + { + $context = $this->getMockExecutionContext(); + $object = $this->getMock('\stdClass'); + + $form = $this->getBuilder('name', '\stdClass', array( + 'invalid_message' => 'invalid_message_key', + // Invalid message parameters must be supported, because the + // invalid message can be a translation key + // see https://github.com/symfony/symfony/issues/5144 + 'invalid_message_parameters' => array('{{ foo }}' => 'bar'), + 'validation_groups' => array(), + )) + ->setData($object) + ->addViewTransformer(new CallbackTransformer( + function ($data) { return $data; }, + function () { throw new TransformationFailedException(); } + )) + ->getForm(); + + // Launch transformer + $form->submit('foo'); + + $context->expects($this->never()) + ->method('validate'); + + $context->expects($this->once()) + ->method('addViolation') + ->with( + 'invalid_message_key', + array('{{ value }}' => 'foo', '{{ foo }}' => 'bar'), + 'foo' + ); + $context->expects($this->never()) + ->method('addViolationAt'); + + $this->validator->initialize($context); + $this->validator->validate($form, new Form()); + } + + public function testDontValidateConstraintsIfNotSynchronized() + { + $context = $this->getMockExecutionContext(); + $object = $this->getMock('\stdClass'); + $constraint1 = $this->getMock('Symfony\Component\Validator\Constraint'); + $constraint2 = $this->getMock('Symfony\Component\Validator\Constraint'); + + $options = array( + 'validation_groups' => array('group1', 'group2'), + 'constraints' => array($constraint1, $constraint2), + ); + $form = $this->getBuilder('name', '\stdClass', $options) + ->setData($object) + ->addViewTransformer(new CallbackTransformer( + function ($data) { return $data; }, + function () { throw new TransformationFailedException(); } + )) + ->getForm(); + + // Launch transformer + $form->submit(array()); + + $context->expects($this->never()) + ->method('validate'); + + $this->validator->initialize($context); + $this->validator->validate($form, new Form()); + } + + // https://github.com/symfony/symfony/issues/4359 + public function testDontMarkInvalidIfAnyChildIsNotSynchronized() + { + $context = $this->getMockExecutionContext(); + $object = $this->getMock('\stdClass'); + + $failingTransformer = new CallbackTransformer( + function ($data) { return $data; }, + function () { throw new TransformationFailedException(); } + ); + + $form = $this->getBuilder('name', '\stdClass') + ->setData($object) + ->addViewTransformer($failingTransformer) + ->setCompound(true) + ->setDataMapper($this->getDataMapper()) + ->add( + $this->getBuilder('child') + ->addViewTransformer($failingTransformer) + ) + ->getForm(); + + // Launch transformer + $form->submit(array('child' => 'foo')); + + $context->expects($this->never()) + ->method('addViolation'); + $context->expects($this->never()) + ->method('addViolationAt'); + + $this->validator->initialize($context); + $this->validator->validate($form, new Form()); + } + + public function testHandleCallbackValidationGroups() + { + $context = $this->getMockExecutionContext(); + $object = $this->getMock('\stdClass'); + $options = array('validation_groups' => array($this, 'getValidationGroups')); + $form = $this->getBuilder('name', '\stdClass', $options) + ->setData($object) + ->getForm(); + + $context->expects($this->at(0)) + ->method('validate') + ->with($object, 'data', 'group1', true); + $context->expects($this->at(1)) + ->method('validate') + ->with($object, 'data', 'group2', true); + + $this->validator->initialize($context); + $this->validator->validate($form, new Form()); + } + + public function testDontExecuteFunctionNames() + { + $context = $this->getMockExecutionContext(); + $object = $this->getMock('\stdClass'); + $options = array('validation_groups' => 'header'); + $form = $this->getBuilder('name', '\stdClass', $options) + ->setData($object) + ->getForm(); + + $context->expects($this->once()) + ->method('validate') + ->with($object, 'data', 'header', true); + + $this->validator->initialize($context); + $this->validator->validate($form, new Form()); + } + + public function testHandleClosureValidationGroups() + { + $context = $this->getMockExecutionContext(); + $object = $this->getMock('\stdClass'); + $options = array('validation_groups' => function(FormInterface $form){ + return array('group1', 'group2'); + }); + $form = $this->getBuilder('name', '\stdClass', $options) + ->setData($object) + ->getForm(); + + $context->expects($this->at(0)) + ->method('validate') + ->with($object, 'data', 'group1', true); + $context->expects($this->at(1)) + ->method('validate') + ->with($object, 'data', 'group2', true); + + $this->validator->initialize($context); + $this->validator->validate($form, new Form()); + } + + public function testUseValidationGroupOfClickedButton() + { + $context = $this->getMockExecutionContext(); + $object = $this->getMock('\stdClass'); + + $parent = $this->getBuilder('parent', null, array('cascade_validation' => true)) + ->setCompound(true) + ->setDataMapper($this->getDataMapper()) + ->getForm(); + $form = $this->getForm('name', '\stdClass', array( + 'validation_groups' => 'form_group', + )); + + $parent->add($form); + $parent->add($this->getClickedSubmitButton('submit', array( + 'validation_groups' => 'button_group', + ))); + + $form->setData($object); + + $context->expects($this->once()) + ->method('validate') + ->with($object, 'data', 'button_group', true); + + $this->validator->initialize($context); + $this->validator->validate($form, new Form()); + } + + public function testDontUseValidationGroupOfUnclickedButton() + { + $context = $this->getMockExecutionContext(); + $object = $this->getMock('\stdClass'); + + $parent = $this->getBuilder('parent', null, array('cascade_validation' => true)) + ->setCompound(true) + ->setDataMapper($this->getDataMapper()) + ->getForm(); + $form = $this->getForm('name', '\stdClass', array( + 'validation_groups' => 'form_group', + )); + + $parent->add($form); + $parent->add($this->getSubmitButton('submit', array( + 'validation_groups' => 'button_group', + ))); + + $form->setData($object); + + $context->expects($this->once()) + ->method('validate') + ->with($object, 'data', 'form_group', true); + + $this->validator->initialize($context); + $this->validator->validate($form, new Form()); + } + + public function testUseInheritedValidationGroup() + { + $context = $this->getMockExecutionContext(); + $object = $this->getMock('\stdClass'); + + $parentOptions = array( + 'validation_groups' => 'group', + 'cascade_validation' => true, + ); + $parent = $this->getBuilder('parent', null, $parentOptions) + ->setCompound(true) + ->setDataMapper($this->getDataMapper()) + ->getForm(); + $form = $this->getBuilder('name', '\stdClass')->getForm(); + $parent->add($form); + + $form->setData($object); + + $context->expects($this->once()) + ->method('validate') + ->with($object, 'data', 'group', true); + + $this->validator->initialize($context); + $this->validator->validate($form, new Form()); + } + + public function testUseInheritedCallbackValidationGroup() + { + $context = $this->getMockExecutionContext(); + $object = $this->getMock('\stdClass'); + + $parentOptions = array( + 'validation_groups' => array($this, 'getValidationGroups'), + 'cascade_validation' => true, + ); + $parent = $this->getBuilder('parent', null, $parentOptions) + ->setCompound(true) + ->setDataMapper($this->getDataMapper()) + ->getForm(); + $form = $this->getBuilder('name', '\stdClass')->getForm(); + $parent->add($form); + + $form->setData($object); + + $context->expects($this->at(0)) + ->method('validate') + ->with($object, 'data', 'group1', true); + $context->expects($this->at(1)) + ->method('validate') + ->with($object, 'data', 'group2', true); + + $this->validator->initialize($context); + $this->validator->validate($form, new Form()); + } + + public function testUseInheritedClosureValidationGroup() + { + $context = $this->getMockExecutionContext(); + $object = $this->getMock('\stdClass'); + + $parentOptions = array( + 'validation_groups' => function(FormInterface $form){ + return array('group1', 'group2'); + }, + 'cascade_validation' => true, + ); + $parent = $this->getBuilder('parent', null, $parentOptions) + ->setCompound(true) + ->setDataMapper($this->getDataMapper()) + ->getForm(); + $form = $this->getBuilder('name', '\stdClass')->getForm(); + $parent->add($form); + + $form->setData($object); + + $context->expects($this->at(0)) + ->method('validate') + ->with($object, 'data', 'group1', true); + $context->expects($this->at(1)) + ->method('validate') + ->with($object, 'data', 'group2', true); + + $this->validator->initialize($context); + $this->validator->validate($form, new Form()); + } + + public function testAppendPropertyPath() + { + $context = $this->getMockExecutionContext(); + $object = $this->getMock('\stdClass'); + $form = $this->getBuilder('name', '\stdClass') + ->setData($object) + ->getForm(); + + $context->expects($this->once()) + ->method('validate') + ->with($object, 'data', 'Default', true); + + $this->validator->initialize($context); + $this->validator->validate($form, new Form()); + } + + public function testDontWalkScalars() + { + $context = $this->getMockExecutionContext(); + + $form = $this->getBuilder() + ->setData('scalar') + ->getForm(); + + $context->expects($this->never()) + ->method('validate'); + + $this->validator->initialize($context); + $this->validator->validate($form, new Form()); + } + + public function testViolationIfExtraData() + { + $context = $this->getMockExecutionContext(); + + $form = $this->getBuilder('parent', null, array('extra_fields_message' => 'Extra!')) + ->setCompound(true) + ->setDataMapper($this->getDataMapper()) + ->add($this->getBuilder('child')) + ->getForm(); + + $form->submit(array('foo' => 'bar')); + + $context->expects($this->once()) + ->method('addViolation') + ->with( + 'Extra!', + array('{{ extra_fields }}' => 'foo'), + array('foo' => 'bar') + ); + $context->expects($this->never()) + ->method('addViolationAt'); + + $this->validator->initialize($context); + $this->validator->validate($form, new Form()); + } + + /** + * @dataProvider getPostMaxSizeFixtures + */ + public function testPostMaxSizeViolation($contentLength, $iniMax, $nbViolation, array $params = array()) + { + $this->serverParams->expects($this->once()) + ->method('getContentLength') + ->will($this->returnValue($contentLength)); + $this->serverParams->expects($this->any()) + ->method('getNormalizedIniPostMaxSize') + ->will($this->returnValue($iniMax)); + + $context = $this->getMockExecutionContext(); + $options = array('post_max_size_message' => 'Max {{ max }}!'); + $form = $this->getBuilder('name', null, $options)->getForm(); + + for ($i = 0; $i < $nbViolation; ++$i) { + if (0 === $i && count($params) > 0) { + $context->expects($this->at($i)) + ->method('addViolation') + ->with($options['post_max_size_message'], $params); + } else { + $context->expects($this->at($i)) + ->method('addViolation'); + } + } + + $context->expects($this->never()) + ->method('addViolationAt'); + + $this->validator->initialize($context); + $this->validator->validate($form, new Form()); + } + + public function getPostMaxSizeFixtures() + { + return array( + array(pow(1024, 3) + 1, '1G', 1, array('{{ max }}' => '1G')), + array(pow(1024, 3), '1G', 0), + array(pow(1024, 2) + 1, '1M', 1, array('{{ max }}' => '1M')), + array(pow(1024, 2), '1M', 0), + array(1024 + 1, '1K', 1, array('{{ max }}' => '1K')), + array(1024, '1K', 0), + array(null, '1K', 0), + array(1024, '', 0), + array(1024, 0, 0), + ); + } + + public function testNoViolationIfNotRoot() + { + $this->serverParams->expects($this->once()) + ->method('getContentLength') + ->will($this->returnValue(1025)); + $this->serverParams->expects($this->never()) + ->method('getNormalizedIniPostMaxSize'); + + $context = $this->getMockExecutionContext(); + $parent = $this->getBuilder() + ->setCompound(true) + ->setDataMapper($this->getDataMapper()) + ->getForm(); + $form = $this->getForm(); + $parent->add($form); + + $context->expects($this->never()) + ->method('addViolation'); + $context->expects($this->never()) + ->method('addViolationAt'); + + $this->validator->initialize($context); + $this->validator->validate($form, new Form()); + } + + /** + * Access has to be public, as this method is called via callback array + * in {@link testValidateFormDataCanHandleCallbackValidationGroups()} + * and {@link testValidateFormDataUsesInheritedCallbackValidationGroup()} + */ + public function getValidationGroups(FormInterface $form) + { + return array('group1', 'group2'); + } + + private function getMockExecutionContext() + { + return $this->getMock('Symfony\Component\Validator\ExecutionContextInterface'); + } + + /** + * @param string $name + * @param string $dataClass + * @param array $options + * + * @return FormBuilder + */ + private function getBuilder($name = 'name', $dataClass = null, array $options = array()) + { + $options = array_replace(array( + 'constraints' => array(), + 'invalid_message_parameters' => array(), + ), $options); + + return new FormBuilder($name, $dataClass, $this->dispatcher, $this->factory, $options); + } + + private function getForm($name = 'name', $dataClass = null, array $options = array()) + { + return $this->getBuilder($name, $dataClass, $options)->getForm(); + } + + private function getSubmitButton($name = 'name', array $options = array()) + { + $builder = new SubmitButtonBuilder($name, $options); + + return $builder->getForm(); + } + + private function getClickedSubmitButton($name = 'name', array $options = array()) + { + return $this->getSubmitButton($name, $options)->submit(''); + } + + /** + * @return \PHPUnit_Framework_MockObject_MockObject + */ + private function getDataMapper() + { + return $this->getMock('Symfony\Component\Form\DataMapperInterface'); + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Validator/EventListener/ValidationListenerTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Validator/EventListener/ValidationListenerTest.php new file mode 100644 index 00000000..528f9463 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Validator/EventListener/ValidationListenerTest.php @@ -0,0 +1,145 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Validator\EventListener; + +use Symfony\Component\Form\FormBuilder; +use Symfony\Component\Form\FormEvent; +use Symfony\Component\Form\Extension\Validator\Constraints\Form; +use Symfony\Component\Form\Extension\Validator\EventListener\ValidationListener; +use Symfony\Component\PropertyAccess\PropertyPath; +use Symfony\Component\Validator\ConstraintViolation; + +class ValidationListenerTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + private $dispatcher; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + private $factory; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + private $validator; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + private $violationMapper; + + /** + * @var ValidationListener + */ + private $listener; + + private $message; + + private $messageTemplate; + + private $params; + + protected function setUp() + { + if (!class_exists('Symfony\Component\EventDispatcher\Event')) { + $this->markTestSkipped('The "EventDispatcher" component is not available'); + } + + $this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); + $this->factory = $this->getMock('Symfony\Component\Form\FormFactoryInterface'); + $this->validator = $this->getMock('Symfony\Component\Validator\ValidatorInterface'); + $this->violationMapper = $this->getMock('Symfony\Component\Form\Extension\Validator\ViolationMapper\ViolationMapperInterface'); + $this->listener = new ValidationListener($this->validator, $this->violationMapper); + $this->message = 'Message'; + $this->messageTemplate = 'Message template'; + $this->params = array('foo' => 'bar'); + } + + private function getConstraintViolation($code = null) + { + return new ConstraintViolation($this->message, $this->messageTemplate, $this->params, null, 'prop.path', null, null, $code); + } + + private function getBuilder($name = 'name', $propertyPath = null, $dataClass = null) + { + $builder = new FormBuilder($name, $dataClass, $this->dispatcher, $this->factory); + $builder->setPropertyPath(new PropertyPath($propertyPath ?: $name)); + $builder->setAttribute('error_mapping', array()); + $builder->setErrorBubbling(false); + $builder->setMapped(true); + + return $builder; + } + + private function getForm($name = 'name', $propertyPath = null, $dataClass = null) + { + return $this->getBuilder($name, $propertyPath, $dataClass)->getForm(); + } + + private function getMockForm() + { + return $this->getMock('Symfony\Component\Form\Test\FormInterface'); + } + + // More specific mapping tests can be found in ViolationMapperTest + public function testMapViolation() + { + $violation = $this->getConstraintViolation(); + $form = $this->getForm('street'); + + $this->validator->expects($this->once()) + ->method('validate') + ->will($this->returnValue(array($violation))); + + $this->violationMapper->expects($this->once()) + ->method('mapViolation') + ->with($violation, $form, false); + + $this->listener->validateForm(new FormEvent($form, null)); + } + + public function testMapViolationAllowsNonSyncIfInvalid() + { + $violation = $this->getConstraintViolation(Form::ERR_INVALID); + $form = $this->getForm('street'); + + $this->validator->expects($this->once()) + ->method('validate') + ->will($this->returnValue(array($violation))); + + $this->violationMapper->expects($this->once()) + ->method('mapViolation') + // pass true now + ->with($violation, $form, true); + + $this->listener->validateForm(new FormEvent($form, null)); + } + + public function testValidateIgnoresNonRoot() + { + $form = $this->getMockForm(); + $form->expects($this->once()) + ->method('isRoot') + ->will($this->returnValue(false)); + + $this->validator->expects($this->never()) + ->method('validate'); + + $this->violationMapper->expects($this->never()) + ->method('mapViolation'); + + $this->listener->validateForm(new FormEvent($form, null)); + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Validator/Type/FormTypeValidatorExtensionTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Validator/Type/FormTypeValidatorExtensionTest.php new file mode 100644 index 00000000..66194105 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Validator/Type/FormTypeValidatorExtensionTest.php @@ -0,0 +1,85 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Validator\Type; + +use Symfony\Component\Form\FormInterface; + +class FormTypeValidatorExtensionTest extends TypeTestCase +{ + public function testValidationGroupNullByDefault() + { + $form = $this->factory->create('form'); + + $this->assertNull($form->getConfig()->getOption('validation_groups')); + } + + public function testValidationGroupsTransformedToArray() + { + $form = $this->factory->create('form', null, array( + 'validation_groups' => 'group', + )); + + $this->assertEquals(array('group'), $form->getConfig()->getOption('validation_groups')); + } + + public function testValidationGroupsCanBeSetToArray() + { + $form = $this->factory->create('form', null, array( + 'validation_groups' => array('group1', 'group2'), + )); + + $this->assertEquals(array('group1', 'group2'), $form->getConfig()->getOption('validation_groups')); + } + + public function testValidationGroupsCanBeSetToFalse() + { + $form = $this->factory->create('form', null, array( + 'validation_groups' => false, + )); + + $this->assertEquals(array(), $form->getConfig()->getOption('validation_groups')); + } + + public function testValidationGroupsCanBeSetToCallback() + { + $form = $this->factory->create('form', null, array( + 'validation_groups' => array($this, 'testValidationGroupsCanBeSetToCallback'), + )); + + $this->assertTrue(is_callable($form->getConfig()->getOption('validation_groups'))); + } + + public function testValidationGroupsCanBeSetToClosure() + { + $form = $this->factory->create('form', null, array( + 'validation_groups' => function(FormInterface $form){ return null; }, + )); + + $this->assertTrue(is_callable($form->getConfig()->getOption('validation_groups'))); + } + + public function testSubmitValidatesData() + { + $builder = $this->factory->createBuilder('form', null, array( + 'validation_groups' => 'group', + )); + $builder->add('firstName', 'form'); + $form = $builder->getForm(); + + $this->validator->expects($this->once()) + ->method('validate') + ->with($this->equalTo($form)); + + // specific data is irrelevant + $form->submit(array()); + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Validator/Type/TypeTestCase.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Validator/Type/TypeTestCase.php new file mode 100644 index 00000000..d94d896a --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Validator/Type/TypeTestCase.php @@ -0,0 +1,49 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Validator\Type; + +use Symfony\Component\Form\Test\TypeTestCase as BaseTypeTestCase; +use Symfony\Component\Form\Extension\Validator\ValidatorExtension; + +abstract class TypeTestCase extends BaseTypeTestCase +{ + protected $validator; + + protected function setUp() + { + if (!class_exists('Symfony\Component\Validator\Constraint')) { + $this->markTestSkipped('The "Validator" component is not available'); + } + + $this->validator = $this->getMock('Symfony\Component\Validator\ValidatorInterface'); + $metadataFactory = $this->getMock('Symfony\Component\Validator\MetadataFactoryInterface'); + $this->validator->expects($this->once())->method('getMetadataFactory')->will($this->returnValue($metadataFactory)); + $metadata = $this->getMockBuilder('Symfony\Component\Validator\Mapping\ClassMetadata')->disableOriginalConstructor()->getMock(); + $metadataFactory->expects($this->once())->method('getMetadataFor')->will($this->returnValue($metadata)); + + parent::setUp(); + } + + protected function tearDown() + { + $this->validator = null; + + parent::tearDown(); + } + + protected function getExtensions() + { + return array_merge(parent::getExtensions(), array( + new ValidatorExtension($this->validator), + )); + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Validator/Util/ServerParamsTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Validator/Util/ServerParamsTest.php new file mode 100644 index 00000000..7ad5b771 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Validator/Util/ServerParamsTest.php @@ -0,0 +1,46 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Validator\Util; + +class ServerParamsTest extends \PHPUnit_Framework_TestCase +{ + /** @dataProvider getGetPostMaxSizeTestData */ + public function testGetPostMaxSize($size, $bytes) + { + $serverParams = $this->getMock('Symfony\Component\Form\Extension\Validator\Util\ServerParams', array('getNormalizedIniPostMaxSize')); + $serverParams + ->expects($this->any()) + ->method('getNormalizedIniPostMaxSize') + ->will($this->returnValue(strtoupper($size))); + + $this->assertEquals($bytes, $serverParams->getPostMaxSize()); + } + + public function getGetPostMaxSizeTestData() + { + return array( + array('2k', 2048), + array('2 k', 2048), + array('8m', 8 * 1024 * 1024), + array('+2 k', 2048), + array('+2???k', 2048), + array('0x10', 16), + array('0xf', 15), + array('010', 8), + array('+0x10 k', 16 * 1024), + array('1g', 1024 * 1024 * 1024), + array('-1', -1), + array('0', 0), + array('2mk', 2048), // the unit must be the last char, so in this case 'k', not 'm' + ); + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php new file mode 100644 index 00000000..c802ea7e --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php @@ -0,0 +1,1481 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Validator\ViolationMapper; + +use Symfony\Component\Form\Extension\Validator\ViolationMapper\ViolationMapper; +use Symfony\Component\Form\Exception\TransformationFailedException; +use Symfony\Component\Form\CallbackTransformer; +use Symfony\Component\Form\Form; +use Symfony\Component\Form\FormConfigBuilder; +use Symfony\Component\Form\FormError; +use Symfony\Component\PropertyAccess\PropertyPath; +use Symfony\Component\Validator\ConstraintViolation; + +/** + * @author Bernhard Schussek + */ +class ViolationMapperTest extends \PHPUnit_Framework_TestCase +{ + const LEVEL_0 = 0; + + const LEVEL_1 = 1; + + const LEVEL_1B = 2; + + const LEVEL_2 = 3; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + private $dispatcher; + + /** + * @var ViolationMapper + */ + private $mapper; + + /** + * @var string + */ + private $message; + + /** + * @var string + */ + private $messageTemplate; + + /** + * @var array + */ + private $params; + + protected function setUp() + { + if (!class_exists('Symfony\Component\EventDispatcher\Event')) { + $this->markTestSkipped('The "EventDispatcher" component is not available'); + } + + $this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); + $this->mapper = new ViolationMapper(); + $this->message = 'Message'; + $this->messageTemplate = 'Message template'; + $this->params = array('foo' => 'bar'); + } + + protected function getForm($name = 'name', $propertyPath = null, $dataClass = null, $errorMapping = array(), $inheritData = false, $synchronized = true) + { + $config = new FormConfigBuilder($name, $dataClass, $this->dispatcher, array( + 'error_mapping' => $errorMapping, + )); + $config->setMapped(true); + $config->setInheritData($inheritData); + $config->setPropertyPath($propertyPath); + $config->setCompound(true); + $config->setDataMapper($this->getDataMapper()); + + if (!$synchronized) { + $config->addViewTransformer(new CallbackTransformer( + function ($normData) { return $normData; }, + function () { throw new TransformationFailedException(); } + )); + } + + return new Form($config); + } + + /** + * @return \PHPUnit_Framework_MockObject_MockObject + */ + private function getDataMapper() + { + return $this->getMock('Symfony\Component\Form\DataMapperInterface'); + } + + /** + * @param $propertyPath + * + * @return ConstraintViolation + */ + protected function getConstraintViolation($propertyPath) + { + return new ConstraintViolation($this->message, $this->messageTemplate, $this->params, null, $propertyPath, null); + } + + /** + * @return FormError + */ + protected function getFormError() + { + return new FormError($this->message, $this->messageTemplate, $this->params); + } + + public function testMapToFormInheritingParentDataIfDataDoesNotMatch() + { + $violation = $this->getConstraintViolation('children[address].data.foo'); + $parent = $this->getForm('parent'); + $child = $this->getForm('address', 'address', null, array(), true); + $grandChild = $this->getForm('street'); + + $parent->add($child); + $child->add($grandChild); + + $this->mapper->mapViolation($violation, $parent); + + $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); + $this->assertEquals(array($this->getFormError()), $child->getErrors(), $child->getName().' should have an error, but has none'); + $this->assertCount(0, $grandChild->getErrors(), $grandChild->getName().' should not have an error, but has one'); + } + + public function testFollowDotRules() + { + $violation = $this->getConstraintViolation('data.foo'); + $parent = $this->getForm('parent', null, null, array( + 'foo' => 'address', + )); + $child = $this->getForm('address', null, null, array( + '.' => 'street', + )); + $grandChild = $this->getForm('street', null, null, array( + '.' => 'name', + )); + $grandGrandChild = $this->getForm('name'); + + $parent->add($child); + $child->add($grandChild); + $grandChild->add($grandGrandChild); + + $this->mapper->mapViolation($violation, $parent); + + $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); + $this->assertCount(0, $child->getErrors(), $child->getName().' should not have an error, but has one'); + $this->assertCount(0, $grandChild->getErrors(), $grandChild->getName().' should not have an error, but has one'); + $this->assertEquals(array($this->getFormError()), $grandGrandChild->getErrors(), $grandGrandChild->getName().' should have an error, but has none'); + } + + public function testAbortMappingIfNotSynchronized() + { + $violation = $this->getConstraintViolation('children[address].data.street'); + $parent = $this->getForm('parent'); + $child = $this->getForm('address', 'address', null, array(), false, false); + // even though "street" is synchronized, it should not have any errors + // due to its parent not being synchronized + $grandChild = $this->getForm('street' , 'street'); + + $parent->add($child); + $child->add($grandChild); + + // submit to invoke the transformer and mark the form unsynchronized + $parent->submit(array()); + + $this->mapper->mapViolation($violation, $parent); + + $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); + $this->assertCount(0, $child->getErrors(), $child->getName().' should not have an error, but has one'); + $this->assertCount(0, $grandChild->getErrors(), $grandChild->getName().' should not have an error, but has one'); + } + + public function testAbortDotRuleMappingIfNotSynchronized() + { + $violation = $this->getConstraintViolation('data.address'); + $parent = $this->getForm('parent'); + $child = $this->getForm('address', 'address', null, array( + '.' => 'street', + ), false, false); + // even though "street" is synchronized, it should not have any errors + // due to its parent not being synchronized + $grandChild = $this->getForm('street'); + + $parent->add($child); + $child->add($grandChild); + + // submit to invoke the transformer and mark the form unsynchronized + $parent->submit(array()); + + $this->mapper->mapViolation($violation, $parent); + + $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); + $this->assertCount(0, $child->getErrors(), $child->getName().' should not have an error, but has one'); + $this->assertCount(0, $grandChild->getErrors(), $grandChild->getName().' should not have an error, but has one'); + } + + public function provideDefaultTests() + { + // The mapping must be deterministic! If a child has the property path "[street]", + // "data[street]" should be mapped, but "data.street" should not! + return array( + // mapping target, child name, its property path, grand child name, its property path, violation path + array(self::LEVEL_0, 'address', 'address', 'street', 'street', ''), + array(self::LEVEL_0, 'address', 'address', 'street', 'street', 'data'), + + array(self::LEVEL_2, 'address', 'address', 'street', 'street', 'children[address].children[street].data'), + array(self::LEVEL_2, 'address', 'address', 'street', 'street', 'children[address].children[street].data.prop'), + array(self::LEVEL_1, 'address', 'address', 'street', 'street', 'children[address].data'), + array(self::LEVEL_2, 'address', 'address', 'street', 'street', 'children[address].data.street'), + array(self::LEVEL_2, 'address', 'address', 'street', 'street', 'children[address].data.street.prop'), + array(self::LEVEL_1, 'address', 'address', 'street', 'street', 'children[address].data[street]'), + array(self::LEVEL_1, 'address', 'address', 'street', 'street', 'children[address].data[street].prop'), + array(self::LEVEL_2, 'address', 'address', 'street', 'street', 'data.address.street'), + array(self::LEVEL_2, 'address', 'address', 'street', 'street', 'data.address.street.prop'), + array(self::LEVEL_1, 'address', 'address', 'street', 'street', 'data.address[street]'), + array(self::LEVEL_1, 'address', 'address', 'street', 'street', 'data.address[street].prop'), + array(self::LEVEL_0, 'address', 'address', 'street', 'street', 'data[address].street'), + array(self::LEVEL_0, 'address', 'address', 'street', 'street', 'data[address].street.prop'), + array(self::LEVEL_0, 'address', 'address', 'street', 'street', 'data[address][street]'), + array(self::LEVEL_0, 'address', 'address', 'street', 'street', 'data[address][street].prop'), + + array(self::LEVEL_2, 'address', 'address', 'street', '[street]', 'children[address].children[street].data'), + array(self::LEVEL_2, 'address', 'address', 'street', '[street]', 'children[address].children[street].data.prop'), + array(self::LEVEL_1, 'address', 'address', 'street', '[street]', 'children[address].data'), + array(self::LEVEL_1, 'address', 'address', 'street', '[street]', 'children[address].data.street'), + array(self::LEVEL_1, 'address', 'address', 'street', '[street]', 'children[address].data.street.prop'), + array(self::LEVEL_2, 'address', 'address', 'street', '[street]', 'children[address].data[street]'), + array(self::LEVEL_2, 'address', 'address', 'street', '[street]', 'children[address].data[street].prop'), + array(self::LEVEL_1, 'address', 'address', 'street', '[street]', 'data.address.street'), + array(self::LEVEL_1, 'address', 'address', 'street', '[street]', 'data.address.street.prop'), + array(self::LEVEL_2, 'address', 'address', 'street', '[street]', 'data.address[street]'), + array(self::LEVEL_2, 'address', 'address', 'street', '[street]', 'data.address[street].prop'), + array(self::LEVEL_0, 'address', 'address', 'street', '[street]', 'data[address].street'), + array(self::LEVEL_0, 'address', 'address', 'street', '[street]', 'data[address].street.prop'), + array(self::LEVEL_0, 'address', 'address', 'street', '[street]', 'data[address][street]'), + array(self::LEVEL_0, 'address', 'address', 'street', '[street]', 'data[address][street].prop'), + + array(self::LEVEL_2, 'address', '[address]', 'street', 'street', 'children[address].children[street].data'), + array(self::LEVEL_2, 'address', '[address]', 'street', 'street', 'children[address].children[street].data.prop'), + array(self::LEVEL_1, 'address', '[address]', 'street', 'street', 'children[address].data'), + array(self::LEVEL_2, 'address', '[address]', 'street', 'street', 'children[address].data.street'), + array(self::LEVEL_2, 'address', '[address]', 'street', 'street', 'children[address].data.street.prop'), + array(self::LEVEL_1, 'address', '[address]', 'street', 'street', 'children[address].data[street]'), + array(self::LEVEL_1, 'address', '[address]', 'street', 'street', 'children[address].data[street].prop'), + array(self::LEVEL_0, 'address', '[address]', 'street', 'street', 'data.address.street'), + array(self::LEVEL_0, 'address', '[address]', 'street', 'street', 'data.address.street.prop'), + array(self::LEVEL_0, 'address', '[address]', 'street', 'street', 'data.address[street]'), + array(self::LEVEL_0, 'address', '[address]', 'street', 'street', 'data.address[street].prop'), + array(self::LEVEL_2, 'address', '[address]', 'street', 'street', 'data[address].street'), + array(self::LEVEL_2, 'address', '[address]', 'street', 'street', 'data[address].street.prop'), + array(self::LEVEL_1, 'address', '[address]', 'street', 'street', 'data[address][street]'), + array(self::LEVEL_1, 'address', '[address]', 'street', 'street', 'data[address][street].prop'), + + array(self::LEVEL_2, 'address', '[address]', 'street', '[street]', 'children[address].children[street].data'), + array(self::LEVEL_2, 'address', '[address]', 'street', '[street]', 'children[address].children[street].data.prop'), + array(self::LEVEL_1, 'address', '[address]', 'street', '[street]', 'children[address].data'), + array(self::LEVEL_1, 'address', '[address]', 'street', '[street]', 'children[address].data.street'), + array(self::LEVEL_1, 'address', '[address]', 'street', '[street]', 'children[address].data.street.prop'), + array(self::LEVEL_2, 'address', '[address]', 'street', '[street]', 'children[address].data[street]'), + array(self::LEVEL_2, 'address', '[address]', 'street', '[street]', 'children[address].data[street].prop'), + array(self::LEVEL_0, 'address', '[address]', 'street', '[street]', 'data.address.street'), + array(self::LEVEL_0, 'address', '[address]', 'street', '[street]', 'data.address.street.prop'), + array(self::LEVEL_0, 'address', '[address]', 'street', '[street]', 'data.address[street]'), + array(self::LEVEL_0, 'address', '[address]', 'street', '[street]', 'data.address[street].prop'), + array(self::LEVEL_1, 'address', '[address]', 'street', '[street]', 'data[address].street'), + array(self::LEVEL_1, 'address', '[address]', 'street', '[street]', 'data[address].street.prop'), + array(self::LEVEL_2, 'address', '[address]', 'street', '[street]', 'data[address][street]'), + array(self::LEVEL_2, 'address', '[address]', 'street', '[street]', 'data[address][street].prop'), + + array(self::LEVEL_2, 'address', 'person.address', 'street', 'street', 'children[address].children[street].data'), + array(self::LEVEL_2, 'address', 'person.address', 'street', 'street', 'children[address].children[street].data.prop'), + array(self::LEVEL_1, 'address', 'person.address', 'street', 'street', 'children[address].data'), + array(self::LEVEL_2, 'address', 'person.address', 'street', 'street', 'children[address].data.street'), + array(self::LEVEL_2, 'address', 'person.address', 'street', 'street', 'children[address].data.street.prop'), + array(self::LEVEL_1, 'address', 'person.address', 'street', 'street', 'children[address].data[street]'), + array(self::LEVEL_1, 'address', 'person.address', 'street', 'street', 'children[address].data[street].prop'), + array(self::LEVEL_2, 'address', 'person.address', 'street', 'street', 'data.person.address.street'), + array(self::LEVEL_2, 'address', 'person.address', 'street', 'street', 'data.person.address.street.prop'), + array(self::LEVEL_1, 'address', 'person.address', 'street', 'street', 'data.person.address[street]'), + array(self::LEVEL_1, 'address', 'person.address', 'street', 'street', 'data.person.address[street].prop'), + array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'data.person[address].street'), + array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'data.person[address].street.prop'), + array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'data.person[address][street]'), + array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'data.person[address][street].prop'), + array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'data[person].address.street'), + array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'data[person].address.street.prop'), + array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'data[person].address[street]'), + array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'data[person].address[street].prop'), + array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'data[person][address].street'), + array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'data[person][address].street.prop'), + array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'data[person][address][street]'), + array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'data[person][address][street].prop'), + + array(self::LEVEL_2, 'address', 'person.address', 'street', '[street]', 'children[address].children[street].data'), + array(self::LEVEL_2, 'address', 'person.address', 'street', '[street]', 'children[address].children[street].data.prop'), + array(self::LEVEL_1, 'address', 'person.address', 'street', '[street]', 'children[address].data'), + array(self::LEVEL_1, 'address', 'person.address', 'street', '[street]', 'children[address].data.street'), + array(self::LEVEL_1, 'address', 'person.address', 'street', '[street]', 'children[address].data.street.prop'), + array(self::LEVEL_2, 'address', 'person.address', 'street', '[street]', 'children[address].data[street]'), + array(self::LEVEL_2, 'address', 'person.address', 'street', '[street]', 'children[address].data[street].prop'), + array(self::LEVEL_1, 'address', 'person.address', 'street', '[street]', 'data.person.address.street'), + array(self::LEVEL_1, 'address', 'person.address', 'street', '[street]', 'data.person.address.street.prop'), + array(self::LEVEL_2, 'address', 'person.address', 'street', '[street]', 'data.person.address[street]'), + array(self::LEVEL_2, 'address', 'person.address', 'street', '[street]', 'data.person.address[street].prop'), + array(self::LEVEL_0, 'address', 'person.address', 'street', '[street]', 'data.person[address].street'), + array(self::LEVEL_0, 'address', 'person.address', 'street', '[street]', 'data.person[address].street.prop'), + array(self::LEVEL_0, 'address', 'person.address', 'street', '[street]', 'data.person[address][street]'), + array(self::LEVEL_0, 'address', 'person.address', 'street', '[street]', 'data.person[address][street].prop'), + array(self::LEVEL_0, 'address', 'person.address', 'street', '[street]', 'data[person].address.street'), + array(self::LEVEL_0, 'address', 'person.address', 'street', '[street]', 'data[person].address.street.prop'), + array(self::LEVEL_0, 'address', 'person.address', 'street', '[street]', 'data[person].address[street]'), + array(self::LEVEL_0, 'address', 'person.address', 'street', '[street]', 'data[person].address[street].prop'), + array(self::LEVEL_0, 'address', 'person.address', 'street', '[street]', 'data[person][address].street'), + array(self::LEVEL_0, 'address', 'person.address', 'street', '[street]', 'data[person][address].street.prop'), + array(self::LEVEL_0, 'address', 'person.address', 'street', '[street]', 'data[person][address][street]'), + array(self::LEVEL_0, 'address', 'person.address', 'street', '[street]', 'data[person][address][street].prop'), + + array(self::LEVEL_2, 'address', 'person[address]', 'street', 'street', 'children[address].children[street].data'), + array(self::LEVEL_2, 'address', 'person[address]', 'street', 'street', 'children[address].children[street].data.prop'), + array(self::LEVEL_1, 'address', 'person[address]', 'street', 'street', 'children[address].data'), + array(self::LEVEL_2, 'address', 'person[address]', 'street', 'street', 'children[address].data.street'), + array(self::LEVEL_2, 'address', 'person[address]', 'street', 'street', 'children[address].data.street.prop'), + array(self::LEVEL_1, 'address', 'person[address]', 'street', 'street', 'children[address].data[street]'), + array(self::LEVEL_1, 'address', 'person[address]', 'street', 'street', 'children[address].data[street].prop'), + array(self::LEVEL_0, 'address', 'person[address]', 'street', 'street', 'data.person.address.street'), + array(self::LEVEL_0, 'address', 'person[address]', 'street', 'street', 'data.person.address.street.prop'), + array(self::LEVEL_0, 'address', 'person[address]', 'street', 'street', 'data.person.address[street]'), + array(self::LEVEL_0, 'address', 'person[address]', 'street', 'street', 'data.person.address[street].prop'), + array(self::LEVEL_2, 'address', 'person[address]', 'street', 'street', 'data.person[address].street'), + array(self::LEVEL_2, 'address', 'person[address]', 'street', 'street', 'data.person[address].street.prop'), + array(self::LEVEL_1, 'address', 'person[address]', 'street', 'street', 'data.person[address][street]'), + array(self::LEVEL_1, 'address', 'person[address]', 'street', 'street', 'data.person[address][street].prop'), + array(self::LEVEL_0, 'address', 'person[address]', 'street', 'street', 'data[person].address.street'), + array(self::LEVEL_0, 'address', 'person[address]', 'street', 'street', 'data[person].address.street.prop'), + array(self::LEVEL_0, 'address', 'person[address]', 'street', 'street', 'data[person].address[street]'), + array(self::LEVEL_0, 'address', 'person[address]', 'street', 'street', 'data[person].address[street].prop'), + array(self::LEVEL_0, 'address', 'person[address]', 'street', 'street', 'data[person][address].street'), + array(self::LEVEL_0, 'address', 'person[address]', 'street', 'street', 'data[person][address].street.prop'), + array(self::LEVEL_0, 'address', 'person[address]', 'street', 'street', 'data[person][address][street]'), + array(self::LEVEL_0, 'address', 'person[address]', 'street', 'street', 'data[person][address][street].prop'), + + array(self::LEVEL_2, 'address', 'person[address]', 'street', '[street]', 'children[address].children[street].data'), + array(self::LEVEL_2, 'address', 'person[address]', 'street', '[street]', 'children[address].children[street].data.prop'), + array(self::LEVEL_1, 'address', 'person[address]', 'street', '[street]', 'children[address].data'), + array(self::LEVEL_1, 'address', 'person[address]', 'street', '[street]', 'children[address].data.street'), + array(self::LEVEL_1, 'address', 'person[address]', 'street', '[street]', 'children[address].data.street.prop'), + array(self::LEVEL_2, 'address', 'person[address]', 'street', '[street]', 'children[address].data[street]'), + array(self::LEVEL_2, 'address', 'person[address]', 'street', '[street]', 'children[address].data[street].prop'), + array(self::LEVEL_0, 'address', 'person[address]', 'street', '[street]', 'data.person.address.street'), + array(self::LEVEL_0, 'address', 'person[address]', 'street', '[street]', 'data.person.address.street.prop'), + array(self::LEVEL_0, 'address', 'person[address]', 'street', '[street]', 'data.person.address[street]'), + array(self::LEVEL_0, 'address', 'person[address]', 'street', '[street]', 'data.person.address[street].prop'), + array(self::LEVEL_1, 'address', 'person[address]', 'street', '[street]', 'data.person[address].street'), + array(self::LEVEL_1, 'address', 'person[address]', 'street', '[street]', 'data.person[address].street.prop'), + array(self::LEVEL_2, 'address', 'person[address]', 'street', '[street]', 'data.person[address][street]'), + array(self::LEVEL_2, 'address', 'person[address]', 'street', '[street]', 'data.person[address][street].prop'), + array(self::LEVEL_0, 'address', 'person[address]', 'street', '[street]', 'data[person].address.street'), + array(self::LEVEL_0, 'address', 'person[address]', 'street', '[street]', 'data[person].address.street.prop'), + array(self::LEVEL_0, 'address', 'person[address]', 'street', '[street]', 'data[person].address[street]'), + array(self::LEVEL_0, 'address', 'person[address]', 'street', '[street]', 'data[person].address[street].prop'), + array(self::LEVEL_0, 'address', 'person[address]', 'street', '[street]', 'data[person][address].street'), + array(self::LEVEL_0, 'address', 'person[address]', 'street', '[street]', 'data[person][address].street.prop'), + array(self::LEVEL_0, 'address', 'person[address]', 'street', '[street]', 'data[person][address][street]'), + array(self::LEVEL_0, 'address', 'person[address]', 'street', '[street]', 'data[person][address][street].prop'), + + array(self::LEVEL_2, 'address', '[person].address', 'street', 'street', 'children[address].children[street].data'), + array(self::LEVEL_2, 'address', '[person].address', 'street', 'street', 'children[address].children[street].data.prop'), + array(self::LEVEL_1, 'address', '[person].address', 'street', 'street', 'children[address].data'), + array(self::LEVEL_2, 'address', '[person].address', 'street', 'street', 'children[address].data.street'), + array(self::LEVEL_2, 'address', '[person].address', 'street', 'street', 'children[address].data.street.prop'), + array(self::LEVEL_1, 'address', '[person].address', 'street', 'street', 'children[address].data[street]'), + array(self::LEVEL_1, 'address', '[person].address', 'street', 'street', 'children[address].data[street].prop'), + array(self::LEVEL_0, 'address', '[person].address', 'street', 'street', 'data.person.address.street'), + array(self::LEVEL_0, 'address', '[person].address', 'street', 'street', 'data.person.address.street.prop'), + array(self::LEVEL_0, 'address', '[person].address', 'street', 'street', 'data.person.address[street]'), + array(self::LEVEL_0, 'address', '[person].address', 'street', 'street', 'data.person.address[street].prop'), + array(self::LEVEL_0, 'address', '[person].address', 'street', 'street', 'data.person[address].street'), + array(self::LEVEL_0, 'address', '[person].address', 'street', 'street', 'data.person[address].street.prop'), + array(self::LEVEL_0, 'address', '[person].address', 'street', 'street', 'data.person[address][street]'), + array(self::LEVEL_0, 'address', '[person].address', 'street', 'street', 'data.person[address][street].prop'), + array(self::LEVEL_2, 'address', '[person].address', 'street', 'street', 'data[person].address.street'), + array(self::LEVEL_2, 'address', '[person].address', 'street', 'street', 'data[person].address.street.prop'), + array(self::LEVEL_1, 'address', '[person].address', 'street', 'street', 'data[person].address[street]'), + array(self::LEVEL_1, 'address', '[person].address', 'street', 'street', 'data[person].address[street].prop'), + array(self::LEVEL_0, 'address', '[person].address', 'street', 'street', 'data[person][address].street'), + array(self::LEVEL_0, 'address', '[person].address', 'street', 'street', 'data[person][address].street.prop'), + array(self::LEVEL_0, 'address', '[person].address', 'street', 'street', 'data[person][address][street]'), + array(self::LEVEL_0, 'address', '[person].address', 'street', 'street', 'data[person][address][street].prop'), + + array(self::LEVEL_2, 'address', '[person].address', 'street', '[street]', 'children[address].children[street].data'), + array(self::LEVEL_2, 'address', '[person].address', 'street', '[street]', 'children[address].children[street].data.prop'), + array(self::LEVEL_1, 'address', '[person].address', 'street', '[street]', 'children[address].data'), + array(self::LEVEL_1, 'address', '[person].address', 'street', '[street]', 'children[address].data.street'), + array(self::LEVEL_1, 'address', '[person].address', 'street', '[street]', 'children[address].data.street.prop'), + array(self::LEVEL_2, 'address', '[person].address', 'street', '[street]', 'children[address].data[street]'), + array(self::LEVEL_2, 'address', '[person].address', 'street', '[street]', 'children[address].data[street].prop'), + array(self::LEVEL_0, 'address', '[person].address', 'street', '[street]', 'data.person.address.street'), + array(self::LEVEL_0, 'address', '[person].address', 'street', '[street]', 'data.person.address.street.prop'), + array(self::LEVEL_0, 'address', '[person].address', 'street', '[street]', 'data.person.address[street]'), + array(self::LEVEL_0, 'address', '[person].address', 'street', '[street]', 'data.person.address[street].prop'), + array(self::LEVEL_0, 'address', '[person].address', 'street', '[street]', 'data.person[address].street'), + array(self::LEVEL_0, 'address', '[person].address', 'street', '[street]', 'data.person[address].street.prop'), + array(self::LEVEL_0, 'address', '[person].address', 'street', '[street]', 'data.person[address][street]'), + array(self::LEVEL_0, 'address', '[person].address', 'street', '[street]', 'data.person[address][street].prop'), + array(self::LEVEL_1, 'address', '[person].address', 'street', '[street]', 'data[person].address.street'), + array(self::LEVEL_1, 'address', '[person].address', 'street', '[street]', 'data[person].address.street.prop'), + array(self::LEVEL_2, 'address', '[person].address', 'street', '[street]', 'data[person].address[street]'), + array(self::LEVEL_2, 'address', '[person].address', 'street', '[street]', 'data[person].address[street].prop'), + array(self::LEVEL_0, 'address', '[person].address', 'street', '[street]', 'data[person][address].street'), + array(self::LEVEL_0, 'address', '[person].address', 'street', '[street]', 'data[person][address].street.prop'), + array(self::LEVEL_0, 'address', '[person].address', 'street', '[street]', 'data[person][address][street]'), + array(self::LEVEL_0, 'address', '[person].address', 'street', '[street]', 'data[person][address][street].prop'), + + array(self::LEVEL_2, 'address', '[person][address]', 'street', 'street', 'children[address].children[street].data'), + array(self::LEVEL_2, 'address', '[person][address]', 'street', 'street', 'children[address].children[street].data.prop'), + array(self::LEVEL_1, 'address', '[person][address]', 'street', 'street', 'children[address]'), + array(self::LEVEL_1, 'address', '[person][address]', 'street', 'street', 'children[address].data'), + array(self::LEVEL_2, 'address', '[person][address]', 'street', 'street', 'children[address].data.street'), + array(self::LEVEL_2, 'address', '[person][address]', 'street', 'street', 'children[address].data.street.prop'), + array(self::LEVEL_1, 'address', '[person][address]', 'street', 'street', 'children[address].data[street]'), + array(self::LEVEL_1, 'address', '[person][address]', 'street', 'street', 'children[address].data[street].prop'), + array(self::LEVEL_0, 'address', '[person][address]', 'street', 'street', 'data.person.address.street'), + array(self::LEVEL_0, 'address', '[person][address]', 'street', 'street', 'data.person.address.street.prop'), + array(self::LEVEL_0, 'address', '[person][address]', 'street', 'street', 'data.person.address[street]'), + array(self::LEVEL_0, 'address', '[person][address]', 'street', 'street', 'data.person.address[street].prop'), + array(self::LEVEL_0, 'address', '[person][address]', 'street', 'street', 'data.person[address].street'), + array(self::LEVEL_0, 'address', '[person][address]', 'street', 'street', 'data.person[address].street.prop'), + array(self::LEVEL_0, 'address', '[person][address]', 'street', 'street', 'data.person[address][street]'), + array(self::LEVEL_0, 'address', '[person][address]', 'street', 'street', 'data.person[address][street].prop'), + array(self::LEVEL_0, 'address', '[person][address]', 'street', 'street', 'data[person].address.street'), + array(self::LEVEL_0, 'address', '[person][address]', 'street', 'street', 'data[person].address.street.prop'), + array(self::LEVEL_0, 'address', '[person][address]', 'street', 'street', 'data[person].address[street]'), + array(self::LEVEL_0, 'address', '[person][address]', 'street', 'street', 'data[person].address[street].prop'), + array(self::LEVEL_2, 'address', '[person][address]', 'street', 'street', 'data[person][address].street'), + array(self::LEVEL_2, 'address', '[person][address]', 'street', 'street', 'data[person][address].street.prop'), + array(self::LEVEL_1, 'address', '[person][address]', 'street', 'street', 'data[person][address][street]'), + array(self::LEVEL_1, 'address', '[person][address]', 'street', 'street', 'data[person][address][street].prop'), + + array(self::LEVEL_2, 'address', '[person][address]', 'street', '[street]', 'children[address].children[street].data'), + array(self::LEVEL_2, 'address', '[person][address]', 'street', '[street]', 'children[address].children[street].data.prop'), + array(self::LEVEL_1, 'address', '[person][address]', 'street', '[street]', 'children[address].data'), + array(self::LEVEL_1, 'address', '[person][address]', 'street', '[street]', 'children[address].data.street'), + array(self::LEVEL_1, 'address', '[person][address]', 'street', '[street]', 'children[address].data.street.prop'), + array(self::LEVEL_2, 'address', '[person][address]', 'street', '[street]', 'children[address].data[street]'), + array(self::LEVEL_2, 'address', '[person][address]', 'street', '[street]', 'children[address].data[street].prop'), + array(self::LEVEL_0, 'address', '[person][address]', 'street', '[street]', 'data.person.address.street'), + array(self::LEVEL_0, 'address', '[person][address]', 'street', '[street]', 'data.person.address.street.prop'), + array(self::LEVEL_0, 'address', '[person][address]', 'street', '[street]', 'data.person.address[street]'), + array(self::LEVEL_0, 'address', '[person][address]', 'street', '[street]', 'data.person.address[street].prop'), + array(self::LEVEL_0, 'address', '[person][address]', 'street', '[street]', 'data.person[address].street'), + array(self::LEVEL_0, 'address', '[person][address]', 'street', '[street]', 'data.person[address].street.prop'), + array(self::LEVEL_0, 'address', '[person][address]', 'street', '[street]', 'data.person[address][street]'), + array(self::LEVEL_0, 'address', '[person][address]', 'street', '[street]', 'data.person[address][street].prop'), + array(self::LEVEL_0, 'address', '[person][address]', 'street', '[street]', 'data[person].address.street'), + array(self::LEVEL_0, 'address', '[person][address]', 'street', '[street]', 'data[person].address.street.prop'), + array(self::LEVEL_0, 'address', '[person][address]', 'street', '[street]', 'data[person].address[street]'), + array(self::LEVEL_0, 'address', '[person][address]', 'street', '[street]', 'data[person].address[street].prop'), + array(self::LEVEL_1, 'address', '[person][address]', 'street', '[street]', 'data[person][address].street'), + array(self::LEVEL_1, 'address', '[person][address]', 'street', '[street]', 'data[person][address].street.prop'), + array(self::LEVEL_2, 'address', '[person][address]', 'street', '[street]', 'data[person][address][street]'), + array(self::LEVEL_2, 'address', '[person][address]', 'street', '[street]', 'data[person][address][street].prop'), + + array(self::LEVEL_2, 'address', 'address', 'street', 'office.street', 'children[address].children[street].data'), + array(self::LEVEL_2, 'address', 'address', 'street', 'office.street', 'children[address].children[street].data.prop'), + array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'children[address].data'), + array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'children[address].data.office'), + array(self::LEVEL_2, 'address', 'address', 'street', 'office.street', 'children[address].data.office.street'), + array(self::LEVEL_2, 'address', 'address', 'street', 'office.street', 'children[address].data.office.street.prop'), + array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'children[address].data.office[street]'), + array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'children[address].data.office[street].prop'), + array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'children[address].data[office]'), + array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'children[address].data[office].street'), + array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'children[address].data[office].street.prop'), + array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'children[address].data[office][street]'), + array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'children[address].data[office][street].prop'), + array(self::LEVEL_2, 'address', 'address', 'street', 'office.street', 'data.address.office.street'), + array(self::LEVEL_2, 'address', 'address', 'street', 'office.street', 'data.address.office.street.prop'), + array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'data.address.office[street]'), + array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'data.address.office[street].prop'), + array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'data.address[office].street'), + array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'data.address[office].street.prop'), + array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'data.address[office][street]'), + array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'data.address[office][street].prop'), + array(self::LEVEL_0, 'address', 'address', 'street', 'office.street', 'data[address].office.street'), + array(self::LEVEL_0, 'address', 'address', 'street', 'office.street', 'data[address].office.street.prop'), + array(self::LEVEL_0, 'address', 'address', 'street', 'office.street', 'data[address].office[street]'), + array(self::LEVEL_0, 'address', 'address', 'street', 'office.street', 'data[address].office[street].prop'), + array(self::LEVEL_0, 'address', 'address', 'street', 'office.street', 'data[address][office].street'), + array(self::LEVEL_0, 'address', 'address', 'street', 'office.street', 'data[address][office].street.prop'), + array(self::LEVEL_0, 'address', 'address', 'street', 'office.street', 'data[address][office][street]'), + array(self::LEVEL_0, 'address', 'address', 'street', 'office.street', 'data[address][office][street].prop'), + + array(self::LEVEL_2, 'address', '[address]', 'street', 'office.street', 'children[address].children[street].data'), + array(self::LEVEL_2, 'address', '[address]', 'street', 'office.street', 'children[address].children[street].data.prop'), + array(self::LEVEL_1, 'address', '[address]', 'street', 'office.street', 'children[address].data'), + array(self::LEVEL_1, 'address', '[address]', 'street', 'office.street', 'children[address].data.office'), + array(self::LEVEL_2, 'address', '[address]', 'street', 'office.street', 'children[address].data.office.street'), + array(self::LEVEL_2, 'address', '[address]', 'street', 'office.street', 'children[address].data.office.street.prop'), + array(self::LEVEL_1, 'address', '[address]', 'street', 'office.street', 'children[address].data.office[street]'), + array(self::LEVEL_1, 'address', '[address]', 'street', 'office.street', 'children[address].data.office[street].prop'), + array(self::LEVEL_1, 'address', '[address]', 'street', 'office.street', 'children[address].data[office]'), + array(self::LEVEL_1, 'address', '[address]', 'street', 'office.street', 'children[address].data[office].street'), + array(self::LEVEL_1, 'address', '[address]', 'street', 'office.street', 'children[address].data[office].street.prop'), + array(self::LEVEL_1, 'address', '[address]', 'street', 'office.street', 'children[address].data[office][street]'), + array(self::LEVEL_1, 'address', '[address]', 'street', 'office.street', 'children[address].data[office][street].prop'), + array(self::LEVEL_0, 'address', '[address]', 'street', 'office.street', 'data.address.office.street'), + array(self::LEVEL_0, 'address', '[address]', 'street', 'office.street', 'data.address.office.street.prop'), + array(self::LEVEL_0, 'address', '[address]', 'street', 'office.street', 'data.address.office[street]'), + array(self::LEVEL_0, 'address', '[address]', 'street', 'office.street', 'data.address.office[street].prop'), + array(self::LEVEL_0, 'address', '[address]', 'street', 'office.street', 'data.address[office].street'), + array(self::LEVEL_0, 'address', '[address]', 'street', 'office.street', 'data.address[office].street.prop'), + array(self::LEVEL_0, 'address', '[address]', 'street', 'office.street', 'data.address[office][street]'), + array(self::LEVEL_0, 'address', '[address]', 'street', 'office.street', 'data.address[office][street].prop'), + array(self::LEVEL_2, 'address', '[address]', 'street', 'office.street', 'data[address].office.street'), + array(self::LEVEL_2, 'address', '[address]', 'street', 'office.street', 'data[address].office.street.prop'), + array(self::LEVEL_1, 'address', '[address]', 'street', 'office.street', 'data[address].office[street]'), + array(self::LEVEL_1, 'address', '[address]', 'street', 'office.street', 'data[address].office[street].prop'), + array(self::LEVEL_1, 'address', '[address]', 'street', 'office.street', 'data[address][office].street'), + array(self::LEVEL_1, 'address', '[address]', 'street', 'office.street', 'data[address][office].street.prop'), + array(self::LEVEL_1, 'address', '[address]', 'street', 'office.street', 'data[address][office][street]'), + array(self::LEVEL_1, 'address', '[address]', 'street', 'office.street', 'data[address][office][street].prop'), + + array(self::LEVEL_2, 'address', 'address', 'street', 'office[street]', 'children[address].children[street].data'), + array(self::LEVEL_2, 'address', 'address', 'street', 'office[street]', 'children[address].children[street].data.prop'), + array(self::LEVEL_1, 'address', 'address', 'street', 'office[street]', 'children[address].data'), + array(self::LEVEL_1, 'address', 'address', 'street', 'office[street]', 'children[address].data.office'), + array(self::LEVEL_1, 'address', 'address', 'street', 'office[street]', 'children[address].data.office.street'), + array(self::LEVEL_1, 'address', 'address', 'street', 'office[street]', 'children[address].data.office.street.prop'), + array(self::LEVEL_2, 'address', 'address', 'street', 'office[street]', 'children[address].data.office[street]'), + array(self::LEVEL_2, 'address', 'address', 'street', 'office[street]', 'children[address].data.office[street].prop'), + array(self::LEVEL_1, 'address', 'address', 'street', 'office[street]', 'children[address].data[office]'), + array(self::LEVEL_1, 'address', 'address', 'street', 'office[street]', 'children[address].data[office].street'), + array(self::LEVEL_1, 'address', 'address', 'street', 'office[street]', 'children[address].data[office].street.prop'), + array(self::LEVEL_1, 'address', 'address', 'street', 'office[street]', 'children[address].data[office][street]'), + array(self::LEVEL_1, 'address', 'address', 'street', 'office[street]', 'children[address].data[office][street].prop'), + array(self::LEVEL_1, 'address', 'address', 'street', 'office[street]', 'data.address.office.street'), + array(self::LEVEL_1, 'address', 'address', 'street', 'office[street]', 'data.address.office.street.prop'), + array(self::LEVEL_2, 'address', 'address', 'street', 'office[street]', 'data.address.office[street]'), + array(self::LEVEL_2, 'address', 'address', 'street', 'office[street]', 'data.address.office[street].prop'), + array(self::LEVEL_1, 'address', 'address', 'street', 'office[street]', 'data.address[office].street'), + array(self::LEVEL_1, 'address', 'address', 'street', 'office[street]', 'data.address[office].street.prop'), + array(self::LEVEL_1, 'address', 'address', 'street', 'office[street]', 'data.address[office][street]'), + array(self::LEVEL_1, 'address', 'address', 'street', 'office[street]', 'data.address[office][street].prop'), + array(self::LEVEL_0, 'address', 'address', 'street', 'office[street]', 'data[address].office.street'), + array(self::LEVEL_0, 'address', 'address', 'street', 'office[street]', 'data[address].office.street.prop'), + array(self::LEVEL_0, 'address', 'address', 'street', 'office[street]', 'data[address].office[street]'), + array(self::LEVEL_0, 'address', 'address', 'street', 'office[street]', 'data[address].office[street].prop'), + array(self::LEVEL_0, 'address', 'address', 'street', 'office[street]', 'data[address][office].street'), + array(self::LEVEL_0, 'address', 'address', 'street', 'office[street]', 'data[address][office].street.prop'), + array(self::LEVEL_0, 'address', 'address', 'street', 'office[street]', 'data[address][office][street]'), + array(self::LEVEL_0, 'address', 'address', 'street', 'office[street]', 'data[address][office][street].prop'), + + array(self::LEVEL_2, 'address', '[address]', 'street', 'office[street]', 'children[address].children[street].data'), + array(self::LEVEL_2, 'address', '[address]', 'street', 'office[street]', 'children[address].children[street].data.prop'), + array(self::LEVEL_1, 'address', '[address]', 'street', 'office[street]', 'children[address].data.office.street'), + array(self::LEVEL_1, 'address', '[address]', 'street', 'office[street]', 'children[address].data.office.street.prop'), + array(self::LEVEL_2, 'address', '[address]', 'street', 'office[street]', 'children[address].data.office[street]'), + array(self::LEVEL_2, 'address', '[address]', 'street', 'office[street]', 'children[address].data.office[street].prop'), + array(self::LEVEL_1, 'address', '[address]', 'street', 'office[street]', 'children[address].data[office]'), + array(self::LEVEL_1, 'address', '[address]', 'street', 'office[street]', 'children[address].data[office].street'), + array(self::LEVEL_1, 'address', '[address]', 'street', 'office[street]', 'children[address].data[office].street.prop'), + array(self::LEVEL_1, 'address', '[address]', 'street', 'office[street]', 'children[address].data[office][street]'), + array(self::LEVEL_1, 'address', '[address]', 'street', 'office[street]', 'children[address].data[office][street].prop'), + array(self::LEVEL_0, 'address', '[address]', 'street', 'office[street]', 'data.address.office.street'), + array(self::LEVEL_0, 'address', '[address]', 'street', 'office[street]', 'data.address.office.street.prop'), + array(self::LEVEL_0, 'address', '[address]', 'street', 'office[street]', 'data.address.office[street]'), + array(self::LEVEL_0, 'address', '[address]', 'street', 'office[street]', 'data.address.office[street].prop'), + array(self::LEVEL_0, 'address', '[address]', 'street', 'office[street]', 'data.address[office].street'), + array(self::LEVEL_0, 'address', '[address]', 'street', 'office[street]', 'data.address[office].street.prop'), + array(self::LEVEL_0, 'address', '[address]', 'street', 'office[street]', 'data.address[office][street]'), + array(self::LEVEL_0, 'address', '[address]', 'street', 'office[street]', 'data.address[office][street].prop'), + array(self::LEVEL_1, 'address', '[address]', 'street', 'office[street]', 'data[address].office.street'), + array(self::LEVEL_1, 'address', '[address]', 'street', 'office[street]', 'data[address].office.street.prop'), + array(self::LEVEL_2, 'address', '[address]', 'street', 'office[street]', 'data[address].office[street]'), + array(self::LEVEL_2, 'address', '[address]', 'street', 'office[street]', 'data[address].office[street].prop'), + array(self::LEVEL_1, 'address', '[address]', 'street', 'office[street]', 'data[address][office].street'), + array(self::LEVEL_1, 'address', '[address]', 'street', 'office[street]', 'data[address][office].street.prop'), + array(self::LEVEL_1, 'address', '[address]', 'street', 'office[street]', 'data[address][office][street]'), + array(self::LEVEL_1, 'address', '[address]', 'street', 'office[street]', 'data[address][office][street].prop'), + + array(self::LEVEL_2, 'address', 'address', 'street', '[office].street', 'children[address].children[street].data'), + array(self::LEVEL_2, 'address', 'address', 'street', '[office].street', 'children[address].children[street].data.prop'), + array(self::LEVEL_1, 'address', 'address', 'street', '[office].street', 'children[address].data'), + array(self::LEVEL_1, 'address', 'address', 'street', '[office].street', 'children[address].data.office'), + array(self::LEVEL_1, 'address', 'address', 'street', '[office].street', 'children[address].data.office.street'), + array(self::LEVEL_1, 'address', 'address', 'street', '[office].street', 'children[address].data.office.street.prop'), + array(self::LEVEL_1, 'address', 'address', 'street', '[office].street', 'children[address].data.office[street]'), + array(self::LEVEL_1, 'address', 'address', 'street', '[office].street', 'children[address].data.office[street].prop'), + array(self::LEVEL_1, 'address', 'address', 'street', '[office].street', 'children[address].data[office]'), + array(self::LEVEL_2, 'address', 'address', 'street', '[office].street', 'children[address].data[office].street'), + array(self::LEVEL_2, 'address', 'address', 'street', '[office].street', 'children[address].data[office].street.prop'), + array(self::LEVEL_1, 'address', 'address', 'street', '[office].street', 'children[address].data[office][street]'), + array(self::LEVEL_1, 'address', 'address', 'street', '[office].street', 'children[address].data[office][street].prop'), + array(self::LEVEL_1, 'address', 'address', 'street', '[office].street', 'data.address.office.street'), + array(self::LEVEL_1, 'address', 'address', 'street', '[office].street', 'data.address.office.street.prop'), + array(self::LEVEL_1, 'address', 'address', 'street', '[office].street', 'data.address.office[street]'), + array(self::LEVEL_1, 'address', 'address', 'street', '[office].street', 'data.address.office[street].prop'), + array(self::LEVEL_2, 'address', 'address', 'street', '[office].street', 'data.address[office].street'), + array(self::LEVEL_2, 'address', 'address', 'street', '[office].street', 'data.address[office].street.prop'), + array(self::LEVEL_1, 'address', 'address', 'street', '[office].street', 'data.address[office][street]'), + array(self::LEVEL_1, 'address', 'address', 'street', '[office].street', 'data.address[office][street].prop'), + array(self::LEVEL_0, 'address', 'address', 'street', '[office].street', 'data[address].office.street'), + array(self::LEVEL_0, 'address', 'address', 'street', '[office].street', 'data[address].office.street.prop'), + array(self::LEVEL_0, 'address', 'address', 'street', '[office].street', 'data[address].office[street]'), + array(self::LEVEL_0, 'address', 'address', 'street', '[office].street', 'data[address].office[street].prop'), + array(self::LEVEL_0, 'address', 'address', 'street', '[office].street', 'data[address][office].street'), + array(self::LEVEL_0, 'address', 'address', 'street', '[office].street', 'data[address][office].street.prop'), + array(self::LEVEL_0, 'address', 'address', 'street', '[office].street', 'data[address][office][street]'), + array(self::LEVEL_0, 'address', 'address', 'street', '[office].street', 'data[address][office][street].prop'), + + array(self::LEVEL_2, 'address', '[address]', 'street', '[office].street', 'children[address].children[street].data'), + array(self::LEVEL_2, 'address', '[address]', 'street', '[office].street', 'children[address].children[street].data.prop'), + array(self::LEVEL_1, 'address', '[address]', 'street', '[office].street', 'children[address].data'), + array(self::LEVEL_1, 'address', '[address]', 'street', '[office].street', 'children[address].data.office'), + array(self::LEVEL_1, 'address', '[address]', 'street', '[office].street', 'children[address].data.office.street'), + array(self::LEVEL_1, 'address', '[address]', 'street', '[office].street', 'children[address].data.office.street.prop'), + array(self::LEVEL_1, 'address', '[address]', 'street', '[office].street', 'children[address].data.office[street]'), + array(self::LEVEL_1, 'address', '[address]', 'street', '[office].street', 'children[address].data.office[street].prop'), + array(self::LEVEL_1, 'address', '[address]', 'street', '[office].street', 'children[address].data[office]'), + array(self::LEVEL_2, 'address', '[address]', 'street', '[office].street', 'children[address].data[office].street'), + array(self::LEVEL_2, 'address', '[address]', 'street', '[office].street', 'children[address].data[office].street.prop'), + array(self::LEVEL_1, 'address', '[address]', 'street', '[office].street', 'children[address].data[office][street]'), + array(self::LEVEL_1, 'address', '[address]', 'street', '[office].street', 'children[address].data[office][street].prop'), + array(self::LEVEL_0, 'address', '[address]', 'street', '[office].street', 'data.address.office.street'), + array(self::LEVEL_0, 'address', '[address]', 'street', '[office].street', 'data.address.office.street.prop'), + array(self::LEVEL_0, 'address', '[address]', 'street', '[office].street', 'data.address.office[street]'), + array(self::LEVEL_0, 'address', '[address]', 'street', '[office].street', 'data.address.office[street].prop'), + array(self::LEVEL_0, 'address', '[address]', 'street', '[office].street', 'data.address[office].street'), + array(self::LEVEL_0, 'address', '[address]', 'street', '[office].street', 'data.address[office].street.prop'), + array(self::LEVEL_0, 'address', '[address]', 'street', '[office].street', 'data.address[office][street]'), + array(self::LEVEL_0, 'address', '[address]', 'street', '[office].street', 'data.address[office][street].prop'), + array(self::LEVEL_1, 'address', '[address]', 'street', '[office].street', 'data[address].office.street'), + array(self::LEVEL_1, 'address', '[address]', 'street', '[office].street', 'data[address].office.street.prop'), + array(self::LEVEL_1, 'address', '[address]', 'street', '[office].street', 'data[address].office[street]'), + array(self::LEVEL_1, 'address', '[address]', 'street', '[office].street', 'data[address].office[street].prop'), + array(self::LEVEL_2, 'address', '[address]', 'street', '[office].street', 'data[address][office].street'), + array(self::LEVEL_2, 'address', '[address]', 'street', '[office].street', 'data[address][office].street.prop'), + array(self::LEVEL_1, 'address', '[address]', 'street', '[office].street', 'data[address][office][street]'), + array(self::LEVEL_1, 'address', '[address]', 'street', '[office].street', 'data[address][office][street].prop'), + + array(self::LEVEL_2, 'address', 'address', 'street', '[office][street]', 'children[address].children[street].data'), + array(self::LEVEL_2, 'address', 'address', 'street', '[office][street]', 'children[address].children[street].data.prop'), + array(self::LEVEL_1, 'address', 'address', 'street', '[office][street]', 'children[address].data'), + array(self::LEVEL_1, 'address', 'address', 'street', '[office][street]', 'children[address].data.office'), + array(self::LEVEL_1, 'address', 'address', 'street', '[office][street]', 'children[address].data.office.street'), + array(self::LEVEL_1, 'address', 'address', 'street', '[office][street]', 'children[address].data.office.street.prop'), + array(self::LEVEL_1, 'address', 'address', 'street', '[office][street]', 'children[address].data.office[street]'), + array(self::LEVEL_1, 'address', 'address', 'street', '[office][street]', 'children[address].data.office[street].prop'), + array(self::LEVEL_1, 'address', 'address', 'street', '[office][street]', 'children[address].data[office]'), + array(self::LEVEL_1, 'address', 'address', 'street', '[office][street]', 'children[address].data[office].street'), + array(self::LEVEL_1, 'address', 'address', 'street', '[office][street]', 'children[address].data[office].street.prop'), + array(self::LEVEL_2, 'address', 'address', 'street', '[office][street]', 'children[address].data[office][street]'), + array(self::LEVEL_2, 'address', 'address', 'street', '[office][street]', 'children[address].data[office][street].prop'), + array(self::LEVEL_1, 'address', 'address', 'street', '[office][street]', 'data.address.office.street'), + array(self::LEVEL_1, 'address', 'address', 'street', '[office][street]', 'data.address.office.street.prop'), + array(self::LEVEL_1, 'address', 'address', 'street', '[office][street]', 'data.address.office[street]'), + array(self::LEVEL_1, 'address', 'address', 'street', '[office][street]', 'data.address.office[street].prop'), + array(self::LEVEL_1, 'address', 'address', 'street', '[office][street]', 'data.address[office].street'), + array(self::LEVEL_1, 'address', 'address', 'street', '[office][street]', 'data.address[office].street.prop'), + array(self::LEVEL_2, 'address', 'address', 'street', '[office][street]', 'data.address[office][street]'), + array(self::LEVEL_2, 'address', 'address', 'street', '[office][street]', 'data.address[office][street].prop'), + array(self::LEVEL_0, 'address', 'address', 'street', '[office][street]', 'data[address].office.street'), + array(self::LEVEL_0, 'address', 'address', 'street', '[office][street]', 'data[address].office.street.prop'), + array(self::LEVEL_0, 'address', 'address', 'street', '[office][street]', 'data[address].office[street]'), + array(self::LEVEL_0, 'address', 'address', 'street', '[office][street]', 'data[address].office[street].prop'), + array(self::LEVEL_0, 'address', 'address', 'street', '[office][street]', 'data[address][office].street'), + array(self::LEVEL_0, 'address', 'address', 'street', '[office][street]', 'data[address][office].street.prop'), + array(self::LEVEL_0, 'address', 'address', 'street', '[office][street]', 'data[address][office][street]'), + array(self::LEVEL_0, 'address', 'address', 'street', '[office][street]', 'data[address][office][street].prop'), + + array(self::LEVEL_2, 'address', '[address]', 'street', '[office][street]', 'children[address].children[street].data'), + array(self::LEVEL_2, 'address', '[address]', 'street', '[office][street]', 'children[address].children[street].data.prop'), + array(self::LEVEL_1, 'address', '[address]', 'street', '[office][street]', 'children[address].data'), + array(self::LEVEL_1, 'address', '[address]', 'street', '[office][street]', 'children[address].data.office'), + array(self::LEVEL_1, 'address', '[address]', 'street', '[office][street]', 'children[address].data.office.street'), + array(self::LEVEL_1, 'address', '[address]', 'street', '[office][street]', 'children[address].data.office.street.prop'), + array(self::LEVEL_1, 'address', '[address]', 'street', '[office][street]', 'children[address].data.office[street]'), + array(self::LEVEL_1, 'address', '[address]', 'street', '[office][street]', 'children[address].data.office[street].prop'), + array(self::LEVEL_1, 'address', '[address]', 'street', '[office][street]', 'children[address].data[office]'), + array(self::LEVEL_1, 'address', '[address]', 'street', '[office][street]', 'children[address].data[office].street'), + array(self::LEVEL_1, 'address', '[address]', 'street', '[office][street]', 'children[address].data[office].street.prop'), + array(self::LEVEL_2, 'address', '[address]', 'street', '[office][street]', 'children[address].data[office][street]'), + array(self::LEVEL_2, 'address', '[address]', 'street', '[office][street]', 'children[address].data[office][street].prop'), + array(self::LEVEL_0, 'address', '[address]', 'street', '[office][street]', 'data.address.office.street'), + array(self::LEVEL_0, 'address', '[address]', 'street', '[office][street]', 'data.address.office.street.prop'), + array(self::LEVEL_0, 'address', '[address]', 'street', '[office][street]', 'data.address.office[street]'), + array(self::LEVEL_0, 'address', '[address]', 'street', '[office][street]', 'data.address.office[street].prop'), + array(self::LEVEL_0, 'address', '[address]', 'street', '[office][street]', 'data.address[office].street'), + array(self::LEVEL_0, 'address', '[address]', 'street', '[office][street]', 'data.address[office].street.prop'), + array(self::LEVEL_0, 'address', '[address]', 'street', '[office][street]', 'data.address[office][street]'), + array(self::LEVEL_0, 'address', '[address]', 'street', '[office][street]', 'data.address[office][street].prop'), + array(self::LEVEL_1, 'address', '[address]', 'street', '[office][street]', 'data[address].office.street'), + array(self::LEVEL_1, 'address', '[address]', 'street', '[office][street]', 'data[address].office.street.prop'), + array(self::LEVEL_1, 'address', '[address]', 'street', '[office][street]', 'data[address].office[street]'), + array(self::LEVEL_1, 'address', '[address]', 'street', '[office][street]', 'data[address].office[street].prop'), + array(self::LEVEL_1, 'address', '[address]', 'street', '[office][street]', 'data[address][office].street'), + array(self::LEVEL_1, 'address', '[address]', 'street', '[office][street]', 'data[address][office].street.prop'), + array(self::LEVEL_2, 'address', '[address]', 'street', '[office][street]', 'data[address][office][street]'), + array(self::LEVEL_2, 'address', '[address]', 'street', '[office][street]', 'data[address][office][street].prop'), + + // Edge cases which must not occur + array(self::LEVEL_1, 'address', 'address', 'street', 'street', 'children[address][street]'), + array(self::LEVEL_1, 'address', 'address', 'street', 'street', 'children[address][street].prop'), + array(self::LEVEL_1, 'address', 'address', 'street', '[street]', 'children[address][street]'), + array(self::LEVEL_1, 'address', 'address', 'street', '[street]', 'children[address][street].prop'), + array(self::LEVEL_1, 'address', '[address]', 'street', 'street', 'children[address][street]'), + array(self::LEVEL_1, 'address', '[address]', 'street', 'street', 'children[address][street].prop'), + array(self::LEVEL_1, 'address', '[address]', 'street', '[street]', 'children[address][street]'), + array(self::LEVEL_1, 'address', '[address]', 'street', '[street]', 'children[address][street].prop'), + + array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'children[person].children[address].children[street]'), + array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'children[person].children[address].data.street'), + array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'children[person].data.address.street'), + array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'data.address.street'), + + array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'children[address].children[office].children[street]'), + array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'children[address].children[office].data.street'), + array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'children[address].data.street'), + array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'data.address.street'), + ); + } + + /** + * @dataProvider provideDefaultTests + */ + public function testDefaultErrorMapping($target, $childName, $childPath, $grandChildName, $grandChildPath, $violationPath) + { + $violation = $this->getConstraintViolation($violationPath); + $parent = $this->getForm('parent'); + $child = $this->getForm($childName, $childPath); + $grandChild = $this->getForm($grandChildName, $grandChildPath); + + $parent->add($child); + $child->add($grandChild); + + $this->mapper->mapViolation($violation, $parent); + + if (self::LEVEL_0 === $target) { + $this->assertEquals(array($this->getFormError()), $parent->getErrors(), $parent->getName().' should have an error, but has none'); + $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one'); + $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one'); + } elseif (self::LEVEL_1 === $target) { + $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); + $this->assertEquals(array($this->getFormError()), $child->getErrors(), $childName.' should have an error, but has none'); + $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one'); + } else { + $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); + $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one'); + $this->assertEquals(array($this->getFormError()), $grandChild->getErrors(), $grandChildName.' should have an error, but has none'); + } + } + + public function provideCustomDataErrorTests() + { + return array( + // mapping target, error mapping, child name, its property path, grand child name, its property path, violation path + array(self::LEVEL_1, 'foo', 'address', 'address', 'address', 'street', 'street', 'data.foo'), + array(self::LEVEL_1, 'foo', 'address', 'address', 'address', 'street', 'street', 'data.foo.prop'), + array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', 'street', 'data[foo]'), + array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', 'street', 'data[foo].prop'), + + array(self::LEVEL_1, 'foo', 'address', 'address', 'address', 'street', 'street', 'data.address'), + array(self::LEVEL_1, 'foo', 'address', 'address', 'address', 'street', 'street', 'data.address.prop'), + array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', 'street', 'data[address]'), + array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', 'street', 'data[address].prop'), + + array(self::LEVEL_1, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.foo'), + array(self::LEVEL_1, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.foo.prop'), + array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[foo]'), + array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[foo].prop'), + + array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.address'), + array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.address.prop'), + array(self::LEVEL_1, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[address]'), + array(self::LEVEL_1, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[address].prop'), + + array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.foo'), + array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.foo.prop'), + array(self::LEVEL_1, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[foo]'), + array(self::LEVEL_1, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[foo].prop'), + + array(self::LEVEL_1, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.address'), + array(self::LEVEL_1, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.address.prop'), + array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[address]'), + array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[address].prop'), + + array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data.foo'), + array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data.foo.prop'), + array(self::LEVEL_1, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data[foo]'), + array(self::LEVEL_1, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data[foo].prop'), + + array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data.address'), + array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data.address.prop'), + array(self::LEVEL_1, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data[address]'), + array(self::LEVEL_1, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data[address].prop'), + + array(self::LEVEL_2, 'foo', 'address', 'address', 'address', 'street', 'street', 'data.foo.street'), + array(self::LEVEL_2, 'foo', 'address', 'address', 'address', 'street', 'street', 'data.foo.street.prop'), + array(self::LEVEL_1, 'foo', 'address', 'address', 'address', 'street', 'street', 'data.foo[street]'), + array(self::LEVEL_1, 'foo', 'address', 'address', 'address', 'street', 'street', 'data.foo[street].prop'), + array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', 'street', 'data[foo].street'), + array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', 'street', 'data[foo].street.prop'), + array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', 'street', 'data[foo][street]'), + array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', 'street', 'data[foo][street].prop'), + + array(self::LEVEL_2, 'foo', 'address', 'address', 'address', 'street', 'street', 'data.address.street'), + array(self::LEVEL_2, 'foo', 'address', 'address', 'address', 'street', 'street', 'data.address.street.prop'), + array(self::LEVEL_1, 'foo', 'address', 'address', 'address', 'street', 'street', 'data.address[street]'), + array(self::LEVEL_1, 'foo', 'address', 'address', 'address', 'street', 'street', 'data.address[street].prop'), + array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', 'street', 'data[address].street'), + array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', 'street', 'data[address].street.prop'), + array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', 'street', 'data[address][street]'), + array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', 'street', 'data[address][street].prop'), + + array(self::LEVEL_1, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data.foo.street'), + array(self::LEVEL_1, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data.foo.street.prop'), + array(self::LEVEL_2, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data.foo[street]'), + array(self::LEVEL_2, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data.foo[street].prop'), + array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data[foo].street'), + array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data[foo].street.prop'), + array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data[foo][street]'), + array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data[foo][street].prop'), + + array(self::LEVEL_1, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data.address.street'), + array(self::LEVEL_1, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data.address.street.prop'), + array(self::LEVEL_2, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data.address[street]'), + array(self::LEVEL_2, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data.address[street].prop'), + array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data[address].street'), + array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data[address].street.prop'), + array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data[address][street]'), + array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data[address][street].prop'), + + array(self::LEVEL_2, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.foo.street'), + array(self::LEVEL_2, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.foo.street.prop'), + array(self::LEVEL_1, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.foo[street]'), + array(self::LEVEL_1, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.foo[street].prop'), + array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[foo].street'), + array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[foo].street.prop'), + array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[foo][street]'), + array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[foo][street].prop'), + + array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.address.street'), + array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.address.street.prop'), + array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.address[street]'), + array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.address[street].prop'), + array(self::LEVEL_2, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[address].street'), + array(self::LEVEL_2, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[address].street.prop'), + array(self::LEVEL_1, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[address][street]'), + array(self::LEVEL_1, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[address][street].prop'), + + array(self::LEVEL_1, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data.foo.street'), + array(self::LEVEL_1, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data.foo.street.prop'), + array(self::LEVEL_2, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data.foo[street]'), + array(self::LEVEL_2, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data.foo[street].prop'), + array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data[foo].street'), + array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data[foo].street.prop'), + array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data[foo][street]'), + array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data[foo][street].prop'), + + array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data.address.street'), + array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data.address.street.prop'), + array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data.address[street]'), + array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data.address[street].prop'), + array(self::LEVEL_1, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data[address].street'), + array(self::LEVEL_1, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data[address].street.prop'), + array(self::LEVEL_2, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data[address][street]'), + array(self::LEVEL_2, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data[address][street].prop'), + + array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.foo.street'), + array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.foo.street.prop'), + array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.foo[street]'), + array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.foo[street].prop'), + array(self::LEVEL_2, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[foo].street'), + array(self::LEVEL_2, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[foo].street.prop'), + array(self::LEVEL_1, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[foo][street]'), + array(self::LEVEL_1, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[foo][street].prop'), + + array(self::LEVEL_2, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.address.street'), + array(self::LEVEL_2, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.address.street.prop'), + array(self::LEVEL_1, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.address[street]'), + array(self::LEVEL_1, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.address[street].prop'), + array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[address].street'), + array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[address].street.prop'), + array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[address][street]'), + array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[address][street].prop'), + + array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data.foo.street'), + array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data.foo.street.prop'), + array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data.foo[street]'), + array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data.foo[street].prop'), + array(self::LEVEL_1, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data[foo].street'), + array(self::LEVEL_1, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data[foo].street.prop'), + array(self::LEVEL_2, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data[foo][street]'), + array(self::LEVEL_2, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data[foo][street].prop'), + + array(self::LEVEL_1, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data.address.street'), + array(self::LEVEL_1, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data.address.street.prop'), + array(self::LEVEL_2, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data.address[street]'), + array(self::LEVEL_2, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data.address[street].prop'), + array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data[address].street'), + array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data[address].street.prop'), + array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data[address][street]'), + array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data[address][street].prop'), + + array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data.foo.street'), + array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data.foo.street.prop'), + array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data.foo[street]'), + array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data.foo[street].prop'), + array(self::LEVEL_2, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data[foo].street'), + array(self::LEVEL_2, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data[foo].street.prop'), + array(self::LEVEL_1, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data[foo][street]'), + array(self::LEVEL_1, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data[foo][street].prop'), + + array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data.address.street'), + array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data.address.street.prop'), + array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data.address[street]'), + array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data.address[street].prop'), + array(self::LEVEL_2, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data[address].street'), + array(self::LEVEL_2, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data[address].street.prop'), + array(self::LEVEL_1, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data[address][street]'), + array(self::LEVEL_1, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data[address][street].prop'), + + array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data.foo.street'), + array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data.foo.street.prop'), + array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data.foo[street]'), + array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data.foo[street].prop'), + array(self::LEVEL_1, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data[foo].street'), + array(self::LEVEL_1, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data[foo].street.prop'), + array(self::LEVEL_2, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data[foo][street]'), + array(self::LEVEL_2, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data[foo][street].prop'), + + array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data.address.street'), + array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data.address.street.prop'), + array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data.address[street]'), + array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data.address[street].prop'), + array(self::LEVEL_1, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data[address].street'), + array(self::LEVEL_1, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data[address].street.prop'), + array(self::LEVEL_2, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data[address][street]'), + array(self::LEVEL_2, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data[address][street].prop'), + + array(self::LEVEL_1, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar'), + array(self::LEVEL_1, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar.prop'), + array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar]'), + array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar].prop'), + array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar'), + array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar.prop'), + array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar]'), + array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar].prop'), + + array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar'), + array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar.prop'), + array(self::LEVEL_1, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar]'), + array(self::LEVEL_1, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar].prop'), + array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar'), + array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar.prop'), + array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar]'), + array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar].prop'), + + array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar'), + array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar.prop'), + array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar]'), + array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar].prop'), + array(self::LEVEL_1, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar'), + array(self::LEVEL_1, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar.prop'), + array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar]'), + array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar].prop'), + + array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar'), + array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar.prop'), + array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar]'), + array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar].prop'), + array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar'), + array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar.prop'), + array(self::LEVEL_1, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar]'), + array(self::LEVEL_1, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar].prop'), + + array(self::LEVEL_2, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar.street'), + array(self::LEVEL_2, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar.street.prop'), + array(self::LEVEL_1, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar[street]'), + array(self::LEVEL_1, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar[street].prop'), + array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar].street'), + array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar].street.prop'), + array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar][street]'), + array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar][street].prop'), + array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar.street'), + array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar.street.prop'), + array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar[street]'), + array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar[street].prop'), + array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar].street'), + array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar].street.prop'), + array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar][street]'), + array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar][street].prop'), + + array(self::LEVEL_1, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar.street'), + array(self::LEVEL_1, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar.street.prop'), + array(self::LEVEL_2, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar[street]'), + array(self::LEVEL_2, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar[street].prop'), + array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar].street'), + array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar].street.prop'), + array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar][street]'), + array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar][street].prop'), + array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar.street'), + array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar.street.prop'), + array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar[street]'), + array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar[street].prop'), + array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar].street'), + array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar].street.prop'), + array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar][street]'), + array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar][street].prop'), + + array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar.street'), + array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar.street.prop'), + array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar[street]'), + array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar[street].prop'), + array(self::LEVEL_2, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar].street'), + array(self::LEVEL_2, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar].street.prop'), + array(self::LEVEL_1, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar][street]'), + array(self::LEVEL_1, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar][street].prop'), + array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar.street'), + array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar.street.prop'), + array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar[street]'), + array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar[street].prop'), + array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar].street'), + array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar].street.prop'), + array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar][street]'), + array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar][street].prop'), + + array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar.street'), + array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar.street.prop'), + array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar[street]'), + array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar[street].prop'), + array(self::LEVEL_1, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar].street'), + array(self::LEVEL_1, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar].street.prop'), + array(self::LEVEL_2, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar][street]'), + array(self::LEVEL_2, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar][street].prop'), + array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar.street'), + array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar.street.prop'), + array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar[street]'), + array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar[street].prop'), + array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar].street'), + array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar].street.prop'), + array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar][street]'), + array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar][street].prop'), + + array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar.street'), + array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar.street.prop'), + array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar[street]'), + array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar[street].prop'), + array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar].street'), + array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar].street.prop'), + array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar][street]'), + array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar][street].prop'), + array(self::LEVEL_2, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar.street'), + array(self::LEVEL_2, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar.street.prop'), + array(self::LEVEL_1, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar[street]'), + array(self::LEVEL_1, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar[street].prop'), + array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar].street'), + array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar].street.prop'), + array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar][street]'), + array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar][street].prop'), + + array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar.street'), + array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar.street.prop'), + array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar[street]'), + array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar[street].prop'), + array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar].street'), + array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar].street.prop'), + array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar][street]'), + array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar][street].prop'), + array(self::LEVEL_1, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar.street'), + array(self::LEVEL_1, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar.street.prop'), + array(self::LEVEL_2, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar[street]'), + array(self::LEVEL_2, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar[street].prop'), + array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar].street'), + array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar].street.prop'), + array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar][street]'), + array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar][street].prop'), + + array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar.street'), + array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar.street.prop'), + array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar[street]'), + array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar[street].prop'), + array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar].street'), + array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar].street.prop'), + array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar][street]'), + array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar][street].prop'), + array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar.street'), + array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar.street.prop'), + array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar[street]'), + array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar[street].prop'), + array(self::LEVEL_2, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar].street'), + array(self::LEVEL_2, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar].street.prop'), + array(self::LEVEL_1, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar][street]'), + array(self::LEVEL_1, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar][street].prop'), + + array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar.street'), + array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar.street.prop'), + array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar[street]'), + array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar[street].prop'), + array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar].street'), + array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar].street.prop'), + array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar][street]'), + array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar][street].prop'), + array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar.street'), + array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar.street.prop'), + array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar[street]'), + array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar[street].prop'), + array(self::LEVEL_1, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar].street'), + array(self::LEVEL_1, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar].street.prop'), + array(self::LEVEL_2, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar][street]'), + array(self::LEVEL_2, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar][street].prop'), + + array(self::LEVEL_2, 'foo', 'address.street', 'address', 'address', 'street', 'street', 'data.foo'), + array(self::LEVEL_2, 'foo', 'address.street', 'address', 'address', 'street', 'street', 'data.foo.prop'), + array(self::LEVEL_2, '[foo]', 'address.street', 'address', 'address', 'street', 'street', 'data[foo]'), + array(self::LEVEL_2, '[foo]', 'address.street', 'address', 'address', 'street', 'street', 'data[foo].prop'), + + array(self::LEVEL_2, 'foo', 'address.street', 'address', 'address', 'street', '[street]', 'data.foo'), + array(self::LEVEL_2, 'foo', 'address.street', 'address', 'address', 'street', '[street]', 'data.foo.prop'), + array(self::LEVEL_2, '[foo]', 'address.street', 'address', 'address', 'street', '[street]', 'data[foo]'), + array(self::LEVEL_2, '[foo]', 'address.street', 'address', 'address', 'street', '[street]', 'data[foo].prop'), + + array(self::LEVEL_2, 'foo', 'address.street', 'address', '[address]', 'street', 'street', 'data.foo'), + array(self::LEVEL_2, 'foo', 'address.street', 'address', '[address]', 'street', 'street', 'data.foo.prop'), + array(self::LEVEL_2, '[foo]', 'address.street', 'address', '[address]', 'street', 'street', 'data[foo]'), + array(self::LEVEL_2, '[foo]', 'address.street', 'address', '[address]', 'street', 'street', 'data[foo].prop'), + + array(self::LEVEL_2, 'foo.bar', 'address.street', 'address', 'address', 'street', 'street', 'data.foo.bar'), + array(self::LEVEL_2, 'foo.bar', 'address.street', 'address', 'address', 'street', 'street', 'data.foo.bar.prop'), + array(self::LEVEL_2, 'foo[bar]', 'address.street', 'address', 'address', 'street', 'street', 'data.foo[bar]'), + array(self::LEVEL_2, 'foo[bar]', 'address.street', 'address', 'address', 'street', 'street', 'data.foo[bar].prop'), + array(self::LEVEL_2, '[foo].bar', 'address.street', 'address', 'address', 'street', 'street', 'data[foo].bar'), + array(self::LEVEL_2, '[foo].bar', 'address.street', 'address', 'address', 'street', 'street', 'data[foo].bar.prop'), + array(self::LEVEL_2, '[foo][bar]', 'address.street', 'address', 'address', 'street', 'street', 'data[foo][bar]'), + array(self::LEVEL_2, '[foo][bar]', 'address.street', 'address', 'address', 'street', 'street', 'data[foo][bar].prop'), + + array(self::LEVEL_2, 'foo.bar', 'address.street', 'address', 'address', 'street', '[street]', 'data.foo.bar'), + array(self::LEVEL_2, 'foo.bar', 'address.street', 'address', 'address', 'street', '[street]', 'data.foo.bar.prop'), + array(self::LEVEL_2, 'foo[bar]', 'address.street', 'address', 'address', 'street', '[street]', 'data.foo[bar]'), + array(self::LEVEL_2, 'foo[bar]', 'address.street', 'address', 'address', 'street', '[street]', 'data.foo[bar].prop'), + array(self::LEVEL_2, '[foo].bar', 'address.street', 'address', 'address', 'street', '[street]', 'data[foo].bar'), + array(self::LEVEL_2, '[foo].bar', 'address.street', 'address', 'address', 'street', '[street]', 'data[foo].bar.prop'), + array(self::LEVEL_2, '[foo][bar]', 'address.street', 'address', 'address', 'street', '[street]', 'data[foo][bar]'), + array(self::LEVEL_2, '[foo][bar]', 'address.street', 'address', 'address', 'street', '[street]', 'data[foo][bar].prop'), + + array(self::LEVEL_2, 'foo.bar', 'address.street', 'address', '[address]', 'street', 'street', 'data.foo.bar'), + array(self::LEVEL_2, 'foo.bar', 'address.street', 'address', '[address]', 'street', 'street', 'data.foo.bar.prop'), + array(self::LEVEL_2, 'foo[bar]', 'address.street', 'address', '[address]', 'street', 'street', 'data.foo[bar]'), + array(self::LEVEL_2, 'foo[bar]', 'address.street', 'address', '[address]', 'street', 'street', 'data.foo[bar].prop'), + array(self::LEVEL_2, '[foo].bar', 'address.street', 'address', '[address]', 'street', 'street', 'data[foo].bar'), + array(self::LEVEL_2, '[foo].bar', 'address.street', 'address', '[address]', 'street', 'street', 'data[foo].bar.prop'), + array(self::LEVEL_2, '[foo][bar]', 'address.street', 'address', '[address]', 'street', 'street', 'data[foo][bar]'), + array(self::LEVEL_2, '[foo][bar]', 'address.street', 'address', '[address]', 'street', 'street', 'data[foo][bar].prop'), + + // Edge cases + array(self::LEVEL_2, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.foo.street'), + array(self::LEVEL_2, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.foo.street.prop'), + array(self::LEVEL_1, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.foo[street]'), + array(self::LEVEL_1, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.foo[street].prop'), + array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[foo].street'), + array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[foo].street.prop'), + array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[foo][street]'), + array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[foo][street].prop'), + + array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.foo.street'), + array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.foo.street.prop'), + array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.foo[street]'), + array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.foo[street].prop'), + array(self::LEVEL_2, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[foo].street'), + array(self::LEVEL_2, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[foo].street.prop'), + array(self::LEVEL_1, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[foo][street]'), + array(self::LEVEL_1, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[foo][street].prop'), + ); + } + + /** + * @dataProvider provideCustomDataErrorTests + */ + public function testCustomDataErrorMapping($target, $mapFrom, $mapTo, $childName, $childPath, $grandChildName, $grandChildPath, $violationPath) + { + $violation = $this->getConstraintViolation($violationPath); + $parent = $this->getForm('parent', null, null, array($mapFrom => $mapTo)); + $child = $this->getForm($childName, $childPath); + $grandChild = $this->getForm($grandChildName, $grandChildPath); + + $parent->add($child); + $child->add($grandChild); + + // Add a field mapped to the first element of $mapFrom + // to try to distract the algorithm + // Only add it if we expect the error to come up on a different + // level than LEVEL_0, because in this case the error would + // (correctly) be mapped to the distraction field + if ($target !== self::LEVEL_0) { + $mapFromPath = new PropertyPath($mapFrom); + $mapFromPrefix = $mapFromPath->isIndex(0) + ? '['.$mapFromPath->getElement(0).']' + : $mapFromPath->getElement(0); + $distraction = $this->getForm('distraction', $mapFromPrefix); + + $parent->add($distraction); + } + + $this->mapper->mapViolation($violation, $parent); + + if ($target !== self::LEVEL_0) { + $this->assertCount(0, $distraction->getErrors(), 'distraction should not have an error, but has one'); + } + + if (self::LEVEL_0 === $target) { + $this->assertEquals(array($this->getFormError()), $parent->getErrors(), $parent->getName().' should have an error, but has none'); + $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one'); + $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one'); + } elseif (self::LEVEL_1 === $target) { + $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); + $this->assertEquals(array($this->getFormError()), $child->getErrors(), $childName.' should have an error, but has none'); + $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one'); + } else { + $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); + $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one'); + $this->assertEquals(array($this->getFormError()), $grandChild->getErrors(), $grandChildName.' should have an error, but has none'); + } + } + + public function provideCustomFormErrorTests() + { + // This case is different than the data errors, because here the + // left side of the mapping refers to the property path of the actual + // children. In other words, a child error only works if + // 1) the error actually maps to an existing child and + // 2) the property path of that child (relative to the form providing + // the mapping) matches the left side of the mapping + return array( + // mapping target, map from, map to, child name, its property path, grand child name, its property path, violation path + array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[foo].children[street].data'), + array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[foo].children[street].data.prop'), + array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[foo].data.street'), + array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[foo].data.street.prop'), + array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[foo].data[street]'), + array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[foo].data[street].prop'), + + array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].children[street].data'), + array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].children[street].data.prop'), + array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].data.street'), + array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].data.street.prop'), + array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].data[street]'), + array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].data[street].prop'), + + // Property path of the erroneous field and mapping must match exactly + array(self::LEVEL_1B, 'foo', 'address', 'foo', '[foo]', 'address', 'address', 'street', 'street', 'children[foo].children[street].data'), + array(self::LEVEL_1B, 'foo', 'address', 'foo', '[foo]', 'address', 'address', 'street', 'street', 'children[foo].children[street].data.prop'), + array(self::LEVEL_1B, 'foo', 'address', 'foo', '[foo]', 'address', 'address', 'street', 'street', 'children[foo].data.street'), + array(self::LEVEL_1B, 'foo', 'address', 'foo', '[foo]', 'address', 'address', 'street', 'street', 'children[foo].data.street.prop'), + array(self::LEVEL_1B, 'foo', 'address', 'foo', '[foo]', 'address', 'address', 'street', 'street', 'children[foo].data[street]'), + array(self::LEVEL_1B, 'foo', 'address', 'foo', '[foo]', 'address', 'address', 'street', 'street', 'children[foo].data[street].prop'), + + array(self::LEVEL_1B, '[foo]', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[foo].children[street].data'), + array(self::LEVEL_1B, '[foo]', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[foo].children[street].data.prop'), + array(self::LEVEL_1B, '[foo]', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[foo].data.street'), + array(self::LEVEL_1B, '[foo]', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[foo].data.street.prop'), + array(self::LEVEL_1B, '[foo]', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[foo].data[street]'), + array(self::LEVEL_1B, '[foo]', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[foo].data[street].prop'), + + array(self::LEVEL_1, '[foo]', 'address', 'foo', '[foo]', 'address', 'address', 'street', 'street', 'children[foo].children[street].data'), + array(self::LEVEL_1, '[foo]', 'address', 'foo', '[foo]', 'address', 'address', 'street', 'street', 'children[foo].children[street].data.prop'), + array(self::LEVEL_2, '[foo]', 'address', 'foo', '[foo]', 'address', 'address', 'street', 'street', 'children[foo].data.street'), + array(self::LEVEL_2, '[foo]', 'address', 'foo', '[foo]', 'address', 'address', 'street', 'street', 'children[foo].data.street.prop'), + array(self::LEVEL_1, '[foo]', 'address', 'foo', '[foo]', 'address', 'address', 'street', 'street', 'children[foo].data[street]'), + array(self::LEVEL_1, '[foo]', 'address', 'foo', '[foo]', 'address', 'address', 'street', 'street', 'children[foo].data[street].prop'), + + array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[foo].children[street].data'), + array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[foo].children[street].data.prop'), + array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[foo].data.street'), + array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[foo].data.street.prop'), + array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[foo].data[street]'), + array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[foo].data[street].prop'), + + array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].children[street].data'), + array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].children[street].data.prop'), + array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].data.street'), + array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].data.street.prop'), + array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].data[street]'), + array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].data[street].prop'), + + array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[foo].children[street].data'), + array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[foo].children[street].data.prop'), + array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[foo].data.street'), + array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[foo].data.street.prop'), + array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[foo].data[street]'), + array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[foo].data[street].prop'), + + array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].children[street].data'), + array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].children[street].data.prop'), + array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].data.street'), + array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].data.street.prop'), + array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].data[street]'), + array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].data[street].prop'), + + array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[foo].children[street].data'), + array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[foo].children[street].data.prop'), + array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[foo].data.street'), + array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[foo].data.street.prop'), + array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[foo].data[street]'), + array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[foo].data[street].prop'), + + array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].children[street].data'), + array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].children[street].data.prop'), + array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].data.street'), + array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].data.street.prop'), + array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].data[street]'), + array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].data[street].prop'), + + // Map to a nested child + array(self::LEVEL_2, 'foo', 'address.street', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[foo]'), + array(self::LEVEL_2, 'foo', 'address.street', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[foo]'), + array(self::LEVEL_2, 'foo', 'address.street', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[foo]'), + array(self::LEVEL_2, 'foo', 'address.street', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[foo]'), + + // Map from a nested child + array(self::LEVEL_1B, 'address.street', 'foo', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].children[street]'), + array(self::LEVEL_1B, 'address.street', 'foo', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].data.street'), + array(self::LEVEL_1, 'address.street', 'foo', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].data[street]'), + array(self::LEVEL_2, 'address.street', 'foo', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].children[street]'), + array(self::LEVEL_1B, 'address.street', 'foo', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].data.street'), + array(self::LEVEL_2, 'address.street', 'foo', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].data[street]'), + array(self::LEVEL_2, 'address.street', 'foo', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].children[street]'), + array(self::LEVEL_2, 'address.street', 'foo', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].data.street'), + array(self::LEVEL_1, 'address.street', 'foo', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].data[street]'), + array(self::LEVEL_2, 'address.street', 'foo', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].children[street]'), + array(self::LEVEL_1, 'address.street', 'foo', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].data.street'), + array(self::LEVEL_2, 'address.street', 'foo', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].data[street]'), + + array(self::LEVEL_2, 'address[street]', 'foo', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].children[street]'), + array(self::LEVEL_2, 'address[street]', 'foo', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].data.street'), + array(self::LEVEL_1B, 'address[street]', 'foo', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].data[street]'), + array(self::LEVEL_1B, 'address[street]', 'foo', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].children[street]'), + array(self::LEVEL_1, 'address[street]', 'foo', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].data.street'), + array(self::LEVEL_1B, 'address[street]', 'foo', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].data[street]'), + array(self::LEVEL_2, 'address[street]', 'foo', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].children[street]'), + array(self::LEVEL_2, 'address[street]', 'foo', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].data.street'), + array(self::LEVEL_1, 'address[street]', 'foo', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].data[street]'), + array(self::LEVEL_2, 'address[street]', 'foo', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].children[street]'), + array(self::LEVEL_1, 'address[street]', 'foo', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].data.street'), + array(self::LEVEL_2, 'address[street]', 'foo', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].data[street]'), + + array(self::LEVEL_2, '[address].street', 'foo', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].children[street]'), + array(self::LEVEL_2, '[address].street', 'foo', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].data.street'), + array(self::LEVEL_1, '[address].street', 'foo', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].data[street]'), + array(self::LEVEL_2, '[address].street', 'foo', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].children[street]'), + array(self::LEVEL_1, '[address].street', 'foo', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].data.street'), + array(self::LEVEL_2, '[address].street', 'foo', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].data[street]'), + array(self::LEVEL_1B, '[address].street', 'foo', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].children[street]'), + array(self::LEVEL_1B, '[address].street', 'foo', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].data.street'), + array(self::LEVEL_1, '[address].street', 'foo', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].data[street]'), + array(self::LEVEL_2, '[address].street', 'foo', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].children[street]'), + array(self::LEVEL_1B, '[address].street', 'foo', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].data.street'), + array(self::LEVEL_2, '[address].street', 'foo', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].data[street]'), + + array(self::LEVEL_2, '[address][street]', 'foo', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].children[street]'), + array(self::LEVEL_2, '[address][street]', 'foo', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].data.street'), + array(self::LEVEL_1, '[address][street]', 'foo', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].data[street]'), + array(self::LEVEL_2, '[address][street]', 'foo', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].children[street]'), + array(self::LEVEL_1, '[address][street]', 'foo', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].data.street'), + array(self::LEVEL_2, '[address][street]', 'foo', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].data[street]'), + array(self::LEVEL_2, '[address][street]', 'foo', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].children[street]'), + array(self::LEVEL_2, '[address][street]', 'foo', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].data.street'), + array(self::LEVEL_1B, '[address][street]', 'foo', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].data[street]'), + array(self::LEVEL_1B, '[address][street]', 'foo', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].children[street]'), + array(self::LEVEL_1, '[address][street]', 'foo', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].data.street'), + array(self::LEVEL_1B, '[address][street]', 'foo', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].data[street]'), + ); + } + + /** + * @dataProvider provideCustomFormErrorTests + */ + public function testCustomFormErrorMapping($target, $mapFrom, $mapTo, $errorName, $errorPath, $childName, $childPath, $grandChildName, $grandChildPath, $violationPath) + { + $violation = $this->getConstraintViolation($violationPath); + $parent = $this->getForm('parent', null, null, array($mapFrom => $mapTo)); + $child = $this->getForm($childName, $childPath); + $grandChild = $this->getForm($grandChildName, $grandChildPath); + $errorChild = $this->getForm($errorName, $errorPath); + + $parent->add($child); + $parent->add($errorChild); + $child->add($grandChild); + + $this->mapper->mapViolation($violation, $parent); + + if (self::LEVEL_0 === $target) { + $this->assertCount(0, $errorChild->getErrors(), $errorName.' should not have an error, but has one'); + $this->assertEquals(array($this->getFormError()), $parent->getErrors(), $parent->getName().' should have an error, but has none'); + $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one'); + $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one'); + } elseif (self::LEVEL_1 === $target) { + $this->assertCount(0, $errorChild->getErrors(), $errorName.' should not have an error, but has one'); + $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); + $this->assertEquals(array($this->getFormError()), $child->getErrors(), $childName.' should have an error, but has none'); + $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one'); + } elseif (self::LEVEL_1B === $target) { + $this->assertEquals(array($this->getFormError()), $errorChild->getErrors(), $errorName.' should have an error, but has none'); + $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); + $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one'); + $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one'); + } else { + $this->assertCount(0, $errorChild->getErrors(), $errorName.' should not have an error, but has one'); + $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); + $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one'); + $this->assertEquals(array($this->getFormError()), $grandChild->getErrors(), $grandChildName.' should have an error, but has none'); + } + } + + public function provideErrorTestsForFormInheritingParentData() + { + return array( + // mapping target, child name, its property path, grand child name, its property path, violation path + array(self::LEVEL_2, 'address', 'address', 'street', 'street', 'children[address].children[street].data'), + array(self::LEVEL_2, 'address', 'address', 'street', 'street', 'children[address].children[street].data.prop'), + array(self::LEVEL_2, 'address', 'address', 'street', 'street', 'children[address].data.street'), + array(self::LEVEL_2, 'address', 'address', 'street', 'street', 'children[address].data.street.prop'), + array(self::LEVEL_1, 'address', 'address', 'street', 'street', 'children[address].data[street]'), + array(self::LEVEL_1, 'address', 'address', 'street', 'street', 'children[address].data[street].prop'), + array(self::LEVEL_2, 'address', 'address', 'street', 'street', 'data.street'), + array(self::LEVEL_2, 'address', 'address', 'street', 'street', 'data.street.prop'), + array(self::LEVEL_0, 'address', 'address', 'street', 'street', 'data[street]'), + array(self::LEVEL_0, 'address', 'address', 'street', 'street', 'data[street].prop'), + array(self::LEVEL_0, 'address', 'address', 'street', 'street', 'data.address.street'), + array(self::LEVEL_0, 'address', 'address', 'street', 'street', 'data.address.street.prop'), + array(self::LEVEL_0, 'address', 'address', 'street', 'street', 'data.address[street]'), + array(self::LEVEL_0, 'address', 'address', 'street', 'street', 'data.address[street].prop'), + array(self::LEVEL_0, 'address', 'address', 'street', 'street', 'data[address].street'), + array(self::LEVEL_0, 'address', 'address', 'street', 'street', 'data[address].street.prop'), + array(self::LEVEL_0, 'address', 'address', 'street', 'street', 'data[address][street]'), + array(self::LEVEL_0, 'address', 'address', 'street', 'street', 'data[address][street].prop'), + ); + } + + /** + * @dataProvider provideErrorTestsForFormInheritingParentData + */ + public function testErrorMappingForFormInheritingParentData($target, $childName, $childPath, $grandChildName, $grandChildPath, $violationPath) + { + $violation = $this->getConstraintViolation($violationPath); + $parent = $this->getForm('parent'); + $child = $this->getForm($childName, $childPath, null, array(), true); + $grandChild = $this->getForm($grandChildName, $grandChildPath); + + $parent->add($child); + $child->add($grandChild); + + $this->mapper->mapViolation($violation, $parent); + + if (self::LEVEL_0 === $target) { + $this->assertEquals(array($this->getFormError()), $parent->getErrors(), $parent->getName().' should have an error, but has none'); + $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one'); + $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one'); + } elseif (self::LEVEL_1 === $target) { + $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); + $this->assertEquals(array($this->getFormError()), $child->getErrors(), $childName.' should have an error, but has none'); + $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one'); + } else { + $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); + $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one'); + $this->assertEquals(array($this->getFormError()), $grandChild->getErrors(), $grandChildName.' should have an error, but has none'); + } + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Validator/ViolationMapper/ViolationPathTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Validator/ViolationMapper/ViolationPathTest.php new file mode 100644 index 00000000..02df8f43 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Validator/ViolationMapper/ViolationPathTest.php @@ -0,0 +1,245 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Validator\ViolationMapper; + +use Symfony\Component\Form\Extension\Validator\ViolationMapper\ViolationPath; + +/** + * @author Bernhard Schussek + */ +class ViolationPathTest extends \PHPUnit_Framework_TestCase +{ + public function providePaths() + { + return array( + array('children[address]', array( + array('address', true, true), + )), + array('children[address].children[street]', array( + array('address', true, true), + array('street', true, true), + )), + array('children[address][street]', array( + array('address', true, true), + ), 'children[address]'), + array('children[address].data', array( + array('address', true, true), + ), 'children[address]'), + array('children[address].data.street', array( + array('address', true, true), + array('street', false, false), + )), + array('children[address].data[street]', array( + array('address', true, true), + array('street', false, true), + )), + array('children[address].children[street].data.name', array( + array('address', true, true), + array('street', true, true), + array('name', false, false), + )), + array('children[address].children[street].data[name]', array( + array('address', true, true), + array('street', true, true), + array('name', false, true), + )), + array('data.address', array( + array('address', false, false), + )), + array('data[address]', array( + array('address', false, true), + )), + array('data.address.street', array( + array('address', false, false), + array('street', false, false), + )), + array('data[address].street', array( + array('address', false, true), + array('street', false, false), + )), + array('data.address[street]', array( + array('address', false, false), + array('street', false, true), + )), + array('data[address][street]', array( + array('address', false, true), + array('street', false, true), + )), + // A few invalid examples + array('data', array(), ''), + array('children', array(), ''), + array('children.address', array(), ''), + array('children.address[street]', array(), ''), + ); + } + + /** + * @dataProvider providePaths + */ + public function testCreatePath($string, $entries, $slicedPath = null) + { + if (null === $slicedPath) { + $slicedPath = $string; + } + + $path = new ViolationPath($string); + + $this->assertSame($slicedPath, $path->__toString()); + $this->assertSame(count($entries), count($path->getElements())); + $this->assertSame(count($entries), $path->getLength()); + + foreach ($entries as $index => $entry) { + $this->assertEquals($entry[0], $path->getElement($index)); + $this->assertSame($entry[1], $path->mapsForm($index)); + $this->assertSame($entry[2], $path->isIndex($index)); + $this->assertSame(!$entry[2], $path->isProperty($index)); + } + } + + public function provideParents() + { + return array( + array('children[address]', null), + array('children[address].children[street]', 'children[address]'), + array('children[address].data.street', 'children[address]'), + array('children[address].data[street]', 'children[address]'), + array('data.address', null), + array('data.address.street', 'data.address'), + array('data.address[street]', 'data.address'), + array('data[address].street', 'data[address]'), + array('data[address][street]', 'data[address]'), + ); + } + + /** + * @dataProvider provideParents + */ + public function testGetParent($violationPath, $parentPath) + { + $path = new ViolationPath($violationPath); + $parent = $parentPath === null ? null : new ViolationPath($parentPath); + + $this->assertEquals($parent, $path->getParent()); + } + + public function testGetElement() + { + $path = new ViolationPath('children[address].data[street].name'); + + $this->assertEquals('street', $path->getElement(1)); + } + + /** + * @expectedException \OutOfBoundsException + */ + public function testGetElementDoesNotAcceptInvalidIndices() + { + $path = new ViolationPath('children[address].data[street].name'); + + $path->getElement(3); + } + + /** + * @expectedException \OutOfBoundsException + */ + public function testGetElementDoesNotAcceptNegativeIndices() + { + $path = new ViolationPath('children[address].data[street].name'); + + $path->getElement(-1); + } + + public function testIsProperty() + { + $path = new ViolationPath('children[address].data[street].name'); + + $this->assertFalse($path->isProperty(1)); + $this->assertTrue($path->isProperty(2)); + } + + /** + * @expectedException \OutOfBoundsException + */ + public function testIsPropertyDoesNotAcceptInvalidIndices() + { + $path = new ViolationPath('children[address].data[street].name'); + + $path->isProperty(3); + } + + /** + * @expectedException \OutOfBoundsException + */ + public function testIsPropertyDoesNotAcceptNegativeIndices() + { + $path = new ViolationPath('children[address].data[street].name'); + + $path->isProperty(-1); + } + + public function testIsIndex() + { + $path = new ViolationPath('children[address].data[street].name'); + + $this->assertTrue($path->isIndex(1)); + $this->assertFalse($path->isIndex(2)); + } + + /** + * @expectedException \OutOfBoundsException + */ + public function testIsIndexDoesNotAcceptInvalidIndices() + { + $path = new ViolationPath('children[address].data[street].name'); + + $path->isIndex(3); + } + + /** + * @expectedException \OutOfBoundsException + */ + public function testIsIndexDoesNotAcceptNegativeIndices() + { + $path = new ViolationPath('children[address].data[street].name'); + + $path->isIndex(-1); + } + + public function testMapsForm() + { + $path = new ViolationPath('children[address].data[street].name'); + + $this->assertTrue($path->mapsForm(0)); + $this->assertFalse($path->mapsForm(1)); + $this->assertFalse($path->mapsForm(2)); + } + + /** + * @expectedException \OutOfBoundsException + */ + public function testMapsFormDoesNotAcceptInvalidIndices() + { + $path = new ViolationPath('children[address].data[street].name'); + + $path->mapsForm(3); + } + + /** + * @expectedException \OutOfBoundsException + */ + public function testMapsFormDoesNotAcceptNegativeIndices() + { + $path = new ViolationPath('children[address].data[street].name'); + + $path->mapsForm(-1); + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Fixtures/AlternatingRowType.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Fixtures/AlternatingRowType.php new file mode 100644 index 00000000..ee7d1353 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Fixtures/AlternatingRowType.php @@ -0,0 +1,27 @@ +getFormFactory(); + + $builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) use ($formFactory) { + $form = $event->getForm(); + $type = $form->getName() % 2 === 0 ? 'text' : 'textarea'; + $form->add('title', $type); + }); + } + + public function getName() + { + return 'alternating_row'; + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Fixtures/Author.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Fixtures/Author.php new file mode 100644 index 00000000..11204894 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Fixtures/Author.php @@ -0,0 +1,71 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Fixtures; + +class Author +{ + public $firstName; + private $lastName; + private $australian; + public $child; + private $readPermissions; + + private $privateProperty; + + public function setLastName($lastName) + { + $this->lastName = $lastName; + } + + public function getLastName() + { + return $this->lastName; + } + + private function getPrivateGetter() + { + return 'foobar'; + } + + public function setAustralian($australian) + { + $this->australian = $australian; + } + + public function isAustralian() + { + return $this->australian; + } + + public function setReadPermissions($bool) + { + $this->readPermissions = $bool; + } + + public function hasReadPermissions() + { + return $this->readPermissions; + } + + private function isPrivateIsser() + { + return true; + } + + public function getPrivateSetter() + { + } + + private function setPrivateSetter($data) + { + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Fixtures/AuthorType.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Fixtures/AuthorType.php new file mode 100644 index 00000000..147f6e48 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Fixtures/AuthorType.php @@ -0,0 +1,30 @@ +add('firstName') + ->add('lastName') + ; + } + + public function getName() + { + return 'author'; + } + + public function setDefaultOptions(OptionsResolverInterface $resolver) + { + $resolver->setDefaults(array( + 'data_class' => 'Symfony\Component\Form\Tests\Fixtures\Author', + )); + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Fixtures/CustomArrayObject.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Fixtures/CustomArrayObject.php new file mode 100644 index 00000000..950f677f --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Fixtures/CustomArrayObject.php @@ -0,0 +1,70 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Fixtures; + +/** + * This class is a hand written simplified version of PHP native `ArrayObject` + * class, to show that it behaves differently than the PHP native implementation. + */ +class CustomArrayObject implements \ArrayAccess, \IteratorAggregate, \Countable, \Serializable +{ + private $array; + + public function __construct(array $array = null) + { + $this->array = $array ?: array(); + } + + public function offsetExists($offset) + { + return array_key_exists($offset, $this->array); + } + + public function offsetGet($offset) + { + return $this->array[$offset]; + } + + public function offsetSet($offset, $value) + { + if (null === $offset) { + $this->array[] = $value; + } else { + $this->array[$offset] = $value; + } + } + + public function offsetUnset($offset) + { + unset($this->array[$offset]); + } + + public function getIterator() + { + return new \ArrayIterator($this->array); + } + + public function count() + { + return count($this->array); + } + + public function serialize() + { + return serialize($this->array); + } + + public function unserialize($serialized) + { + $this->array = (array) unserialize((string) $serialized); + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Fixtures/FixedDataTransformer.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Fixtures/FixedDataTransformer.php new file mode 100644 index 00000000..a5a31248 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Fixtures/FixedDataTransformer.php @@ -0,0 +1,45 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Fixtures; + +use Symfony\Component\Form\DataTransformerInterface; +use Symfony\Component\Form\Exception\RuntimeException; + +class FixedDataTransformer implements DataTransformerInterface +{ + private $mapping; + + public function __construct(array $mapping) + { + $this->mapping = $mapping; + } + + public function transform($value) + { + if (!array_key_exists($value, $this->mapping)) { + throw new RuntimeException(sprintf('No mapping for value "%s"', $value)); + } + + return $this->mapping[$value]; + } + + public function reverseTransform($value) + { + $result = array_search($value, $this->mapping, true); + + if ($result === false) { + throw new RuntimeException(sprintf('No reverse mapping for value "%s"', $value)); + } + + return $result; + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Fixtures/FixedFilterListener.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Fixtures/FixedFilterListener.php new file mode 100644 index 00000000..762a10b8 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Fixtures/FixedFilterListener.php @@ -0,0 +1,66 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Fixtures; + +use Symfony\Component\Form\FormEvents; +use Symfony\Component\Form\FormEvent; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; + +class FixedFilterListener implements EventSubscriberInterface +{ + private $mapping; + + public function __construct(array $mapping) + { + $this->mapping = array_merge(array( + 'preSubmit' => array(), + 'onSubmit' => array(), + 'preSetData' => array(), + ), $mapping); + } + + public function preSubmit(FormEvent $event) + { + $data = $event->getData(); + + if (isset($this->mapping['preSubmit'][$data])) { + $event->setData($this->mapping['preSubmit'][$data]); + } + } + + public function onSubmit(FormEvent $event) + { + $data = $event->getData(); + + if (isset($this->mapping['onSubmit'][$data])) { + $event->setData($this->mapping['onSubmit'][$data]); + } + } + + public function preSetData(FormEvent $event) + { + $data = $event->getData(); + + if (isset($this->mapping['preSetData'][$data])) { + $event->setData($this->mapping['preSetData'][$data]); + } + } + + public static function getSubscribedEvents() + { + return array( + FormEvents::PRE_SUBMIT => 'preSubmit', + FormEvents::SUBMIT => 'onSubmit', + FormEvents::PRE_SET_DATA => 'preSetData', + ); + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Fixtures/FooSubType.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Fixtures/FooSubType.php new file mode 100644 index 00000000..4f7ba6d4 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Fixtures/FooSubType.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Fixtures; + +use Symfony\Component\Form\AbstractType; +use Symfony\Component\Form\FormBuilder; +use Symfony\Component\Form\FormBuilderInterface; +use Symfony\Component\Form\FormFactoryInterface; +use Symfony\Component\EventDispatcher\EventDispatcher; +use Symfony\Component\OptionsResolver\OptionsResolverInterface; + +class FooSubType extends AbstractType +{ + public function getName() + { + return 'foo_sub_type'; + } + + public function getParent() + { + return 'foo'; + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Fixtures/FooSubTypeWithParentInstance.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Fixtures/FooSubTypeWithParentInstance.php new file mode 100644 index 00000000..468b5a32 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Fixtures/FooSubTypeWithParentInstance.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Fixtures; + +use Symfony\Component\Form\AbstractType; +use Symfony\Component\Form\FormBuilder; +use Symfony\Component\Form\FormBuilderInterface; +use Symfony\Component\Form\FormFactoryInterface; +use Symfony\Component\EventDispatcher\EventDispatcher; +use Symfony\Component\OptionsResolver\OptionsResolverInterface; + +class FooSubTypeWithParentInstance extends AbstractType +{ + public function getName() + { + return 'foo_sub_type_parent_instance'; + } + + public function getParent() + { + return new FooType(); + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Fixtures/FooType.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Fixtures/FooType.php new file mode 100644 index 00000000..d26d3f76 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Fixtures/FooType.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Fixtures; + +use Symfony\Component\Form\AbstractType; +use Symfony\Component\Form\FormBuilder; +use Symfony\Component\Form\FormBuilderInterface; +use Symfony\Component\Form\FormFactoryInterface; +use Symfony\Component\EventDispatcher\EventDispatcher; +use Symfony\Component\OptionsResolver\OptionsResolverInterface; + +class FooType extends AbstractType +{ + public function getName() + { + return 'foo'; + } + + public function getParent() + { + return null; + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Fixtures/FooTypeBarExtension.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Fixtures/FooTypeBarExtension.php new file mode 100644 index 00000000..c5f92e11 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Fixtures/FooTypeBarExtension.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Fixtures; + +use Symfony\Component\Form\AbstractTypeExtension; +use Symfony\Component\Form\FormBuilderInterface; + +class FooTypeBarExtension extends AbstractTypeExtension +{ + public function buildForm(FormBuilderInterface $builder, array $options) + { + $builder->setAttribute('bar', 'x'); + } + + public function getAllowedOptionValues() + { + return array( + 'a_or_b' => array('c'), + ); + } + + public function getExtendedType() + { + return 'foo'; + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Fixtures/FooTypeBazExtension.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Fixtures/FooTypeBazExtension.php new file mode 100644 index 00000000..2e364754 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Fixtures/FooTypeBazExtension.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Fixtures; + +use Symfony\Component\Form\AbstractTypeExtension; +use Symfony\Component\Form\FormBuilderInterface; + +class FooTypeBazExtension extends AbstractTypeExtension +{ + public function buildForm(FormBuilderInterface $builder, array $options) + { + $builder->setAttribute('baz', 'x'); + } + + public function getExtendedType() + { + return 'foo'; + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Fixtures/TestExtension.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Fixtures/TestExtension.php new file mode 100644 index 00000000..f9de560f --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Fixtures/TestExtension.php @@ -0,0 +1,72 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Fixtures; + +use Symfony\Component\Form\FormTypeInterface; +use Symfony\Component\Form\FormTypeExtensionInterface; +use Symfony\Component\Form\FormTypeGuesserInterface; +use Symfony\Component\Form\FormExtensionInterface; + +class TestExtension implements FormExtensionInterface +{ + private $types = array(); + + private $extensions = array(); + + private $guesser; + + public function __construct(FormTypeGuesserInterface $guesser) + { + $this->guesser = $guesser; + } + + public function addType(FormTypeInterface $type) + { + $this->types[$type->getName()] = $type; + } + + public function getType($name) + { + return isset($this->types[$name]) ? $this->types[$name] : null; + } + + public function hasType($name) + { + return isset($this->types[$name]); + } + + public function addTypeExtension(FormTypeExtensionInterface $extension) + { + $type = $extension->getExtendedType(); + + if (!isset($this->extensions[$type])) { + $this->extensions[$type] = array(); + } + + $this->extensions[$type][] = $extension; + } + + public function getTypeExtensions($name) + { + return isset($this->extensions[$name]) ? $this->extensions[$name] : array(); + } + + public function hasTypeExtensions($name) + { + return isset($this->extensions[$name]); + } + + public function getTypeGuesser() + { + return $this->guesser; + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Fixtures/foo b/vendor/symfony/form/Symfony/Component/Form/Tests/Fixtures/foo new file mode 100644 index 00000000..e69de29b diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/FormBuilderTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/FormBuilderTest.php new file mode 100644 index 00000000..e076c97e --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/FormBuilderTest.php @@ -0,0 +1,232 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests; + +use Symfony\Component\Form\FormBuilder; + +class FormBuilderTest extends \PHPUnit_Framework_TestCase +{ + private $dispatcher; + + private $factory; + + private $builder; + + protected function setUp() + { + if (!class_exists('Symfony\Component\EventDispatcher\EventDispatcher')) { + $this->markTestSkipped('The "EventDispatcher" component is not available'); + } + + $this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); + $this->factory = $this->getMock('Symfony\Component\Form\FormFactoryInterface'); + $this->builder = new FormBuilder('name', null, $this->dispatcher, $this->factory); + } + + protected function tearDown() + { + $this->dispatcher = null; + $this->factory = null; + $this->builder = null; + } + + /** + * Changing the name is not allowed, otherwise the name and property path + * are not synchronized anymore + * + * @see FormType::buildForm + */ + public function testNoSetName() + { + $this->assertFalse(method_exists($this->builder, 'setName')); + } + + public function testAddNameNoStringAndNoInteger() + { + $this->setExpectedException('Symfony\Component\Form\Exception\UnexpectedTypeException'); + $this->builder->add(true); + } + + public function testAddTypeNoString() + { + $this->setExpectedException('Symfony\Component\Form\Exception\UnexpectedTypeException'); + $this->builder->add('foo', 1234); + } + + public function testAddWithGuessFluent() + { + $this->builder = new FormBuilder('name', 'stdClass', $this->dispatcher, $this->factory); + $builder = $this->builder->add('foo'); + $this->assertSame($builder, $this->builder); + } + + public function testAddIsFluent() + { + $builder = $this->builder->add('foo', 'text', array('bar' => 'baz')); + $this->assertSame($builder, $this->builder); + } + + public function testAdd() + { + $this->assertFalse($this->builder->has('foo')); + $this->builder->add('foo', 'text'); + $this->assertTrue($this->builder->has('foo')); + } + + public function testAddIntegerName() + { + $this->assertFalse($this->builder->has(0)); + $this->builder->add(0, 'text'); + $this->assertTrue($this->builder->has(0)); + } + + public function testAll() + { + $this->factory->expects($this->once()) + ->method('createNamedBuilder') + ->with('foo', 'text') + ->will($this->returnValue(new FormBuilder('foo', null, $this->dispatcher, $this->factory))); + + $this->assertCount(0, $this->builder->all()); + $this->assertFalse($this->builder->has('foo')); + + $this->builder->add('foo', 'text'); + $children = $this->builder->all(); + + $this->assertTrue($this->builder->has('foo')); + $this->assertCount(1, $children); + $this->assertArrayHasKey('foo', $children); + } + + /* + * https://github.com/symfony/symfony/issues/4693 + */ + public function testMaintainOrderOfLazyAndExplicitChildren() + { + $this->builder->add('foo', 'text'); + $this->builder->add($this->getFormBuilder('bar')); + $this->builder->add('baz', 'text'); + + $children = $this->builder->all(); + + $this->assertSame(array('foo', 'bar', 'baz'), array_keys($children)); + } + + public function testAddFormType() + { + $this->assertFalse($this->builder->has('foo')); + $this->builder->add('foo', $this->getMock('Symfony\Component\Form\FormTypeInterface')); + $this->assertTrue($this->builder->has('foo')); + } + + public function testRemove() + { + $this->builder->add('foo', 'text'); + $this->builder->remove('foo'); + $this->assertFalse($this->builder->has('foo')); + } + + public function testRemoveUnknown() + { + $this->builder->remove('foo'); + $this->assertFalse($this->builder->has('foo')); + } + + // https://github.com/symfony/symfony/pull/4826 + public function testRemoveAndGetForm() + { + $this->builder->add('foo', 'text'); + $this->builder->remove('foo'); + $form = $this->builder->getForm(); + $this->assertInstanceOf('Symfony\Component\Form\Form', $form); + } + + public function testCreateNoTypeNo() + { + $this->factory->expects($this->once()) + ->method('createNamedBuilder') + ->with('foo', 'text', null, array()) + ; + + $this->builder->create('foo'); + } + + public function testGetUnknown() + { + $this->setExpectedException('Symfony\Component\Form\Exception\InvalidArgumentException', 'The child with the name "foo" does not exist.'); + $this->builder->get('foo'); + } + + public function testGetExplicitType() + { + $expectedType = 'text'; + $expectedName = 'foo'; + $expectedOptions = array('bar' => 'baz'); + + $this->factory->expects($this->once()) + ->method('createNamedBuilder') + ->with($expectedName, $expectedType, null, $expectedOptions) + ->will($this->returnValue($this->getFormBuilder())); + + $this->builder->add($expectedName, $expectedType, $expectedOptions); + $builder = $this->builder->get($expectedName); + + $this->assertNotSame($builder, $this->builder); + } + + public function testGetGuessedType() + { + $expectedName = 'foo'; + $expectedOptions = array('bar' => 'baz'); + + $this->factory->expects($this->once()) + ->method('createBuilderForProperty') + ->with('stdClass', $expectedName, null, $expectedOptions) + ->will($this->returnValue($this->getFormBuilder())); + + $this->builder = new FormBuilder('name', 'stdClass', $this->dispatcher, $this->factory); + $this->builder->add($expectedName, null, $expectedOptions); + $builder = $this->builder->get($expectedName); + + $this->assertNotSame($builder, $this->builder); + } + + public function testGetFormConfigErasesReferences() + { + $builder = new FormBuilder('name', null, $this->dispatcher, $this->factory); + $builder->add(new FormBuilder('child', null, $this->dispatcher, $this->factory)); + + $config = $builder->getFormConfig(); + $reflClass = new \ReflectionClass($config); + $children = $reflClass->getProperty('children'); + $unresolvedChildren = $reflClass->getProperty('unresolvedChildren'); + + $children->setAccessible(true); + $unresolvedChildren->setAccessible(true); + + $this->assertEmpty($children->getValue($config)); + $this->assertEmpty($unresolvedChildren->getValue($config)); + } + + private function getFormBuilder($name = 'name') + { + $mock = $this->getMockBuilder('Symfony\Component\Form\FormBuilder') + ->disableOriginalConstructor() + ->getMock(); + + $mock->expects($this->any()) + ->method('getName') + ->will($this->returnValue($name)); + + return $mock; + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/FormConfigTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/FormConfigTest.php new file mode 100644 index 00000000..961dfd33 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/FormConfigTest.php @@ -0,0 +1,148 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests; + +use Symfony\Component\Form\Exception\UnexpectedTypeException; +use Symfony\Component\Form\FormConfigBuilder; +use Symfony\Component\Form\Exception\InvalidArgumentException; + +/** + * @author Bernhard Schussek + */ +class FormConfigTest extends \PHPUnit_Framework_TestCase +{ + public function getHtml4Ids() + { + return array( + array('z0', true), + array('A0', true), + array('A9', true), + array('Z0', true), + array('#', false), + array('a#', false), + array('a$', false), + array('a%', false), + array('a ', false), + array("a\t", false), + array("a\n", false), + array('a-', true), + array('a_', true), + array('a:', true), + // Periods are allowed by the HTML4 spec, but disallowed by us + // because they break the generated property paths + array('a.', false), + // Contrary to the HTML4 spec, we allow names starting with a + // number, otherwise naming fields by collection indices is not + // possible. + // For root forms, leading digits will be stripped from the + // "id" attribute to produce valid HTML4. + array('0', true), + array('9', true), + // Contrary to the HTML4 spec, we allow names starting with an + // underscore, since this is already a widely used practice in + // Symfony2. + // For root forms, leading underscores will be stripped from the + // "id" attribute to produce valid HTML4. + array('_', true), + // Integers are allowed + array(0, true), + array(123, true), + // NULL is allowed + array(null, true), + // Other types are not + array(1.23, false), + array(5., false), + array(true, false), + array(new \stdClass(), false), + ); + } + + /** + * @dataProvider getHtml4Ids + */ + public function testNameAcceptsOnlyNamesValidAsIdsInHtml4($name, $accepted) + { + $dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); + + try { + new FormConfigBuilder($name, null, $dispatcher); + if (!$accepted) { + $this->fail(sprintf('The value "%s" should not be accepted', $name)); + } + } catch (UnexpectedTypeException $e) { + // if the value was not accepted, but should be, rethrow exception + if ($accepted) { + throw $e; + } + } catch (InvalidArgumentException $e) { + // if the value was not accepted, but should be, rethrow exception + if ($accepted) { + throw $e; + } + } + } + + public function testGetRequestHandlerCreatesNativeRequestHandlerIfNotSet() + { + $config = $this->getConfigBuilder()->getFormConfig(); + + $this->assertInstanceOf('Symfony\Component\Form\NativeRequestHandler', $config->getRequestHandler()); + } + + public function testGetRequestHandlerReusesNativeRequestHandlerInstance() + { + $config1 = $this->getConfigBuilder()->getFormConfig(); + $config2 = $this->getConfigBuilder()->getFormConfig(); + + $this->assertSame($config1->getRequestHandler(), $config2->getRequestHandler()); + } + + public function testSetMethodAllowsGet() + { + $this->getConfigBuilder()->setMethod('GET'); + } + + public function testSetMethodAllowsPost() + { + $this->getConfigBuilder()->setMethod('POST'); + } + + public function testSetMethodAllowsPut() + { + $this->getConfigBuilder()->setMethod('PUT'); + } + + public function testSetMethodAllowsDelete() + { + $this->getConfigBuilder()->setMethod('DELETE'); + } + + public function testSetMethodAllowsPatch() + { + $this->getConfigBuilder()->setMethod('PATCH'); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\InvalidArgumentException + */ + public function testSetMethodDoesNotAllowOtherValues() + { + $this->getConfigBuilder()->setMethod('foo'); + } + + private function getConfigBuilder($name = 'name') + { + $dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); + + return new FormConfigBuilder($name, null, $dispatcher); + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/FormFactoryBuilderTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/FormFactoryBuilderTest.php new file mode 100644 index 00000000..a1292dbe --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/FormFactoryBuilderTest.php @@ -0,0 +1,59 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests; + +use Symfony\Component\Form\FormFactoryBuilder; +use Symfony\Component\Form\Tests\Fixtures\FooType; + +class FormFactoryBuilderTest extends \PHPUnit_Framework_TestCase +{ + private $registry; + private $guesser; + private $type; + + protected function setUp() + { + $factory = new \ReflectionClass('Symfony\Component\Form\FormFactory'); + $this->registry = $factory->getProperty('registry'); + $this->registry->setAccessible(true); + + $this->guesser = $this->getMock('Symfony\Component\Form\FormTypeGuesserInterface'); + $this->type = new FooType; + } + + public function testAddType() + { + $factoryBuilder = new FormFactoryBuilder; + $factoryBuilder->addType($this->type); + + $factory = $factoryBuilder->getFormFactory(); + $registry = $this->registry->getValue($factory); + $extensions = $registry->getExtensions(); + + $this->assertCount(1, $extensions); + $this->assertTrue($extensions[0]->hasType($this->type->getName())); + $this->assertNull($extensions[0]->getTypeGuesser()); + } + + public function testAddTypeGuesser() + { + $factoryBuilder = new FormFactoryBuilder; + $factoryBuilder->addTypeGuesser($this->guesser); + + $factory = $factoryBuilder->getFormFactory(); + $registry = $this->registry->getValue($factory); + $extensions = $registry->getExtensions(); + + $this->assertCount(1, $extensions); + $this->assertNotNull($extensions[0]->getTypeGuesser()); + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/FormFactoryTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/FormFactoryTest.php new file mode 100644 index 00000000..ea872b01 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/FormFactoryTest.php @@ -0,0 +1,506 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests; + +use Symfony\Component\Form\FormTypeGuesserChain; +use Symfony\Component\Form\FormFactory; +use Symfony\Component\Form\Guess\Guess; +use Symfony\Component\Form\Guess\ValueGuess; +use Symfony\Component\Form\Guess\TypeGuess; +use Symfony\Component\Form\Tests\Fixtures\Author; +use Symfony\Component\Form\Tests\Fixtures\FooType; +use Symfony\Component\Form\Tests\Fixtures\FooSubType; +use Symfony\Component\Form\Tests\Fixtures\FooSubTypeWithParentInstance; + +/** + * @author Bernhard Schussek + */ +class FormFactoryTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + private $guesser1; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + private $guesser2; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + private $registry; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + private $resolvedTypeFactory; + + /** + * @var FormFactory + */ + private $factory; + + protected function setUp() + { + if (!class_exists('Symfony\Component\EventDispatcher\EventDispatcher')) { + $this->markTestSkipped('The "EventDispatcher" component is not available'); + } + + $this->resolvedTypeFactory = $this->getMock('Symfony\Component\Form\ResolvedFormTypeFactoryInterface'); + $this->guesser1 = $this->getMock('Symfony\Component\Form\FormTypeGuesserInterface'); + $this->guesser2 = $this->getMock('Symfony\Component\Form\FormTypeGuesserInterface'); + $this->registry = $this->getMock('Symfony\Component\Form\FormRegistryInterface'); + $this->factory = new FormFactory($this->registry, $this->resolvedTypeFactory); + + $this->registry->expects($this->any()) + ->method('getTypeGuesser') + ->will($this->returnValue(new FormTypeGuesserChain(array( + $this->guesser1, + $this->guesser2, + )))); + } + + public function testCreateNamedBuilderWithTypeName() + { + $options = array('a' => '1', 'b' => '2'); + $resolvedType = $this->getMockResolvedType(); + + $this->registry->expects($this->once()) + ->method('getType') + ->with('type') + ->will($this->returnValue($resolvedType)); + + $resolvedType->expects($this->once()) + ->method('createBuilder') + ->with($this->factory, 'name', $options) + ->will($this->returnValue('BUILDER')); + + $this->assertSame('BUILDER', $this->factory->createNamedBuilder('name', 'type', null, $options)); + } + + public function testCreateNamedBuilderWithTypeInstance() + { + $options = array('a' => '1', 'b' => '2'); + $type = new FooType(); + $resolvedType = $this->getMockResolvedType(); + + $this->resolvedTypeFactory->expects($this->once()) + ->method('createResolvedType') + ->with($type) + ->will($this->returnValue($resolvedType)); + + $resolvedType->expects($this->once()) + ->method('createBuilder') + ->with($this->factory, 'name', $options) + ->will($this->returnValue('BUILDER')); + + $this->assertSame('BUILDER', $this->factory->createNamedBuilder('name', $type, null, $options)); + } + + public function testCreateNamedBuilderWithTypeInstanceWithParentType() + { + $options = array('a' => '1', 'b' => '2'); + $type = new FooSubType(); + $resolvedType = $this->getMockResolvedType(); + $parentResolvedType = $this->getMockResolvedType(); + + $this->registry->expects($this->once()) + ->method('getType') + ->with('foo') + ->will($this->returnValue($parentResolvedType)); + + $this->resolvedTypeFactory->expects($this->once()) + ->method('createResolvedType') + ->with($type, array(), $parentResolvedType) + ->will($this->returnValue($resolvedType)); + + $resolvedType->expects($this->once()) + ->method('createBuilder') + ->with($this->factory, 'name', $options) + ->will($this->returnValue('BUILDER')); + + $this->assertSame('BUILDER', $this->factory->createNamedBuilder('name', $type, null, $options)); + } + + public function testCreateNamedBuilderWithTypeInstanceWithParentTypeInstance() + { + $options = array('a' => '1', 'b' => '2'); + $type = new FooSubTypeWithParentInstance(); + $resolvedType = $this->getMockResolvedType(); + $parentResolvedType = $this->getMockResolvedType(); + + $this->resolvedTypeFactory->expects($this->at(0)) + ->method('createResolvedType') + ->with($type->getParent()) + ->will($this->returnValue($parentResolvedType)); + + $this->resolvedTypeFactory->expects($this->at(1)) + ->method('createResolvedType') + ->with($type, array(), $parentResolvedType) + ->will($this->returnValue($resolvedType)); + + $resolvedType->expects($this->once()) + ->method('createBuilder') + ->with($this->factory, 'name', $options) + ->will($this->returnValue('BUILDER')); + + $this->assertSame('BUILDER', $this->factory->createNamedBuilder('name', $type, null, $options)); + } + + public function testCreateNamedBuilderWithResolvedTypeInstance() + { + $options = array('a' => '1', 'b' => '2'); + $resolvedType = $this->getMockResolvedType(); + + $resolvedType->expects($this->once()) + ->method('createBuilder') + ->with($this->factory, 'name', $options) + ->will($this->returnValue('BUILDER')); + + $this->assertSame('BUILDER', $this->factory->createNamedBuilder('name', $resolvedType, null, $options)); + } + + public function testCreateNamedBuilderFillsDataOption() + { + $givenOptions = array('a' => '1', 'b' => '2'); + $expectedOptions = array_merge($givenOptions, array('data' => 'DATA')); + $resolvedType = $this->getMockResolvedType(); + + $this->registry->expects($this->once()) + ->method('getType') + ->with('type') + ->will($this->returnValue($resolvedType)); + + $resolvedType->expects($this->once()) + ->method('createBuilder') + ->with($this->factory, 'name', $expectedOptions) + ->will($this->returnValue('BUILDER')); + + $this->assertSame('BUILDER', $this->factory->createNamedBuilder('name', 'type', 'DATA', $givenOptions)); + } + + public function testCreateNamedBuilderDoesNotOverrideExistingDataOption() + { + $options = array('a' => '1', 'b' => '2', 'data' => 'CUSTOM'); + $resolvedType = $this->getMockResolvedType(); + + $this->registry->expects($this->once()) + ->method('getType') + ->with('type') + ->will($this->returnValue($resolvedType)); + + $resolvedType->expects($this->once()) + ->method('createBuilder') + ->with($this->factory, 'name', $options) + ->will($this->returnValue('BUILDER')); + + $this->assertSame('BUILDER', $this->factory->createNamedBuilder('name', 'type', 'DATA', $options)); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException + * @expectedExceptionMessage Expected argument of type "string, Symfony\Component\Form\ResolvedFormTypeInterface or Symfony\Component\Form\FormTypeInterface", "stdClass" given + */ + public function testCreateNamedBuilderThrowsUnderstandableException() + { + $this->factory->createNamedBuilder('name', new \stdClass()); + } + + public function testCreateUsesTypeNameIfTypeGivenAsString() + { + $options = array('a' => '1', 'b' => '2'); + $resolvedType = $this->getMockResolvedType(); + $builder = $this->getMockFormBuilder(); + + $this->registry->expects($this->once()) + ->method('getType') + ->with('TYPE') + ->will($this->returnValue($resolvedType)); + + $resolvedType->expects($this->once()) + ->method('createBuilder') + ->with($this->factory, 'TYPE', $options) + ->will($this->returnValue($builder)); + + $builder->expects($this->once()) + ->method('getForm') + ->will($this->returnValue('FORM')); + + $this->assertSame('FORM', $this->factory->create('TYPE', null, $options)); + } + + public function testCreateUsesTypeNameIfTypeGivenAsObject() + { + $options = array('a' => '1', 'b' => '2'); + $resolvedType = $this->getMockResolvedType(); + $builder = $this->getMockFormBuilder(); + + $resolvedType->expects($this->once()) + ->method('getName') + ->will($this->returnValue('TYPE')); + + $resolvedType->expects($this->once()) + ->method('createBuilder') + ->with($this->factory, 'TYPE', $options) + ->will($this->returnValue($builder)); + + $builder->expects($this->once()) + ->method('getForm') + ->will($this->returnValue('FORM')); + + $this->assertSame('FORM', $this->factory->create($resolvedType, null, $options)); + } + + public function testCreateNamed() + { + $options = array('a' => '1', 'b' => '2'); + $resolvedType = $this->getMockResolvedType(); + $builder = $this->getMockFormBuilder(); + + $this->registry->expects($this->once()) + ->method('getType') + ->with('type') + ->will($this->returnValue($resolvedType)); + + $resolvedType->expects($this->once()) + ->method('createBuilder') + ->with($this->factory, 'name', $options) + ->will($this->returnValue($builder)); + + $builder->expects($this->once()) + ->method('getForm') + ->will($this->returnValue('FORM')); + + $this->assertSame('FORM', $this->factory->createNamed('name', 'type', null, $options)); + } + + public function testCreateBuilderForPropertyWithoutTypeGuesser() + { + $registry = $this->getMock('Symfony\Component\Form\FormRegistryInterface'); + $factory = $this->getMockBuilder('Symfony\Component\Form\FormFactory') + ->setMethods(array('createNamedBuilder')) + ->setConstructorArgs(array($registry, $this->resolvedTypeFactory)) + ->getMock(); + + $factory->expects($this->once()) + ->method('createNamedBuilder') + ->with('firstName', 'text', null, array()) + ->will($this->returnValue('builderInstance')); + + $builder = $factory->createBuilderForProperty('Application\Author', 'firstName'); + + $this->assertEquals('builderInstance', $builder); + } + + public function testCreateBuilderForPropertyCreatesFormWithHighestConfidence() + { + $this->guesser1->expects($this->once()) + ->method('guessType') + ->with('Application\Author', 'firstName') + ->will($this->returnValue(new TypeGuess( + 'text', + array('max_length' => 10), + Guess::MEDIUM_CONFIDENCE + ))); + + $this->guesser2->expects($this->once()) + ->method('guessType') + ->with('Application\Author', 'firstName') + ->will($this->returnValue(new TypeGuess( + 'password', + array('max_length' => 7), + Guess::HIGH_CONFIDENCE + ))); + + $factory = $this->getMockFactory(array('createNamedBuilder')); + + $factory->expects($this->once()) + ->method('createNamedBuilder') + ->with('firstName', 'password', null, array('max_length' => 7)) + ->will($this->returnValue('builderInstance')); + + $builder = $factory->createBuilderForProperty('Application\Author', 'firstName'); + + $this->assertEquals('builderInstance', $builder); + } + + public function testCreateBuilderCreatesTextFormIfNoGuess() + { + $this->guesser1->expects($this->once()) + ->method('guessType') + ->with('Application\Author', 'firstName') + ->will($this->returnValue(null)); + + $factory = $this->getMockFactory(array('createNamedBuilder')); + + $factory->expects($this->once()) + ->method('createNamedBuilder') + ->with('firstName', 'text') + ->will($this->returnValue('builderInstance')); + + $builder = $factory->createBuilderForProperty('Application\Author', 'firstName'); + + $this->assertEquals('builderInstance', $builder); + } + + public function testOptionsCanBeOverridden() + { + $this->guesser1->expects($this->once()) + ->method('guessType') + ->with('Application\Author', 'firstName') + ->will($this->returnValue(new TypeGuess( + 'text', + array('max_length' => 10), + Guess::MEDIUM_CONFIDENCE + ))); + + $factory = $this->getMockFactory(array('createNamedBuilder')); + + $factory->expects($this->once()) + ->method('createNamedBuilder') + ->with('firstName', 'text', null, array('max_length' => 11)) + ->will($this->returnValue('builderInstance')); + + $builder = $factory->createBuilderForProperty( + 'Application\Author', + 'firstName', + null, + array('max_length' => 11) + ); + + $this->assertEquals('builderInstance', $builder); + } + + public function testCreateBuilderUsesMaxLengthIfFound() + { + $this->guesser1->expects($this->once()) + ->method('guessMaxLength') + ->with('Application\Author', 'firstName') + ->will($this->returnValue(new ValueGuess( + 15, + Guess::MEDIUM_CONFIDENCE + ))); + + $this->guesser2->expects($this->once()) + ->method('guessMaxLength') + ->with('Application\Author', 'firstName') + ->will($this->returnValue(new ValueGuess( + 20, + Guess::HIGH_CONFIDENCE + ))); + + $factory = $this->getMockFactory(array('createNamedBuilder')); + + $factory->expects($this->once()) + ->method('createNamedBuilder') + ->with('firstName', 'text', null, array('max_length' => 20)) + ->will($this->returnValue('builderInstance')); + + $builder = $factory->createBuilderForProperty( + 'Application\Author', + 'firstName' + ); + + $this->assertEquals('builderInstance', $builder); + } + + public function testCreateBuilderUsesRequiredSettingWithHighestConfidence() + { + $this->guesser1->expects($this->once()) + ->method('guessRequired') + ->with('Application\Author', 'firstName') + ->will($this->returnValue(new ValueGuess( + true, + Guess::MEDIUM_CONFIDENCE + ))); + + $this->guesser2->expects($this->once()) + ->method('guessRequired') + ->with('Application\Author', 'firstName') + ->will($this->returnValue(new ValueGuess( + false, + Guess::HIGH_CONFIDENCE + ))); + + $factory = $this->getMockFactory(array('createNamedBuilder')); + + $factory->expects($this->once()) + ->method('createNamedBuilder') + ->with('firstName', 'text', null, array('required' => false)) + ->will($this->returnValue('builderInstance')); + + $builder = $factory->createBuilderForProperty( + 'Application\Author', + 'firstName' + ); + + $this->assertEquals('builderInstance', $builder); + } + + public function testCreateBuilderUsesPatternIfFound() + { + $this->guesser1->expects($this->once()) + ->method('guessPattern') + ->with('Application\Author', 'firstName') + ->will($this->returnValue(new ValueGuess( + '[a-z]', + Guess::MEDIUM_CONFIDENCE + ))); + + $this->guesser2->expects($this->once()) + ->method('guessPattern') + ->with('Application\Author', 'firstName') + ->will($this->returnValue(new ValueGuess( + '[a-zA-Z]', + Guess::HIGH_CONFIDENCE + ))); + + $factory = $this->getMockFactory(array('createNamedBuilder')); + + $factory->expects($this->once()) + ->method('createNamedBuilder') + ->with('firstName', 'text', null, array('pattern' => '[a-zA-Z]')) + ->will($this->returnValue('builderInstance')); + + $builder = $factory->createBuilderForProperty( + 'Application\Author', + 'firstName' + ); + + $this->assertEquals('builderInstance', $builder); + } + + private function getMockFactory(array $methods = array()) + { + return $this->getMockBuilder('Symfony\Component\Form\FormFactory') + ->setMethods($methods) + ->setConstructorArgs(array($this->registry, $this->resolvedTypeFactory)) + ->getMock(); + } + + private function getMockResolvedType() + { + return $this->getMock('Symfony\Component\Form\ResolvedFormTypeInterface'); + } + + private function getMockType() + { + return $this->getMock('Symfony\Component\Form\FormTypeInterface'); + } + + private function getMockFormBuilder() + { + return $this->getMock('Symfony\Component\Form\Test\FormBuilderInterface'); + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/FormIntegrationTestCase.php b/vendor/symfony/form/Symfony/Component/Form/Tests/FormIntegrationTestCase.php new file mode 100644 index 00000000..763286c2 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/FormIntegrationTestCase.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests; + +use Symfony\Component\Form\Test\FormIntegrationTestCase as BaseFormIntegrationTestCase; + +/** + * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use Symfony\Component\Form\Test\FormIntegrationTestCase instead. + */ +abstract class FormIntegrationTestCase extends BaseFormIntegrationTestCase +{ +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/FormPerformanceTestCase.php b/vendor/symfony/form/Symfony/Component/Form/Tests/FormPerformanceTestCase.php new file mode 100644 index 00000000..39882e85 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/FormPerformanceTestCase.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests; + +use Symfony\Component\Form\Test\FormPerformanceTestCase as BaseFormPerformanceTestCase; + +/** + * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use Symfony\Component\Form\Test\FormPerformanceTestCase instead. + */ +abstract class FormPerformanceTestCase extends BaseFormPerformanceTestCase +{ +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/FormRegistryTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/FormRegistryTest.php new file mode 100644 index 00000000..0c8bb6b4 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/FormRegistryTest.php @@ -0,0 +1,243 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests; + +use Symfony\Component\Form\FormRegistry; +use Symfony\Component\Form\FormTypeGuesserChain; +use Symfony\Component\Form\Tests\Fixtures\TestExtension; +use Symfony\Component\Form\Tests\Fixtures\FooSubTypeWithParentInstance; +use Symfony\Component\Form\Tests\Fixtures\FooSubType; +use Symfony\Component\Form\Tests\Fixtures\FooTypeBazExtension; +use Symfony\Component\Form\Tests\Fixtures\FooTypeBarExtension; +use Symfony\Component\Form\Tests\Fixtures\FooType; + +/** + * @author Bernhard Schussek + */ +class FormRegistryTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var FormRegistry + */ + private $registry; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + private $resolvedTypeFactory; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + private $guesser1; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + private $guesser2; + + /** + * @var TestExtension + */ + private $extension1; + + /** + * @var TestExtension + */ + private $extension2; + + protected function setUp() + { + $this->resolvedTypeFactory = $this->getMock('Symfony\Component\Form\ResolvedFormTypeFactory'); + $this->guesser1 = $this->getMock('Symfony\Component\Form\FormTypeGuesserInterface'); + $this->guesser2 = $this->getMock('Symfony\Component\Form\FormTypeGuesserInterface'); + $this->extension1 = new TestExtension($this->guesser1); + $this->extension2 = new TestExtension($this->guesser2); + $this->registry = new FormRegistry(array( + $this->extension1, + $this->extension2, + ), $this->resolvedTypeFactory); + } + + public function testGetTypeFromExtension() + { + $type = new FooType(); + $resolvedType = $this->getMock('Symfony\Component\Form\ResolvedFormTypeInterface'); + + $this->extension2->addType($type); + + $this->resolvedTypeFactory->expects($this->once()) + ->method('createResolvedType') + ->with($type) + ->will($this->returnValue($resolvedType)); + + $resolvedType->expects($this->any()) + ->method('getName') + ->will($this->returnValue('foo')); + + $resolvedType = $this->registry->getType('foo'); + + $this->assertSame($resolvedType, $this->registry->getType('foo')); + } + + public function testGetTypeWithTypeExtensions() + { + $type = new FooType(); + $ext1 = new FooTypeBarExtension(); + $ext2 = new FooTypeBazExtension(); + $resolvedType = $this->getMock('Symfony\Component\Form\ResolvedFormTypeInterface'); + + $this->extension2->addType($type); + $this->extension1->addTypeExtension($ext1); + $this->extension2->addTypeExtension($ext2); + + $this->resolvedTypeFactory->expects($this->once()) + ->method('createResolvedType') + ->with($type, array($ext1, $ext2)) + ->will($this->returnValue($resolvedType)); + + $resolvedType->expects($this->any()) + ->method('getName') + ->will($this->returnValue('foo')); + + $this->assertSame($resolvedType, $this->registry->getType('foo')); + } + + public function testGetTypeConnectsParent() + { + $parentType = new FooType(); + $type = new FooSubType(); + $parentResolvedType = $this->getMock('Symfony\Component\Form\ResolvedFormTypeInterface'); + $resolvedType = $this->getMock('Symfony\Component\Form\ResolvedFormTypeInterface'); + + $this->extension1->addType($parentType); + $this->extension2->addType($type); + + $this->resolvedTypeFactory->expects($this->at(0)) + ->method('createResolvedType') + ->with($parentType) + ->will($this->returnValue($parentResolvedType)); + + $this->resolvedTypeFactory->expects($this->at(1)) + ->method('createResolvedType') + ->with($type, array(), $parentResolvedType) + ->will($this->returnValue($resolvedType)); + + $parentResolvedType->expects($this->any()) + ->method('getName') + ->will($this->returnValue('foo')); + + $resolvedType->expects($this->any()) + ->method('getName') + ->will($this->returnValue('foo_sub_type')); + + $this->assertSame($resolvedType, $this->registry->getType('foo_sub_type')); + } + + public function testGetTypeConnectsParentIfGetParentReturnsInstance() + { + $type = new FooSubTypeWithParentInstance(); + $parentResolvedType = $this->getMock('Symfony\Component\Form\ResolvedFormTypeInterface'); + $resolvedType = $this->getMock('Symfony\Component\Form\ResolvedFormTypeInterface'); + + $this->extension1->addType($type); + + $this->resolvedTypeFactory->expects($this->at(0)) + ->method('createResolvedType') + ->with($this->isInstanceOf('Symfony\Component\Form\Tests\Fixtures\FooType')) + ->will($this->returnValue($parentResolvedType)); + + $this->resolvedTypeFactory->expects($this->at(1)) + ->method('createResolvedType') + ->with($type, array(), $parentResolvedType) + ->will($this->returnValue($resolvedType)); + + $parentResolvedType->expects($this->any()) + ->method('getName') + ->will($this->returnValue('foo')); + + $resolvedType->expects($this->any()) + ->method('getName') + ->will($this->returnValue('foo_sub_type_parent_instance')); + + $this->assertSame($resolvedType, $this->registry->getType('foo_sub_type_parent_instance')); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException + */ + public function testGetTypeThrowsExceptionIfParentNotFound() + { + $type = new FooSubType(); + + $this->extension1->addType($type); + + $this->registry->getType($type); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\InvalidArgumentException + */ + public function testGetTypeThrowsExceptionIfTypeNotFound() + { + $this->registry->getType('bar'); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException + */ + public function testGetTypeThrowsExceptionIfNoString() + { + $this->registry->getType(array()); + } + + public function testHasTypeAfterLoadingFromExtension() + { + $type = new FooType(); + $resolvedType = $this->getMock('Symfony\Component\Form\ResolvedFormTypeInterface'); + + $this->resolvedTypeFactory->expects($this->once()) + ->method('createResolvedType') + ->with($type) + ->will($this->returnValue($resolvedType)); + + $resolvedType->expects($this->any()) + ->method('getName') + ->will($this->returnValue('foo')); + + $this->assertFalse($this->registry->hasType('foo')); + + $this->extension2->addType($type); + + $this->assertTrue($this->registry->hasType('foo')); + } + + public function testGetTypeGuesser() + { + $expectedGuesser = new FormTypeGuesserChain(array($this->guesser1, $this->guesser2)); + + $this->assertEquals($expectedGuesser, $this->registry->getTypeGuesser()); + + $registry = new FormRegistry( + array($this->getMock('Symfony\Component\Form\FormExtensionInterface')), + $this->resolvedTypeFactory); + + $this->assertNull($registry->getTypeGuesser()); + } + + public function testGetExtensions() + { + $expectedExtensions = array($this->extension1, $this->extension2); + + $this->assertEquals($expectedExtensions, $this->registry->getExtensions()); + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/FormRendererTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/FormRendererTest.php new file mode 100644 index 00000000..69b048f7 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/FormRendererTest.php @@ -0,0 +1,27 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Test; + +class FormRendererTest extends \PHPUnit_Framework_TestCase +{ + public function testHumanize() + { + $renderer = $this->getMockBuilder('Symfony\Component\Form\FormRenderer') + ->setMethods(null) + ->disableOriginalConstructor() + ->getMock() + ; + + $this->assertEquals('Is active', $renderer->humanize('is_active')); + $this->assertEquals('Is active', $renderer->humanize('isActive')); + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/Guess/GuessTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/Guess/GuessTest.php new file mode 100644 index 00000000..235eb6ed --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/Guess/GuessTest.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Guess; + +use Symfony\Component\Form\Guess\Guess; + +class TestGuess extends Guess {} + +class GuessTest extends \PHPUnit_Framework_TestCase +{ + public function testGetBestGuessReturnsGuessWithHighestConfidence() + { + $guess1 = new TestGuess(Guess::MEDIUM_CONFIDENCE); + $guess2 = new TestGuess(Guess::LOW_CONFIDENCE); + $guess3 = new TestGuess(Guess::HIGH_CONFIDENCE); + + $this->assertSame($guess3, Guess::getBestGuess(array($guess1, $guess2, $guess3))); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testGuessExpectsValidConfidence() + { + new TestGuess(5); + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/NativeRequestHandlerTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/NativeRequestHandlerTest.php new file mode 100644 index 00000000..9d3a997f --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/NativeRequestHandlerTest.php @@ -0,0 +1,219 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests; + +use Symfony\Component\Form\NativeRequestHandler; + +/** + * @author Bernhard Schussek + */ +class NativeRequestHandlerTest extends AbstractRequestHandlerTest +{ + private static $serverBackup; + + public static function setUpBeforeClass() + { + self::$serverBackup = $_SERVER; + } + + protected function setUp() + { + parent::setUp(); + + $_GET = array(); + $_POST = array(); + $_FILES = array(); + $_SERVER = array( + // PHPUnit needs this entry + 'SCRIPT_NAME' => self::$serverBackup['SCRIPT_NAME'], + ); + } + + protected function tearDown() + { + parent::tearDown(); + + $_GET = array(); + $_POST = array(); + $_FILES = array(); + $_SERVER = self::$serverBackup; + } + + /** + * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException + */ + public function testRequestShouldBeNull() + { + $this->requestHandler->handleRequest($this->getMockForm('name', 'GET'), 'request'); + } + + public function testMethodOverrideHeaderTakesPrecedenceIfPost() + { + $form = $this->getMockForm('param1', 'PUT'); + + $this->setRequestData('POST', array( + 'param1' => 'DATA', + )); + + $_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'] = 'PUT'; + + $form->expects($this->once()) + ->method('submit') + ->with('DATA'); + + $this->requestHandler->handleRequest($form, $this->request); + } + + public function testConvertEmptyUploadedFilesToNull() + { + $form = $this->getMockForm('param1', 'POST', false); + + $this->setRequestData('POST', array(), array('param1' => array( + 'name' => '', + 'type' => '', + 'tmp_name' => '', + 'error' => UPLOAD_ERR_NO_FILE, + 'size' => 0 + ))); + + $form->expects($this->once()) + ->method('submit') + ->with($this->identicalTo(null)); + + $this->requestHandler->handleRequest($form, $this->request); + } + + public function testFixBuggyFilesArray() + { + $form = $this->getMockForm('param1', 'POST', false); + + $this->setRequestData('POST', array(), array('param1' => array( + 'name' => array( + 'field' => 'upload.txt', + ), + 'type' => array( + 'field' => 'text/plain', + ), + 'tmp_name' => array( + 'field' => 'owfdskjasdfsa', + ), + 'error' => array( + 'field' => UPLOAD_ERR_OK, + ), + 'size' => array( + 'field' => 100, + ), + ))); + + $form->expects($this->once()) + ->method('submit') + ->with(array( + 'field' => array( + 'name' => 'upload.txt', + 'type' => 'text/plain', + 'tmp_name' => 'owfdskjasdfsa', + 'error' => UPLOAD_ERR_OK, + 'size' => 100, + ), + )); + + $this->requestHandler->handleRequest($form, $this->request); + } + + public function testFixBuggyNestedFilesArray() + { + $form = $this->getMockForm('param1', 'POST'); + + $this->setRequestData('POST', array(), array('param1' => array( + 'name' => array( + 'field' => array('subfield' => 'upload.txt'), + ), + 'type' => array( + 'field' => array('subfield' => 'text/plain'), + ), + 'tmp_name' => array( + 'field' => array('subfield' => 'owfdskjasdfsa'), + ), + 'error' => array( + 'field' => array('subfield' => UPLOAD_ERR_OK), + ), + 'size' => array( + 'field' => array('subfield' => 100), + ), + ))); + + $form->expects($this->once()) + ->method('submit') + ->with(array( + 'field' => array( + 'subfield' => array( + 'name' => 'upload.txt', + 'type' => 'text/plain', + 'tmp_name' => 'owfdskjasdfsa', + 'error' => UPLOAD_ERR_OK, + 'size' => 100, + ), + ), + )); + + $this->requestHandler->handleRequest($form, $this->request); + } + + public function testMethodOverrideHeaderIgnoredIfNotPost() + { + $form = $this->getMockForm('param1', 'POST'); + + $this->setRequestData('GET', array( + 'param1' => 'DATA', + )); + + $_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'] = 'PUT'; + + $form->expects($this->never()) + ->method('submit'); + + $this->requestHandler->handleRequest($form, $this->request); + } + + protected function setRequestData($method, $data, $files = array()) + { + if ('GET' === $method) { + $_GET = $data; + $_FILES = array(); + } else { + $_POST = $data; + $_FILES = $files; + } + + $_SERVER = array( + 'REQUEST_METHOD' => $method, + // PHPUnit needs this entry + 'SCRIPT_NAME' => self::$serverBackup['SCRIPT_NAME'], + ); + } + + protected function getRequestHandler() + { + return new NativeRequestHandler(); + } + + protected function getMockFile() + { + return array( + 'name' => 'upload.txt', + 'type' => 'text/plain', + 'tmp_name' => 'owfdskjasdfsa', + 'error' => UPLOAD_ERR_OK, + 'size' => 100, + ); + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/ResolvedFormTypeTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/ResolvedFormTypeTest.php new file mode 100644 index 00000000..bb32a241 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/ResolvedFormTypeTest.php @@ -0,0 +1,280 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests; + +use Symfony\Component\Form\ResolvedFormType; +use Symfony\Component\Form\FormView; +use Symfony\Component\Form\FormBuilder; +use Symfony\Component\Form\Form; +use Symfony\Component\OptionsResolver\OptionsResolverInterface; + +/** + * @author Bernhard Schussek + */ +class ResolvedFormTypeTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + private $dispatcher; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + private $factory; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + private $dataMapper; + + protected function setUp() + { + if (!class_exists('Symfony\Component\OptionsResolver\OptionsResolver')) { + $this->markTestSkipped('The "OptionsResolver" component is not available'); + } + + if (!class_exists('Symfony\Component\EventDispatcher\EventDispatcher')) { + $this->markTestSkipped('The "EventDispatcher" component is not available'); + } + + $this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); + $this->factory = $this->getMock('Symfony\Component\Form\FormFactoryInterface'); + $this->dataMapper = $this->getMock('Symfony\Component\Form\DataMapperInterface'); + } + + public function testCreateBuilder() + { + if (version_compare(\PHPUnit_Runner_Version::id(), '3.7', '<')) { + $this->markTestSkipped('This test requires PHPUnit 3.7.'); + } + + $parentType = $this->getMockFormType(); + $type = $this->getMockFormType(); + $extension1 = $this->getMockFormTypeExtension(); + $extension2 = $this->getMockFormTypeExtension(); + + $parentResolvedType = new ResolvedFormType($parentType); + $resolvedType = new ResolvedFormType($type, array($extension1, $extension2), $parentResolvedType); + + $test = $this; + $i = 0; + + $assertIndex = function ($index) use (&$i, $test) { + return function () use (&$i, $test, $index) { + /* @var \PHPUnit_Framework_TestCase $test */ + $test->assertEquals($index, $i, 'Executed at index '.$index); + + ++$i; + }; + }; + + $assertIndexAndAddOption = function ($index, $option, $default) use ($assertIndex) { + $assertIndex = $assertIndex($index); + + return function (OptionsResolverInterface $resolver) use ($assertIndex, $index, $option, $default) { + $assertIndex(); + + $resolver->setDefaults(array($option => $default)); + }; + }; + + // First the default options are generated for the super type + $parentType->expects($this->once()) + ->method('setDefaultOptions') + ->will($this->returnCallback($assertIndexAndAddOption(0, 'a', 'a_default'))); + + // The form type itself + $type->expects($this->once()) + ->method('setDefaultOptions') + ->will($this->returnCallback($assertIndexAndAddOption(1, 'b', 'b_default'))); + + // And its extensions + $extension1->expects($this->once()) + ->method('setDefaultOptions') + ->will($this->returnCallback($assertIndexAndAddOption(2, 'c', 'c_default'))); + + $extension2->expects($this->once()) + ->method('setDefaultOptions') + ->will($this->returnCallback($assertIndexAndAddOption(3, 'd', 'd_default'))); + + $givenOptions = array('a' => 'a_custom', 'c' => 'c_custom'); + $resolvedOptions = array('a' => 'a_custom', 'b' => 'b_default', 'c' => 'c_custom', 'd' => 'd_default'); + + // Then the form is built for the super type + $parentType->expects($this->once()) + ->method('buildForm') + ->with($this->anything(), $resolvedOptions) + ->will($this->returnCallback($assertIndex(4))); + + // Then the type itself + $type->expects($this->once()) + ->method('buildForm') + ->with($this->anything(), $resolvedOptions) + ->will($this->returnCallback($assertIndex(5))); + + // Then its extensions + $extension1->expects($this->once()) + ->method('buildForm') + ->with($this->anything(), $resolvedOptions) + ->will($this->returnCallback($assertIndex(6))); + + $extension2->expects($this->once()) + ->method('buildForm') + ->with($this->anything(), $resolvedOptions) + ->will($this->returnCallback($assertIndex(7))); + + $factory = $this->getMockFormFactory(); + $builder = $resolvedType->createBuilder($factory, 'name', $givenOptions); + + $this->assertSame($resolvedType, $builder->getType()); + } + + public function testCreateView() + { + $parentType = $this->getMockFormType(); + $type = $this->getMockFormType(); + $field1Type = $this->getMockFormType(); + $field2Type = $this->getMockFormType(); + $extension1 = $this->getMockFormTypeExtension(); + $extension2 = $this->getMockFormTypeExtension(); + + $parentResolvedType = new ResolvedFormType($parentType); + $resolvedType = new ResolvedFormType($type, array($extension1, $extension2), $parentResolvedType); + $field1ResolvedType = new ResolvedFormType($field1Type); + $field2ResolvedType = new ResolvedFormType($field2Type); + + $options = array('a' => '1', 'b' => '2'); + $form = $this->getBuilder('name', $options) + ->setCompound(true) + ->setDataMapper($this->dataMapper) + ->setType($resolvedType) + ->add($this->getBuilder('foo')->setType($field1ResolvedType)) + ->add($this->getBuilder('bar')->setType($field2ResolvedType)) + ->getForm(); + + $test = $this; + $i = 0; + + $assertIndexAndNbOfChildViews = function ($index, $nbOfChildViews) use (&$i, $test) { + return function (FormView $view) use (&$i, $test, $index, $nbOfChildViews) { + /* @var \PHPUnit_Framework_TestCase $test */ + $test->assertEquals($index, $i, 'Executed at index '.$index); + $test->assertCount($nbOfChildViews, $view); + + ++$i; + }; + }; + + // First the super type + $parentType->expects($this->once()) + ->method('buildView') + ->with($this->anything(), $form, $options) + ->will($this->returnCallback($assertIndexAndNbOfChildViews(0, 0))); + + // Then the type itself + $type->expects($this->once()) + ->method('buildView') + ->with($this->anything(), $form, $options) + ->will($this->returnCallback($assertIndexAndNbOfChildViews(1, 0))); + + // Then its extensions + $extension1->expects($this->once()) + ->method('buildView') + ->with($this->anything(), $form, $options) + ->will($this->returnCallback($assertIndexAndNbOfChildViews(2, 0))); + + $extension2->expects($this->once()) + ->method('buildView') + ->with($this->anything(), $form, $options) + ->will($this->returnCallback($assertIndexAndNbOfChildViews(3, 0))); + + // Now the first child form + $field1Type->expects($this->once()) + ->method('buildView') + ->will($this->returnCallback($assertIndexAndNbOfChildViews(4, 0))); + $field1Type->expects($this->once()) + ->method('finishView') + ->will($this->returnCallback($assertIndexAndNbOfChildViews(5, 0))); + + // And the second child form + $field2Type->expects($this->once()) + ->method('buildView') + ->will($this->returnCallback($assertIndexAndNbOfChildViews(6, 0))); + $field2Type->expects($this->once()) + ->method('finishView') + ->will($this->returnCallback($assertIndexAndNbOfChildViews(7, 0))); + + // Again first the parent + $parentType->expects($this->once()) + ->method('finishView') + ->with($this->anything(), $form, $options) + ->will($this->returnCallback($assertIndexAndNbOfChildViews(8, 2))); + + // Then the type itself + $type->expects($this->once()) + ->method('finishView') + ->with($this->anything(), $form, $options) + ->will($this->returnCallback($assertIndexAndNbOfChildViews(9, 2))); + + // Then its extensions + $extension1->expects($this->once()) + ->method('finishView') + ->with($this->anything(), $form, $options) + ->will($this->returnCallback($assertIndexAndNbOfChildViews(10, 2))); + + $extension2->expects($this->once()) + ->method('finishView') + ->with($this->anything(), $form, $options) + ->will($this->returnCallback($assertIndexAndNbOfChildViews(11, 2))); + + $parentView = new FormView(); + $view = $resolvedType->createView($form, $parentView); + + $this->assertSame($parentView, $view->parent); + } + + /** + * @return \PHPUnit_Framework_MockObject_MockObject + */ + private function getMockFormType() + { + return $this->getMock('Symfony\Component\Form\FormTypeInterface'); + } + + /** + * @return \PHPUnit_Framework_MockObject_MockObject + */ + private function getMockFormTypeExtension() + { + return $this->getMock('Symfony\Component\Form\FormTypeExtensionInterface'); + } + + /** + * @return \PHPUnit_Framework_MockObject_MockObject + */ + private function getMockFormFactory() + { + return $this->getMock('Symfony\Component\Form\FormFactoryInterface'); + } + + /** + * @param string $name + * @param array $options + * + * @return FormBuilder + */ + protected function getBuilder($name = 'name', array $options = array()) + { + return new FormBuilder($name, null, $this->dispatcher, $this->factory, $options); + } +} diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/SimpleFormTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/SimpleFormTest.php new file mode 100644 index 00000000..bedad676 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/SimpleFormTest.php @@ -0,0 +1,1045 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests; + +use Symfony\Component\Form\Form; +use Symfony\Component\Form\FormEvent; +use Symfony\Component\Form\FormEvents; +use Symfony\Component\PropertyAccess\PropertyPath; +use Symfony\Component\Form\FormConfigBuilder; +use Symfony\Component\Form\FormError; +use Symfony\Component\Form\Exception\TransformationFailedException; +use Symfony\Component\EventDispatcher\EventDispatcher; +use Symfony\Component\Form\Tests\Fixtures\FixedDataTransformer; +use Symfony\Component\Form\Tests\Fixtures\FixedFilterListener; + +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) + { + $this->iterator = new \ArrayIterator($count > 0 ? array_fill(0, $count, 'Foo') : array()); + } + + public function getIterator() + { + return $this->iterator; + } +} + +class SimpleFormTest extends AbstractFormTest +{ + public function testDataIsInitializedToConfiguredValue() + { + $model = new FixedDataTransformer(array( + 'default' => 'foo', + )); + $view = new FixedDataTransformer(array( + 'foo' => 'bar', + )); + + $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()); + } + + // https://github.com/symfony/symfony/commit/d4f4038f6daf7cf88ca7c7ab089473cce5ebf7d8#commitcomment-1632879 + public function testDataIsInitializedFromSubmit() + { + $mock = $this->getMockBuilder('\stdClass') + ->setMethods(array('preSetData', 'preSubmit')) + ->getMock(); + $mock->expects($this->at(0)) + ->method('preSetData'); + $mock->expects($this->at(1)) + ->method('preSubmit'); + + $config = new FormConfigBuilder('name', null, $this->dispatcher); + $config->addEventListener(FormEvents::PRE_SET_DATA, array($mock, 'preSetData')); + $config->addEventListener(FormEvents::PRE_SUBMIT, array($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') + ->setMethods(array('preBind')) + ->getMock(); + $mock->expects($this->once()) + ->method('preBind') + ->with($this->callback(function ($event) { + return null === $event->getData(); + })); + + $config = new FormConfigBuilder('name', null, $this->dispatcher); + $config->addEventListener(FormEvents::PRE_BIND, array($mock, 'preBind')); + $form = new Form($config); + + $form->bind(false); + + $this->assertTrue($form->isValid()); + $this->assertNull($form->getData()); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\AlreadySubmittedException + */ + public function testSubmitThrowsExceptionIfAlreadySubmitted() + { + $this->form->submit(array()); + $this->form->submit(array()); + } + + 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()); + } + + public function testAlwaysDisabledIfParentDisabled() + { + $parent = $this->getBuilder()->setDisabled(true)->getForm(); + $child = $this->getBuilder()->setDisabled(false)->getForm(); + + $child->setParent($parent); + + $this->assertTrue($child->isDisabled()); + } + + public function testDisabled() + { + $parent = $this->getBuilder()->setDisabled(false)->getForm(); + $child = $this->getBuilder()->setDisabled(true)->getForm(); + + $child->setParent($parent); + + $this->assertTrue($child->isDisabled()); + } + + public function testNotDisabled() + { + $parent = $this->getBuilder()->setDisabled(false)->getForm(); + $child = $this->getBuilder()->setDisabled(false)->getForm(); + + $child->setParent($parent); + + $this->assertFalse($child->isDisabled()); + } + + public function testGetRootReturnsRootOfParent() + { + $parent = $this->getMockForm(); + $parent->expects($this->once()) + ->method('getRoot') + ->will($this->returnValue('ROOT')); + + $this->form->setParent($parent); + + $this->assertEquals('ROOT', $this->form->getRoot()); + } + + public function testGetRootReturnsSelfIfNoParent() + { + $this->assertSame($this->form, $this->form->getRoot()); + } + + public function testEmptyIfEmptyArray() + { + $this->form->setData(array()); + + $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()); + } + + 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() + { + $this->form->submit(array()); + $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() + { + $this->form->submit(array()); + $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()) + ->addEventSubscriber(new FixedFilterListener(array( + 'preSetData' => array( + 'app' => 'filtered', + ), + ))) + ->addModelTransformer(new FixedDataTransformer(array( + '' => '', + 'filtered' => 'norm', + ))) + ->addViewTransformer(new FixedDataTransformer(array( + '' => '', + 'norm' => 'client', + ))) + ->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() + ->addViewTransformer(new FixedDataTransformer(array( + '' => '', + 'first' => 'second', + ))) + ->addViewTransformer(new FixedDataTransformer(array( + '' => '', + 'second' => 'third', + ))) + ->getForm(); + + $form->setData('first'); + + $this->assertEquals('third', $form->getViewData()); + } + + public function testSetDataExecutesModelTransformersInReverseOrder() + { + $form = $this->getBuilder() + ->addModelTransformer(new FixedDataTransformer(array( + '' => '', + 'second' => 'third', + ))) + ->addModelTransformer(new FixedDataTransformer(array( + '' => '', + 'first' => 'second', + ))) + ->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() + ->addModelTransformer(new FixedDataTransformer(array( + '' => '', + 1 => 23, + ))) + ->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 + * 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 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()) + ->addEventSubscriber(new FixedFilterListener(array( + 'preSubmit' => array( + 'client' => 'filteredclient', + ), + 'onSubmit' => array( + 'norm' => 'filterednorm', + ), + ))) + ->addViewTransformer(new FixedDataTransformer(array( + '' => '', + // direction is reversed! + 'norm' => 'filteredclient', + 'filterednorm' => 'cleanedclient' + ))) + ->addModelTransformer(new FixedDataTransformer(array( + '' => '', + // direction is reversed! + 'app' => 'filterednorm', + ))) + ->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() + ->addViewTransformer(new FixedDataTransformer(array( + '' => '', + 'third' => 'second', + ))) + ->addViewTransformer(new FixedDataTransformer(array( + '' => '', + 'second' => 'first', + ))) + ->getForm(); + + $form->submit('first'); + + $this->assertEquals('third', $form->getNormData()); + } + + public function testSubmitExecutesModelTransformersInOrder() + { + $form = $this->getBuilder() + ->addModelTransformer(new FixedDataTransformer(array( + '' => '', + 'second' => 'first', + ))) + ->addModelTransformer(new FixedDataTransformer(array( + '' => '', + 'third' => 'second', + ))) + ->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') + ->will($this->throwException(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') + ->will($this->throwException(new TransformationFailedException())); + + $form = $this->getBuilder() + ->addModelTransformer($transformer) + ->getForm(); + + $form->submit('foobar'); + + $this->assertFalse($form->isSynchronized()); + } + + public function testEmptyDataCreatedBeforeTransforming() + { + $form = $this->getBuilder() + ->setEmptyData('foo') + ->addViewTransformer(new FixedDataTransformer(array( + '' => '', + // direction is reversed! + 'bar' => 'foo', + ))) + ->getForm(); + + $form->submit(''); + + $this->assertEquals('bar', $form->getData()); + } + + public function testEmptyDataFromClosure() + { + $test = $this; + $form = $this->getBuilder() + ->setEmptyData(function ($form) use ($test) { + // the form instance is passed to the closure to allow use + // of form data when creating the empty value + $test->assertInstanceOf('Symfony\Component\Form\FormInterface', $form); + + return 'foo'; + }) + ->addViewTransformer(new FixedDataTransformer(array( + '' => '', + // direction is reversed! + 'bar' => 'foo', + ))) + ->getForm(); + + $form->submit(''); + + $this->assertEquals('bar', $form->getData()); + } + + public function testSubmitResetsErrors() + { + $this->form->addError(new FormError('Error!')); + $this->form->submit('foobar'); + + $this->assertSame(array(), $this->form->getErrors()); + } + + public function testCreateView() + { + $type = $this->getMock('Symfony\Component\Form\ResolvedFormTypeInterface'); + $view = $this->getMock('Symfony\Component\Form\FormView'); + $form = $this->getBuilder()->setType($type)->getForm(); + + $type->expects($this->once()) + ->method('createView') + ->with($form) + ->will($this->returnValue($view)); + + $this->assertSame($view, $form->createView()); + } + + public function testCreateViewWithParent() + { + $type = $this->getMock('Symfony\Component\Form\ResolvedFormTypeInterface'); + $view = $this->getMock('Symfony\Component\Form\FormView'); + $parentForm = $this->getMock('Symfony\Component\Form\Test\FormInterface'); + $parentView = $this->getMock('Symfony\Component\Form\FormView'); + $form = $this->getBuilder()->setType($type)->getForm(); + $form->setParent($parentForm); + + $parentForm->expects($this->once()) + ->method('createView') + ->will($this->returnValue($parentView)); + + $type->expects($this->once()) + ->method('createView') + ->with($form, $parentView) + ->will($this->returnValue($view)); + + $this->assertSame($view, $form->createView()); + } + + public function testCreateViewWithExplicitParent() + { + $type = $this->getMock('Symfony\Component\Form\ResolvedFormTypeInterface'); + $view = $this->getMock('Symfony\Component\Form\FormView'); + $parentView = $this->getMock('Symfony\Component\Form\FormView'); + $form = $this->getBuilder()->setType($type)->getForm(); + + $type->expects($this->once()) + ->method('createView') + ->with($form, $parentView) + ->will($this->returnValue($view)); + + $this->assertSame($view, $form->createView($parentView)); + } + + public function testGetErrorsAsString() + { + $this->form->addError(new FormError('Error!')); + + $this->assertEquals("ERROR: Error!\n", $this->form->getErrorsAsString()); + } + + public function testFormCanHaveEmptyName() + { + $form = $this->getBuilder('')->getForm(); + + $this->assertEquals('', $form->getName()); + } + + 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()); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\LogicException + */ + public function testViewDataMustNotBeObjectIfDataClassIsNull() + { + $config = new FormConfigBuilder('name', null, $this->dispatcher); + $config->addViewTransformer(new FixedDataTransformer(array( + '' => '', + 'foo' => new \stdClass(), + ))); + $form = new Form($config); + + $form->setData('foo'); + } + + public function testViewDataMayBeArrayAccessIfDataClassIsNull() + { + $arrayAccess = $this->getMock('\ArrayAccess'); + $config = new FormConfigBuilder('name', null, $this->dispatcher); + $config->addViewTransformer(new FixedDataTransformer(array( + '' => '', + 'foo' => $arrayAccess, + ))); + $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); + $config->addViewTransformer(new FixedDataTransformer(array( + '' => '', + 'foo' => array('bar' => 'baz'), + ))); + $form = new Form($config); + + $form->setData('foo'); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\RuntimeException + */ + 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() + { + $test = $this; + + $child = $this->getBuilder('child', $this->dispatcher); + $child->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) use ($test) { + // child form doesn't receive the wrong data that is submitted on parent + $test->assertNull($event->getData()); + }); + + $parent = $this->getBuilder('parent', new EventDispatcher()) + ->setCompound(true) + ->setDataMapper($this->getDataMapper()) + ->add($child) + ->getForm(); + + $parent->submit('not-an-array'); + } + + public function testHandleRequestForwardsToRequestHandler() + { + $handler = $this->getMock('Symfony\Component\Form\RequestHandlerInterface'); + + $form = $this->getBuilder() + ->setRequestHandler($handler) + ->getForm(); + + $handler->expects($this->once()) + ->method('handleRequest') + ->with($this->identicalTo($form), 'REQUEST'); + + $this->assertSame($form, $form->handleRequest('REQUEST')); + } + + public function testFormInheritsParentData() + { + $child = $this->getBuilder('child') + ->setInheritData(true); + + $parent = $this->getBuilder('parent') + ->setCompound(true) + ->setDataMapper($this->getDataMapper()) + ->setData('foo') + ->addModelTransformer(new FixedDataTransformer(array( + 'foo' => 'norm[foo]', + ))) + ->addViewTransformer(new FixedDataTransformer(array( + 'norm[foo]' => 'view[foo]', + ))) + ->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() + { + $test = $this; + $form = $this->getBuilder() + ->addEventListener(FormEvents::POST_SUBMIT, function (FormEvent $event) use ($test) { + $test->assertNull($event->getData()); + }) + ->setInheritData(true) + ->getForm(); + + $form->submit('foo'); + } + + public function testSubmitIsNeverFiredIfInheritData() + { + $test = $this; + $form = $this->getBuilder() + ->addEventListener(FormEvents::SUBMIT, function (FormEvent $event) use ($test) { + $test->fail('The SUBMIT event should not be fired'); + }) + ->setInheritData(true) + ->getForm(); + + $form->submit('foo'); + } + + public function testInitializeSetsDefaultData() + { + $config = $this->getBuilder()->setData('DEFAULT')->getFormConfig(); + $form = $this->getMock('Symfony\Component\Form\Form', array('setData'), array($config)); + + $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(); + } + + protected function createForm() + { + return $this->getBuilder()->getForm(); + } +} -- cgit v1.2.3