ModelTaskTest.php 37 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225
  1. <?php
  2. /**
  3. * ModelTaskTest file
  4. *
  5. * Test Case for test generation shell task
  6. *
  7. * CakePHP : Rapid Development Framework (http://cakephp.org)
  8. * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  9. *
  10. * Licensed under The MIT License
  11. * For full copyright and license information, please see the LICENSE.txt
  12. * Redistributions of files must retain the above copyright notice.
  13. *
  14. * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  15. * @link http://cakephp.org CakePHP Project
  16. * @package Cake.Test.Case.Console.Command.Task
  17. * @since CakePHP v 1.2.6
  18. * @license http://www.opensource.org/licenses/mit-license.php MIT License
  19. */
  20. App::uses('ShellDispatcher', 'Console');
  21. App::uses('Shell', 'Console');
  22. App::uses('ConsoleOutput', 'Console');
  23. App::uses('ConsoleInput', 'Console');
  24. App::uses('FixtureTask', 'Console/Command/Task');
  25. App::uses('TemplateTask', 'Console/Command/Task');
  26. App::uses('ModelTask', 'Console/Command/Task');
  27. /**
  28. * ModelTaskTest class
  29. *
  30. * @package Cake.Test.Case.Console.Command.Task
  31. */
  32. class ModelTaskTest extends CakeTestCase {
  33. /**
  34. * fixtures
  35. *
  36. * @var array
  37. */
  38. public $fixtures = array(
  39. 'core.bake_article', 'core.bake_comment', 'core.bake_articles_bake_tag',
  40. 'core.bake_tag', 'core.category_thread', 'core.number_tree'
  41. );
  42. /**
  43. * setUp method
  44. *
  45. * @return void
  46. */
  47. public function setUp() {
  48. parent::setUp();
  49. $out = $this->getMock('ConsoleOutput', array(), array(), '', false);
  50. $in = $this->getMock('ConsoleInput', array(), array(), '', false);
  51. $this->Task = $this->getMock('ModelTask',
  52. array('in', 'err', 'createFile', '_stop', '_checkUnitTest'),
  53. array($out, $out, $in)
  54. );
  55. $this->_setupOtherMocks();
  56. }
  57. /**
  58. * Setup a mock that has out mocked. Normally this is not used as it makes $this->at() really tricky.
  59. *
  60. * @return void
  61. */
  62. protected function _useMockedOut() {
  63. $out = $this->getMock('ConsoleOutput', array(), array(), '', false);
  64. $in = $this->getMock('ConsoleInput', array(), array(), '', false);
  65. $this->Task = $this->getMock('ModelTask',
  66. array('in', 'out', 'err', 'hr', 'createFile', '_stop', '_checkUnitTest'),
  67. array($out, $out, $in)
  68. );
  69. $this->_setupOtherMocks();
  70. }
  71. /**
  72. * sets up the rest of the dependencies for Model Task
  73. *
  74. * @return void
  75. */
  76. protected function _setupOtherMocks() {
  77. $out = $this->getMock('ConsoleOutput', array(), array(), '', false);
  78. $in = $this->getMock('ConsoleInput', array(), array(), '', false);
  79. $this->Task->Fixture = $this->getMock('FixtureTask', array(), array($out, $out, $in));
  80. $this->Task->Test = $this->getMock('FixtureTask', array(), array($out, $out, $in));
  81. $this->Task->Template = new TemplateTask($out, $out, $in);
  82. $this->Task->name = 'Model';
  83. $this->Task->interactive = true;
  84. }
  85. /**
  86. * tearDown method
  87. *
  88. * @return void
  89. */
  90. public function tearDown() {
  91. parent::tearDown();
  92. unset($this->Task);
  93. }
  94. /**
  95. * Test that listAll scans the database connection and lists all the tables in it.s
  96. *
  97. * @return void
  98. */
  99. public function testListAllArgument() {
  100. $this->_useMockedOut();
  101. $result = $this->Task->listAll('test');
  102. $this->assertContains('bake_articles', $result);
  103. $this->assertContains('bake_articles_bake_tags', $result);
  104. $this->assertContains('bake_tags', $result);
  105. $this->assertContains('bake_comments', $result);
  106. $this->assertContains('category_threads', $result);
  107. }
  108. /**
  109. * Test that listAll uses the connection property
  110. *
  111. * @return void
  112. */
  113. public function testListAllConnection() {
  114. $this->_useMockedOut();
  115. $this->Task->connection = 'test';
  116. $result = $this->Task->listAll();
  117. $this->assertContains('bake_articles', $result);
  118. $this->assertContains('bake_articles_bake_tags', $result);
  119. $this->assertContains('bake_tags', $result);
  120. $this->assertContains('bake_comments', $result);
  121. $this->assertContains('category_threads', $result);
  122. }
  123. /**
  124. * Test that getName interacts with the user and returns the model name.
  125. *
  126. * @return void
  127. */
  128. public function testGetNameQuit() {
  129. $this->Task->expects($this->once())->method('in')->will($this->returnValue('q'));
  130. $this->Task->expects($this->once())->method('_stop');
  131. $this->Task->getName('test');
  132. }
  133. /**
  134. * test getName with a valid option.
  135. *
  136. * @return void
  137. */
  138. public function testGetNameValidOption() {
  139. $listing = $this->Task->listAll('test');
  140. $this->Task->expects($this->any())->method('in')->will($this->onConsecutiveCalls(1, 4));
  141. $result = $this->Task->getName('test');
  142. $this->assertEquals(Inflector::classify($listing[0]), $result);
  143. $result = $this->Task->getName('test');
  144. $this->assertEquals(Inflector::classify($listing[3]), $result);
  145. }
  146. /**
  147. * test that an out of bounds option causes an error.
  148. *
  149. * @return void
  150. */
  151. public function testGetNameWithOutOfBoundsOption() {
  152. $this->Task->expects($this->any())->method('in')->will($this->onConsecutiveCalls(99, 1));
  153. $this->Task->expects($this->once())->method('err');
  154. $this->Task->getName('test');
  155. }
  156. /**
  157. * Test table name interactions
  158. *
  159. * @return void
  160. */
  161. public function testGetTableName() {
  162. $this->Task->expects($this->at(0))->method('in')->will($this->returnValue('y'));
  163. $result = $this->Task->getTable('BakeArticle', 'test');
  164. $expected = 'bake_articles';
  165. $this->assertEquals($expected, $result);
  166. }
  167. /**
  168. * test getting a custom table name.
  169. *
  170. * @return void
  171. */
  172. public function testGetTableNameCustom() {
  173. $this->Task->expects($this->any())->method('in')->will($this->onConsecutiveCalls('n', 'my_table'));
  174. $result = $this->Task->getTable('BakeArticle', 'test');
  175. $expected = 'my_table';
  176. $this->assertEquals($expected, $result);
  177. }
  178. /**
  179. * test getTable with non-conventional tablenames
  180. *
  181. * @return void
  182. */
  183. public function testGetTableOddTableInteractive() {
  184. $out = $this->getMock('ConsoleOutput', array(), array(), '', false);
  185. $in = $this->getMock('ConsoleInput', array(), array(), '', false);
  186. $this->Task = $this->getMock('ModelTask',
  187. array('in', 'err', '_stop', '_checkUnitTest', 'getAllTables'),
  188. array($out, $out, $in)
  189. );
  190. $this->_setupOtherMocks();
  191. $this->Task->connection = 'test';
  192. $this->Task->path = '/my/path/';
  193. $this->Task->interactive = true;
  194. $this->Task->expects($this->once())->method('getAllTables')->will($this->returnValue(array('articles', 'bake_odd')));
  195. $this->Task->expects($this->any())->method('in')
  196. ->will($this->onConsecutiveCalls(
  197. 2 // bake_odd
  198. ));
  199. $result = $this->Task->getName();
  200. $expected = 'BakeOdd';
  201. $this->assertEquals($expected, $result);
  202. $result = $this->Task->getTable($result);
  203. $expected = 'bake_odd';
  204. $this->assertEquals($expected, $result);
  205. }
  206. /**
  207. * test getTable with non-conventional tablenames
  208. *
  209. * @return void
  210. */
  211. public function testGetTableOddTable() {
  212. $out = $this->getMock('ConsoleOutput', array(), array(), '', false);
  213. $in = $this->getMock('ConsoleInput', array(), array(), '', false);
  214. $this->Task = $this->getMock('ModelTask',
  215. array('in', 'err', '_stop', '_checkUnitTest', 'getAllTables'),
  216. array($out, $out, $in)
  217. );
  218. $this->_setupOtherMocks();
  219. $this->Task->connection = 'test';
  220. $this->Task->path = '/my/path/';
  221. $this->Task->interactive = false;
  222. $this->Task->args = array('BakeOdd');
  223. $this->Task->expects($this->once())->method('getAllTables')->will($this->returnValue(array('articles', 'bake_odd')));
  224. $this->Task->listAll();
  225. $result = $this->Task->getTable('BakeOdd');
  226. $expected = 'bake_odd';
  227. $this->assertEquals($expected, $result);
  228. }
  229. /**
  230. * test that initializing the validations works.
  231. *
  232. * @return void
  233. */
  234. public function testInitValidations() {
  235. $result = $this->Task->initValidations();
  236. $this->assertTrue(in_array('notEmpty', $result));
  237. }
  238. /**
  239. * test that individual field validation works, with interactive = false
  240. * tests the guessing features of validation
  241. *
  242. * @return void
  243. */
  244. public function testFieldValidationGuessing() {
  245. $this->Task->interactive = false;
  246. $this->Task->initValidations();
  247. $result = $this->Task->fieldValidation('text', array('type' => 'string', 'length' => 10, 'null' => false));
  248. $expected = array('notEmpty' => 'notEmpty');
  249. $this->assertEquals($expected, $result);
  250. $result = $this->Task->fieldValidation('text', array('type' => 'date', 'length' => 10, 'null' => false));
  251. $expected = array('date' => 'date');
  252. $this->assertEquals($expected, $result);
  253. $result = $this->Task->fieldValidation('text', array('type' => 'time', 'length' => 10, 'null' => false));
  254. $expected = array('time' => 'time');
  255. $this->assertEquals($expected, $result);
  256. $result = $this->Task->fieldValidation('email', array('type' => 'string', 'length' => 10, 'null' => false));
  257. $expected = array('email' => 'email');
  258. $this->assertEquals($expected, $result);
  259. $result = $this->Task->fieldValidation('test', array('type' => 'integer', 'length' => 10, 'null' => false));
  260. $expected = array('numeric' => 'numeric');
  261. $this->assertEquals($expected, $result);
  262. $result = $this->Task->fieldValidation('test', array('type' => 'boolean', 'length' => 10, 'null' => false));
  263. $expected = array('boolean' => 'boolean');
  264. $this->assertEquals($expected, $result);
  265. }
  266. /**
  267. * test that interactive field validation works and returns multiple validators.
  268. *
  269. * @return void
  270. */
  271. public function testInteractiveFieldValidation() {
  272. $this->Task->initValidations();
  273. $this->Task->interactive = true;
  274. $this->Task->expects($this->any())->method('in')
  275. ->will($this->onConsecutiveCalls('24', 'y', '18', 'n'));
  276. $result = $this->Task->fieldValidation('text', array('type' => 'string', 'length' => 10, 'null' => false));
  277. $expected = array('notEmpty' => 'notEmpty', 'maxLength' => 'maxLength');
  278. $this->assertEquals($expected, $result);
  279. }
  280. /**
  281. * test that a bogus response doesn't cause errors to bubble up.
  282. *
  283. * @return void
  284. */
  285. public function testInteractiveFieldValidationWithBogusResponse() {
  286. $this->_useMockedOut();
  287. $this->Task->initValidations();
  288. $this->Task->interactive = true;
  289. $this->Task->expects($this->any())->method('in')
  290. ->will($this->onConsecutiveCalls('999999', '24', 'n'));
  291. $this->Task->expects($this->at(10))->method('out')
  292. ->with($this->stringContains('make a valid'));
  293. $result = $this->Task->fieldValidation('text', array('type' => 'string', 'length' => 10, 'null' => false));
  294. $expected = array('notEmpty' => 'notEmpty');
  295. $this->assertEquals($expected, $result);
  296. }
  297. /**
  298. * test that a regular expression can be used for validation.
  299. *
  300. * @return void
  301. */
  302. public function testInteractiveFieldValidationWithRegexp() {
  303. $this->Task->initValidations();
  304. $this->Task->interactive = true;
  305. $this->Task->expects($this->any())->method('in')
  306. ->will($this->onConsecutiveCalls('/^[a-z]{0,9}$/', 'n'));
  307. $result = $this->Task->fieldValidation('text', array('type' => 'string', 'length' => 10, 'null' => false));
  308. $expected = array('a_z_0_9' => '/^[a-z]{0,9}$/');
  309. $this->assertEquals($expected, $result);
  310. }
  311. /**
  312. * test the validation Generation routine
  313. *
  314. * @return void
  315. */
  316. public function testNonInteractiveDoValidation() {
  317. $Model = $this->getMock('Model');
  318. $Model->primaryKey = 'id';
  319. $Model->expects($this->any())->method('schema')->will($this->returnValue(array(
  320. 'id' => array(
  321. 'type' => 'integer',
  322. 'length' => 11,
  323. 'null' => false,
  324. 'key' => 'primary',
  325. ),
  326. 'name' => array(
  327. 'type' => 'string',
  328. 'length' => 20,
  329. 'null' => false,
  330. ),
  331. 'email' => array(
  332. 'type' => 'string',
  333. 'length' => 255,
  334. 'null' => false,
  335. ),
  336. 'some_date' => array(
  337. 'type' => 'date',
  338. 'length' => '',
  339. 'null' => false,
  340. ),
  341. 'some_time' => array(
  342. 'type' => 'time',
  343. 'length' => '',
  344. 'null' => false,
  345. ),
  346. 'created' => array(
  347. 'type' => 'datetime',
  348. 'length' => '',
  349. 'null' => false,
  350. )
  351. )));
  352. $this->Task->interactive = false;
  353. $result = $this->Task->doValidation($Model);
  354. $expected = array(
  355. 'name' => array(
  356. 'notEmpty' => 'notEmpty'
  357. ),
  358. 'email' => array(
  359. 'email' => 'email',
  360. ),
  361. 'some_date' => array(
  362. 'date' => 'date'
  363. ),
  364. 'some_time' => array(
  365. 'time' => 'time'
  366. ),
  367. );
  368. $this->assertEquals($expected, $result);
  369. }
  370. /**
  371. * test that finding primary key works
  372. *
  373. * @return void
  374. */
  375. public function testFindPrimaryKey() {
  376. $fields = array(
  377. 'one' => array(),
  378. 'two' => array(),
  379. 'key' => array('key' => 'primary')
  380. );
  381. $anything = new PHPUnit_Framework_Constraint_IsAnything();
  382. $this->Task->expects($this->once())->method('in')
  383. ->with($anything, null, 'key')
  384. ->will($this->returnValue('my_field'));
  385. $result = $this->Task->findPrimaryKey($fields);
  386. $expected = 'my_field';
  387. $this->assertEquals($expected, $result);
  388. }
  389. /**
  390. * test finding Display field
  391. *
  392. * @return void
  393. */
  394. public function testFindDisplayFieldNone() {
  395. $fields = array(
  396. 'id' => array(), 'tagname' => array(), 'body' => array(),
  397. 'created' => array(), 'modified' => array()
  398. );
  399. $this->Task->expects($this->at(0))->method('in')->will($this->returnValue('n'));
  400. $result = $this->Task->findDisplayField($fields);
  401. $this->assertFalse($result);
  402. }
  403. /**
  404. * Test finding a displayname from user input
  405. *
  406. * @return void
  407. */
  408. public function testFindDisplayName() {
  409. $fields = array(
  410. 'id' => array(), 'tagname' => array(), 'body' => array(),
  411. 'created' => array(), 'modified' => array()
  412. );
  413. $this->Task->expects($this->any())->method('in')
  414. ->will($this->onConsecutiveCalls('y', 2));
  415. $result = $this->Task->findDisplayField($fields);
  416. $this->assertEquals('tagname', $result);
  417. }
  418. /**
  419. * test that belongsTo generation works.
  420. *
  421. * @return void
  422. */
  423. public function testBelongsToGeneration() {
  424. $model = new Model(array('ds' => 'test', 'name' => 'BakeComment'));
  425. $result = $this->Task->findBelongsTo($model, array());
  426. $expected = array(
  427. 'belongsTo' => array(
  428. array(
  429. 'alias' => 'BakeArticle',
  430. 'className' => 'BakeArticle',
  431. 'foreignKey' => 'bake_article_id',
  432. ),
  433. array(
  434. 'alias' => 'BakeUser',
  435. 'className' => 'BakeUser',
  436. 'foreignKey' => 'bake_user_id',
  437. ),
  438. )
  439. );
  440. $this->assertEquals($expected, $result);
  441. $model = new Model(array('ds' => 'test', 'name' => 'CategoryThread'));
  442. $result = $this->Task->findBelongsTo($model, array());
  443. $expected = array(
  444. 'belongsTo' => array(
  445. array(
  446. 'alias' => 'ParentCategoryThread',
  447. 'className' => 'CategoryThread',
  448. 'foreignKey' => 'parent_id',
  449. ),
  450. )
  451. );
  452. $this->assertEquals($expected, $result);
  453. }
  454. /**
  455. * test that hasOne and/or hasMany relations are generated properly.
  456. *
  457. * @return void
  458. */
  459. public function testHasManyHasOneGeneration() {
  460. $model = new Model(array('ds' => 'test', 'name' => 'BakeArticle'));
  461. $this->Task->connection = 'test';
  462. $this->Task->listAll();
  463. $result = $this->Task->findHasOneAndMany($model, array());
  464. $expected = array(
  465. 'hasMany' => array(
  466. array(
  467. 'alias' => 'BakeComment',
  468. 'className' => 'BakeComment',
  469. 'foreignKey' => 'bake_article_id',
  470. ),
  471. ),
  472. 'hasOne' => array(
  473. array(
  474. 'alias' => 'BakeComment',
  475. 'className' => 'BakeComment',
  476. 'foreignKey' => 'bake_article_id',
  477. ),
  478. ),
  479. );
  480. $this->assertEquals($expected, $result);
  481. $model = new Model(array('ds' => 'test', 'name' => 'CategoryThread'));
  482. $result = $this->Task->findHasOneAndMany($model, array());
  483. $expected = array(
  484. 'hasOne' => array(
  485. array(
  486. 'alias' => 'ChildCategoryThread',
  487. 'className' => 'CategoryThread',
  488. 'foreignKey' => 'parent_id',
  489. ),
  490. ),
  491. 'hasMany' => array(
  492. array(
  493. 'alias' => 'ChildCategoryThread',
  494. 'className' => 'CategoryThread',
  495. 'foreignKey' => 'parent_id',
  496. ),
  497. )
  498. );
  499. $this->assertEquals($expected, $result);
  500. }
  501. /**
  502. * Test that HABTM generation works
  503. *
  504. * @return void
  505. */
  506. public function testHasAndBelongsToManyGeneration() {
  507. $model = new Model(array('ds' => 'test', 'name' => 'BakeArticle'));
  508. $this->Task->connection = 'test';
  509. $this->Task->listAll();
  510. $result = $this->Task->findHasAndBelongsToMany($model, array());
  511. $expected = array(
  512. 'hasAndBelongsToMany' => array(
  513. array(
  514. 'alias' => 'BakeTag',
  515. 'className' => 'BakeTag',
  516. 'foreignKey' => 'bake_article_id',
  517. 'joinTable' => 'bake_articles_bake_tags',
  518. 'associationForeignKey' => 'bake_tag_id',
  519. ),
  520. ),
  521. );
  522. $this->assertEquals($expected, $result);
  523. }
  524. /**
  525. * test non interactive doAssociations
  526. *
  527. * @return void
  528. */
  529. public function testDoAssociationsNonInteractive() {
  530. $this->Task->connection = 'test';
  531. $this->Task->interactive = false;
  532. $model = new Model(array('ds' => 'test', 'name' => 'BakeArticle'));
  533. $result = $this->Task->doAssociations($model);
  534. $expected = array(
  535. 'belongsTo' => array(
  536. array(
  537. 'alias' => 'BakeUser',
  538. 'className' => 'BakeUser',
  539. 'foreignKey' => 'bake_user_id',
  540. ),
  541. ),
  542. 'hasMany' => array(
  543. array(
  544. 'alias' => 'BakeComment',
  545. 'className' => 'BakeComment',
  546. 'foreignKey' => 'bake_article_id',
  547. ),
  548. ),
  549. 'hasAndBelongsToMany' => array(
  550. array(
  551. 'alias' => 'BakeTag',
  552. 'className' => 'BakeTag',
  553. 'foreignKey' => 'bake_article_id',
  554. 'joinTable' => 'bake_articles_bake_tags',
  555. 'associationForeignKey' => 'bake_tag_id',
  556. ),
  557. ),
  558. );
  559. $this->assertEquals($expected, $result);
  560. }
  561. /**
  562. * test non interactive doActsAs
  563. *
  564. * @return void
  565. */
  566. public function testDoActsAs() {
  567. $this->Task->connection = 'test';
  568. $this->Task->interactive = false;
  569. $model = new Model(array('ds' => 'test', 'name' => 'NumberTree'));
  570. $result = $this->Task->doActsAs($model);
  571. $this->assertEquals(array('Tree'), $result);
  572. }
  573. /**
  574. * Ensure that the fixture object is correctly called.
  575. *
  576. * @return void
  577. */
  578. public function testBakeFixture() {
  579. $this->Task->plugin = 'TestPlugin';
  580. $this->Task->interactive = true;
  581. $this->Task->Fixture->expects($this->at(0))->method('bake')->with('BakeArticle', 'bake_articles');
  582. $this->Task->bakeFixture('BakeArticle', 'bake_articles');
  583. $this->assertEquals($this->Task->plugin, $this->Task->Fixture->plugin);
  584. $this->assertEquals($this->Task->connection, $this->Task->Fixture->connection);
  585. $this->assertEquals($this->Task->interactive, $this->Task->Fixture->interactive);
  586. }
  587. /**
  588. * Ensure that the test object is correctly called.
  589. *
  590. * @return void
  591. */
  592. public function testBakeTest() {
  593. $this->Task->plugin = 'TestPlugin';
  594. $this->Task->interactive = true;
  595. $this->Task->Test->expects($this->at(0))->method('bake')->with('Model', 'BakeArticle');
  596. $this->Task->bakeTest('BakeArticle');
  597. $this->assertEquals($this->Task->plugin, $this->Task->Test->plugin);
  598. $this->assertEquals($this->Task->connection, $this->Task->Test->connection);
  599. $this->assertEquals($this->Task->interactive, $this->Task->Test->interactive);
  600. }
  601. /**
  602. * test confirming of associations, and that when an association is hasMany
  603. * a question for the hasOne is also not asked.
  604. *
  605. * @return void
  606. */
  607. public function testConfirmAssociations() {
  608. $associations = array(
  609. 'hasOne' => array(
  610. array(
  611. 'alias' => 'ChildCategoryThread',
  612. 'className' => 'CategoryThread',
  613. 'foreignKey' => 'parent_id',
  614. ),
  615. ),
  616. 'hasMany' => array(
  617. array(
  618. 'alias' => 'ChildCategoryThread',
  619. 'className' => 'CategoryThread',
  620. 'foreignKey' => 'parent_id',
  621. ),
  622. ),
  623. 'belongsTo' => array(
  624. array(
  625. 'alias' => 'User',
  626. 'className' => 'User',
  627. 'foreignKey' => 'user_id',
  628. ),
  629. )
  630. );
  631. $model = new Model(array('ds' => 'test', 'name' => 'CategoryThread'));
  632. $this->Task->expects($this->any())->method('in')
  633. ->will($this->onConsecutiveCalls('n', 'y', 'n', 'n', 'n'));
  634. $result = $this->Task->confirmAssociations($model, $associations);
  635. $this->assertTrue(empty($result['hasOne']));
  636. $result = $this->Task->confirmAssociations($model, $associations);
  637. $this->assertTrue(empty($result['hasMany']));
  638. $this->assertTrue(empty($result['hasOne']));
  639. }
  640. /**
  641. * test that inOptions generates questions and only accepts a valid answer
  642. *
  643. * @return void
  644. */
  645. public function testInOptions() {
  646. $this->_useMockedOut();
  647. $options = array('one', 'two', 'three');
  648. $this->Task->expects($this->at(0))->method('out')->with('1. one');
  649. $this->Task->expects($this->at(1))->method('out')->with('2. two');
  650. $this->Task->expects($this->at(2))->method('out')->with('3. three');
  651. $this->Task->expects($this->at(3))->method('in')->will($this->returnValue(10));
  652. $this->Task->expects($this->at(4))->method('out')->with('1. one');
  653. $this->Task->expects($this->at(5))->method('out')->with('2. two');
  654. $this->Task->expects($this->at(6))->method('out')->with('3. three');
  655. $this->Task->expects($this->at(7))->method('in')->will($this->returnValue(2));
  656. $result = $this->Task->inOptions($options, 'Pick a number');
  657. $this->assertEquals(1, $result);
  658. }
  659. /**
  660. * test baking validation
  661. *
  662. * @return void
  663. */
  664. public function testBakeValidation() {
  665. $validate = array(
  666. 'name' => array(
  667. 'notempty' => 'notEmpty'
  668. ),
  669. 'email' => array(
  670. 'email' => 'email',
  671. ),
  672. 'some_date' => array(
  673. 'date' => 'date'
  674. ),
  675. 'some_time' => array(
  676. 'time' => 'time'
  677. )
  678. );
  679. $result = $this->Task->bake('BakeArticle', compact('validate'));
  680. $this->assertRegExp('/class BakeArticle extends AppModel \{/', $result);
  681. $this->assertRegExp('/\$validate \= array\(/', $result);
  682. $expected = <<< STRINGEND
  683. array(
  684. 'notempty' => array(
  685. 'rule' => array('notEmpty'),
  686. //'message' => 'Your custom message here',
  687. //'allowEmpty' => false,
  688. //'required' => false,
  689. //'last' => false, // Stop validation after this rule
  690. //'on' => 'create', // Limit validation to 'create' or 'update' operations
  691. ),
  692. STRINGEND;
  693. $this->assertRegExp('/' . preg_quote(str_replace("\r\n", "\n", $expected), '/') . '/', $result);
  694. }
  695. /**
  696. * test baking relations
  697. *
  698. * @return void
  699. */
  700. public function testBakeRelations() {
  701. $associations = array(
  702. 'belongsTo' => array(
  703. array(
  704. 'alias' => 'SomethingElse',
  705. 'className' => 'SomethingElse',
  706. 'foreignKey' => 'something_else_id',
  707. ),
  708. array(
  709. 'alias' => 'BakeUser',
  710. 'className' => 'BakeUser',
  711. 'foreignKey' => 'bake_user_id',
  712. ),
  713. ),
  714. 'hasOne' => array(
  715. array(
  716. 'alias' => 'OtherModel',
  717. 'className' => 'OtherModel',
  718. 'foreignKey' => 'other_model_id',
  719. ),
  720. ),
  721. 'hasMany' => array(
  722. array(
  723. 'alias' => 'BakeComment',
  724. 'className' => 'BakeComment',
  725. 'foreignKey' => 'parent_id',
  726. ),
  727. ),
  728. 'hasAndBelongsToMany' => array(
  729. array(
  730. 'alias' => 'BakeTag',
  731. 'className' => 'BakeTag',
  732. 'foreignKey' => 'bake_article_id',
  733. 'joinTable' => 'bake_articles_bake_tags',
  734. 'associationForeignKey' => 'bake_tag_id',
  735. ),
  736. )
  737. );
  738. $result = $this->Task->bake('BakeArticle', compact('associations'));
  739. $this->assertContains(' * @property BakeUser $BakeUser', $result);
  740. $this->assertContains(' * @property OtherModel $OtherModel', $result);
  741. $this->assertContains(' * @property BakeComment $BakeComment', $result);
  742. $this->assertContains(' * @property BakeTag $BakeTag', $result);
  743. $this->assertRegExp('/\$hasAndBelongsToMany \= array\(/', $result);
  744. $this->assertRegExp('/\$hasMany \= array\(/', $result);
  745. $this->assertRegExp('/\$belongsTo \= array\(/', $result);
  746. $this->assertRegExp('/\$hasOne \= array\(/', $result);
  747. $this->assertRegExp('/BakeTag/', $result);
  748. $this->assertRegExp('/OtherModel/', $result);
  749. $this->assertRegExp('/SomethingElse/', $result);
  750. $this->assertRegExp('/BakeComment/', $result);
  751. }
  752. /**
  753. * test bake() with a -plugin param
  754. *
  755. * @return void
  756. */
  757. public function testBakeWithPlugin() {
  758. $this->Task->plugin = 'ControllerTest';
  759. //fake plugin path
  760. CakePlugin::load('ControllerTest', array('path' => APP . 'Plugin' . DS . 'ControllerTest' . DS));
  761. $path = APP . 'Plugin' . DS . 'ControllerTest' . DS . 'Model' . DS . 'BakeArticle.php';
  762. $this->Task->expects($this->once())->method('createFile')
  763. ->with($path, $this->stringContains('BakeArticle extends ControllerTestAppModel'));
  764. $result = $this->Task->bake('BakeArticle', array(), array());
  765. $this->assertContains("App::uses('ControllerTestAppModel', 'ControllerTest.Model');", $result);
  766. $this->assertEquals(count(ClassRegistry::keys()), 0);
  767. $this->assertEquals(count(ClassRegistry::mapKeys()), 0);
  768. }
  769. /**
  770. * test bake() for models with behaviors
  771. *
  772. * @return void
  773. */
  774. public function testBakeWithBehaviors() {
  775. $result = $this->Task->bake('NumberTree', array('actsAs' => array('Tree', 'PluginName.Sluggable')));
  776. $expected = <<<TEXT
  777. /**
  778. * Behaviors
  779. *
  780. * @var array
  781. */
  782. public \$actsAs = array(
  783. 'Tree',
  784. 'PluginName.Sluggable',
  785. );
  786. TEXT;
  787. $this->assertTextContains($expected, $result);
  788. }
  789. /**
  790. * test that execute passes runs bake depending with named model.
  791. *
  792. * @return void
  793. */
  794. public function testExecuteWithNamedModel() {
  795. $this->Task->connection = 'test';
  796. $this->Task->path = '/my/path/';
  797. $this->Task->args = array('BakeArticle');
  798. $filename = '/my/path/BakeArticle.php';
  799. $this->Task->expects($this->once())->method('_checkUnitTest')->will($this->returnValue(1));
  800. $this->Task->expects($this->once())->method('createFile')
  801. ->with($filename, $this->stringContains('class BakeArticle extends AppModel'));
  802. $this->Task->execute();
  803. $this->assertEquals(count(ClassRegistry::keys()), 0);
  804. $this->assertEquals(count(ClassRegistry::mapKeys()), 0);
  805. }
  806. /**
  807. * data provider for testExecuteWithNamedModelVariations
  808. *
  809. * @return void
  810. */
  811. public static function nameVariations() {
  812. return array(
  813. array('BakeArticles'), array('BakeArticle'), array('bake_article'), array('bake_articles')
  814. );
  815. }
  816. /**
  817. * test that execute passes with different inflections of the same name.
  818. *
  819. * @dataProvider nameVariations
  820. * @return void
  821. */
  822. public function testExecuteWithNamedModelVariations($name) {
  823. $this->Task->connection = 'test';
  824. $this->Task->path = '/my/path/';
  825. $this->Task->expects($this->once())->method('_checkUnitTest')->will($this->returnValue(1));
  826. $this->Task->args = array($name);
  827. $filename = '/my/path/BakeArticle.php';
  828. $this->Task->expects($this->at(0))->method('createFile')
  829. ->with($filename, $this->stringContains('class BakeArticle extends AppModel'));
  830. $this->Task->execute();
  831. }
  832. /**
  833. * test that execute with a model name picks up hasMany associations.
  834. *
  835. * @return void
  836. */
  837. public function testExecuteWithNamedModelHasManyCreated() {
  838. $this->Task->connection = 'test';
  839. $this->Task->path = '/my/path/';
  840. $this->Task->args = array('BakeArticle');
  841. $filename = '/my/path/BakeArticle.php';
  842. $this->Task->expects($this->once())->method('_checkUnitTest')->will($this->returnValue(1));
  843. $this->Task->expects($this->at(0))->method('createFile')
  844. ->with($filename, $this->stringContains("'BakeComment' => array("));
  845. $this->Task->execute();
  846. }
  847. /**
  848. * test that execute runs all() when args[0] = all
  849. *
  850. * @return void
  851. */
  852. public function testExecuteIntoAll() {
  853. $count = count($this->Task->listAll('test'));
  854. if ($count != count($this->fixtures)) {
  855. $this->markTestSkipped('Additional tables detected.');
  856. }
  857. $this->Task->connection = 'test';
  858. $this->Task->path = '/my/path/';
  859. $this->Task->args = array('all');
  860. $this->Task->expects($this->once())->method('_checkUnitTest')->will($this->returnValue(true));
  861. $this->Task->Fixture->expects($this->exactly(5))->method('bake');
  862. $this->Task->Test->expects($this->exactly(5))->method('bake');
  863. $filename = '/my/path/BakeArticle.php';
  864. $this->Task->expects($this->at(1))->method('createFile')
  865. ->with($filename, $this->stringContains('class BakeArticle'));
  866. $filename = '/my/path/BakeArticlesBakeTag.php';
  867. $this->Task->expects($this->at(2))->method('createFile')
  868. ->with($filename, $this->stringContains('class BakeArticlesBakeTag'));
  869. $filename = '/my/path/BakeComment.php';
  870. $this->Task->expects($this->at(3))->method('createFile')
  871. ->with($filename, $this->stringContains('class BakeComment'));
  872. $filename = '/my/path/BakeComment.php';
  873. $this->Task->expects($this->at(3))->method('createFile')
  874. ->with($filename, $this->stringContains('public $primaryKey = \'otherid\';'));
  875. $filename = '/my/path/BakeTag.php';
  876. $this->Task->expects($this->at(4))->method('createFile')
  877. ->with($filename, $this->stringContains('class BakeTag'));
  878. $filename = '/my/path/BakeTag.php';
  879. $this->Task->expects($this->at(4))->method('createFile')
  880. ->with($filename, $this->logicalNot($this->stringContains('public $primaryKey')));
  881. $filename = '/my/path/CategoryThread.php';
  882. $this->Task->expects($this->at(5))->method('createFile')
  883. ->with($filename, $this->stringContains('class CategoryThread'));
  884. $this->Task->execute();
  885. $this->assertEquals(count(ClassRegistry::keys()), 0);
  886. $this->assertEquals(count(ClassRegistry::mapKeys()), 0);
  887. }
  888. /**
  889. * test that odd tablenames aren't inflected back from modelname
  890. *
  891. * @return void
  892. */
  893. public function testExecuteIntoAllOddTables() {
  894. $out = $this->getMock('ConsoleOutput', array(), array(), '', false);
  895. $in = $this->getMock('ConsoleInput', array(), array(), '', false);
  896. $this->Task = $this->getMock('ModelTask',
  897. array('in', 'err', '_stop', '_checkUnitTest', 'getAllTables', '_getModelObject', 'bake', 'bakeFixture'),
  898. array($out, $out, $in)
  899. );
  900. $this->_setupOtherMocks();
  901. $this->Task->connection = 'test';
  902. $this->Task->path = '/my/path/';
  903. $this->Task->args = array('all');
  904. $this->Task->expects($this->once())->method('_checkUnitTest')->will($this->returnValue(true));
  905. $this->Task->expects($this->once())->method('getAllTables')->will($this->returnValue(array('bake_odd')));
  906. $object = new Model(array('name' => 'BakeOdd', 'table' => 'bake_odd', 'ds' => 'test'));
  907. $this->Task->expects($this->once())->method('_getModelObject')->with('BakeOdd', 'bake_odd')->will($this->returnValue($object));
  908. $this->Task->expects($this->at(3))->method('bake')->with($object, false)->will($this->returnValue(true));
  909. $this->Task->expects($this->once())->method('bakeFixture')->with('BakeOdd', 'bake_odd');
  910. $this->Task->execute();
  911. $out = $this->getMock('ConsoleOutput', array(), array(), '', false);
  912. $in = $this->getMock('ConsoleInput', array(), array(), '', false);
  913. $this->Task = $this->getMock('ModelTask',
  914. array('in', 'err', '_stop', '_checkUnitTest', 'getAllTables', '_getModelObject', 'doAssociations', 'doValidation', 'doActsAs', 'createFile'),
  915. array($out, $out, $in)
  916. );
  917. $this->_setupOtherMocks();
  918. $this->Task->connection = 'test';
  919. $this->Task->path = '/my/path/';
  920. $this->Task->args = array('all');
  921. $this->Task->expects($this->once())->method('_checkUnitTest')->will($this->returnValue(true));
  922. $this->Task->expects($this->once())->method('getAllTables')->will($this->returnValue(array('bake_odd')));
  923. $object = new Model(array('name' => 'BakeOdd', 'table' => 'bake_odd', 'ds' => 'test'));
  924. $this->Task->expects($this->once())->method('_getModelObject')->will($this->returnValue($object));
  925. $this->Task->expects($this->once())->method('doAssociations')->will($this->returnValue(array()));
  926. $this->Task->expects($this->once())->method('doValidation')->will($this->returnValue(array()));
  927. $this->Task->expects($this->once())->method('doActsAs')->will($this->returnValue(array()));
  928. $filename = '/my/path/BakeOdd.php';
  929. $this->Task->expects($this->once())->method('createFile')
  930. ->with($filename, $this->stringContains('class BakeOdd'));
  931. $filename = '/my/path/BakeOdd.php';
  932. $this->Task->expects($this->once())->method('createFile')
  933. ->with($filename, $this->stringContains('public $useTable = \'bake_odd\''));
  934. $this->Task->execute();
  935. }
  936. /**
  937. * test that odd tablenames aren't inflected back from modelname
  938. *
  939. * @return void
  940. */
  941. public function testExecuteIntoBakeOddTables() {
  942. $out = $this->getMock('ConsoleOutput', array(), array(), '', false);
  943. $in = $this->getMock('ConsoleInput', array(), array(), '', false);
  944. $this->Task = $this->getMock('ModelTask',
  945. array('in', 'err', '_stop', '_checkUnitTest', 'getAllTables', '_getModelObject', 'bake', 'bakeFixture'),
  946. array($out, $out, $in)
  947. );
  948. $this->_setupOtherMocks();
  949. $this->Task->connection = 'test';
  950. $this->Task->path = '/my/path/';
  951. $this->Task->args = array('BakeOdd');
  952. $this->Task->expects($this->once())->method('_checkUnitTest')->will($this->returnValue(true));
  953. $this->Task->expects($this->once())->method('getAllTables')->will($this->returnValue(array('articles', 'bake_odd')));
  954. $object = new Model(array('name' => 'BakeOdd', 'table' => 'bake_odd', 'ds' => 'test'));
  955. $this->Task->expects($this->once())->method('_getModelObject')->with('BakeOdd', 'bake_odd')->will($this->returnValue($object));
  956. $this->Task->expects($this->once())->method('bake')->with($object, false)->will($this->returnValue(true));
  957. $this->Task->expects($this->once())->method('bakeFixture')->with('BakeOdd', 'bake_odd');
  958. $this->Task->execute();
  959. $out = $this->getMock('ConsoleOutput', array(), array(), '', false);
  960. $in = $this->getMock('ConsoleInput', array(), array(), '', false);
  961. $this->Task = $this->getMock('ModelTask',
  962. array('in', 'err', '_stop', '_checkUnitTest', 'getAllTables', '_getModelObject', 'doAssociations', 'doValidation', 'doActsAs', 'createFile'),
  963. array($out, $out, $in)
  964. );
  965. $this->_setupOtherMocks();
  966. $this->Task->connection = 'test';
  967. $this->Task->path = '/my/path/';
  968. $this->Task->args = array('BakeOdd');
  969. $this->Task->expects($this->once())->method('_checkUnitTest')->will($this->returnValue(true));
  970. $this->Task->expects($this->once())->method('getAllTables')->will($this->returnValue(array('articles', 'bake_odd')));
  971. $object = new Model(array('name' => 'BakeOdd', 'table' => 'bake_odd', 'ds' => 'test'));
  972. $this->Task->expects($this->once())->method('_getModelObject')->will($this->returnValue($object));
  973. $this->Task->expects($this->once())->method('doAssociations')->will($this->returnValue(array()));
  974. $this->Task->expects($this->once())->method('doValidation')->will($this->returnValue(array()));
  975. $this->Task->expects($this->once())->method('doActsAs')->will($this->returnValue(array()));
  976. $filename = '/my/path/BakeOdd.php';
  977. $this->Task->expects($this->once())->method('createFile')
  978. ->with($filename, $this->stringContains('class BakeOdd'));
  979. $filename = '/my/path/BakeOdd.php';
  980. $this->Task->expects($this->once())->method('createFile')
  981. ->with($filename, $this->stringContains('public $useTable = \'bake_odd\''));
  982. $this->Task->execute();
  983. }
  984. /**
  985. * test that skipTables changes how all() works.
  986. *
  987. * @return void
  988. */
  989. public function testSkipTablesAndAll() {
  990. $count = count($this->Task->listAll('test'));
  991. if ($count != count($this->fixtures)) {
  992. $this->markTestSkipped('Additional tables detected.');
  993. }
  994. $this->Task->connection = 'test';
  995. $this->Task->path = '/my/path/';
  996. $this->Task->args = array('all');
  997. $this->Task->expects($this->once())->method('_checkUnitTest')->will($this->returnValue(true));
  998. $this->Task->skipTables = array('bake_tags');
  999. $this->Task->Fixture->expects($this->exactly(4))->method('bake');
  1000. $this->Task->Test->expects($this->exactly(4))->method('bake');
  1001. $filename = '/my/path/BakeArticle.php';
  1002. $this->Task->expects($this->at(1))->method('createFile')
  1003. ->with($filename, $this->stringContains('class BakeArticle'));
  1004. $filename = '/my/path/BakeArticlesBakeTag.php';
  1005. $this->Task->expects($this->at(2))->method('createFile')
  1006. ->with($filename, $this->stringContains('class BakeArticlesBakeTag'));
  1007. $filename = '/my/path/BakeComment.php';
  1008. $this->Task->expects($this->at(3))->method('createFile')
  1009. ->with($filename, $this->stringContains('class BakeComment'));
  1010. $filename = '/my/path/CategoryThread.php';
  1011. $this->Task->expects($this->at(4))->method('createFile')
  1012. ->with($filename, $this->stringContains('class CategoryThread'));
  1013. $this->Task->execute();
  1014. }
  1015. /**
  1016. * test the interactive side of bake.
  1017. *
  1018. * @return void
  1019. */
  1020. public function testExecuteIntoInteractive() {
  1021. $tables = $this->Task->listAll('test');
  1022. $article = array_search('bake_articles', $tables) + 1;
  1023. $this->Task->connection = 'test';
  1024. $this->Task->path = '/my/path/';
  1025. $this->Task->interactive = true;
  1026. $this->Task->expects($this->any())->method('in')
  1027. ->will($this->onConsecutiveCalls(
  1028. $article, // article
  1029. 'n', // no validation
  1030. 'y', // associations
  1031. 'y', // comment relation
  1032. 'y', // user relation
  1033. 'y', // tag relation
  1034. 'n', // additional assocs
  1035. 'y' // looks good?
  1036. ));
  1037. $this->Task->expects($this->once())->method('_checkUnitTest')->will($this->returnValue(true));
  1038. $this->Task->Test->expects($this->once())->method('bake');
  1039. $this->Task->Fixture->expects($this->once())->method('bake');
  1040. $filename = '/my/path/BakeArticle.php';
  1041. $this->Task->expects($this->once())->method('createFile')
  1042. ->with($filename, $this->stringContains('class BakeArticle'));
  1043. $this->Task->execute();
  1044. $this->assertEquals(count(ClassRegistry::keys()), 0);
  1045. $this->assertEquals(count(ClassRegistry::mapKeys()), 0);
  1046. }
  1047. /**
  1048. * test using bake interactively with a table that does not exist.
  1049. *
  1050. * @return void
  1051. */
  1052. public function testExecuteWithNonExistantTableName() {
  1053. $this->Task->connection = 'test';
  1054. $this->Task->path = '/my/path/';
  1055. $this->Task->expects($this->any())->method('in')
  1056. ->will($this->onConsecutiveCalls(
  1057. 'Foobar', // Or type in the name of the model
  1058. 'y', // Do you want to use this table
  1059. 'n' // Doesn't exist, continue anyway?
  1060. ));
  1061. $this->Task->execute();
  1062. }
  1063. /**
  1064. * test using bake interactively with a table that does not exist.
  1065. *
  1066. * @return void
  1067. */
  1068. public function testForcedExecuteWithNonExistantTableName() {
  1069. $this->Task->connection = 'test';
  1070. $this->Task->path = '/my/path/';
  1071. $this->Task->expects($this->any())->method('in')
  1072. ->will($this->onConsecutiveCalls(
  1073. 'Foobar', // Or type in the name of the model
  1074. 'y', // Do you want to use this table
  1075. 'y', // Doesn't exist, continue anyway?
  1076. 'id', // Primary key
  1077. 'y' // Looks good?
  1078. ));
  1079. $this->Task->execute();
  1080. }
  1081. }