EntityContextTest.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454
  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 CakePHP(tm) v 3.0
  13. * @license http://www.opensource.org/licenses/mit-license.php MIT License
  14. */
  15. namespace Cake\Test\TestCase\View\Form;
  16. use Cake\Network\Request;
  17. use Cake\ORM\Entity;
  18. use Cake\ORM\Table;
  19. use Cake\ORM\TableRegistry;
  20. use Cake\TestSuite\TestCase;
  21. use Cake\Validation\Validator;
  22. use Cake\View\Form\EntityContext;
  23. /**
  24. * Test stub.
  25. */
  26. class Article extends Entity {
  27. }
  28. /**
  29. * Entity context test case.
  30. */
  31. class EntityContextTest extends TestCase {
  32. /**
  33. * Fixtures to use.
  34. *
  35. * @var array
  36. */
  37. public $fixtures = ['core.article', 'core.comment'];
  38. /**
  39. * setup method.
  40. *
  41. * @return void
  42. */
  43. public function setUp() {
  44. parent::setUp();
  45. $this->request = new Request();
  46. }
  47. /**
  48. * Test operations that lack a table argument.
  49. *
  50. * @return void
  51. */
  52. public function testOperationsNoTableArg() {
  53. $row = new Article([
  54. 'title' => 'Test entity',
  55. 'body' => 'Something new'
  56. ]);
  57. $row->errors('title', ['Title is required.']);
  58. $context = new EntityContext($this->request, [
  59. 'entity' => $row,
  60. ]);
  61. $result = $context->val('title');
  62. $this->assertEquals($row->title, $result);
  63. $result = $context->error('title');
  64. $this->assertEquals($row->errors('title'), $result);
  65. }
  66. /**
  67. * Test reading data.
  68. *
  69. * @return void
  70. */
  71. public function testValBasic() {
  72. $row = new Entity([
  73. 'title' => 'Test entity',
  74. 'body' => 'Something new'
  75. ]);
  76. $context = new EntityContext($this->request, [
  77. 'entity' => $row,
  78. 'table' => 'Articles',
  79. ]);
  80. $result = $context->val('title');
  81. $this->assertEquals($row->title, $result);
  82. $result = $context->val('body');
  83. $this->assertEquals($row->body, $result);
  84. $result = $context->val('nope');
  85. $this->assertNull($result);
  86. }
  87. /**
  88. * Test reading values from associated entities.
  89. *
  90. * @return void
  91. */
  92. public function testValAssociated() {
  93. $row = new Entity([
  94. 'title' => 'Test entity',
  95. 'user' => new Entity([
  96. 'username' => 'mark',
  97. 'fname' => 'Mark'
  98. ]),
  99. 'comments' => [
  100. new Entity(['comment' => 'Test comment']),
  101. new Entity(['comment' => 'Second comment']),
  102. ]
  103. ]);
  104. $context = new EntityContext($this->request, [
  105. 'entity' => $row,
  106. 'table' => 'Articles',
  107. ]);
  108. $result = $context->val('user.fname');
  109. $this->assertEquals($row->user->fname, $result);
  110. $result = $context->val('comments.0.comment');
  111. $this->assertEquals($row->comments[0]->comment, $result);
  112. $result = $context->val('comments.1.comment');
  113. $this->assertEquals($row->comments[1]->comment, $result);
  114. $result = $context->val('comments.0.nope');
  115. $this->assertNull($result);
  116. $result = $context->val('comments.0.nope.no_way');
  117. $this->assertNull($result);
  118. }
  119. /**
  120. * Test validator as a string.
  121. *
  122. * @return void
  123. */
  124. public function testIsRequiredStringValidator() {
  125. $this->_setupTables();
  126. $context = new EntityContext($this->request, [
  127. 'entity' => new Entity(),
  128. 'table' => 'Articles',
  129. 'validator' => 'create',
  130. ]);
  131. $this->assertTrue($context->isRequired('title'));
  132. $this->assertFalse($context->isRequired('body'));
  133. $this->assertFalse($context->isRequired('Herp.derp.derp'));
  134. $this->assertFalse($context->isRequired('nope'));
  135. }
  136. /**
  137. * Test isRequired on associated entities.
  138. *
  139. * @return void
  140. */
  141. public function testIsRequiredAssociatedHasMany() {
  142. $this->_setupTables();
  143. $comments = TableRegistry::get('Comments');
  144. $validator = $comments->validator();
  145. $validator->add('user_id', 'number', [
  146. 'rule' => 'numeric',
  147. ]);
  148. $row = new Entity([
  149. 'title' => 'My title',
  150. 'comments' => [
  151. new Entity(['comment' => 'First comment']),
  152. new Entity(['comment' => 'Second comment']),
  153. ]
  154. ]);
  155. $context = new EntityContext($this->request, [
  156. 'entity' => $row,
  157. 'table' => 'Articles',
  158. 'validator' => 'default',
  159. ]);
  160. $this->assertTrue($context->isRequired('comments.0.user_id'));
  161. $this->assertFalse($context->isRequired('comments.0.other'));
  162. }
  163. /**
  164. * Test isRequired on associated entities with custom validators.
  165. *
  166. * @return void
  167. */
  168. public function testIsRequiredAssociatedValidator() {
  169. $this->_setupTables();
  170. $row = new Entity([
  171. 'title' => 'My title',
  172. 'comments' => [
  173. new Entity(['comment' => 'First comment']),
  174. new Entity(['comment' => 'Second comment']),
  175. ]
  176. ]);
  177. $context = new EntityContext($this->request, [
  178. 'entity' => $row,
  179. 'table' => 'Articles',
  180. 'validator' => [
  181. 'Articles' => 'create',
  182. 'Comments' => 'custom'
  183. ]
  184. ]);
  185. $this->assertTrue($context->isRequired('title'));
  186. $this->assertFalse($context->isRequired('body'));
  187. $this->assertTrue($context->isRequired('comments.0.comment'));
  188. $this->assertTrue($context->isRequired('comments.1.comment'));
  189. }
  190. /**
  191. * Test isRequired on associated entities.
  192. *
  193. * @return void
  194. */
  195. public function testIsRequiredAssociatedBelongsTo() {
  196. $this->_setupTables();
  197. $row = new Entity([
  198. 'title' => 'My title',
  199. 'user' => new Entity(['username' => 'Mark']),
  200. ]);
  201. $context = new EntityContext($this->request, [
  202. 'entity' => $row,
  203. 'table' => 'Articles',
  204. 'validator' => [
  205. 'Articles' => 'create',
  206. 'Users' => 'custom'
  207. ]
  208. ]);
  209. $this->assertTrue($context->isRequired('user.username'));
  210. $this->assertFalse($context->isRequired('user.first_name'));
  211. }
  212. /**
  213. * Test type() basic
  214. *
  215. * @return void
  216. */
  217. public function testType() {
  218. $this->_setupTables();
  219. $row = new Entity([
  220. 'title' => 'My title',
  221. 'body' => 'Some content',
  222. ]);
  223. $context = new EntityContext($this->request, [
  224. 'entity' => $row,
  225. 'table' => 'Articles',
  226. ]);
  227. $this->assertEquals('string', $context->type('title'));
  228. $this->assertEquals('text', $context->type('body'));
  229. $this->assertEquals('integer', $context->type('user_id'));
  230. $this->assertNull($context->type('nope'));
  231. }
  232. /**
  233. * Test getting types for associated records.
  234. *
  235. * @return void
  236. */
  237. public function testTypeAssociated() {
  238. $this->_setupTables();
  239. $row = new Entity([
  240. 'title' => 'My title',
  241. 'user' => new Entity(['username' => 'Mark']),
  242. ]);
  243. $context = new EntityContext($this->request, [
  244. 'entity' => $row,
  245. 'table' => 'Articles',
  246. ]);
  247. $this->assertEquals('string', $context->type('user.username'));
  248. $this->assertEquals('text', $context->type('user.bio'));
  249. $this->assertNull($context->type('user.nope'));
  250. }
  251. /**
  252. * Test attributes for fields.
  253. *
  254. * @return void
  255. */
  256. public function testAttributes() {
  257. $this->_setupTables();
  258. $row = new Entity([
  259. 'title' => 'My title',
  260. 'user' => new Entity(['username' => 'Mark']),
  261. ]);
  262. $context = new EntityContext($this->request, [
  263. 'entity' => $row,
  264. 'table' => 'Articles',
  265. ]);
  266. $expected = [
  267. 'length' => 255, 'precision' => null
  268. ];
  269. $this->assertEquals($expected, $context->attributes('title'));
  270. $expected = [
  271. 'length' => null, 'precision' => null
  272. ];
  273. $this->assertEquals($expected, $context->attributes('body'));
  274. $expected = [
  275. 'length' => 10, 'precision' => 3
  276. ];
  277. $this->assertEquals($expected, $context->attributes('user.rating'));
  278. }
  279. /**
  280. * Test hasError
  281. *
  282. * @return void
  283. */
  284. public function testHasError() {
  285. $this->_setupTables();
  286. $row = new Entity([
  287. 'title' => 'My title',
  288. 'user' => new Entity(['username' => 'Mark']),
  289. ]);
  290. $row->errors('title', []);
  291. $row->errors('body', 'Gotta have one');
  292. $row->errors('user_id', ['Required field']);
  293. $context = new EntityContext($this->request, [
  294. 'entity' => $row,
  295. 'table' => 'Articles',
  296. ]);
  297. $this->assertFalse($context->hasError('title'));
  298. $this->assertFalse($context->hasError('nope'));
  299. $this->assertTrue($context->hasError('body'));
  300. $this->assertTrue($context->hasError('user_id'));
  301. }
  302. /**
  303. * Test hasError on associated records
  304. *
  305. * @return void
  306. */
  307. public function testHasErrorAssociated() {
  308. $this->_setupTables();
  309. $row = new Entity([
  310. 'title' => 'My title',
  311. 'user' => new Entity(['username' => 'Mark']),
  312. ]);
  313. $row->errors('title', []);
  314. $row->errors('body', 'Gotta have one');
  315. $row->user->errors('username', ['Required']);
  316. $context = new EntityContext($this->request, [
  317. 'entity' => $row,
  318. 'table' => 'Articles',
  319. ]);
  320. $this->assertTrue($context->hasError('user.username'));
  321. $this->assertFalse($context->hasError('user.nope'));
  322. $this->assertFalse($context->hasError('no.nope'));
  323. }
  324. /**
  325. * Test error
  326. *
  327. * @return void
  328. */
  329. public function testError() {
  330. $this->_setupTables();
  331. $row = new Entity([
  332. 'title' => 'My title',
  333. 'user' => new Entity(['username' => 'Mark']),
  334. ]);
  335. $row->errors('title', []);
  336. $row->errors('body', 'Gotta have one');
  337. $row->errors('user_id', ['Required field']);
  338. $row->user->errors('username', ['Required']);
  339. $context = new EntityContext($this->request, [
  340. 'entity' => $row,
  341. 'table' => 'Articles',
  342. ]);
  343. $this->assertEquals([], $context->error('title'));
  344. $expected = ['Gotta have one'];
  345. $this->assertEquals($expected, $context->error('body'));
  346. $expected = ['Required'];
  347. $this->assertEquals($expected, $context->error('user.username'));
  348. }
  349. /**
  350. * Setup tables for tests.
  351. *
  352. * @return void
  353. */
  354. protected function _setupTables() {
  355. $articles = TableRegistry::get('Articles');
  356. $articles->belongsTo('Users');
  357. $articles->hasMany('Comments');
  358. $comments = TableRegistry::get('Comments');
  359. $users = TableRegistry::get('Users');
  360. $articles->schema([
  361. 'id' => ['type' => 'integer', 'length' => 11, 'null' => false],
  362. 'title' => ['type' => 'string', 'length' => 255],
  363. 'user_id' => ['type' => 'integer', 'length' => 11, 'null' => false],
  364. 'body' => ['type' => 'text']
  365. ]);
  366. $users->schema([
  367. 'id' => ['type' => 'integer', 'length' => 11],
  368. 'username' => ['type' => 'string', 'length' => 255],
  369. 'bio' => ['type' => 'text'],
  370. 'rating' => ['type' => 'decimal', 'length' => 10, 'precision' => 3],
  371. ]);
  372. $validator = new Validator();
  373. $validator->add('title', 'minlength', [
  374. 'rule' => ['minlength', 10]
  375. ])
  376. ->add('body', 'maxlength', [
  377. 'rule' => ['maxlength', 1000]
  378. ])->allowEmpty('body');
  379. $articles->validator('create', $validator);
  380. $validator = new Validator();
  381. $validator->add('username', 'length', [
  382. 'rule' => ['minlength', 10]
  383. ]);
  384. $users->validator('custom', $validator);
  385. $validator = new Validator();
  386. $validator->add('comment', 'length', [
  387. 'rule' => ['minlength', 10]
  388. ]);
  389. $comments->validator('custom', $validator);
  390. }
  391. }