Subversion Repositories SmartDukaan

Rev

Details | Last modification | View Log | RSS feed

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