Actualización

This commit is contained in:
Xes
2025-04-10 12:24:57 +02:00
parent 8969cc929d
commit 45420b6f0d
39760 changed files with 4303286 additions and 0 deletions

View File

@@ -0,0 +1,157 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests;
abstract class AbstractBootstrap3HorizontalLayoutTest extends AbstractBootstrap3LayoutTest
{
public function testLabelOnForm()
{
$form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\DateType');
$view = $form->createView();
$this->renderWidget($view, array('label' => 'foo'));
$html = $this->renderLabel($view);
$this->assertMatchesXpath($html,
'/label
[@class="col-sm-2 control-label required"]
[.="[trans]Name[/trans]"]
'
);
}
public function testLabelDoesNotRenderFieldAttributes()
{
$form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TextType');
$html = $this->renderLabel($form->createView(), null, array(
'attr' => array(
'class' => 'my&class',
),
));
$this->assertMatchesXpath($html,
'/label
[@for="name"]
[@class="col-sm-2 control-label required"]
'
);
}
public function testLabelWithCustomAttributesPassedDirectly()
{
$form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TextType');
$html = $this->renderLabel($form->createView(), null, array(
'label_attr' => array(
'class' => 'my&class',
),
));
$this->assertMatchesXpath($html,
'/label
[@for="name"]
[@class="my&class col-sm-2 control-label required"]
'
);
}
public function testLabelWithCustomTextAndCustomAttributesPassedDirectly()
{
$form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TextType');
$html = $this->renderLabel($form->createView(), 'Custom label', array(
'label_attr' => array(
'class' => 'my&class',
),
));
$this->assertMatchesXpath($html,
'/label
[@for="name"]
[@class="my&class col-sm-2 control-label required"]
[.="[trans]Custom label[/trans]"]
'
);
}
public function testLabelWithCustomTextAsOptionAndCustomAttributesPassedDirectly()
{
$form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TextType', 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 col-sm-2 control-label required"]
[.="[trans]Custom label[/trans]"]
'
);
}
public function testStartTag()
{
$form = $this->factory->create('Symfony\Component\Form\Extension\Core\Type\FormType', null, array(
'method' => 'get',
'action' => 'http://example.com/directory',
));
$html = $this->renderStart($form->createView());
$this->assertSame('<form name="form" method="get" action="http://example.com/directory" class="form-horizontal">', $html);
}
public function testStartTagWithOverriddenVars()
{
$form = $this->factory->create('Symfony\Component\Form\Extension\Core\Type\FormType', null, array(
'method' => 'put',
'action' => 'http://example.com/directory',
));
$html = $this->renderStart($form->createView(), array(
'method' => 'post',
'action' => 'http://foo.com/directory',
));
$this->assertSame('<form name="form" method="post" action="http://foo.com/directory" class="form-horizontal">', $html);
}
public function testStartTagForMultipartForm()
{
$form = $this->factory->createBuilder('Symfony\Component\Form\Extension\Core\Type\FormType', null, array(
'method' => 'get',
'action' => 'http://example.com/directory',
))
->add('file', 'Symfony\Component\Form\Extension\Core\Type\FileType')
->getForm();
$html = $this->renderStart($form->createView());
$this->assertSame('<form name="form" method="get" action="http://example.com/directory" class="form-horizontal" enctype="multipart/form-data">', $html);
}
public function testStartTagWithExtraAttributes()
{
$form = $this->factory->create('Symfony\Component\Form\Extension\Core\Type\FormType', null, array(
'method' => 'get',
'action' => 'http://example.com/directory',
));
$html = $this->renderStart($form->createView(), array(
'attr' => array('class' => 'foobar'),
));
$this->assertSame('<form name="form" method="get" action="http://example.com/directory" class="foobar form-horizontal">', $html);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,934 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests;
use Symfony\Component\Form\FormError;
use Symfony\Component\Security\Csrf\CsrfToken;
abstract class AbstractDivLayoutTest extends AbstractLayoutTest
{
public function testRow()
{
$form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TextType');
$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', 'Symfony\Component\Form\Extension\Core\Type\TextType')->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', 'Symfony\Component\Form\Extension\Core\Type\RepeatedType');
$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', 'Symfony\Component\Form\Extension\Core\Type\ButtonType');
$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', 'Symfony\Component\Form\Extension\Core\Type\FormType')
->add('field1', 'Symfony\Component\Form\Extension\Core\Type\TextType')
->add('field2', 'Symfony\Component\Form\Extension\Core\Type\RepeatedType')
->add('field3', 'Symfony\Component\Form\Extension\Core\Type\TextType')
->add('field4', 'Symfony\Component\Form\Extension\Core\Type\TextType')
->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', 'Symfony\Component\Form\Extension\Core\Type\FormType')
->add('field1', 'Symfony\Component\Form\Extension\Core\Type\TextType')
->add('field2', 'Symfony\Component\Form\Extension\Core\Type\TextType');
$child2 = $this->factory->createNamedBuilder('child2', 'Symfony\Component\Form\Extension\Core\Type\FormType')
->add('field1', 'Symfony\Component\Form\Extension\Core\Type\TextType')
->add('field2', 'Symfony\Component\Form\Extension\Core\Type\TextType');
$view = $this->factory->createNamedBuilder('parent', 'Symfony\Component\Form\Extension\Core\Type\FormType')
->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', 'Symfony\Component\Form\Extension\Core\Type\FormType')
->add('first', 'Symfony\Component\Form\Extension\Core\Type\TextType')
->add('password', 'Symfony\Component\Form\Extension\Core\Type\RepeatedType')
->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', 'Symfony\Component\Form\Extension\Core\Type\FormType')
->add('first', 'Symfony\Component\Form\Extension\Core\Type\TextType')
->add('password', 'Symfony\Component\Form\Extension\Core\Type\RepeatedType')
->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', 'Symfony\Component\Form\Extension\Core\Type\FormType')
->add('first', 'Symfony\Component\Form\Extension\Core\Type\TextType')
->add('password', 'Symfony\Component\Form\Extension\Core\Type\RepeatedType')
->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('names', 'Symfony\Component\Form\Extension\Core\Type\CollectionType', array('a', 'b'), array(
'entry_type' => 'Symfony\Component\Form\Extension\Core\Type\TextType',
));
$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('names', 'Symfony\Component\Form\Extension\Core\Type\CollectionType', $data, array(
'entry_type' => 'Symfony\Component\Form\Tests\Fixtures\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('names', 'Symfony\Component\Form\Extension\Core\Type\CollectionType', array(), array(
'entry_type' => 'Symfony\Component\Form\Extension\Core\Type\TextType',
));
$this->assertWidgetMatchesXpath($form->createView(), array(),
'/div
[./input[@type="hidden"][@id="names__token"]]
[count(./div)=0]
'
);
}
public function testCollectionRow()
{
$collection = $this->factory->createNamedBuilder(
'collection',
'Symfony\Component\Form\Extension\Core\Type\CollectionType',
array('a', 'b'),
array('entry_type' => 'Symfony\Component\Form\Extension\Core\Type\TextType')
);
$form = $this->factory->createNamedBuilder('form', 'Symfony\Component\Form\Extension\Core\Type\FormType')
->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', 'Symfony\Component\Form\Extension\Core\Type\FormType')
->setMethod('PUT')
->setAction('http://example.com')
->add('firstName', 'Symfony\Component\Form\Extension\Core\Type\TextType')
->add('lastName', 'Symfony\Component\Form\Extension\Core\Type\TextType')
->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', 'Symfony\Component\Form\Extension\Core\Type\FormType')
->add('firstName', 'Symfony\Component\Form\Extension\Core\Type\TextType')
->add('lastName', 'Symfony\Component\Form\Extension\Core\Type\TextType')
->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', 'Symfony\Component\Form\Extension\Core\Type\FormType')
->add($this->factory
->createNamedBuilder('child', 'Symfony\Component\Form\Extension\Core\Type\FormType', null, array('error_bubbling' => false))
->add('grandChild', 'Symfony\Component\Form\Extension\Core\Type\FormType')
)
->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->csrfTokenManager->expects($this->any())
->method('getToken')
->will($this->returnValue(new CsrfToken('token_id', 'foo&bar')));
$form = $this->factory->createNamedBuilder('name', 'Symfony\Component\Form\Extension\Core\Type\FormType')
->add($this->factory
// No CSRF protection on nested forms
->createNamedBuilder('child', 'Symfony\Component\Form\Extension\Core\Type\FormType')
->add($this->factory->createNamedBuilder('grandchild', 'Symfony\Component\Form\Extension\Core\Type\TextType'))
)
->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', 'Symfony\Component\Form\Extension\Core\Type\RepeatedType', 'foobar', array(
'type' => 'Symfony\Component\Form\Extension\Core\Type\TextType',
));
$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', 'Symfony\Component\Form\Extension\Core\Type\RepeatedType', 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', 'Symfony\Component\Form\Extension\Core\Type\FormType')
->add('name', 'Symfony\Component\Form\Extension\Core\Type\SearchType')
->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', 'Symfony\Component\Form\Extension\Core\Type\TextType');
$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', 'Symfony\Component\Form\Extension\Core\Type\TextType', 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', 'Symfony\Component\Form\Extension\Core\Type\EmailType')
->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', 'Symfony\Component\Form\Extension\Core\Type\FormType')
->add('field', 'Symfony\Component\Form\Extension\Core\Type\TextType');
$view = $this->factory->createNamedBuilder('parent', 'Symfony\Component\Form\Extension\Core\Type\FormType')
->add('field', 'Symfony\Component\Form\Extension\Core\Type\TextType')
->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('names', 'Symfony\Component\Form\Extension\Core\Type\CollectionType', $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]"]]
]
'
);
}
/**
* The block "_name_c_entry_label" should be overridden in the theme of the
* implemented driver.
*/
public function testChoiceRowWithCustomBlock()
{
$form = $this->factory->createNamedBuilder('name_c', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', 'a', array(
'choices' => array('ChoiceA' => 'a', 'ChoiceB' => 'b'),
'expanded' => true,
))
->getForm();
$this->assertWidgetMatchesXpath($form->createView(), array(),
'/div
[
./label[.="Custom name label: [trans]ChoiceA[/trans]"]
/following-sibling::label[.="Custom name label: [trans]ChoiceB[/trans]"]
]
'
);
}
public function testSingleChoiceExpandedWithLabelsAsFalse()
{
$form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', '&a', array(
'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'),
'choice_label' => false,
'multiple' => false,
'expanded' => true,
));
$this->assertWidgetMatchesXpath($form->createView(), array(),
'/div
[
./input[@type="radio"][@name="name"][@id="name_0"][@value="&a"][@checked]
/following-sibling::input[@type="radio"][@name="name"][@id="name_1"][@value="&b"][not(@checked)]
/following-sibling::input[@type="hidden"][@id="name__token"]
]
[count(./input)=3]
[count(./label)=1]
'
);
}
public function testSingleChoiceExpandedWithLabelsSetByCallable()
{
$form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', '&a', array(
'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b', 'Choice&C' => '&c'),
'choice_label' => function ($choice, $label, $value) {
if ('&b' === $choice) {
return false;
}
return 'label.'.$value;
},
'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]label.&a[/trans]"]
/following-sibling::input[@type="radio"][@name="name"][@id="name_1"][@value="&b"][not(@checked)]
/following-sibling::input[@type="radio"][@name="name"][@id="name_2"][@value="&c"][not(@checked)]
/following-sibling::label[@for="name_2"][.="[trans]label.&c[/trans]"]
/following-sibling::input[@type="hidden"][@id="name__token"]
]
[count(./input)=4]
[count(./label)=3]
'
);
}
public function testSingleChoiceExpandedWithLabelsSetFalseByCallable()
{
$form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', '&a', array(
'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'),
'choice_label' => function () {
return false;
},
'multiple' => false,
'expanded' => true,
));
$this->assertWidgetMatchesXpath($form->createView(), array(),
'/div
[
./input[@type="radio"][@name="name"][@id="name_0"][@value="&a"][@checked]
/following-sibling::input[@type="radio"][@name="name"][@id="name_1"][@value="&b"][not(@checked)]
/following-sibling::input[@type="hidden"][@id="name__token"]
]
[count(./input)=3]
[count(./label)=1]
'
);
}
public function testMultipleChoiceExpandedWithLabelsAsFalse()
{
$form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', array('&a'), array(
'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'),
'choice_label' => false,
'multiple' => true,
'expanded' => true,
));
$this->assertWidgetMatchesXpath($form->createView(), array(),
'/div
[
./input[@type="checkbox"][@name="name[]"][@id="name_0"][@value="&a"][@checked]
/following-sibling::input[@type="checkbox"][@name="name[]"][@id="name_1"][@value="&b"][not(@checked)]
/following-sibling::input[@type="hidden"][@id="name__token"]
]
[count(./input)=3]
[count(./label)=1]
'
);
}
public function testMultipleChoiceExpandedWithLabelsSetByCallable()
{
$form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', array('&a'), array(
'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b', 'Choice&C' => '&c'),
'choice_label' => function ($choice, $label, $value) {
if ('&b' === $choice) {
return false;
}
return 'label.'.$value;
},
'multiple' => true,
'expanded' => true,
));
$this->assertWidgetMatchesXpath($form->createView(), array(),
'/div
[
./input[@type="checkbox"][@name="name[]"][@id="name_0"][@value="&a"][@checked]
/following-sibling::label[@for="name_0"][.="[trans]label.&a[/trans]"]
/following-sibling::input[@type="checkbox"][@name="name[]"][@id="name_1"][@value="&b"][not(@checked)]
/following-sibling::input[@type="checkbox"][@name="name[]"][@id="name_2"][@value="&c"][not(@checked)]
/following-sibling::label[@for="name_2"][.="[trans]label.&c[/trans]"]
/following-sibling::input[@type="hidden"][@id="name__token"]
]
[count(./input)=4]
[count(./label)=3]
'
);
}
public function testMultipleChoiceExpandedWithLabelsSetFalseByCallable()
{
$form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', array('&a'), array(
'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'),
'choice_label' => function () {
return false;
},
'multiple' => true,
'expanded' => true,
));
$this->assertWidgetMatchesXpath($form->createView(), array(),
'/div
[
./input[@type="checkbox"][@name="name[]"][@id="name_0"][@value="&a"][@checked]
/following-sibling::input[@type="checkbox"][@name="name[]"][@id="name_1"][@value="&b"][not(@checked)]
/following-sibling::input[@type="hidden"][@id="name__token"]
]
[count(./input)=3]
[count(./label)=1]
'
);
}
public function testFormEndWithRest()
{
$view = $this->factory->createNamedBuilder('name', 'Symfony\Component\Form\Extension\Core\Type\FormType')
->add('field1', 'Symfony\Component\Form\Extension\Core\Type\TextType')
->add('field2', 'Symfony\Component\Form\Extension\Core\Type\TextType')
->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('<form>'.$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', 'Symfony\Component\Form\Extension\Core\Type\FormType')
->add('field1', 'Symfony\Component\Form\Extension\Core\Type\TextType')
->add('field2', 'Symfony\Component\Form\Extension\Core\Type\TextType')
->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('</form>', $html);
}
public function testWidgetContainerAttributes()
{
$form = $this->factory->createNamed('form', 'Symfony\Component\Form\Extension\Core\Type\FormType', null, array(
'attr' => array('class' => 'foobar', 'data-foo' => 'bar'),
));
$form->add('text', 'Symfony\Component\Form\Extension\Core\Type\TextType');
$html = $this->renderWidget($form->createView());
// compare plain HTML to check the whitespace
$this->assertContains('<div id="form" class="foobar" data-foo="bar">', $html);
}
public function testWidgetContainerAttributeNameRepeatedIfTrue()
{
$form = $this->factory->createNamed('form', 'Symfony\Component\Form\Extension\Core\Type\FormType', null, array(
'attr' => array('foo' => true),
));
$html = $this->renderWidget($form->createView());
// foo="foo"
$this->assertContains('<div id="form" foo="foo">', $html);
}
}

View File

@@ -0,0 +1,44 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Form\AbstractExtension;
use Symfony\Component\Form\Tests\Fixtures\FooType;
class AbstractExtensionTest extends TestCase
{
public function testHasType()
{
$loader = new ConcreteExtension();
$this->assertTrue($loader->hasType('Symfony\Component\Form\Tests\Fixtures\FooType'));
$this->assertFalse($loader->hasType('foo'));
}
public function testGetType()
{
$loader = new ConcreteExtension();
$this->assertInstanceOf('Symfony\Component\Form\Tests\Fixtures\FooType', $loader->getType('Symfony\Component\Form\Tests\Fixtures\FooType'));
}
}
class ConcreteExtension extends AbstractExtension
{
protected function loadTypes()
{
return array(new FooType());
}
protected function loadTypeGuesser()
{
}
}

View File

@@ -0,0 +1,111 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Form\FormBuilder;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
abstract class AbstractFormTest extends TestCase
{
/**
* @var EventDispatcherInterface
*/
protected $dispatcher;
/**
* @var \Symfony\Component\Form\FormFactoryInterface
*/
protected $factory;
/**
* @var \Symfony\Component\Form\FormInterface
*/
protected $form;
protected function setUp()
{
$this->dispatcher = new EventDispatcher();
$this->factory = $this->getMockBuilder('Symfony\Component\Form\FormFactoryInterface')->getMock();
$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
* @param array $options
*
* @return FormBuilder
*/
protected function getBuilder($name = 'name', EventDispatcherInterface $dispatcher = null, $dataClass = null, array $options = array())
{
return new FormBuilder($name, $dataClass, $dispatcher ?: $this->dispatcher, $this->factory, $options);
}
/**
* @param string $name
*
* @return \PHPUnit_Framework_MockObject_MockObject
*/
protected function getMockForm($name = 'name')
{
$form = $this->getMockBuilder('Symfony\Component\Form\Test\FormInterface')->getMock();
$config = $this->getMockBuilder('Symfony\Component\Form\FormConfigInterface')->getMock();
$form->expects($this->any())
->method('getName')
->will($this->returnValue($name));
$form->expects($this->any())
->method('getConfig')
->will($this->returnValue($config));
return $form;
}
/**
* @return \PHPUnit_Framework_MockObject_MockObject
*/
protected function getDataMapper()
{
return $this->getMockBuilder('Symfony\Component\Form\DataMapperInterface')->getMock();
}
/**
* @return \PHPUnit_Framework_MockObject_MockObject
*/
protected function getDataTransformer()
{
return $this->getMockBuilder('Symfony\Component\Form\DataTransformerInterface')->getMock();
}
/**
* @return \PHPUnit_Framework_MockObject_MockObject
*/
protected function getFormValidator()
{
return $this->getMockBuilder('Symfony\Component\Form\FormValidatorInterface')->getMock();
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,382 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Form\FormError;
use Symfony\Component\Form\FormFactory;
use Symfony\Component\Form\Forms;
use Symfony\Component\Form\RequestHandlerInterface;
/**
* @author Bernhard Schussek <bschussek@gmail.com>
*/
abstract class AbstractRequestHandlerTest extends TestCase
{
/**
* @var RequestHandlerInterface
*/
protected $requestHandler;
/**
* @var FormFactory
*/
protected $factory;
protected $request;
protected $serverParams;
protected function setUp()
{
$this->serverParams = $this->getMockBuilder('Symfony\Component\Form\Util\ServerParams')->setMethods(array('getNormalizedIniPostMaxSize', 'getContentLength'))->getMock();
$this->requestHandler = $this->getRequestHandler();
$this->factory = Forms::createFormFactoryBuilder()->getFormFactory();
$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 testDoNoSubmitSimpleFormIfNameNotInRequestAndNotGetRequest($method)
{
$form = $this->getMockForm('param1', $method, false);
$this->setRequestData($method, array(
'paramx' => array(),
));
$form->expects($this->never())
->method('submit');
$this->requestHandler->handleRequest($form, $this->request);
}
/**
* @dataProvider methodExceptGetProvider
*/
public function testDoNotSubmitCompoundFormIfNameNotInRequestAndNotGetRequest($method)
{
$form = $this->getMockForm('param1', $method, true);
$this->setRequestData($method, array(
'paramx' => array(),
));
$form->expects($this->never())
->method('submit');
$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);
}
/**
* @dataProvider methodExceptGetProvider
*/
public function testSubmitMultipleFiles($method)
{
$form = $this->getMockForm('param1', $method);
$file = $this->getMockFile();
$this->setRequestData($method, array(
'param1' => null,
), array(
'param2' => $this->getMockFile('2'),
'param1' => $file,
'param3' => $this->getMockFile('3'),
));
$form->expects($this->once())
->method('submit')
->with($file, 'PATCH' !== $method);
$this->requestHandler->handleRequest($form, $this->request);
}
/**
* @dataProvider methodExceptGetProvider
*/
public function testSubmitFileWithNamelessForm($method)
{
$form = $this->getMockForm(null, $method);
$file = $this->getMockFile();
$this->setRequestData($method, array(
'' => null,
), array(
'' => $file,
));
$form->expects($this->once())
->method('submit')
->with($file, 'PATCH' !== $method);
$this->requestHandler->handleRequest($form, $this->request);
}
/**
* @dataProvider getPostMaxSizeFixtures
*/
public function testAddFormErrorIfPostMaxSizeExceeded($contentLength, $iniMax, $shouldFail, array $errorParams = array())
{
$this->serverParams->expects($this->once())
->method('getContentLength')
->will($this->returnValue($contentLength));
$this->serverParams->expects($this->any())
->method('getNormalizedIniPostMaxSize')
->will($this->returnValue($iniMax));
$options = array('post_max_size_message' => 'Max {{ max }}!');
$form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TextType', null, $options);
$this->setRequestData('POST', array(), array());
$this->requestHandler->handleRequest($form, $this->request);
if ($shouldFail) {
$error = new FormError($options['post_max_size_message'], null, $errorParams);
$error->setOrigin($form);
$this->assertEquals(array($error), iterator_to_array($form->getErrors()));
$this->assertTrue($form->isSubmitted());
} else {
$this->assertCount(0, $form->getErrors());
$this->assertFalse($form->isSubmitted());
}
}
public function getPostMaxSizeFixtures()
{
return array(
array(pow(1024, 3) + 1, '1G', true, array('{{ max }}' => '1G')),
array(pow(1024, 3), '1G', false),
array(pow(1024, 2) + 1, '1M', true, array('{{ max }}' => '1M')),
array(pow(1024, 2), '1M', false),
array(1024 + 1, '1K', true, array('{{ max }}' => '1K')),
array(1024, '1K', false),
array(null, '1K', false),
array(1024, '', false),
array(1024, 0, false),
);
}
abstract protected function setRequestData($method, $data, $files = array());
abstract protected function getRequestHandler();
abstract protected function getMockFile($suffix = '');
protected function getMockForm($name, $method = null, $compound = true)
{
$config = $this->getMockBuilder('Symfony\Component\Form\FormConfigInterface')->getMock();
$config->expects($this->any())
->method('getMethod')
->will($this->returnValue($method));
$config->expects($this->any())
->method('getCompound')
->will($this->returnValue($compound));
$form = $this->getMockBuilder('Symfony\Component\Form\Test\FormInterface')->getMock();
$form->expects($this->any())
->method('getName')
->will($this->returnValue($name));
$form->expects($this->any())
->method('getConfig')
->will($this->returnValue($config));
return $form;
}
}

View File

@@ -0,0 +1,536 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests;
use Symfony\Component\Form\FormError;
use Symfony\Component\Security\Csrf\CsrfToken;
abstract class AbstractTableLayoutTest extends AbstractLayoutTest
{
public function testRow()
{
$form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TextType');
$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', 'Symfony\Component\Form\Extension\Core\Type\TextType', 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', 'Symfony\Component\Form\Extension\Core\Type\RepeatedType');
$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', 'Symfony\Component\Form\Extension\Core\Type\RepeatedType');
$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', 'Symfony\Component\Form\Extension\Core\Type\ButtonType');
$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', 'Symfony\Component\Form\Extension\Core\Type\FormType')
->add('field1', 'Symfony\Component\Form\Extension\Core\Type\TextType')
->add('field2', 'Symfony\Component\Form\Extension\Core\Type\RepeatedType')
->add('field3', 'Symfony\Component\Form\Extension\Core\Type\TextType')
->add('field4', 'Symfony\Component\Form\Extension\Core\Type\TextType')
->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('names', 'Symfony\Component\Form\Extension\Core\Type\CollectionType', array('a', 'b'), array(
'entry_type' => 'Symfony\Component\Form\Extension\Core\Type\TextType',
));
$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="names__token"]]
]
[count(./tr[./td/input])=3]
'
);
}
public function testEmptyCollection()
{
$form = $this->factory->createNamed('names', 'Symfony\Component\Form\Extension\Core\Type\CollectionType', array(), array(
'entry_type' => 'Symfony\Component\Form\Extension\Core\Type\TextType',
));
$this->assertWidgetMatchesXpath($form->createView(), array(),
'/table
[./tr[@style="display: none"][./td[@colspan="2"]/input[@type="hidden"][@id="names__token"]]]
[count(./tr[./td/input])=1]
'
);
}
public function testForm()
{
$view = $this->factory->createNamedBuilder('name', 'Symfony\Component\Form\Extension\Core\Type\FormType')
->setMethod('PUT')
->setAction('http://example.com')
->add('firstName', 'Symfony\Component\Form\Extension\Core\Type\TextType')
->add('lastName', 'Symfony\Component\Form\Extension\Core\Type\TextType')
->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', 'Symfony\Component\Form\Extension\Core\Type\FormType')
->add('firstName', 'Symfony\Component\Form\Extension\Core\Type\TextType')
->add('lastName', 'Symfony\Component\Form\Extension\Core\Type\TextType')
->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', 'Symfony\Component\Form\Extension\Core\Type\FormType')
->add($this->factory
->createNamedBuilder('child', 'Symfony\Component\Form\Extension\Core\Type\FormType', null, array('error_bubbling' => false))
->add('grandChild', 'Symfony\Component\Form\Extension\Core\Type\FormType')
)
->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->csrfTokenManager->expects($this->any())
->method('getToken')
->will($this->returnValue(new CsrfToken('token_id', 'foo&bar')));
$form = $this->factory->createNamedBuilder('name', 'Symfony\Component\Form\Extension\Core\Type\FormType')
->add($this->factory
// No CSRF protection on nested forms
->createNamedBuilder('child', 'Symfony\Component\Form\Extension\Core\Type\FormType')
->add($this->factory->createNamedBuilder('grandchild', 'Symfony\Component\Form\Extension\Core\Type\TextType'))
)
->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', 'Symfony\Component\Form\Extension\Core\Type\RepeatedType', 'foobar', array(
'type' => 'Symfony\Component\Form\Extension\Core\Type\TextType',
));
$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', 'Symfony\Component\Form\Extension\Core\Type\RepeatedType', 'foobar', array(
'type' => 'Symfony\Component\Form\Extension\Core\Type\PasswordType',
'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('names', 'Symfony\Component\Form\Extension\Core\Type\CollectionType', $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', 'Symfony\Component\Form\Extension\Core\Type\FormType')
->add('field1', 'Symfony\Component\Form\Extension\Core\Type\TextType')
->add('field2', 'Symfony\Component\Form\Extension\Core\Type\TextType')
->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 <table>
// tag.
$this->assertMatchesXpath('<form>'.$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', 'Symfony\Component\Form\Extension\Core\Type\FormType')
->add('field1', 'Symfony\Component\Form\Extension\Core\Type\TextType')
->add('field2', 'Symfony\Component\Form\Extension\Core\Type\TextType')
->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('</form>', $html);
}
public function testWidgetContainerAttributes()
{
$form = $this->factory->createNamed('form', 'Symfony\Component\Form\Extension\Core\Type\FormType', null, array(
'attr' => array('class' => 'foobar', 'data-foo' => 'bar'),
));
$form->add('text', 'Symfony\Component\Form\Extension\Core\Type\TextType');
$html = $this->renderWidget($form->createView());
// compare plain HTML to check the whitespace
$this->assertContains('<table id="form" class="foobar" data-foo="bar">', $html);
}
public function testWidgetContainerAttributeNameRepeatedIfTrue()
{
$form = $this->factory->createNamed('form', 'Symfony\Component\Form\Extension\Core\Type\FormType', null, array(
'attr' => array('foo' => true),
));
$html = $this->renderWidget($form->createView());
// foo="foo"
$this->assertContains('<table id="form" foo="foo">', $html);
}
}

View File

@@ -0,0 +1,62 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Form\ButtonBuilder;
/**
* @author Alexander Cheprasov <cheprasov.84@ya.ru>
*/
class ButtonBuilderTest extends TestCase
{
public function getValidNames()
{
return array(
array('reset'),
array('submit'),
array('foo'),
array('0'),
array(0),
array('button[]'),
);
}
/**
* @dataProvider getValidNames
*/
public function testValidNames($name)
{
$this->assertInstanceOf('\Symfony\Component\Form\ButtonBuilder', new ButtonBuilder($name));
}
public function getInvalidNames()
{
return array(
array(''),
array(false),
array(null),
);
}
/**
* @dataProvider getInvalidNames
*/
public function testInvalidNames($name)
{
$this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}(
'\Symfony\Component\Form\Exception\InvalidArgumentException',
'Buttons cannot have empty names.'
);
new ButtonBuilder($name);
}
}

View File

@@ -0,0 +1,71 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Form\ButtonBuilder;
use Symfony\Component\Form\FormBuilder;
/**
* @author Bernhard Schussek <bschussek@gmail.com>
*/
class ButtonTest extends TestCase
{
private $dispatcher;
private $factory;
protected function setUp()
{
$this->dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcherInterface')->getMock();
$this->factory = $this->getMockBuilder('Symfony\Component\Form\FormFactoryInterface')->getMock();
}
/**
* @dataProvider getDisabledStates
*/
public function testDisabledIfParentIsDisabled($parentDisabled, $buttonDisabled, $result)
{
$form = $this->getFormBuilder('form')
->setDisabled($parentDisabled)
->getForm();
$button = $this->getButtonBuilder('button')
->setDisabled($buttonDisabled)
->getForm();
$button->setParent($form);
$this->assertSame($result, $button->isDisabled());
}
public function getDisabledStates()
{
return array(
// parent, button, result
array(true, true, true),
array(true, false, true),
array(false, true, true),
array(false, false, false),
);
}
private function getButtonBuilder($name)
{
return new ButtonBuilder($name);
}
private function getFormBuilder($name)
{
return new FormBuilder($name, null, $this->dispatcher, $this->factory);
}
}

View File

@@ -0,0 +1,29 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Form\CallbackTransformer;
class CallbackTransformerTest extends TestCase
{
public function testTransform()
{
$transformer = new CallbackTransformer(
function ($value) { return $value.' has been transformed'; },
function ($value) { return $value.' has reversely been transformed'; }
);
$this->assertEquals('foo has been transformed', $transformer->transform('foo'));
$this->assertEquals('bar has reversely been transformed', $transformer->reverseTransform('bar'));
}
}

View File

@@ -0,0 +1,229 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\ChoiceList;
use PHPUnit\Framework\TestCase;
/**
* @author Bernhard Schussek <bschussek@gmail.com>
*/
abstract class AbstractChoiceListTest extends TestCase
{
/**
* @var \Symfony\Component\Form\ChoiceList\ChoiceListInterface
*/
protected $list;
/**
* @var array
*/
protected $choices;
/**
* @var array
*/
protected $values;
/**
* @var array
*/
protected $structuredValues;
/**
* @var array
*/
protected $keys;
/**
* @var mixed
*/
protected $choice1;
/**
* @var mixed
*/
protected $choice2;
/**
* @var mixed
*/
protected $choice3;
/**
* @var mixed
*/
protected $choice4;
/**
* @var string
*/
protected $value1;
/**
* @var string
*/
protected $value2;
/**
* @var string
*/
protected $value3;
/**
* @var string
*/
protected $value4;
/**
* @var string
*/
protected $key1;
/**
* @var string
*/
protected $key2;
/**
* @var string
*/
protected $key3;
/**
* @var string
*/
protected $key4;
protected function setUp()
{
parent::setUp();
$this->list = $this->createChoiceList();
$choices = $this->getChoices();
$this->values = $this->getValues();
$this->structuredValues = array_combine(array_keys($choices), $this->values);
$this->choices = array_combine($this->values, $choices);
$this->keys = array_combine($this->values, array_keys($choices));
// allow access to the individual entries without relying on their indices
reset($this->choices);
reset($this->values);
reset($this->keys);
for ($i = 1; $i <= 4; ++$i) {
$this->{'choice'.$i} = current($this->choices);
$this->{'value'.$i} = current($this->values);
$this->{'key'.$i} = current($this->keys);
next($this->choices);
next($this->values);
next($this->keys);
}
}
public function testGetChoices()
{
$this->assertSame($this->choices, $this->list->getChoices());
}
public function testGetValues()
{
$this->assertSame($this->values, $this->list->getValues());
}
public function testGetStructuredValues()
{
$this->assertSame($this->values, $this->list->getStructuredValues());
}
public function testGetOriginalKeys()
{
$this->assertSame($this->keys, $this->list->getOriginalKeys());
}
public function testGetChoicesForValues()
{
$values = array($this->value1, $this->value2);
$this->assertSame(array($this->choice1, $this->choice2), $this->list->getChoicesForValues($values));
}
public function testGetChoicesForValuesPreservesKeys()
{
$values = array(5 => $this->value1, 8 => $this->value2);
$this->assertSame(array(5 => $this->choice1, 8 => $this->choice2), $this->list->getChoicesForValues($values));
}
public function testGetChoicesForValuesPreservesOrder()
{
$values = array($this->value2, $this->value1);
$this->assertSame(array($this->choice2, $this->choice1), $this->list->getChoicesForValues($values));
}
public function testGetChoicesForValuesIgnoresNonExistingValues()
{
$values = array($this->value1, $this->value2, 'foobar');
$this->assertSame(array($this->choice1, $this->choice2), $this->list->getChoicesForValues($values));
}
// https://github.com/symfony/symfony/issues/3446
public function testGetChoicesForValuesEmpty()
{
$this->assertSame(array(), $this->list->getChoicesForValues(array()));
}
public function testGetValuesForChoices()
{
$choices = array($this->choice1, $this->choice2);
$this->assertSame(array($this->value1, $this->value2), $this->list->getValuesForChoices($choices));
}
public function testGetValuesForChoicesPreservesKeys()
{
$choices = array(5 => $this->choice1, 8 => $this->choice2);
$this->assertSame(array(5 => $this->value1, 8 => $this->value2), $this->list->getValuesForChoices($choices));
}
public function testGetValuesForChoicesPreservesOrder()
{
$choices = array($this->choice2, $this->choice1);
$this->assertSame(array($this->value2, $this->value1), $this->list->getValuesForChoices($choices));
}
public function testGetValuesForChoicesIgnoresNonExistingChoices()
{
$choices = array($this->choice1, $this->choice2, 'foobar');
$this->assertSame(array($this->value1, $this->value2), $this->list->getValuesForChoices($choices));
}
public function testGetValuesForChoicesEmpty()
{
$this->assertSame(array(), $this->list->getValuesForChoices(array()));
}
public function testGetChoicesForValuesWithNull()
{
$values = $this->list->getValuesForChoices(array(null));
$this->assertNotEmpty($this->list->getChoicesForValues($values));
}
/**
* @return \Symfony\Component\Form\ChoiceList\ChoiceListInterface
*/
abstract protected function createChoiceList();
abstract protected function getChoices();
abstract protected function getValues();
}

View File

@@ -0,0 +1,166 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\ChoiceList;
use Symfony\Component\Form\ChoiceList\ArrayChoiceList;
/**
* @author Bernhard Schussek <bschussek@gmail.com>
*/
class ArrayChoiceListTest extends AbstractChoiceListTest
{
private $object;
protected function setUp()
{
$this->object = new \stdClass();
parent::setUp();
}
protected function createChoiceList()
{
return new ArrayChoiceList($this->getChoices());
}
protected function getChoices()
{
return array(0, 1, 1.5, '1', 'a', false, true, $this->object, null);
}
protected function getValues()
{
return array('0', '1', '2', '3', '4', '5', '6', '7', '8');
}
public function testCreateChoiceListWithValueCallback()
{
$callback = function ($choice) {
return ':'.$choice;
};
$choiceList = new ArrayChoiceList(array(2 => 'foo', 7 => 'bar', 10 => 'baz'), $callback);
$this->assertSame(array(':foo', ':bar', ':baz'), $choiceList->getValues());
$this->assertSame(array(':foo' => 'foo', ':bar' => 'bar', ':baz' => 'baz'), $choiceList->getChoices());
$this->assertSame(array(':foo' => 2, ':bar' => 7, ':baz' => 10), $choiceList->getOriginalKeys());
$this->assertSame(array(1 => 'foo', 2 => 'baz'), $choiceList->getChoicesForValues(array(1 => ':foo', 2 => ':baz')));
$this->assertSame(array(1 => ':foo', 2 => ':baz'), $choiceList->getValuesForChoices(array(1 => 'foo', 2 => 'baz')));
}
public function testCreateChoiceListWithoutValueCallbackAndDuplicateFreeToStringChoices()
{
$choiceList = new ArrayChoiceList(array(2 => 'foo', 7 => 'bar', 10 => 123));
$this->assertSame(array('foo', 'bar', '123'), $choiceList->getValues());
$this->assertSame(array('foo' => 'foo', 'bar' => 'bar', '123' => 123), $choiceList->getChoices());
$this->assertSame(array('foo' => 2, 'bar' => 7, '123' => 10), $choiceList->getOriginalKeys());
$this->assertSame(array(1 => 'foo', 2 => 123), $choiceList->getChoicesForValues(array(1 => 'foo', 2 => '123')));
$this->assertSame(array(1 => 'foo', 2 => '123'), $choiceList->getValuesForChoices(array(1 => 'foo', 2 => 123)));
}
public function testCreateChoiceListWithoutValueCallbackAndToStringDuplicates()
{
$choiceList = new ArrayChoiceList(array(2 => 'foo', 7 => '123', 10 => 123));
$this->assertSame(array('0', '1', '2'), $choiceList->getValues());
$this->assertSame(array('0' => 'foo', '1' => '123', '2' => 123), $choiceList->getChoices());
$this->assertSame(array('0' => 2, '1' => 7, '2' => 10), $choiceList->getOriginalKeys());
$this->assertSame(array(1 => 'foo', 2 => 123), $choiceList->getChoicesForValues(array(1 => '0', 2 => '2')));
$this->assertSame(array(1 => '0', 2 => '2'), $choiceList->getValuesForChoices(array(1 => 'foo', 2 => 123)));
}
public function testCreateChoiceListWithoutValueCallbackAndMixedChoices()
{
$object = new \stdClass();
$choiceList = new ArrayChoiceList(array(2 => 'foo', 5 => array(7 => '123'), 10 => $object));
$this->assertSame(array('0', '1', '2'), $choiceList->getValues());
$this->assertSame(array('0' => 'foo', '1' => '123', '2' => $object), $choiceList->getChoices());
$this->assertSame(array('0' => 2, '1' => 7, '2' => 10), $choiceList->getOriginalKeys());
$this->assertSame(array(1 => 'foo', 2 => $object), $choiceList->getChoicesForValues(array(1 => '0', 2 => '2')));
$this->assertSame(array(1 => '0', 2 => '2'), $choiceList->getValuesForChoices(array(1 => 'foo', 2 => $object)));
}
public function testCreateChoiceListWithGroupedChoices()
{
$choiceList = new ArrayChoiceList(array(
'Group 1' => array('A' => 'a', 'B' => 'b'),
'Group 2' => array('C' => 'c', 'D' => 'd'),
));
$this->assertSame(array('a', 'b', 'c', 'd'), $choiceList->getValues());
$this->assertSame(array(
'Group 1' => array('A' => 'a', 'B' => 'b'),
'Group 2' => array('C' => 'c', 'D' => 'd'),
), $choiceList->getStructuredValues());
$this->assertSame(array('a' => 'a', 'b' => 'b', 'c' => 'c', 'd' => 'd'), $choiceList->getChoices());
$this->assertSame(array('a' => 'A', 'b' => 'B', 'c' => 'C', 'd' => 'D'), $choiceList->getOriginalKeys());
$this->assertSame(array(1 => 'a', 2 => 'b'), $choiceList->getChoicesForValues(array(1 => 'a', 2 => 'b')));
$this->assertSame(array(1 => 'a', 2 => 'b'), $choiceList->getValuesForChoices(array(1 => 'a', 2 => 'b')));
}
public function testCompareChoicesByIdentityByDefault()
{
$callback = function ($choice) {
return $choice->value;
};
$obj1 = (object) array('value' => 'value1');
$obj2 = (object) array('value' => 'value2');
$choiceList = new ArrayChoiceList(array($obj1, $obj2), $callback);
$this->assertSame(array(2 => 'value2'), $choiceList->getValuesForChoices(array(2 => $obj2)));
$this->assertSame(array(2 => 'value2'), $choiceList->getValuesForChoices(array(2 => (object) array('value' => 'value2'))));
}
public function testGetChoicesForValuesWithContainingNull()
{
$choiceList = new ArrayChoiceList(array('Null' => null));
$this->assertSame(array(0 => null), $choiceList->getChoicesForValues(array('0')));
}
public function testGetChoicesForValuesWithContainingFalseAndNull()
{
$choiceList = new ArrayChoiceList(array('False' => false, 'Null' => null));
$this->assertSame(array(0 => null), $choiceList->getChoicesForValues(array('1')));
$this->assertSame(array(0 => false), $choiceList->getChoicesForValues(array('0')));
}
public function testGetChoicesForValuesWithContainingEmptyStringAndNull()
{
$choiceList = new ArrayChoiceList(array('Empty String' => '', 'Null' => null));
$this->assertSame(array(0 => ''), $choiceList->getChoicesForValues(array('0')));
$this->assertSame(array(0 => null), $choiceList->getChoicesForValues(array('1')));
}
public function testGetChoicesForValuesWithContainingEmptyStringAndBooleans()
{
$choiceList = new ArrayChoiceList(array('Empty String' => '', 'True' => true, 'False' => false));
$this->assertSame(array(0 => ''), $choiceList->getChoicesForValues(array('')));
$this->assertSame(array(0 => true), $choiceList->getChoicesForValues(array('1')));
$this->assertSame(array(0 => false), $choiceList->getChoicesForValues(array('0')));
}
public function testGetChoicesForValuesWithContainingEmptyStringAndFloats()
{
$choiceList = new ArrayChoiceList(array('Empty String' => '', '1/3' => 0.3, '1/2' => 0.5));
$this->assertSame(array(0 => ''), $choiceList->getChoicesForValues(array('')));
$this->assertSame(array(0 => 0.3), $choiceList->getChoicesForValues(array('0.3')));
$this->assertSame(array(0 => 0.5), $choiceList->getChoicesForValues(array('0.5')));
}
}

View File

@@ -0,0 +1,532 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\ChoiceList\Factory;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Form\ChoiceList\Factory\CachingFactoryDecorator;
/**
* @author Bernhard Schussek <bschussek@gmail.com>
*/
class CachingFactoryDecoratorTest extends TestCase
{
/**
* @var \PHPUnit_Framework_MockObject_MockObject
*/
private $decoratedFactory;
/**
* @var CachingFactoryDecorator
*/
private $factory;
protected function setUp()
{
$this->decoratedFactory = $this->getMockBuilder('Symfony\Component\Form\ChoiceList\Factory\ChoiceListFactoryInterface')->getMock();
$this->factory = new CachingFactoryDecorator($this->decoratedFactory);
}
public function testCreateFromChoicesEmpty()
{
$list = new \stdClass();
$this->decoratedFactory->expects($this->once())
->method('createListFromChoices')
->with(array())
->will($this->returnValue($list));
$this->assertSame($list, $this->factory->createListFromChoices(array()));
$this->assertSame($list, $this->factory->createListFromChoices(array()));
}
public function testCreateFromChoicesComparesTraversableChoicesAsArray()
{
// The top-most traversable is converted to an array
$choices1 = new \ArrayIterator(array('A' => 'a'));
$choices2 = array('A' => 'a');
$list = new \stdClass();
$this->decoratedFactory->expects($this->once())
->method('createListFromChoices')
->with($choices2)
->will($this->returnValue($list));
$this->assertSame($list, $this->factory->createListFromChoices($choices1));
$this->assertSame($list, $this->factory->createListFromChoices($choices2));
}
public function testCreateFromChoicesFlattensChoices()
{
$choices1 = array('key' => array('A' => 'a'));
$choices2 = array('A' => 'a');
$list = new \stdClass();
$this->decoratedFactory->expects($this->once())
->method('createListFromChoices')
->with($choices1)
->will($this->returnValue($list));
$this->assertSame($list, $this->factory->createListFromChoices($choices1));
$this->assertSame($list, $this->factory->createListFromChoices($choices2));
}
/**
* @dataProvider provideSameChoices
*/
public function testCreateFromChoicesSameChoices($choice1, $choice2)
{
$choices1 = array($choice1);
$choices2 = array($choice2);
$list = new \stdClass();
$this->decoratedFactory->expects($this->once())
->method('createListFromChoices')
->with($choices1)
->will($this->returnValue($list));
$this->assertSame($list, $this->factory->createListFromChoices($choices1));
$this->assertSame($list, $this->factory->createListFromChoices($choices2));
}
/**
* @dataProvider provideDistinguishedChoices
*/
public function testCreateFromChoicesDifferentChoices($choice1, $choice2)
{
$choices1 = array($choice1);
$choices2 = array($choice2);
$list1 = new \stdClass();
$list2 = new \stdClass();
$this->decoratedFactory->expects($this->at(0))
->method('createListFromChoices')
->with($choices1)
->will($this->returnValue($list1));
$this->decoratedFactory->expects($this->at(1))
->method('createListFromChoices')
->with($choices2)
->will($this->returnValue($list2));
$this->assertSame($list1, $this->factory->createListFromChoices($choices1));
$this->assertSame($list2, $this->factory->createListFromChoices($choices2));
}
public function testCreateFromChoicesSameValueClosure()
{
$choices = array(1);
$list = new \stdClass();
$closure = function () {};
$this->decoratedFactory->expects($this->once())
->method('createListFromChoices')
->with($choices, $closure)
->will($this->returnValue($list));
$this->assertSame($list, $this->factory->createListFromChoices($choices, $closure));
$this->assertSame($list, $this->factory->createListFromChoices($choices, $closure));
}
public function testCreateFromChoicesDifferentValueClosure()
{
$choices = array(1);
$list1 = new \stdClass();
$list2 = new \stdClass();
$closure1 = function () {};
$closure2 = function () {};
$this->decoratedFactory->expects($this->at(0))
->method('createListFromChoices')
->with($choices, $closure1)
->will($this->returnValue($list1));
$this->decoratedFactory->expects($this->at(1))
->method('createListFromChoices')
->with($choices, $closure2)
->will($this->returnValue($list2));
$this->assertSame($list1, $this->factory->createListFromChoices($choices, $closure1));
$this->assertSame($list2, $this->factory->createListFromChoices($choices, $closure2));
}
public function testCreateFromLoaderSameLoader()
{
$loader = $this->getMockBuilder('Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface')->getMock();
$list = new \stdClass();
$this->decoratedFactory->expects($this->once())
->method('createListFromLoader')
->with($loader)
->will($this->returnValue($list));
$this->assertSame($list, $this->factory->createListFromLoader($loader));
$this->assertSame($list, $this->factory->createListFromLoader($loader));
}
public function testCreateFromLoaderDifferentLoader()
{
$loader1 = $this->getMockBuilder('Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface')->getMock();
$loader2 = $this->getMockBuilder('Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface')->getMock();
$list1 = new \stdClass();
$list2 = new \stdClass();
$this->decoratedFactory->expects($this->at(0))
->method('createListFromLoader')
->with($loader1)
->will($this->returnValue($list1));
$this->decoratedFactory->expects($this->at(1))
->method('createListFromLoader')
->with($loader2)
->will($this->returnValue($list2));
$this->assertSame($list1, $this->factory->createListFromLoader($loader1));
$this->assertSame($list2, $this->factory->createListFromLoader($loader2));
}
public function testCreateFromLoaderSameValueClosure()
{
$loader = $this->getMockBuilder('Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface')->getMock();
$list = new \stdClass();
$closure = function () {};
$this->decoratedFactory->expects($this->once())
->method('createListFromLoader')
->with($loader, $closure)
->will($this->returnValue($list));
$this->assertSame($list, $this->factory->createListFromLoader($loader, $closure));
$this->assertSame($list, $this->factory->createListFromLoader($loader, $closure));
}
public function testCreateFromLoaderDifferentValueClosure()
{
$loader = $this->getMockBuilder('Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface')->getMock();
$list1 = new \stdClass();
$list2 = new \stdClass();
$closure1 = function () {};
$closure2 = function () {};
$this->decoratedFactory->expects($this->at(0))
->method('createListFromLoader')
->with($loader, $closure1)
->will($this->returnValue($list1));
$this->decoratedFactory->expects($this->at(1))
->method('createListFromLoader')
->with($loader, $closure2)
->will($this->returnValue($list2));
$this->assertSame($list1, $this->factory->createListFromLoader($loader, $closure1));
$this->assertSame($list2, $this->factory->createListFromLoader($loader, $closure2));
}
public function testCreateViewSamePreferredChoices()
{
$preferred = array('a');
$list = $this->getMockBuilder('Symfony\Component\Form\ChoiceList\ChoiceListInterface')->getMock();
$view = new \stdClass();
$this->decoratedFactory->expects($this->once())
->method('createView')
->with($list, $preferred)
->will($this->returnValue($view));
$this->assertSame($view, $this->factory->createView($list, $preferred));
$this->assertSame($view, $this->factory->createView($list, $preferred));
}
public function testCreateViewDifferentPreferredChoices()
{
$preferred1 = array('a');
$preferred2 = array('b');
$list = $this->getMockBuilder('Symfony\Component\Form\ChoiceList\ChoiceListInterface')->getMock();
$view1 = new \stdClass();
$view2 = new \stdClass();
$this->decoratedFactory->expects($this->at(0))
->method('createView')
->with($list, $preferred1)
->will($this->returnValue($view1));
$this->decoratedFactory->expects($this->at(1))
->method('createView')
->with($list, $preferred2)
->will($this->returnValue($view2));
$this->assertSame($view1, $this->factory->createView($list, $preferred1));
$this->assertSame($view2, $this->factory->createView($list, $preferred2));
}
public function testCreateViewSamePreferredChoicesClosure()
{
$preferred = function () {};
$list = $this->getMockBuilder('Symfony\Component\Form\ChoiceList\ChoiceListInterface')->getMock();
$view = new \stdClass();
$this->decoratedFactory->expects($this->once())
->method('createView')
->with($list, $preferred)
->will($this->returnValue($view));
$this->assertSame($view, $this->factory->createView($list, $preferred));
$this->assertSame($view, $this->factory->createView($list, $preferred));
}
public function testCreateViewDifferentPreferredChoicesClosure()
{
$preferred1 = function () {};
$preferred2 = function () {};
$list = $this->getMockBuilder('Symfony\Component\Form\ChoiceList\ChoiceListInterface')->getMock();
$view1 = new \stdClass();
$view2 = new \stdClass();
$this->decoratedFactory->expects($this->at(0))
->method('createView')
->with($list, $preferred1)
->will($this->returnValue($view1));
$this->decoratedFactory->expects($this->at(1))
->method('createView')
->with($list, $preferred2)
->will($this->returnValue($view2));
$this->assertSame($view1, $this->factory->createView($list, $preferred1));
$this->assertSame($view2, $this->factory->createView($list, $preferred2));
}
public function testCreateViewSameLabelClosure()
{
$labels = function () {};
$list = $this->getMockBuilder('Symfony\Component\Form\ChoiceList\ChoiceListInterface')->getMock();
$view = new \stdClass();
$this->decoratedFactory->expects($this->once())
->method('createView')
->with($list, null, $labels)
->will($this->returnValue($view));
$this->assertSame($view, $this->factory->createView($list, null, $labels));
$this->assertSame($view, $this->factory->createView($list, null, $labels));
}
public function testCreateViewDifferentLabelClosure()
{
$labels1 = function () {};
$labels2 = function () {};
$list = $this->getMockBuilder('Symfony\Component\Form\ChoiceList\ChoiceListInterface')->getMock();
$view1 = new \stdClass();
$view2 = new \stdClass();
$this->decoratedFactory->expects($this->at(0))
->method('createView')
->with($list, null, $labels1)
->will($this->returnValue($view1));
$this->decoratedFactory->expects($this->at(1))
->method('createView')
->with($list, null, $labels2)
->will($this->returnValue($view2));
$this->assertSame($view1, $this->factory->createView($list, null, $labels1));
$this->assertSame($view2, $this->factory->createView($list, null, $labels2));
}
public function testCreateViewSameIndexClosure()
{
$index = function () {};
$list = $this->getMockBuilder('Symfony\Component\Form\ChoiceList\ChoiceListInterface')->getMock();
$view = new \stdClass();
$this->decoratedFactory->expects($this->once())
->method('createView')
->with($list, null, null, $index)
->will($this->returnValue($view));
$this->assertSame($view, $this->factory->createView($list, null, null, $index));
$this->assertSame($view, $this->factory->createView($list, null, null, $index));
}
public function testCreateViewDifferentIndexClosure()
{
$index1 = function () {};
$index2 = function () {};
$list = $this->getMockBuilder('Symfony\Component\Form\ChoiceList\ChoiceListInterface')->getMock();
$view1 = new \stdClass();
$view2 = new \stdClass();
$this->decoratedFactory->expects($this->at(0))
->method('createView')
->with($list, null, null, $index1)
->will($this->returnValue($view1));
$this->decoratedFactory->expects($this->at(1))
->method('createView')
->with($list, null, null, $index2)
->will($this->returnValue($view2));
$this->assertSame($view1, $this->factory->createView($list, null, null, $index1));
$this->assertSame($view2, $this->factory->createView($list, null, null, $index2));
}
public function testCreateViewSameGroupByClosure()
{
$groupBy = function () {};
$list = $this->getMockBuilder('Symfony\Component\Form\ChoiceList\ChoiceListInterface')->getMock();
$view = new \stdClass();
$this->decoratedFactory->expects($this->once())
->method('createView')
->with($list, null, null, null, $groupBy)
->will($this->returnValue($view));
$this->assertSame($view, $this->factory->createView($list, null, null, null, $groupBy));
$this->assertSame($view, $this->factory->createView($list, null, null, null, $groupBy));
}
public function testCreateViewDifferentGroupByClosure()
{
$groupBy1 = function () {};
$groupBy2 = function () {};
$list = $this->getMockBuilder('Symfony\Component\Form\ChoiceList\ChoiceListInterface')->getMock();
$view1 = new \stdClass();
$view2 = new \stdClass();
$this->decoratedFactory->expects($this->at(0))
->method('createView')
->with($list, null, null, null, $groupBy1)
->will($this->returnValue($view1));
$this->decoratedFactory->expects($this->at(1))
->method('createView')
->with($list, null, null, null, $groupBy2)
->will($this->returnValue($view2));
$this->assertSame($view1, $this->factory->createView($list, null, null, null, $groupBy1));
$this->assertSame($view2, $this->factory->createView($list, null, null, null, $groupBy2));
}
public function testCreateViewSameAttributes()
{
$attr = array('class' => 'foobar');
$list = $this->getMockBuilder('Symfony\Component\Form\ChoiceList\ChoiceListInterface')->getMock();
$view = new \stdClass();
$this->decoratedFactory->expects($this->once())
->method('createView')
->with($list, null, null, null, null, $attr)
->will($this->returnValue($view));
$this->assertSame($view, $this->factory->createView($list, null, null, null, null, $attr));
$this->assertSame($view, $this->factory->createView($list, null, null, null, null, $attr));
}
public function testCreateViewDifferentAttributes()
{
$attr1 = array('class' => 'foobar1');
$attr2 = array('class' => 'foobar2');
$list = $this->getMockBuilder('Symfony\Component\Form\ChoiceList\ChoiceListInterface')->getMock();
$view1 = new \stdClass();
$view2 = new \stdClass();
$this->decoratedFactory->expects($this->at(0))
->method('createView')
->with($list, null, null, null, null, $attr1)
->will($this->returnValue($view1));
$this->decoratedFactory->expects($this->at(1))
->method('createView')
->with($list, null, null, null, null, $attr2)
->will($this->returnValue($view2));
$this->assertSame($view1, $this->factory->createView($list, null, null, null, null, $attr1));
$this->assertSame($view2, $this->factory->createView($list, null, null, null, null, $attr2));
}
public function testCreateViewSameAttributesClosure()
{
$attr = function () {};
$list = $this->getMockBuilder('Symfony\Component\Form\ChoiceList\ChoiceListInterface')->getMock();
$view = new \stdClass();
$this->decoratedFactory->expects($this->once())
->method('createView')
->with($list, null, null, null, null, $attr)
->will($this->returnValue($view));
$this->assertSame($view, $this->factory->createView($list, null, null, null, null, $attr));
$this->assertSame($view, $this->factory->createView($list, null, null, null, null, $attr));
}
public function testCreateViewDifferentAttributesClosure()
{
$attr1 = function () {};
$attr2 = function () {};
$list = $this->getMockBuilder('Symfony\Component\Form\ChoiceList\ChoiceListInterface')->getMock();
$view1 = new \stdClass();
$view2 = new \stdClass();
$this->decoratedFactory->expects($this->at(0))
->method('createView')
->with($list, null, null, null, null, $attr1)
->will($this->returnValue($view1));
$this->decoratedFactory->expects($this->at(1))
->method('createView')
->with($list, null, null, null, null, $attr2)
->will($this->returnValue($view2));
$this->assertSame($view1, $this->factory->createView($list, null, null, null, null, $attr1));
$this->assertSame($view2, $this->factory->createView($list, null, null, null, null, $attr2));
}
public function provideSameChoices()
{
$object = (object) array('foo' => 'bar');
return array(
array(0, 0),
array('a', 'a'),
// https://github.com/symfony/symfony/issues/10409
array(chr(181).'meter', chr(181).'meter'), // UTF-8
array($object, $object),
);
}
public function provideDistinguishedChoices()
{
return array(
array(0, false),
array(0, null),
array(0, '0'),
array(0, ''),
array(1, true),
array(1, '1'),
array(1, 'a'),
array('', false),
array('', null),
array(false, null),
// Same properties, but not identical
array((object) array('foo' => 'bar'), (object) array('foo' => 'bar')),
);
}
public function provideSameKeyChoices()
{
// Only test types here that can be used as array keys
return array(
array(0, 0),
array(0, '0'),
array('a', 'a'),
array(chr(181).'meter', chr(181).'meter'),
);
}
public function provideDistinguishedKeyChoices()
{
// Only test types here that can be used as array keys
return array(
array(0, ''),
array(1, 'a'),
array('', 'a'),
);
}
}

View File

@@ -0,0 +1,791 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\ChoiceList\Factory;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Form\ChoiceList\ArrayChoiceList;
use Symfony\Component\Form\ChoiceList\ChoiceListInterface;
use Symfony\Component\Form\ChoiceList\Factory\DefaultChoiceListFactory;
use Symfony\Component\Form\ChoiceList\LazyChoiceList;
use Symfony\Component\Form\ChoiceList\View\ChoiceGroupView;
use Symfony\Component\Form\ChoiceList\View\ChoiceListView;
use Symfony\Component\Form\ChoiceList\View\ChoiceView;
class DefaultChoiceListFactoryTest extends TestCase
{
private $obj1;
private $obj2;
private $obj3;
private $obj4;
private $list;
/**
* @var DefaultChoiceListFactory
*/
private $factory;
public function getValue($object)
{
return $object->value;
}
public function getScalarValue($choice)
{
switch ($choice) {
case 'a': return 'a';
case 'b': return 'b';
case 'c': return '1';
case 'd': return '2';
}
}
public function getLabel($object)
{
return $object->label;
}
public function getFormIndex($object)
{
return $object->index;
}
public function isPreferred($object)
{
return $this->obj2 === $object || $this->obj3 === $object;
}
public function getAttr($object)
{
return $object->attr;
}
public function getGroup($object)
{
return $this->obj1 === $object || $this->obj2 === $object ? 'Group 1' : 'Group 2';
}
public function getGroupAsObject($object)
{
return $this->obj1 === $object || $this->obj2 === $object
? new DefaultChoiceListFactoryTest_Castable('Group 1')
: new DefaultChoiceListFactoryTest_Castable('Group 2');
}
protected function setUp()
{
$this->obj1 = (object) array('label' => 'A', 'index' => 'w', 'value' => 'a', 'preferred' => false, 'group' => 'Group 1', 'attr' => array());
$this->obj2 = (object) array('label' => 'B', 'index' => 'x', 'value' => 'b', 'preferred' => true, 'group' => 'Group 1', 'attr' => array('attr1' => 'value1'));
$this->obj3 = (object) array('label' => 'C', 'index' => 'y', 'value' => 1, 'preferred' => true, 'group' => 'Group 2', 'attr' => array('attr2' => 'value2'));
$this->obj4 = (object) array('label' => 'D', 'index' => 'z', 'value' => 2, 'preferred' => false, 'group' => 'Group 2', 'attr' => array());
$this->list = new ArrayChoiceList(
array('A' => $this->obj1, 'B' => $this->obj2, 'C' => $this->obj3, 'D' => $this->obj4)
);
$this->factory = new DefaultChoiceListFactory();
}
public function testCreateFromChoicesEmpty()
{
$list = $this->factory->createListFromChoices(array());
$this->assertSame(array(), $list->getChoices());
$this->assertSame(array(), $list->getValues());
}
public function testCreateFromChoicesFlat()
{
$list = $this->factory->createListFromChoices(
array('A' => $this->obj1, 'B' => $this->obj2, 'C' => $this->obj3, 'D' => $this->obj4)
);
$this->assertObjectListWithGeneratedValues($list);
}
public function testCreateFromChoicesFlatTraversable()
{
$list = $this->factory->createListFromChoices(
new \ArrayIterator(array('A' => $this->obj1, 'B' => $this->obj2, 'C' => $this->obj3, 'D' => $this->obj4))
);
$this->assertObjectListWithGeneratedValues($list);
}
public function testCreateFromChoicesFlatValuesAsCallable()
{
$list = $this->factory->createListFromChoices(
array('A' => $this->obj1, 'B' => $this->obj2, 'C' => $this->obj3, 'D' => $this->obj4),
array($this, 'getValue')
);
$this->assertObjectListWithCustomValues($list);
}
public function testCreateFromChoicesFlatValuesAsClosure()
{
$list = $this->factory->createListFromChoices(
array('A' => $this->obj1, 'B' => $this->obj2, 'C' => $this->obj3, 'D' => $this->obj4),
function ($object) { return $object->value; }
);
$this->assertObjectListWithCustomValues($list);
}
public function testCreateFromChoicesGrouped()
{
$list = $this->factory->createListFromChoices(
array(
'Group 1' => array('A' => $this->obj1, 'B' => $this->obj2),
'Group 2' => array('C' => $this->obj3, 'D' => $this->obj4),
)
);
$this->assertObjectListWithGeneratedValues($list);
}
public function testCreateFromChoicesGroupedTraversable()
{
$list = $this->factory->createListFromChoices(
new \ArrayIterator(array(
'Group 1' => array('A' => $this->obj1, 'B' => $this->obj2),
'Group 2' => array('C' => $this->obj3, 'D' => $this->obj4),
))
);
$this->assertObjectListWithGeneratedValues($list);
}
public function testCreateFromChoicesGroupedValuesAsCallable()
{
$list = $this->factory->createListFromChoices(
array(
'Group 1' => array('A' => $this->obj1, 'B' => $this->obj2),
'Group 2' => array('C' => $this->obj3, 'D' => $this->obj4),
),
array($this, 'getValue')
);
$this->assertObjectListWithCustomValues($list);
}
public function testCreateFromChoicesGroupedValuesAsClosure()
{
$list = $this->factory->createListFromChoices(
array(
'Group 1' => array('A' => $this->obj1, 'B' => $this->obj2),
'Group 2' => array('C' => $this->obj3, 'D' => $this->obj4),
),
function ($object) { return $object->value; }
);
$this->assertObjectListWithCustomValues($list);
}
public function testCreateFromLoader()
{
$loader = $this->getMockBuilder('Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface')->getMock();
$list = $this->factory->createListFromLoader($loader);
$this->assertEquals(new LazyChoiceList($loader), $list);
}
public function testCreateFromLoaderWithValues()
{
$loader = $this->getMockBuilder('Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface')->getMock();
$value = function () {};
$list = $this->factory->createListFromLoader($loader, $value);
$this->assertEquals(new LazyChoiceList($loader, $value), $list);
}
public function testCreateViewFlat()
{
$view = $this->factory->createView($this->list);
$this->assertEquals(new ChoiceListView(
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'),
), array()
), $view);
}
public function testCreateViewFlatPreferredChoices()
{
$view = $this->factory->createView(
$this->list,
array($this->obj2, $this->obj3)
);
$this->assertFlatView($view);
}
public function testCreateViewFlatPreferredChoicesEmptyArray()
{
$view = $this->factory->createView(
$this->list,
array()
);
$this->assertEquals(new ChoiceListView(
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'),
), array()
), $view);
}
public function testCreateViewFlatPreferredChoicesAsCallable()
{
$view = $this->factory->createView(
$this->list,
array($this, 'isPreferred')
);
$this->assertFlatView($view);
}
public function testCreateViewFlatPreferredChoicesAsClosure()
{
$obj2 = $this->obj2;
$obj3 = $this->obj3;
$view = $this->factory->createView(
$this->list,
function ($object) use ($obj2, $obj3) {
return $obj2 === $object || $obj3 === $object;
}
);
$this->assertFlatView($view);
}
public function testCreateViewFlatPreferredChoicesClosureReceivesKey()
{
$view = $this->factory->createView(
$this->list,
function ($object, $key) {
return 'B' === $key || 'C' === $key;
}
);
$this->assertFlatView($view);
}
public function testCreateViewFlatPreferredChoicesClosureReceivesValue()
{
$view = $this->factory->createView(
$this->list,
function ($object, $key, $value) {
return '1' === $value || '2' === $value;
}
);
$this->assertFlatView($view);
}
public function testCreateViewFlatLabelAsCallable()
{
$view = $this->factory->createView(
$this->list,
array($this->obj2, $this->obj3),
array($this, 'getLabel')
);
$this->assertFlatView($view);
}
public function testCreateViewFlatLabelAsClosure()
{
$view = $this->factory->createView(
$this->list,
array($this->obj2, $this->obj3),
function ($object) {
return $object->label;
}
);
$this->assertFlatView($view);
}
public function testCreateViewFlatLabelClosureReceivesKey()
{
$view = $this->factory->createView(
$this->list,
array($this->obj2, $this->obj3),
function ($object, $key) {
return $key;
}
);
$this->assertFlatView($view);
}
public function testCreateViewFlatLabelClosureReceivesValue()
{
$view = $this->factory->createView(
$this->list,
array($this->obj2, $this->obj3),
function ($object, $key, $value) {
switch ($value) {
case '0': return 'A';
case '1': return 'B';
case '2': return 'C';
case '3': return 'D';
}
}
);
$this->assertFlatView($view);
}
public function testCreateViewFlatIndexAsCallable()
{
$view = $this->factory->createView(
$this->list,
array($this->obj2, $this->obj3),
null, // label
array($this, 'getFormIndex')
);
$this->assertFlatViewWithCustomIndices($view);
}
public function testCreateViewFlatIndexAsClosure()
{
$view = $this->factory->createView(
$this->list,
array($this->obj2, $this->obj3),
null, // label
function ($object) {
return $object->index;
}
);
$this->assertFlatViewWithCustomIndices($view);
}
public function testCreateViewFlatIndexClosureReceivesKey()
{
$view = $this->factory->createView(
$this->list,
array($this->obj2, $this->obj3),
null, // label
function ($object, $key) {
switch ($key) {
case 'A': return 'w';
case 'B': return 'x';
case 'C': return 'y';
case 'D': return 'z';
}
}
);
$this->assertFlatViewWithCustomIndices($view);
}
public function testCreateViewFlatIndexClosureReceivesValue()
{
$view = $this->factory->createView(
$this->list,
array($this->obj2, $this->obj3),
null, // label
function ($object, $key, $value) {
switch ($value) {
case '0': return 'w';
case '1': return 'x';
case '2': return 'y';
case '3': return 'z';
}
}
);
$this->assertFlatViewWithCustomIndices($view);
}
public function testCreateViewFlatGroupByOriginalStructure()
{
$list = new ArrayChoiceList(array(
'Group 1' => array('A' => $this->obj1, 'B' => $this->obj2),
'Group 2' => array('C' => $this->obj3, 'D' => $this->obj4),
'Group empty' => array(),
));
$view = $this->factory->createView(
$list,
array($this->obj2, $this->obj3)
);
$this->assertGroupedView($view);
}
public function testCreateViewFlatGroupByEmpty()
{
$view = $this->factory->createView(
$this->list,
array($this->obj2, $this->obj3),
null, // label
null, // index
array() // ignored
);
$this->assertFlatView($view);
}
public function testCreateViewFlatGroupByAsCallable()
{
$view = $this->factory->createView(
$this->list,
array($this->obj2, $this->obj3),
null, // label
null, // index
array($this, 'getGroup')
);
$this->assertGroupedView($view);
}
public function testCreateViewFlatGroupByObjectThatCanBeCastToString()
{
$view = $this->factory->createView(
$this->list,
array($this->obj2, $this->obj3),
null, // label
null, // index
array($this, 'getGroupAsObject')
);
$this->assertGroupedView($view);
}
public function testCreateViewFlatGroupByAsClosure()
{
$obj1 = $this->obj1;
$obj2 = $this->obj2;
$view = $this->factory->createView(
$this->list,
array($this->obj2, $this->obj3),
null, // label
null, // index
function ($object) use ($obj1, $obj2) {
return $obj1 === $object || $obj2 === $object ? 'Group 1' : 'Group 2';
}
);
$this->assertGroupedView($view);
}
public function testCreateViewFlatGroupByClosureReceivesKey()
{
$view = $this->factory->createView(
$this->list,
array($this->obj2, $this->obj3),
null, // label
null, // index
function ($object, $key) {
return 'A' === $key || 'B' === $key ? 'Group 1' : 'Group 2';
}
);
$this->assertGroupedView($view);
}
public function testCreateViewFlatGroupByClosureReceivesValue()
{
$view = $this->factory->createView(
$this->list,
array($this->obj2, $this->obj3),
null, // label
null, // index
function ($object, $key, $value) {
return '0' === $value || '1' === $value ? 'Group 1' : 'Group 2';
}
);
$this->assertGroupedView($view);
}
public function testCreateViewFlatAttrAsArray()
{
$view = $this->factory->createView(
$this->list,
array($this->obj2, $this->obj3),
null, // label
null, // index
null, // group
array(
'B' => array('attr1' => 'value1'),
'C' => array('attr2' => 'value2'),
)
);
$this->assertFlatViewWithAttr($view);
}
public function testCreateViewFlatAttrEmpty()
{
$view = $this->factory->createView(
$this->list,
array($this->obj2, $this->obj3),
null, // label
null, // index
null, // group
array()
);
$this->assertFlatView($view);
}
public function testCreateViewFlatAttrAsCallable()
{
$view = $this->factory->createView(
$this->list,
array($this->obj2, $this->obj3),
null, // label
null, // index
null, // group
array($this, 'getAttr')
);
$this->assertFlatViewWithAttr($view);
}
public function testCreateViewFlatAttrAsClosure()
{
$view = $this->factory->createView(
$this->list,
array($this->obj2, $this->obj3),
null, // label
null, // index
null, // group
function ($object) {
return $object->attr;
}
);
$this->assertFlatViewWithAttr($view);
}
public function testCreateViewFlatAttrClosureReceivesKey()
{
$view = $this->factory->createView(
$this->list,
array($this->obj2, $this->obj3),
null, // label
null, // index
null, // group
function ($object, $key) {
switch ($key) {
case 'B': return array('attr1' => 'value1');
case 'C': return array('attr2' => 'value2');
default: return array();
}
}
);
$this->assertFlatViewWithAttr($view);
}
public function testCreateViewFlatAttrClosureReceivesValue()
{
$view = $this->factory->createView(
$this->list,
array($this->obj2, $this->obj3),
null, // label
null, // index
null, // group
function ($object, $key, $value) {
switch ($value) {
case '1': return array('attr1' => 'value1');
case '2': return array('attr2' => 'value2');
default: return array();
}
}
);
$this->assertFlatViewWithAttr($view);
}
private function assertScalarListWithChoiceValues(ChoiceListInterface $list)
{
$this->assertSame(array('a', 'b', 'c', 'd'), $list->getValues());
$this->assertSame(array(
'a' => 'a',
'b' => 'b',
'c' => 'c',
'd' => 'd',
), $list->getChoices());
$this->assertSame(array(
'a' => 'A',
'b' => 'B',
'c' => 'C',
'd' => 'D',
), $list->getOriginalKeys());
}
private function assertObjectListWithGeneratedValues(ChoiceListInterface $list)
{
$this->assertSame(array('0', '1', '2', '3'), $list->getValues());
$this->assertSame(array(
0 => $this->obj1,
1 => $this->obj2,
2 => $this->obj3,
3 => $this->obj4,
), $list->getChoices());
$this->assertSame(array(
0 => 'A',
1 => 'B',
2 => 'C',
3 => 'D',
), $list->getOriginalKeys());
}
private function assertScalarListWithCustomValues(ChoiceListInterface $list)
{
$this->assertSame(array('a', 'b', '1', '2'), $list->getValues());
$this->assertSame(array(
'a' => 'a',
'b' => 'b',
1 => 'c',
2 => 'd',
), $list->getChoices());
$this->assertSame(array(
'a' => 'A',
'b' => 'B',
1 => 'C',
2 => 'D',
), $list->getOriginalKeys());
}
private function assertObjectListWithCustomValues(ChoiceListInterface $list)
{
$this->assertSame(array('a', 'b', '1', '2'), $list->getValues());
$this->assertSame(array(
'a' => $this->obj1,
'b' => $this->obj2,
1 => $this->obj3,
2 => $this->obj4,
), $list->getChoices());
$this->assertSame(array(
'a' => 'A',
'b' => 'B',
1 => 'C',
2 => 'D',
), $list->getOriginalKeys());
}
private function assertFlatView($view)
{
$this->assertEquals(new ChoiceListView(
array(
0 => new ChoiceView($this->obj1, '0', 'A'),
3 => new ChoiceView($this->obj4, '3', 'D'),
), array(
1 => new ChoiceView($this->obj2, '1', 'B'),
2 => new ChoiceView($this->obj3, '2', 'C'),
)
), $view);
}
private function assertFlatViewWithCustomIndices($view)
{
$this->assertEquals(new ChoiceListView(
array(
'w' => new ChoiceView($this->obj1, '0', 'A'),
'z' => new ChoiceView($this->obj4, '3', 'D'),
), array(
'x' => new ChoiceView($this->obj2, '1', 'B'),
'y' => new ChoiceView($this->obj3, '2', 'C'),
)
), $view);
}
private function assertFlatViewWithAttr($view)
{
$this->assertEquals(new ChoiceListView(
array(
0 => new ChoiceView($this->obj1, '0', 'A'),
3 => new ChoiceView($this->obj4, '3', 'D'),
), array(
1 => new ChoiceView(
$this->obj2,
'1',
'B',
array('attr1' => 'value1')
),
2 => new ChoiceView(
$this->obj3,
'2',
'C',
array('attr2' => 'value2')
),
)
), $view);
}
private function assertGroupedView($view)
{
$this->assertEquals(new ChoiceListView(
array(
'Group 1' => new ChoiceGroupView(
'Group 1',
array(0 => new ChoiceView($this->obj1, '0', 'A'))
),
'Group 2' => new ChoiceGroupView(
'Group 2',
array(3 => new ChoiceView($this->obj4, '3', 'D'))
),
), array(
'Group 1' => new ChoiceGroupView(
'Group 1',
array(1 => new ChoiceView($this->obj2, '1', 'B'))
),
'Group 2' => new ChoiceGroupView(
'Group 2',
array(2 => new ChoiceView($this->obj3, '2', 'C'))
),
)
), $view);
}
}
class DefaultChoiceListFactoryTest_Castable
{
private $property;
public function __construct($property)
{
$this->property = $property;
}
public function __toString()
{
return $this->property;
}
}

View File

@@ -0,0 +1,483 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\ChoiceList\Factory;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Form\ChoiceList\Factory\PropertyAccessDecorator;
use Symfony\Component\PropertyAccess\PropertyPath;
/**
* @author Bernhard Schussek <bschussek@gmail.com>
*/
class PropertyAccessDecoratorTest extends TestCase
{
/**
* @var \PHPUnit_Framework_MockObject_MockObject
*/
private $decoratedFactory;
/**
* @var PropertyAccessDecorator
*/
private $factory;
protected function setUp()
{
$this->decoratedFactory = $this->getMockBuilder('Symfony\Component\Form\ChoiceList\Factory\ChoiceListFactoryInterface')->getMock();
$this->factory = new PropertyAccessDecorator($this->decoratedFactory);
}
public function testCreateFromChoicesPropertyPath()
{
$choices = array((object) array('property' => 'value'));
$this->decoratedFactory->expects($this->once())
->method('createListFromChoices')
->with($choices, $this->isInstanceOf('\Closure'))
->will($this->returnCallback(function ($choices, $callback) {
return array_map($callback, $choices);
}));
$this->assertSame(array('value'), $this->factory->createListFromChoices($choices, 'property'));
}
public function testCreateFromChoicesPropertyPathInstance()
{
$choices = array((object) array('property' => 'value'));
$this->decoratedFactory->expects($this->once())
->method('createListFromChoices')
->with($choices, $this->isInstanceOf('\Closure'))
->will($this->returnCallback(function ($choices, $callback) {
return array_map($callback, $choices);
}));
$this->assertSame(array('value'), $this->factory->createListFromChoices($choices, new PropertyPath('property')));
}
/**
* @group legacy
*/
public function testCreateFromChoicesPropertyPathWithCallableString()
{
$choices = array('foo' => 'bar');
$this->decoratedFactory->expects($this->once())
->method('createListFromChoices')
->with($choices, 'end')
->willReturn('RESULT');
$this->assertSame('RESULT', $this->factory->createListFromChoices($choices, 'end'));
}
public function testCreateFromLoaderPropertyPath()
{
$loader = $this->getMockBuilder('Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface')->getMock();
$this->decoratedFactory->expects($this->once())
->method('createListFromLoader')
->with($loader, $this->isInstanceOf('\Closure'))
->will($this->returnCallback(function ($loader, $callback) {
return $callback((object) array('property' => 'value'));
}));
$this->assertSame('value', $this->factory->createListFromLoader($loader, 'property'));
}
/**
* @group legacy
*/
public function testCreateFromLoaderPropertyPathWithCallableString()
{
$loader = $this->getMockBuilder('Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface')->getMock();
$this->decoratedFactory->expects($this->once())
->method('createListFromLoader')
->with($loader, 'end')
->willReturn('RESULT');
$this->assertSame('RESULT', $this->factory->createListFromLoader($loader, 'end'));
}
// https://github.com/symfony/symfony/issues/5494
public function testCreateFromChoicesAssumeNullIfValuePropertyPathUnreadable()
{
$choices = array(null);
$this->decoratedFactory->expects($this->once())
->method('createListFromChoices')
->with($choices, $this->isInstanceOf('\Closure'))
->will($this->returnCallback(function ($choices, $callback) {
return array_map($callback, $choices);
}));
$this->assertSame(array(null), $this->factory->createListFromChoices($choices, 'property'));
}
// https://github.com/symfony/symfony/issues/5494
public function testCreateFromChoiceLoaderAssumeNullIfValuePropertyPathUnreadable()
{
$loader = $this->getMockBuilder('Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface')->getMock();
$this->decoratedFactory->expects($this->once())
->method('createListFromLoader')
->with($loader, $this->isInstanceOf('\Closure'))
->will($this->returnCallback(function ($loader, $callback) {
return $callback(null);
}));
$this->assertNull($this->factory->createListFromLoader($loader, 'property'));
}
public function testCreateFromLoaderPropertyPathInstance()
{
$loader = $this->getMockBuilder('Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface')->getMock();
$this->decoratedFactory->expects($this->once())
->method('createListFromLoader')
->with($loader, $this->isInstanceOf('\Closure'))
->will($this->returnCallback(function ($loader, $callback) {
return $callback((object) array('property' => 'value'));
}));
$this->assertSame('value', $this->factory->createListFromLoader($loader, new PropertyPath('property')));
}
public function testCreateViewPreferredChoicesAsPropertyPath()
{
$list = $this->getMockBuilder('Symfony\Component\Form\ChoiceList\ChoiceListInterface')->getMock();
$this->decoratedFactory->expects($this->once())
->method('createView')
->with($list, $this->isInstanceOf('\Closure'))
->will($this->returnCallback(function ($list, $preferred) {
return $preferred((object) array('property' => true));
}));
$this->assertTrue($this->factory->createView(
$list,
'property'
));
}
/**
* @group legacy
*/
public function testCreateViewPreferredChoicesAsPropertyPathWithCallableString()
{
$list = $this->getMockBuilder('Symfony\Component\Form\ChoiceList\ChoiceListInterface')->getMock();
$this->decoratedFactory->expects($this->once())
->method('createView')
->with($list, 'end')
->willReturn('RESULT');
$this->assertSame('RESULT', $this->factory->createView(
$list,
'end'
));
}
public function testCreateViewPreferredChoicesAsPropertyPathInstance()
{
$list = $this->getMockBuilder('Symfony\Component\Form\ChoiceList\ChoiceListInterface')->getMock();
$this->decoratedFactory->expects($this->once())
->method('createView')
->with($list, $this->isInstanceOf('\Closure'))
->will($this->returnCallback(function ($list, $preferred) {
return $preferred((object) array('property' => true));
}));
$this->assertTrue($this->factory->createView(
$list,
new PropertyPath('property')
));
}
// https://github.com/symfony/symfony/issues/5494
public function testCreateViewAssumeNullIfPreferredChoicesPropertyPathUnreadable()
{
$list = $this->getMockBuilder('Symfony\Component\Form\ChoiceList\ChoiceListInterface')->getMock();
$this->decoratedFactory->expects($this->once())
->method('createView')
->with($list, $this->isInstanceOf('\Closure'))
->will($this->returnCallback(function ($list, $preferred) {
return $preferred((object) array('category' => null));
}));
$this->assertFalse($this->factory->createView(
$list,
'category.preferred'
));
}
public function testCreateViewLabelsAsPropertyPath()
{
$list = $this->getMockBuilder('Symfony\Component\Form\ChoiceList\ChoiceListInterface')->getMock();
$this->decoratedFactory->expects($this->once())
->method('createView')
->with($list, null, $this->isInstanceOf('\Closure'))
->will($this->returnCallback(function ($list, $preferred, $label) {
return $label((object) array('property' => 'label'));
}));
$this->assertSame('label', $this->factory->createView(
$list,
null, // preferred choices
'property'
));
}
/**
* @group legacy
*/
public function testCreateViewLabelsAsPropertyPathWithCallableString()
{
$list = $this->getMockBuilder('Symfony\Component\Form\ChoiceList\ChoiceListInterface')->getMock();
$this->decoratedFactory->expects($this->once())
->method('createView')
->with($list, null, 'end')
->willReturn('RESULT');
$this->assertSame('RESULT', $this->factory->createView(
$list,
null, // preferred choices
'end'
));
}
public function testCreateViewLabelsAsPropertyPathInstance()
{
$list = $this->getMockBuilder('Symfony\Component\Form\ChoiceList\ChoiceListInterface')->getMock();
$this->decoratedFactory->expects($this->once())
->method('createView')
->with($list, null, $this->isInstanceOf('\Closure'))
->will($this->returnCallback(function ($list, $preferred, $label) {
return $label((object) array('property' => 'label'));
}));
$this->assertSame('label', $this->factory->createView(
$list,
null, // preferred choices
new PropertyPath('property')
));
}
public function testCreateViewIndicesAsPropertyPath()
{
$list = $this->getMockBuilder('Symfony\Component\Form\ChoiceList\ChoiceListInterface')->getMock();
$this->decoratedFactory->expects($this->once())
->method('createView')
->with($list, null, null, $this->isInstanceOf('\Closure'))
->will($this->returnCallback(function ($list, $preferred, $label, $index) {
return $index((object) array('property' => 'index'));
}));
$this->assertSame('index', $this->factory->createView(
$list,
null, // preferred choices
null, // label
'property'
));
}
/**
* @group legacy
*/
public function testCreateViewIndicesAsPropertyPathWithCallableString()
{
$list = $this->getMockBuilder('Symfony\Component\Form\ChoiceList\ChoiceListInterface')->getMock();
$this->decoratedFactory->expects($this->once())
->method('createView')
->with($list, null, null, 'end')
->willReturn('RESULT');
$this->assertSame('RESULT', $this->factory->createView(
$list,
null, // preferred choices
null, // label
'end'
));
}
public function testCreateViewIndicesAsPropertyPathInstance()
{
$list = $this->getMockBuilder('Symfony\Component\Form\ChoiceList\ChoiceListInterface')->getMock();
$this->decoratedFactory->expects($this->once())
->method('createView')
->with($list, null, null, $this->isInstanceOf('\Closure'))
->will($this->returnCallback(function ($list, $preferred, $label, $index) {
return $index((object) array('property' => 'index'));
}));
$this->assertSame('index', $this->factory->createView(
$list,
null, // preferred choices
null, // label
new PropertyPath('property')
));
}
public function testCreateViewGroupsAsPropertyPath()
{
$list = $this->getMockBuilder('Symfony\Component\Form\ChoiceList\ChoiceListInterface')->getMock();
$this->decoratedFactory->expects($this->once())
->method('createView')
->with($list, null, null, null, $this->isInstanceOf('\Closure'))
->will($this->returnCallback(function ($list, $preferred, $label, $index, $groupBy) {
return $groupBy((object) array('property' => 'group'));
}));
$this->assertSame('group', $this->factory->createView(
$list,
null, // preferred choices
null, // label
null, // index
'property'
));
}
/**
* @group legacy
*/
public function testCreateViewGroupsAsPropertyPathWithCallableString()
{
$list = $this->getMockBuilder('Symfony\Component\Form\ChoiceList\ChoiceListInterface')->getMock();
$this->decoratedFactory->expects($this->once())
->method('createView')
->with($list, null, null, null, 'end')
->willReturn('RESULT');
$this->assertSame('RESULT', $this->factory->createView(
$list,
null, // preferred choices
null, // label
null, // index
'end'
));
}
public function testCreateViewGroupsAsPropertyPathInstance()
{
$list = $this->getMockBuilder('Symfony\Component\Form\ChoiceList\ChoiceListInterface')->getMock();
$this->decoratedFactory->expects($this->once())
->method('createView')
->with($list, null, null, null, $this->isInstanceOf('\Closure'))
->will($this->returnCallback(function ($list, $preferred, $label, $index, $groupBy) {
return $groupBy((object) array('property' => 'group'));
}));
$this->assertSame('group', $this->factory->createView(
$list,
null, // preferred choices
null, // label
null, // index
new PropertyPath('property')
));
}
// https://github.com/symfony/symfony/issues/5494
public function testCreateViewAssumeNullIfGroupsPropertyPathUnreadable()
{
$list = $this->getMockBuilder('Symfony\Component\Form\ChoiceList\ChoiceListInterface')->getMock();
$this->decoratedFactory->expects($this->once())
->method('createView')
->with($list, null, null, null, $this->isInstanceOf('\Closure'))
->will($this->returnCallback(function ($list, $preferred, $label, $index, $groupBy) {
return $groupBy((object) array('group' => null));
}));
$this->assertNull($this->factory->createView(
$list,
null, // preferred choices
null, // label
null, // index
'group.name'
));
}
public function testCreateViewAttrAsPropertyPath()
{
$list = $this->getMockBuilder('Symfony\Component\Form\ChoiceList\ChoiceListInterface')->getMock();
$this->decoratedFactory->expects($this->once())
->method('createView')
->with($list, null, null, null, null, $this->isInstanceOf('\Closure'))
->will($this->returnCallback(function ($list, $preferred, $label, $index, $groupBy, $attr) {
return $attr((object) array('property' => 'attr'));
}));
$this->assertSame('attr', $this->factory->createView(
$list,
null, // preferred choices
null, // label
null, // index
null, // groups
'property'
));
}
/**
* @group legacy
*/
public function testCreateViewAttrAsPropertyPathWithCallableString()
{
$list = $this->getMockBuilder('Symfony\Component\Form\ChoiceList\ChoiceListInterface')->getMock();
$this->decoratedFactory->expects($this->once())
->method('createView')
->with($list, null, null, null, null, 'end')
->willReturn('RESULT');
$this->assertSame('RESULT', $this->factory->createView(
$list,
null, // preferred choices
null, // label
null, // inde
null, // groups
'end'
));
}
public function testCreateViewAttrAsPropertyPathInstance()
{
$list = $this->getMockBuilder('Symfony\Component\Form\ChoiceList\ChoiceListInterface')->getMock();
$this->decoratedFactory->expects($this->once())
->method('createView')
->with($list, null, null, null, null, $this->isInstanceOf('\Closure'))
->will($this->returnCallback(function ($list, $preferred, $label, $index, $groupBy, $attr) {
return $attr((object) array('property' => 'attr'));
}));
$this->assertSame('attr', $this->factory->createView(
$list,
null, // preferred choices
null, // label
null, // index
null, // groups
new PropertyPath('property')
));
}
}

View File

@@ -0,0 +1,208 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\ChoiceList;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Form\ChoiceList\ArrayChoiceList;
use Symfony\Component\Form\ChoiceList\LazyChoiceList;
/**
* @author Bernhard Schussek <bschussek@gmail.com>
*/
class LazyChoiceListTest extends TestCase
{
/**
* @var LazyChoiceList
*/
private $list;
/**
* @var \PHPUnit_Framework_MockObject_MockObject
*/
private $loadedList;
/**
* @var \PHPUnit_Framework_MockObject_MockObject
*/
private $loader;
private $value;
protected function setUp()
{
$this->loadedList = $this->getMockBuilder('Symfony\Component\Form\ChoiceList\ChoiceListInterface')->getMock();
$this->loader = $this->getMockBuilder('Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface')->getMock();
$this->value = function () {};
$this->list = new LazyChoiceList($this->loader, $this->value);
}
public function testGetChoiceLoadersLoadsLoadedListOnFirstCall()
{
$this->loader->expects($this->exactly(2))
->method('loadChoiceList')
->with($this->value)
->will($this->returnValue($this->loadedList));
// The same list is returned by the loader
$this->loadedList->expects($this->exactly(2))
->method('getChoices')
->will($this->returnValue('RESULT'));
$this->assertSame('RESULT', $this->list->getChoices());
$this->assertSame('RESULT', $this->list->getChoices());
}
/**
* @group legacy
*/
public function testGetChoicesUsesLoadedListWhenLoaderDoesNotCacheChoiceListOnFirstCall()
{
$this->loader->expects($this->at(0))
->method('loadChoiceList')
->with($this->value)
->willReturn($this->loadedList);
$this->loader->expects($this->at(1))
->method('loadChoiceList')
->with($this->value)
->willReturn(new ArrayChoiceList(array('a', 'b')));
// The same list is returned by the lazy choice list
$this->loadedList->expects($this->exactly(2))
->method('getChoices')
->will($this->returnValue('RESULT'));
$this->assertSame('RESULT', $this->list->getChoices());
$this->assertSame('RESULT', $this->list->getChoices());
}
public function testGetValuesLoadsLoadedListOnFirstCall()
{
$this->loader->expects($this->exactly(2))
->method('loadChoiceList')
->with($this->value)
->will($this->returnValue($this->loadedList));
// The same list is returned by the loader
$this->loadedList->expects($this->exactly(2))
->method('getValues')
->will($this->returnValue('RESULT'));
$this->assertSame('RESULT', $this->list->getValues());
$this->assertSame('RESULT', $this->list->getValues());
}
public function testGetStructuredValuesLoadsLoadedListOnFirstCall()
{
$this->loader->expects($this->exactly(2))
->method('loadChoiceList')
->with($this->value)
->will($this->returnValue($this->loadedList));
// The same list is returned by the loader
$this->loadedList->expects($this->exactly(2))
->method('getStructuredValues')
->will($this->returnValue('RESULT'));
$this->assertSame('RESULT', $this->list->getStructuredValues());
$this->assertSame('RESULT', $this->list->getStructuredValues());
}
public function testGetOriginalKeysLoadsLoadedListOnFirstCall()
{
$this->loader->expects($this->exactly(2))
->method('loadChoiceList')
->with($this->value)
->will($this->returnValue($this->loadedList));
// The same list is returned by the loader
$this->loadedList->expects($this->exactly(2))
->method('getOriginalKeys')
->will($this->returnValue('RESULT'));
$this->assertSame('RESULT', $this->list->getOriginalKeys());
$this->assertSame('RESULT', $this->list->getOriginalKeys());
}
public function testGetChoicesForValuesForwardsCallIfListNotLoaded()
{
$this->loader->expects($this->exactly(2))
->method('loadChoicesForValues')
->with(array('a', 'b'))
->will($this->returnValue('RESULT'));
$this->assertSame('RESULT', $this->list->getChoicesForValues(array('a', 'b')));
$this->assertSame('RESULT', $this->list->getChoicesForValues(array('a', 'b')));
}
public function testGetChoicesForValuesUsesLoadedList()
{
$this->loader->expects($this->exactly(3))
->method('loadChoiceList')
->with($this->value)
// For BC, the same choice loaded list is returned 3 times
// It should only twice in 4.0
->will($this->returnValue($this->loadedList));
$this->loader->expects($this->never())
->method('loadChoicesForValues');
$this->loadedList->expects($this->exactly(2))
->method('getChoicesForValues')
->with(array('a', 'b'))
->will($this->returnValue('RESULT'));
// load choice list
$this->list->getChoices();
$this->assertSame('RESULT', $this->list->getChoicesForValues(array('a', 'b')));
$this->assertSame('RESULT', $this->list->getChoicesForValues(array('a', 'b')));
}
/**
* @group legacy
*/
public function testGetValuesForChoicesForwardsCallIfListNotLoaded()
{
$this->loader->expects($this->exactly(2))
->method('loadValuesForChoices')
->with(array('a', 'b'))
->will($this->returnValue('RESULT'));
$this->assertSame('RESULT', $this->list->getValuesForChoices(array('a', 'b')));
$this->assertSame('RESULT', $this->list->getValuesForChoices(array('a', 'b')));
}
public function testGetValuesForChoicesUsesLoadedList()
{
$this->loader->expects($this->exactly(3))
->method('loadChoiceList')
->with($this->value)
// For BC, the same choice loaded list is returned 3 times
// It should only twice in 4.0
->will($this->returnValue($this->loadedList));
$this->loader->expects($this->never())
->method('loadValuesForChoices');
$this->loadedList->expects($this->exactly(2))
->method('getValuesForChoices')
->with(array('a', 'b'))
->will($this->returnValue('RESULT'));
// load choice list
$this->list->getChoices();
$this->assertSame('RESULT', $this->list->getValuesForChoices(array('a', 'b')));
$this->assertSame('RESULT', $this->list->getValuesForChoices(array('a', 'b')));
}
}

View File

@@ -0,0 +1,102 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\ChoiceList\Loader;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Form\ChoiceList\LazyChoiceList;
use Symfony\Component\Form\ChoiceList\Loader\CallbackChoiceLoader;
/**
* @author Jules Pietri <jules@heahprod.com>
*/
class CallbackChoiceLoaderTest extends TestCase
{
/**
* @var \Symfony\Component\Form\ChoiceList\Loader\CallbackChoiceLoader
*/
private static $loader;
/**
* @var callable
*/
private static $value;
/**
* @var array
*/
private static $choices;
/**
* @var string[]
*/
private static $choiceValues;
/**
* @var \Symfony\Component\Form\ChoiceList\LazyChoiceList
*/
private static $lazyChoiceList;
public static function setUpBeforeClass()
{
self::$loader = new CallbackChoiceLoader(function () {
return self::$choices;
});
self::$value = function ($choice) {
return isset($choice->value) ? $choice->value : null;
};
self::$choices = array(
(object) array('value' => 'choice_one'),
(object) array('value' => 'choice_two'),
);
self::$choiceValues = array('choice_one', 'choice_two');
self::$lazyChoiceList = new LazyChoiceList(self::$loader, self::$value);
}
public function testLoadChoiceList()
{
$this->assertInstanceOf('\Symfony\Component\Form\ChoiceList\ChoiceListInterface', self::$loader->loadChoiceList(self::$value));
}
public function testLoadChoiceListOnlyOnce()
{
$loadedChoiceList = self::$loader->loadChoiceList(self::$value);
$this->assertSame($loadedChoiceList, self::$loader->loadChoiceList(self::$value));
}
public function testLoadChoicesForValuesLoadsChoiceListOnFirstCall()
{
$this->assertSame(
self::$loader->loadChoicesForValues(self::$choiceValues, self::$value),
self::$lazyChoiceList->getChoicesForValues(self::$choiceValues),
'Choice list should not be reloaded.'
);
}
public function testLoadValuesForChoicesLoadsChoiceListOnFirstCall()
{
$this->assertSame(
self::$loader->loadValuesForChoices(self::$choices, self::$value),
self::$lazyChoiceList->getValuesForChoices(self::$choices),
'Choice list should not be reloaded.'
);
}
public static function tearDownAfterClass()
{
self::$loader = null;
self::$value = null;
self::$choices = array();
self::$choiceValues = array();
self::$lazyChoiceList = null;
}
}

View File

@@ -0,0 +1,50 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests;
use Symfony\Component\Form\Test\FormPerformanceTestCase;
/**
* @author Bernhard Schussek <bschussek@gmail.com>
*/
class CompoundFormPerformanceTest extends 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('Symfony\Component\Form\Extension\Core\Type\FormType')
->add('firstName', 'Symfony\Component\Form\Extension\Core\Type\TextType')
->add('lastName', 'Symfony\Component\Form\Extension\Core\Type\TextType')
->add('gender', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', array(
'choices' => array('male' => 'Male', 'female' => 'Female'),
'required' => false,
))
->add('age', 'Symfony\Component\Form\Extension\Core\Type\NumberType')
->add('birthDate', 'Symfony\Component\Form\Extension\Core\Type\BirthdayType')
->add('city', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', array(
// simulate 300 different cities
'choices' => range(1, 300),
))
->getForm();
// load the form into a view
$form->createView();
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,243 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\DependencyInjection;
use PHPUnit\Framework\TestCase;
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
use Symfony\Component\Form\DependencyInjection\FormPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\ServiceLocator;
use Symfony\Component\Form\AbstractType;
/**
* @author Bernhard Schussek <bschussek@gmail.com>
*/
class FormPassTest extends TestCase
{
public function testDoNothingIfFormExtensionNotLoaded()
{
$container = $this->createContainerBuilder();
$container->compile();
$this->assertFalse($container->hasDefinition('form.extension'));
}
public function testAddTaggedTypes()
{
$container = $this->createContainerBuilder();
$container->setDefinition('form.extension', $this->createExtensionDefinition());
$container->register('my.type1', __CLASS__.'_Type1')->addTag('form.type');
$container->register('my.type2', __CLASS__.'_Type2')->addTag('form.type');
$container->compile();
$extDefinition = $container->getDefinition('form.extension');
$this->assertEquals(
(new Definition(ServiceLocator::class, array(array(
__CLASS__.'_Type1' => new ServiceClosureArgument(new Reference('my.type1')),
__CLASS__.'_Type2' => new ServiceClosureArgument(new Reference('my.type2')),
))))->addTag('container.service_locator')->setPublic(false),
$extDefinition->getArgument(0)
);
}
/**
* @dataProvider addTaggedTypeExtensionsDataProvider
*/
public function testAddTaggedTypeExtensions(array $extensions, array $expectedRegisteredExtensions)
{
$container = $this->createContainerBuilder();
$container->setDefinition('form.extension', $this->createExtensionDefinition());
foreach ($extensions as $serviceId => $tag) {
$container->register($serviceId, 'stdClass')->addTag('form.type_extension', $tag);
}
$container->compile();
$extDefinition = $container->getDefinition('form.extension');
$this->assertEquals($expectedRegisteredExtensions, $extDefinition->getArgument(1));
}
/**
* @return array
*/
public function addTaggedTypeExtensionsDataProvider()
{
return array(
array(
array(
'my.type_extension1' => array('extended_type' => 'type1'),
'my.type_extension2' => array('extended_type' => 'type1'),
'my.type_extension3' => array('extended_type' => 'type2'),
),
array(
'type1' => new IteratorArgument(array(
new Reference('my.type_extension1'),
new Reference('my.type_extension2'),
)),
'type2' => new IteratorArgument(array(new Reference('my.type_extension3'))),
),
),
array(
array(
'my.type_extension1' => array('extended_type' => 'type1', 'priority' => 1),
'my.type_extension2' => array('extended_type' => 'type1', 'priority' => 2),
'my.type_extension3' => array('extended_type' => 'type1', 'priority' => -1),
'my.type_extension4' => array('extended_type' => 'type2', 'priority' => 2),
'my.type_extension5' => array('extended_type' => 'type2', 'priority' => 1),
'my.type_extension6' => array('extended_type' => 'type2', 'priority' => 1),
),
array(
'type1' => new IteratorArgument(array(
new Reference('my.type_extension2'),
new Reference('my.type_extension1'),
new Reference('my.type_extension3'),
)),
'type2' => new IteratorArgument(array(
new Reference('my.type_extension4'),
new Reference('my.type_extension5'),
new Reference('my.type_extension6'),
)),
),
),
);
}
/**
* @expectedException \InvalidArgumentException
* @expectedExceptionMessage extended-type attribute, none was configured for the "my.type_extension" service
*/
public function testAddTaggedFormTypeExtensionWithoutExtendedTypeAttribute()
{
$container = $this->createContainerBuilder();
$container->setDefinition('form.extension', $this->createExtensionDefinition());
$container->register('my.type_extension', 'stdClass')
->addTag('form.type_extension');
$container->compile();
}
public function testAddTaggedGuessers()
{
$container = $this->createContainerBuilder();
$definition1 = new Definition('stdClass');
$definition1->addTag('form.type_guesser');
$definition2 = new Definition('stdClass');
$definition2->addTag('form.type_guesser');
$container->setDefinition('form.extension', $this->createExtensionDefinition());
$container->setDefinition('my.guesser1', $definition1);
$container->setDefinition('my.guesser2', $definition2);
$container->compile();
$extDefinition = $container->getDefinition('form.extension');
$this->assertEquals(
new IteratorArgument(array(
new Reference('my.guesser1'),
new Reference('my.guesser2'),
)),
$extDefinition->getArgument(2)
);
}
/**
* @dataProvider privateTaggedServicesProvider
*/
public function testPrivateTaggedServices($id, $tagName, callable $assertion, array $tagAttributes = array())
{
$formPass = new FormPass();
$container = new ContainerBuilder();
$container->setDefinition('form.extension', $this->createExtensionDefinition());
$container->register($id, 'stdClass')->setPublic(false)->addTag($tagName, $tagAttributes);
$formPass->process($container);
$assertion($container);
}
public function privateTaggedServicesProvider()
{
return array(
array(
'my.type',
'form.type',
function (ContainerBuilder $container) {
$formTypes = $container->getDefinition('form.extension')->getArgument(0);
$this->assertInstanceOf(Reference::class, $formTypes);
$locator = $container->getDefinition((string) $formTypes);
$expectedLocatorMap = array(
'stdClass' => new ServiceClosureArgument(new Reference('my.type')),
);
$this->assertInstanceOf(Definition::class, $locator);
$this->assertEquals($expectedLocatorMap, $locator->getArgument(0));
},
),
array(
'my.type_extension',
'form.type_extension',
function (ContainerBuilder $container) {
$this->assertEquals(
array('Symfony\Component\Form\Extension\Core\Type\FormType' => new IteratorArgument(array(new Reference('my.type_extension')))),
$container->getDefinition('form.extension')->getArgument(1)
);
},
array('extended_type' => 'Symfony\Component\Form\Extension\Core\Type\FormType'),
),
array('my.guesser', 'form.type_guesser', function (ContainerBuilder $container) {
$this->assertEquals(new IteratorArgument(array(new Reference('my.guesser'))), $container->getDefinition('form.extension')->getArgument(2));
}),
);
}
private function createExtensionDefinition()
{
$definition = new Definition('Symfony\Component\Form\Extension\DependencyInjection\DependencyInjectionExtension');
$definition->setArguments(array(
array(),
array(),
new IteratorArgument(array()),
));
return $definition;
}
private function createContainerBuilder()
{
$container = new ContainerBuilder();
$container->addCompilerPass(new FormPass());
return $container;
}
}
class FormPassTest_Type1 extends AbstractType
{
}
class FormPassTest_Type2 extends AbstractType
{
}

View File

@@ -0,0 +1,362 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\Extension\Core\DataMapper;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Form\FormConfigBuilder;
use Symfony\Component\Form\FormConfigInterface;
use Symfony\Component\Form\Extension\Core\DataMapper\PropertyPathMapper;
class PropertyPathMapperTest extends TestCase
{
/**
* @var PropertyPathMapper
*/
private $mapper;
/**
* @var \PHPUnit_Framework_MockObject_MockObject
*/
private $dispatcher;
/**
* @var \PHPUnit_Framework_MockObject_MockObject
*/
private $propertyAccessor;
protected function setUp()
{
$this->dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcherInterface')->getMock();
$this->propertyAccessor = $this->getMockBuilder('Symfony\Component\PropertyAccess\PropertyAccessorInterface')->getMock();
$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 bool $synchronized
* @param bool $submitted
*
* @return \PHPUnit_Framework_MockObject_MockObject
*/
private function getForm(FormConfigInterface $config, $synchronized = true, $submitted = true)
{
$form = $this->getMockBuilder('Symfony\Component\Form\Form')
->setConstructorArgs(array($config))
->setMethods(array('isSynchronized', 'isSubmitted'))
->getMock();
$form->expects($this->any())
->method('isSynchronized')
->will($this->returnValue($synchronized));
$form->expects($this->any())
->method('isSubmitted')
->will($this->returnValue($submitted));
return $form;
}
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 testMapDataToFormsSetsDefaultDataIfPassedDataIsNull()
{
$default = new \stdClass();
$propertyPath = $this->getPropertyPath('engine');
$this->propertyAccessor->expects($this->never())
->method('getValue');
$config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher);
$config->setByReference(true);
$config->setPropertyPath($propertyPath);
$config->setData($default);
$form = $this->getMockBuilder('Symfony\Component\Form\Form')
->setConstructorArgs(array($config))
->setMethods(array('setData'))
->getMock();
$form->expects($this->once())
->method('setData')
->with($default);
$this->mapper->mapDataToForms(null, array($form));
}
public function testMapDataToFormsSetsDefaultDataIfPassedDataIsEmptyArray()
{
$default = new \stdClass();
$propertyPath = $this->getPropertyPath('engine');
$this->propertyAccessor->expects($this->never())
->method('getValue');
$config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher);
$config->setByReference(true);
$config->setPropertyPath($propertyPath);
$config->setData($default);
$form = $this->getMockBuilder('Symfony\Component\Form\Form')
->setConstructorArgs(array($config))
->setMethods(array('setData'))
->getMock();
$form->expects($this->once())
->method('setData')
->with($default);
$this->mapper->mapDataToForms(array(), array($form));
}
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 testMapFormsToDataIgnoresUnsubmittedForms()
{
$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, true, false);
$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);
}
}

View File

@@ -0,0 +1,150 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Form\Extension\Core\DataTransformer\ArrayToPartsTransformer;
class ArrayToPartsTransformerTest extends 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');
}
}

View File

@@ -0,0 +1,35 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer;
use PHPUnit\Framework\TestCase;
class BaseDateTimeTransformerTest extends TestCase
{
/**
* @expectedException \Symfony\Component\Form\Exception\InvalidArgumentException
* @expectedExceptionMessage this_timezone_does_not_exist
*/
public function testConstructFailsIfInputTimezoneIsInvalid()
{
$this->getMockBuilder('Symfony\Component\Form\Extension\Core\DataTransformer\BaseDateTimeTransformer')->setConstructorArgs(array('this_timezone_does_not_exist'))->getMock();
}
/**
* @expectedException \Symfony\Component\Form\Exception\InvalidArgumentException
* @expectedExceptionMessage that_timezone_does_not_exist
*/
public function testConstructFailsIfOutputTimezoneIsInvalid()
{
$this->getMockBuilder('Symfony\Component\Form\Extension\Core\DataTransformer\BaseDateTimeTransformer')->setConstructorArgs(array(null, 'that_timezone_does_not_exist'))->getMock();
}
}

View File

@@ -0,0 +1,71 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Form\Extension\Core\DataTransformer\BooleanToStringTransformer;
class BooleanToStringTransformerTest extends TestCase
{
const TRUE_VALUE = '1';
/**
* @var BooleanToStringTransformer
*/
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));
}
// https://github.com/symfony/symfony/issues/8989
public function testTransformAcceptsNull()
{
$this->assertNull($this->transformer->transform(null));
}
/**
* @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
*/
public function testTransformFailsIfString()
{
$this->transformer->transform('1');
}
/**
* @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
*/
public function testReverseTransformFailsIfInteger()
{
$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));
}
}

View File

@@ -0,0 +1,97 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Form\ChoiceList\ArrayChoiceList;
use Symfony\Component\Form\Extension\Core\DataTransformer\ChoiceToValueTransformer;
class ChoiceToValueTransformerTest extends TestCase
{
protected $transformer;
protected $transformerWithNull;
protected function setUp()
{
$list = new ArrayChoiceList(array('', false, 'X', true));
$listWithNull = new ArrayChoiceList(array('', false, 'X', null));
$this->transformer = new ChoiceToValueTransformer($list);
$this->transformerWithNull = new ChoiceToValueTransformer($listWithNull);
}
protected function tearDown()
{
$this->transformer = null;
$this->transformerWithNull = null;
}
public function transformProvider()
{
return array(
// more extensive test set can be found in FormUtilTest
array('', '', '', '0'),
array(false, '0', false, '1'),
array('X', 'X', 'X', '2'),
array(true, '1', null, '3'),
);
}
/**
* @dataProvider transformProvider
*/
public function testTransform($in, $out, $inWithNull, $outWithNull)
{
$this->assertSame($out, $this->transformer->transform($in));
$this->assertSame($outWithNull, $this->transformerWithNull->transform($inWithNull));
}
public function reverseTransformProvider()
{
return array(
// values are expected to be valid choice keys already and stay
// the same
array('', '', '0', ''),
array('0', false, '1', false),
array('X', 'X', '2', 'X'),
array('1', true, '3', null),
);
}
/**
* @dataProvider reverseTransformProvider
*/
public function testReverseTransform($in, $out, $inWithNull, $outWithNull)
{
$this->assertSame($out, $this->transformer->reverseTransform($in));
$this->assertSame($outWithNull, $this->transformerWithNull->reverseTransform($inWithNull));
}
public function reverseTransformExpectsStringOrNullProvider()
{
return array(
array(0),
array(true),
array(false),
array(array()),
);
}
/**
* @dataProvider reverseTransformExpectsStringOrNullProvider
* @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
*/
public function testReverseTransformExpectsStringOrNull($value)
{
$this->transformer->reverseTransform($value);
}
}

View File

@@ -0,0 +1,91 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Form\ChoiceList\ArrayChoiceList;
use Symfony\Component\Form\Extension\Core\DataTransformer\ChoicesToValuesTransformer;
class ChoicesToValuesTransformerTest extends TestCase
{
protected $transformer;
protected $transformerWithNull;
protected function setUp()
{
$list = new ArrayChoiceList(array('', false, 'X'));
$listWithNull = new ArrayChoiceList(array('', false, 'X', null));
$this->transformer = new ChoicesToValuesTransformer($list);
$this->transformerWithNull = new ChoicesToValuesTransformer($listWithNull);
}
protected function tearDown()
{
$this->transformer = null;
$this->transformerWithNull = null;
}
public function testTransform()
{
$in = array('', false, 'X');
$out = array('', '0', 'X');
$this->assertSame($out, $this->transformer->transform($in));
$in[] = null;
$outWithNull = array('0', '1', '2', '3');
$this->assertSame($outWithNull, $this->transformerWithNull->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', 'X');
$out = array('', false, 'X');
$this->assertSame($out, $this->transformer->reverseTransform($in));
// values are expected to be valid choices and stay the same
$inWithNull = array('0', '1', '2', '3');
$out[] = null;
$this->assertSame($out, $this->transformerWithNull->reverseTransform($inWithNull));
}
public function testReverseTransformNull()
{
$this->assertSame(array(), $this->transformer->reverseTransform(null));
$this->assertSame(array(), $this->transformerWithNull->reverseTransform(null));
}
/**
* @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
*/
public function testReverseTransformExpectsArray()
{
$this->transformer->reverseTransform('foobar');
}
}

View File

@@ -0,0 +1,54 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Form\Extension\Core\DataTransformer\DataTransformerChain;
class DataTransformerChainTest extends TestCase
{
public function testTransform()
{
$transformer1 = $this->getMockBuilder('Symfony\Component\Form\DataTransformerInterface')->getMock();
$transformer1->expects($this->once())
->method('transform')
->with($this->identicalTo('foo'))
->will($this->returnValue('bar'));
$transformer2 = $this->getMockBuilder('Symfony\Component\Form\DataTransformerInterface')->getMock();
$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->getMockBuilder('Symfony\Component\Form\DataTransformerInterface')->getMock();
$transformer2->expects($this->once())
->method('reverseTransform')
->with($this->identicalTo('foo'))
->will($this->returnValue('bar'));
$transformer1 = $this->getMockBuilder('Symfony\Component\Form\DataTransformerInterface')->getMock();
$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'));
}
}

View File

@@ -0,0 +1,22 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer;
use PHPUnit\Framework\TestCase;
abstract class DateIntervalTestCase extends TestCase
{
public static function assertDateIntervalEquals(\DateInterval $expected, \DateInterval $actual)
{
self::assertEquals($expected->format('%RP%yY%mM%dDT%hH%iM%sS'), $actual->format('%RP%yY%mM%dDT%hH%iM%sS'));
}
}

View File

@@ -0,0 +1,265 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer;
use Symfony\Component\Form\Extension\Core\DataTransformer\DateIntervalToArrayTransformer;
use Symfony\Component\Form\Exception\TransformationFailedException;
use Symfony\Component\Form\Exception\UnexpectedTypeException;
/**
* @author Steffen Roßkamp <steffen.rosskamp@gimmickmedia.de>
*/
class DateIntervalToArrayTransformerTest extends DateIntervalTestCase
{
public function testTransform()
{
$transformer = new DateIntervalToArrayTransformer();
$input = new \DateInterval('P1Y2M3DT4H5M6S');
$output = array(
'years' => '1',
'months' => '2',
'days' => '3',
'hours' => '4',
'minutes' => '5',
'seconds' => '6',
'invert' => false,
);
$this->assertSame($output, $transformer->transform($input));
}
public function testTransformEmpty()
{
$transformer = new DateIntervalToArrayTransformer();
$output = array(
'years' => '',
'months' => '',
'days' => '',
'hours' => '',
'minutes' => '',
'seconds' => '',
'invert' => false,
);
$this->assertSame($output, $transformer->transform(null));
}
public function testTransformEmptyWithFields()
{
$transformer = new DateIntervalToArrayTransformer(array('years', 'weeks', 'minutes', 'seconds'));
$output = array(
'years' => '',
'weeks' => '',
'minutes' => '',
'seconds' => '',
);
$this->assertSame($output, $transformer->transform(null));
}
public function testTransformWithFields()
{
$transformer = new DateIntervalToArrayTransformer(array('years', 'minutes', 'seconds'));
$input = new \DateInterval('P1Y2M3DT4H5M6S');
$output = array(
'years' => '1',
'minutes' => '5',
'seconds' => '6',
);
$this->assertSame($output, $transformer->transform($input));
}
public function testTransformWithWeek()
{
$transformer = new DateIntervalToArrayTransformer(array('weeks', 'minutes', 'seconds'));
$input = new \DateInterval('P1Y2M3WT4H5M6S');
$output = array(
'weeks' => '3',
'minutes' => '5',
'seconds' => '6',
);
$input = $transformer->transform($input);
ksort($input);
ksort($output);
$this->assertSame($output, $input);
}
public function testTransformDaysToWeeks()
{
$transformer = new DateIntervalToArrayTransformer(array('weeks', 'minutes', 'seconds'));
$input = new \DateInterval('P1Y2M23DT4H5M6S');
$output = array(
'weeks' => '3',
'minutes' => '5',
'seconds' => '6',
);
$input = $transformer->transform($input);
ksort($input);
ksort($output);
$this->assertSame($output, $input);
}
public function testTransformDaysNotOverflowingToWeeks()
{
$transformer = new DateIntervalToArrayTransformer(array('days', 'minutes', 'seconds'));
$input = new \DateInterval('P1Y2M23DT4H5M6S');
$output = array(
'days' => '23',
'minutes' => '5',
'seconds' => '6',
);
$this->assertSame($output, $transformer->transform($input));
}
public function testTransformWithInvert()
{
$transformer = new DateIntervalToArrayTransformer(array('years', 'invert'));
$input = new \DateInterval('P1Y');
$input->invert = 1;
$output = array(
'years' => '1',
'invert' => true,
);
$this->assertSame($output, $transformer->transform($input));
}
public function testTransformWithPadding()
{
$transformer = new DateIntervalToArrayTransformer(null, true);
$input = new \DateInterval('P1Y2M3DT4H5M6S');
$output = array(
'years' => '01',
'months' => '02',
'days' => '03',
'hours' => '04',
'minutes' => '05',
'seconds' => '06',
'invert' => false,
);
$this->assertSame($output, $transformer->transform($input));
}
public function testTransformWithFieldsAndPadding()
{
$transformer = new DateIntervalToArrayTransformer(array('years', 'minutes', 'seconds'), true);
$input = new \DateInterval('P1Y2M3DT4H5M6S');
$output = array(
'years' => '01',
'minutes' => '05',
'seconds' => '06',
);
$this->assertSame($output, $transformer->transform($input));
}
public function testReverseTransformRequiresDateTime()
{
$transformer = new DateIntervalToArrayTransformer();
$this->assertNull($transformer->reverseTransform(null));
$this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}(UnexpectedTypeException::class);
$transformer->reverseTransform('12345');
}
public function testReverseTransformWithUnsetFields()
{
$transformer = new DateIntervalToArrayTransformer();
$input = array('years' => '1');
$this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}(TransformationFailedException::class);
$transformer->reverseTransform($input);
}
public function testReverseTransformWithEmptyFields()
{
$transformer = new DateIntervalToArrayTransformer(array('years', 'minutes', 'seconds'));
$input = array(
'years' => '1',
'minutes' => '',
'seconds' => '6',
);
$this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}(TransformationFailedException::class, 'This amount of "minutes" is invalid');
$transformer->reverseTransform($input);
}
public function testReverseTransformWithWrongInvertType()
{
$transformer = new DateIntervalToArrayTransformer(array('invert'));
$input = array(
'invert' => '1',
);
$this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}(TransformationFailedException::class, 'The value of "invert" must be boolean');
$transformer->reverseTransform($input);
}
public function testReverseTransform()
{
$transformer = new DateIntervalToArrayTransformer();
$input = array(
'years' => '1',
'months' => '2',
'days' => '3',
'hours' => '4',
'minutes' => '5',
'seconds' => '6',
'invert' => false,
);
$output = new \DateInterval('P01Y02M03DT04H05M06S');
$this->assertDateIntervalEquals($output, $transformer->reverseTransform($input));
}
public function testReverseTransformWithWeek()
{
$transformer = new DateIntervalToArrayTransformer(
array('years', 'months', 'weeks', 'hours', 'minutes', 'seconds')
);
$input = array(
'years' => '1',
'months' => '2',
'weeks' => '3',
'hours' => '4',
'minutes' => '5',
'seconds' => '6',
);
$output = new \DateInterval('P1Y2M21DT4H5M6S');
$this->assertDateIntervalEquals($output, $transformer->reverseTransform($input));
}
public function testReverseTransformWithFields()
{
$transformer = new DateIntervalToArrayTransformer(array('years', 'minutes', 'seconds'));
$input = array(
'years' => '1',
'minutes' => '5',
'seconds' => '6',
);
$output = new \DateInterval('P1Y0M0DT0H5M6S');
$this->assertDateIntervalEquals($output, $transformer->reverseTransform($input));
}
public function testBothTransformsWithWeek()
{
$transformer = new DateIntervalToArrayTransformer(
array('years', 'months', 'weeks', 'hours', 'minutes', 'seconds')
);
$interval = new \DateInterval('P1Y2M21DT4H5M6S');
$array = array(
'years' => '1',
'months' => '2',
'weeks' => '3',
'hours' => '4',
'minutes' => '5',
'seconds' => '6',
);
$input = $transformer->transform($interval);
ksort($input);
ksort($array);
$this->assertSame($array, $input);
$interval = new \DateInterval('P1Y2M0DT4H5M6S');
$input['weeks'] = '0';
$this->assertDateIntervalEquals($interval, $transformer->reverseTransform($input));
}
}

View File

@@ -0,0 +1,122 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer;
use Symfony\Component\Form\Extension\Core\DataTransformer\DateIntervalToStringTransformer;
use Symfony\Component\Form\Exception\TransformationFailedException;
use Symfony\Component\Form\Exception\UnexpectedTypeException;
/**
* @author Steffen Roßkamp <steffen.rosskamp@gimmickmedia.de>
*/
class DateIntervalToStringTransformerTest extends DateIntervalTestCase
{
public function dataProviderISO()
{
$data = array(
array('P%YY%MM%DDT%HH%IM%SS', 'P00Y00M00DT00H00M00S', 'PT0S'),
array('P%yY%mM%dDT%hH%iM%sS', 'P0Y0M0DT0H0M0S', 'PT0S'),
array('P%yY%mM%dDT%hH%iM%sS', 'P10Y2M3DT16H5M6S', 'P10Y2M3DT16H5M6S'),
array('P%yY%mM%dDT%hH%iM', 'P10Y2M3DT16H5M', 'P10Y2M3DT16H5M'),
array('P%yY%mM%dDT%hH', 'P10Y2M3DT16H', 'P10Y2M3DT16H'),
array('P%yY%mM%dD', 'P10Y2M3D', 'P10Y2M3DT0H'),
);
return $data;
}
public function dataProviderDate()
{
$data = array(
array(
'%y years %m months %d days %h hours %i minutes %s seconds',
'10 years 2 months 3 days 16 hours 5 minutes 6 seconds',
'P10Y2M3DT16H5M6S',
),
array(
'%y years %m months %d days %h hours %i minutes',
'10 years 2 months 3 days 16 hours 5 minutes',
'P10Y2M3DT16H5M',
),
array('%y years %m months %d days %h hours', '10 years 2 months 3 days 16 hours', 'P10Y2M3DT16H'),
array('%y years %m months %d days', '10 years 2 months 3 days', 'P10Y2M3D'),
array('%y years %m months', '10 years 2 months', 'P10Y2M'),
array('%y year', '1 year', 'P1Y'),
);
return $data;
}
/**
* @dataProvider dataProviderISO
*/
public function testTransform($format, $output, $input)
{
$transformer = new DateIntervalToStringTransformer($format);
$input = new \DateInterval($input);
$this->assertEquals($output, $transformer->transform($input));
}
public function testTransformEmpty()
{
$transformer = new DateIntervalToStringTransformer();
$this->assertSame('', $transformer->transform(null));
}
public function testTransformExpectsDateTime()
{
$transformer = new DateIntervalToStringTransformer();
$this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}(UnexpectedTypeException::class);
$transformer->transform('1234');
}
/**
* @dataProvider dataProviderISO
*/
public function testReverseTransform($format, $input, $output)
{
$reverseTransformer = new DateIntervalToStringTransformer($format, true);
$interval = new \DateInterval($output);
$this->assertDateIntervalEquals($interval, $reverseTransformer->reverseTransform($input));
}
/**
* @dataProvider dataProviderDate
*/
public function testReverseTransformDateString($format, $input, $output)
{
$reverseTransformer = new DateIntervalToStringTransformer($format, true);
$interval = new \DateInterval($output);
$this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}(TransformationFailedException::class);
$this->assertDateIntervalEquals($interval, $reverseTransformer->reverseTransform($input));
}
public function testReverseTransformEmpty()
{
$reverseTransformer = new DateIntervalToStringTransformer();
$this->assertNull($reverseTransformer->reverseTransform(''));
}
public function testReverseTransformExpectsString()
{
$reverseTransformer = new DateIntervalToStringTransformer();
$this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}(UnexpectedTypeException::class);
$reverseTransformer->reverseTransform(1234);
}
public function testReverseTransformExpectsValidIntervalString()
{
$reverseTransformer = new DateIntervalToStringTransformer();
$this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}(TransformationFailedException::class);
$reverseTransformer->reverseTransform('10Y');
}
}

View File

@@ -0,0 +1,22 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer;
use PHPUnit\Framework\TestCase;
abstract class DateTimeTestCase extends TestCase
{
public static function assertDateTimeEquals(\DateTime $expected, \DateTime $actual)
{
self::assertEquals($expected->format('U'), $actual->format('U'));
}
}

View File

@@ -0,0 +1,580 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\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));
}
public function testTransformDateTimeImmutable()
{
$transformer = new DateTimeToArrayTransformer('America/New_York', 'Asia/Hong_Kong');
$input = new \DateTimeImmutable('2010-02-03 04:05:06 America/New_York');
$dateTime = new \DateTimeImmutable('2010-02-03 04:05:06 America/New_York');
$dateTime = $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',
));
}
/**
* @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
*/
public function testReverseTransformWithEmptyStringHour()
{
$transformer = new DateTimeToArrayTransformer();
$transformer->reverseTransform(array(
'year' => '2010',
'month' => '2',
'day' => '31',
'hour' => '',
'minute' => '5',
'second' => '6',
));
}
/**
* @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
*/
public function testReverseTransformWithEmptyStringMinute()
{
$transformer = new DateTimeToArrayTransformer();
$transformer->reverseTransform(array(
'year' => '2010',
'month' => '2',
'day' => '31',
'hour' => '4',
'minute' => '',
'second' => '6',
));
}
/**
* @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
*/
public function testReverseTransformWithEmptyStringSecond()
{
$transformer = new DateTimeToArrayTransformer();
$transformer->reverseTransform(array(
'year' => '2010',
'month' => '2',
'day' => '31',
'hour' => '4',
'minute' => '5',
'second' => '',
));
}
}

View File

@@ -0,0 +1,343 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\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, '57.1');
\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, '3. Februar 2010 um 04:05', '2010-02-03 04:05:00 UTC'),
array(\IntlDateFormatter::FULL, null, null, 'Mittwoch, 3. Februar 2010 um 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, '3. Februar 2010', '2010-02-03 00:00:00 UTC'),
array(\IntlDateFormatter::FULL, \IntlDateFormatter::NONE, null, 'Mittwoch, 3. 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 UTC', '2010-02-03 04:05:06 UTC'),
array(null, \IntlDateFormatter::LONG, null, '03.02.2010, 04:05:06 UTC', '2010-02-03 04:05:06 GMT'),
// 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 UTC', '1970-01-01 04:05:06 GMT'),
array(\IntlDateFormatter::NONE, \IntlDateFormatter::LONG, null, '04:05:06 UTC', '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)
{
IntlTestHelper::requireFullIntl($this, '59.1');
\Locale::setDefault('de_AT');
$transformer = new DateTimeToLocalizedStringTransformer(
'UTC',
'UTC',
$dateFormat,
$timeFormat,
\IntlDateFormatter::GREGORIAN,
$pattern
);
$input = new \DateTime($input);
$this->assertEquals($output, $transformer->transform($input));
}
public function testTransformFullTime()
{
IntlTestHelper::requireFullIntl($this, '59.1');
\Locale::setDefault('de_AT');
$transformer = new DateTimeToLocalizedStringTransformer('UTC', 'UTC', null, \IntlDateFormatter::FULL);
$this->assertEquals('03.02.2010, 04:05:06 Koordinierte Weltzeit', $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 testReverseTransformWithNoConstructorParameters()
{
$tz = date_default_timezone_get();
date_default_timezone_set('Europe/Rome');
$transformer = new DateTimeToLocalizedStringTransformer();
$dateTime = new \DateTime('2010-02-03 04:05');
$this->assertEquals(
$dateTime->format('c'),
$transformer->reverseTransform('03.02.2010, 04:05')->format('c')
);
date_default_timezone_set($tz);
}
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));
}
public function testTransformDateTimeImmutableTimezones()
{
$transformer = new DateTimeToLocalizedStringTransformer('America/New_York', 'Asia/Hong_Kong');
$input = new \DateTimeImmutable('2010-02-03 04:05:06 America/New_York');
$dateTime = clone $input;
$dateTime = $dateTime->setTimezone(new \DateTimeZone('Asia/Hong_Kong'));
$this->assertEquals($dateTime->format('d.m.Y, H:i'), $transformer->transform($input));
}
/**
* @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
*/
public function testTransformRequiresValidDateTime()
{
$transformer = new DateTimeToLocalizedStringTransformer();
$transformer->transform('2010-01-01');
}
public function testTransformWrapsIntlErrors()
{
$transformer = new DateTimeToLocalizedStringTransformer();
$this->markTestIncomplete('Checking for intl errors needs to be reimplemented');
// HOW TO REPRODUCE?
//$this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}('Symfony\Component\Form\Extension\Core\DataTransformer\TransformationFailedException');
//$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 testReverseTransformOnlyDateWithDifferentTimezones()
{
$transformer = new DateTimeToLocalizedStringTransformer('Europe/Berlin', 'Pacific/Tahiti', \IntlDateFormatter::FULL, \IntlDateFormatter::FULL, \IntlDateFormatter::GREGORIAN, 'yyyy-MM-dd');
$dateTime = new \DateTime('2017-01-10 11:00', new \DateTimeZone('Europe/Berlin'));
$this->assertDateTimeEquals($dateTime, $transformer->reverseTransform('2017-01-10'));
}
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 testReverseTransformDateOnlyWithDstIssue()
{
$transformer = new DateTimeToLocalizedStringTransformer('Europe/Rome', 'Europe/Rome', \IntlDateFormatter::FULL, \IntlDateFormatter::FULL, \IntlDateFormatter::GREGORIAN, 'dd/MM/yyyy');
$this->assertDateTimeEquals(
new \DateTime('1978-05-28', new \DateTimeZone('Europe/Rome')),
$transformer->reverseTransform('28/05/1978')
);
}
public function testReverseTransformDateOnlyWithDstIssueAndEscapedText()
{
$transformer = new DateTimeToLocalizedStringTransformer('Europe/Rome', 'Europe/Rome', \IntlDateFormatter::FULL, \IntlDateFormatter::FULL, \IntlDateFormatter::GREGORIAN, "'day': dd 'month': MM 'year': yyyy");
$this->assertDateTimeEquals(
new \DateTime('1978-05-28', new \DateTimeZone('Europe/Rome')),
$transformer->reverseTransform('day: 28 month: 05 year: 1978')
);
}
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');
}
}

View File

@@ -0,0 +1,143 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\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'),
array('Europe/Amsterdam', 'Europe/Amsterdam', '2013-08-21 10:30:00 Europe/Amsterdam', '2013-08-21T08:30:00Z'),
));
}
/**
* @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));
}
/**
* @dataProvider transformProvider
*/
public function testTransformDateTimeImmutable($fromTz, $toTz, $from, $to)
{
$transformer = new DateTimeToRfc3339Transformer($fromTz, $toTz);
$this->assertSame($to, $transformer->transform(null !== $from ? new \DateTimeImmutable($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');
}
}

View File

@@ -0,0 +1,174 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\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'),
array('Y-z', '2010-33', '2010-02-03 00: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'),
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 testTransformDateTimeImmutable()
{
$transformer = new DateTimeToStringTransformer('Asia/Hong_Kong', 'America/New_York', 'Y-m-d H:i:s');
$input = new \DateTimeImmutable('2010-02-03 12:05:06 America/New_York');
$output = $input->format('Y-m-d H:i:s');
$input = $input->setTimezone(new \DateTimeZone('Asia/Hong_Kong'));
$this->assertEquals($output, $transformer->transform($input));
}
public function testTransformExpectsDateTime()
{
$transformer = new DateTimeToStringTransformer();
$this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}('Symfony\Component\Form\Exception\TransformationFailedException');
$transformer->transform('1234');
}
/**
* @dataProvider dataProvider
*/
public function testReverseTransform($format, $input, $output)
{
$reverseTransformer = new DateTimeToStringTransformer('UTC', 'UTC', $format);
$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->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}('Symfony\Component\Form\Exception\TransformationFailedException');
$reverseTransformer->reverseTransform(1234);
}
public function testReverseTransformExpectsValidDateString()
{
$reverseTransformer = new DateTimeToStringTransformer();
$this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}('Symfony\Component\Form\Exception\TransformationFailedException');
$reverseTransformer->reverseTransform('2010-2010-2010');
}
public function testReverseTransformWithNonExistingDate()
{
$reverseTransformer = new DateTimeToStringTransformer();
$this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}('Symfony\Component\Form\Exception\TransformationFailedException');
$reverseTransformer->reverseTransform('2010-04-31');
}
}

View File

@@ -0,0 +1,115 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\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 testTransformDateTimeImmutable()
{
$transformer = new DateTimeToTimestampTransformer('Asia/Hong_Kong', 'America/New_York');
$input = new \DateTimeImmutable('2010-02-03 04:05:06 America/New_York');
$output = $input->format('U');
$input = $input->setTimezone(new \DateTimeZone('Asia/Hong_Kong'));
$this->assertEquals($output, $transformer->transform($input));
}
public function testTransformExpectsDateTime()
{
$transformer = new DateTimeToTimestampTransformer();
$this->{method_exists($this, $_ = 'expectException') ? $_ : '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->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}('Symfony\Component\Form\Exception\TransformationFailedException');
$reverseTransformer->reverseTransform('2010-2010-2010');
}
}

View File

@@ -0,0 +1,245 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Form\Extension\Core\DataTransformer\IntegerToLocalizedStringTransformer;
use Symfony\Component\Intl\Util\IntlTestHelper;
class IntegerToLocalizedStringTransformerTest extends TestCase
{
protected function setUp()
{
parent::setUp();
\Locale::setDefault('en');
}
public function transformWithRoundingProvider()
{
return array(
// towards positive infinity (1.6 -> 2, -1.6 -> -1)
array(1234.5, '1235', IntegerToLocalizedStringTransformer::ROUND_CEILING),
array(1234.4, '1235', IntegerToLocalizedStringTransformer::ROUND_CEILING),
array(-1234.5, '-1234', IntegerToLocalizedStringTransformer::ROUND_CEILING),
array(-1234.4, '-1234', IntegerToLocalizedStringTransformer::ROUND_CEILING),
// towards negative infinity (1.6 -> 1, -1.6 -> -2)
array(1234.5, '1234', IntegerToLocalizedStringTransformer::ROUND_FLOOR),
array(1234.4, '1234', IntegerToLocalizedStringTransformer::ROUND_FLOOR),
array(-1234.5, '-1235', IntegerToLocalizedStringTransformer::ROUND_FLOOR),
array(-1234.4, '-1235', IntegerToLocalizedStringTransformer::ROUND_FLOOR),
// away from zero (1.6 -> 2, -1.6 -> 2)
array(1234.5, '1235', IntegerToLocalizedStringTransformer::ROUND_UP),
array(1234.4, '1235', IntegerToLocalizedStringTransformer::ROUND_UP),
array(-1234.5, '-1235', IntegerToLocalizedStringTransformer::ROUND_UP),
array(-1234.4, '-1235', IntegerToLocalizedStringTransformer::ROUND_UP),
// towards zero (1.6 -> 1, -1.6 -> -1)
array(1234.5, '1234', IntegerToLocalizedStringTransformer::ROUND_DOWN),
array(1234.4, '1234', IntegerToLocalizedStringTransformer::ROUND_DOWN),
array(-1234.5, '-1234', IntegerToLocalizedStringTransformer::ROUND_DOWN),
array(-1234.4, '-1234', IntegerToLocalizedStringTransformer::ROUND_DOWN),
// round halves (.5) to the next even number
array(1234.6, '1235', IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN),
array(1234.5, '1234', IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN),
array(1234.4, '1234', IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN),
array(1233.5, '1234', IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN),
array(1232.5, '1232', IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN),
array(-1234.6, '-1235', IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN),
array(-1234.5, '-1234', IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN),
array(-1234.4, '-1234', IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN),
array(-1233.5, '-1234', IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN),
array(-1232.5, '-1232', IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN),
// round halves (.5) away from zero
array(1234.6, '1235', IntegerToLocalizedStringTransformer::ROUND_HALF_UP),
array(1234.5, '1235', IntegerToLocalizedStringTransformer::ROUND_HALF_UP),
array(1234.4, '1234', IntegerToLocalizedStringTransformer::ROUND_HALF_UP),
array(-1234.6, '-1235', IntegerToLocalizedStringTransformer::ROUND_HALF_UP),
array(-1234.5, '-1235', IntegerToLocalizedStringTransformer::ROUND_HALF_UP),
array(-1234.4, '-1234', IntegerToLocalizedStringTransformer::ROUND_HALF_UP),
// round halves (.5) towards zero
array(1234.6, '1235', IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN),
array(1234.5, '1234', IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN),
array(1234.4, '1234', IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN),
array(-1234.6, '-1235', IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN),
array(-1234.5, '-1234', IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN),
array(-1234.4, '-1234', IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN),
);
}
/**
* @dataProvider transformWithRoundingProvider
*/
public function testTransformWithRounding($input, $output, $roundingMode)
{
$transformer = new IntegerToLocalizedStringTransformer(null, null, $roundingMode);
$this->assertEquals($output, $transformer->transform($input));
}
public function testReverseTransform()
{
// Since we test against "de_AT", we need the full implementation
IntlTestHelper::requireFullIntl($this, false);
\Locale::setDefault('de_AT');
$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()
{
// Since we test against "de_DE", we need the full implementation
IntlTestHelper::requireFullIntl($this, false);
\Locale::setDefault('de_DE');
$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'));
}
public function reverseTransformWithRoundingProvider()
{
return array(
// towards positive infinity (1.6 -> 2, -1.6 -> -1)
array('1234,5', 1235, IntegerToLocalizedStringTransformer::ROUND_CEILING),
array('1234,4', 1235, IntegerToLocalizedStringTransformer::ROUND_CEILING),
array('-1234,5', -1234, IntegerToLocalizedStringTransformer::ROUND_CEILING),
array('-1234,4', -1234, IntegerToLocalizedStringTransformer::ROUND_CEILING),
// towards negative infinity (1.6 -> 1, -1.6 -> -2)
array('1234,5', 1234, IntegerToLocalizedStringTransformer::ROUND_FLOOR),
array('1234,4', 1234, IntegerToLocalizedStringTransformer::ROUND_FLOOR),
array('-1234,5', -1235, IntegerToLocalizedStringTransformer::ROUND_FLOOR),
array('-1234,4', -1235, IntegerToLocalizedStringTransformer::ROUND_FLOOR),
// away from zero (1.6 -> 2, -1.6 -> 2)
array('1234,5', 1235, IntegerToLocalizedStringTransformer::ROUND_UP),
array('1234,4', 1235, IntegerToLocalizedStringTransformer::ROUND_UP),
array('-1234,5', -1235, IntegerToLocalizedStringTransformer::ROUND_UP),
array('-1234,4', -1235, IntegerToLocalizedStringTransformer::ROUND_UP),
// towards zero (1.6 -> 1, -1.6 -> -1)
array('1234,5', 1234, IntegerToLocalizedStringTransformer::ROUND_DOWN),
array('1234,4', 1234, IntegerToLocalizedStringTransformer::ROUND_DOWN),
array('-1234,5', -1234, IntegerToLocalizedStringTransformer::ROUND_DOWN),
array('-1234,4', -1234, IntegerToLocalizedStringTransformer::ROUND_DOWN),
// round halves (.5) to the next even number
array('1234,6', 1235, IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN),
array('1234,5', 1234, IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN),
array('1234,4', 1234, IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN),
array('1233,5', 1234, IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN),
array('1232,5', 1232, IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN),
array('-1234,6', -1235, IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN),
array('-1234,5', -1234, IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN),
array('-1234,4', -1234, IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN),
array('-1233,5', -1234, IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN),
array('-1232,5', -1232, IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN),
// round halves (.5) away from zero
array('1234,6', 1235, IntegerToLocalizedStringTransformer::ROUND_HALF_UP),
array('1234,5', 1235, IntegerToLocalizedStringTransformer::ROUND_HALF_UP),
array('1234,4', 1234, IntegerToLocalizedStringTransformer::ROUND_HALF_UP),
array('-1234,6', -1235, IntegerToLocalizedStringTransformer::ROUND_HALF_UP),
array('-1234,5', -1235, IntegerToLocalizedStringTransformer::ROUND_HALF_UP),
array('-1234,4', -1234, IntegerToLocalizedStringTransformer::ROUND_HALF_UP),
// round halves (.5) towards zero
array('1234,6', 1235, IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN),
array('1234,5', 1234, IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN),
array('1234,4', 1234, IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN),
array('-1234,6', -1235, IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN),
array('-1234,5', -1234, IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN),
array('-1234,4', -1234, IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN),
);
}
/**
* @dataProvider reverseTransformWithRoundingProvider
*/
public function testReverseTransformWithRounding($input, $output, $roundingMode)
{
$transformer = new IntegerToLocalizedStringTransformer(null, null, $roundingMode);
$this->assertEquals($output, $transformer->reverseTransform($input));
}
/**
* @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('-∞');
}
}

View File

@@ -0,0 +1,75 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Form\Extension\Core\DataTransformer\MoneyToLocalizedStringTransformer;
use Symfony\Component\Intl\Util\IntlTestHelper;
class MoneyToLocalizedStringTransformerTest extends TestCase
{
public function testTransform()
{
// Since we test against "de_AT", we need the full implementation
IntlTestHelper::requireFullIntl($this, false);
\Locale::setDefault('de_AT');
$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->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}('Symfony\Component\Form\Exception\TransformationFailedException');
$transformer->transform('abcd');
}
public function testTransformEmpty()
{
$transformer = new MoneyToLocalizedStringTransformer();
$this->assertSame('', $transformer->transform(null));
}
public function testReverseTransform()
{
// Since we test against "de_AT", we need the full implementation
IntlTestHelper::requireFullIntl($this, false);
\Locale::setDefault('de_AT');
$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->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}('Symfony\Component\Form\Exception\TransformationFailedException');
$transformer->reverseTransform(12345);
}
public function testReverseTransformEmpty()
{
$transformer = new MoneyToLocalizedStringTransformer();
$this->assertNull($transformer->reverseTransform(''));
}
}

View File

@@ -0,0 +1,660 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Form\Extension\Core\DataTransformer\NumberToLocalizedStringTransformer;
use Symfony\Component\Intl\Util\IntlTestHelper;
class NumberToLocalizedStringTransformerTest extends TestCase
{
protected function setUp()
{
parent::setUp();
\Locale::setDefault('en');
}
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)
{
// Since we test against other locales, we need the full implementation
IntlTestHelper::requireFullIntl($this, false);
\Locale::setDefault($locale);
$transformer = new NumberToLocalizedStringTransformer();
$this->assertSame($to, $transformer->transform($from));
}
public function provideTransformationsWithGrouping()
{
return array(
array(1234.5, '1.234,5', 'de_DE'),
array(12345.912, '12.345,912', 'de_DE'),
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)
{
// Since we test against other locales, we need the full implementation
IntlTestHelper::requireFullIntl($this, false);
\Locale::setDefault($locale);
$transformer = new NumberToLocalizedStringTransformer(null, true);
$this->assertSame($to, $transformer->transform($from));
}
public function testTransformWithScale()
{
// Since we test against "de_AT", we need the full implementation
IntlTestHelper::requireFullIntl($this, false);
\Locale::setDefault('de_AT');
$transformer = new NumberToLocalizedStringTransformer(2);
$this->assertEquals('1234,50', $transformer->transform(1234.5));
$this->assertEquals('678,92', $transformer->transform(678.916));
}
public function transformWithRoundingProvider()
{
return array(
// towards positive infinity (1.6 -> 2, -1.6 -> -1)
array(0, 1234.5, '1235', NumberToLocalizedStringTransformer::ROUND_CEILING),
array(0, 1234.4, '1235', NumberToLocalizedStringTransformer::ROUND_CEILING),
array(0, -1234.5, '-1234', NumberToLocalizedStringTransformer::ROUND_CEILING),
array(0, -1234.4, '-1234', NumberToLocalizedStringTransformer::ROUND_CEILING),
array(1, 123.45, '123,5', NumberToLocalizedStringTransformer::ROUND_CEILING),
array(1, 123.44, '123,5', NumberToLocalizedStringTransformer::ROUND_CEILING),
array(1, -123.45, '-123,4', NumberToLocalizedStringTransformer::ROUND_CEILING),
array(1, -123.44, '-123,4', NumberToLocalizedStringTransformer::ROUND_CEILING),
// towards negative infinity (1.6 -> 1, -1.6 -> -2)
array(0, 1234.5, '1234', NumberToLocalizedStringTransformer::ROUND_FLOOR),
array(0, 1234.4, '1234', NumberToLocalizedStringTransformer::ROUND_FLOOR),
array(0, -1234.5, '-1235', NumberToLocalizedStringTransformer::ROUND_FLOOR),
array(0, -1234.4, '-1235', NumberToLocalizedStringTransformer::ROUND_FLOOR),
array(1, 123.45, '123,4', NumberToLocalizedStringTransformer::ROUND_FLOOR),
array(1, 123.44, '123,4', NumberToLocalizedStringTransformer::ROUND_FLOOR),
array(1, -123.45, '-123,5', NumberToLocalizedStringTransformer::ROUND_FLOOR),
array(1, -123.44, '-123,5', NumberToLocalizedStringTransformer::ROUND_FLOOR),
// away from zero (1.6 -> 2, -1.6 -> 2)
array(0, 1234.5, '1235', NumberToLocalizedStringTransformer::ROUND_UP),
array(0, 1234.4, '1235', NumberToLocalizedStringTransformer::ROUND_UP),
array(0, -1234.5, '-1235', NumberToLocalizedStringTransformer::ROUND_UP),
array(0, -1234.4, '-1235', NumberToLocalizedStringTransformer::ROUND_UP),
array(1, 123.45, '123,5', NumberToLocalizedStringTransformer::ROUND_UP),
array(1, 123.44, '123,5', NumberToLocalizedStringTransformer::ROUND_UP),
array(1, -123.45, '-123,5', NumberToLocalizedStringTransformer::ROUND_UP),
array(1, -123.44, '-123,5', NumberToLocalizedStringTransformer::ROUND_UP),
// towards zero (1.6 -> 1, -1.6 -> -1)
array(0, 1234.5, '1234', NumberToLocalizedStringTransformer::ROUND_DOWN),
array(0, 1234.4, '1234', NumberToLocalizedStringTransformer::ROUND_DOWN),
array(0, -1234.5, '-1234', NumberToLocalizedStringTransformer::ROUND_DOWN),
array(0, -1234.4, '-1234', NumberToLocalizedStringTransformer::ROUND_DOWN),
array(1, 123.45, '123,4', NumberToLocalizedStringTransformer::ROUND_DOWN),
array(1, 123.44, '123,4', NumberToLocalizedStringTransformer::ROUND_DOWN),
array(1, -123.45, '-123,4', NumberToLocalizedStringTransformer::ROUND_DOWN),
array(1, -123.44, '-123,4', NumberToLocalizedStringTransformer::ROUND_DOWN),
// round halves (.5) to the next even number
array(0, 1234.6, '1235', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
array(0, 1234.5, '1234', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
array(0, 1234.4, '1234', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
array(0, 1233.5, '1234', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
array(0, 1232.5, '1232', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
array(0, -1234.6, '-1235', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
array(0, -1234.5, '-1234', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
array(0, -1234.4, '-1234', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
array(0, -1233.5, '-1234', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
array(0, -1232.5, '-1232', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
array(1, 123.46, '123,5', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
array(1, 123.45, '123,4', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
array(1, 123.44, '123,4', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
array(1, 123.35, '123,4', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
array(1, 123.25, '123,2', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
array(1, -123.46, '-123,5', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
array(1, -123.45, '-123,4', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
array(1, -123.44, '-123,4', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
array(1, -123.35, '-123,4', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
array(1, -123.25, '-123,2', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
// round halves (.5) away from zero
array(0, 1234.6, '1235', NumberToLocalizedStringTransformer::ROUND_HALF_UP),
array(0, 1234.5, '1235', NumberToLocalizedStringTransformer::ROUND_HALF_UP),
array(0, 1234.4, '1234', NumberToLocalizedStringTransformer::ROUND_HALF_UP),
array(0, -1234.6, '-1235', NumberToLocalizedStringTransformer::ROUND_HALF_UP),
array(0, -1234.5, '-1235', NumberToLocalizedStringTransformer::ROUND_HALF_UP),
array(0, -1234.4, '-1234', NumberToLocalizedStringTransformer::ROUND_HALF_UP),
array(1, 123.46, '123,5', NumberToLocalizedStringTransformer::ROUND_HALF_UP),
array(1, 123.45, '123,5', NumberToLocalizedStringTransformer::ROUND_HALF_UP),
array(1, 123.44, '123,4', NumberToLocalizedStringTransformer::ROUND_HALF_UP),
array(1, -123.46, '-123,5', NumberToLocalizedStringTransformer::ROUND_HALF_UP),
array(1, -123.45, '-123,5', NumberToLocalizedStringTransformer::ROUND_HALF_UP),
array(1, -123.44, '-123,4', NumberToLocalizedStringTransformer::ROUND_HALF_UP),
// round halves (.5) towards zero
array(0, 1234.6, '1235', NumberToLocalizedStringTransformer::ROUND_HALF_DOWN),
array(0, 1234.5, '1234', NumberToLocalizedStringTransformer::ROUND_HALF_DOWN),
array(0, 1234.4, '1234', NumberToLocalizedStringTransformer::ROUND_HALF_DOWN),
array(0, -1234.6, '-1235', NumberToLocalizedStringTransformer::ROUND_HALF_DOWN),
array(0, -1234.5, '-1234', NumberToLocalizedStringTransformer::ROUND_HALF_DOWN),
array(0, -1234.4, '-1234', NumberToLocalizedStringTransformer::ROUND_HALF_DOWN),
array(1, 123.46, '123,5', NumberToLocalizedStringTransformer::ROUND_HALF_DOWN),
array(1, 123.45, '123,4', NumberToLocalizedStringTransformer::ROUND_HALF_DOWN),
array(1, 123.44, '123,4', NumberToLocalizedStringTransformer::ROUND_HALF_DOWN),
array(1, -123.46, '-123,5', NumberToLocalizedStringTransformer::ROUND_HALF_DOWN),
array(1, -123.45, '-123,4', NumberToLocalizedStringTransformer::ROUND_HALF_DOWN),
array(1, -123.44, '-123,4', NumberToLocalizedStringTransformer::ROUND_HALF_DOWN),
);
}
/**
* @dataProvider transformWithRoundingProvider
*/
public function testTransformWithRounding($scale, $input, $output, $roundingMode)
{
// Since we test against "de_AT", we need the full implementation
IntlTestHelper::requireFullIntl($this, false);
\Locale::setDefault('de_AT');
$transformer = new NumberToLocalizedStringTransformer($scale, null, $roundingMode);
$this->assertEquals($output, $transformer->transform($input));
}
public function testTransformDoesNotRoundIfNoScale()
{
// Since we test against "de_AT", we need the full implementation
IntlTestHelper::requireFullIntl($this, false);
\Locale::setDefault('de_AT');
$transformer = new NumberToLocalizedStringTransformer(null, null, NumberToLocalizedStringTransformer::ROUND_DOWN);
$this->assertEquals('1234,547', $transformer->transform(1234.547));
}
/**
* @dataProvider provideTransformations
*/
public function testReverseTransform($to, $from, $locale)
{
// Since we test against other locales, we need the full implementation
IntlTestHelper::requireFullIntl($this, false);
\Locale::setDefault($locale);
$transformer = new NumberToLocalizedStringTransformer();
$this->assertEquals($to, $transformer->reverseTransform($from));
}
/**
* @dataProvider provideTransformationsWithGrouping
*/
public function testReverseTransformWithGrouping($to, $from, $locale)
{
// Since we test against other locales, we need the full implementation
IntlTestHelper::requireFullIntl($this, '4.8.1.1');
\Locale::setDefault($locale);
$transformer = new NumberToLocalizedStringTransformer(null, true);
$this->assertEquals($to, $transformer->reverseTransform($from));
}
/**
* @see https://github.com/symfony/symfony/issues/7609
*/
public function testReverseTransformWithGroupingAndFixedSpaces()
{
// Since we test against other locales, we need the full implementation
IntlTestHelper::requireFullIntl($this, false);
\Locale::setDefault('ru');
$transformer = new NumberToLocalizedStringTransformer(null, true);
$this->assertEquals(1234.5, $transformer->reverseTransform("1\xc2\xa0234,5"));
}
public function testReverseTransformWithGroupingButWithoutGroupSeparator()
{
// Since we test against "de_AT", we need the full implementation
IntlTestHelper::requireFullIntl($this, false);
\Locale::setDefault('de_AT');
$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 reverseTransformWithRoundingProvider()
{
return array(
// towards positive infinity (1.6 -> 2, -1.6 -> -1)
array(0, '1234,5', 1235, NumberToLocalizedStringTransformer::ROUND_CEILING),
array(0, '1234,4', 1235, NumberToLocalizedStringTransformer::ROUND_CEILING),
array(0, '-1234,5', -1234, NumberToLocalizedStringTransformer::ROUND_CEILING),
array(0, '-1234,4', -1234, NumberToLocalizedStringTransformer::ROUND_CEILING),
array(1, '123,45', 123.5, NumberToLocalizedStringTransformer::ROUND_CEILING),
array(1, '123,44', 123.5, NumberToLocalizedStringTransformer::ROUND_CEILING),
array(1, '-123,45', -123.4, NumberToLocalizedStringTransformer::ROUND_CEILING),
array(1, '-123,44', -123.4, NumberToLocalizedStringTransformer::ROUND_CEILING),
// towards negative infinity (1.6 -> 1, -1.6 -> -2)
array(0, '1234,5', 1234, NumberToLocalizedStringTransformer::ROUND_FLOOR),
array(0, '1234,4', 1234, NumberToLocalizedStringTransformer::ROUND_FLOOR),
array(0, '-1234,5', -1235, NumberToLocalizedStringTransformer::ROUND_FLOOR),
array(0, '-1234,4', -1235, NumberToLocalizedStringTransformer::ROUND_FLOOR),
array(1, '123,45', 123.4, NumberToLocalizedStringTransformer::ROUND_FLOOR),
array(1, '123,44', 123.4, NumberToLocalizedStringTransformer::ROUND_FLOOR),
array(1, '-123,45', -123.5, NumberToLocalizedStringTransformer::ROUND_FLOOR),
array(1, '-123,44', -123.5, NumberToLocalizedStringTransformer::ROUND_FLOOR),
// away from zero (1.6 -> 2, -1.6 -> 2)
array(0, '1234,5', 1235, NumberToLocalizedStringTransformer::ROUND_UP),
array(0, '1234,4', 1235, NumberToLocalizedStringTransformer::ROUND_UP),
array(0, '-1234,5', -1235, NumberToLocalizedStringTransformer::ROUND_UP),
array(0, '-1234,4', -1235, NumberToLocalizedStringTransformer::ROUND_UP),
array(1, '123,45', 123.5, NumberToLocalizedStringTransformer::ROUND_UP),
array(1, '123,44', 123.5, NumberToLocalizedStringTransformer::ROUND_UP),
array(1, '-123,45', -123.5, NumberToLocalizedStringTransformer::ROUND_UP),
array(1, '-123,44', -123.5, NumberToLocalizedStringTransformer::ROUND_UP),
// towards zero (1.6 -> 1, -1.6 -> -1)
array(0, '1234,5', 1234, NumberToLocalizedStringTransformer::ROUND_DOWN),
array(0, '1234,4', 1234, NumberToLocalizedStringTransformer::ROUND_DOWN),
array(0, '-1234,5', -1234, NumberToLocalizedStringTransformer::ROUND_DOWN),
array(0, '-1234,4', -1234, NumberToLocalizedStringTransformer::ROUND_DOWN),
array(1, '123,45', 123.4, NumberToLocalizedStringTransformer::ROUND_DOWN),
array(1, '123,44', 123.4, NumberToLocalizedStringTransformer::ROUND_DOWN),
array(1, '-123,45', -123.4, NumberToLocalizedStringTransformer::ROUND_DOWN),
array(1, '-123,44', -123.4, NumberToLocalizedStringTransformer::ROUND_DOWN),
array(2, '37.37', 37.37, NumberToLocalizedStringTransformer::ROUND_DOWN),
array(2, '2.01', 2.01, NumberToLocalizedStringTransformer::ROUND_DOWN),
// round halves (.5) to the next even number
array(0, '1234,6', 1235, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
array(0, '1234,5', 1234, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
array(0, '1234,4', 1234, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
array(0, '1233,5', 1234, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
array(0, '1232,5', 1232, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
array(0, '-1234,6', -1235, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
array(0, '-1234,5', -1234, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
array(0, '-1234,4', -1234, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
array(0, '-1233,5', -1234, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
array(0, '-1232,5', -1232, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
array(1, '123,46', 123.5, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
array(1, '123,45', 123.4, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
array(1, '123,44', 123.4, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
array(1, '123,35', 123.4, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
array(1, '123,25', 123.2, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
array(1, '-123,46', -123.5, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
array(1, '-123,45', -123.4, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
array(1, '-123,44', -123.4, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
array(1, '-123,35', -123.4, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
array(1, '-123,25', -123.2, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN),
// round halves (.5) away from zero
array(0, '1234,6', 1235, NumberToLocalizedStringTransformer::ROUND_HALF_UP),
array(0, '1234,5', 1235, NumberToLocalizedStringTransformer::ROUND_HALF_UP),
array(0, '1234,4', 1234, NumberToLocalizedStringTransformer::ROUND_HALF_UP),
array(0, '-1234,6', -1235, NumberToLocalizedStringTransformer::ROUND_HALF_UP),
array(0, '-1234,5', -1235, NumberToLocalizedStringTransformer::ROUND_HALF_UP),
array(0, '-1234,4', -1234, NumberToLocalizedStringTransformer::ROUND_HALF_UP),
array(1, '123,46', 123.5, NumberToLocalizedStringTransformer::ROUND_HALF_UP),
array(1, '123,45', 123.5, NumberToLocalizedStringTransformer::ROUND_HALF_UP),
array(1, '123,44', 123.4, NumberToLocalizedStringTransformer::ROUND_HALF_UP),
array(1, '-123,46', -123.5, NumberToLocalizedStringTransformer::ROUND_HALF_UP),
array(1, '-123,45', -123.5, NumberToLocalizedStringTransformer::ROUND_HALF_UP),
array(1, '-123,44', -123.4, NumberToLocalizedStringTransformer::ROUND_HALF_UP),
// round halves (.5) towards zero
array(0, '1234,6', 1235, NumberToLocalizedStringTransformer::ROUND_HALF_DOWN),
array(0, '1234,5', 1234, NumberToLocalizedStringTransformer::ROUND_HALF_DOWN),
array(0, '1234,4', 1234, NumberToLocalizedStringTransformer::ROUND_HALF_DOWN),
array(0, '-1234,6', -1235, NumberToLocalizedStringTransformer::ROUND_HALF_DOWN),
array(0, '-1234,5', -1234, NumberToLocalizedStringTransformer::ROUND_HALF_DOWN),
array(0, '-1234,4', -1234, NumberToLocalizedStringTransformer::ROUND_HALF_DOWN),
array(1, '123,46', 123.5, NumberToLocalizedStringTransformer::ROUND_HALF_DOWN),
array(1, '123,45', 123.4, NumberToLocalizedStringTransformer::ROUND_HALF_DOWN),
array(1, '123,44', 123.4, NumberToLocalizedStringTransformer::ROUND_HALF_DOWN),
array(1, '-123,46', -123.5, NumberToLocalizedStringTransformer::ROUND_HALF_DOWN),
array(1, '-123,45', -123.4, NumberToLocalizedStringTransformer::ROUND_HALF_DOWN),
array(1, '-123,44', -123.4, NumberToLocalizedStringTransformer::ROUND_HALF_DOWN),
);
}
/**
* @dataProvider reverseTransformWithRoundingProvider
*/
public function testReverseTransformWithRounding($scale, $input, $output, $roundingMode)
{
$transformer = new NumberToLocalizedStringTransformer($scale, null, $roundingMode);
$this->assertEquals($output, $transformer->reverseTransform($input));
}
public function testReverseTransformDoesNotRoundIfNoScale()
{
$transformer = new NumberToLocalizedStringTransformer(null, null, NumberToLocalizedStringTransformer::ROUND_DOWN);
$this->assertEquals(1234.547, $transformer->reverseTransform('1234,547'));
}
public function testDecimalSeparatorMayBeDotIfGroupingSeparatorIsNotDot()
{
// Since we test against other locales, we need the full implementation
IntlTestHelper::requireFullIntl($this, '4.8.1.1');
\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()
{
// Since we test against "de_DE", we need the full implementation
IntlTestHelper::requireFullIntl($this, '4.8.1.1');
\Locale::setDefault('de_DE');
$transformer = new NumberToLocalizedStringTransformer(null, true);
$transformer->reverseTransform('1.234.5');
}
/**
* @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
*/
public function testDecimalSeparatorMayNotBeDotIfGroupingSeparatorIsDotWithNoGroupSep()
{
// Since we test against "de_DE", we need the full implementation
IntlTestHelper::requireFullIntl($this, '4.8.1.1');
\Locale::setDefault('de_DE');
$transformer = new NumberToLocalizedStringTransformer(null, true);
$transformer->reverseTransform('1234.5');
}
public function testDecimalSeparatorMayBeDotIfGroupingSeparatorIsDotButNoGroupingUsed()
{
// Since we test against other locales, we need the full implementation
IntlTestHelper::requireFullIntl($this, false);
\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()
{
// Since we test against other locales, we need the full implementation
IntlTestHelper::requireFullIntl($this, '4.8.1.1');
\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()
{
IntlTestHelper::requireFullIntl($this, '4.8.1.1');
$transformer = new NumberToLocalizedStringTransformer(null, true);
$transformer->reverseTransform('1,234,5');
}
/**
* @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
*/
public function testDecimalSeparatorMayNotBeCommaIfGroupingSeparatorIsCommaWithNoGroupSep()
{
IntlTestHelper::requireFullIntl($this, '4.8.1.1');
$transformer = new NumberToLocalizedStringTransformer(null, true);
$transformer->reverseTransform('1234,5');
}
public function testDecimalSeparatorMayBeCommaIfGroupingSeparatorIsCommaButNoGroupingUsed()
{
$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
*
* @see 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()
{
// Since we test against other locales, we need the full implementation
IntlTestHelper::requireFullIntl($this, false);
\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()
{
// Since we test against other locales, we need the full implementation
IntlTestHelper::requireFullIntl($this, false);
\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()
{
// Since we test against other locales, we need the full implementation
IntlTestHelper::requireFullIntl($this, false);
\Locale::setDefault('ru');
$transformer = new NumberToLocalizedStringTransformer(null, true);
$transformer->reverseTransform("12\xc2\xa0345,678foo");
}
public function testReverseTransformBigInt()
{
$transformer = new NumberToLocalizedStringTransformer(null, true);
$this->assertEquals(PHP_INT_MAX - 1, (int) $transformer->reverseTransform((string) (PHP_INT_MAX - 1)));
}
public function testReverseTransformSmallInt()
{
$transformer = new NumberToLocalizedStringTransformer(null, true);
$this->assertSame(1.0, $transformer->reverseTransform('1'));
}
}

View File

@@ -0,0 +1,122 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Form\Extension\Core\DataTransformer\PercentToLocalizedStringTransformer;
use Symfony\Component\Intl\Util\IntlTestHelper;
class PercentToLocalizedStringTransformerTest extends TestCase
{
protected function setUp()
{
parent::setUp();
\Locale::setDefault('en');
}
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 testTransformWithScale()
{
// Since we test against "de_AT", we need the full implementation
IntlTestHelper::requireFullIntl($this, false);
\Locale::setDefault('de_AT');
$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 testReverseTransformWithScale()
{
// Since we test against "de_AT", we need the full implementation
IntlTestHelper::requireFullIntl($this, false);
\Locale::setDefault('de_AT');
$transformer = new PercentToLocalizedStringTransformer(2);
$this->assertEquals(0.1234, $transformer->reverseTransform('12,34'));
}
public function testTransformExpectsNumeric()
{
$transformer = new PercentToLocalizedStringTransformer();
$this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}('Symfony\Component\Form\Exception\TransformationFailedException');
$transformer->transform('foo');
}
public function testReverseTransformExpectsString()
{
$transformer = new PercentToLocalizedStringTransformer();
$this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}('Symfony\Component\Form\Exception\TransformationFailedException');
$transformer->reverseTransform(1);
}
}

View File

@@ -0,0 +1,143 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Form\Extension\Core\DataTransformer\ValueToDuplicatesTransformer;
class ValueToDuplicatesTransformerTest extends 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));
}
public function testReverseTransformEmptyArray()
{
$input = array(
'a' => array(),
'b' => array(),
'c' => array(),
);
$this->assertNull($this->transformer->reverseTransform($input));
}
public function testReverseTransformZeroString()
{
$input = array(
'a' => '0',
'b' => '0',
'c' => '0',
);
$this->assertSame('0', $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');
}
}

View File

@@ -0,0 +1,68 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\Extension\Core\EventListener;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\Extension\Core\EventListener\FixUrlProtocolListener;
class FixUrlProtocolListenerTest extends TestCase
{
public function testFixHttpUrl()
{
$data = 'www.symfony.com';
$form = $this->getMockBuilder('Symfony\Component\Form\Test\FormInterface')->getMock();
$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->getMockBuilder('Symfony\Component\Form\Test\FormInterface')->getMock();
$event = new FormEvent($form, $data);
$filter = new FixUrlProtocolListener('http');
$filter->onSubmit($event);
$this->assertEquals('http://www.symfony.com', $event->getData());
}
public function provideUrlsWithSupportedProtocols()
{
return array(
array('ftp://www.symfony.com'),
array('chrome-extension://foo'),
array('h323://foo'),
array('iris.beep://foo'),
array('foo+bar://foo'),
);
}
/**
* @dataProvider provideUrlsWithSupportedProtocols
*/
public function testSkipOtherProtocol($url)
{
$form = $this->getMockBuilder('Symfony\Component\Form\Test\FormInterface')->getMock();
$event = new FormEvent($form, $url);
$filter = new FixUrlProtocolListener('http');
$filter->onSubmit($event);
$this->assertEquals($url, $event->getData());
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 B

View File

@@ -0,0 +1,27 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\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);
}
}

View File

@@ -0,0 +1,27 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\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);
}
}

View File

@@ -0,0 +1,28 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\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);
}
}

View File

@@ -0,0 +1,256 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\Extension\Core\EventListener;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\Extension\Core\EventListener\MergeCollectionListener;
abstract class MergeCollectionListenerTest extends TestCase
{
protected $dispatcher;
protected $factory;
protected $form;
protected function setUp()
{
$this->dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcherInterface')->getMock();
$this->factory = $this->getMockBuilder('Symfony\Component\Form\FormFactoryInterface')->getMock();
$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->getMockBuilder('Symfony\Component\Form\Test\FormInterface')->getMock();
}
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());
}
}

View File

@@ -0,0 +1,278 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\Extension\Core\EventListener;
use Doctrine\Common\Collections\ArrayCollection;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Form\Extension\Core\EventListener\ResizeFormListener;
use Symfony\Component\Form\FormBuilder;
use Symfony\Component\Form\FormEvent;
class ResizeFormListenerTest extends TestCase
{
private $dispatcher;
private $factory;
private $form;
protected function setUp()
{
$this->dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcherInterface')->getMock();
$this->factory = $this->getMockBuilder('Symfony\Component\Form\FormFactoryInterface')->getMock();
$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->getMockBuilder('Symfony\Component\Form\DataMapperInterface')->getMock();
}
protected function getMockForm()
{
return $this->getMockBuilder('Symfony\Component\Form\Test\FormInterface')->getMock();
}
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]', 'attr' => array('maxlength' => 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]', 'attr' => array('maxlength' => 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('attr' => array('maxlength' => 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]', 'attr' => array('maxlength' => 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('attr' => array('maxlength' => 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'));
}
public function testPreSubmitDealsWithNoArrayOrTraversable()
{
$data = 'no array or traversable';
$event = new FormEvent($this->form, $data);
$listener = new ResizeFormListener('text', array(), false, false);
$listener->preSubmit($event);
$this->assertFalse($this->form->has('1'));
}
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());
}
public function testOnSubmitDealsWithObjectBackedIteratorAggregate()
{
$this->form->add($this->getForm('1'));
$data = new \ArrayObject(array(0 => 'first', 1 => 'second', 2 => 'third'));
$event = new FormEvent($this->form, $data);
$listener = new ResizeFormListener('text', array(), false, true);
$listener->onSubmit($event);
$this->assertArrayNotHasKey(0, $event->getData());
$this->assertArrayNotHasKey(2, $event->getData());
}
public function testOnSubmitDealsWithArrayBackedIteratorAggregate()
{
$this->form->add($this->getForm('1'));
$data = new ArrayCollection(array(0 => 'first', 1 => 'second', 2 => 'third'));
$event = new FormEvent($this->form, $data);
$listener = new ResizeFormListener('text', array(), false, true);
$listener->onSubmit($event);
$this->assertArrayNotHasKey(0, $event->getData());
$this->assertArrayNotHasKey(2, $event->getData());
}
}

View File

@@ -0,0 +1,43 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\Extension\Core\EventListener;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\Extension\Core\EventListener\TrimListener;
class TrimListenerTest extends TestCase
{
public function testTrim()
{
$data = ' Foo! ';
$form = $this->getMockBuilder('Symfony\Component\Form\Test\FormInterface')->getMock();
$event = new FormEvent($form, $data);
$filter = new TrimListener();
$filter->preSubmit($event);
$this->assertEquals('Foo!', $event->getData());
}
public function testTrimSkipNonStrings()
{
$data = 1234;
$form = $this->getMockBuilder('Symfony\Component\Form\Test\FormInterface')->getMock();
$event = new FormEvent($form, $data);
$filter = new TrimListener();
$filter->preSubmit($event);
$this->assertSame(1234, $event->getData());
}
}

View File

@@ -0,0 +1,152 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\Extension\Core\Type;
use Symfony\Component\Form\Test\TypeTestCase;
/**
* @author Bernhard Schussek <bschussek@gmail.com>
*/
abstract class BaseTypeTest extends TypeTestCase
{
const TESTED_TYPE = '';
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', FormTypeTest::TESTED_TYPE)
->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', FormTypeTest::TESTED_TYPE)
->add('child', FormTypeTest::TESTED_TYPE);
$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()
{
$view = $this->factory->create($this->getTestedType(), null, array(
'translation_domain' => 'domain',
))
->createView();
$this->assertSame('domain', $view->vars['translation_domain']);
}
public function testInheritTranslationDomainFromParent()
{
$view = $this->factory
->createNamedBuilder('parent', FormTypeTest::TESTED_TYPE, 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', FormTypeTest::TESTED_TYPE, 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', FormTypeTest::TESTED_TYPE)
->add('child', $this->getTestedType())
->getForm()
->createView();
$this->assertNull($view['child']->vars['translation_domain']);
}
public function testPassLabelToView()
{
$view = $this->factory->createNamed('__test___field', $this->getTestedType(), null, array('label' => 'My label'))
->createView();
$this->assertSame('My label', $view->vars['label']);
}
public function testPassMultipartFalseToView()
{
$view = $this->factory->create($this->getTestedType())
->createView();
$this->assertFalse($view->vars['multipart']);
}
public function testSubmitNull($expected = null, $norm = null, $view = null)
{
$form = $this->factory->create($this->getTestedType());
$form->submit(null);
$this->assertSame($expected, $form->getData());
$this->assertSame($norm, $form->getNormData());
$this->assertSame($view, $form->getViewData());
}
protected function getTestedType()
{
return static::TESTED_TYPE;
}
}

View File

@@ -0,0 +1,30 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\Extension\Core\Type;
/**
* @author Stepan Anchugov <kixxx1@gmail.com>
*/
class BirthdayTypeTest extends DateTypeTest
{
const TESTED_TYPE = 'Symfony\Component\Form\Extension\Core\Type\BirthdayType';
/**
* @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException
*/
public function testSetInvalidYearsOption()
{
$this->factory->create(static::TESTED_TYPE, null, array(
'years' => 'bad value',
));
}
}

View File

@@ -0,0 +1,25 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\Extension\Core\Type;
/**
* @author Bernhard Schussek <bschussek@gmail.com>
*/
class ButtonTypeTest extends BaseTypeTest
{
const TESTED_TYPE = 'Symfony\Component\Form\Extension\Core\Type\ButtonType';
public function testCreateButtonInstances()
{
$this->assertInstanceOf('Symfony\Component\Form\Button', $this->factory->create(static::TESTED_TYPE));
}
}

View File

@@ -0,0 +1,180 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\Extension\Core\Type;
use Symfony\Component\Form\CallbackTransformer;
class CheckboxTypeTest extends BaseTypeTest
{
const TESTED_TYPE = 'Symfony\Component\Form\Extension\Core\Type\CheckboxType';
public function testDataIsFalseByDefault()
{
$form = $this->factory->create(static::TESTED_TYPE);
$this->assertFalse($form->getData());
$this->assertFalse($form->getNormData());
$this->assertNull($form->getViewData());
}
public function testPassValueToView()
{
$view = $this->factory->create(static::TESTED_TYPE, null, array('value' => 'foobar'))
->createView();
$this->assertEquals('foobar', $view->vars['value']);
}
public function testCheckedIfDataTrue()
{
$view = $this->factory->create(static::TESTED_TYPE)
->setData(true)
->createView();
$this->assertTrue($view->vars['checked']);
}
public function testCheckedIfDataTrueWithEmptyValue()
{
$view = $this->factory->create(static::TESTED_TYPE, null, array('value' => ''))
->setData(true)
->createView();
$this->assertTrue($view->vars['checked']);
}
public function testNotCheckedIfDataFalse()
{
$view = $this->factory->create(static::TESTED_TYPE)
->setData(false)
->createView();
$this->assertFalse($view->vars['checked']);
}
public function testSubmitWithValueChecked()
{
$form = $this->factory->create(static::TESTED_TYPE, null, array(
'value' => 'foobar',
));
$form->submit('foobar');
$this->assertTrue($form->getData());
$this->assertEquals('foobar', $form->getViewData());
}
public function testSubmitWithRandomValueChecked()
{
$form = $this->factory->create(static::TESTED_TYPE, null, array(
'value' => 'foobar',
));
$form->submit('krixikraxi');
$this->assertTrue($form->getData());
$this->assertEquals('foobar', $form->getViewData());
}
public function testSubmitWithValueUnchecked()
{
$form = $this->factory->create(static::TESTED_TYPE, null, array(
'value' => 'foobar',
));
$form->submit(null);
$this->assertFalse($form->getData());
$this->assertNull($form->getViewData());
}
public function testSubmitWithEmptyValueChecked()
{
$form = $this->factory->create(static::TESTED_TYPE, null, array(
'value' => '',
));
$form->submit('');
$this->assertTrue($form->getData());
$this->assertSame('', $form->getViewData());
}
public function testSubmitWithEmptyValueUnchecked()
{
$form = $this->factory->create(static::TESTED_TYPE, null, array(
'value' => '',
));
$form->submit(null);
$this->assertFalse($form->getData());
$this->assertNull($form->getViewData());
}
public function testSubmitWithEmptyValueAndFalseUnchecked()
{
$form = $this->factory->create(static::TESTED_TYPE, null, array(
'value' => '',
));
$form->submit(false);
$this->assertFalse($form->getData());
$this->assertNull($form->getViewData());
}
public function testSubmitWithEmptyValueAndTrueChecked()
{
$form = $this->factory->create(static::TESTED_TYPE, null, array(
'value' => '',
));
$form->submit(true);
$this->assertTrue($form->getData());
$this->assertSame('', $form->getViewData());
}
/**
* @dataProvider provideCustomModelTransformerData
*/
public function testCustomModelTransformer($data, $checked)
{
// present a binary status field as a checkbox
$transformer = new CallbackTransformer(
function ($value) {
return 'checked' == $value;
},
function ($value) {
return $value ? 'checked' : 'unchecked';
}
);
$form = $this->factory->createBuilder(static::TESTED_TYPE)
->addModelTransformer($transformer)
->getForm();
$form->setData($data);
$view = $form->createView();
$this->assertSame($data, $form->getData());
$this->assertSame($checked, $form->getNormData());
$this->assertEquals($checked, $view->vars['checked']);
}
public function provideCustomModelTransformerData()
{
return array(
array('checked', true),
array('unchecked', false),
);
}
public function testSubmitNull($expected = null, $norm = null, $view = null)
{
parent::testSubmitNull(false, false, null);
}
}

View File

@@ -0,0 +1,38 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\Extension\Core\Type;
use Symfony\Component\Form\Test\FormPerformanceTestCase;
/**
* @author Bernhard Schussek <bschussek@gmail.com>
*/
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('Symfony\Component\Form\Extension\Core\Type\ChoiceType', mt_rand(1, 400), array(
'choices' => $choices,
));
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,367 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\Extension\Core\Type;
use Symfony\Component\Form\Tests\Fixtures\Author;
class CollectionTypeTest extends BaseTypeTest
{
const TESTED_TYPE = 'Symfony\Component\Form\Extension\Core\Type\CollectionType';
public function testContainsNoChildByDefault()
{
$form = $this->factory->create(static::TESTED_TYPE, null, array(
'entry_type' => TextTypeTest::TESTED_TYPE,
));
$this->assertCount(0, $form);
}
public function testSetDataAdjustsSize()
{
$form = $this->factory->create(static::TESTED_TYPE, null, array(
'entry_type' => TextTypeTest::TESTED_TYPE,
'entry_options' => array(
'attr' => array('maxlength' => 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());
$formAttrs0 = $form[0]->getConfig()->getOption('attr');
$formAttrs1 = $form[1]->getConfig()->getOption('attr');
$this->assertEquals(20, $formAttrs0['maxlength']);
$this->assertEquals(20, $formAttrs1['maxlength']);
$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());
$formAttrs0 = $form[0]->getConfig()->getOption('attr');
$this->assertEquals(20, $formAttrs0['maxlength']);
}
public function testThrowsExceptionIfObjectIsNotTraversable()
{
$form = $this->factory->create(static::TESTED_TYPE, null, array(
'entry_type' => TextTypeTest::TESTED_TYPE,
));
$this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}('Symfony\Component\Form\Exception\UnexpectedTypeException');
$form->setData(new \stdClass());
}
public function testNotResizedIfSubmittedWithMissingData()
{
$form = $this->factory->create(static::TESTED_TYPE, null, array(
'entry_type' => TextTypeTest::TESTED_TYPE,
));
$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(static::TESTED_TYPE, null, array(
'entry_type' => TextTypeTest::TESTED_TYPE,
'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 testResizedDownIfSubmittedWithEmptyDataAndDeleteEmpty()
{
$form = $this->factory->create(static::TESTED_TYPE, null, array(
'entry_type' => TextTypeTest::TESTED_TYPE,
'allow_delete' => true,
'delete_empty' => 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 testDontAddEmptyDataIfDeleteEmpty()
{
$form = $this->factory->create(static::TESTED_TYPE, null, array(
'entry_type' => TextTypeTest::TESTED_TYPE,
'allow_add' => true,
'delete_empty' => true,
));
$form->setData(array('foo@foo.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 testNoDeleteEmptyIfDeleteNotAllowed()
{
$form = $this->factory->create(static::TESTED_TYPE, null, array(
'entry_type' => TextTypeTest::TESTED_TYPE,
'allow_delete' => false,
'delete_empty' => true,
));
$form->setData(array('foo@foo.com'));
$form->submit(array(''));
$this->assertTrue($form->has('0'));
$this->assertEquals('', $form[0]->getData());
}
public function testResizedDownIfSubmittedWithCompoundEmptyDataAndDeleteEmpty()
{
$form = $this->factory->create(static::TESTED_TYPE, null, array(
'entry_type' => 'Symfony\Component\Form\Tests\Fixtures\AuthorType',
// If the field is not required, no new Author will be created if the
// form is completely empty
'entry_options' => array('required' => false),
'allow_add' => true,
'delete_empty' => true,
));
$form->setData(array(new Author('first', 'last')));
$form->submit(array(
array('firstName' => 's_first', 'lastName' => 's_last'),
array('firstName' => '', 'lastName' => ''),
));
$this->assertTrue($form->has('0'));
$this->assertFalse($form->has('1'));
$this->assertEquals(new Author('s_first', 's_last'), $form[0]->getData());
$this->assertEquals(array(new Author('s_first', 's_last')), $form->getData());
}
public function testNotResizedIfSubmittedWithExtraData()
{
$form = $this->factory->create(static::TESTED_TYPE, null, array(
'entry_type' => TextTypeTest::TESTED_TYPE,
));
$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(static::TESTED_TYPE, null, array(
'entry_type' => TextTypeTest::TESTED_TYPE,
'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(static::TESTED_TYPE, null, array(
'entry_type' => FormTypeTest::TESTED_TYPE,
'allow_add' => true,
'prototype' => false,
));
$this->assertFalse($form->has('__name__'));
}
public function testPrototypeMultipartPropagation()
{
$form = $this->factory
->create(static::TESTED_TYPE, null, array(
'entry_type' => FileTypeTest::TESTED_TYPE,
'allow_add' => true,
'prototype' => true,
))
;
$this->assertTrue($form->createView()->vars['multipart']);
}
public function testGetDataDoesNotContainsPrototypeNameBeforeDataAreSet()
{
$form = $this->factory->create(static::TESTED_TYPE, array(), array(
'entry_type' => FileTypeTest::TESTED_TYPE,
'prototype' => true,
'allow_add' => true,
));
$data = $form->getData();
$this->assertFalse(isset($data['__name__']));
}
public function testGetDataDoesNotContainsPrototypeNameAfterDataAreSet()
{
$form = $this->factory->create(static::TESTED_TYPE, array(), array(
'entry_type' => FileTypeTest::TESTED_TYPE,
'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(static::TESTED_TYPE, null, array(
'entry_type' => FormTypeTest::TESTED_TYPE,
'prototype' => true,
'allow_add' => true,
));
$this->assertSame('__name__', $form->getConfig()->getAttribute('prototype')->getName(), '__name__ is the default');
$form = $this->factory->create(static::TESTED_TYPE, null, array(
'entry_type' => FormTypeTest::TESTED_TYPE,
'prototype' => true,
'allow_add' => true,
'prototype_name' => '__test__',
));
$this->assertSame('__test__', $form->getConfig()->getAttribute('prototype')->getName());
}
public function testPrototypeDefaultLabel()
{
$form = $this->factory->create(static::TESTED_TYPE, array(), array(
'entry_type' => FileTypeTest::TESTED_TYPE,
'allow_add' => true,
'prototype' => true,
'prototype_name' => '__test__',
));
$this->assertSame('__test__label__', $form->createView()->vars['prototype']->vars['label']);
}
public function testPrototypeData()
{
$form = $this->factory->create(static::TESTED_TYPE, array(), array(
'allow_add' => true,
'prototype' => true,
'prototype_data' => 'foo',
'entry_type' => TextTypeTest::TESTED_TYPE,
'entry_options' => array(
'data' => 'bar',
'label' => false,
),
));
$this->assertSame('foo', $form->createView()->vars['prototype']->vars['value']);
$this->assertFalse($form->createView()->vars['prototype']->vars['label']);
}
public function testPrototypeDefaultRequired()
{
$form = $this->factory->create(static::TESTED_TYPE, array(), array(
'entry_type' => FileTypeTest::TESTED_TYPE,
'allow_add' => true,
'prototype' => true,
'prototype_name' => '__test__',
));
$this->assertTrue($form->createView()->vars['prototype']->vars['required']);
}
public function testPrototypeSetNotRequired()
{
$form = $this->factory->create(static::TESTED_TYPE, array(), array(
'entry_type' => FileTypeTest::TESTED_TYPE,
'allow_add' => true,
'prototype' => true,
'prototype_name' => '__test__',
'required' => false,
));
$this->assertFalse($form->createView()->vars['required'], 'collection is not required');
$this->assertFalse($form->createView()->vars['prototype']->vars['required'], '"prototype" should not be required');
}
public function testPrototypeSetNotRequiredIfParentNotRequired()
{
$child = $this->factory->create(static::TESTED_TYPE, array(), array(
'entry_type' => FileTypeTest::TESTED_TYPE,
'allow_add' => true,
'prototype' => true,
'prototype_name' => '__test__',
));
$parent = $this->factory->create(FormTypeTest::TESTED_TYPE, array(), array(
'required' => false,
));
$child->setParent($parent);
$this->assertFalse($parent->createView()->vars['required'], 'Parent is not required');
$this->assertFalse($child->createView()->vars['required'], 'Child is not required');
$this->assertFalse($child->createView()->vars['prototype']->vars['required'], '"Prototype" should not be required');
}
public function testPrototypeNotOverrideRequiredByEntryOptionsInFavorOfParent()
{
$child = $this->factory->create(static::TESTED_TYPE, array(), array(
'entry_type' => FileTypeTest::TESTED_TYPE,
'allow_add' => true,
'prototype' => true,
'prototype_name' => '__test__',
'entry_options' => array(
'required' => true,
),
));
$parent = $this->factory->create(FormTypeTest::TESTED_TYPE, array(), array(
'required' => false,
));
$child->setParent($parent);
$this->assertFalse($parent->createView()->vars['required'], 'Parent is not required');
$this->assertFalse($child->createView()->vars['required'], 'Child is not required');
$this->assertFalse($child->createView()->vars['prototype']->vars['required'], '"Prototype" should not be required');
}
public function testSubmitNull($expected = null, $norm = null, $view = null)
{
parent::testSubmitNull(array(), array(), array());
}
}

View File

@@ -0,0 +1,59 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\Extension\Core\Type;
use Symfony\Component\Form\ChoiceList\View\ChoiceView;
use Symfony\Component\Intl\Util\IntlTestHelper;
class CountryTypeTest extends BaseTypeTest
{
const TESTED_TYPE = 'Symfony\Component\Form\Extension\Core\Type\CountryType';
protected function setUp()
{
IntlTestHelper::requireIntl($this, false);
parent::setUp();
}
public function testCountriesAreSelectable()
{
$choices = $this->factory->create(static::TESTED_TYPE)
->createView()->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()
{
$choices = $this->factory->create(static::TESTED_TYPE, 'country')
->createView()->vars['choices'];
$countryCodes = array();
foreach ($choices as $choice) {
$countryCodes[] = $choice->value;
}
$this->assertNotContains('ZZ', $countryCodes);
}
public function testSubmitNull($expected = null, $norm = null, $view = null)
{
parent::testSubmitNull($expected, $norm, '');
}
}

View File

@@ -0,0 +1,42 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\Extension\Core\Type;
use Symfony\Component\Form\ChoiceList\View\ChoiceView;
use Symfony\Component\Intl\Util\IntlTestHelper;
class CurrencyTypeTest extends BaseTypeTest
{
const TESTED_TYPE = 'Symfony\Component\Form\Extension\Core\Type\CurrencyType';
protected function setUp()
{
IntlTestHelper::requireIntl($this, false);
parent::setUp();
}
public function testCurrenciesAreSelectable()
{
$choices = $this->factory->create(static::TESTED_TYPE)
->createView()->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);
}
public function testSubmitNull($expected = null, $norm = null, $view = null)
{
parent::testSubmitNull($expected, $norm, '');
}
}

View File

@@ -0,0 +1,413 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\Extension\Core\Type;
use Symfony\Component\Form\Extension\Core\Type\DateIntervalType;
use Symfony\Component\Form\FormError;
use Symfony\Component\Form\FormInterface;
class DateIntervalTypeTest extends BaseTypeTest
{
const TESTED_TYPE = DateIntervalType::class;
public function testSubmitDateInterval()
{
$form = $this->factory->create(static::TESTED_TYPE, null, array('input' => 'dateinterval'));
$form->submit(array(
'years' => '7',
'months' => '6',
'days' => '5',
));
$this->assertDateIntervalEquals(new \DateInterval('P7Y6M5D'), $form->getData());
}
public function testSubmitString()
{
$form = $this->factory->create(static::TESTED_TYPE, null, array('input' => 'string'));
$form->submit(array(
'years' => '7',
'months' => '6',
'days' => '5',
));
$this->assertSame('P7Y6M5D', $form->getData());
}
public function testSubmitArray()
{
$form = $this->factory->create(static::TESTED_TYPE, null, array('input' => 'array'));
$input = array(
'years' => '7',
'months' => '6',
'days' => '5',
);
$form->submit($input);
$this->assertSame($input, $form->getData());
}
public function testSubmitWithoutMonths()
{
$interval = new \DateInterval('P7Y5D');
$form = $this->factory->create(static::TESTED_TYPE, $interval, array(
'input' => 'dateinterval',
'with_months' => false,
));
$form->submit(array(
'years' => '7',
'months' => '6',
'days' => '5',
));
$this->assertDateIntervalEquals($interval, $form->getData());
$this->assertTrue($form->isSynchronized());
}
public function testSubmitWithTime()
{
$interval = new \DateInterval('P7Y6M5DT4H3M2S');
$form = $this->factory->create(static::TESTED_TYPE, $interval, array(
'input' => 'dateinterval',
'with_hours' => true,
'with_minutes' => true,
'with_seconds' => true,
));
$form->submit(array(
'years' => '7',
'months' => '6',
'days' => '5',
'hours' => '4',
'minutes' => '3',
'seconds' => '2',
));
$this->assertDateIntervalEquals($interval, $form->getData());
$this->assertTrue($form->isSynchronized());
}
public function testSubmitWithWeeks()
{
$form = $this->factory->create(static::TESTED_TYPE, new \DateInterval('P0Y'), array(
'input' => 'dateinterval',
'with_years' => false,
'with_months' => false,
'with_weeks' => true,
'with_days' => false,
));
$form->submit(array(
'weeks' => '30',
));
$this->assertDateIntervalEquals(new \DateInterval('P30W'), $form->getData());
}
public function testSubmitWithInvert()
{
$form = $this->factory->create(static::TESTED_TYPE, null, array(
'input' => 'dateinterval',
'with_invert' => true,
));
$form->submit(array(
'years' => '7',
'months' => '6',
'days' => '5',
'invert' => true,
));
$interval = new \DateInterval('P7Y6M5D');
$interval->invert = 1;
$this->assertDateIntervalEquals($interval, $form->getData());
}
public function testSubmitStringSingleText()
{
$form = $this->factory->create(static::TESTED_TYPE, null, array(
'input' => 'string',
'widget' => 'single_text',
));
$interval = 'P7Y6M5D';
$form->submit($interval);
$this->assertSame($interval, $form->getData());
$this->assertSame($interval, $form->getViewData());
}
public function testSubmitStringSingleTextWithSeconds()
{
$form = $this->factory->create(static::TESTED_TYPE, null, array(
'input' => 'string',
'widget' => 'single_text',
'with_hours' => true,
'with_minutes' => true,
'with_seconds' => true,
));
$interval = 'P7Y6M5DT4H3M2S';
$form->submit($interval);
$this->assertSame($interval, $form->getData());
$this->assertSame($interval, $form->getViewData());
}
public function testSubmitArrayInteger()
{
$form = $this->factory->create(static::TESTED_TYPE, null, array(
'widget' => 'integer',
'with_invert' => true,
));
$years = '7';
$form->submit(array(
'years' => '7',
'months' => '6',
'days' => '5',
'invert' => true,
));
$this->assertSame($years, $form['years']->getData());
$this->assertSame($years, $form['years']->getViewData());
}
public function testInitializeWithDateInterval()
{
// Throws an exception if "data_class" option is not explicitly set
// to null in the type
$this->assertInstanceOf(FormInterface::class, $this->factory->create(static::TESTED_TYPE, new \DateInterval('P0Y')));
}
public function testPassDefaultPlaceholderToViewIfNotRequired()
{
$view = $this->factory->create(static::TESTED_TYPE, null, array(
'required' => false,
'with_seconds' => true,
))
->createView();
$this->assertSame('', $view['years']->vars['placeholder']);
$this->assertSame('', $view['months']->vars['placeholder']);
$this->assertSame('', $view['days']->vars['placeholder']);
$this->assertSame('', $view['seconds']->vars['placeholder']);
}
public function testPassNoPlaceholderToViewIfRequired()
{
$view = $this->factory->create(static::TESTED_TYPE, null, array(
'required' => true,
'with_seconds' => true,
))
->createView();
$this->assertNull($view['years']->vars['placeholder']);
$this->assertNull($view['months']->vars['placeholder']);
$this->assertNull($view['days']->vars['placeholder']);
$this->assertNull($view['seconds']->vars['placeholder']);
}
public function testPassPlaceholderAsString()
{
$view = $this->factory->create(static::TESTED_TYPE, null, array(
'placeholder' => 'Empty',
'with_seconds' => true,
))
->createView();
$this->assertSame('Empty', $view['years']->vars['placeholder']);
$this->assertSame('Empty', $view['months']->vars['placeholder']);
$this->assertSame('Empty', $view['days']->vars['placeholder']);
$this->assertSame('Empty', $view['seconds']->vars['placeholder']);
}
public function testPassPlaceholderAsArray()
{
$view = $this->factory->create(static::TESTED_TYPE, null, array(
'placeholder' => array(
'years' => 'Empty years',
'months' => 'Empty months',
'days' => 'Empty days',
'hours' => 'Empty hours',
'minutes' => 'Empty minutes',
'seconds' => 'Empty seconds',
),
'with_hours' => true,
'with_minutes' => true,
'with_seconds' => true,
))
->createView();
$this->assertSame('Empty years', $view['years']->vars['placeholder']);
$this->assertSame('Empty months', $view['months']->vars['placeholder']);
$this->assertSame('Empty days', $view['days']->vars['placeholder']);
$this->assertSame('Empty hours', $view['hours']->vars['placeholder']);
$this->assertSame('Empty minutes', $view['minutes']->vars['placeholder']);
$this->assertSame('Empty seconds', $view['seconds']->vars['placeholder']);
}
public function testPassPlaceholderAsPartialArrayAddEmptyIfNotRequired()
{
$view = $this->factory->create(static::TESTED_TYPE, null, array(
'required' => false,
'placeholder' => array(
'years' => 'Empty years',
'days' => 'Empty days',
'hours' => 'Empty hours',
'seconds' => 'Empty seconds',
),
'with_hours' => true,
'with_minutes' => true,
'with_seconds' => true,
))
->createView();
$this->assertSame('Empty years', $view['years']->vars['placeholder']);
$this->assertSame('', $view['months']->vars['placeholder']);
$this->assertSame('Empty days', $view['days']->vars['placeholder']);
$this->assertSame('Empty hours', $view['hours']->vars['placeholder']);
$this->assertSame('', $view['minutes']->vars['placeholder']);
$this->assertSame('Empty seconds', $view['seconds']->vars['placeholder']);
}
public function testPassPlaceholderAsPartialArrayAddNullIfRequired()
{
$view = $this->factory->create(static::TESTED_TYPE, null, array(
'required' => true,
'placeholder' => array(
'years' => 'Empty years',
'days' => 'Empty days',
'hours' => 'Empty hours',
'seconds' => 'Empty seconds',
),
'with_hours' => true,
'with_minutes' => true,
'with_seconds' => true,
))
->createView();
$this->assertSame('Empty years', $view['years']->vars['placeholder']);
$this->assertNull($view['months']->vars['placeholder']);
$this->assertSame('Empty days', $view['days']->vars['placeholder']);
$this->assertSame('Empty hours', $view['hours']->vars['placeholder']);
$this->assertNull($view['minutes']->vars['placeholder']);
$this->assertSame('Empty seconds', $view['seconds']->vars['placeholder']);
}
public function testDateTypeChoiceErrorsBubbleUp()
{
$error = new FormError('Invalid!');
$form = $this->factory->create(static::TESTED_TYPE, null);
$form['years']->addError($error);
$this->assertSame(array(), iterator_to_array($form['years']->getErrors()));
$this->assertSame(array($error), iterator_to_array($form->getErrors()));
}
public function testTranslationsAreDisabledForChoiceWidget()
{
$form = $this->factory->create(static::TESTED_TYPE, null, array(
'widget' => 'choice',
'with_hours' => true,
'with_minutes' => true,
'with_seconds' => true,
));
$this->assertFalse($form->get('years')->getConfig()->getOption('choice_translation_domain'));
$this->assertFalse($form->get('months')->getConfig()->getOption('choice_translation_domain'));
$this->assertFalse($form->get('days')->getConfig()->getOption('choice_translation_domain'));
$this->assertFalse($form->get('hours')->getConfig()->getOption('choice_translation_domain'));
$this->assertFalse($form->get('minutes')->getConfig()->getOption('choice_translation_domain'));
$this->assertFalse($form->get('seconds')->getConfig()->getOption('choice_translation_domain'));
}
public function testInvertDoesNotInheritRequiredOption()
{
$form = $this->factory->create(static::TESTED_TYPE, null, array(
'input' => 'dateinterval',
'with_invert' => true,
'required' => true,
));
$this->assertFalse($form->get('invert')->getConfig()->getOption('required'));
}
public function testCanChangeTimeFieldsLabels()
{
$form = $this->factory->create(
static::TESTED_TYPE,
null,
array(
'required' => true,
'with_invert' => true,
'with_hours' => true,
'with_minutes' => true,
'with_seconds' => true,
'labels' => array(
'invert' => 'form.trans.invert',
'years' => 'form.trans.years',
'months' => 'form.trans.months',
'days' => 'form.trans.days',
'hours' => 'form.trans.hours',
'minutes' => 'form.trans.minutes',
'seconds' => 'form.trans.seconds',
),
)
);
$view = $form->createView();
$this->assertSame('form.trans.invert', $view['invert']->vars['label']);
$this->assertSame('form.trans.years', $view['years']->vars['label']);
$this->assertSame('form.trans.months', $view['months']->vars['label']);
$this->assertSame('form.trans.days', $view['days']->vars['label']);
$this->assertSame('form.trans.hours', $view['hours']->vars['label']);
$this->assertSame('form.trans.minutes', $view['minutes']->vars['label']);
$this->assertSame('form.trans.seconds', $view['seconds']->vars['label']);
}
public function testInvertDefaultLabel()
{
$form = $this->factory->create(static::TESTED_TYPE, null, array('with_invert' => true));
$view = $form->createView();
$this->assertSame('Negative interval', $view['invert']->vars['label']);
$form = $this->factory->create(static::TESTED_TYPE, null, array(
'with_invert' => true,
'labels' => array('invert' => null),
));
$view = $form->createView();
$this->assertSame('Negative interval', $view['invert']->vars['label']);
}
public function testSubmitNull($expected = null, $norm = null, $view = null)
{
parent::testSubmitNull($expected, $norm, array(
'years' => '',
'months' => '',
'days' => '',
));
}
}

View File

@@ -0,0 +1,583 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\Extension\Core\Type;
use Symfony\Component\Form\FormError;
class DateTimeTypeTest extends BaseTypeTest
{
const TESTED_TYPE = 'Symfony\Component\Form\Extension\Core\Type\DateTimeType';
protected function setUp()
{
\Locale::setDefault('en');
parent::setUp();
}
public function testSubmitDateTime()
{
$form = $this->factory->create(static::TESTED_TYPE, null, array(
'model_timezone' => 'UTC',
'view_timezone' => 'UTC',
'date_widget' => 'choice',
'years' => array(2010),
'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(static::TESTED_TYPE, null, array(
'model_timezone' => 'UTC',
'view_timezone' => 'UTC',
'input' => 'string',
'date_widget' => 'choice',
'years' => array(2010),
'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(static::TESTED_TYPE, null, array(
'model_timezone' => 'UTC',
'view_timezone' => 'UTC',
'input' => 'timestamp',
'date_widget' => 'choice',
'years' => array(2010),
'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(static::TESTED_TYPE, null, array(
'model_timezone' => 'UTC',
'view_timezone' => 'UTC',
'date_widget' => 'choice',
'years' => array(2010),
'time_widget' => 'choice',
'input' => 'datetime',
'with_minutes' => false,
));
$form->setData(new \DateTime());
$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(static::TESTED_TYPE, null, array(
'model_timezone' => 'UTC',
'view_timezone' => 'UTC',
'date_widget' => 'choice',
'years' => array(2010),
'time_widget' => 'choice',
'input' => 'datetime',
'with_seconds' => true,
));
$form->setData(new \DateTime());
$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(static::TESTED_TYPE, null, array(
'model_timezone' => 'America/New_York',
'view_timezone' => 'Pacific/Tahiti',
'date_widget' => 'choice',
'years' => array(2010),
'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(static::TESTED_TYPE, 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(static::TESTED_TYPE, 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(static::TESTED_TYPE, 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(static::TESTED_TYPE, 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());
}
public function testInitializeWithDateTime()
{
// Throws an exception if "data_class" option is not explicitly set
// to null in the type
$this->assertInstanceOf('Symfony\Component\Form\FormInterface', $this->factory->create(static::TESTED_TYPE, new \DateTime()));
}
public function testSingleTextWidgetShouldUseTheRightInputType()
{
$view = $this->factory->create(static::TESTED_TYPE, null, array(
'widget' => 'single_text',
))
->createView();
$this->assertEquals('datetime', $view->vars['type']);
}
public function testPassDefaultPlaceholderToViewIfNotRequired()
{
$view = $this->factory->create(static::TESTED_TYPE, null, array(
'required' => false,
'with_seconds' => true,
))
->createView();
$this->assertSame('', $view['date']['year']->vars['placeholder']);
$this->assertSame('', $view['date']['month']->vars['placeholder']);
$this->assertSame('', $view['date']['day']->vars['placeholder']);
$this->assertSame('', $view['time']['hour']->vars['placeholder']);
$this->assertSame('', $view['time']['minute']->vars['placeholder']);
$this->assertSame('', $view['time']['second']->vars['placeholder']);
}
public function testPassNoPlaceholderToViewIfRequired()
{
$view = $this->factory->create(static::TESTED_TYPE, null, array(
'required' => true,
'with_seconds' => true,
))
->createView();
$this->assertNull($view['date']['year']->vars['placeholder']);
$this->assertNull($view['date']['month']->vars['placeholder']);
$this->assertNull($view['date']['day']->vars['placeholder']);
$this->assertNull($view['time']['hour']->vars['placeholder']);
$this->assertNull($view['time']['minute']->vars['placeholder']);
$this->assertNull($view['time']['second']->vars['placeholder']);
}
public function testPassPlaceholderAsString()
{
$view = $this->factory->create(static::TESTED_TYPE, null, array(
'placeholder' => 'Empty',
'with_seconds' => true,
))
->createView();
$this->assertSame('Empty', $view['date']['year']->vars['placeholder']);
$this->assertSame('Empty', $view['date']['month']->vars['placeholder']);
$this->assertSame('Empty', $view['date']['day']->vars['placeholder']);
$this->assertSame('Empty', $view['time']['hour']->vars['placeholder']);
$this->assertSame('Empty', $view['time']['minute']->vars['placeholder']);
$this->assertSame('Empty', $view['time']['second']->vars['placeholder']);
}
public function testPassPlaceholderAsArray()
{
$view = $this->factory->create(static::TESTED_TYPE, null, array(
'placeholder' => array(
'year' => 'Empty year',
'month' => 'Empty month',
'day' => 'Empty day',
'hour' => 'Empty hour',
'minute' => 'Empty minute',
'second' => 'Empty second',
),
'with_seconds' => true,
))
->createView();
$this->assertSame('Empty year', $view['date']['year']->vars['placeholder']);
$this->assertSame('Empty month', $view['date']['month']->vars['placeholder']);
$this->assertSame('Empty day', $view['date']['day']->vars['placeholder']);
$this->assertSame('Empty hour', $view['time']['hour']->vars['placeholder']);
$this->assertSame('Empty minute', $view['time']['minute']->vars['placeholder']);
$this->assertSame('Empty second', $view['time']['second']->vars['placeholder']);
}
public function testPassPlaceholderAsPartialArrayAddEmptyIfNotRequired()
{
$view = $this->factory->create(static::TESTED_TYPE, null, array(
'required' => false,
'placeholder' => array(
'year' => 'Empty year',
'day' => 'Empty day',
'hour' => 'Empty hour',
'second' => 'Empty second',
),
'with_seconds' => true,
))
->createView();
$this->assertSame('Empty year', $view['date']['year']->vars['placeholder']);
$this->assertSame('', $view['date']['month']->vars['placeholder']);
$this->assertSame('Empty day', $view['date']['day']->vars['placeholder']);
$this->assertSame('Empty hour', $view['time']['hour']->vars['placeholder']);
$this->assertSame('', $view['time']['minute']->vars['placeholder']);
$this->assertSame('Empty second', $view['time']['second']->vars['placeholder']);
}
public function testPassPlaceholderAsPartialArrayAddNullIfRequired()
{
$view = $this->factory->create(static::TESTED_TYPE, null, array(
'required' => true,
'placeholder' => array(
'year' => 'Empty year',
'day' => 'Empty day',
'hour' => 'Empty hour',
'second' => 'Empty second',
),
'with_seconds' => true,
))
->createView();
$this->assertSame('Empty year', $view['date']['year']->vars['placeholder']);
$this->assertNull($view['date']['month']->vars['placeholder']);
$this->assertSame('Empty day', $view['date']['day']->vars['placeholder']);
$this->assertSame('Empty hour', $view['time']['hour']->vars['placeholder']);
$this->assertNull($view['time']['minute']->vars['placeholder']);
$this->assertSame('Empty second', $view['time']['second']->vars['placeholder']);
}
public function testPassHtml5TypeIfSingleTextAndHtml5Format()
{
$view = $this->factory->create(static::TESTED_TYPE, null, array(
'widget' => 'single_text',
))
->createView();
$this->assertSame('datetime', $view->vars['type']);
}
public function testDontPassHtml5TypeIfHtml5NotAllowed()
{
$view = $this->factory->create(static::TESTED_TYPE, null, array(
'widget' => 'single_text',
'html5' => false,
))
->createView();
$this->assertFalse(isset($view->vars['type']));
}
public function testDontPassHtml5TypeIfNotHtml5Format()
{
$view = $this->factory->create(static::TESTED_TYPE, null, array(
'widget' => 'single_text',
'format' => 'yyyy-MM-dd HH:mm',
))
->createView();
$this->assertFalse(isset($view->vars['type']));
}
public function testDontPassHtml5TypeIfNotSingleText()
{
$view = $this->factory->create(static::TESTED_TYPE, null, array(
'widget' => 'text',
))
->createView();
$this->assertFalse(isset($view->vars['type']));
}
public function testDateTypeChoiceErrorsBubbleUp()
{
$error = new FormError('Invalid!');
$form = $this->factory->create(static::TESTED_TYPE, null);
$form['date']->addError($error);
$this->assertSame(array(), iterator_to_array($form['date']->getErrors()));
$this->assertSame(array($error), iterator_to_array($form->getErrors()));
}
public function testDateTypeSingleTextErrorsBubbleUp()
{
$error = new FormError('Invalid!');
$form = $this->factory->create(static::TESTED_TYPE, null, array(
'date_widget' => 'single_text',
));
$form['date']->addError($error);
$this->assertSame(array(), iterator_to_array($form['date']->getErrors()));
$this->assertSame(array($error), iterator_to_array($form->getErrors()));
}
public function testTimeTypeChoiceErrorsBubbleUp()
{
$error = new FormError('Invalid!');
$form = $this->factory->create(static::TESTED_TYPE, null);
$form['time']->addError($error);
$this->assertSame(array(), iterator_to_array($form['time']->getErrors()));
$this->assertSame(array($error), iterator_to_array($form->getErrors()));
}
public function testTimeTypeSingleTextErrorsBubbleUp()
{
$error = new FormError('Invalid!');
$form = $this->factory->create(static::TESTED_TYPE, null, array(
'time_widget' => 'single_text',
));
$form['time']->addError($error);
$this->assertSame(array(), iterator_to_array($form['time']->getErrors()));
$this->assertSame(array($error), iterator_to_array($form->getErrors()));
}
public function testPassDefaultChoiceTranslationDomain()
{
$form = $this->factory->create(static::TESTED_TYPE, null, array(
'with_seconds' => true,
));
$view = $form->createView();
$this->assertFalse($view['date']['year']->vars['choice_translation_domain']);
$this->assertFalse($view['date']['month']->vars['choice_translation_domain']);
$this->assertFalse($view['date']['day']->vars['choice_translation_domain']);
$this->assertFalse($view['time']['hour']->vars['choice_translation_domain']);
$this->assertFalse($view['time']['minute']->vars['choice_translation_domain']);
$this->assertFalse($view['time']['second']->vars['choice_translation_domain']);
}
public function testPassChoiceTranslationDomainAsString()
{
$form = $this->factory->create(static::TESTED_TYPE, null, array(
'choice_translation_domain' => 'messages',
'with_seconds' => true,
));
$view = $form->createView();
$this->assertSame('messages', $view['date']['year']->vars['choice_translation_domain']);
$this->assertSame('messages', $view['date']['month']->vars['choice_translation_domain']);
$this->assertSame('messages', $view['date']['day']->vars['choice_translation_domain']);
$this->assertSame('messages', $view['time']['hour']->vars['choice_translation_domain']);
$this->assertSame('messages', $view['time']['minute']->vars['choice_translation_domain']);
$this->assertSame('messages', $view['time']['second']->vars['choice_translation_domain']);
}
public function testPassChoiceTranslationDomainAsArray()
{
$form = $this->factory->create(static::TESTED_TYPE, null, array(
'choice_translation_domain' => array(
'year' => 'foo',
'month' => 'test',
'hour' => 'foo',
'second' => 'test',
),
'with_seconds' => true,
));
$view = $form->createView();
$this->assertSame('foo', $view['date']['year']->vars['choice_translation_domain']);
$this->assertSame('test', $view['date']['month']->vars['choice_translation_domain']);
$this->assertFalse($view['date']['day']->vars['choice_translation_domain']);
$this->assertSame('foo', $view['time']['hour']->vars['choice_translation_domain']);
$this->assertFalse($view['time']['minute']->vars['choice_translation_domain']);
$this->assertSame('test', $view['time']['second']->vars['choice_translation_domain']);
}
public function testSubmitNull($expected = null, $norm = null, $view = null)
{
parent::testSubmitNull($expected, $norm, array(
// View data is an array of choice values array
'date' => array('year' => '', 'month' => '', 'day' => ''),
'time' => array('hour' => '', 'minute' => ''),
));
}
public function testSubmitNullWithText()
{
$form = $this->factory->create(static::TESTED_TYPE, null, array(
'widget' => 'text',
));
$form->submit(null);
$this->assertNull($form->getData());
$this->assertNull($form->getNormData());
$this->assertSame(array(
// View data is an array of choice values array
'date' => array('year' => '', 'month' => '', 'day' => ''),
'time' => array('hour' => '', 'minute' => ''),
), $form->getViewData());
}
public function testSubmitNullWithSingleText()
{
$form = $this->factory->create(static::TESTED_TYPE, null, array(
'widget' => 'single_text',
));
$form->submit(null);
$this->assertNull($form->getData());
$this->assertNull($form->getNormData());
$this->assertSame('', $form->getViewData());
}
}

View File

@@ -0,0 +1,978 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\Extension\Core\Type;
use Symfony\Component\Form\ChoiceList\View\ChoiceView;
use Symfony\Component\Form\FormError;
use Symfony\Component\Intl\Util\IntlTestHelper;
class DateTypeTest extends BaseTypeTest
{
const TESTED_TYPE = 'Symfony\Component\Form\Extension\Core\Type\DateType';
private $defaultTimezone;
protected function setUp()
{
parent::setUp();
$this->defaultTimezone = date_default_timezone_get();
}
protected function tearDown()
{
date_default_timezone_set($this->defaultTimezone);
\Locale::setDefault('en');
}
/**
* @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException
*/
public function testInvalidWidgetOption()
{
$this->factory->create(static::TESTED_TYPE, null, array(
'widget' => 'fake_widget',
));
}
/**
* @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException
*/
public function testInvalidInputOption()
{
$this->factory->create(static::TESTED_TYPE, null, array(
'input' => 'fake_input',
));
}
public function testSubmitFromSingleTextDateTimeWithDefaultFormat()
{
$form = $this->factory->create(static::TESTED_TYPE, 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 testSubmitFromSingleTextDateTimeWithCustomFormat()
{
$form = $this->factory->create(static::TESTED_TYPE, null, array(
'model_timezone' => 'UTC',
'view_timezone' => 'UTC',
'widget' => 'single_text',
'input' => 'datetime',
'format' => 'yyyy',
));
$form->submit('2010');
$this->assertDateTimeEquals(new \DateTime('2010-01-01 UTC'), $form->getData());
$this->assertEquals('2010', $form->getViewData());
}
public function testSubmitFromSingleTextDateTime()
{
// we test against "de_DE", so we need the full implementation
IntlTestHelper::requireFullIntl($this, false);
\Locale::setDefault('de_DE');
$form = $this->factory->create(static::TESTED_TYPE, 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()
{
// we test against "de_DE", so we need the full implementation
IntlTestHelper::requireFullIntl($this, false);
\Locale::setDefault('de_DE');
$form = $this->factory->create(static::TESTED_TYPE, 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()
{
// we test against "de_DE", so we need the full implementation
IntlTestHelper::requireFullIntl($this, false);
\Locale::setDefault('de_DE');
$form = $this->factory->create(static::TESTED_TYPE, 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()
{
// we test against "de_DE", so we need the full implementation
IntlTestHelper::requireFullIntl($this, false);
\Locale::setDefault('de_DE');
$form = $this->factory->create(static::TESTED_TYPE, 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(static::TESTED_TYPE, 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(static::TESTED_TYPE, null, array(
'model_timezone' => 'UTC',
'view_timezone' => 'UTC',
'widget' => 'choice',
'years' => array(2010),
));
$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(static::TESTED_TYPE, 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(static::TESTED_TYPE, 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(static::TESTED_TYPE, 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(static::TESTED_TYPE, 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(static::TESTED_TYPE, 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)
{
$view = $this->factory->create(static::TESTED_TYPE, null, array(
'format' => $format,
))
->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 not accepted
* as valid IntlDateFormatter constants for FULL, LONG, MEDIUM or SHORT respectively.
*
* @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException
*/
public function testThrowExceptionIfFormatIsNoPattern()
{
$this->factory->create(static::TESTED_TYPE, null, array(
'format' => '0',
'widget' => 'single_text',
'input' => 'string',
));
}
/**
* @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException
* @expectedExceptionMessage The "format" option should contain the letters "y", "M" and "d". Its current value is "yy".
*/
public function testThrowExceptionIfFormatDoesNotContainYearMonthAndDay()
{
$this->factory->create(static::TESTED_TYPE, null, array(
'months' => array(6, 7),
'format' => 'yy',
));
}
/**
* @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException
* @expectedExceptionMessage The "format" option should contain the letters "y", "M" or "d". Its current value is "wrong".
*/
public function testThrowExceptionIfFormatMissesYearMonthAndDayWithSingleTextWidget()
{
$this->factory->create(static::TESTED_TYPE, null, array(
'widget' => 'single_text',
'format' => 'wrong',
));
}
/**
* @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException
*/
public function testThrowExceptionIfFormatIsNoConstant()
{
$this->factory->create(static::TESTED_TYPE, null, array(
'format' => 105,
));
}
/**
* @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException
*/
public function testThrowExceptionIfFormatIsInvalid()
{
$this->factory->create(static::TESTED_TYPE, null, array(
'format' => array(),
));
}
/**
* @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException
*/
public function testThrowExceptionIfYearsIsInvalid()
{
$this->factory->create(static::TESTED_TYPE, null, array(
'years' => 'bad value',
));
}
/**
* @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException
*/
public function testThrowExceptionIfMonthsIsInvalid()
{
$this->factory->create(static::TESTED_TYPE, null, array(
'months' => 'bad value',
));
}
/**
* @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException
*/
public function testThrowExceptionIfDaysIsInvalid()
{
$this->factory->create(static::TESTED_TYPE, null, array(
'days' => 'bad value',
));
}
public function testSetDataWithNegativeTimezoneOffsetStringInput()
{
// we test against "de_DE", so we need the full implementation
IntlTestHelper::requireFullIntl($this, false);
\Locale::setDefault('de_DE');
$form = $this->factory->create(static::TESTED_TYPE, null, array(
'format' => \IntlDateFormatter::MEDIUM,
'model_timezone' => 'UTC',
'view_timezone' => 'America/New_York',
'input' => 'string',
'widget' => 'single_text',
));
$form->setData('2010-06-02');
// 2010-06-02 00:00:00 UTC
// 2010-06-01 20:00:00 UTC-4
$this->assertEquals('01.06.2010', $form->getViewData());
}
public function testSetDataWithNegativeTimezoneOffsetDateTimeInput()
{
// we test against "de_DE", so we need the full implementation
IntlTestHelper::requireFullIntl($this, false);
\Locale::setDefault('de_DE');
$form = $this->factory->create(static::TESTED_TYPE, null, array(
'format' => \IntlDateFormatter::MEDIUM,
'model_timezone' => 'UTC',
'view_timezone' => 'America/New_York',
'input' => 'datetime',
'widget' => 'single_text',
));
$dateTime = new \DateTime('2010-06-02 UTC');
$form->setData($dateTime);
// 2010-06-02 00:00:00 UTC
// 2010-06-01 20:00:00 UTC-4
$this->assertDateTimeEquals($dateTime, $form->getData());
$this->assertEquals('01.06.2010', $form->getViewData());
}
public function testYearsOption()
{
$form = $this->factory->create(static::TESTED_TYPE, 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(static::TESTED_TYPE, null, array(
'months' => array(6, 7),
'format' => \IntlDateFormatter::SHORT,
));
$view = $form->createView();
$this->assertEquals(array(
new ChoiceView(6, '6', '06'),
new ChoiceView(7, '7', '07'),
), $view['month']->vars['choices']);
}
public function testMonthsOptionShortFormat()
{
// we test against "de_AT", so we need the full implementation
IntlTestHelper::requireFullIntl($this, '57.1');
\Locale::setDefault('de_AT');
$form = $this->factory->create(static::TESTED_TYPE, 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()
{
// we test against "de_AT", so we need the full implementation
IntlTestHelper::requireFullIntl($this, false);
\Locale::setDefault('de_AT');
$view = $this->factory->create(static::TESTED_TYPE, null, array(
'months' => array(1, 4),
'format' => 'dd.MMMM.yy',
))
->createView();
$this->assertEquals(array(
new ChoiceView(1, '1', 'Jänner'),
new ChoiceView(4, '4', 'April'),
), $view['month']->vars['choices']);
}
public function testMonthsOptionLongFormatWithDifferentTimezone()
{
// we test against "de_AT", so we need the full implementation
IntlTestHelper::requireFullIntl($this, false);
\Locale::setDefault('de_AT');
$view = $this->factory->create(static::TESTED_TYPE, null, array(
'months' => array(1, 4),
'format' => 'dd.MMMM.yy',
))
->createView();
$this->assertEquals(array(
new ChoiceView(1, '1', 'Jänner'),
new ChoiceView(4, '4', 'April'),
), $view['month']->vars['choices']);
}
public function testIsDayWithinRangeReturnsTrueIfWithin()
{
$view = $this->factory->create(static::TESTED_TYPE, null, array(
'days' => array(6, 7),
))
->createView();
$this->assertEquals(array(
new ChoiceView(6, '6', '06'),
new ChoiceView(7, '7', '07'),
), $view['day']->vars['choices']);
}
public function testIsSynchronizedReturnsTrueIfChoiceAndCompletelyEmpty()
{
$form = $this->factory->create(static::TESTED_TYPE, null, array(
'model_timezone' => 'UTC',
'view_timezone' => 'UTC',
'widget' => 'choice',
));
$form->submit(array(
'day' => '',
'month' => '',
'year' => '',
));
$this->assertTrue($form->isSynchronized());
}
public function testIsSynchronizedReturnsTrueIfChoiceAndCompletelyFilled()
{
$form = $this->factory->create(static::TESTED_TYPE, new \DateTime(), array(
'model_timezone' => 'UTC',
'view_timezone' => 'UTC',
'widget' => 'choice',
));
$form->submit(array(
'day' => '1',
'month' => '6',
'year' => '2010',
));
$this->assertTrue($form->isSynchronized());
}
public function testIsSynchronizedReturnsFalseIfChoiceAndDayEmpty()
{
$form = $this->factory->create(static::TESTED_TYPE, null, array(
'model_timezone' => 'UTC',
'view_timezone' => 'UTC',
'widget' => 'choice',
));
$form->submit(array(
'day' => '',
'month' => '6',
'year' => '2010',
));
$this->assertFalse($form->isSynchronized());
}
public function testPassDatePatternToView()
{
// we test against "de_AT", so we need the full implementation
IntlTestHelper::requireFullIntl($this, false);
\Locale::setDefault('de_AT');
$view = $this->factory->create(static::TESTED_TYPE)
->createView();
$this->assertSame('{{ day }}{{ month }}{{ year }}', $view->vars['date_pattern']);
}
public function testPassDatePatternToViewDifferentFormat()
{
// we test against "de_AT", so we need the full implementation
IntlTestHelper::requireFullIntl($this, false);
\Locale::setDefault('de_AT');
$view = $this->factory->create(static::TESTED_TYPE, null, array(
'format' => \IntlDateFormatter::LONG,
))
->createView();
$this->assertSame('{{ day }}{{ month }}{{ year }}', $view->vars['date_pattern']);
}
public function testPassDatePatternToViewDifferentPattern()
{
$view = $this->factory->create(static::TESTED_TYPE, null, array(
'format' => 'MMyyyydd',
))
->createView();
$this->assertSame('{{ month }}{{ year }}{{ day }}', $view->vars['date_pattern']);
}
public function testPassDatePatternToViewDifferentPatternWithSeparators()
{
$view = $this->factory->create(static::TESTED_TYPE, null, array(
'format' => 'MM*yyyy*dd',
))
->createView();
$this->assertSame('{{ month }}*{{ year }}*{{ day }}', $view->vars['date_pattern']);
}
public function testDontPassDatePatternIfText()
{
$view = $this->factory->create(static::TESTED_TYPE, null, array(
'widget' => 'single_text',
))
->createView();
$this->assertFalse(isset($view->vars['date_pattern']));
}
public function testDatePatternFormatWithQuotedStrings()
{
// we test against "es_ES", so we need the full implementation
IntlTestHelper::requireFullIntl($this, false);
\Locale::setDefault('es_ES');
$view = $this->factory->create(static::TESTED_TYPE, null, array(
// EEEE, d 'de' MMMM 'de' y
'format' => \IntlDateFormatter::FULL,
))
->createView();
$this->assertEquals('{{ day }}{{ month }}{{ year }}', $view->vars['date_pattern']);
}
public function testPassWidgetToView()
{
$view = $this->factory->create(static::TESTED_TYPE, null, array(
'widget' => 'single_text',
))
->createView();
$this->assertSame('single_text', $view->vars['widget']);
}
public function testInitializeWithDateTime()
{
// Throws an exception if "data_class" option is not explicitly set
// to null in the type
$this->assertInstanceOf('Symfony\Component\Form\FormInterface', $this->factory->create(static::TESTED_TYPE, new \DateTime()));
}
public function testSingleTextWidgetShouldUseTheRightInputType()
{
$view = $this->factory->create(static::TESTED_TYPE, null, array(
'widget' => 'single_text',
))
->createView();
$this->assertEquals('date', $view->vars['type']);
}
public function testPassDefaultPlaceholderToViewIfNotRequired()
{
$view = $this->factory->create(static::TESTED_TYPE, null, array(
'required' => false,
))
->createView();
$this->assertSame('', $view['year']->vars['placeholder']);
$this->assertSame('', $view['month']->vars['placeholder']);
$this->assertSame('', $view['day']->vars['placeholder']);
}
public function testPassNoPlaceholderToViewIfRequired()
{
$view = $this->factory->create(static::TESTED_TYPE, null, array(
'required' => true,
))
->createView();
$this->assertNull($view['year']->vars['placeholder']);
$this->assertNull($view['month']->vars['placeholder']);
$this->assertNull($view['day']->vars['placeholder']);
}
public function testPassPlaceholderAsString()
{
$view = $this->factory->create(static::TESTED_TYPE, null, array(
'placeholder' => 'Empty',
))
->createView();
$this->assertSame('Empty', $view['year']->vars['placeholder']);
$this->assertSame('Empty', $view['month']->vars['placeholder']);
$this->assertSame('Empty', $view['day']->vars['placeholder']);
}
public function testPassPlaceholderAsArray()
{
$view = $this->factory->create(static::TESTED_TYPE, null, array(
'placeholder' => array(
'year' => 'Empty year',
'month' => 'Empty month',
'day' => 'Empty day',
),
))
->createView();
$this->assertSame('Empty year', $view['year']->vars['placeholder']);
$this->assertSame('Empty month', $view['month']->vars['placeholder']);
$this->assertSame('Empty day', $view['day']->vars['placeholder']);
}
public function testPassPlaceholderAsPartialArrayAddEmptyIfNotRequired()
{
$view = $this->factory->create(static::TESTED_TYPE, null, array(
'required' => false,
'placeholder' => array(
'year' => 'Empty year',
'day' => 'Empty day',
),
))
->createView();
$this->assertSame('Empty year', $view['year']->vars['placeholder']);
$this->assertSame('', $view['month']->vars['placeholder']);
$this->assertSame('Empty day', $view['day']->vars['placeholder']);
}
public function testPassPlaceholderAsPartialArrayAddNullIfRequired()
{
$view = $this->factory->create(static::TESTED_TYPE, null, array(
'required' => true,
'placeholder' => array(
'year' => 'Empty year',
'day' => 'Empty day',
),
))
->createView();
$this->assertSame('Empty year', $view['year']->vars['placeholder']);
$this->assertNull($view['month']->vars['placeholder']);
$this->assertSame('Empty day', $view['day']->vars['placeholder']);
}
public function testPassHtml5TypeIfSingleTextAndHtml5Format()
{
$view = $this->factory->create(static::TESTED_TYPE, null, array(
'widget' => 'single_text',
))
->createView();
$this->assertSame('date', $view->vars['type']);
}
public function testDontPassHtml5TypeIfHtml5NotAllowed()
{
$view = $this->factory->create(static::TESTED_TYPE, null, array(
'widget' => 'single_text',
'html5' => false,
))
->createView();
$this->assertFalse(isset($view->vars['type']));
}
public function testDontPassHtml5TypeIfNotHtml5Format()
{
$view = $this->factory->create(static::TESTED_TYPE, null, array(
'widget' => 'single_text',
'format' => \IntlDateFormatter::MEDIUM,
))
->createView();
$this->assertFalse(isset($view->vars['type']));
}
public function testDontPassHtml5TypeIfNotSingleText()
{
$view = $this->factory->create(static::TESTED_TYPE, null, array(
'widget' => 'text',
))
->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(static::TESTED_TYPE, null, array(
'widget' => $widget,
));
$form['year']->addError($error);
$this->assertSame(array(), iterator_to_array($form['year']->getErrors()));
$this->assertSame(array($error), iterator_to_array($form->getErrors()));
}
/**
* @dataProvider provideCompoundWidgets
*/
public function testMonthErrorsBubbleUp($widget)
{
$error = new FormError('Invalid!');
$form = $this->factory->create(static::TESTED_TYPE, null, array(
'widget' => $widget,
));
$form['month']->addError($error);
$this->assertSame(array(), iterator_to_array($form['month']->getErrors()));
$this->assertSame(array($error), iterator_to_array($form->getErrors()));
}
/**
* @dataProvider provideCompoundWidgets
*/
public function testDayErrorsBubbleUp($widget)
{
$error = new FormError('Invalid!');
$form = $this->factory->create(static::TESTED_TYPE, null, array(
'widget' => $widget,
));
$form['day']->addError($error);
$this->assertSame(array(), iterator_to_array($form['day']->getErrors()));
$this->assertSame(array($error), iterator_to_array($form->getErrors()));
}
public function testYearsFor32BitsMachines()
{
if (4 !== PHP_INT_SIZE) {
$this->markTestSkipped('PHP 32 bit is required.');
}
$view = $this->factory->create(static::TESTED_TYPE, null, array(
'years' => range(1900, 2040),
))
->createView();
$listChoices = array();
foreach (range(1902, 2037) as $y) {
$listChoices[] = new ChoiceView($y, $y, $y);
}
$this->assertEquals($listChoices, $view['year']->vars['choices']);
}
public function testPassDefaultChoiceTranslationDomain()
{
$form = $this->factory->create(static::TESTED_TYPE);
$view = $form->createView();
$this->assertFalse($view['year']->vars['choice_translation_domain']);
$this->assertFalse($view['month']->vars['choice_translation_domain']);
$this->assertFalse($view['day']->vars['choice_translation_domain']);
}
public function testPassChoiceTranslationDomainAsString()
{
$form = $this->factory->create(static::TESTED_TYPE, null, array(
'choice_translation_domain' => 'messages',
));
$view = $form->createView();
$this->assertSame('messages', $view['year']->vars['choice_translation_domain']);
$this->assertSame('messages', $view['month']->vars['choice_translation_domain']);
$this->assertSame('messages', $view['day']->vars['choice_translation_domain']);
}
public function testPassChoiceTranslationDomainAsArray()
{
$form = $this->factory->create(static::TESTED_TYPE, null, array(
'choice_translation_domain' => array(
'year' => 'foo',
'day' => 'test',
),
));
$view = $form->createView();
$this->assertSame('foo', $view['year']->vars['choice_translation_domain']);
$this->assertFalse($view['month']->vars['choice_translation_domain']);
$this->assertSame('test', $view['day']->vars['choice_translation_domain']);
}
public function testSubmitNull($expected = null, $norm = null, $view = null)
{
parent::testSubmitNull($expected, $norm, array('year' => '', 'month' => '', 'day' => ''));
}
public function testSubmitNullWithSingleText()
{
$form = $this->factory->create(static::TESTED_TYPE, null, array(
'widget' => 'single_text',
));
$form->submit(null);
$this->assertNull($form->getData());
$this->assertNull($form->getNormData());
$this->assertSame('', $form->getViewData());
}
}

View File

@@ -0,0 +1,87 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\Extension\Core\Type;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Form\Forms;
use Symfony\Component\Form\Tests\Fixtures\ChoiceTypeExtension;
use Symfony\Component\Form\Tests\Fixtures\LazyChoiceTypeExtension;
class ExtendedChoiceTypeTest extends TestCase
{
/**
* @group legacy
* @dataProvider provideTestedTypes
*/
public function testLegacyChoicesAreOverridden($type)
{
$factory = Forms::createFormFactoryBuilder()
->addTypeExtension(new ChoiceTypeExtension($type))
->getFormFactory()
;
$choices = $factory->create($type)->createView()->vars['choices'];
$this->assertCount(2, $choices);
$this->assertSame('A', $choices[0]->label);
$this->assertSame('a', $choices[0]->value);
$this->assertSame('B', $choices[1]->label);
$this->assertSame('b', $choices[1]->value);
}
/**
* @dataProvider provideTestedTypes
*/
public function testChoicesAreOverridden($type)
{
$factory = Forms::createFormFactoryBuilder()
->addTypeExtension(new ChoiceTypeExtension($type))
->getFormFactory()
;
$choices = $factory->create($type, null, array('choice_loader' => null))->createView()->vars['choices'];
$this->assertCount(2, $choices);
$this->assertSame('A', $choices[0]->label);
$this->assertSame('a', $choices[0]->value);
$this->assertSame('B', $choices[1]->label);
$this->assertSame('b', $choices[1]->value);
}
/**
* @dataProvider provideTestedTypes
*/
public function testChoiceLoaderIsOverridden($type)
{
$factory = Forms::createFormFactoryBuilder()
->addTypeExtension(new LazyChoiceTypeExtension($type))
->getFormFactory()
;
$choices = $factory->create($type)->createView()->vars['choices'];
$this->assertCount(2, $choices);
$this->assertSame('Lazy A', $choices[0]->label);
$this->assertSame('lazy_a', $choices[0]->value);
$this->assertSame('Lazy B', $choices[1]->label);
$this->assertSame('lazy_b', $choices[1]->value);
}
public function provideTestedTypes()
{
yield array(CountryTypeTest::TESTED_TYPE);
yield array(CurrencyTypeTest::TESTED_TYPE);
yield array(LanguageTypeTest::TESTED_TYPE);
yield array(LocaleTypeTest::TESTED_TYPE);
yield array(TimezoneTypeTest::TESTED_TYPE);
}
}

View File

@@ -0,0 +1,137 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\Extension\Core\Type;
class FileTypeTest extends BaseTypeTest
{
const TESTED_TYPE = 'Symfony\Component\Form\Extension\Core\Type\FileType';
// https://github.com/symfony/symfony/pull/5028
public function testSetData()
{
$form = $this->factory->createBuilder(static::TESTED_TYPE)->getForm();
$data = $this->getMockBuilder('Symfony\Component\HttpFoundation\File\File')
->setConstructorArgs(array(__DIR__.'/../../../Fixtures/foo', 'foo'))
->getMock();
$form->setData($data);
// Ensures the data class is defined to accept File instance
$this->assertSame($data, $form->getData());
}
public function testSubmit()
{
$form = $this->factory->createBuilder(static::TESTED_TYPE)->getForm();
$data = $this->createUploadedFileMock('abcdef', 'original.jpg', true);
$form->submit($data);
$this->assertSame($data, $form->getData());
}
public function testSetDataMultiple()
{
$form = $this->factory->createBuilder(static::TESTED_TYPE, null, array(
'multiple' => true,
))->getForm();
$data = array(
$this->createUploadedFileMock('abcdef', 'first.jpg', true),
$this->createUploadedFileMock('zyxwvu', 'second.jpg', true),
);
$form->setData($data);
$this->assertSame($data, $form->getData());
}
public function testSubmitMultiple()
{
$form = $this->factory->createBuilder(static::TESTED_TYPE, null, array(
'multiple' => true,
))->getForm();
$data = array(
$this->createUploadedFileMock('abcdef', 'first.jpg', true),
$this->createUploadedFileMock('zyxwvu', 'second.jpg', true),
);
$form->submit($data);
$this->assertSame($data, $form->getData());
$view = $form->createView();
$this->assertSame('file[]', $view->vars['full_name']);
$this->assertArrayHasKey('multiple', $view->vars['attr']);
}
public function testDontPassValueToView()
{
$form = $this->factory->create(static::TESTED_TYPE);
$form->submit(array(
'file' => $this->createUploadedFileMock('abcdef', 'original.jpg', true),
));
$this->assertEquals('', $form->createView()->vars['value']);
}
public function testPassMultipartFalseToView()
{
$view = $this->factory->create(static::TESTED_TYPE)
->createView();
$this->assertTrue($view->vars['multipart']);
}
public function testSubmitNull($expected = null, $norm = null, $view = null)
{
parent::testSubmitNull($expected, $norm, '');
}
public function testSubmitNullWhenMultiple()
{
$form = $this->factory->create(static::TESTED_TYPE, null, array(
'multiple' => true,
));
// submitted data when an input file is uploaded without choosing any file
$form->submit(array(null));
$this->assertSame(array(), $form->getData());
$this->assertSame(array(), $form->getNormData());
$this->assertSame(array(), $form->getViewData());
}
private function createUploadedFileMock($name, $originalName, $valid)
{
$file = $this
->getMockBuilder('Symfony\Component\HttpFoundation\File\UploadedFile')
->setConstructorArgs(array(__DIR__.'/../../../Fixtures/foo', 'foo'))
->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;
}
}

View File

@@ -0,0 +1,637 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\Extension\Core\Type;
use Symfony\Component\PropertyAccess\PropertyPath;
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
{
const TESTED_TYPE = 'Symfony\Component\Form\Extension\Core\Type\FormType';
public function testCreateFormInstances()
{
$this->assertInstanceOf('Symfony\Component\Form\Form', $this->factory->create(static::TESTED_TYPE));
}
public function testPassRequiredAsOption()
{
$form = $this->factory->create(static::TESTED_TYPE, null, array('required' => false));
$this->assertFalse($form->isRequired());
$form = $this->factory->create(static::TESTED_TYPE, null, array('required' => true));
$this->assertTrue($form->isRequired());
}
public function testSubmittedDataIsTrimmedBeforeTransforming()
{
$form = $this->factory->createBuilder(static::TESTED_TYPE)
->addViewTransformer(new FixedDataTransformer(array(
'' => '',
'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(static::TESTED_TYPE, null, array('trim' => false))
->addViewTransformer(new FixedDataTransformer(array(
'' => '',
'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', static::TESTED_TYPE, null, array('attr' => array('readonly' => true)))
->add('child', static::TESTED_TYPE)
->getForm()
->createView();
$this->assertTrue($view['child']->vars['attr']['readonly']);
}
public function testReadOnlyFormWithNonReadOnlyParentIsReadOnly()
{
$view = $this->factory->createNamedBuilder('parent', static::TESTED_TYPE)
->add('child', static::TESTED_TYPE, array('attr' => array('readonly' => true)))
->getForm()
->createView();
$this->assertTrue($view['child']->vars['attr']['readonly']);
}
public function testNonReadOnlyFormWithNonReadOnlyParentIsNotReadOnly()
{
$view = $this->factory->createNamedBuilder('parent', static::TESTED_TYPE)
->add('child', static::TESTED_TYPE)
->getForm()
->createView();
$this->assertArrayNotHasKey('readonly', $view['child']->vars['attr']);
}
public function testPassMaxLengthToView()
{
$view = $this->factory->create(static::TESTED_TYPE, null, array('attr' => array('maxlength' => 10)))
->createView();
$this->assertSame(10, $view->vars['attr']['maxlength']);
}
public function testDataClassMayBeNull()
{
$this->assertInstanceOf('Symfony\Component\Form\FormBuilderInterface', $this->factory->createBuilder(static::TESTED_TYPE, null, array(
'data_class' => null,
)));
}
public function testDataClassMayBeAbstractClass()
{
$this->assertInstanceOf('Symfony\Component\Form\FormBuilderInterface', $this->factory->createBuilder(static::TESTED_TYPE, null, array(
'data_class' => 'Symfony\Component\Form\Tests\Fixtures\AbstractAuthor',
)));
}
public function testDataClassMayBeInterface()
{
$this->assertInstanceOf('Symfony\Component\Form\FormBuilderInterface', $this->factory->createBuilder(static::TESTED_TYPE, null, array(
'data_class' => 'Symfony\Component\Form\Tests\Fixtures\AuthorInterface',
)));
}
/**
* @expectedException \Symfony\Component\Form\Exception\InvalidArgumentException
*/
public function testDataClassMustBeValidClassOrInterface()
{
$this->factory->createBuilder(static::TESTED_TYPE, null, array(
'data_class' => 'foobar',
));
}
public function testSubmitWithEmptyDataCreatesObjectIfClassAvailable()
{
$form = $this->factory->createBuilder(static::TESTED_TYPE, null, array(
'data_class' => 'Symfony\Component\Form\Tests\Fixtures\Author',
'required' => false,
))
->add('firstName', TextTypeTest::TESTED_TYPE)
->add('lastName', TextTypeTest::TESTED_TYPE)
->getForm();
$this->assertNull($form->getData());
// 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 testSubmitWithDefaultDataDontCreateObject()
{
$defaultAuthor = new Author();
$form = $this->factory->createBuilder(static::TESTED_TYPE, null, array(
// data class is inferred from the passed object
'data' => $defaultAuthor,
'required' => false,
))
->add('firstName', TextTypeTest::TESTED_TYPE)
->add('lastName', TextTypeTest::TESTED_TYPE)
->getForm();
// partially empty
$form->submit(array('firstName' => 'Bernhard', 'lastName' => ''));
$author = new Author();
$author->firstName = 'Bernhard';
$author->setLastName('');
$this->assertEquals($author, $form->getData());
$this->assertSame($defaultAuthor, $form->getData());
}
public function testSubmitWithEmptyDataCreatesArrayIfDataClassIsNull()
{
$form = $this->factory->createBuilder(static::TESTED_TYPE, null, array(
'data_class' => null,
'required' => false,
))
->add('firstName', TextTypeTest::TESTED_TYPE)
->getForm();
$this->assertNull($form->getData());
$form->submit(array('firstName' => 'Bernhard'));
$this->assertSame(array('firstName' => 'Bernhard'), $form->getData());
}
public function testSubmitEmptyWithEmptyDataDontCreateObjectIfNotRequired()
{
$form = $this->factory->createBuilder(static::TESTED_TYPE, null, array(
'data_class' => 'Symfony\Component\Form\Tests\Fixtures\Author',
'required' => false,
))
->add('firstName', TextTypeTest::TESTED_TYPE)
->add('lastName', TextTypeTest::TESTED_TYPE)
->getForm();
$this->assertNull($form->getData());
$form->submit(array('firstName' => '', 'lastName' => ''));
$this->assertNull($form->getData());
}
public function testSubmitEmptyWithEmptyDataCreatesObjectIfRequired()
{
$form = $this->factory->createBuilder(static::TESTED_TYPE, null, array(
'data_class' => 'Symfony\Component\Form\Tests\Fixtures\Author',
'required' => true,
))
->add('firstName', TextTypeTest::TESTED_TYPE)
->add('lastName', TextTypeTest::TESTED_TYPE)
->getForm();
$this->assertNull($form->getData());
$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(static::TESTED_TYPE)
->add('firstName', TextTypeTest::TESTED_TYPE)
->getForm();
$this->assertNull($form->getData());
$form->submit(array('firstName' => 'Bernhard'));
$this->assertSame(array('firstName' => 'Bernhard'), $form->getData());
}
public function testSubmitWithEmptyDataPassesEmptyStringToTransformerIfNotCompound()
{
$form = $this->factory->createBuilder(static::TESTED_TYPE)
->addViewTransformer(new FixedDataTransformer(array(
// required for the initial, internal setData(null)
'' => 'null',
// required to test that submit(null) is converted to ''
'empty' => '',
)))
->setCompound(false)
->getForm();
$this->assertNull($form->getData());
$this->assertNull($form->getNormData());
$this->assertSame('null', $form->getViewData());
$form->submit(null);
$this->assertSame('empty', $form->getData());
$this->assertSame('empty', $form->getNormData());
$this->assertSame('', $form->getViewData());
}
public function testSubmitWithEmptyDataUsesEmptyDataOption()
{
$author = new Author();
$form = $this->factory->createBuilder(static::TESTED_TYPE, null, array(
'data_class' => 'Symfony\Component\Form\Tests\Fixtures\Author',
'empty_data' => $author,
))
->add('firstName', TextTypeTest::TESTED_TYPE)
->getForm();
$this->assertNull($form->getData());
$this->assertNull($form->getViewData());
$form->submit(array('firstName' => 'Bernhard'));
$this->assertSame($author, $form->getData());
$this->assertEquals('Bernhard', $author->firstName);
}
/**
* @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException
*/
public function testAttributesException()
{
$this->factory->create(static::TESTED_TYPE, null, array('attr' => ''));
}
public function testNameCanBeEmptyString()
{
$form = $this->factory->createNamed('', static::TESTED_TYPE);
$this->assertEquals('', $form->getName());
}
public function testSubformDoesntCallSettersForReferences()
{
$author = new FormTest_AuthorWithoutRefSetter(new Author());
$builder = $this->factory->createBuilder(static::TESTED_TYPE, $author);
$builder->add('reference', static::TESTED_TYPE, array(
'data_class' => 'Symfony\Component\Form\Tests\Fixtures\Author',
));
$builder->get('reference')->add('firstName', TextTypeTest::TESTED_TYPE);
$form = $builder->getForm();
$form->submit(array(
// reference has a getter, but no 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(static::TESTED_TYPE, $author);
$builder->add('referenceCopy', static::TESTED_TYPE, array(
'data_class' => 'Symfony\Component\Form\Tests\Fixtures\Author',
));
$builder->get('referenceCopy')->add('firstName', TextTypeTest::TESTED_TYPE);
$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(static::TESTED_TYPE, $author);
$builder->add('referenceCopy', static::TESTED_TYPE, array(
'data_class' => 'Symfony\Component\Form\Tests\Fixtures\Author',
'by_reference' => false,
));
$builder->get('referenceCopy')->add('firstName', TextTypeTest::TESTED_TYPE);
$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(static::TESTED_TYPE, $author);
$builder->add('referenceCopy', static::TESTED_TYPE);
$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(static::TESTED_TYPE);
$builder->setData($author);
$builder->add('referenceCopy', static::TESTED_TYPE);
$builder->get('referenceCopy')->addViewTransformer(new CallbackTransformer(
function () {},
function ($value) use ($ref2) { // reverseTransform
return $ref2;
}
));
$form = $builder->getForm();
$form->submit(array(
'referenceCopy' => array(), // 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(static::TESTED_TYPE)
->add('foo', TextTypeTest::TESTED_TYPE)
->add('bar', FileTypeTest::TESTED_TYPE)
->getForm()
->createView();
$this->assertTrue($view->vars['multipart']);
}
public function testViewIsNotRenderedByDefault()
{
$view = $this->factory->createBuilder(static::TESTED_TYPE)
->add('foo', static::TESTED_TYPE)
->getForm()
->createView();
$this->assertFalse($view->isRendered());
}
public function testErrorBubblingIfCompound()
{
$form = $this->factory->create(static::TESTED_TYPE);
$this->assertTrue($form->getConfig()->getErrorBubbling());
}
public function testNoErrorBubblingIfNotCompound()
{
$form = $this->factory->create(static::TESTED_TYPE, null, array(
'compound' => false,
));
$this->assertFalse($form->getConfig()->getErrorBubbling());
}
public function testOverrideErrorBubbling()
{
$form = $this->factory->create(static::TESTED_TYPE, null, array(
'compound' => false,
'error_bubbling' => true,
));
$this->assertTrue($form->getConfig()->getErrorBubbling());
}
public function testPropertyPath()
{
$form = $this->factory->create(static::TESTED_TYPE, 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', static::TESTED_TYPE, null, array(
'property_path' => null,
));
$this->assertEquals(new PropertyPath('name'), $form->getPropertyPath());
$this->assertTrue($form->getConfig()->getMapped());
}
public function testNotMapped()
{
$form = $this->factory->create(static::TESTED_TYPE, null, array(
'property_path' => 'foo',
'mapped' => false,
));
$this->assertEquals(new PropertyPath('foo'), $form->getPropertyPath());
$this->assertFalse($form->getConfig()->getMapped());
}
public function testViewValidNotSubmitted()
{
$view = $this->factory->create(static::TESTED_TYPE)
->createView();
$this->assertTrue($view->vars['valid']);
}
public function testViewNotValidSubmitted()
{
$form = $this->factory->create(static::TESTED_TYPE);
$form->submit(array());
$form->addError(new FormError('An error'));
$this->assertFalse($form->createView()->vars['valid']);
}
public function testViewSubmittedNotSubmitted()
{
$view = $this->factory->create(static::TESTED_TYPE)
->createView();
$this->assertFalse($view->vars['submitted']);
}
public function testViewSubmittedSubmitted()
{
$form = $this->factory->create(static::TESTED_TYPE);
$form->submit(array());
$this->assertTrue($form->createView()->vars['submitted']);
}
public function testDataOptionSupersedesSetDataCalls()
{
$form = $this->factory->create(static::TESTED_TYPE, null, array(
'data' => 'default',
'compound' => false,
));
$form->setData('foobar');
$this->assertSame('default', $form->getData());
}
public function testPassedDataSupersedesSetDataCalls()
{
$form = $this->factory->create(static::TESTED_TYPE, 'default', array(
'compound' => false,
));
$form->setData('foobar');
$this->assertSame('default', $form->getData());
}
public function testDataOptionSupersedesSetDataCallsIfNull()
{
$form = $this->factory->create(static::TESTED_TYPE, null, array(
'data' => null,
'compound' => false,
));
$form->setData('foobar');
$this->assertNull($form->getData());
}
public function testNormDataIsPassedToView()
{
$view = $this->factory->createBuilder(static::TESTED_TYPE)
->addModelTransformer(new FixedDataTransformer(array(
'foo' => 'bar',
)))
->addViewTransformer(new FixedDataTransformer(array(
'bar' => 'baz',
)))
->setData('foo')
->getForm()
->createView();
$this->assertSame('bar', $view->vars['data']);
$this->assertSame('baz', $view->vars['value']);
}
// https://github.com/symfony/symfony/issues/6862
public function testPassZeroLabelToView()
{
$view = $this->factory->create(static::TESTED_TYPE, null, array(
'label' => '0',
))
->createView();
$this->assertSame('0', $view->vars['label']);
}
public function testSubmitNull($expected = null, $norm = null, $view = null)
{
parent::testSubmitNull(array(), array(), array());
}
}

View File

@@ -0,0 +1,41 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\Extension\Core\Type;
use Symfony\Component\Intl\Util\IntlTestHelper;
class IntegerTypeTest extends BaseTypeTest
{
const TESTED_TYPE = 'Symfony\Component\Form\Extension\Core\Type\IntegerType';
protected function setUp()
{
IntlTestHelper::requireIntl($this, false);
parent::setUp();
}
public function testSubmitCastsToInteger()
{
$form = $this->factory->create(static::TESTED_TYPE);
$form->submit('1.678');
$this->assertSame(1, $form->getData());
$this->assertSame('1', $form->getViewData());
}
public function testSubmitNull($expected = null, $norm = null, $view = null)
{
parent::testSubmitNull($expected, $norm, '');
}
}

View File

@@ -0,0 +1,52 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\Extension\Core\Type;
use Symfony\Component\Form\ChoiceList\View\ChoiceView;
use Symfony\Component\Intl\Util\IntlTestHelper;
class LanguageTypeTest extends BaseTypeTest
{
const TESTED_TYPE = 'Symfony\Component\Form\Extension\Core\Type\LanguageType';
protected function setUp()
{
IntlTestHelper::requireIntl($this, false);
parent::setUp();
}
public function testCountriesAreSelectable()
{
$choices = $this->factory->create(static::TESTED_TYPE)
->createView()->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', 'American 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()
{
$choices = $this->factory->create(static::TESTED_TYPE, 'language')
->createView()->vars['choices'];
$this->assertNotContains(new ChoiceView('mul', 'mul', 'Mehrsprachig'), $choices, '', false, false);
}
public function testSubmitNull($expected = null, $norm = null, $view = null)
{
parent::testSubmitNull($expected, $norm, '');
}
}

View File

@@ -0,0 +1,42 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\Extension\Core\Type;
use Symfony\Component\Form\ChoiceList\View\ChoiceView;
use Symfony\Component\Intl\Util\IntlTestHelper;
class LocaleTypeTest extends BaseTypeTest
{
const TESTED_TYPE = 'Symfony\Component\Form\Extension\Core\Type\LocaleType';
protected function setUp()
{
IntlTestHelper::requireIntl($this, false);
parent::setUp();
}
public function testLocalesAreSelectable()
{
$choices = $this->factory->create(static::TESTED_TYPE)
->createView()->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);
}
public function testSubmitNull($expected = null, $norm = null, $view = null)
{
parent::testSubmitNull($expected, $norm, '');
}
}

View File

@@ -0,0 +1,65 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\Extension\Core\Type;
use Symfony\Component\Intl\Util\IntlTestHelper;
class MoneyTypeTest extends BaseTypeTest
{
const TESTED_TYPE = 'Symfony\Component\Form\Extension\Core\Type\MoneyType';
protected function setUp()
{
// we test against different locales, so we need the full
// implementation
IntlTestHelper::requireFullIntl($this, false);
parent::setUp();
}
public function testPassMoneyPatternToView()
{
\Locale::setDefault('de_DE');
$view = $this->factory->create(static::TESTED_TYPE)
->createView();
$this->assertSame('{{ widget }} €', $view->vars['money_pattern']);
}
public function testMoneyPatternWorksForYen()
{
\Locale::setDefault('en_US');
$view = $this->factory->create(static::TESTED_TYPE, null, array('currency' => 'JPY'))
->createView();
$this->assertTrue((bool) strstr($view->vars['money_pattern'], '¥'));
}
// https://github.com/symfony/symfony/issues/5458
public function testPassDifferentPatternsForDifferentCurrencies()
{
\Locale::setDefault('de_DE');
$view1 = $this->factory->create(static::TESTED_TYPE, null, array('currency' => 'GBP'))->createView();
$view2 = $this->factory->create(static::TESTED_TYPE, null, array('currency' => 'EUR'))->createView();
$this->assertSame('{{ widget }} £', $view1->vars['money_pattern']);
$this->assertSame('{{ widget }} €', $view2->vars['money_pattern']);
}
public function testSubmitNull($expected = null, $norm = null, $view = null)
{
parent::testSubmitNull($expected, $norm, '');
}
}

View File

@@ -0,0 +1,66 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\Extension\Core\Type;
use Symfony\Component\Intl\Util\IntlTestHelper;
class NumberTypeTest extends BaseTypeTest
{
const TESTED_TYPE = 'Symfony\Component\Form\Extension\Core\Type\NumberType';
protected function setUp()
{
parent::setUp();
// we test against "de_DE", so we need the full implementation
IntlTestHelper::requireFullIntl($this, false);
\Locale::setDefault('de_DE');
}
public function testDefaultFormatting()
{
$form = $this->factory->create(static::TESTED_TYPE);
$form->setData('12345.67890');
$this->assertSame('12345,679', $form->createView()->vars['value']);
}
public function testDefaultFormattingWithGrouping()
{
$form = $this->factory->create(static::TESTED_TYPE, null, array('grouping' => true));
$form->setData('12345.67890');
$this->assertSame('12.345,679', $form->createView()->vars['value']);
}
public function testDefaultFormattingWithScale()
{
$form = $this->factory->create(static::TESTED_TYPE, null, array('scale' => 2));
$form->setData('12345.67890');
$this->assertSame('12345,68', $form->createView()->vars['value']);
}
public function testDefaultFormattingWithRounding()
{
$form = $this->factory->create(static::TESTED_TYPE, null, array('scale' => 0, 'rounding_mode' => \NumberFormatter::ROUND_UP));
$form->setData('12345.54321');
$this->assertSame('12346', $form->createView()->vars['value']);
}
public function testSubmitNull($expected = null, $norm = null, $view = null)
{
parent::testSubmitNull($expected, $norm, '');
}
}

View File

@@ -0,0 +1,54 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\Extension\Core\Type;
class PasswordTypeTest extends BaseTypeTest
{
const TESTED_TYPE = 'Symfony\Component\Form\Extension\Core\Type\PasswordType';
public function testEmptyIfNotSubmitted()
{
$form = $this->factory->create(static::TESTED_TYPE);
$form->setData('pAs5w0rd');
$this->assertSame('', $form->createView()->vars['value']);
}
public function testEmptyIfSubmitted()
{
$form = $this->factory->create(static::TESTED_TYPE);
$form->submit('pAs5w0rd');
$this->assertSame('', $form->createView()->vars['value']);
}
public function testNotEmptyIfSubmittedAndNotAlwaysEmpty()
{
$form = $this->factory->create(static::TESTED_TYPE, null, array('always_empty' => false));
$form->submit('pAs5w0rd');
$this->assertSame('pAs5w0rd', $form->createView()->vars['value']);
}
public function testNotTrimmed()
{
$form = $this->factory->create(static::TESTED_TYPE, null);
$form->submit(' pAs5w0rd ');
$this->assertSame(' pAs5w0rd ', $form->getData());
}
public function testSubmitNull($expected = null, $norm = null, $view = null)
{
parent::testSubmitNull($expected, $norm, '');
}
}

View File

@@ -0,0 +1,193 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\Extension\Core\Type;
use Symfony\Component\Form\Form;
class RepeatedTypeTest extends BaseTypeTest
{
const TESTED_TYPE = 'Symfony\Component\Form\Extension\Core\Type\RepeatedType';
/**
* @var Form
*/
protected $form;
protected function setUp()
{
parent::setUp();
$this->form = $this->factory->create(static::TESTED_TYPE, null, array(
'type' => TextTypeTest::TESTED_TYPE,
));
}
public function testSetData()
{
$this->form->setData('foobar');
$this->assertSame('foobar', $this->form['first']->getData());
$this->assertSame('foobar', $this->form['second']->getData());
}
public function testSetOptions()
{
$form = $this->factory->create(static::TESTED_TYPE, null, array(
'type' => TextTypeTest::TESTED_TYPE,
'options' => array('label' => 'Global'),
));
$this->assertSame('Global', $form['first']->getConfig()->getOption('label'));
$this->assertSame('Global', $form['second']->getConfig()->getOption('label'));
$this->assertTrue($form['first']->isRequired());
$this->assertTrue($form['second']->isRequired());
}
public function testSetOptionsPerChild()
{
$form = $this->factory->create(static::TESTED_TYPE, null, array(
// the global required value cannot be overridden
'type' => TextTypeTest::TESTED_TYPE,
'first_options' => array('label' => 'Test', 'required' => false),
'second_options' => array('label' => 'Test2'),
));
$this->assertSame('Test', $form['first']->getConfig()->getOption('label'));
$this->assertSame('Test2', $form['second']->getConfig()->getOption('label'));
$this->assertTrue($form['first']->isRequired());
$this->assertTrue($form['second']->isRequired());
}
public function testSetRequired()
{
$form = $this->factory->create(static::TESTED_TYPE, null, array(
'required' => false,
'type' => TextTypeTest::TESTED_TYPE,
));
$this->assertFalse($form['first']->isRequired());
$this->assertFalse($form['second']->isRequired());
}
/**
* @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException
*/
public function testSetInvalidOptions()
{
$this->factory->create(static::TESTED_TYPE, null, array(
'type' => TextTypeTest::TESTED_TYPE,
'options' => 'bad value',
));
}
/**
* @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException
*/
public function testSetInvalidFirstOptions()
{
$this->factory->create(static::TESTED_TYPE, null, array(
'type' => TextTypeTest::TESTED_TYPE,
'first_options' => 'bad value',
));
}
/**
* @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException
*/
public function testSetInvalidSecondOptions()
{
$this->factory->create(static::TESTED_TYPE, null, array(
'type' => TextTypeTest::TESTED_TYPE,
'second_options' => 'bad value',
));
}
public function testSetErrorBubblingToTrue()
{
$form = $this->factory->create(static::TESTED_TYPE, 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(static::TESTED_TYPE, 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(static::TESTED_TYPE, 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(static::TESTED_TYPE, null, array(
'type' => TextTypeTest::TESTED_TYPE,
'options' => array('label' => 'Label'),
'second_options' => array('label' => 'Second label'),
));
$this->assertSame('Label', $form['first']->getConfig()->getOption('label'));
$this->assertSame('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->assertSame('foo', $this->form['first']->getViewData());
$this->assertSame('bar', $this->form['second']->getViewData());
$this->assertFalse($this->form->isSynchronized());
$this->assertSame($input, $this->form->getViewData());
$this->assertNull($this->form->getData());
}
public function testSubmitEqual()
{
$input = array('first' => 'foo', 'second' => 'foo');
$this->form->submit($input);
$this->assertSame('foo', $this->form['first']->getViewData());
$this->assertSame('foo', $this->form['second']->getViewData());
$this->assertTrue($this->form->isSynchronized());
$this->assertSame($input, $this->form->getViewData());
$this->assertSame('foo', $this->form->getData());
}
public function testSubmitNull($expected = null, $norm = null, $view = null)
{
parent::testSubmitNull($expected, $norm, array('first' => null, 'second' => null));
}
}

View File

@@ -0,0 +1,65 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\Extension\Core\Type;
/**
* @author Bernhard Schussek <bschussek@gmail.com>
*/
class SubmitTypeTest extends ButtonTypeTest
{
const TESTED_TYPE = 'Symfony\Component\Form\Extension\Core\Type\SubmitType';
public function testCreateSubmitButtonInstances()
{
$this->assertInstanceOf('Symfony\Component\Form\SubmitButton', $this->factory->create(static::TESTED_TYPE));
}
public function testNotClickedByDefault()
{
$button = $this->factory->create(static::TESTED_TYPE);
$this->assertFalse($button->isClicked());
}
public function testNotClickedIfSubmittedWithNull()
{
$button = $this->factory->create(static::TESTED_TYPE);
$button->submit(null);
$this->assertFalse($button->isClicked());
}
public function testClickedIfSubmittedWithEmptyString()
{
$button = $this->factory->create(static::TESTED_TYPE);
$button->submit('');
$this->assertTrue($button->isClicked());
}
public function testClickedIfSubmittedWithUnemptyString()
{
$button = $this->factory->create(static::TESTED_TYPE);
$button->submit('foo');
$this->assertTrue($button->isClicked());
}
public function testSubmitCanBeAddedToForm()
{
$form = $this->factory
->createBuilder(FormTypeTest::TESTED_TYPE)
->getForm();
$this->assertSame($form, $form->add('send', static::TESTED_TYPE));
}
}

View File

@@ -0,0 +1,61 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\Extension\Core\Type;
class TextTypeTest extends BaseTypeTest
{
const TESTED_TYPE = 'Symfony\Component\Form\Extension\Core\Type\TextType';
public function testSubmitNull($expected = null, $norm = null, $view = null)
{
parent::testSubmitNull($expected, $norm, '');
}
public function testSubmitNullReturnsNullWithEmptyDataAsString()
{
$form = $this->factory->create(static::TESTED_TYPE, 'name', array(
'empty_data' => '',
));
$form->submit(null);
$this->assertSame('', $form->getData());
$this->assertSame('', $form->getNormData());
$this->assertSame('', $form->getViewData());
}
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(static::TESTED_TYPE, null, array(
'data' => $data,
));
$view = $form->createView();
$this->assertFalse($form->isEmpty());
$this->assertSame($dataAsString, $view->vars['value']);
$this->assertSame($dataAsString, $form->getData());
}
}

View File

@@ -0,0 +1,771 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\Extension\Core\Type;
use Symfony\Component\Form\ChoiceList\View\ChoiceView;
use Symfony\Component\Form\FormError;
class TimeTypeTest extends BaseTypeTest
{
const TESTED_TYPE = 'Symfony\Component\Form\Extension\Core\Type\TimeType';
public function testSubmitDateTime()
{
$form = $this->factory->create(static::TESTED_TYPE, 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(static::TESTED_TYPE, 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(static::TESTED_TYPE, 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(static::TESTED_TYPE, 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(static::TESTED_TYPE, 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(static::TESTED_TYPE, 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(static::TESTED_TYPE, 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(static::TESTED_TYPE, 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(static::TESTED_TYPE, 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(static::TESTED_TYPE, 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(static::TESTED_TYPE, 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 testSubmitWithSecondsAndBrowserOmissionSeconds()
{
$form = $this->factory->create(static::TESTED_TYPE, null, array(
'model_timezone' => 'UTC',
'view_timezone' => 'UTC',
'input' => 'string',
'widget' => 'single_text',
'with_seconds' => true,
));
$form->submit('03:04');
$this->assertEquals('03:04:00', $form->getData());
$this->assertEquals('03:04:00', $form->getViewData());
}
public function testSetDataWithoutMinutes()
{
$form = $this->factory->create(static::TESTED_TYPE, 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(static::TESTED_TYPE, 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(static::TESTED_TYPE, 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(static::TESTED_TYPE, 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(static::TESTED_TYPE, 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(static::TESTED_TYPE, 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(static::TESTED_TYPE, 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(static::TESTED_TYPE, 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(static::TESTED_TYPE, 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(static::TESTED_TYPE, 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(static::TESTED_TYPE, 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(static::TESTED_TYPE, 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(static::TESTED_TYPE, 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(static::TESTED_TYPE, null, array(
'widget' => 'choice',
'with_seconds' => true,
));
$form->submit(array(
'hour' => '0',
'minute' => '0',
'second' => '',
));
$this->assertTrue($form->isPartiallyFilled());
}
public function testInitializeWithDateTime()
{
// Throws an exception if "data_class" option is not explicitly set
// to null in the type
$this->assertInstanceOf('Symfony\Component\Form\FormInterface', $this->factory->create(static::TESTED_TYPE, new \DateTime()));
}
public function testSingleTextWidgetShouldUseTheRightInputType()
{
$form = $this->factory->create(static::TESTED_TYPE, null, array(
'widget' => 'single_text',
));
$view = $form->createView();
$this->assertEquals('time', $view->vars['type']);
}
public function testSingleTextWidgetWithSecondsShouldHaveRightStepAttribute()
{
$form = $this->factory->create(static::TESTED_TYPE, null, array(
'widget' => 'single_text',
'with_seconds' => true,
));
$view = $form->createView();
$this->assertArrayHasKey('step', $view->vars['attr']);
$this->assertEquals(1, $view->vars['attr']['step']);
}
public function testSingleTextWidgetWithSecondsShouldNotOverrideStepAttribute()
{
$form = $this->factory->create(static::TESTED_TYPE, null, array(
'widget' => 'single_text',
'with_seconds' => true,
'attr' => array(
'step' => 30,
),
));
$view = $form->createView();
$this->assertArrayHasKey('step', $view->vars['attr']);
$this->assertEquals(30, $view->vars['attr']['step']);
}
public function testDontPassHtml5TypeIfHtml5NotAllowed()
{
$form = $this->factory->create(static::TESTED_TYPE, null, array(
'widget' => 'single_text',
'html5' => false,
));
$view = $form->createView();
$this->assertFalse(isset($view->vars['type']));
}
public function testPassDefaultPlaceholderToViewIfNotRequired()
{
$form = $this->factory->create(static::TESTED_TYPE, null, array(
'required' => false,
'with_seconds' => true,
));
$view = $form->createView();
$this->assertSame('', $view['hour']->vars['placeholder']);
$this->assertSame('', $view['minute']->vars['placeholder']);
$this->assertSame('', $view['second']->vars['placeholder']);
}
public function testPassNoPlaceholderToViewIfRequired()
{
$form = $this->factory->create(static::TESTED_TYPE, null, array(
'required' => true,
'with_seconds' => true,
));
$view = $form->createView();
$this->assertNull($view['hour']->vars['placeholder']);
$this->assertNull($view['minute']->vars['placeholder']);
$this->assertNull($view['second']->vars['placeholder']);
}
public function testPassPlaceholderAsString()
{
$form = $this->factory->create(static::TESTED_TYPE, null, array(
'placeholder' => 'Empty',
'with_seconds' => true,
));
$view = $form->createView();
$this->assertSame('Empty', $view['hour']->vars['placeholder']);
$this->assertSame('Empty', $view['minute']->vars['placeholder']);
$this->assertSame('Empty', $view['second']->vars['placeholder']);
}
public function testPassPlaceholderAsArray()
{
$form = $this->factory->create(static::TESTED_TYPE, null, array(
'placeholder' => array(
'hour' => 'Empty hour',
'minute' => 'Empty minute',
'second' => 'Empty second',
),
'with_seconds' => true,
));
$view = $form->createView();
$this->assertSame('Empty hour', $view['hour']->vars['placeholder']);
$this->assertSame('Empty minute', $view['minute']->vars['placeholder']);
$this->assertSame('Empty second', $view['second']->vars['placeholder']);
}
public function testPassPlaceholderAsPartialArrayAddEmptyIfNotRequired()
{
$form = $this->factory->create(static::TESTED_TYPE, null, array(
'required' => false,
'placeholder' => array(
'hour' => 'Empty hour',
'second' => 'Empty second',
),
'with_seconds' => true,
));
$view = $form->createView();
$this->assertSame('Empty hour', $view['hour']->vars['placeholder']);
$this->assertSame('', $view['minute']->vars['placeholder']);
$this->assertSame('Empty second', $view['second']->vars['placeholder']);
}
public function testPassPlaceholderAsPartialArrayAddNullIfRequired()
{
$form = $this->factory->create(static::TESTED_TYPE, null, array(
'required' => true,
'placeholder' => array(
'hour' => 'Empty hour',
'second' => 'Empty second',
),
'with_seconds' => true,
));
$view = $form->createView();
$this->assertSame('Empty hour', $view['hour']->vars['placeholder']);
$this->assertNull($view['minute']->vars['placeholder']);
$this->assertSame('Empty second', $view['second']->vars['placeholder']);
}
public function provideCompoundWidgets()
{
return array(
array('text'),
array('choice'),
);
}
/**
* @dataProvider provideCompoundWidgets
*/
public function testHourErrorsBubbleUp($widget)
{
$error = new FormError('Invalid!');
$form = $this->factory->create(static::TESTED_TYPE, null, array(
'widget' => $widget,
));
$form['hour']->addError($error);
$this->assertSame(array(), iterator_to_array($form['hour']->getErrors()));
$this->assertSame(array($error), iterator_to_array($form->getErrors()));
}
/**
* @dataProvider provideCompoundWidgets
*/
public function testMinuteErrorsBubbleUp($widget)
{
$error = new FormError('Invalid!');
$form = $this->factory->create(static::TESTED_TYPE, null, array(
'widget' => $widget,
));
$form['minute']->addError($error);
$this->assertSame(array(), iterator_to_array($form['minute']->getErrors()));
$this->assertSame(array($error), iterator_to_array($form->getErrors()));
}
/**
* @dataProvider provideCompoundWidgets
*/
public function testSecondErrorsBubbleUp($widget)
{
$error = new FormError('Invalid!');
$form = $this->factory->create(static::TESTED_TYPE, null, array(
'widget' => $widget,
'with_seconds' => true,
));
$form['second']->addError($error);
$this->assertSame(array(), iterator_to_array($form['second']->getErrors()));
$this->assertSame(array($error), iterator_to_array($form->getErrors()));
}
/**
* @expectedException \Symfony\Component\Form\Exception\InvalidConfigurationException
*/
public function testInitializeWithSecondsAndWithoutMinutes()
{
$this->factory->create(static::TESTED_TYPE, null, array(
'with_minutes' => false,
'with_seconds' => true,
));
}
/**
* @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException
*/
public function testThrowExceptionIfHoursIsInvalid()
{
$this->factory->create(static::TESTED_TYPE, null, array(
'hours' => 'bad value',
));
}
/**
* @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException
*/
public function testThrowExceptionIfMinutesIsInvalid()
{
$this->factory->create(static::TESTED_TYPE, null, array(
'minutes' => 'bad value',
));
}
/**
* @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException
*/
public function testThrowExceptionIfSecondsIsInvalid()
{
$this->factory->create(static::TESTED_TYPE, null, array(
'seconds' => 'bad value',
));
}
public function testPassDefaultChoiceTranslationDomain()
{
$form = $this->factory->create(static::TESTED_TYPE);
$view = $form->createView();
$this->assertFalse($view['hour']->vars['choice_translation_domain']);
$this->assertFalse($view['minute']->vars['choice_translation_domain']);
}
public function testPassChoiceTranslationDomainAsString()
{
$form = $this->factory->create(static::TESTED_TYPE, null, array(
'choice_translation_domain' => 'messages',
'with_seconds' => true,
));
$view = $form->createView();
$this->assertSame('messages', $view['hour']->vars['choice_translation_domain']);
$this->assertSame('messages', $view['minute']->vars['choice_translation_domain']);
$this->assertSame('messages', $view['second']->vars['choice_translation_domain']);
}
public function testPassChoiceTranslationDomainAsArray()
{
$form = $this->factory->create(static::TESTED_TYPE, null, array(
'choice_translation_domain' => array(
'hour' => 'foo',
'second' => 'test',
),
'with_seconds' => true,
));
$view = $form->createView();
$this->assertSame('foo', $view['hour']->vars['choice_translation_domain']);
$this->assertFalse($view['minute']->vars['choice_translation_domain']);
$this->assertSame('test', $view['second']->vars['choice_translation_domain']);
}
public function testSubmitNull($expected = null, $norm = null, $view = null)
{
$view = array('hour' => '', 'minute' => '');
parent::testSubmitNull($expected, $norm, $view);
}
}

View File

@@ -0,0 +1,36 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\Extension\Core\Type;
use Symfony\Component\Form\ChoiceList\View\ChoiceView;
class TimezoneTypeTest extends BaseTypeTest
{
const TESTED_TYPE = 'Symfony\Component\Form\Extension\Core\Type\TimezoneType';
public function testTimezonesAreSelectable()
{
$choices = $this->factory->create(static::TESTED_TYPE)
->createView()->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);
}
public function testSubmitNull($expected = null, $norm = null, $view = null)
{
parent::testSubmitNull($expected, $norm, '');
}
}

View File

@@ -0,0 +1,85 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\Extension\Core\Type;
class UrlTypeTest extends TextTypeTest
{
const TESTED_TYPE = 'Symfony\Component\Form\Extension\Core\Type\UrlType';
public function testSubmitAddsDefaultProtocolIfNoneIsIncluded()
{
$form = $this->factory->create(static::TESTED_TYPE, '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(static::TESTED_TYPE, 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(static::TESTED_TYPE, null, array(
'default_protocol' => 'http',
));
$form->submit('');
$this->assertNull($form->getData());
$this->assertSame('', $form->getViewData());
}
public function testSubmitAddsNoDefaultProtocolIfNull()
{
$form = $this->factory->create(static::TESTED_TYPE, null, array(
'default_protocol' => 'http',
));
$form->submit(null);
$this->assertNull($form->getData());
$this->assertSame('', $form->getViewData());
}
public function testSubmitAddsNoDefaultProtocolIfSetToNull()
{
$form = $this->factory->create(static::TESTED_TYPE, null, array(
'default_protocol' => null,
));
$form->submit('www.domain.com');
$this->assertSame('www.domain.com', $form->getData());
$this->assertSame('www.domain.com', $form->getViewData());
}
/**
* @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException
*/
public function testThrowExceptionIfDefaultProtocolIsInvalid()
{
$this->factory->create(static::TESTED_TYPE, null, array(
'default_protocol' => array(),
));
}
}

View File

@@ -0,0 +1,97 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\Extension\Csrf\EventListener;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Form\FormBuilder;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\Extension\Csrf\EventListener\CsrfValidationListener;
class CsrfValidationListenerTest extends TestCase
{
protected $dispatcher;
protected $factory;
protected $tokenManager;
protected $form;
protected function setUp()
{
$this->dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcherInterface')->getMock();
$this->factory = $this->getMockBuilder('Symfony\Component\Form\FormFactoryInterface')->getMock();
$this->tokenManager = $this->getMockBuilder('Symfony\Component\Security\Csrf\CsrfTokenManagerInterface')->getMock();
$this->form = $this->getBuilder('post')
->setDataMapper($this->getDataMapper())
->getForm();
}
protected function tearDown()
{
$this->dispatcher = null;
$this->factory = null;
$this->tokenManager = 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->getMockBuilder('Symfony\Component\Form\DataMapperInterface')->getMock();
}
protected function getMockForm()
{
return $this->getMockBuilder('Symfony\Component\Form\Test\FormInterface')->getMock();
}
// https://github.com/symfony/symfony/pull/5838
public function testStringFormData()
{
$data = 'XP4HUzmHPi';
$event = new FormEvent($this->form, $data);
$validation = new CsrfValidationListener('csrf', $this->tokenManager, 'unknown', 'Invalid.');
$validation->preSubmit($event);
// Validate accordingly
$this->assertSame($data, $event->getData());
}
public function testMaxPostSizeExceeded()
{
$serverParams = $this
->getMockBuilder('\Symfony\Component\Form\Util\ServerParams')
->disableOriginalConstructor()
->getMock()
;
$serverParams
->expects($this->once())
->method('hasPostMaxSizeBeenExceeded')
->willReturn(true)
;
$event = new FormEvent($this->form, array('csrf' => 'token'));
$validation = new CsrfValidationListener('csrf', $this->tokenManager, 'unknown', 'Error message', null, null, $serverParams);
$validation->preSubmit($event);
$this->assertEmpty($this->form->getErrors());
}
}

View File

@@ -0,0 +1,397 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\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;
use Symfony\Component\Security\Csrf\CsrfToken;
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', 'Symfony\Component\Form\Extension\Core\Type\TextType');
}
}
class FormTypeCsrfExtensionTest extends TypeTestCase
{
/**
* @var \PHPUnit_Framework_MockObject_MockObject
*/
protected $tokenManager;
/**
* @var \PHPUnit_Framework_MockObject_MockObject
*/
protected $translator;
protected function setUp()
{
$this->tokenManager = $this->getMockBuilder('Symfony\Component\Security\Csrf\CsrfTokenManagerInterface')->getMock();
$this->translator = $this->getMockBuilder('Symfony\Component\Translation\TranslatorInterface')->getMock();
parent::setUp();
}
protected function tearDown()
{
$this->tokenManager = null;
$this->translator = null;
parent::tearDown();
}
protected function getExtensions()
{
return array_merge(parent::getExtensions(), array(
new CsrfExtension($this->tokenManager, $this->translator),
));
}
public function testCsrfProtectionByDefaultIfRootAndCompound()
{
$view = $this->factory
->create('Symfony\Component\Form\Extension\Core\Type\FormType', null, array(
'csrf_field_name' => 'csrf',
'compound' => true,
))
->createView();
$this->assertTrue(isset($view['csrf']));
}
public function testNoCsrfProtectionByDefaultIfCompoundButNotRoot()
{
$view = $this->factory
->createNamedBuilder('root', 'Symfony\Component\Form\Extension\Core\Type\FormType')
->add($this->factory
->createNamedBuilder('form', 'Symfony\Component\Form\Extension\Core\Type\FormType', null, array(
'csrf_field_name' => 'csrf',
'compound' => true,
))
)
->getForm()
->get('form')
->createView();
$this->assertFalse(isset($view['csrf']));
}
public function testNoCsrfProtectionByDefaultIfRootButNotCompound()
{
$view = $this->factory
->create('Symfony\Component\Form\Extension\Core\Type\FormType', null, array(
'csrf_field_name' => 'csrf',
'compound' => false,
))
->createView();
$this->assertFalse(isset($view['csrf']));
}
public function testCsrfProtectionCanBeDisabled()
{
$view = $this->factory
->create('Symfony\Component\Form\Extension\Core\Type\FormType', null, array(
'csrf_field_name' => 'csrf',
'csrf_protection' => false,
'compound' => true,
))
->createView();
$this->assertFalse(isset($view['csrf']));
}
public function testGenerateCsrfToken()
{
$this->tokenManager->expects($this->once())
->method('getToken')
->with('TOKEN_ID')
->will($this->returnValue(new CsrfToken('TOKEN_ID', 'token')));
$view = $this->factory
->create('Symfony\Component\Form\Extension\Core\Type\FormType', null, array(
'csrf_field_name' => 'csrf',
'csrf_token_manager' => $this->tokenManager,
'csrf_token_id' => 'TOKEN_ID',
'compound' => true,
))
->createView();
$this->assertEquals('token', $view['csrf']->vars['value']);
}
public function testGenerateCsrfTokenUsesFormNameAsIntentionByDefault()
{
$this->tokenManager->expects($this->once())
->method('getToken')
->with('FORM_NAME')
->will($this->returnValue('token'));
$view = $this->factory
->createNamed('FORM_NAME', 'Symfony\Component\Form\Extension\Core\Type\FormType', null, array(
'csrf_field_name' => 'csrf',
'csrf_token_manager' => $this->tokenManager,
'compound' => true,
))
->createView();
$this->assertEquals('token', $view['csrf']->vars['value']);
}
public function testGenerateCsrfTokenUsesTypeClassAsIntentionIfEmptyFormName()
{
$this->tokenManager->expects($this->once())
->method('getToken')
->with('Symfony\Component\Form\Extension\Core\Type\FormType')
->will($this->returnValue('token'));
$view = $this->factory
->createNamed('', 'Symfony\Component\Form\Extension\Core\Type\FormType', null, array(
'csrf_field_name' => 'csrf',
'csrf_token_manager' => $this->tokenManager,
'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->tokenManager->expects($this->once())
->method('isTokenValid')
->with(new CsrfToken('TOKEN_ID', 'token'))
->will($this->returnValue($valid));
$form = $this->factory
->createBuilder('Symfony\Component\Form\Extension\Core\Type\FormType', null, array(
'csrf_field_name' => 'csrf',
'csrf_token_manager' => $this->tokenManager,
'csrf_token_id' => 'TOKEN_ID',
'compound' => true,
))
->add('child', 'Symfony\Component\Form\Extension\Core\Type\TextType')
->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());
}
/**
* @dataProvider provideBoolean
*/
public function testValidateTokenOnSubmitIfRootAndCompoundUsesFormNameAsIntentionByDefault($valid)
{
$this->tokenManager->expects($this->once())
->method('isTokenValid')
->with(new CsrfToken('FORM_NAME', 'token'))
->will($this->returnValue($valid));
$form = $this->factory
->createNamedBuilder('FORM_NAME', 'Symfony\Component\Form\Extension\Core\Type\FormType', null, array(
'csrf_field_name' => 'csrf',
'csrf_token_manager' => $this->tokenManager,
'compound' => true,
))
->add('child', 'Symfony\Component\Form\Extension\Core\Type\TextType')
->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());
}
/**
* @dataProvider provideBoolean
*/
public function testValidateTokenOnSubmitIfRootAndCompoundUsesTypeClassAsIntentionIfEmptyFormName($valid)
{
$this->tokenManager->expects($this->once())
->method('isTokenValid')
->with(new CsrfToken('Symfony\Component\Form\Extension\Core\Type\FormType', 'token'))
->will($this->returnValue($valid));
$form = $this->factory
->createNamedBuilder('', 'Symfony\Component\Form\Extension\Core\Type\FormType', null, array(
'csrf_field_name' => 'csrf',
'csrf_token_manager' => $this->tokenManager,
'compound' => true,
))
->add('child', 'Symfony\Component\Form\Extension\Core\Type\TextType')
->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->tokenManager->expects($this->never())
->method('isTokenValid');
$form = $this->factory
->createBuilder('Symfony\Component\Form\Extension\Core\Type\FormType', null, array(
'csrf_field_name' => 'csrf',
'csrf_token_manager' => $this->tokenManager,
'csrf_token_id' => 'TOKEN_ID',
'compound' => true,
))
->add('child', 'Symfony\Component\Form\Extension\Core\Type\TextType')
->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->tokenManager->expects($this->never())
->method('isTokenValid');
$form = $this->factory
->createNamedBuilder('root', 'Symfony\Component\Form\Extension\Core\Type\FormType')
->add($this->factory
->createNamedBuilder('form', 'Symfony\Component\Form\Extension\Core\Type\FormType', null, array(
'csrf_field_name' => 'csrf',
'csrf_token_manager' => $this->tokenManager,
'csrf_token_id' => 'TOKEN_ID',
'compound' => true,
))
)
->getForm()
->get('form');
$form->submit(array(
'child' => 'foobar',
'csrf' => 'token',
));
}
public function testDontValidateTokenIfRootButNotCompound()
{
$this->tokenManager->expects($this->never())
->method('isTokenValid');
$form = $this->factory
->create('Symfony\Component\Form\Extension\Core\Type\FormType', null, array(
'csrf_field_name' => 'csrf',
'csrf_token_manager' => $this->tokenManager,
'csrf_token_id' => 'TOKEN_ID',
'compound' => false,
));
$form->submit(array(
'csrf' => 'token',
));
}
public function testNoCsrfProtectionOnPrototype()
{
$prototypeView = $this->factory
->create('Symfony\Component\Form\Extension\Core\Type\CollectionType', null, array(
'entry_type' => __CLASS__.'_ChildType',
'entry_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->tokenManager->expects($this->once())
->method('isTokenValid')
->with(new CsrfToken('TOKEN_ID', 'token'))
->will($this->returnValue(false));
$this->translator->expects($this->once())
->method('trans')
->with('Foobar')
->will($this->returnValue('[trans]Foobar[/trans]'));
$form = $this->factory
->createBuilder('Symfony\Component\Form\Extension\Core\Type\FormType', null, array(
'csrf_field_name' => 'csrf',
'csrf_token_manager' => $this->tokenManager,
'csrf_message' => 'Foobar',
'csrf_token_id' => 'TOKEN_ID',
'compound' => true,
))
->getForm();
$form->submit(array(
'csrf' => 'token',
));
$errors = $form->getErrors();
$expected = new FormError('[trans]Foobar[/trans]');
$expected->setOrigin($form);
$this->assertGreaterThan(0, count($errors));
$this->assertEquals($expected, $errors[0]);
}
}

View File

@@ -0,0 +1,43 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\Extension\DataCollector;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Form\Extension\DataCollector\DataCollectorExtension;
class DataCollectorExtensionTest extends TestCase
{
/**
* @var DataCollectorExtension
*/
private $extension;
/**
* @var \PHPUnit_Framework_MockObject_MockObject
*/
private $dataCollector;
protected function setUp()
{
$this->dataCollector = $this->getMockBuilder('Symfony\Component\Form\Extension\DataCollector\FormDataCollectorInterface')->getMock();
$this->extension = new DataCollectorExtension($this->dataCollector);
}
public function testLoadTypeExtensions()
{
$typeExtensions = $this->extension->getTypeExtensions('Symfony\Component\Form\Extension\Core\Type\FormType');
$this->assertInternalType('array', $typeExtensions);
$this->assertCount(1, $typeExtensions);
$this->assertInstanceOf('Symfony\Component\Form\Extension\DataCollector\Type\DataCollectorTypeExtension', array_shift($typeExtensions));
}
}

View File

@@ -0,0 +1,706 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\Extension\DataCollector;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Form\Extension\DataCollector\FormDataCollector;
use Symfony\Component\Form\Form;
use Symfony\Component\Form\FormBuilder;
use Symfony\Component\Form\FormView;
class FormDataCollectorTest extends TestCase
{
/**
* @var \PHPUnit_Framework_MockObject_MockObject
*/
private $dataExtractor;
/**
* @var FormDataCollector
*/
private $dataCollector;
/**
* @var \PHPUnit_Framework_MockObject_MockObject
*/
private $dispatcher;
/**
* @var \PHPUnit_Framework_MockObject_MockObject
*/
private $factory;
/**
* @var \PHPUnit_Framework_MockObject_MockObject
*/
private $dataMapper;
/**
* @var Form
*/
private $form;
/**
* @var Form
*/
private $childForm;
/**
* @var FormView
*/
private $view;
/**
* @var FormView
*/
private $childView;
protected function setUp()
{
$this->dataExtractor = $this->getMockBuilder('Symfony\Component\Form\Extension\DataCollector\FormDataExtractorInterface')->getMock();
$this->dataCollector = new FormDataCollector($this->dataExtractor);
$this->dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcherInterface')->getMock();
$this->factory = $this->getMockBuilder('Symfony\Component\Form\FormFactoryInterface')->getMock();
$this->dataMapper = $this->getMockBuilder('Symfony\Component\Form\DataMapperInterface')->getMock();
$this->form = $this->createForm('name');
$this->childForm = $this->createForm('child');
$this->view = new FormView();
$this->childView = new FormView();
}
public function testBuildPreliminaryFormTree()
{
$this->form->add($this->childForm);
$this->dataExtractor->expects($this->at(0))
->method('extractConfiguration')
->with($this->form)
->will($this->returnValue(array('config' => 'foo')));
$this->dataExtractor->expects($this->at(1))
->method('extractConfiguration')
->with($this->childForm)
->will($this->returnValue(array('config' => 'bar')));
$this->dataExtractor->expects($this->at(2))
->method('extractDefaultData')
->with($this->form)
->will($this->returnValue(array('default_data' => 'foo')));
$this->dataExtractor->expects($this->at(3))
->method('extractDefaultData')
->with($this->childForm)
->will($this->returnValue(array('default_data' => 'bar')));
$this->dataExtractor->expects($this->at(4))
->method('extractSubmittedData')
->with($this->form)
->will($this->returnValue(array('submitted_data' => 'foo')));
$this->dataExtractor->expects($this->at(5))
->method('extractSubmittedData')
->with($this->childForm)
->will($this->returnValue(array('submitted_data' => 'bar')));
$this->dataCollector->collectConfiguration($this->form);
$this->dataCollector->collectDefaultData($this->form);
$this->dataCollector->collectSubmittedData($this->form);
$this->dataCollector->buildPreliminaryFormTree($this->form);
$childFormData = array(
'config' => 'bar',
'default_data' => 'bar',
'submitted_data' => 'bar',
'children' => array(),
);
$formData = array(
'config' => 'foo',
'default_data' => 'foo',
'submitted_data' => 'foo',
'has_children_error' => false,
'children' => array(
'child' => $childFormData,
),
);
$this->assertSame(array(
'forms' => array(
'name' => $formData,
),
'forms_by_hash' => array(
spl_object_hash($this->form) => $formData,
spl_object_hash($this->childForm) => $childFormData,
),
'nb_errors' => 0,
), $this->dataCollector->getData());
}
public function testBuildMultiplePreliminaryFormTrees()
{
$form1 = $this->createForm('form1');
$form2 = $this->createForm('form2');
$this->dataExtractor->expects($this->at(0))
->method('extractConfiguration')
->with($form1)
->will($this->returnValue(array('config' => 'foo')));
$this->dataExtractor->expects($this->at(1))
->method('extractConfiguration')
->with($form2)
->will($this->returnValue(array('config' => 'bar')));
$this->dataCollector->collectConfiguration($form1);
$this->dataCollector->collectConfiguration($form2);
$this->dataCollector->buildPreliminaryFormTree($form1);
$form1Data = array(
'config' => 'foo',
'children' => array(),
);
$this->assertSame(array(
'forms' => array(
'form1' => $form1Data,
),
'forms_by_hash' => array(
spl_object_hash($form1) => $form1Data,
),
'nb_errors' => 0,
), $this->dataCollector->getData());
$this->dataCollector->buildPreliminaryFormTree($form2);
$form2Data = array(
'config' => 'bar',
'children' => array(),
);
$this->assertSame(array(
'forms' => array(
'form1' => $form1Data,
'form2' => $form2Data,
),
'forms_by_hash' => array(
spl_object_hash($form1) => $form1Data,
spl_object_hash($form2) => $form2Data,
),
'nb_errors' => 0,
), $this->dataCollector->getData());
}
public function testBuildSamePreliminaryFormTreeMultipleTimes()
{
$this->dataExtractor->expects($this->at(0))
->method('extractConfiguration')
->with($this->form)
->will($this->returnValue(array('config' => 'foo')));
$this->dataExtractor->expects($this->at(1))
->method('extractDefaultData')
->with($this->form)
->will($this->returnValue(array('default_data' => 'foo')));
$this->dataCollector->collectConfiguration($this->form);
$this->dataCollector->buildPreliminaryFormTree($this->form);
$formData = array(
'config' => 'foo',
'children' => array(),
);
$this->assertSame(array(
'forms' => array(
'name' => $formData,
),
'forms_by_hash' => array(
spl_object_hash($this->form) => $formData,
),
'nb_errors' => 0,
), $this->dataCollector->getData());
$this->dataCollector->collectDefaultData($this->form);
$this->dataCollector->buildPreliminaryFormTree($this->form);
$formData = array(
'config' => 'foo',
'default_data' => 'foo',
'children' => array(),
);
$this->assertSame(array(
'forms' => array(
'name' => $formData,
),
'forms_by_hash' => array(
spl_object_hash($this->form) => $formData,
),
'nb_errors' => 0,
), $this->dataCollector->getData());
}
public function testBuildPreliminaryFormTreeWithoutCollectingAnyData()
{
$this->dataCollector->buildPreliminaryFormTree($this->form);
$formData = array(
'children' => array(),
);
$this->assertSame(array(
'forms' => array(
'name' => $formData,
),
'forms_by_hash' => array(
spl_object_hash($this->form) => $formData,
),
'nb_errors' => 0,
), $this->dataCollector->getData());
}
public function testBuildFinalFormTree()
{
$this->form->add($this->childForm);
$this->view->children['child'] = $this->childView;
$this->dataExtractor->expects($this->at(0))
->method('extractConfiguration')
->with($this->form)
->will($this->returnValue(array('config' => 'foo')));
$this->dataExtractor->expects($this->at(1))
->method('extractConfiguration')
->with($this->childForm)
->will($this->returnValue(array('config' => 'bar')));
$this->dataExtractor->expects($this->at(2))
->method('extractDefaultData')
->with($this->form)
->will($this->returnValue(array('default_data' => 'foo')));
$this->dataExtractor->expects($this->at(3))
->method('extractDefaultData')
->with($this->childForm)
->will($this->returnValue(array('default_data' => 'bar')));
$this->dataExtractor->expects($this->at(4))
->method('extractSubmittedData')
->with($this->form)
->will($this->returnValue(array('submitted_data' => 'foo')));
$this->dataExtractor->expects($this->at(5))
->method('extractSubmittedData')
->with($this->childForm)
->will($this->returnValue(array('submitted_data' => 'bar')));
$this->dataExtractor->expects($this->at(6))
->method('extractViewVariables')
->with($this->view)
->will($this->returnValue(array('view_vars' => 'foo')));
$this->dataExtractor->expects($this->at(7))
->method('extractViewVariables')
->with($this->childView)
->will($this->returnValue(array('view_vars' => 'bar')));
$this->dataCollector->collectConfiguration($this->form);
$this->dataCollector->collectDefaultData($this->form);
$this->dataCollector->collectSubmittedData($this->form);
$this->dataCollector->collectViewVariables($this->view);
$this->dataCollector->buildFinalFormTree($this->form, $this->view);
$childFormData = array(
'view_vars' => 'bar',
'config' => 'bar',
'default_data' => 'bar',
'submitted_data' => 'bar',
'children' => array(),
);
$formData = array(
'view_vars' => 'foo',
'config' => 'foo',
'default_data' => 'foo',
'submitted_data' => 'foo',
'has_children_error' => false,
'children' => array(
'child' => $childFormData,
),
);
$this->assertSame(array(
'forms' => array(
'name' => $formData,
),
'forms_by_hash' => array(
spl_object_hash($this->form) => $formData,
spl_object_hash($this->childForm) => $childFormData,
),
'nb_errors' => 0,
), $this->dataCollector->getData());
}
public function testSerializeWithFormAddedMultipleTimes()
{
$form1 = $this->createForm('form1');
$form2 = $this->createForm('form2');
$child1 = $this->createForm('child1');
$form1View = new FormView();
$form2View = new FormView();
$child1View = new FormView();
$child1View->vars['is_selected'] = function ($choice, array $values) {
return in_array($choice, $values, true);
};
$form1->add($child1);
$form2->add($child1);
$form1View->children['child1'] = $child1View;
$form2View->children['child1'] = $child1View;
$this->dataExtractor->expects($this->at(0))
->method('extractConfiguration')
->with($form1)
->will($this->returnValue(array('config' => 'foo')));
$this->dataExtractor->expects($this->at(1))
->method('extractConfiguration')
->with($child1)
->will($this->returnValue(array('config' => 'bar')));
$this->dataExtractor->expects($this->at(2))
->method('extractDefaultData')
->with($form1)
->will($this->returnValue(array('default_data' => 'foo')));
$this->dataExtractor->expects($this->at(3))
->method('extractDefaultData')
->with($child1)
->will($this->returnValue(array('default_data' => 'bar')));
$this->dataExtractor->expects($this->at(4))
->method('extractSubmittedData')
->with($form1)
->will($this->returnValue(array('submitted_data' => 'foo')));
$this->dataExtractor->expects($this->at(5))
->method('extractSubmittedData')
->with($child1)
->will($this->returnValue(array('submitted_data' => 'bar')));
$this->dataExtractor->expects($this->at(6))
->method('extractViewVariables')
->with($form1View)
->will($this->returnValue(array('view_vars' => 'foo')));
$this->dataExtractor->expects($this->at(7))
->method('extractViewVariables')
->with($child1View)
->will($this->returnValue(array('view_vars' => $child1View->vars)));
$this->dataExtractor->expects($this->at(8))
->method('extractConfiguration')
->with($form2)
->will($this->returnValue(array('config' => 'foo')));
$this->dataExtractor->expects($this->at(9))
->method('extractConfiguration')
->with($child1)
->will($this->returnValue(array('config' => 'bar')));
$this->dataExtractor->expects($this->at(10))
->method('extractDefaultData')
->with($form2)
->will($this->returnValue(array('default_data' => 'foo')));
$this->dataExtractor->expects($this->at(11))
->method('extractDefaultData')
->with($child1)
->will($this->returnValue(array('default_data' => 'bar')));
$this->dataExtractor->expects($this->at(12))
->method('extractSubmittedData')
->with($form2)
->will($this->returnValue(array('submitted_data' => 'foo')));
$this->dataExtractor->expects($this->at(13))
->method('extractSubmittedData')
->with($child1)
->will($this->returnValue(array('submitted_data' => 'bar')));
$this->dataExtractor->expects($this->at(14))
->method('extractViewVariables')
->with($form2View)
->will($this->returnValue(array('view_vars' => 'foo')));
$this->dataExtractor->expects($this->at(15))
->method('extractViewVariables')
->with($child1View)
->will($this->returnValue(array('view_vars' => $child1View->vars)));
$this->dataCollector->collectConfiguration($form1);
$this->dataCollector->collectDefaultData($form1);
$this->dataCollector->collectSubmittedData($form1);
$this->dataCollector->collectViewVariables($form1View);
$this->dataCollector->buildFinalFormTree($form1, $form1View);
$this->dataCollector->collectConfiguration($form2);
$this->dataCollector->collectDefaultData($form2);
$this->dataCollector->collectSubmittedData($form2);
$this->dataCollector->collectViewVariables($form2View);
$this->dataCollector->buildFinalFormTree($form2, $form2View);
$this->dataCollector->serialize();
}
public function testFinalFormReliesOnFormViewStructure()
{
$this->form->add($child1 = $this->createForm('first'));
$this->form->add($child2 = $this->createForm('second'));
$this->view->children['second'] = $this->childView;
$this->dataCollector->buildPreliminaryFormTree($this->form);
$child1Data = array(
'children' => array(),
);
$child2Data = array(
'children' => array(),
);
$formData = array(
'children' => array(
'first' => $child1Data,
'second' => $child2Data,
),
);
$this->assertSame(array(
'forms' => array(
'name' => $formData,
),
'forms_by_hash' => array(
spl_object_hash($this->form) => $formData,
spl_object_hash($child1) => $child1Data,
spl_object_hash($child2) => $child2Data,
),
'nb_errors' => 0,
), $this->dataCollector->getData());
$this->dataCollector->buildFinalFormTree($this->form, $this->view);
$formData = array(
'children' => array(
// "first" not present in FormView
'second' => $child2Data,
),
);
$this->assertSame(array(
'forms' => array(
'name' => $formData,
),
'forms_by_hash' => array(
spl_object_hash($this->form) => $formData,
spl_object_hash($child1) => $child1Data,
spl_object_hash($child2) => $child2Data,
),
'nb_errors' => 0,
), $this->dataCollector->getData());
}
public function testChildViewsCanBeWithoutCorrespondingChildForms()
{
// don't add $this->childForm to $this->form!
$this->view->children['child'] = $this->childView;
$this->dataExtractor->expects($this->at(0))
->method('extractConfiguration')
->with($this->form)
->will($this->returnValue(array('config' => 'foo')));
$this->dataExtractor->expects($this->at(1))
->method('extractConfiguration')
->with($this->childForm)
->will($this->returnValue(array('config' => 'bar')));
// explicitly call collectConfiguration(), since $this->childForm is not
// contained in the form tree
$this->dataCollector->collectConfiguration($this->form);
$this->dataCollector->collectConfiguration($this->childForm);
$this->dataCollector->buildFinalFormTree($this->form, $this->view);
$childFormData = array(
// no "config" key
'children' => array(),
);
$formData = array(
'config' => 'foo',
'children' => array(
'child' => $childFormData,
),
);
$this->assertSame(array(
'forms' => array(
'name' => $formData,
),
'forms_by_hash' => array(
spl_object_hash($this->form) => $formData,
// no child entry
),
'nb_errors' => 0,
), $this->dataCollector->getData());
}
public function testChildViewsWithoutCorrespondingChildFormsMayBeExplicitlyAssociated()
{
// don't add $this->childForm to $this->form!
$this->view->children['child'] = $this->childView;
// but associate the two
$this->dataCollector->associateFormWithView($this->childForm, $this->childView);
$this->dataExtractor->expects($this->at(0))
->method('extractConfiguration')
->with($this->form)
->will($this->returnValue(array('config' => 'foo')));
$this->dataExtractor->expects($this->at(1))
->method('extractConfiguration')
->with($this->childForm)
->will($this->returnValue(array('config' => 'bar')));
// explicitly call collectConfiguration(), since $this->childForm is not
// contained in the form tree
$this->dataCollector->collectConfiguration($this->form);
$this->dataCollector->collectConfiguration($this->childForm);
$this->dataCollector->buildFinalFormTree($this->form, $this->view);
$childFormData = array(
'config' => 'bar',
'children' => array(),
);
$formData = array(
'config' => 'foo',
'children' => array(
'child' => $childFormData,
),
);
$this->assertSame(array(
'forms' => array(
'name' => $formData,
),
'forms_by_hash' => array(
spl_object_hash($this->form) => $formData,
spl_object_hash($this->childForm) => $childFormData,
),
'nb_errors' => 0,
), $this->dataCollector->getData());
}
public function testCollectSubmittedDataCountsErrors()
{
$form1 = $this->createForm('form1');
$childForm1 = $this->createForm('child1');
$form2 = $this->createForm('form2');
$form1->add($childForm1);
$this->dataExtractor
->method('extractConfiguration')
->will($this->returnValue(array()));
$this->dataExtractor
->method('extractDefaultData')
->will($this->returnValue(array()));
$this->dataExtractor->expects($this->at(4))
->method('extractSubmittedData')
->with($form1)
->will($this->returnValue(array('errors' => array('foo'))));
$this->dataExtractor->expects($this->at(5))
->method('extractSubmittedData')
->with($childForm1)
->will($this->returnValue(array('errors' => array('bar', 'bam'))));
$this->dataExtractor->expects($this->at(8))
->method('extractSubmittedData')
->with($form2)
->will($this->returnValue(array('errors' => array('baz'))));
$this->dataCollector->collectSubmittedData($form1);
$data = $this->dataCollector->getData();
$this->assertSame(3, $data['nb_errors']);
$this->dataCollector->collectSubmittedData($form2);
$data = $this->dataCollector->getData();
$this->assertSame(4, $data['nb_errors']);
}
public function testCollectSubmittedDataExpandedFormsErrors()
{
$child1Form = $this->createForm('child1');
$child11Form = $this->createForm('child11');
$child2Form = $this->createForm('child2');
$child21Form = $this->createForm('child21');
$child1Form->add($child11Form);
$child2Form->add($child21Form);
$this->form->add($child1Form);
$this->form->add($child2Form);
$this->dataExtractor
->method('extractConfiguration')
->will($this->returnValue(array()));
$this->dataExtractor
->method('extractDefaultData')
->will($this->returnValue(array()));
$this->dataExtractor->expects($this->at(10))
->method('extractSubmittedData')
->with($this->form)
->will($this->returnValue(array('errors' => array())));
$this->dataExtractor->expects($this->at(11))
->method('extractSubmittedData')
->with($child1Form)
->will($this->returnValue(array('errors' => array())));
$this->dataExtractor->expects($this->at(12))
->method('extractSubmittedData')
->with($child11Form)
->will($this->returnValue(array('errors' => array('foo'))));
$this->dataExtractor->expects($this->at(13))
->method('extractSubmittedData')
->with($child2Form)
->will($this->returnValue(array('errors' => array())));
$this->dataExtractor->expects($this->at(14))
->method('extractSubmittedData')
->with($child21Form)
->will($this->returnValue(array('errors' => array())));
$this->dataCollector->collectSubmittedData($this->form);
$this->dataCollector->buildPreliminaryFormTree($this->form);
$data = $this->dataCollector->getData();
$formData = $data['forms']['name'];
$child1Data = $formData['children']['child1'];
$child11Data = $child1Data['children']['child11'];
$child2Data = $formData['children']['child2'];
$child21Data = $child2Data['children']['child21'];
$this->assertTrue($formData['has_children_error']);
$this->assertTrue($child1Data['has_children_error']);
$this->assertFalse(isset($child11Data['has_children_error']), 'The leaf data does not contains "has_children_error" property.');
$this->assertFalse($child2Data['has_children_error']);
$this->assertFalse(isset($child21Data['has_children_error']), 'The leaf data does not contains "has_children_error" property.');
}
private function createForm($name)
{
$builder = new FormBuilder($name, null, $this->dispatcher, $this->factory);
$builder->setCompound(true);
$builder->setDataMapper($this->dataMapper);
return $builder->getForm();
}
}

View File

@@ -0,0 +1,423 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\Extension\DataCollector;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Form\CallbackTransformer;
use Symfony\Component\Form\Exception\TransformationFailedException;
use Symfony\Component\Form\Extension\DataCollector\FormDataExtractor;
use Symfony\Component\Form\FormBuilder;
use Symfony\Component\Form\FormError;
use Symfony\Component\Form\FormView;
use Symfony\Component\Form\Tests\Fixtures\FixedDataTransformer;
use Symfony\Component\Validator\ConstraintViolation;
use Symfony\Component\VarDumper\Test\VarDumperTestTrait;
/**
* @author Bernhard Schussek <bschussek@gmail.com>
*/
class FormDataExtractorTest extends TestCase
{
use VarDumperTestTrait;
/**
* @var FormDataExtractor
*/
private $dataExtractor;
/**
* @var \PHPUnit_Framework_MockObject_MockObject
*/
private $dispatcher;
/**
* @var \PHPUnit_Framework_MockObject_MockObject
*/
private $factory;
protected function setUp()
{
$this->dataExtractor = new FormDataExtractor();
$this->dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcherInterface')->getMock();
$this->factory = $this->getMockBuilder('Symfony\Component\Form\FormFactoryInterface')->getMock();
}
public function testExtractConfiguration()
{
$type = $this->getMockBuilder('Symfony\Component\Form\ResolvedFormTypeInterface')->getMock();
$type->expects($this->any())
->method('getInnerType')
->will($this->returnValue(new \stdClass()));
$form = $this->createBuilder('name')
->setType($type)
->getForm();
$this->assertSame(array(
'id' => 'name',
'name' => 'name',
'type_class' => 'stdClass',
'synchronized' => true,
'passed_options' => array(),
'resolved_options' => array(),
), $this->dataExtractor->extractConfiguration($form));
}
public function testExtractConfigurationSortsPassedOptions()
{
$type = $this->getMockBuilder('Symfony\Component\Form\ResolvedFormTypeInterface')->getMock();
$type->expects($this->any())
->method('getInnerType')
->will($this->returnValue(new \stdClass()));
$options = array(
'b' => 'foo',
'a' => 'bar',
'c' => 'baz',
);
$form = $this->createBuilder('name')
->setType($type)
// passed options are stored in an attribute by
// ResolvedTypeDataCollectorProxy
->setAttribute('data_collector/passed_options', $options)
->getForm();
$this->assertSame(array(
'id' => 'name',
'name' => 'name',
'type_class' => 'stdClass',
'synchronized' => true,
'passed_options' => array(
'a' => 'bar',
'b' => 'foo',
'c' => 'baz',
),
'resolved_options' => array(),
), $this->dataExtractor->extractConfiguration($form));
}
public function testExtractConfigurationSortsResolvedOptions()
{
$type = $this->getMockBuilder('Symfony\Component\Form\ResolvedFormTypeInterface')->getMock();
$type->expects($this->any())
->method('getInnerType')
->will($this->returnValue(new \stdClass()));
$options = array(
'b' => 'foo',
'a' => 'bar',
'c' => 'baz',
);
$form = $this->createBuilder('name', $options)
->setType($type)
->getForm();
$this->assertSame(array(
'id' => 'name',
'name' => 'name',
'type_class' => 'stdClass',
'synchronized' => true,
'passed_options' => array(),
'resolved_options' => array(
'a' => 'bar',
'b' => 'foo',
'c' => 'baz',
),
), $this->dataExtractor->extractConfiguration($form));
}
public function testExtractConfigurationBuildsIdRecursively()
{
$type = $this->getMockBuilder('Symfony\Component\Form\ResolvedFormTypeInterface')->getMock();
$type->expects($this->any())
->method('getInnerType')
->will($this->returnValue(new \stdClass()));
$grandParent = $this->createBuilder('grandParent')
->setCompound(true)
->setDataMapper($this->getMockBuilder('Symfony\Component\Form\DataMapperInterface')->getMock())
->getForm();
$parent = $this->createBuilder('parent')
->setCompound(true)
->setDataMapper($this->getMockBuilder('Symfony\Component\Form\DataMapperInterface')->getMock())
->getForm();
$form = $this->createBuilder('name')
->setType($type)
->getForm();
$grandParent->add($parent);
$parent->add($form);
$this->assertSame(array(
'id' => 'grandParent_parent_name',
'name' => 'name',
'type_class' => 'stdClass',
'synchronized' => true,
'passed_options' => array(),
'resolved_options' => array(),
), $this->dataExtractor->extractConfiguration($form));
}
public function testExtractDefaultData()
{
$form = $this->createBuilder('name')->getForm();
$form->setData('Foobar');
$this->assertSame(array(
'default_data' => array(
'norm' => 'Foobar',
),
'submitted_data' => array(),
), $this->dataExtractor->extractDefaultData($form));
}
public function testExtractDefaultDataStoresModelDataIfDifferent()
{
$form = $this->createBuilder('name')
->addModelTransformer(new FixedDataTransformer(array(
'Foo' => 'Bar',
)))
->getForm();
$form->setData('Foo');
$this->assertSame(array(
'default_data' => array(
'norm' => 'Bar',
'model' => 'Foo',
),
'submitted_data' => array(),
), $this->dataExtractor->extractDefaultData($form));
}
public function testExtractDefaultDataStoresViewDataIfDifferent()
{
$form = $this->createBuilder('name')
->addViewTransformer(new FixedDataTransformer(array(
'Foo' => 'Bar',
)))
->getForm();
$form->setData('Foo');
$this->assertSame(array(
'default_data' => array(
'norm' => 'Foo',
'view' => 'Bar',
),
'submitted_data' => array(),
), $this->dataExtractor->extractDefaultData($form));
}
public function testExtractSubmittedData()
{
$form = $this->createBuilder('name')->getForm();
$form->submit('Foobar');
$this->assertSame(array(
'submitted_data' => array(
'norm' => 'Foobar',
),
'errors' => array(),
'synchronized' => true,
), $this->dataExtractor->extractSubmittedData($form));
}
public function testExtractSubmittedDataStoresModelDataIfDifferent()
{
$form = $this->createBuilder('name')
->addModelTransformer(new FixedDataTransformer(array(
'Foo' => 'Bar',
'' => '',
)))
->getForm();
$form->submit('Bar');
$this->assertSame(array(
'submitted_data' => array(
'norm' => 'Bar',
'model' => 'Foo',
),
'errors' => array(),
'synchronized' => true,
), $this->dataExtractor->extractSubmittedData($form));
}
public function testExtractSubmittedDataStoresViewDataIfDifferent()
{
$form = $this->createBuilder('name')
->addViewTransformer(new FixedDataTransformer(array(
'Foo' => 'Bar',
'' => '',
)))
->getForm();
$form->submit('Bar');
$this->assertSame(array(
'submitted_data' => array(
'norm' => 'Foo',
'view' => 'Bar',
),
'errors' => array(),
'synchronized' => true,
), $this->dataExtractor->extractSubmittedData($form));
}
public function testExtractSubmittedDataStoresErrors()
{
$form = $this->createBuilder('name')->getForm();
$form->submit('Foobar');
$form->addError(new FormError('Invalid!'));
$this->assertSame(array(
'submitted_data' => array(
'norm' => 'Foobar',
),
'errors' => array(
array('message' => 'Invalid!', 'origin' => spl_object_hash($form), 'trace' => array()),
),
'synchronized' => true,
), $this->dataExtractor->extractSubmittedData($form));
}
public function testExtractSubmittedDataStoresErrorOrigin()
{
$form = $this->createBuilder('name')->getForm();
$error = new FormError('Invalid!');
$error->setOrigin($form);
$form->submit('Foobar');
$form->addError($error);
$this->assertSame(array(
'submitted_data' => array(
'norm' => 'Foobar',
),
'errors' => array(
array('message' => 'Invalid!', 'origin' => spl_object_hash($form), 'trace' => array()),
),
'synchronized' => true,
), $this->dataExtractor->extractSubmittedData($form));
}
public function testExtractSubmittedDataStoresErrorCause()
{
$form = $this->createBuilder('name')->getForm();
$exception = new \Exception();
$violation = new ConstraintViolation('Foo', 'Foo', array(), 'Root', 'property.path', 'Invalid!', null, null, null, $exception);
$form->submit('Foobar');
$form->addError(new FormError('Invalid!', null, array(), null, $violation));
$origin = spl_object_hash($form);
$this->assertDumpMatchesFormat(<<<EODUMP
array:3 [
"submitted_data" => array:1 [
"norm" => "Foobar"
]
"errors" => array:1 [
0 => array:3 [
"message" => "Invalid!"
"origin" => "$origin"
"trace" => array:2 [
0 => Symfony\Component\Validator\ConstraintViolation {
-message: "Foo"
-messageTemplate: "Foo"
-parameters: []
-plural: null
-root: "Root"
-propertyPath: "property.path"
-invalidValue: "Invalid!"
-constraint: null
-code: null
-cause: Exception {%A}
}
1 => Exception {#1}
]
]
]
"synchronized" => true
]
EODUMP
,
$this->dataExtractor->extractSubmittedData($form)
);
}
public function testExtractSubmittedDataRemembersIfNonSynchronized()
{
$form = $this->createBuilder('name')
->addModelTransformer(new CallbackTransformer(
function () {},
function () {
throw new TransformationFailedException('Fail!');
}
))
->getForm();
$form->submit('Foobar');
$this->assertSame(array(
'submitted_data' => array(
'norm' => 'Foobar',
'model' => null,
),
'errors' => array(),
'synchronized' => false,
), $this->dataExtractor->extractSubmittedData($form));
}
public function testExtractViewVariables()
{
$view = new FormView();
$view->vars = array(
'b' => 'foo',
'a' => 'bar',
'c' => 'baz',
'id' => 'foo_bar',
'name' => 'bar',
);
$this->assertSame(array(
'id' => 'foo_bar',
'name' => 'bar',
'view_vars' => array(
'a' => 'bar',
'b' => 'foo',
'c' => 'baz',
'id' => 'foo_bar',
'name' => 'bar',
),
), $this->dataExtractor->extractViewVariables($view));
}
/**
* @param string $name
* @param array $options
*
* @return FormBuilder
*/
private function createBuilder($name, array $options = array())
{
return new FormBuilder($name, null, $this->dispatcher, $this->factory, $options);
}
}

View File

@@ -0,0 +1,49 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\Extension\DataCollector\Type;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Form\Extension\DataCollector\Type\DataCollectorTypeExtension;
class DataCollectorTypeExtensionTest extends TestCase
{
/**
* @var DataCollectorTypeExtension
*/
private $extension;
/**
* @var \PHPUnit_Framework_MockObject_MockObject
*/
private $dataCollector;
protected function setUp()
{
$this->dataCollector = $this->getMockBuilder('Symfony\Component\Form\Extension\DataCollector\FormDataCollectorInterface')->getMock();
$this->extension = new DataCollectorTypeExtension($this->dataCollector);
}
public function testGetExtendedType()
{
$this->assertEquals('Symfony\Component\Form\Extension\Core\Type\FormType', $this->extension->getExtendedType());
}
public function testBuildForm()
{
$builder = $this->getMockBuilder('Symfony\Component\Form\Test\FormBuilderInterface')->getMock();
$builder->expects($this->atLeastOnce())
->method('addEventSubscriber')
->with($this->isInstanceOf('Symfony\Component\Form\Extension\DataCollector\EventListener\DataCollectorListener'));
$this->extension->buildForm($builder, array());
}
}

View File

@@ -0,0 +1,174 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\Extension\DependencyInjection;
use PHPUnit\Framework\TestCase;
use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
use Symfony\Component\Form\Extension\DependencyInjection\DependencyInjectionExtension;
use Symfony\Component\Form\FormTypeGuesserChain;
use Symfony\Component\Form\FormTypeGuesserInterface;
class DependencyInjectionExtensionTest extends TestCase
{
public function testGetTypeExtensions()
{
$container = $this->createContainerMock();
$container->expects($this->never())->method('get');
$typeExtension1 = $this->createFormTypeExtensionMock('test');
$typeExtension2 = $this->createFormTypeExtensionMock('test');
$typeExtension3 = $this->createFormTypeExtensionMock('other');
$extensions = array(
'test' => new \ArrayIterator(array($typeExtension1, $typeExtension2)),
'other' => new \ArrayIterator(array($typeExtension3)),
);
$extension = new DependencyInjectionExtension($container, $extensions, array());
$this->assertTrue($extension->hasTypeExtensions('test'));
$this->assertTrue($extension->hasTypeExtensions('other'));
$this->assertFalse($extension->hasTypeExtensions('unknown'));
$this->assertSame(array($typeExtension1, $typeExtension2), $extension->getTypeExtensions('test'));
$this->assertSame(array($typeExtension3), $extension->getTypeExtensions('other'));
}
/**
* @expectedException \Symfony\Component\Form\Exception\InvalidArgumentException
*/
public function testThrowExceptionForInvalidExtendedType()
{
$container = $this->getMockBuilder('Psr\Container\ContainerInterface')->getMock();
$container->expects($this->never())->method('get');
$extensions = array(
'test' => new \ArrayIterator(array($this->createFormTypeExtensionMock('unmatched'))),
);
$extension = new DependencyInjectionExtension($container, $extensions, array());
$extension->getTypeExtensions('test');
}
/**
* @group legacy
* @expectedDeprecation Passing four arguments to the Symfony\Component\Form\Extension\DependencyInjection\DependencyInjectionExtension::__construct() method is deprecated since Symfony 3.3 and will be disallowed in Symfony 4.0. The new constructor only accepts three arguments.
*/
public function testLegacyGetTypeExtensions()
{
$container = $this->createContainerMock();
$services = array(
'extension1' => $typeExtension1 = $this->createFormTypeExtensionMock('test'),
'extension2' => $typeExtension2 = $this->createFormTypeExtensionMock('test'),
'extension3' => $typeExtension3 = $this->createFormTypeExtensionMock('other'),
);
$container->expects($this->any())
->method('get')
->willReturnCallback(function ($id) use ($services) {
if (isset($services[$id])) {
return $services[$id];
}
throw new ServiceNotFoundException($id);
});
$extension = new DependencyInjectionExtension($container, array(), array('test' => array('extension1', 'extension2'), 'other' => array('extension3')), array());
$this->assertTrue($extension->hasTypeExtensions('test'));
$this->assertFalse($extension->hasTypeExtensions('unknown'));
$this->assertSame(array($typeExtension1, $typeExtension2), $extension->getTypeExtensions('test'));
}
/**
* @group legacy
* @expectedException \Symfony\Component\Form\Exception\InvalidArgumentException
* @expectedDeprecation Passing four arguments to the Symfony\Component\Form\Extension\DependencyInjection\DependencyInjectionExtension::__construct() method is deprecated since Symfony 3.3 and will be disallowed in Symfony 4.0. The new constructor only accepts three arguments.
*/
public function testLegacyThrowExceptionForInvalidExtendedType()
{
$formTypeExtension = $this->createFormTypeExtensionMock('unmatched');
$container = $this->createContainerMock();
$container->expects($this->any())
->method('get')
->with('extension')
->willReturn($formTypeExtension);
$extension = new DependencyInjectionExtension($container, array(), array('test' => array('extension')), array());
$extensions = $extension->getTypeExtensions('test');
$this->assertCount(1, $extensions);
$this->assertSame($formTypeExtension, $extensions[0]);
}
public function testGetTypeGuesser()
{
$container = $this->createContainerMock();
$extension = new DependencyInjectionExtension($container, array(), array($this->getMockBuilder(FormTypeGuesserInterface::class)->getMock()));
$this->assertInstanceOf(FormTypeGuesserChain::class, $extension->getTypeGuesser());
}
public function testGetTypeGuesserReturnsNullWhenNoTypeGuessersHaveBeenConfigured()
{
$container = $this->createContainerMock();
$extension = new DependencyInjectionExtension($container, array(), array());
$this->assertNull($extension->getTypeGuesser());
}
/**
* @group legacy
*/
public function testLegacyGetTypeGuesser()
{
$container = $this->createContainerMock();
$container
->expects($this->once())
->method('get')
->with('foo')
->willReturn($this->getMockBuilder(FormTypeGuesserInterface::class)->getMock());
$extension = new DependencyInjectionExtension($container, array(), array(), array('foo'));
$this->assertInstanceOf(FormTypeGuesserChain::class, $extension->getTypeGuesser());
}
/**
* @group legacy
*/
public function testLegacyGetTypeGuesserReturnsNullWhenNoTypeGuessersHaveBeenConfigured()
{
$container = $this->createContainerMock();
$extension = new DependencyInjectionExtension($container, array(), array(), array());
$this->assertNull($extension->getTypeGuesser());
}
private function createContainerMock()
{
return $this->getMockBuilder('Psr\Container\ContainerInterface')
->setMethods(array('get', 'has'))
->getMock();
}
private function createFormTypeExtensionMock($extendedType)
{
$extension = $this->getMockBuilder('Symfony\Component\Form\FormTypeExtensionInterface')->getMock();
$extension->expects($this->any())->method('getExtendedType')->willReturn($extendedType);
return $extension;
}
}

View File

@@ -0,0 +1,54 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\Extension\HttpFoundation;
use Symfony\Component\Form\Extension\HttpFoundation\HttpFoundationRequestHandler;
use Symfony\Component\Form\Tests\AbstractRequestHandlerTest;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\File\UploadedFile;
/**
* @author Bernhard Schussek <bschussek@gmail.com>
*/
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($this->serverParams);
}
protected function getMockFile($suffix = '')
{
return new UploadedFile(__DIR__.'/../../Fixtures/foo'.$suffix, 'foo'.$suffix);
}
}

View File

@@ -0,0 +1,54 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\Extension\Validator\Constraints;
use Symfony\Component\Form\Extension\Validator\ValidatorExtension;
use Symfony\Component\Form\Test\FormPerformanceTestCase;
use Symfony\Component\Validator\Validation;
/**
* @author Bernhard Schussek <bschussek@gmail.com>
*/
class FormValidatorPerformanceTest extends FormPerformanceTestCase
{
protected function getExtensions()
{
return array(
new ValidatorExtension(Validation::createValidator()),
);
}
/**
* findClickedButton() used to have an exponential number of calls.
*
* @group benchmark
*/
public function testValidationPerformance()
{
$this->setMaxRunningTime(1);
$builder = $this->factory->createBuilder('Symfony\Component\Form\Extension\Core\Type\FormType');
for ($i = 0; $i < 40; ++$i) {
$builder->add($i, 'Symfony\Component\Form\Extension\Core\Type\FormType');
$builder->get($i)
->add('a')
->add('b')
->add('c');
}
$form = $builder->getForm();
$form->submit(null);
}
}

View File

@@ -0,0 +1,684 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\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\Constraints\GroupSequence;
use Symfony\Component\Validator\Constraints\NotNull;
use Symfony\Component\Validator\Constraints\NotBlank;
use Symfony\Component\Validator\Constraints\Valid;
use Symfony\Component\Validator\Tests\Constraints\AbstractConstraintValidatorTest;
/**
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @todo use ConstraintValidatorTestCase when symfony/validator ~3.2 is required.
*/
class FormValidatorTest extends AbstractConstraintValidatorTest
{
/**
* @var \PHPUnit_Framework_MockObject_MockObject
*/
private $dispatcher;
/**
* @var \PHPUnit_Framework_MockObject_MockObject
*/
private $factory;
/**
* @var \PHPUnit_Framework_MockObject_MockObject
*/
protected $serverParams;
protected function setUp()
{
$this->dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcherInterface')->getMock();
$this->factory = $this->getMockBuilder('Symfony\Component\Form\FormFactoryInterface')->getMock();
$this->serverParams = $this->getMockBuilder('Symfony\Component\Form\Extension\Validator\Util\ServerParams')->setMethods(array('getNormalizedIniPostMaxSize', 'getContentLength'))->getMock();
parent::setUp();
}
protected function createValidator()
{
return new FormValidator($this->serverParams);
}
public function testValidate()
{
$object = $this->getMockBuilder('\stdClass')->getMock();
$options = array('validation_groups' => array('group1', 'group2'));
$form = $this->getBuilder('name', '\stdClass', $options)
->setData($object)
->getForm();
$this->expectValidateAt(0, 'data', $object, array('group1', 'group2'));
$this->validator->validate($form, new Form());
$this->assertNoViolation();
}
public function testValidateConstraints()
{
$object = $this->getMockBuilder('\stdClass')->getMock();
$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
$this->expectValidateAt(0, 'data', $object, array('group1', 'group2'));
// Then custom constraints
$this->expectValidateValueAt(1, 'data', $object, $constraint1, 'group1');
$this->expectValidateValueAt(2, 'data', $object, $constraint2, 'group2');
$this->validator->validate($form, new Form());
$this->assertNoViolation();
}
public function testValidateChildIfValidConstraint()
{
$object = $this->getMockBuilder('\stdClass')->getMock();
$parent = $this->getBuilder('parent')
->setCompound(true)
->setDataMapper($this->getDataMapper())
->getForm();
$options = array(
'validation_groups' => array('group1', 'group2'),
'constraints' => array(new Valid()),
);
$form = $this->getBuilder('name', '\stdClass', $options)->getForm();
$parent->add($form);
$form->setData($object);
$this->expectValidateAt(0, 'data', $object, array('group1', 'group2'));
$this->validator->validate($form, new Form());
$this->assertNoViolation();
}
public function testDontValidateIfParentWithoutValidConstraint()
{
$object = $this->getMockBuilder('\stdClass')->getMock();
$parent = $this->getBuilder('parent', null)
->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);
$this->expectNoValidate();
$this->validator->validate($form, new Form());
$this->assertNoViolation();
}
public function testMissingConstraintIndex()
{
$object = new \stdClass();
$form = new FormBuilder('name', '\stdClass', $this->dispatcher, $this->factory);
$form = $form->setData($object)->getForm();
$this->expectValidateAt(0, 'data', $object, array('Default'));
$this->validator->validate($form, new Form());
$this->assertNoViolation();
}
public function testValidateConstraintsOptionEvenIfNoValidConstraint()
{
$object = $this->getMockBuilder('\stdClass')->getMock();
$constraint1 = new NotNull(array('groups' => array('group1', 'group2')));
$constraint2 = new NotBlank(array('groups' => 'group2'));
$parent = $this->getBuilder('parent', null)
->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);
$this->expectValidateValueAt(0, 'data', $object, $constraint1, 'group1');
$this->expectValidateValueAt(1, 'data', $object, $constraint2, 'group2');
$this->validator->validate($form, new Form());
$this->assertNoViolation();
}
public function testDontValidateIfNoValidationGroups()
{
$object = $this->getMockBuilder('\stdClass')->getMock();
$form = $this->getBuilder('name', '\stdClass', array(
'validation_groups' => array(),
))
->setData($object)
->getForm();
$form->setData($object);
$this->expectNoValidate();
$this->validator->validate($form, new Form());
$this->assertNoViolation();
}
public function testDontValidateConstraintsIfNoValidationGroups()
{
$object = $this->getMockBuilder('\stdClass')->getMock();
$constraint1 = $this->getMockBuilder('Symfony\Component\Validator\Constraint')->getMock();
$constraint2 = $this->getMockBuilder('Symfony\Component\Validator\Constraint')->getMock();
$options = array(
'validation_groups' => array(),
'constraints' => array($constraint1, $constraint2),
);
$form = $this->getBuilder('name', '\stdClass', $options)
->setData($object)
->getForm();
// Launch transformer
$form->submit(array());
$this->expectNoValidate();
$this->validator->validate($form, new Form());
$this->assertNoViolation();
}
public function testDontValidateIfNotSynchronized()
{
$object = $this->getMockBuilder('\stdClass')->getMock();
$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');
$this->expectNoValidate();
$this->validator->validate($form, new Form());
$this->buildViolation('invalid_message_key')
->setParameter('{{ value }}', 'foo')
->setParameter('{{ foo }}', 'bar')
->setInvalidValue('foo')
->setCode(Form::NOT_SYNCHRONIZED_ERROR)
->setCause($form->getTransformationFailure())
->assertRaised();
}
public function testAddInvalidErrorEvenIfNoValidationGroups()
{
$object = $this->getMockBuilder('\stdClass')->getMock();
$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');
$this->expectNoValidate();
$this->validator->validate($form, new Form());
$this->buildViolation('invalid_message_key')
->setParameter('{{ value }}', 'foo')
->setParameter('{{ foo }}', 'bar')
->setInvalidValue('foo')
->setCode(Form::NOT_SYNCHRONIZED_ERROR)
->setCause($form->getTransformationFailure())
->assertRaised();
}
public function testDontValidateConstraintsIfNotSynchronized()
{
$object = $this->getMockBuilder('\stdClass')->getMock();
$constraint1 = $this->getMockBuilder('Symfony\Component\Validator\Constraint')->getMock();
$constraint2 = $this->getMockBuilder('Symfony\Component\Validator\Constraint')->getMock();
$options = array(
'invalid_message' => 'invalid_message_key',
'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('foo');
$this->expectNoValidate();
$this->validator->validate($form, new Form());
$this->buildViolation('invalid_message_key')
->setParameter('{{ value }}', 'foo')
->setInvalidValue('foo')
->setCode(Form::NOT_SYNCHRONIZED_ERROR)
->setCause($form->getTransformationFailure())
->assertRaised();
}
// https://github.com/symfony/symfony/issues/4359
public function testDontMarkInvalidIfAnyChildIsNotSynchronized()
{
$object = $this->getMockBuilder('\stdClass')->getMock();
$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'));
$this->expectNoValidate();
$this->validator->validate($form, new Form());
$this->assertNoViolation();
}
public function testHandleGroupSequenceValidationGroups()
{
$object = $this->getMockBuilder('\stdClass')->getMock();
$options = array('validation_groups' => new GroupSequence(array('group1', 'group2')));
$form = $this->getBuilder('name', '\stdClass', $options)
->setData($object)
->getForm();
$this->expectValidateAt(0, 'data', $object, new GroupSequence(array('group1', 'group2')));
$this->validator->validate($form, new Form());
$this->assertNoViolation();
}
public function testHandleCallbackValidationGroups()
{
$object = $this->getMockBuilder('\stdClass')->getMock();
$options = array('validation_groups' => array($this, 'getValidationGroups'));
$form = $this->getBuilder('name', '\stdClass', $options)
->setData($object)
->getForm();
$this->expectValidateAt(0, 'data', $object, array('group1', 'group2'));
$this->validator->validate($form, new Form());
$this->assertNoViolation();
}
public function testDontExecuteFunctionNames()
{
$object = $this->getMockBuilder('\stdClass')->getMock();
$options = array('validation_groups' => 'header');
$form = $this->getBuilder('name', '\stdClass', $options)
->setData($object)
->getForm();
$this->expectValidateAt(0, 'data', $object, array('header'));
$this->validator->validate($form, new Form());
$this->assertNoViolation();
}
public function testHandleClosureValidationGroups()
{
$object = $this->getMockBuilder('\stdClass')->getMock();
$options = array('validation_groups' => function (FormInterface $form) {
return array('group1', 'group2');
});
$form = $this->getBuilder('name', '\stdClass', $options)
->setData($object)
->getForm();
$this->expectValidateAt(0, 'data', $object, array('group1', 'group2'));
$this->validator->validate($form, new Form());
$this->assertNoViolation();
}
public function testUseValidationGroupOfClickedButton()
{
$object = $this->getMockBuilder('\stdClass')->getMock();
$parent = $this->getBuilder('parent')
->setCompound(true)
->setDataMapper($this->getDataMapper())
->getForm();
$form = $this->getForm('name', '\stdClass', array(
'validation_groups' => 'form_group',
'constraints' => array(new Valid()),
));
$parent->add($form);
$parent->add($this->getSubmitButton('submit', array(
'validation_groups' => 'button_group',
)));
$parent->submit(array('name' => $object, 'submit' => ''));
$this->expectValidateAt(0, 'data', $object, array('button_group'));
$this->validator->validate($form, new Form());
$this->assertNoViolation();
}
public function testDontUseValidationGroupOfUnclickedButton()
{
$object = $this->getMockBuilder('\stdClass')->getMock();
$parent = $this->getBuilder('parent')
->setCompound(true)
->setDataMapper($this->getDataMapper())
->getForm();
$form = $this->getForm('name', '\stdClass', array(
'validation_groups' => 'form_group',
'constraints' => array(new Valid()),
));
$parent->add($form);
$parent->add($this->getSubmitButton('submit', array(
'validation_groups' => 'button_group',
)));
$form->setData($object);
$this->expectValidateAt(0, 'data', $object, array('form_group'));
$this->validator->validate($form, new Form());
$this->assertNoViolation();
}
public function testUseInheritedValidationGroup()
{
$object = $this->getMockBuilder('\stdClass')->getMock();
$parentOptions = array('validation_groups' => 'group');
$parent = $this->getBuilder('parent', null, $parentOptions)
->setCompound(true)
->setDataMapper($this->getDataMapper())
->getForm();
$formOptions = array('constraints' => array(new Valid()));
$form = $this->getBuilder('name', '\stdClass', $formOptions)->getForm();
$parent->add($form);
$form->setData($object);
$this->expectValidateAt(0, 'data', $object, array('group'));
$this->validator->validate($form, new Form());
$this->assertNoViolation();
}
public function testUseInheritedCallbackValidationGroup()
{
$object = $this->getMockBuilder('\stdClass')->getMock();
$parentOptions = array('validation_groups' => array($this, 'getValidationGroups'));
$parent = $this->getBuilder('parent', null, $parentOptions)
->setCompound(true)
->setDataMapper($this->getDataMapper())
->getForm();
$formOptions = array('constraints' => array(new Valid()));
$form = $this->getBuilder('name', '\stdClass', $formOptions)->getForm();
$parent->add($form);
$form->setData($object);
$this->expectValidateAt(0, 'data', $object, array('group1', 'group2'));
$this->validator->validate($form, new Form());
$this->assertNoViolation();
}
public function testUseInheritedClosureValidationGroup()
{
$object = $this->getMockBuilder('\stdClass')->getMock();
$parentOptions = array(
'validation_groups' => function (FormInterface $form) {
return array('group1', 'group2');
},
);
$parent = $this->getBuilder('parent', null, $parentOptions)
->setCompound(true)
->setDataMapper($this->getDataMapper())
->getForm();
$formOptions = array('constraints' => array(new Valid()));
$form = $this->getBuilder('name', '\stdClass', $formOptions)->getForm();
$parent->add($form);
$form->setData($object);
$this->expectValidateAt(0, 'data', $object, array('group1', 'group2'));
$this->validator->validate($form, new Form());
$this->assertNoViolation();
}
public function testAppendPropertyPath()
{
$object = $this->getMockBuilder('\stdClass')->getMock();
$form = $this->getBuilder('name', '\stdClass')
->setData($object)
->getForm();
$this->expectValidateAt(0, 'data', $object, array('Default'));
$this->validator->validate($form, new Form());
$this->assertNoViolation();
}
public function testDontWalkScalars()
{
$form = $this->getBuilder()
->setData('scalar')
->getForm();
$this->expectNoValidate();
$this->validator->validate($form, new Form());
$this->assertNoViolation();
}
public function testViolationIfExtraData()
{
$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'));
$this->expectNoValidate();
$this->validator->validate($form, new Form());
$this->buildViolation('Extra!')
->setParameter('{{ extra_fields }}', 'foo')
->setInvalidValue(array('foo' => 'bar'))
->setCode(Form::NO_SUCH_FIELD_ERROR)
->assertRaised();
}
public function testNoViolationIfAllowExtraData()
{
$context = $this->getMockExecutionContext();
$form = $this
->getBuilder('parent', null, array('allow_extra_fields' => true))
->setCompound(true)
->setDataMapper($this->getDataMapper())
->add($this->getBuilder('child'))
->getForm();
$form->submit(array('foo' => 'bar'));
$context->expects($this->never())
->method('addViolation');
$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()
{
$context = $this->getMockBuilder('Symfony\Component\Validator\Context\ExecutionContextInterface')->getMock();
$validator = $this->getMockBuilder('Symfony\Component\Validator\Validator\ValidatorInterface')->getMock();
$contextualValidator = $this->getMockBuilder('Symfony\Component\Validator\Validator\ContextualValidatorInterface')->getMock();
$validator->expects($this->any())
->method('inContext')
->with($context)
->will($this->returnValue($contextualValidator));
$context->expects($this->any())
->method('getValidator')
->will($this->returnValue($validator));
return $context;
}
/**
* @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();
}
/**
* @return \PHPUnit_Framework_MockObject_MockObject
*/
private function getDataMapper()
{
return $this->getMockBuilder('Symfony\Component\Form\DataMapperInterface')->getMock();
}
}

View File

@@ -0,0 +1,170 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\Extension\Validator\EventListener;
use PHPUnit\Framework\TestCase;
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;
use Symfony\Component\Validator\ConstraintViolationList;
class ValidationListenerTest extends 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()
{
$this->dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcherInterface')->getMock();
$this->factory = $this->getMockBuilder('Symfony\Component\Form\FormFactoryInterface')->getMock();
$this->validator = $this->getMockBuilder('Symfony\Component\Validator\Validator\ValidatorInterface')->getMock();
$this->violationMapper = $this->getMockBuilder('Symfony\Component\Form\Extension\Validator\ViolationMapper\ViolationMapperInterface')->getMock();
$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, new Form());
}
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->getMockBuilder('Symfony\Component\Form\Test\FormInterface')->getMock();
}
// 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::NOT_SYNCHRONIZED_ERROR);
$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));
}
public function testValidateWithEmptyViolationList()
{
$form = $this->getMockForm();
$form->expects($this->once())
->method('isRoot')
->will($this->returnValue(true));
$this->validator
->expects($this->once())
->method('validate')
->will($this->returnValue(new ConstraintViolationList()));
$this->violationMapper
->expects($this->never())
->method('mapViolation');
$this->listener->validateForm(new FormEvent($form, null));
}
public function testValidatorInterface()
{
$validator = $this->getMockBuilder('Symfony\Component\Validator\Validator\ValidatorInterface')->getMock();
$listener = new ValidationListener($validator, $this->violationMapper);
$this->assertAttributeSame($validator, 'validator', $listener);
}
}

View File

@@ -0,0 +1,84 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\Extension\Validator\Type;
use Symfony\Component\Form\Test\FormInterface;
use Symfony\Component\Validator\Constraints\GroupSequence;
/**
* @author Bernhard Schussek <bschussek@gmail.com>
*/
abstract class BaseValidatorExtensionTest extends TypeTestCase
{
public function testValidationGroupNullByDefault()
{
$form = $this->createForm();
$this->assertNull($form->getConfig()->getOption('validation_groups'));
}
public function testValidationGroupsTransformedToArray()
{
$form = $this->createForm(array(
'validation_groups' => 'group',
));
$this->assertEquals(array('group'), $form->getConfig()->getOption('validation_groups'));
}
public function testValidationGroupsCanBeSetToArray()
{
$form = $this->createForm(array(
'validation_groups' => array('group1', 'group2'),
));
$this->assertEquals(array('group1', 'group2'), $form->getConfig()->getOption('validation_groups'));
}
public function testValidationGroupsCanBeSetToFalse()
{
$form = $this->createForm(array(
'validation_groups' => false,
));
$this->assertEquals(array(), $form->getConfig()->getOption('validation_groups'));
}
public function testValidationGroupsCanBeSetToCallback()
{
$form = $this->createForm(array(
'validation_groups' => array($this, 'testValidationGroupsCanBeSetToCallback'),
));
$this->assertInternalType('callable', $form->getConfig()->getOption('validation_groups'));
}
public function testValidationGroupsCanBeSetToClosure()
{
$form = $this->createForm(array(
'validation_groups' => function (FormInterface $form) { },
));
$this->assertInternalType('callable', $form->getConfig()->getOption('validation_groups'));
}
public function testValidationGroupsCanBeSetToGroupSequence()
{
$form = $this->createForm(array(
'validation_groups' => new GroupSequence(array('group1', 'group2')),
));
$this->assertInstanceOf('Symfony\Component\Validator\Constraints\GroupSequence', $form->getConfig()->getOption('validation_groups'));
}
abstract protected function createForm(array $options = array());
}

View File

@@ -0,0 +1,60 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\Extension\Validator\Type;
use Symfony\Component\Form\Extension\Validator\Type\FormTypeValidatorExtension;
use Symfony\Component\Validator\Constraints\Valid;
use Symfony\Component\Validator\ConstraintViolationList;
class FormTypeValidatorExtensionTest extends BaseValidatorExtensionTest
{
public function testSubmitValidatesData()
{
$builder = $this->factory->createBuilder(
'Symfony\Component\Form\Extension\Core\Type\FormType',
null,
array(
'validation_groups' => 'group',
)
);
$builder->add('firstName', 'Symfony\Component\Form\Extension\Core\Type\FormType');
$form = $builder->getForm();
$this->validator->expects($this->once())
->method('validate')
->with($this->equalTo($form))
->will($this->returnValue(new ConstraintViolationList()));
// specific data is irrelevant
$form->submit(array());
}
public function testValidConstraint()
{
$form = $this->createForm(array('constraints' => $valid = new Valid()));
$this->assertSame(array($valid), $form->getConfig()->getOption('constraints'));
}
public function testValidatorInterface()
{
$validator = $this->getMockBuilder('Symfony\Component\Validator\Validator\ValidatorInterface')->getMock();
$formTypeValidatorExtension = new FormTypeValidatorExtension($validator);
$this->assertAttributeSame($validator, 'validator', $formTypeValidatorExtension);
}
protected function createForm(array $options = array())
{
return $this->factory->create('Symfony\Component\Form\Extension\Core\Type\FormType', null, $options);
}
}

View File

@@ -0,0 +1,20 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\Extension\Validator\Type;
class SubmitTypeValidatorExtensionTest extends BaseValidatorExtensionTest
{
protected function createForm(array $options = array())
{
return $this->factory->create('Symfony\Component\Form\Extension\Core\Type\SubmitType', null, $options);
}
}

View File

@@ -0,0 +1,44 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\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()
{
$this->validator = $this->getMockBuilder('Symfony\Component\Validator\Validator\ValidatorInterface')->getMock();
$metadata = $this->getMockBuilder('Symfony\Component\Validator\Mapping\ClassMetadata')->disableOriginalConstructor()->getMock();
$this->validator->expects($this->once())->method('getMetadataFor')->will($this->returnValue($metadata));
$this->validator->expects($this->any())->method('validate')->will($this->returnValue(array()));
parent::setUp();
}
protected function tearDown()
{
$this->validator = null;
parent::tearDown();
}
protected function getExtensions()
{
return array_merge(parent::getExtensions(), array(
new ValidatorExtension($this->validator),
));
}
}

View File

@@ -0,0 +1,44 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\Extension\Validator\Type;
use Symfony\Component\Form\Extension\Validator\Type\UploadValidatorExtension;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\OptionsResolver\Options;
class UploadValidatorExtensionTest extends TypeTestCase
{
public function testPostMaxSizeTranslation()
{
$translator = $this->getMockBuilder('Symfony\Component\Translation\TranslatorInterface')->getMock();
$translator->expects($this->any())
->method('trans')
->with($this->equalTo('old max {{ max }}!'))
->willReturn('translated max {{ max }}!');
$extension = new UploadValidatorExtension($translator);
$resolver = new OptionsResolver();
$resolver->setDefault('post_max_size_message', 'old max {{ max }}!');
$resolver->setDefault('upload_max_size_message', function (Options $options, $message) {
return function () use ($options) {
return $options['post_max_size_message'];
};
});
$extension->configureOptions($resolver);
$options = $resolver->resolve();
$this->assertEquals('translated max {{ max }}!', call_user_func($options['upload_max_size_message']));
}
}

View File

@@ -0,0 +1,72 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\Extension\Validator\Util;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Form\Extension\Validator\Util\ServerParams;
use Symfony\Component\HttpFoundation\Request;
class ServerParamsTest extends TestCase
{
public function testGetContentLengthFromSuperglobals()
{
$serverParams = new ServerParams();
$this->assertNull($serverParams->getContentLength());
$_SERVER['CONTENT_LENGTH'] = 1024;
$this->assertEquals(1024, $serverParams->getContentLength());
unset($_SERVER['CONTENT_LENGTH']);
}
public function testGetContentLengthFromRequest()
{
$request = Request::create('http://foo', 'GET', array(), array(), array(), array('CONTENT_LENGTH' => 1024));
$requestStack = $this->getMockBuilder('Symfony\Component\HttpFoundation\RequestStack')->setMethods(array('getCurrentRequest'))->getMock();
$requestStack->expects($this->once())->method('getCurrentRequest')->will($this->returnValue($request));
$serverParams = new ServerParams($requestStack);
$this->assertEquals(1024, $serverParams->getContentLength());
}
/** @dataProvider getGetPostMaxSizeTestData */
public function testGetPostMaxSize($size, $bytes)
{
$serverParams = $this->getMockBuilder('Symfony\Component\Form\Extension\Validator\Util\ServerParams')->setMethods(array('getNormalizedIniPostMaxSize'))->getMock();
$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'
);
}
}

View File

@@ -0,0 +1,47 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\Extension\Validator;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Form\Extension\Validator\ValidatorExtension;
class ValidatorExtensionTest extends TestCase
{
public function test2Dot5ValidationApi()
{
$validator = $this->getMockBuilder('Symfony\Component\Validator\Validator\RecursiveValidator')
->disableOriginalConstructor()
->getMock();
$metadata = $this->getMockBuilder('Symfony\Component\Validator\Mapping\ClassMetadata')
->disableOriginalConstructor()
->getMock();
$validator->expects($this->once())
->method('getMetadataFor')
->with($this->identicalTo('Symfony\Component\Form\Form'))
->will($this->returnValue($metadata));
// Verify that the constraints are added
$metadata->expects($this->once())
->method('addConstraint')
->with($this->isInstanceOf('Symfony\Component\Form\Extension\Validator\Constraints\Form'));
$metadata->expects($this->once())
->method('addPropertyConstraint')
->with('children', $this->isInstanceOf('Symfony\Component\Validator\Constraints\Valid'));
$extension = new ValidatorExtension($validator);
$guesser = $extension->loadTypeGuesser();
$this->assertInstanceOf('Symfony\Component\Form\Extension\Validator\ValidatorTypeGuesser', $guesser);
}
}

View File

@@ -0,0 +1,138 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\Extension\Validator;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Form\Extension\Validator\ValidatorTypeGuesser;
use Symfony\Component\Form\Guess\Guess;
use Symfony\Component\Form\Guess\ValueGuess;
use Symfony\Component\Validator\Constraints\Email;
use Symfony\Component\Validator\Constraints\Length;
use Symfony\Component\Validator\Constraints\NotBlank;
use Symfony\Component\Validator\Constraints\NotNull;
use Symfony\Component\Validator\Constraints\Range;
use Symfony\Component\Validator\Constraints\IsTrue;
use Symfony\Component\Validator\Constraints\Type;
use Symfony\Component\Validator\Mapping\ClassMetadata;
/**
* @author franek <franek@chicour.net>
* @author Bernhard Schussek <bschussek@gmail.com>
*/
class ValidatorTypeGuesserTest extends TestCase
{
const TEST_CLASS = 'Symfony\Component\Form\Tests\Extension\Validator\ValidatorTypeGuesserTest_TestClass';
const TEST_PROPERTY = 'property';
/**
* @var ValidatorTypeGuesser
*/
private $guesser;
/**
* @var ClassMetadata
*/
private $metadata;
/**
* @var \PHPUnit_Framework_MockObject_MockObject
*/
private $metadataFactory;
protected function setUp()
{
$this->metadata = new ClassMetadata(self::TEST_CLASS);
$this->metadataFactory = $this->getMockBuilder('Symfony\Component\Validator\Mapping\Factory\MetadataFactoryInterface')->getMock();
$this->metadataFactory->expects($this->any())
->method('getMetadataFor')
->with(self::TEST_CLASS)
->will($this->returnValue($this->metadata));
$this->guesser = new ValidatorTypeGuesser($this->metadataFactory);
}
public function guessRequiredProvider()
{
return array(
array(new NotNull(), new ValueGuess(true, Guess::HIGH_CONFIDENCE)),
array(new NotBlank(), new ValueGuess(true, Guess::HIGH_CONFIDENCE)),
array(new IsTrue(), new ValueGuess(true, Guess::HIGH_CONFIDENCE)),
array(new Length(10), new ValueGuess(false, Guess::LOW_CONFIDENCE)),
array(new Range(array('min' => 1, 'max' => 20)), new ValueGuess(false, Guess::LOW_CONFIDENCE)),
);
}
/**
* @dataProvider guessRequiredProvider
*/
public function testGuessRequired($constraint, $guess)
{
// add distracting constraint
$this->metadata->addPropertyConstraint(self::TEST_PROPERTY, new Email());
// add constraint under test
$this->metadata->addPropertyConstraint(self::TEST_PROPERTY, $constraint);
$this->assertEquals($guess, $this->guesser->guessRequired(self::TEST_CLASS, self::TEST_PROPERTY));
}
public function testGuessRequiredReturnsFalseForUnmappedProperties()
{
$this->assertEquals(new ValueGuess(false, Guess::LOW_CONFIDENCE), $this->guesser->guessRequired(self::TEST_CLASS, self::TEST_PROPERTY));
}
public function testGuessMaxLengthForConstraintWithMaxValue()
{
$constraint = new Length(array('max' => '2'));
$result = $this->guesser->guessMaxLengthForConstraint($constraint);
$this->assertInstanceOf('Symfony\Component\Form\Guess\ValueGuess', $result);
$this->assertEquals(2, $result->getValue());
$this->assertEquals(Guess::HIGH_CONFIDENCE, $result->getConfidence());
}
public function testGuessMaxLengthForConstraintWithMinValue()
{
$constraint = new Length(array('min' => '2'));
$result = $this->guesser->guessMaxLengthForConstraint($constraint);
$this->assertNull($result);
}
public function maxLengthTypeProvider()
{
return array(
array('double'),
array('float'),
array('numeric'),
array('real'),
);
}
/**
* @dataProvider maxLengthTypeProvider
*/
public function testGuessMaxLengthForConstraintWithType($type)
{
$constraint = new Type($type);
$result = $this->guesser->guessMaxLengthForConstraint($constraint);
$this->assertInstanceOf('Symfony\Component\Form\Guess\ValueGuess', $result);
$this->assertNull($result->getValue());
$this->assertEquals(Guess::MEDIUM_CONFIDENCE, $result->getConfidence());
}
}
class ValidatorTypeGuesserTest_TestClass
{
private $property;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,247 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\Extension\Validator\ViolationMapper;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Form\Extension\Validator\ViolationMapper\ViolationPath;
/**
* @author Bernhard Schussek <bschussek@gmail.com>
*/
class ViolationPathTest extends 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),
array('street', true, true),
), 'children[address].children[street]'),
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 = null === $parentPath ? 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);
}
}

View File

@@ -0,0 +1,16 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\Fixtures;
abstract class AbstractAuthor
{
}

View File

@@ -0,0 +1,24 @@
<?php
namespace Symfony\Component\Form\Tests\Fixtures;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormBuilderInterface;
class AlternatingRowType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$formFactory = $builder->getFormFactory();
$builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) use ($formFactory) {
$form = $event->getForm();
$type = $form->getName() % 2 === 0
? 'Symfony\Component\Form\Extension\Core\Type\TextType'
: 'Symfony\Component\Form\Extension\Core\Type\TextareaType';
$form->add('title', $type);
});
}
}

Some files were not shown because too many files have changed in this diff Show More