DateTimeWidgetTest.php 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203
  1. <?php
  2. /**
  3. * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  4. * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  5. *
  6. * Licensed under The MIT License
  7. * For full copyright and license information, please see the LICENSE.txt
  8. * Redistributions of files must retain the above copyright notice.
  9. *
  10. * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  11. * @link http://cakephp.org CakePHP(tm) Project
  12. * @since 3.0.0
  13. * @license http://www.opensource.org/licenses/mit-license.php MIT License
  14. */
  15. namespace Cake\Test\TestCase\View\Widget;
  16. use Cake\TestSuite\TestCase;
  17. use Cake\View\StringTemplate;
  18. use Cake\View\Widget\DateTimeWidget;
  19. use Cake\View\Widget\SelectBoxWidget;
  20. /**
  21. * DateTime input test case
  22. */
  23. class DateTimeWidgetTest extends TestCase
  24. {
  25. /**
  26. * @setUp
  27. *
  28. * @return void
  29. */
  30. public function setUp()
  31. {
  32. parent::setUp();
  33. $templates = [
  34. 'select' => '<select name="{{name}}"{{attrs}}>{{content}}</select>',
  35. 'option' => '<option value="{{value}}"{{attrs}}>{{text}}</option>',
  36. 'optgroup' => '<optgroup label="{{label}}"{{attrs}}>{{content}}</optgroup>',
  37. 'dateWidget' => '{{year}}{{month}}{{day}}{{hour}}{{minute}}{{second}}{{meridian}}'
  38. ];
  39. $this->templates = new StringTemplate($templates);
  40. $this->context = $this->getMock('Cake\View\Form\ContextInterface');
  41. $this->selectBox = new SelectBoxWidget($this->templates);
  42. $this->DateTime = new DateTimeWidget($this->templates, $this->selectBox);
  43. }
  44. /**
  45. * Data provider for testing various types of invalid selected values.
  46. *
  47. * @return array
  48. */
  49. public static function invalidSelectedValuesProvider()
  50. {
  51. return [
  52. 'false' => [false],
  53. 'true' => [true],
  54. 'string' => ['Bag of poop'],
  55. 'array' => [[
  56. 'derp' => 'hurt'
  57. ]]
  58. ];
  59. }
  60. /**
  61. * test rendering selected values.
  62. *
  63. * @dataProvider invalidSelectedValuesProvider
  64. * @return void
  65. */
  66. public function testRenderSelectedInvalid($selected)
  67. {
  68. $result = $this->DateTime->render(['val' => $selected], $this->context);
  69. $now = new \DateTime();
  70. $format = '<option value="%s" selected="selected">%s</option>';
  71. $this->assertContains(
  72. sprintf($format, $now->format('Y'), $now->format('Y')),
  73. $result
  74. );
  75. }
  76. /**
  77. * test rendering empty selected.
  78. *
  79. * @return void
  80. */
  81. public function testRenderSelectedEmpty()
  82. {
  83. $result = $this->DateTime->render([
  84. 'val' => '',
  85. 'year' => ['empty' => true],
  86. 'month' => ['empty' => true],
  87. 'day' => ['empty' => true],
  88. 'hour' => ['empty' => true],
  89. 'minute' => ['empty' => true],
  90. ], $this->context);
  91. $this->assertContains('<option value="" selected="selected"></option>', $result);
  92. $this->assertNotRegExp('/value="\d+" selected="selected"/', $result);
  93. $result = $this->DateTime->render([
  94. 'val' => ['year' => '', 'month' => '', 'day' => '', 'hour' => '', 'minute' => ''],
  95. 'year' => ['empty' => true],
  96. 'month' => ['empty' => true],
  97. 'day' => ['empty' => true],
  98. 'hour' => ['empty' => true],
  99. 'minute' => ['empty' => true],
  100. ], $this->context);
  101. $this->assertContains('<option value="" selected="selected"></option>', $result);
  102. $this->assertNotRegExp('/value="\d+" selected="selected"/', $result);
  103. }
  104. /**
  105. * Data provider for testing various acceptable selected values.
  106. *
  107. * @return array
  108. */
  109. public static function selectedValuesProvider()
  110. {
  111. $date = new \DateTime('2014-01-20 12:30:45');
  112. return [
  113. 'DateTime' => [$date],
  114. 'string' => [$date->format('Y-m-d H:i:s')],
  115. 'int' => [$date->getTimestamp()],
  116. 'array' => [[
  117. 'year' => '2014', 'month' => '01', 'day' => '20',
  118. 'hour' => '12', 'minute' => '30', 'second' => '45',
  119. ]]
  120. ];
  121. }
  122. /**
  123. * test rendering selected values.
  124. *
  125. * @dataProvider selectedValuesProvider
  126. * @return void
  127. */
  128. public function testRenderSelected($selected)
  129. {
  130. $result = $this->DateTime->render(['val' => $selected], $this->context);
  131. $this->assertContains('<option value="2014" selected="selected">2014</option>', $result);
  132. $this->assertContains('<option value="01" selected="selected">1</option>', $result);
  133. $this->assertContains('<option value="20" selected="selected">20</option>', $result);
  134. $this->assertContains('<option value="12" selected="selected">12</option>', $result);
  135. $this->assertContains('<option value="30" selected="selected">30</option>', $result);
  136. $this->assertContains('<option value="45" selected="selected">45</option>', $result);
  137. }
  138. public function testRenderInvalidDate()
  139. {
  140. $selected = [
  141. 'year' => '2014', 'month' => '02', 'day' => '31',
  142. 'hour' => '12', 'minute' => '30', 'second' => '45',
  143. ];
  144. $result = $this->DateTime->render(['val' => $selected], $this->context);
  145. $this->assertContains('<option value="2014" selected="selected">2014</option>', $result);
  146. $this->assertContains('<option value="02" selected="selected">2</option>', $result);
  147. $this->assertContains('<option value="31" selected="selected">31</option>', $result);
  148. $this->assertContains('<option value="12" selected="selected">12</option>', $result);
  149. $this->assertContains('<option value="30" selected="selected">30</option>', $result);
  150. $this->assertContains('<option value="45" selected="selected">45</option>', $result);
  151. }
  152. /**
  153. * Test that render() works with an array for val that is missing seconds.
  154. *
  155. * @return void
  156. */
  157. public function testRenderSelectedNoSeconds()
  158. {
  159. $selected = [
  160. 'year' => '2014', 'month' => '01', 'day' => '20',
  161. 'hour' => '12', 'minute' => '30'
  162. ];
  163. $result = $this->DateTime->render(['name' => 'created', 'val' => $selected], $this->context);
  164. $this->assertContains('name="created[year]"', $result);
  165. $this->assertContains('<option value="2014" selected="selected">2014</option>', $result);
  166. $this->assertContains('name="created[month]"', $result);
  167. $this->assertContains('<option value="01" selected="selected">1</option>', $result);
  168. $this->assertContains('name="created[day]"', $result);
  169. $this->assertContains('<option value="20" selected="selected">20</option>', $result);
  170. $this->assertContains('name="created[hour]"', $result);
  171. $this->assertContains('<option value="12" selected="selected">12</option>', $result);
  172. $this->assertContains('name="created[minute]"', $result);
  173. $this->assertContains('<option value="30" selected="selected">30</option>', $result);
  174. $this->assertContains('name="created[second]"', $result);
  175. $this->assertContains('<option value="30" selected="selected">30</option>', $result);
  176. }
  177. /**
  178. * Test that render() adjusts hours based on meridian
  179. *
  180. * @return void
  181. */
  182. public function testRenderSelectedMeridian()
  183. {
  184. $selected = [
  185. 'year' => '2014', 'month' => '01', 'day' => '20',
  186. 'hour' => '7', 'minute' => '30', 'meridian' => 'pm'
  187. ];
  188. $result = $this->DateTime->render(['val' => $selected], $this->context);
  189. $this->assertContains('<option value="2014" selected="selected">2014</option>', $result);
  190. $this->assertContains('<option value="01" selected="selected">1</option>', $result);
  191. $this->assertContains('<option value="20" selected="selected">20</option>', $result);
  192. $this->assertContains('<option value="19" selected="selected">19</option>', $result);
  193. }
  194. /**
  195. * Test rendering widgets with empty values.
  196. *
  197. * @retun void
  198. */
  199. public function testRenderEmptyValues()
  200. {
  201. $result = $this->DateTime->render([
  202. 'year' => ['empty' => 'YEAR'],
  203. 'month' => ['empty' => 'MONTH'],
  204. 'day' => ['empty' => 'DAY'],
  205. 'hour' => ['empty' => 'HOUR'],
  206. 'minute' => ['empty' => 'MINUTE'],
  207. 'second' => ['empty' => 'SECOND'],
  208. 'meridian' => ['empty' => 'MERIDIAN'],
  209. ], $this->context);
  210. $this->assertContains('<option value="" selected="selected">YEAR</option>', $result);
  211. $this->assertContains('<option value="" selected="selected">MONTH</option>', $result);
  212. $this->assertContains('<option value="" selected="selected">DAY</option>', $result);
  213. $this->assertContains('<option value="" selected="selected">HOUR</option>', $result);
  214. $this->assertContains('<option value="" selected="selected">MINUTE</option>', $result);
  215. $this->assertContains('<option value="" selected="selected">SECOND</option>', $result);
  216. $this->assertContains('<option value="" selected="selected">MERIDIAN</option>', $result);
  217. }
  218. /**
  219. * Test rendering the default year widget.
  220. *
  221. * @return void
  222. */
  223. public function testRenderYearWidgetDefaultRange()
  224. {
  225. $now = new \DateTime();
  226. $result = $this->DateTime->render([
  227. 'month' => false,
  228. 'day' => false,
  229. 'hour' => false,
  230. 'minute' => false,
  231. 'second' => false,
  232. 'val' => $now,
  233. ], $this->context);
  234. $year = $now->format('Y');
  235. $format = '<option value="%s" selected="selected">%s</option>';
  236. $this->assertContains(sprintf($format, $year, $year), $result);
  237. $format = '<option value="%s">%s</option>';
  238. $maxYear = $now->format('Y') + 5;
  239. $minYear = $now->format('Y') - 5;
  240. $this->assertContains(sprintf($format, $maxYear, $maxYear), $result);
  241. $this->assertContains(sprintf($format, $minYear, $minYear), $result);
  242. $nope = $now->format('Y') + 6;
  243. $this->assertNotContains(sprintf($format, $nope, $nope), $result);
  244. $nope = $now->format('Y') - 6;
  245. $this->assertNotContains(sprintf($format, $nope, $nope), $result);
  246. }
  247. /**
  248. * Test ordering of year options.
  249. *
  250. * @return void
  251. */
  252. public function testRenderYearWidgetOrdering()
  253. {
  254. $now = new \DateTime('2014-01-01 12:00:00');
  255. $result = $this->DateTime->render([
  256. 'name' => 'date',
  257. 'year' => [
  258. 'start' => 2013,
  259. 'end' => 2015,
  260. 'data-foo' => 'test',
  261. 'order' => 'asc',
  262. ],
  263. 'month' => false,
  264. 'day' => false,
  265. 'hour' => false,
  266. 'minute' => false,
  267. 'second' => false,
  268. 'val' => $now,
  269. 'orderYear' => 'asc',
  270. ], $this->context);
  271. $expected = [
  272. 'select' => ['name' => 'date[year]', 'data-foo' => 'test'],
  273. ['option' => ['value' => '2013']], '2013', '/option',
  274. ['option' => ['value' => '2014', 'selected' => 'selected']], '2014', '/option',
  275. ['option' => ['value' => '2015']], '2015', '/option',
  276. '/select',
  277. ];
  278. $this->assertHtml($expected, $result);
  279. $result = $this->DateTime->render([
  280. 'name' => 'date',
  281. 'year' => [
  282. 'start' => 2013,
  283. 'end' => 2015,
  284. 'order' => 'desc'
  285. ],
  286. 'month' => false,
  287. 'day' => false,
  288. 'hour' => false,
  289. 'minute' => false,
  290. 'second' => false,
  291. 'val' => $now,
  292. ], $this->context);
  293. $expected = [
  294. 'select' => ['name' => 'date[year]'],
  295. ['option' => ['value' => '2015']], '2015', '/option',
  296. ['option' => ['value' => '2014', 'selected' => 'selected']], '2014', '/option',
  297. ['option' => ['value' => '2013']], '2013', '/option',
  298. '/select',
  299. ];
  300. $this->assertHtml($expected, $result);
  301. }
  302. /**
  303. * Test that a selected value outside of the chosen
  304. * year boundary is also included as an option.
  305. *
  306. * @return void
  307. */
  308. public function testRenderYearWidgetValueOutOfBounds()
  309. {
  310. $now = new \DateTime('2010-01-01 12:00:00');
  311. $result = $this->DateTime->render([
  312. 'name' => 'date',
  313. 'year' => [
  314. 'start' => 2013,
  315. 'end' => 2015,
  316. ],
  317. 'month' => false,
  318. 'day' => false,
  319. 'hour' => false,
  320. 'minute' => false,
  321. 'second' => false,
  322. 'val' => $now,
  323. ], $this->context);
  324. $expected = [
  325. 'select' => ['name' => 'date[year]'],
  326. ['option' => ['value' => '2015']], '2015', '/option',
  327. ['option' => ['value' => '2014']], '2014', '/option',
  328. ['option' => ['value' => '2013']], '2013', '/option',
  329. ['option' => ['value' => '2012']], '2012', '/option',
  330. ['option' => ['value' => '2011']], '2011', '/option',
  331. ['option' => ['value' => '2010', 'selected' => 'selected']], '2010', '/option',
  332. '/select',
  333. ];
  334. $this->assertHtml($expected, $result);
  335. $now = new \DateTime('2013-01-01 12:00:00');
  336. $result = $this->DateTime->render([
  337. 'name' => 'date',
  338. 'year' => [
  339. 'start' => 2010,
  340. 'end' => 2011,
  341. ],
  342. 'month' => false,
  343. 'day' => false,
  344. 'hour' => false,
  345. 'minute' => false,
  346. 'second' => false,
  347. 'val' => $now,
  348. ], $this->context);
  349. $expected = [
  350. 'select' => ['name' => 'date[year]'],
  351. ['option' => ['value' => '2013', 'selected' => 'selected']], '2013', '/option',
  352. ['option' => ['value' => '2012']], '2012', '/option',
  353. ['option' => ['value' => '2011']], '2011', '/option',
  354. ['option' => ['value' => '2010']], '2010', '/option',
  355. '/select',
  356. ];
  357. $this->assertHtml($expected, $result);
  358. }
  359. /**
  360. * Test rendering the month widget
  361. *
  362. * @return void
  363. */
  364. public function testRenderMonthWidget()
  365. {
  366. $now = new \DateTime('2010-09-01 12:00:00');
  367. $result = $this->DateTime->render([
  368. 'name' => 'date',
  369. 'year' => false,
  370. 'day' => false,
  371. 'hour' => false,
  372. 'minute' => false,
  373. 'second' => false,
  374. 'val' => $now,
  375. ], $this->context);
  376. $expected = [
  377. 'select' => ['name' => 'date[month]'],
  378. ['option' => ['value' => '01']], '1', '/option',
  379. ['option' => ['value' => '02']], '2', '/option',
  380. ['option' => ['value' => '03']], '3', '/option',
  381. ['option' => ['value' => '04']], '4', '/option',
  382. ['option' => ['value' => '05']], '5', '/option',
  383. ['option' => ['value' => '06']], '6', '/option',
  384. ['option' => ['value' => '07']], '7', '/option',
  385. ['option' => ['value' => '08']], '8', '/option',
  386. ['option' => ['value' => '09', 'selected' => 'selected']], '9', '/option',
  387. ['option' => ['value' => '10']], '10', '/option',
  388. ['option' => ['value' => '11']], '11', '/option',
  389. ['option' => ['value' => '12']], '12', '/option',
  390. '/select',
  391. ];
  392. $this->assertHtml($expected, $result);
  393. }
  394. /**
  395. * Test rendering month widget with names and values without leading zeros.
  396. *
  397. * @return void
  398. */
  399. public function testRenderMonthWidgetWithNamesNoLeadingZeros()
  400. {
  401. $now = new \DateTime('2010-12-01 12:00:00');
  402. $result = $this->DateTime->render([
  403. 'name' => 'date',
  404. 'year' => false,
  405. 'day' => false,
  406. 'hour' => false,
  407. 'minute' => false,
  408. 'second' => false,
  409. 'month' => ['data-foo' => 'test', 'names' => true, 'leadingZeroKey' => false],
  410. 'meridian' => false,
  411. 'val' => $now,
  412. ], $this->context);
  413. $expected = [
  414. 'select' => ['name' => 'date[month]', 'data-foo' => 'test'],
  415. ['option' => ['value' => '1']], 'January', '/option',
  416. ['option' => ['value' => '2']], 'February', '/option',
  417. ['option' => ['value' => '3']], 'March', '/option',
  418. ['option' => ['value' => '4']], 'April', '/option',
  419. ['option' => ['value' => '5']], 'May', '/option',
  420. ['option' => ['value' => '6']], 'June', '/option',
  421. ['option' => ['value' => '7']], 'July', '/option',
  422. ['option' => ['value' => '8']], 'August', '/option',
  423. ['option' => ['value' => '9']], 'September', '/option',
  424. ['option' => ['value' => '10']], 'October', '/option',
  425. ['option' => ['value' => '11']], 'November', '/option',
  426. ['option' => ['value' => '12', 'selected' => 'selected']], 'December', '/option',
  427. '/select',
  428. ];
  429. $this->assertHtml($expected, $result);
  430. $this->assertNotContains(
  431. '<option value="01">January</option>',
  432. $result,
  433. 'no 01 in value'
  434. );
  435. $this->assertNotContains(
  436. 'value="0"',
  437. $result,
  438. 'no 0 in value'
  439. );
  440. $this->assertNotContains(
  441. 'value="00"',
  442. $result,
  443. 'no 00 in value'
  444. );
  445. $this->assertNotContains(
  446. 'value="13"',
  447. $result,
  448. 'no 13 in value'
  449. );
  450. }
  451. /**
  452. * Test rendering month widget with names.
  453. *
  454. * @return void
  455. */
  456. public function testRenderMonthWidgetWithNames()
  457. {
  458. $now = new \DateTime('2010-09-01 12:00:00');
  459. $result = $this->DateTime->render([
  460. 'name' => 'date',
  461. 'year' => false,
  462. 'day' => false,
  463. 'hour' => false,
  464. 'minute' => false,
  465. 'second' => false,
  466. 'month' => ['data-foo' => 'test', 'names' => true],
  467. 'val' => $now,
  468. ], $this->context);
  469. $expected = [
  470. 'select' => ['name' => 'date[month]', 'data-foo' => 'test'],
  471. ['option' => ['value' => '01']], 'January', '/option',
  472. ['option' => ['value' => '02']], 'February', '/option',
  473. ['option' => ['value' => '03']], 'March', '/option',
  474. ['option' => ['value' => '04']], 'April', '/option',
  475. ['option' => ['value' => '05']], 'May', '/option',
  476. ['option' => ['value' => '06']], 'June', '/option',
  477. ['option' => ['value' => '07']], 'July', '/option',
  478. ['option' => ['value' => '08']], 'August', '/option',
  479. ['option' => ['value' => '09', 'selected' => 'selected']], 'September', '/option',
  480. ['option' => ['value' => '10']], 'October', '/option',
  481. ['option' => ['value' => '11']], 'November', '/option',
  482. ['option' => ['value' => '12']], 'December', '/option',
  483. '/select',
  484. ];
  485. $this->assertHtml($expected, $result);
  486. }
  487. /**
  488. * Test rendering month widget with custom names.
  489. *
  490. * @return void
  491. */
  492. public function testRenderMonthWidgetWithCustomNames()
  493. {
  494. $now = new \DateTime('2010-09-01 12:00:00');
  495. $result = $this->DateTime->render([
  496. 'name' => 'date',
  497. 'year' => false,
  498. 'day' => false,
  499. 'hour' => false,
  500. 'minute' => false,
  501. 'second' => false,
  502. 'month' => [
  503. 'names' => ['01' => 'Jan', '02' => 'Feb']
  504. ],
  505. 'val' => $now,
  506. ], $this->context);
  507. $expected = [
  508. 'select' => ['name' => 'date[month]'],
  509. ['option' => ['value' => '01']], 'Jan', '/option',
  510. ['option' => ['value' => '02']], 'Feb', '/option',
  511. '/select',
  512. ];
  513. $this->assertHtml($expected, $result);
  514. }
  515. /**
  516. * Test rendering the day widget.
  517. *
  518. * @return void
  519. */
  520. public function testRenderDayWidget()
  521. {
  522. $now = new \DateTime('2010-09-09 12:00:00');
  523. $result = $this->DateTime->render([
  524. 'name' => 'date',
  525. 'year' => false,
  526. 'month' => false,
  527. 'day' => [
  528. 'data-foo' => 'test',
  529. ],
  530. 'hour' => false,
  531. 'minute' => false,
  532. 'second' => false,
  533. 'val' => $now,
  534. ], $this->context);
  535. $expected = [
  536. 'select' => ['name' => 'date[day]', 'data-foo' => 'test'],
  537. ['option' => ['value' => '01']], '1', '/option',
  538. ['option' => ['value' => '02']], '2', '/option',
  539. ['option' => ['value' => '03']], '3', '/option',
  540. ['option' => ['value' => '04']], '4', '/option',
  541. ['option' => ['value' => '05']], '5', '/option',
  542. ['option' => ['value' => '06']], '6', '/option',
  543. ['option' => ['value' => '07']], '7', '/option',
  544. ['option' => ['value' => '08']], '8', '/option',
  545. ['option' => ['value' => '09', 'selected' => 'selected']], '9', '/option',
  546. ['option' => ['value' => '10']], '10', '/option',
  547. ['option' => ['value' => '11']], '11', '/option',
  548. ['option' => ['value' => '12']], '12', '/option',
  549. ['option' => ['value' => '13']], '13', '/option',
  550. ['option' => ['value' => '14']], '14', '/option',
  551. ['option' => ['value' => '15']], '15', '/option',
  552. ['option' => ['value' => '16']], '16', '/option',
  553. ['option' => ['value' => '17']], '17', '/option',
  554. ['option' => ['value' => '18']], '18', '/option',
  555. ['option' => ['value' => '19']], '19', '/option',
  556. ['option' => ['value' => '20']], '20', '/option',
  557. ['option' => ['value' => '21']], '21', '/option',
  558. ['option' => ['value' => '22']], '22', '/option',
  559. ['option' => ['value' => '23']], '23', '/option',
  560. ['option' => ['value' => '24']], '24', '/option',
  561. ['option' => ['value' => '25']], '25', '/option',
  562. ['option' => ['value' => '26']], '26', '/option',
  563. ['option' => ['value' => '27']], '27', '/option',
  564. ['option' => ['value' => '28']], '28', '/option',
  565. ['option' => ['value' => '29']], '29', '/option',
  566. ['option' => ['value' => '30']], '30', '/option',
  567. ['option' => ['value' => '31']], '31', '/option',
  568. '/select',
  569. ];
  570. $this->assertHtml($expected, $result);
  571. }
  572. /**
  573. * Test rendering the hour picker in 24 hour mode.
  574. *
  575. * @return void
  576. */
  577. public function testRenderHourWidget24StartAndEnd()
  578. {
  579. $now = new \DateTime('2010-09-09 13:00:00');
  580. $result = $this->DateTime->render([
  581. 'name' => 'date',
  582. 'year' => false,
  583. 'month' => false,
  584. 'day' => false,
  585. 'hour' => [
  586. 'start' => 8,
  587. 'end' => 16
  588. ],
  589. 'minute' => false,
  590. 'second' => false,
  591. 'val' => $now,
  592. ], $this->context);
  593. $this->assertContains('<select name="date[hour]">', $result);
  594. $this->assertNotContains(
  595. '<option value="01">1</option>',
  596. $result,
  597. 'no 1 am'
  598. );
  599. $this->assertNotContains(
  600. '<option value="07">7</option>',
  601. $result,
  602. 'contain 7'
  603. );
  604. $this->assertContains(
  605. '<option value="13" selected="selected">13</option>',
  606. $result,
  607. 'selected value present'
  608. );
  609. $this->assertNotContains(
  610. '<option value="17">17</option>',
  611. $result,
  612. 'contains 17 hours'
  613. );
  614. $this->assertNotContains('meridian', $result, '24hrs has no meridian');
  615. }
  616. /**
  617. * Test rendering the hour picker in 24 hour mode.
  618. *
  619. * @return void
  620. */
  621. public function testRenderHourWidget24()
  622. {
  623. $now = new \DateTime('2010-09-09 13:00:00');
  624. $result = $this->DateTime->render([
  625. 'name' => 'date',
  626. 'year' => false,
  627. 'month' => false,
  628. 'day' => false,
  629. 'hour' => [
  630. 'format' => 24,
  631. 'data-foo' => 'test'
  632. ],
  633. 'minute' => false,
  634. 'second' => false,
  635. 'val' => $now,
  636. 'meridian' => [],
  637. ], $this->context);
  638. $this->assertContains('<select name="date[hour]" data-foo="test">', $result);
  639. $this->assertContains('<option value="00">0</option>', $result);
  640. $this->assertContains(
  641. '<option value="01">1</option>',
  642. $result,
  643. 'contain 1 am'
  644. );
  645. $this->assertContains(
  646. '<option value="05">5</option>',
  647. $result,
  648. 'contain 5 am'
  649. );
  650. $this->assertContains(
  651. '<option value="13" selected="selected">13</option>',
  652. $result,
  653. 'selected value present'
  654. );
  655. $this->assertContains('<option value="23">23</option>', $result);
  656. $this->assertNotContains('date[day]', $result, 'No day select.');
  657. $this->assertNotContains('value="0"', $result, 'No zero hour');
  658. $this->assertNotContains('value="24"', $result, 'No 25th hour');
  659. $this->assertNotContains('<select name="date[meridian]">', $result);
  660. $this->assertNotContains('<option value="pm" selected="selected">pm</option>', $result);
  661. }
  662. /**
  663. * test selecting various options in 24 hr mode.
  664. *
  665. * @return void
  666. */
  667. public function testRenderHour24SelectedValues()
  668. {
  669. $now = new \DateTime('2010-09-09 23:00:00');
  670. $data = [
  671. 'name' => 'date',
  672. 'year' => false,
  673. 'month' => false,
  674. 'day' => false,
  675. 'hour' => [],
  676. 'minute' => false,
  677. 'second' => false,
  678. 'val' => $now,
  679. ];
  680. $result = $this->DateTime->render($data, $this->context);
  681. $this->assertContains('<option value="23" selected="selected">23</option>', $result);
  682. $data['val'] = '2010-09-09 23:00:00';
  683. $result = $this->DateTime->render($data, $this->context);
  684. $this->assertContains('<option value="23" selected="selected">23</option>', $result);
  685. }
  686. /**
  687. * Test rendering the hour widget in 12 hour mode.
  688. *
  689. * @return void
  690. */
  691. public function testRenderHourWidget12()
  692. {
  693. $now = new \DateTime('2010-09-09 13:00:00');
  694. $result = $this->DateTime->render([
  695. 'name' => 'date',
  696. 'year' => false,
  697. 'month' => false,
  698. 'day' => false,
  699. 'hour' => [
  700. 'format' => 12,
  701. 'data-foo' => 'test'
  702. ],
  703. 'minute' => false,
  704. 'second' => false,
  705. 'val' => $now,
  706. ], $this->context);
  707. $this->assertContains('<select name="date[hour]" data-foo="test">', $result);
  708. $this->assertContains(
  709. '<option value="01" selected="selected">1</option>',
  710. $result,
  711. 'contain 1pm selected'
  712. );
  713. $this->assertContains(
  714. '<option value="05">5</option>',
  715. $result,
  716. 'contain 5'
  717. );
  718. $this->assertContains(
  719. '<option value="12">12</option>',
  720. $result,
  721. 'contain 12'
  722. );
  723. $this->assertNotContains(
  724. '<option value="13">13</option>',
  725. $result,
  726. 'selected value present'
  727. );
  728. $this->assertNotContains('date[day]', $result, 'No day select.');
  729. $this->assertNotContains('value="0"', $result, 'No zero hour');
  730. $this->assertContains('<select name="date[meridian]">', $result);
  731. $this->assertContains('<option value="pm" selected="selected">pm</option>', $result);
  732. }
  733. /**
  734. * Test rendering hour widget in 12 hour mode at midnight.
  735. *
  736. * @return void
  737. */
  738. public function testRenderHourWidget12Midnight()
  739. {
  740. $now = new \DateTime('2010-09-09 00:30:45');
  741. $result = $this->DateTime->render([
  742. 'name' => 'date',
  743. 'year' => false,
  744. 'month' => false,
  745. 'day' => false,
  746. 'hour' => [
  747. 'format' => 12,
  748. ],
  749. 'minute' => false,
  750. 'second' => false,
  751. 'val' => $now,
  752. ], $this->context);
  753. $this->assertContains(
  754. '<option value="12" selected="selected">12</option>',
  755. $result,
  756. '12 is selected'
  757. );
  758. }
  759. /**
  760. * Test rendering the hour picker in 12 hour mode.
  761. *
  762. * @return void
  763. */
  764. public function testRenderHourWidget12StartAndEnd()
  765. {
  766. $now = new \DateTime('2010-09-09 13:00:00');
  767. $result = $this->DateTime->render([
  768. 'name' => 'date',
  769. 'year' => false,
  770. 'month' => false,
  771. 'day' => false,
  772. 'hour' => [
  773. 'start' => 8,
  774. 'end' => 12
  775. ],
  776. 'minute' => false,
  777. 'second' => false,
  778. 'val' => $now,
  779. ], $this->context);
  780. $this->assertContains('<select name="date[hour]">', $result);
  781. $this->assertContains(
  782. '<option value="08">8</option>',
  783. $result,
  784. 'contains 8am'
  785. );
  786. $this->assertContains(
  787. '<option value="12">12</option>',
  788. $result,
  789. 'contains 8am'
  790. );
  791. $this->assertNotContains(
  792. '<option value="01">1</option>',
  793. $result,
  794. 'no 1 am'
  795. );
  796. $this->assertNotContains(
  797. '<option value="07">7</option>',
  798. $result,
  799. 'contain 7'
  800. );
  801. $this->assertNotContains(
  802. '<option value="13" selected="selected">13</option>',
  803. $result,
  804. 'selected value present'
  805. );
  806. }
  807. /**
  808. * Test rendering the minute widget with no options.
  809. *
  810. * @return void
  811. */
  812. public function testRenderMinuteWidget()
  813. {
  814. $now = new \DateTime('2010-09-09 13:25:00');
  815. $result = $this->DateTime->render([
  816. 'name' => 'date',
  817. 'year' => false,
  818. 'month' => false,
  819. 'day' => false,
  820. 'hour' => false,
  821. 'minute' => [
  822. 'data-foo' => 'test',
  823. ],
  824. 'second' => false,
  825. 'val' => $now,
  826. ], $this->context);
  827. $this->assertContains('<select name="date[minute]" data-foo="test">', $result);
  828. $this->assertContains(
  829. '<option value="00">00</option>',
  830. $result,
  831. 'contains 00'
  832. );
  833. $this->assertContains(
  834. '<option value="05">05</option>',
  835. $result,
  836. 'contains 05'
  837. );
  838. $this->assertContains(
  839. '<option value="25" selected="selected">25</option>',
  840. $result,
  841. 'selected value present'
  842. );
  843. $this->assertContains(
  844. '<option value="59">59</option>',
  845. $result,
  846. 'contains 59'
  847. );
  848. $this->assertNotContains('value="60"', $result, 'No 60 value');
  849. }
  850. /**
  851. * Test rendering the minute widget with empty at zero options.
  852. *
  853. * @return void
  854. */
  855. public function testRenderMinuteWidgetEmptyZeroDefault()
  856. {
  857. $now = new \DateTime('2010-09-09 13:00:23');
  858. $result = $this->DateTime->render([
  859. 'name' => 'date',
  860. 'year' => false,
  861. 'month' => false,
  862. 'day' => false,
  863. 'hour' => false,
  864. 'minute' => [
  865. 'data-foo' => 'test',
  866. ],
  867. 'empty' => '-',
  868. 'default' => '',
  869. 'second' => false,
  870. 'val' => $now,
  871. ], $this->context);
  872. $this->assertContains('<select name="date[minute]" data-foo="test">', $result);
  873. $this->assertContains(
  874. '<option value="">-</option>',
  875. $result,
  876. 'contains empty option -'
  877. );
  878. $this->assertContains(
  879. '<option value="00" selected="selected">00</option>',
  880. $result,
  881. 'selected value present and correct at 00'
  882. );
  883. $this->assertContains(
  884. '<option value="05">05</option>',
  885. $result,
  886. 'contains 05'
  887. );
  888. $this->assertContains(
  889. '<option value="25">25</option>',
  890. $result,
  891. 'contains 25'
  892. );
  893. $this->assertContains(
  894. '<option value="59">59</option>',
  895. $result,
  896. 'contains 59'
  897. );
  898. $this->assertNotContains(
  899. '<option value="" selected="selected">-</option>',
  900. $result,
  901. 'No 0 value as empty value'
  902. );
  903. $this->assertNotContains('value="0"', $result, 'No unpadded 0 value');
  904. $this->assertNotContains('value="60"', $result, 'No 60 value');
  905. }
  906. /**
  907. * Test minutes with interval values.
  908. *
  909. * @return void
  910. */
  911. public function testRenderMinuteWidgetInterval()
  912. {
  913. $now = new \DateTime('2010-09-09 13:23:00');
  914. $result = $this->DateTime->render([
  915. 'name' => 'date',
  916. 'year' => false,
  917. 'month' => false,
  918. 'day' => false,
  919. 'hour' => false,
  920. 'minute' => [
  921. 'interval' => 5
  922. ],
  923. 'second' => false,
  924. 'val' => $now,
  925. ], $this->context);
  926. $this->assertContains('<select name="date[minute]">', $result);
  927. $this->assertContains(
  928. '<option value="00">00</option>',
  929. $result,
  930. 'contains 00'
  931. );
  932. $this->assertContains(
  933. '<option value="05">05</option>',
  934. $result,
  935. 'contains 05'
  936. );
  937. $this->assertContains(
  938. '<option value="25" selected="selected">25</option>',
  939. $result,
  940. 'selected value present'
  941. );
  942. $this->assertContains(
  943. '<option value="55">55</option>',
  944. $result,
  945. 'contains 55'
  946. );
  947. $this->assertNotContains('value="2"', $result, 'No 2 value');
  948. $this->assertNotContains('value="23"', $result, 'No 23 value');
  949. $this->assertNotContains('value="58"', $result, 'No 58 value');
  950. $this->assertNotContains('value="59"', $result, 'No 59 value');
  951. $this->assertNotContains('value="60"', $result, 'No 60 value');
  952. }
  953. /**
  954. * Test rounding up and down.
  955. *
  956. * @return void
  957. */
  958. public function testRenderMinuteWidgetIntervalRounding()
  959. {
  960. $now = new \DateTime('2010-09-09 13:22:00');
  961. $data = [
  962. 'name' => 'date',
  963. 'year' => false,
  964. 'month' => false,
  965. 'day' => false,
  966. 'hour' => false,
  967. 'minute' => [
  968. 'interval' => 5,
  969. 'round' => 'up',
  970. ],
  971. 'second' => false,
  972. 'val' => $now,
  973. ];
  974. $result = $this->DateTime->render($data, $this->context);
  975. $this->assertContains(
  976. '<option value="25" selected="selected">25</option>',
  977. $result,
  978. 'selected value present'
  979. );
  980. $this->assertNotContains('value="23"', $result, 'No 23 value');
  981. $data['minute']['round'] = 'down';
  982. $result = $this->DateTime->render($data, $this->context);
  983. $this->assertContains(
  984. '<option value="20" selected="selected">20</option>',
  985. $result,
  986. 'selected value present'
  987. );
  988. $this->assertNotContains('value="23"', $result, 'No 23 value');
  989. }
  990. /**
  991. * Test that minute interval rounding can effect hours and days.
  992. *
  993. * @return void
  994. */
  995. public function testMinuteIntervalHourRollover()
  996. {
  997. $now = new \DateTime('2010-09-09 23:58:00');
  998. $result = $this->DateTime->render([
  999. 'name' => 'date',
  1000. 'year' => false,
  1001. 'month' => false,
  1002. 'minute' => [
  1003. 'interval' => 5,
  1004. 'round' => 'up',
  1005. ],
  1006. 'second' => false,
  1007. 'val' => $now,
  1008. ], $this->context);
  1009. $this->assertContains(
  1010. '<option value="00" selected="selected">00</option>',
  1011. $result,
  1012. 'selected minute present'
  1013. );
  1014. $this->assertContains(
  1015. '<option value="10" selected="selected">10</option>',
  1016. $result,
  1017. 'selected day present'
  1018. );
  1019. }
  1020. /**
  1021. * Test render seconds basic.
  1022. *
  1023. * @return void
  1024. */
  1025. public function testRenderSecondsWidget()
  1026. {
  1027. $now = new \DateTime('2010-09-09 13:00:25');
  1028. $result = $this->DateTime->render([
  1029. 'name' => 'date',
  1030. 'year' => false,
  1031. 'month' => false,
  1032. 'day' => false,
  1033. 'hour' => false,
  1034. 'minute' => false,
  1035. 'second' => [
  1036. 'data-foo' => 'test',
  1037. ],
  1038. 'val' => $now,
  1039. ], $this->context);
  1040. $this->assertContains('<select name="date[second]" data-foo="test">', $result);
  1041. $this->assertContains(
  1042. '<option value="00">00</option>',
  1043. $result,
  1044. 'contains 00'
  1045. );
  1046. $this->assertContains(
  1047. '<option value="01">01</option>',
  1048. $result,
  1049. 'contains 01'
  1050. );
  1051. $this->assertContains(
  1052. '<option value="05">05</option>',
  1053. $result,
  1054. 'contains 05'
  1055. );
  1056. $this->assertContains(
  1057. '<option value="25" selected="selected">25</option>',
  1058. $result,
  1059. 'selected value present'
  1060. );
  1061. $this->assertContains(
  1062. '<option value="59">59</option>',
  1063. $result,
  1064. 'contains 59'
  1065. );
  1066. $this->assertNotContains('value="0"', $result, 'No unpadded zero value');
  1067. $this->assertNotContains('value="60"', $result, 'No 60 value');
  1068. }
  1069. /**
  1070. * Test the merdian select.
  1071. *
  1072. * @return void
  1073. */
  1074. public function testRenderMeridianWidget()
  1075. {
  1076. $now = new \DateTime('2010-09-09 13:00:25');
  1077. $result = $this->DateTime->render([
  1078. 'name' => 'date',
  1079. 'year' => false,
  1080. 'month' => false,
  1081. 'day' => false,
  1082. 'hour' => false,
  1083. 'minute' => false,
  1084. 'second' => false,
  1085. 'meridian' => [],
  1086. 'val' => $now,
  1087. ], $this->context);
  1088. $expected = [
  1089. 'select' => ['name' => 'date[meridian]'],
  1090. ['option' => ['value' => 'am']], 'am', '/option',
  1091. ['option' => ['value' => 'pm', 'selected' => 'selected']], 'pm', '/option',
  1092. '/select',
  1093. ];
  1094. $this->assertHtml($expected, $result);
  1095. $now = new \DateTime('2010-09-09 09:00:25');
  1096. $result = $this->DateTime->render([
  1097. 'name' => 'date',
  1098. 'year' => false,
  1099. 'month' => false,
  1100. 'day' => false,
  1101. 'hour' => false,
  1102. 'minute' => false,
  1103. 'second' => false,
  1104. 'meridian' => [],
  1105. 'val' => $now,
  1106. ], $this->context);
  1107. $expected = [
  1108. 'select' => ['name' => 'date[meridian]'],
  1109. ['option' => ['value' => 'am', 'selected' => 'selected']], 'am', '/option',
  1110. ['option' => ['value' => 'pm']], 'pm', '/option',
  1111. '/select',
  1112. ];
  1113. $this->assertHtml($expected, $result);
  1114. }
  1115. /**
  1116. * Test that secureFields omits removed selects
  1117. *
  1118. * @return void
  1119. */
  1120. public function testSecureFields()
  1121. {
  1122. $data = [
  1123. 'name' => 'date',
  1124. ];
  1125. $result = $this->DateTime->secureFields($data);
  1126. $expected = [
  1127. 'date[year]', 'date[month]', 'date[day]',
  1128. 'date[hour]', 'date[minute]', 'date[second]',
  1129. ];
  1130. $this->assertEquals($expected, $result, 'No meridian on 24hr input');
  1131. $data = [
  1132. 'name' => 'date',
  1133. 'hour' => ['format' => 24]
  1134. ];
  1135. $result = $this->DateTime->secureFields($data);
  1136. $this->assertEquals($expected, $result, 'No meridian on 24hr input');
  1137. $data = [
  1138. 'name' => 'date',
  1139. 'year' => false,
  1140. 'month' => false,
  1141. 'day' => false,
  1142. 'hour' => [
  1143. 'format' => 12,
  1144. 'data-foo' => 'test'
  1145. ],
  1146. 'minute' => false,
  1147. 'second' => false,
  1148. ];
  1149. $result = $this->DateTime->secureFields($data);
  1150. $expected = [
  1151. 'date[hour]', 'date[meridian]'
  1152. ];
  1153. $this->assertEquals($expected, $result);
  1154. }
  1155. }