FormTest.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417
  1. <?php
  2. namespace Symfony\Tests\Component\Form;
  3. require_once __DIR__ . '/Fixtures/Author.php';
  4. require_once __DIR__ . '/Fixtures/TestField.php';
  5. use Symfony\Component\Form\Form;
  6. use Symfony\Component\Form\Field;
  7. use Symfony\Component\Form\HiddenField;
  8. use Symfony\Component\Form\FieldGroup;
  9. use Symfony\Component\Form\HtmlGenerator;
  10. use Symfony\Component\Form\PropertyPath;
  11. use Symfony\Component\File\UploadedFile;
  12. use Symfony\Component\Validator\ConstraintViolation;
  13. use Symfony\Component\Validator\ConstraintViolationList;
  14. use Symfony\Tests\Component\Form\Fixtures\Author;
  15. use Symfony\Tests\Component\Form\Fixtures\TestField;
  16. class FormTest_PreconfiguredForm extends Form
  17. {
  18. protected function configure()
  19. {
  20. $this->add(new Field('firstName'));
  21. }
  22. }
  23. class TestSetDataBeforeConfigureForm extends Form
  24. {
  25. protected $testCase;
  26. protected $object;
  27. public function __construct($testCase, $name, $object, $validator)
  28. {
  29. $this->testCase = $testCase;
  30. $this->object = $object;
  31. parent::__construct($name, $object, $validator);
  32. }
  33. protected function configure()
  34. {
  35. $this->testCase->assertEquals($this->object, $this->getData());
  36. }
  37. }
  38. class FormTest extends \PHPUnit_Framework_TestCase
  39. {
  40. protected $validator;
  41. protected $form;
  42. protected function setUp()
  43. {
  44. Form::disableDefaultCsrfProtection();
  45. Form::setDefaultCsrfSecret(null);
  46. $this->validator = $this->createMockValidator();
  47. $this->form = new Form('author', new Author(), $this->validator);
  48. }
  49. public function testConstructInitializesObject()
  50. {
  51. $this->assertEquals(new Author(), $this->form->getData());
  52. }
  53. public function testSetDataBeforeConfigure()
  54. {
  55. new TestSetDataBeforeConfigureForm($this, 'author', new Author(), $this->validator);
  56. }
  57. public function testIsCsrfProtected()
  58. {
  59. $this->assertFalse($this->form->isCsrfProtected());
  60. $this->form->enableCsrfProtection();
  61. $this->assertTrue($this->form->isCsrfProtected());
  62. $this->form->disableCsrfProtection();
  63. $this->assertFalse($this->form->isCsrfProtected());
  64. }
  65. public function testNoCsrfProtectionByDefault()
  66. {
  67. $form = new Form('author', new Author(), $this->validator);
  68. $this->assertFalse($form->isCsrfProtected());
  69. }
  70. public function testDefaultCsrfProtectionCanBeEnabled()
  71. {
  72. Form::enableDefaultCsrfProtection();
  73. $form = new Form('author', new Author(), $this->validator);
  74. $this->assertTrue($form->isCsrfProtected());
  75. }
  76. public function testGeneratedCsrfSecretByDefault()
  77. {
  78. $form = new Form('author', new Author(), $this->validator);
  79. $this->assertTrue(strlen($form->getCsrfSecret()) >= 32);
  80. }
  81. public function testDefaultCsrfSecretCanBeSet()
  82. {
  83. Form::setDefaultCsrfSecret('foobar');
  84. $form = new Form('author', new Author(), $this->validator);
  85. $this->assertEquals('foobar', $form->getCsrfSecret());
  86. }
  87. public function testDefaultCsrfFieldNameCanBeSet()
  88. {
  89. Form::setDefaultCsrfFieldName('foobar');
  90. $form = new Form('author', new Author(), $this->validator);
  91. $this->assertEquals('foobar', $form->getCsrfFieldName());
  92. }
  93. public function testCsrfProtectedFormsHaveExtraField()
  94. {
  95. $this->form->enableCsrfProtection();
  96. $this->assertTrue($this->form->has($this->form->getCsrfFieldName()));
  97. $field = $this->form->get($this->form->getCsrfFieldName());
  98. $this->assertTrue($field instanceof HiddenField);
  99. $this->assertGreaterThanOrEqual(32, strlen($field->getDisplayedData()));
  100. }
  101. public function testIsCsrfTokenValidPassesIfCsrfProtectionIsDisabled()
  102. {
  103. $this->form->bind(array());
  104. $this->assertTrue($this->form->isCsrfTokenValid());
  105. }
  106. public function testIsCsrfTokenValidPasses()
  107. {
  108. $this->form->enableCsrfProtection();
  109. $field = $this->form->getCsrfFieldName();
  110. $token = $this->form->get($field)->getDisplayedData();
  111. $this->form->bind(array($field => $token));
  112. $this->assertTrue($this->form->isCsrfTokenValid());
  113. }
  114. public function testIsCsrfTokenValidFails()
  115. {
  116. $this->form->enableCsrfProtection();
  117. $field = $this->form->getCsrfFieldName();
  118. $this->form->bind(array($field => 'foobar'));
  119. $this->assertFalse($this->form->isCsrfTokenValid());
  120. }
  121. public function testDefaultLocaleCanBeSet()
  122. {
  123. Form::setDefaultLocale('de-DE-1996');
  124. $form = new Form('author', new Author(), $this->validator);
  125. $field = $this->getMock('Symfony\Component\Form\Field', array(), array(), '', false, false);
  126. $field->expects($this->any())
  127. ->method('getKey')
  128. ->will($this->returnValue('firstName'));
  129. $field->expects($this->once())
  130. ->method('setLocale')
  131. ->with($this->equalTo('de-DE-1996'));
  132. $form->add($field);
  133. }
  134. public function testDefaultTranslatorCanBeSet()
  135. {
  136. $translator = $this->getMock('Symfony\Component\I18N\TranslatorInterface');
  137. Form::setDefaultTranslator($translator);
  138. $form = new Form('author', new Author(), $this->validator);
  139. $field = $this->getMock('Symfony\Component\Form\Field', array(), array(), '', false, false);
  140. $field->expects($this->any())
  141. ->method('getKey')
  142. ->will($this->returnValue('firstName'));
  143. $field->expects($this->once())
  144. ->method('setTranslator')
  145. ->with($this->equalTo($translator));
  146. $form->add($field);
  147. }
  148. public function testValidationGroupsCanBeSet()
  149. {
  150. $form = new Form('author', new Author(), $this->validator);
  151. $this->assertNull($form->getValidationGroups());
  152. $form->setValidationGroups('group');
  153. $this->assertEquals(array('group'), $form->getValidationGroups());
  154. $form->setValidationGroups(array('group1', 'group2'));
  155. $this->assertEquals(array('group1', 'group2'), $form->getValidationGroups());
  156. $form->setValidationGroups(null);
  157. $this->assertNull($form->getValidationGroups());
  158. }
  159. public function testBindUsesValidationGroups()
  160. {
  161. $field = $this->createMockField('firstName');
  162. $form = new Form('author', new Author(), $this->validator);
  163. $form->add($field);
  164. $form->setValidationGroups('group');
  165. $this->validator->expects($this->once())
  166. ->method('validate')
  167. ->with($this->equalTo($form), $this->equalTo(array('group')));
  168. $form->bind(array()); // irrelevant
  169. }
  170. public function testBindConvertsUploadedFiles()
  171. {
  172. $tmpFile = $this->createTempFile();
  173. $file = new UploadedFile($tmpFile, basename($tmpFile), 'text/plain', 100, 0);
  174. $field = $this->createMockField('file');
  175. $field->expects($this->once())
  176. ->method('bind')
  177. ->with($this->equalTo($file));
  178. $form = new Form('author', new Author(), $this->validator);
  179. $form->add($field);
  180. // test
  181. $form->bind(array(), array('file' => array(
  182. 'name' => basename($tmpFile),
  183. 'type' => 'text/plain',
  184. 'tmp_name' => $tmpFile,
  185. 'error' => 0,
  186. 'size' => 100
  187. )));
  188. }
  189. public function testBindConvertsUploadedFilesWithPhpBug()
  190. {
  191. $tmpFile = $this->createTempFile();
  192. $file = new UploadedFile($tmpFile, basename($tmpFile), 'text/plain', 100, 0);
  193. $field = $this->createMockField('file');
  194. $field->expects($this->once())
  195. ->method('bind')
  196. ->with($this->equalTo($file));
  197. $form = new Form('author', new Author(), $this->validator);
  198. $form->add($field);
  199. // test
  200. $form->bind(array(), array(
  201. 'name' => array(
  202. 'file' => basename($tmpFile),
  203. ),
  204. 'type' => array(
  205. 'file' => 'text/plain',
  206. ),
  207. 'tmp_name' => array(
  208. 'file' => $tmpFile,
  209. ),
  210. 'error' => array(
  211. 'file' => 0,
  212. ),
  213. 'size' => array(
  214. 'file' => 100,
  215. ),
  216. ));
  217. }
  218. public function testBindConvertsNestedUploadedFilesWithPhpBug()
  219. {
  220. $tmpFile = $this->createTempFile();
  221. $file = new UploadedFile($tmpFile, basename($tmpFile), 'text/plain', 100, 0);
  222. $group = $this->getMock(
  223. 'Symfony\Component\Form\FieldGroup',
  224. array('bind'),
  225. array('child', array('property_path' => null))
  226. );
  227. $group->expects($this->once())
  228. ->method('bind')
  229. ->with($this->equalTo(array('file' => $file)));
  230. $form = new Form('author', new Author(), $this->validator);
  231. $form->add($group);
  232. // test
  233. $form->bind(array(), array(
  234. 'name' => array(
  235. 'child' => array('file' => basename($tmpFile)),
  236. ),
  237. 'type' => array(
  238. 'child' => array('file' => 'text/plain'),
  239. ),
  240. 'tmp_name' => array(
  241. 'child' => array('file' => $tmpFile),
  242. ),
  243. 'error' => array(
  244. 'child' => array('file' => 0),
  245. ),
  246. 'size' => array(
  247. 'child' => array('file' => 100),
  248. ),
  249. ));
  250. }
  251. public function testMultipartFormsWithoutParentsRequireFiles()
  252. {
  253. $form = new Form('author', new Author(), $this->validator);
  254. $form->add($this->createMultipartMockField('file'));
  255. $this->setExpectedException('InvalidArgumentException');
  256. // should be given in second argument
  257. $form->bind(array('file' => 'test.txt'));
  258. }
  259. public function testMultipartFormsWithParentsRequireNoFiles()
  260. {
  261. $form = new Form('author', new Author(), $this->validator);
  262. $form->add($this->createMultipartMockField('file'));
  263. $form->setParent($this->createMockField('group'));
  264. // files are expected to be converted by the parent
  265. $form->bind(array('file' => 'test.txt'));
  266. }
  267. public function testRenderFormTagProducesValidXhtml()
  268. {
  269. $form = new Form('author', new Author(), $this->validator);
  270. $this->assertEquals('<form action="url" method="post">', $form->renderFormTag('url'));
  271. }
  272. public function testSetCharsetAdjustsGenerator()
  273. {
  274. $form = $this->getMock(
  275. 'Symfony\Component\Form\Form',
  276. array('setGenerator'),
  277. array(),
  278. '',
  279. false // don't call original constructor
  280. );
  281. $form->expects($this->once())
  282. ->method('setGenerator')
  283. ->with($this->equalTo(new HtmlGenerator('iso-8859-1')));
  284. $form->setCharset('iso-8859-1');
  285. }
  286. protected function createMockField($key)
  287. {
  288. $field = $this->getMock(
  289. 'Symfony\Component\Form\FieldInterface',
  290. array(),
  291. array(),
  292. '',
  293. false, // don't use constructor
  294. false // don't call parent::__clone
  295. );
  296. $field->expects($this->any())
  297. ->method('getKey')
  298. ->will($this->returnValue($key));
  299. return $field;
  300. }
  301. protected function createMockFieldGroup($key)
  302. {
  303. $field = $this->getMock(
  304. 'Symfony\Component\Form\FieldGroup',
  305. array(),
  306. array(),
  307. '',
  308. false, // don't use constructor
  309. false // don't call parent::__clone
  310. );
  311. $field->expects($this->any())
  312. ->method('getKey')
  313. ->will($this->returnValue($key));
  314. return $field;
  315. }
  316. protected function createMultipartMockField($key)
  317. {
  318. $field = $this->createMockField($key);
  319. $field->expects($this->any())
  320. ->method('isMultipart')
  321. ->will($this->returnValue(true));
  322. return $field;
  323. }
  324. protected function createTempFile()
  325. {
  326. return tempnam(sys_get_temp_dir(), 'FormTest');
  327. }
  328. protected function createMockValidator()
  329. {
  330. return $this->getMock('Symfony\Component\Validator\ValidatorInterface');
  331. }
  332. }