FormTest.php 12 KB

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