ModelTaskTest.php 37 KB

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