FormTest.php 45 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472
  1. <?php
  2. /**
  3. * Lithium: the most rad php framework
  4. *
  5. * @copyright Copyright 2013, Union of RAD (http://union-of-rad.org)
  6. * @license http://opensource.org/licenses/bsd-license.php The BSD License
  7. */
  8. namespace lithium\tests\cases\template\helper;
  9. use Exception;
  10. use lithium\action\Request;
  11. use lithium\net\http\Router;
  12. use lithium\data\entity\Record;
  13. use lithium\data\entity\Document;
  14. use lithium\template\helper\Form;
  15. use lithium\tests\mocks\template\helper\MockFormPost;
  16. use lithium\tests\mocks\template\helper\MockFormRenderer;
  17. class FormTest extends \lithium\test\Unit {
  18. protected $_model = 'lithium\tests\mocks\template\helper\MockFormPost';
  19. protected $_model2 = 'lithium\tests\mocks\template\helper\MockFormPostInfo';
  20. /**
  21. * Test object instance.
  22. *
  23. * @var object
  24. */
  25. public $form = null;
  26. /**
  27. * The rendering context object.
  28. *
  29. * @var object
  30. */
  31. public $context = null;
  32. public $base = null;
  33. protected $_routes = array();
  34. /**
  35. * Initialize test by creating a new object instance with a default context.
  36. */
  37. public function setUp() {
  38. $this->_routes = Router::get();
  39. Router::reset();
  40. Router::connect('/{:controller}/{:action}/{:id}.{:type}', array('id' => null));
  41. Router::connect('/{:controller}/{:action}/{:args}');
  42. $request = new Request();
  43. $request->params = array('controller' => 'posts', 'action' => 'index');
  44. $request->persist = array('controller');
  45. $this->context = new MockFormRenderer(compact('request'));
  46. $this->form = new Form(array('context' => $this->context));
  47. $this->base = $this->context->request()->env('base') . '/';
  48. }
  49. public function tearDown() {
  50. Router::reset();
  51. foreach ($this->_routes as $route) {
  52. Router::connect($route);
  53. }
  54. }
  55. public function testFormCreation() {
  56. $result = $this->form->create();
  57. $this->assertTags($result, array('form' => array(
  58. 'action' => "{$this->base}posts", 'method' => 'post'
  59. )));
  60. $result = $this->form->create(null, array('method' => 'get'));
  61. $this->assertTags($result, array(
  62. 'form' => array('action' => "{$this->base}posts", 'method' => 'get')
  63. ));
  64. $result = $this->form->create(null, array('type' => 'file'));
  65. $this->assertTags($result, array('form' => array(
  66. 'action' => "{$this->base}posts",
  67. 'enctype' => 'multipart/form-data',
  68. 'method' => 'post'
  69. )));
  70. $result = $this->form->create(null, array('method' => 'get', 'type' => 'file'));
  71. $this->assertTags($result, array('form' => array(
  72. 'action' => "{$this->base}posts",
  73. 'method' => 'post',
  74. 'enctype' => 'multipart/form-data'
  75. )));
  76. $result = $this->form->create(null, array('id' => 'Registration'));
  77. $this->assertTags($result, array(
  78. 'form' => array(
  79. 'action' => "{$this->base}posts",
  80. 'method' => 'post',
  81. 'id' => 'Registration'
  82. )
  83. ));
  84. }
  85. /**
  86. * Tests creating forms with non-browser compatible HTTP methods, required for REST interfaces.
  87. */
  88. public function testRestFormCreation() {
  89. $result = $this->form->create(null, array('action' => 'delete', 'method' => 'delete'));
  90. $this->assertTags($result, array(
  91. 'form' => array(
  92. 'action' => "{$this->base}posts/delete", 'method' => 'post'
  93. ),
  94. 'input' => array('type' => "hidden", 'name' => '_method', 'value' => 'DELETE')
  95. ));
  96. $result = $this->form->create(null, array('method' => 'put', 'type' => 'file'));
  97. $this->assertTags($result, array(
  98. 'form' => array(
  99. 'action' => "{$this->base}posts",
  100. 'method' => 'post',
  101. 'enctype' => 'multipart/form-data'
  102. ),
  103. 'input' => array('type' => "hidden", 'name' => '_method', 'value' => 'PUT')
  104. ));
  105. $record = new Record(array('exists' => true, 'model' => $this->_model));
  106. $result = $this->form->create($record);
  107. $this->assertTags($result, array(
  108. 'form' => array('action' => "{$this->base}posts", 'method' => 'post'),
  109. 'input' => array('type' => "hidden", 'name' => '_method', 'value' => 'PUT')
  110. ));
  111. }
  112. public function testFormCreationWithBinding() {
  113. $record = new Record(array('model' => $this->_model, 'data' => array(
  114. 'id' => '5',
  115. 'author_id' => '2',
  116. 'title' => 'This is a saved post',
  117. 'body' => 'This is the body of the saved post'
  118. )));
  119. $this->assertTags($this->form->create($record), array(
  120. 'form' => array('action' => "{$this->base}posts", 'method' => 'post')
  121. ));
  122. }
  123. /**
  124. * Ensures that password fields aren't rendered with pre-populated values from bound record or
  125. * document objects.
  126. */
  127. public function testPasswordWithBindingValue() {
  128. $this->form->create(new Record(array(
  129. 'model' => $this->_model, 'data' => array('pass' => 'foobar')
  130. )));
  131. $result = $this->form->password('pass');
  132. $this->assertTags($result, array(
  133. 'input' => array('type' => 'password', 'name' => 'pass', 'id' => 'MockFormPostPass')
  134. ));
  135. }
  136. public function testFormDataBinding() {
  137. try {
  138. MockFormPost::config(array('meta' => array('connection' => false)));
  139. } catch (Exception $e) {
  140. MockFormPost::config(array('meta' => array('connection' => false)));
  141. }
  142. $record = new Record(array('model' => $this->_model, 'data' => array(
  143. 'id' => '5',
  144. 'author_id' => '2',
  145. 'title' => 'This is a saved post',
  146. 'body' => 'This is the body of the saved post',
  147. 'zeroInt' => 0,
  148. 'zeroString' => "0"
  149. )));
  150. $result = $this->form->create($record);
  151. $this->assertTags($result, array(
  152. 'form' => array('action' => "{$this->base}posts", 'method' => 'post')
  153. ));
  154. $result = $this->form->text('title');
  155. $this->assertTags($result, array('input' => array(
  156. 'type' => 'text', 'name' => 'title',
  157. 'value' => 'This is a saved post', 'id' => 'MockFormPostTitle'
  158. )));
  159. $result = $this->form->text('zeroInt');
  160. $this->assertTags($result, array('input' => array(
  161. 'type' => 'text', 'name' => 'zeroInt',
  162. 'value' => '0', 'id' => 'MockFormPostZeroInt'
  163. )));
  164. $result = $this->form->text('zeroString');
  165. $this->assertTags($result, array('input' => array(
  166. 'type' => 'text', 'name' => 'zeroString',
  167. 'value' => '0', 'id' => 'MockFormPostZeroString'
  168. )));
  169. $this->assertEqual('</form>', $this->form->end());
  170. $this->assertTags($this->form->text('title'), array('input' => array(
  171. 'type' => 'text', 'name' => 'title', 'id' => 'Title'
  172. )));
  173. }
  174. public function testTextBox() {
  175. $result = $this->form->text('foo');
  176. $this->assertTags($result, array('input' => array(
  177. 'type' => 'text', 'name' => 'foo', 'id' => 'Foo'
  178. )));
  179. }
  180. public function testElementsWithDefaultConfiguration() {
  181. $this->form = new Form(array(
  182. 'context' => new MockFormRenderer(), 'base' => array('class' => 'editable')
  183. ));
  184. $result = $this->form->text('foo');
  185. $this->assertTags($result, array('input' => array(
  186. 'type' => 'text', 'name' => 'foo', 'class' => 'editable', 'id' => 'Foo'
  187. )));
  188. $this->form->config(array('base' => array('maxlength' => 255)));
  189. $result = $this->form->text('foo');
  190. $this->assertTags($result, array('input' => array(
  191. 'type' => 'text', 'name' => 'foo', 'class' => 'editable',
  192. 'maxlength' => '255', 'id' => 'Foo'
  193. )));
  194. $this->form->config(array('text' => array('class' => 'locked')));
  195. $result = $this->form->text('foo');
  196. $this->assertTags($result, array('input' => array(
  197. 'type' => 'text', 'name' => 'foo', 'class' => 'locked',
  198. 'maxlength' => '255', 'id' => 'Foo'
  199. )));
  200. $result = $this->form->config();
  201. $expected = array(
  202. 'base' => array('class' => 'editable', 'maxlength' => 255),
  203. 'text' => array('class' => 'locked'),
  204. 'textarea' => array(),
  205. 'templates' => array('create' => 'form', 'end' => 'form-end'),
  206. 'attributes' => array(
  207. 'id' => $result['attributes']['id'],
  208. 'name' => $result['attributes']['name']
  209. )
  210. );
  211. $this->assertEqual($expected, $result);
  212. $this->assertTrue(is_callable($result['attributes']['id']));
  213. $this->assertTrue(is_callable($result['attributes']['name']));
  214. }
  215. public function testFormElementWithDefaultValue() {
  216. $result = $this->form->text('foo', array('default' => 'Message here'));
  217. $this->assertTags($result, array('input' => array(
  218. 'type' => 'text', 'name' => 'foo', 'value' => 'Message here', 'id' => 'Foo'
  219. )));
  220. $result = $this->form->text('foo', array(
  221. 'default' => 'Message here', 'value' => 'My Name Is Jonas', 'id' => 'Foo'
  222. ));
  223. $this->assertTags($result, array('input' => array(
  224. 'type' => 'text', 'name' => 'foo', 'value' => 'My Name Is Jonas', 'id' => 'Foo'
  225. )));
  226. $result = $this->form->text('foo', array('value' => 'My Name Is Jonas'));
  227. $this->assertTags($result, array('input' => array(
  228. 'type' => 'text', 'name' => 'foo', 'value' => 'My Name Is Jonas', 'id' => 'Foo'
  229. )));
  230. }
  231. public function testFormInputField() {
  232. $tag = array('input' => array('type' => 'file', 'name' => 'upload', 'id' => 'Upload'));
  233. $result = $this->form->file('upload');
  234. $this->assertTags($result, $tag);
  235. $value = new Document(array('model' => $this->_model));
  236. $result = $this->form->file('upload', compact('value'));
  237. $tag['input']['value'] = '';
  238. $this->assertTags($result, $tag);
  239. }
  240. public function testHiddenFieldWithId() {
  241. $result = $this->form->hidden('my_field');
  242. $this->assertTags($result, array('input' => array(
  243. 'type' => 'hidden', 'name' => 'my_field', 'id' => 'MyField'
  244. )));
  245. }
  246. public function testLabelGeneration() {
  247. $result = $this->form->label('next', 'Enter the next value >>');
  248. $this->assertTags($result, array(
  249. 'label' => array('for' => 'next'),
  250. 'Enter the next value &gt;&gt;',
  251. '/label'
  252. ));
  253. $result = $this->form->label('user_name');
  254. $this->assertTags($result, array(
  255. 'label' => array('for' => 'user_name'),
  256. 'User Name',
  257. '/label'
  258. ));
  259. $result = $this->form->label('first_name', array(
  260. 'First Name' => array('id' => 'first_name_label')
  261. ));
  262. $this->assertTags($result, array(
  263. 'label' => array('for' => 'first_name', 'id' => 'first_name_label'),
  264. 'First Name',
  265. '/label'
  266. ));
  267. $result = $this->form->label('first_name', array(
  268. null => array('id' => 'first_name_label')
  269. ));
  270. $this->assertTags($result, array(
  271. 'label' => array('for' => 'first_name', 'id' => 'first_name_label'),
  272. 'First Name',
  273. '/label'
  274. ));
  275. }
  276. public function testLabelGenerationWithNoEscape() {
  277. $result = $this->form->label('next', 'Enter the next value >>', array('escape' => false));
  278. $this->assertTags($result, array(
  279. 'label' => array('for' => 'next'),
  280. 'Enter the next value >>',
  281. '/label'
  282. ));
  283. }
  284. public function testSubmitGeneration() {
  285. $result = $this->form->submit('Continue >');
  286. $this->assertTags($result, array('input' => array(
  287. 'type' => 'submit',
  288. 'value' => 'Continue &gt;'
  289. )));
  290. $result = $this->form->submit('Continue >', array('class' => 'special'));
  291. $this->assertTags($result, array('input' => array(
  292. 'type' => 'submit',
  293. 'value' => 'Continue &gt;',
  294. 'class' => 'special'
  295. )));
  296. }
  297. public function testTextareaGeneration() {
  298. $result = $this->form->textarea('foo', array('value' => 'some content >'));
  299. $this->assertTags($result, array(
  300. 'textarea' => array('name' => 'foo', 'id' => 'Foo'),
  301. 'some content &gt;',
  302. '/textarea'
  303. ));
  304. }
  305. public function testCheckboxGeneration() {
  306. $result = $this->form->checkbox('foo');
  307. $this->assertTags($result, array(
  308. array('input' => array('type' => 'hidden', 'value' => '', 'name' => 'foo')),
  309. array('input' => array(
  310. 'type' => 'checkbox', 'value' => '1', 'name' => 'foo', 'id' => 'Foo'
  311. ))
  312. ));
  313. $result = $this->form->checkbox('foo', array('checked' => false));
  314. $this->assertTags($result, array(
  315. array('input' => array('type' => 'hidden', 'value' => '', 'name' => 'foo')),
  316. array('input' => array(
  317. 'type' => 'checkbox', 'value' => '1', 'name' => 'foo', 'id' => 'Foo'
  318. ))
  319. ));
  320. $result = $this->form->checkbox('foo', array('checked' => true));
  321. $this->assertTags($result, array(
  322. array('input' => array('type' => 'hidden', 'value' => '', 'name' => 'foo')),
  323. array('input' => array(
  324. 'type' => 'checkbox', 'value' => '1', 'name' => 'foo',
  325. 'checked' => 'checked', 'id' => 'Foo'
  326. ))
  327. ));
  328. $record = new Record(array('model' => $this->_model, 'data' => array('foo' => true)));
  329. $this->form->create($record);
  330. $result = $this->form->checkbox('foo');
  331. $this->assertTags($result, array(
  332. array('input' => array('type' => 'hidden', 'value' => '', 'name' => 'foo')),
  333. array('input' => array(
  334. 'type' => 'checkbox', 'value' => '1', 'name' => 'foo', 'id' => 'MockFormPostFoo',
  335. 'checked' => 'checked'
  336. ))
  337. ));
  338. $record = new Record(array('model' => $this->_model, 'data' => array('foo' => false)));
  339. $this->form->create($record);
  340. $result = $this->form->checkbox('foo');
  341. $this->assertTags($result, array(
  342. array('input' => array('type' => 'hidden', 'value' => '', 'name' => 'foo')),
  343. array('input' => array(
  344. 'type' => 'checkbox', 'value' => '1', 'name' => 'foo', 'id' => 'MockFormPostFoo'
  345. ))
  346. ));
  347. $document = new Document(array(
  348. 'model' => $this->_model,
  349. 'data' => array(
  350. 'subdocument' => array(
  351. 'foo' => true
  352. )
  353. )
  354. ));
  355. $this->form->create($document);
  356. $result = $this->form->checkbox('subdocument.foo');
  357. $this->assertTags($result, array(
  358. array('input' => array(
  359. 'type' => 'hidden', 'value' => '', 'name' => 'subdocument[foo]')
  360. ),
  361. array('input' => array(
  362. 'type' => 'checkbox', 'value' => '1', 'name' => 'subdocument[foo]',
  363. 'checked' => 'checked', 'id' => 'MockFormPostSubdocumentFoo'
  364. ))
  365. ));
  366. }
  367. public function testCustomCheckbox() {
  368. $result = $this->form->checkbox('foo', array('value' => '1'));
  369. $this->assertTags($result, array(
  370. array('input' => array('type' => 'hidden', 'value' => '', 'name' => 'foo')),
  371. array('input' => array(
  372. 'type' => 'checkbox', 'value' => '1', 'name' => 'foo', 'id' => 'Foo'
  373. ))
  374. ));
  375. $result = $this->form->checkbox('foo', array('checked' => true, 'value' => '1'));
  376. $this->assertTags($result, array(
  377. array('input' => array('type' => 'hidden', 'value' => '', 'name' => 'foo')),
  378. array('input' => array(
  379. 'type' => 'checkbox', 'value' => '1', 'name' => 'foo',
  380. 'checked' => 'checked', 'id' => 'Foo'
  381. ))
  382. ));
  383. $record = new Record(array('model' => $this->_model, 'data' => array('foo' => true)));
  384. $this->form->create($record);
  385. $result = $this->form->checkbox('foo', array('value' => '1'));
  386. $this->assertTags($result, array(
  387. array('input' => array('type' => 'hidden', 'value' => '', 'name' => 'foo')),
  388. array('input' => array(
  389. 'type' => 'checkbox', 'value' => '1', 'name' => 'foo',
  390. 'id' => 'MockFormPostFoo', 'checked' => 'checked'
  391. ))
  392. ));
  393. $result = $this->form->checkbox('foo', array('value' => true));
  394. $this->assertTags($result, array(
  395. array('input' => array('type' => 'hidden', 'value' => '', 'name' => 'foo')),
  396. array('input' => array(
  397. 'type' => 'checkbox', 'value' => '1', 'name' => 'foo',
  398. 'id' => 'MockFormPostFoo', 'checked' => 'checked'
  399. ))
  400. ));
  401. }
  402. public function testCustomValueCheckbox() {
  403. $result = $this->form->checkbox('foo', array('value' => 'HERO'));
  404. $this->assertTags($result, array(
  405. array('input' => array('type' => 'hidden', 'value' => '', 'name' => 'foo')),
  406. array('input' => array(
  407. 'type' => 'checkbox', 'value' => 'HERO', 'name' => 'foo', 'id' => 'Foo'
  408. ))
  409. ));
  410. $result = $this->form->checkbox('foo', array('value' => 'nose'));
  411. $this->assertTags($result, array(
  412. array('input' => array('type' => 'hidden', 'value' => '', 'name' => 'foo')),
  413. array('input' => array(
  414. 'type' => 'checkbox', 'value' => 'nose', 'name' => 'foo', 'id' => 'Foo'
  415. ))
  416. ));
  417. $record = new Record(array('model' => $this->_model, 'data' => array('foo' => 'nose')));
  418. $this->form->create($record);
  419. $result = $this->form->checkbox('foo', array('value' => 'nose'));
  420. $this->assertTags($result, array(
  421. array('input' => array('type' => 'hidden', 'value' => '', 'name' => 'foo')),
  422. array('input' => array(
  423. 'type' => 'checkbox', 'value' => 'nose', 'name' => 'foo',
  424. 'id' => 'MockFormPostFoo', 'checked' => 'checked'
  425. ))
  426. ));
  427. $record = new Record(array('model' => $this->_model, 'data' => array('foo' => 'foot')));
  428. $this->form->create($record);
  429. $result = $this->form->checkbox('foo', array('value' => 'nose'));
  430. $this->assertTags($result, array(
  431. array('input' => array('type' => 'hidden', 'value' => '', 'name' => 'foo')),
  432. array('input' => array(
  433. 'type' => 'checkbox', 'value' => 'nose', 'name' => 'foo', 'id' => 'MockFormPostFoo'
  434. ))
  435. ));
  436. $record = new Record(array('model' => $this->_model, 'data' => array('foo' => false)));
  437. $this->form->create($record);
  438. $result = $this->form->checkbox('foo', array('value' => '0'));
  439. $this->assertTags($result, array(
  440. array('input' => array('type' => 'hidden', 'value' => '', 'name' => 'foo')),
  441. array('input' => array(
  442. 'type' => 'checkbox', 'value' => '0', 'name' => 'foo', 'id' => 'MockFormPostFoo',
  443. 'checked' => 'checked'
  444. ))
  445. ));
  446. }
  447. public function testRadioGeneration() {
  448. $result = $this->form->radio('foo');
  449. $this->assertTags($result, array(array(
  450. 'input' => array('type' => 'radio', 'value' => '1', 'name' => 'foo', 'id' => 'Foo'))
  451. ));
  452. $result = $this->form->radio('foo', array('checked' => false));
  453. $this->assertTags($result, array(array(
  454. 'input' => array('type' => 'radio', 'value' => '1', 'name' => 'foo', 'id' => 'Foo'))
  455. ));
  456. $result = $this->form->radio('foo', array('checked' => true));
  457. $this->assertTags($result, array(array(
  458. 'input' => array(
  459. 'type' => 'radio',
  460. 'value' => '1',
  461. 'name' => 'foo',
  462. 'checked' => 'checked',
  463. 'id' => 'Foo')
  464. )
  465. ));
  466. $record = new Record(array('model' => $this->_model, 'data' => array('foo' => true)));
  467. $this->form->create($record);
  468. $result = $this->form->radio('foo');
  469. $this->assertTags($result, array(
  470. array('input' => array(
  471. 'type' => 'radio', 'value' => '1', 'name' => 'foo', 'id' => 'MockFormPostFoo',
  472. 'checked' => 'checked'
  473. ))
  474. ));
  475. $record = new Record(array('model' => $this->_model, 'data' => array('foo' => false)));
  476. $this->form->create($record);
  477. $result = $this->form->radio('foo');
  478. $this->assertTags($result, array(
  479. array('input' => array(
  480. 'type' => 'radio', 'value' => '1', 'name' => 'foo', 'id' => 'MockFormPostFoo'
  481. ))
  482. ));
  483. }
  484. public function testCustomRadio() {
  485. $result = $this->form->radio('foo', array('value' => '1'));
  486. $this->assertTags($result, array(
  487. array('input' => array(
  488. 'type' => 'radio', 'value' => '1', 'name' => 'foo', 'id' => 'Foo'
  489. ))
  490. ));
  491. $result = $this->form->radio('foo', array('checked' => true, 'value' => '1'));
  492. $this->assertTags($result, array(
  493. array('input' => array(
  494. 'type' => 'radio', 'value' => '1', 'name' => 'foo',
  495. 'checked' => 'checked', 'id' => 'Foo'
  496. ))
  497. ));
  498. $record = new Record(array('model' => $this->_model, 'data' => array('foo' => true)));
  499. $this->form->create($record);
  500. $result = $this->form->radio('foo', array('value' => '1'));
  501. $this->assertTags($result, array(
  502. array('input' => array(
  503. 'type' => 'radio', 'value' => '1', 'name' => 'foo',
  504. 'id' => 'MockFormPostFoo', 'checked' => 'checked'
  505. ))
  506. ));
  507. $result = $this->form->radio('foo', array('value' => true));
  508. $this->assertTags($result, array(
  509. array('input' => array(
  510. 'type' => 'radio', 'value' => '1', 'name' => 'foo',
  511. 'id' => 'MockFormPostFoo', 'checked' => 'checked'
  512. ))
  513. ));
  514. }
  515. public function testCustomValueRadio() {
  516. $result = $this->form->radio('foo', array('value' => 'HERO'));
  517. $this->assertTags($result, array(
  518. array('input' => array(
  519. 'type' => 'radio', 'value' => 'HERO', 'name' => 'foo', 'id' => 'Foo'
  520. ))
  521. ));
  522. $result = $this->form->radio('foo', array('value' => 'nose'));
  523. $this->assertTags($result, array(
  524. array('input' => array(
  525. 'type' => 'radio', 'value' => 'nose', 'name' => 'foo', 'id' => 'Foo'
  526. ))
  527. ));
  528. $record = new Record(array('model' => $this->_model, 'data' => array('foo' => 'nose')));
  529. $this->form->create($record);
  530. $result = $this->form->radio('foo', array('value' => 'nose'));
  531. $this->assertTags($result, array(
  532. array('input' => array(
  533. 'type' => 'radio', 'value' => 'nose', 'name' => 'foo',
  534. 'id' => 'MockFormPostFoo', 'checked' => 'checked'
  535. ))
  536. ));
  537. $record = new Record(array('model' => $this->_model, 'data' => array('foo' => 'foot')));
  538. $this->form->create($record);
  539. $result = $this->form->checkbox('foo', array('value' => 'nose'));
  540. $this->assertTags($result, array(
  541. array('input' => array('type' => 'hidden', 'value' => '', 'name' => 'foo')),
  542. array('input' => array(
  543. 'type' => 'checkbox', 'value' => 'nose', 'name' => 'foo', 'id' => 'MockFormPostFoo'
  544. ))
  545. ));
  546. $record = new Record(array('model' => $this->_model, 'data' => array('foo' => false)));
  547. $this->form->create($record);
  548. $result = $this->form->radio('foo', array('value' => '0'));
  549. $this->assertTags($result, array(
  550. array('input' => array(
  551. 'type' => 'radio', 'value' => '0', 'name' => 'foo',
  552. 'id' => 'MockFormPostFoo', 'checked' => 'checked'
  553. ))
  554. ));
  555. }
  556. public function testSelectGeneration() {
  557. $result = $this->form->select('foo');
  558. $this->assertTags($result, array(
  559. 'select' => array('name' => 'foo', 'id' => 'Foo'), '/select'
  560. ));
  561. $result = $this->form->select(
  562. 'colors',
  563. array('r' => 'red', 'g "' => 'green', 'b' => 'blue'),
  564. array('id' => 'Colors', 'value' => 'g "')
  565. );
  566. $this->assertTags($result, array(
  567. 'select' => array('name' => 'colors', 'id' => 'Colors'),
  568. array('option' => array('value' => 'r')),
  569. 'red',
  570. '/option',
  571. array('option' => array('value' => 'g &quot;', 'selected' => 'selected')),
  572. 'green',
  573. '/option',
  574. array('option' => array('value' => 'b')),
  575. 'blue',
  576. '/option',
  577. '/select'
  578. ));
  579. }
  580. /**
  581. * When trying to determine which option of a select box should be selected, we should be
  582. * integer/string agnostic because it all looks the same in HTML.
  583. *
  584. */
  585. public function testSelectTypeAgnosticism() {
  586. $taglist = array(
  587. 'select' => array('name' => 'numbers', 'id' => 'Numbers'),
  588. array('option' => array('value' => '0')),
  589. 'Zero',
  590. '/option',
  591. array('option' => array('value' => '1', 'selected' => 'selected')),
  592. 'One',
  593. '/option',
  594. array('option' => array('value' => '2')),
  595. 'Two',
  596. '/option',
  597. '/select'
  598. );
  599. $result = $this->form->select(
  600. 'numbers',
  601. array(0 => 'Zero', 1 => 'One', 2 => 'Two'),
  602. array('id' => 'Numbers', 'value' => '1')
  603. );
  604. $this->assertTags($result, $taglist);
  605. $result = $this->form->select(
  606. 'numbers',
  607. array('0' => 'Zero', '1' => 'One', '2' => 'Two'),
  608. array('id' => 'Numbers', 'value' => 1)
  609. );
  610. $this->assertTags($result, $taglist);
  611. }
  612. public function testSelectWithEmptyOption() {
  613. $result = $this->form->select('numbers', array('zero', 'first', 'second'), array(
  614. 'empty' => true
  615. ));
  616. $this->assertTags($result, array(
  617. 'select' => array('id' => 'Numbers', 'name' => 'numbers'),
  618. array('option' => array('value' => '', 'selected' => 'selected')),
  619. '/option',
  620. array('option' => array('value' => '0')),
  621. 'zero',
  622. '/option',
  623. array('option' => array('value' => '1')),
  624. 'first',
  625. '/option',
  626. array('option' => array('value' => '2')),
  627. 'second',
  628. '/option',
  629. '/select'
  630. ));
  631. $result = $this->form->select('numbers', array('zero', 'first', 'second'), array(
  632. 'empty' => '> Make a selection'
  633. ));
  634. $this->assertTags($result, array(
  635. 'select' => array('name' => 'numbers', 'id' => 'Numbers'),
  636. array('option' => array('value' => '', 'selected' => 'selected')),
  637. '&gt; Make a selection',
  638. '/option',
  639. array('option' => array('value' => '0')),
  640. 'zero',
  641. '/option',
  642. array('option' => array('value' => '1')),
  643. 'first',
  644. '/option',
  645. array('option' => array('value' => '2')),
  646. 'second',
  647. '/option',
  648. '/select'
  649. ));
  650. }
  651. /**
  652. * Tests that calling `select()` with nested arrays will produce lists of `<option />`s wrapped
  653. * in `<optgroup />` elements.
  654. */
  655. public function testRecursiveSelect() {
  656. $list = array(
  657. 'Linux' => array(
  658. '1' => 'Ubuntu 10.10',
  659. '2' => 'CentOS 5'
  660. ),
  661. 'Other' => array(
  662. '4' => 'Solaris',
  663. '5' => 'Windows Server 2010 R2'
  664. )
  665. );
  666. $result = $this->form->select('opsys', $list, array(
  667. 'empty' => 'Select one', 'value' => '5'
  668. ));
  669. $this->assertTags($result, array(
  670. 'select' => array('name' => 'opsys', 'id' => 'Opsys'),
  671. array('option' => array('value' => '')),
  672. 'Select one',
  673. '/option',
  674. array('optgroup' => array('label' => 'Linux')),
  675. array('option' => array('value' => '1')),
  676. 'Ubuntu 10.10',
  677. '/option',
  678. array('option' => array('value' => '2')),
  679. 'CentOS 5',
  680. '/option',
  681. '/optgroup',
  682. array('optgroup' => array('label' => 'Other')),
  683. array('option' => array('value' => '4')),
  684. 'Solaris',
  685. '/option',
  686. array('option' => array('value' => '5', 'selected' => 'selected')),
  687. 'Windows Server 2010 R2',
  688. '/option',
  689. '/optgroup',
  690. '/select'
  691. ));
  692. }
  693. public function testTemplateRemapping() {
  694. $result = $this->form->password('passwd');
  695. $this->assertTags($result, array('input' => array(
  696. 'type' => 'password', 'name' => 'passwd', 'id' => 'Passwd'
  697. )));
  698. $this->form->config(array('templates' => array('password' => 'text')));
  699. $result = $this->form->password('passwd');
  700. $this->assertTags($result, array('input' => array(
  701. 'type' => 'text', 'name' => 'passwd', 'id' => 'Passwd'
  702. )));
  703. }
  704. public function testMultiSelect() {
  705. $expected = array(
  706. 'select' => array('name' => 'numbers[]', 'id' => 'Numbers', 'multiple' => 'multiple'),
  707. array('option' => array('value' => '', 'selected' => 'selected')),
  708. '&gt; Make a selection',
  709. '/option',
  710. array('option' => array('value' => '1')),
  711. 'first',
  712. '/option',
  713. array('option' => array('value' => '2')),
  714. 'second',
  715. '/option',
  716. '/select'
  717. );
  718. $result = $this->form->select('numbers', array('1' => 'first', '2' => 'second'), array(
  719. 'empty' => '> Make a selection',
  720. 'multiple' => true
  721. ));
  722. $this->assertTags($result, $expected);
  723. $expected = array(
  724. 'select' => array(
  725. 'name' => 'numbers[]', 'multiple' => 'multiple', 'size' => 5, 'id' => 'Numbers'
  726. ),
  727. array('option' => array('value' => '1')),
  728. 'first',
  729. '/option',
  730. array('option' => array('value' => '2')),
  731. 'second',
  732. '/option',
  733. '/select'
  734. );
  735. $result = $this->form->select('numbers', array('1' => 'first', '2' => 'second'), array(
  736. 'multiple' => true,
  737. 'size' => 5
  738. ));
  739. $this->assertTags($result, $expected);
  740. }
  741. public function testMultiselected() {
  742. $expected = array(
  743. 'select' => array('name' => 'numbers[]', 'id' => 'Numbers', 'multiple' => 'multiple'),
  744. array('option' => array('value' => '1', 'selected' => 'selected')),
  745. 'first',
  746. '/option',
  747. array('option' => array('value' => '2')),
  748. 'second',
  749. '/option',
  750. array('option' => array('value' => '3', 'selected' => 'selected')),
  751. 'third',
  752. '/option',
  753. array('option' => array('value' => '4', 'selected' => 'selected')),
  754. 'fourth',
  755. '/option',
  756. '/select'
  757. );
  758. $list = array(1 => 'first', 2 => 'second', 3 => 'third', 4 => 'fourth');
  759. $options = array('value' => array(1, 3, 4), 'multiple' => true);
  760. $result = $this->form->select('numbers', $list, $options);
  761. $this->assertTags($result, $expected);
  762. }
  763. public function testFormCreateWithMoreParams() {
  764. $request = new Request();
  765. $request->params = array('controller' => 'mock', 'action' => 'test', 'args' => array('1'));
  766. $context = new MockFormRenderer(compact('request'));
  767. $form = new Form(compact('context'));
  768. $result = $form->create();
  769. $this->assertTags($result, array('form' => array(
  770. 'action' => "{$this->base}mock/test/1",
  771. 'method' => 'post'
  772. )));
  773. }
  774. public function testFormCreateWithMoreParamsButSpecifiedAction() {
  775. $request = new Request();
  776. $request->params = array('controller' => 'mock', 'action' => 'test', 'args' => array('1'));
  777. $request->persist = array('controller');
  778. $context = new MockFormRenderer(compact('request'));
  779. $form = new Form(compact('context'));
  780. $result = $form->create(null, array('action' => 'radness'));
  781. $this->assertTags($result, array('form' => array(
  782. 'action' => "{$this->base}mock/radness",
  783. 'method' => 'post'
  784. )));
  785. }
  786. public function testFormField() {
  787. $result = $this->form->field('name');
  788. $this->assertTags($result, array(
  789. 'div' => array(),
  790. 'label' => array('for' => 'Name'), 'Name', '/label',
  791. 'input' => array('type' => 'text', 'name' => 'name', 'id' => 'Name'),
  792. '/div'
  793. ));
  794. $result = $this->form->field('name', array('type' => 'radio', 'value' => 'foo'));
  795. $this->assertTags($result, array(
  796. 'div' => array(),
  797. 'input' => array('type' => 'radio', 'name' => 'name', 'value' => 'foo', 'id' => 'Name'),
  798. 'label' => array('for' => 'Name'), 'Name', '/label',
  799. '/div'
  800. ));
  801. $result = $this->form->field('name', array('type' => 'checkbox'));
  802. $expected = array(
  803. '<div>',
  804. '<input type="hidden" name="name" value="" />',
  805. '<input type="checkbox" name="name" id="Name" value="1" />',
  806. '<label for="Name">Name</label></div>'
  807. );
  808. $this->assertEqual(join('', $expected), $result);
  809. }
  810. public function testFormFieldWithCustomConfig() {
  811. $this->form->config(array('field' => array('class' => 'custom-field')));
  812. $result = $this->form->field('username');
  813. $this->assertTags($result, array(
  814. 'div' => array(),
  815. 'label' => array('for' => 'Username'),
  816. 'Username',
  817. '/label',
  818. 'input' => array(
  819. 'type' => 'text',
  820. 'name' => 'username',
  821. 'class' => 'custom-field',
  822. 'id' => 'Username'
  823. ),
  824. '/div'
  825. ));
  826. $this->assertTags($this->form->end(), array('/form'));
  827. $this->form->config(array('templates' => array('end' => "</table></form>")));
  828. $this->assertTags($this->form->end(), array('/table', '/form'));
  829. }
  830. /**
  831. * Verifies that calls to `field()` with `'type' => 'hidden'` do not produce `<label />`s.
  832. */
  833. public function testHiddenFieldWithNoLabel() {
  834. $result = $this->form->field('foo', array('type' => 'hidden'));
  835. $this->assertTags($result, array(
  836. 'div' => array(),
  837. 'input' => array('type' => 'hidden', 'name' => 'foo', 'id' => 'Foo'),
  838. '/div'
  839. ));
  840. }
  841. public function testFormFieldWithCustomTemplate() {
  842. $result = $this->form->field('name', array(
  843. 'template' => '<div{:wrap}>{:label}: {:input}{:error}</div>'
  844. ));
  845. $this->assertTags($result, array(
  846. 'div' => array(),
  847. 'label' => array('for' => 'Name'), 'Name', '/label', ':',
  848. 'input' => array('type' => 'text', 'name' => 'name', 'id' => 'Name')
  849. ));
  850. }
  851. public function testFieldWithLabelShorthand() {
  852. $result = $this->form->field(array('name' => 'Enter a name'));
  853. $this->assertTags($result, array(
  854. 'div' => array(),
  855. 'label' => array('for' => 'Name'), 'Enter a name', '/label',
  856. 'input' => array('type' => 'text', 'name' => 'name', 'id' => 'Name')
  857. ));
  858. }
  859. /**
  860. * Demonstrates that the options for a `<label />` element can be passed through the `field()`
  861. * method, using the label text as a key.
  862. */
  863. public function testFieldLabelWithOptions() {
  864. $result = $this->form->field('name', array(
  865. 'label' => array('Item Name' => array('class' => 'required'))
  866. ));
  867. $this->assertTags($result, array(
  868. 'div' => array(),
  869. 'label' => array('for' => 'Name', 'class' => 'required'), 'Item Name', '/label',
  870. 'input' => array('type' => 'text', 'name' => 'name', 'id' => 'Name')
  871. ));
  872. $result = $this->form->field('video_preview', array(
  873. 'label' => array('<a href="http://www.youtube.com/">Youtube</a>' => array(
  874. 'escape' => false
  875. ))
  876. ));
  877. $this->assertTags($result, array(
  878. 'div' => array(),
  879. 'label' => array('for' => 'VideoPreview'),
  880. 'a' => array('href' => 'http://www.youtube.com/'), 'Youtube', '/a', '/label',
  881. 'input' => array('type' => 'text', 'name' => 'video_preview', 'id' => 'VideoPreview')
  882. ));
  883. }
  884. public function testMultipleFields() {
  885. $result = $this->form->field(array(
  886. 'name' => 'Enter a name',
  887. 'phone_number',
  888. 'email' => 'Enter a valid email'
  889. ));
  890. $this->assertTags($result, array(
  891. array('div' => array()),
  892. array('label' => array('for' => 'Name')),
  893. 'Enter a name',
  894. '/label',
  895. array('input' => array('type' => 'text', 'name' => 'name', 'id' => 'Name')),
  896. '/div',
  897. array('div' => array()),
  898. array('label' => array('for' => 'PhoneNumber')),
  899. 'Phone Number',
  900. '/label',
  901. array('input' => array(
  902. 'type' => 'text', 'name' => 'phone_number', 'id' => 'PhoneNumber'
  903. )),
  904. '/div',
  905. array('div' => array()),
  906. array('label' => array('for' => 'Email')),
  907. 'Enter a valid email',
  908. '/label',
  909. array('input' => array('type' => 'text', 'name' => 'email', 'id' => 'Email')),
  910. '/div'
  911. ));
  912. }
  913. public function testCustomInputTypes() {
  914. // Creates an HTML5 'range' input slider:
  915. $range = $this->form->range('completion', array('min' => 0, 'max' => 100));
  916. $this->assertTags($range, array('input' => array(
  917. 'type' => 'range', 'name' => 'completion',
  918. 'min' => '0', 'max' => '100', 'id' => 'Completion'
  919. )));
  920. }
  921. public function testFieldWithCustomType() {
  922. $field = $this->form->field('completion', array(
  923. 'type' => 'range', 'id' => 'completion', 'min' => '0', 'max' => '100',
  924. 'label' => 'Completion %', 'wrap' => array('class' => 'input')
  925. ));
  926. $this->assertTags($field, array(
  927. 'div' => array('class' => 'input'),
  928. 'label' => array('for' => 'completion'), 'Completion %', '/label',
  929. 'input' => array(
  930. 'type' => 'range', 'name' => 'completion',
  931. 'id' => 'completion', 'min' => '0', 'max' => '100'
  932. ),
  933. '/div'
  934. ));
  935. }
  936. public function testFormFieldSelect() {
  937. $result = $this->form->field('states', array(
  938. 'type' => 'select', 'list' => array('CA', 'RI')
  939. ));
  940. $this->assertTags($result, array(
  941. 'div' => array(),
  942. 'label' => array('for' => 'States'), 'States', '/label',
  943. 'select' => array('name' => 'states', 'id' => 'States'),
  944. array('option' => array('value' => '0')),
  945. 'CA',
  946. '/option',
  947. array('option' => array('value' => '1')),
  948. 'RI',
  949. '/option',
  950. '/select'
  951. ));
  952. }
  953. public function testFormErrorWithout() {
  954. $this->form->create(null);
  955. $result = $this->form->error('name');
  956. $this->assertTrue(is_null($result));
  957. }
  958. public function testFormErrorWithRecordAndStringError() {
  959. $record = new Record(array('model' => $this->_model));
  960. $record->errors(array('name' => 'Please enter a name'));
  961. $this->form->create($record);
  962. $result = $this->form->error('name');
  963. $this->assertTags($result, array(
  964. 'div' => array('class' => 'error'), 'Please enter a name', '/div'
  965. ));
  966. }
  967. public function testFormMultipleErrors() {
  968. $record = new Record(array('model' => $this->_model));
  969. $record->errors(array('email' => array('Empty', 'Valid')));
  970. $this->form->create($record);
  971. $result = $this->form->error('email');
  972. $this->assertTags($result, array(
  973. array('div' => array('class' => 'error')), 'Empty', '/div',
  974. array('div' => array('class' => 'error')), 'Valid', '/div'
  975. ));
  976. $result = $this->form->error('email', 0);
  977. $this->assertTags($result, array('div' => array('class' => 'error'), 'Empty', '/div'));
  978. $result = $this->form->error('email', 1);
  979. $this->assertTags($result, array('div' => array('class' => 'error'), 'Valid', '/div'));
  980. $result = $this->form->error('email', true);
  981. $this->assertTags($result, array('div' => array('class' => 'error'), 'Empty', '/div'));
  982. }
  983. public function testFormErrorWithRecordAndSpecificKey() {
  984. $record = new Record(array('model' => $this->_model));
  985. $record->errors(array('name' => array('Please enter a name')));
  986. $this->form->create($record);
  987. $result = $this->form->error('name', 0);
  988. $this->assertTags($result, array(
  989. 'div' => array('class' => 'error'), 'Please enter a name', '/div'
  990. ));
  991. }
  992. public function testFormErrorWithRecordAndSpecificKeyAndValue() {
  993. $record = new Record(array('model' => $this->_model));
  994. $record->name = 'Nils';
  995. $record->errors(array('name' => array('Please enter a name')));
  996. $this->form->create($record);
  997. $result = $this->form->error('name');
  998. $this->assertTags($result, array(
  999. 'div' => array('class' => 'error'), 'Please enter a name', '/div'
  1000. ));
  1001. }
  1002. public function testFormFieldWithError() {
  1003. $record = new Record(array('model' => $this->_model));
  1004. $record->errors(array('name' => array('Please enter a name')));
  1005. $this->form->create($record);
  1006. $result = $this->form->field('name');
  1007. $this->assertTags($result, array(
  1008. '<div', 'label' => array('for' => 'MockFormPostName'), 'Name', '/label',
  1009. 'input' => array('type' => "text", 'name' => 'name', 'id' => 'MockFormPostName'),
  1010. 'div' => array('class' => "error"), 'Please enter a name', '/div', '/div'
  1011. ));
  1012. }
  1013. public function testErrorWithCustomConfiguration() {
  1014. $this->form->config(array('error' => array('class' => 'custom-error-class')));
  1015. $record = new Record(array('model' => $this->_model));
  1016. $record->errors(array('name' => array('Please enter a name')));
  1017. $this->form->create($record);
  1018. $result = $this->form->field('name');
  1019. $this->assertTags($result, array(
  1020. '<div', 'label' => array('for' => 'MockFormPostName'), 'Name', '/label',
  1021. 'input' => array('type' => "text", 'name' => 'name', 'id' => 'MockFormPostName'),
  1022. 'div' => array('class' => "custom-error-class"), 'Please enter a name', '/div', '/div'
  1023. ));
  1024. }
  1025. /**
  1026. * Tests that the string template form `Form::field()` can be overridden.
  1027. */
  1028. public function testFieldTemplateOverride() {
  1029. $this->form->config(array('templates' => array('field' => '{:label}{:input}{:error}')));
  1030. $result = $this->form->field('name', array('type' => 'text'));
  1031. $this->assertTags($result, array(
  1032. 'label' => array('for' => 'Name'), 'Name', '/label',
  1033. 'input' => array('type' => 'text', 'name' => 'name', 'id' => 'Name')
  1034. ));
  1035. }
  1036. /**
  1037. * Tests that the `field()` method properly renders a `<select />` element if the `'list'`
  1038. * option is passed.
  1039. */
  1040. public function testFieldAssumeSelectIfList() {
  1041. $result = $this->form->field('colors', array(
  1042. 'list' => array('r' => 'red', 'g' => 'green', 'b' => 'blue')
  1043. ));
  1044. $expected = array(
  1045. '<div',
  1046. array('label' => array('for' => 'Colors')),
  1047. 'Colors',
  1048. '/label',
  1049. 'select' => array('name' => 'colors', 'id' => 'Colors'),
  1050. array('option' => array('value' => 'r')),
  1051. 'red',
  1052. '/option',
  1053. array('option' => array('value' => 'g')),
  1054. 'green',
  1055. '/option',
  1056. array('option' => array('value' => 'b')),
  1057. 'blue',
  1058. '/option',
  1059. '/select',
  1060. '/div'
  1061. );
  1062. $this->assertTags($result, $expected);
  1063. }
  1064. public function testFieldInputIdWithFormId() {
  1065. $this->form->create(null, array('id' => 'registration'));
  1066. $result = $this->form->field('name');
  1067. $this->assertTags($result, array(
  1068. 'div' => array(),
  1069. 'label' => array('for' => 'Name'), 'Name', '/label',
  1070. 'input' => array('type' => 'text', 'name' => 'name', 'id' => 'Name')
  1071. ));
  1072. }
  1073. /**
  1074. * Tests that inputs for nested objects can be assigned using dot syntax.
  1075. */
  1076. public function testNestedFieldAccess() {
  1077. $doc = new Document(array('data' => array('foo' => array('bar' => 'value'))));
  1078. $this->form->create($doc);
  1079. $result = $this->form->text('foo.bar');
  1080. $this->assertTags($result, array('input' => array(
  1081. 'type' => 'text', 'name' => 'foo[bar]', 'id' => 'FooBar', 'value' => 'value'
  1082. )));
  1083. $result = $this->form->field('foo.bar');
  1084. $this->assertTags($result, array(
  1085. 'div' => array(),
  1086. 'label' => array('for' => 'FooBar'), 'Foo Bar', '/label',
  1087. 'input' => array(
  1088. 'type' => 'text', 'name' => 'foo[bar]', 'id' => 'FooBar', 'value' => 'value'
  1089. )
  1090. ));
  1091. }
  1092. /**
  1093. * Tests rendering errors for nested fields.
  1094. */
  1095. public function testNestedFieldError() {
  1096. $doc = new Document(array('data' => array('foo' => array('bar' => 'value'))));
  1097. $doc->errors(array('foo.bar' => 'Something bad happened.'));
  1098. $this->form->create($doc);
  1099. $result = $this->form->field('foo.bar');
  1100. $this->assertTags($result, array(
  1101. array('div' => array()),
  1102. 'label' => array('for' => 'FooBar'), 'Foo Bar', '/label',
  1103. 'input' => array(
  1104. 'type' => 'text', 'name' => 'foo[bar]', 'id' => 'FooBar', 'value' => 'value'
  1105. ),
  1106. 'div' => array('class' => 'error'), 'Something bad happened.', '/div',
  1107. array('/div' => array())
  1108. ));
  1109. }
  1110. public function testFormCreationWithNoContext() {
  1111. $this->form = new Form(array('context' => new MockFormRenderer(array(
  1112. 'request' => new Request(array('base' => '/bbq'))
  1113. ))));
  1114. $result = $this->form->create(null, array('url' => '/foo'));
  1115. $this->assertTags($result, array('form' => array(
  1116. 'action' => "/bbq/foo",
  1117. 'method' => "post"
  1118. )));
  1119. }
  1120. /**
  1121. * Tests that magic method support can be used to automatically generate a `<button />` tag
  1122. * based on the default string template.
  1123. */
  1124. public function testButton() {
  1125. $result = $this->form->button('Foo!', array('id' => 'bar'));
  1126. $this->assertTags($result, array('button' => array('id' => 'bar'), 'Foo!', '/button'));
  1127. $result = $this->form->button('Continue >', array('type' => 'submit'));
  1128. $this->assertTags($result, array(
  1129. 'button' => array('type' => 'submit', 'id' => 'Continue'),
  1130. 'Continue &gt;',
  1131. '/button'
  1132. ));
  1133. }
  1134. /**
  1135. * Tests that field references passed to `label()` in dot-separated format correctly translate
  1136. * to DOM ID values.
  1137. */
  1138. public function testLabelIdGeneration() {
  1139. $this->assertTags($this->form->label('user.name'), array(
  1140. 'label' => array('for' => 'UserName'), 'User Name', '/label'
  1141. ));
  1142. }
  1143. /**
  1144. * Test that field already defined template strings with special types (e.g. radio, checkbox,
  1145. * etc.) and passed customize template, and the template must apply.
  1146. */
  1147. public function testRadioTypeFieldWithCustomTemplate() {
  1148. $result = $this->form->field('name', array(
  1149. 'template' => '<span{:wrap}>{:label}: {:input}{:error}</span>',
  1150. 'type' => 'radio'
  1151. ));
  1152. $this->assertTags($result, array(
  1153. 'span' => array(),
  1154. 'label' => array('for' => 'Name'), 'Name', '/label', ':',
  1155. 'input' => array('type' => 'radio', 'name' => 'name', 'id' => 'Name', 'value' => '1')
  1156. ));
  1157. }
  1158. public function testFormCreationMultipleBindings() {
  1159. $record1 = new Record(array('model' => $this->_model, 'data' => array(
  1160. 'author_id' => '2',
  1161. 'title' => 'New post',
  1162. 'body' => 'New post body'
  1163. )));
  1164. $record2 = new Record(array('model' => $this->_model2, 'data' => array(
  1165. 'section' => 'New post section',
  1166. 'notes' => 'New post notes'
  1167. )));
  1168. $result = $this->form->create(array(
  1169. 'MockFormPost' => $record1,
  1170. 'MockFormPostInfo' => $record2
  1171. ));
  1172. $this->assertTags($result, array(
  1173. 'form' => array('action' => "{$this->base}posts", 'method' => 'post')
  1174. ));
  1175. $result = $this->form->text('title');
  1176. $this->assertTags($result, array('input' => array(
  1177. 'type' => 'text', 'name' => 'title',
  1178. 'value' => 'New post', 'id' => 'MockFormPostTitle'
  1179. )));
  1180. $result = $this->form->text('MockFormPost.title');
  1181. $this->assertTags($result, array('input' => array(
  1182. 'type' => 'text', 'name' => 'MockFormPost[title]',
  1183. 'value' => 'New post', 'id' => 'MockFormPostTitle'
  1184. )));
  1185. $result = $this->form->text('body');
  1186. $this->assertTags($result, array('input' => array(
  1187. 'type' => 'text', 'name' => 'body',
  1188. 'value' => 'New post body', 'id' => 'MockFormPostBody'
  1189. )));
  1190. $result = $this->form->text('MockFormPostInfo.section');
  1191. $this->assertTags($result, array('input' => array(
  1192. 'type' => 'text', 'name' => 'MockFormPostInfo[section]',
  1193. 'value' => 'New post section', 'id' => 'MockFormPostInfoSection'
  1194. )));
  1195. $result = $this->form->end();
  1196. $this->assertTags($result, array('/form'));
  1197. $result = $this->form->create(array('a' => $record1, 'b' => $record2));
  1198. $this->assertTags($result, array(
  1199. 'form' => array('action' => "{$this->base}posts", 'method' => 'post')
  1200. ));
  1201. $result = $this->form->text('title');
  1202. $this->assertTags($result, array('input' => array(
  1203. 'type' => 'text', 'name' => 'title',
  1204. 'value' => 'New post', 'id' => 'MockFormPostTitle'
  1205. )));
  1206. $result = $this->form->text('a.title');
  1207. $this->assertTags($result, array('input' => array(
  1208. 'type' => 'text', 'name' => 'a[title]',
  1209. 'value' => 'New post', 'id' => 'MockFormPostTitle'
  1210. )));
  1211. $result = $this->form->text('body');
  1212. $this->assertTags($result, array('input' => array(
  1213. 'type' => 'text', 'name' => 'body',
  1214. 'value' => 'New post body', 'id' => 'MockFormPostBody'
  1215. )));
  1216. $result = $this->form->text('b.section');
  1217. $this->assertTags($result, array('input' => array(
  1218. 'type' => 'text', 'name' => 'b[section]',
  1219. 'value' => 'New post section', 'id' => 'MockFormPostInfoSection'
  1220. )));
  1221. $result = $this->form->end();
  1222. $this->assertTags($result, array('/form'));
  1223. }
  1224. public function testFormErrorMultipleBindings() {
  1225. $record1 = new Record(array('model' => $this->_model, 'data' => array(
  1226. 'author_id' => '2',
  1227. 'title' => 'New post',
  1228. 'body' => 'New post body'
  1229. )));
  1230. $record2 = new Record(array('model' => $this->_model2, 'data' => array(
  1231. 'section' => 'New post section',
  1232. 'notes' => 'New post notes'
  1233. )));
  1234. $record1->errors(array('title' => 'Not a cool title'));
  1235. $record2->errors(array('section' => 'Not a cool section'));
  1236. $this->form->create(compact('record1', 'record2'));
  1237. $result = $this->form->error('title');
  1238. $this->assertTags($result, array(
  1239. 'div' => array('class' => 'error'), 'Not a cool title', '/div'
  1240. ));
  1241. $result = $this->form->error('body');
  1242. $this->assertTrue(empty($result));
  1243. $result = $this->form->error('record1.title');
  1244. $this->assertTags($result, array(
  1245. 'div' => array('class' => 'error'), 'Not a cool title', '/div'
  1246. ));
  1247. $result = $this->form->error('record2.section');
  1248. $this->assertTags($result, array(
  1249. 'div' => array('class' => 'error'), 'Not a cool section', '/div'
  1250. ));
  1251. }
  1252. public function testBindingByName() {
  1253. $post = new Record(array('model' => $this->_model, 'data' => array(
  1254. 'author_id' => '2',
  1255. 'title' => 'New post',
  1256. 'body' => 'New post body'
  1257. )));
  1258. $info = new Record(array('model' => $this->_model2, 'data' => array(
  1259. 'section' => 'New post section',
  1260. 'notes' => 'New post notes'
  1261. )));
  1262. $this->form->create(compact('post', 'info'));
  1263. $this->assertEqual($post, $this->form->binding('post'));
  1264. $this->assertEqual($info, $this->form->binding('info'));
  1265. }
  1266. public function testRespondsTo() {
  1267. $this->assertTrue($this->form->respondsTo('foobarbaz'));
  1268. $this->assertFalse($this->form->respondsTo(0));
  1269. }
  1270. }
  1271. ?>