Subversion Repositories SmartDukaan

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
15403 manish.sha 1
<?php
2
/**
3
 * ModelValidationTest file
4
 *
5
 * CakePHP(tm) Tests <http://book.cakephp.org/2.0/en/development/testing.html>
6
 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
7
 *
8
 * Licensed under The MIT License
9
 * For full copyright and license information, please see the LICENSE.txt
10
 * Redistributions of files must retain the above copyright notice
11
 *
12
 * @copyright     Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
13
 * @link          http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests
14
 * @package       Cake.Test.Case.Model
15
 * @since         CakePHP(tm) v 1.2.0.4206
16
 * @license       http://www.opensource.org/licenses/mit-license.php MIT License
17
 */
18
 
19
require_once dirname(__FILE__) . DS . 'ModelTestBase.php';
20
 
21
/**
22
 * ModelValidationTest
23
 *
24
 * @package       Cake.Test.Case.Model
25
 */
26
class ModelValidationTest extends BaseModelTest {
27
 
28
/**
29
 * override locale to the default (eng).
30
 *
31
 * @return void
32
 */
33
	public function setUp() {
34
		parent::setUp();
35
		Configure::write('Config.language', 'eng');
36
	}
37
 
38
/**
39
 * Tests validation parameter order in custom validation methods
40
 *
41
 * @return void
42
 */
43
	public function testValidationParams() {
44
		$TestModel = new ValidationTest1();
45
		$TestModel->validate['title'] = array(
46
			'rule' => 'customValidatorWithParams',
47
			'required' => true
48
		);
49
		$TestModel->create(array('title' => 'foo'));
50
		$TestModel->invalidFields();
51
 
52
		$expected = array(
53
			'data' => array(
54
				'title' => 'foo'
55
			),
56
			'validator' => array(
57
				'rule' => 'customValidatorWithParams',
58
				'on' => null,
59
				'last' => true,
60
				'allowEmpty' => false,
61
				'required' => true,
62
				'message' => null
63
			),
64
			'or' => true,
65
			'ignoreOnSame' => 'id'
66
		);
67
		$this->assertEquals($expected, $TestModel->validatorParams);
68
 
69
		$TestModel->validate['title'] = array(
70
			'rule' => 'customValidatorWithMessage',
71
			'required' => true
72
		);
73
		$expected = array(
74
			'title' => array('This field will *never* validate! Muhahaha!')
75
		);
76
 
77
		$this->assertEquals($expected, $TestModel->invalidFields());
78
 
79
		$TestModel->validate['title'] = array(
80
			'rule' => array('customValidatorWithSixParams', 'one', 'two', null, 'four'),
81
			'required' => true
82
		);
83
		$TestModel->create(array('title' => 'foo'));
84
		$TestModel->invalidFields();
85
		$expected = array(
86
			'data' => array(
87
				'title' => 'foo'
88
			),
89
			'one' => 'one',
90
			'two' => 'two',
91
			'three' => null,
92
			'four' => 'four',
93
			'five' => array(
94
				'rule' => array(1 => 'one', 2 => 'two', 3 => null, 4 => 'four'),
95
				'on' => null,
96
				'last' => true,
97
				'allowEmpty' => false,
98
				'required' => true,
99
				'message' => null
100
			),
101
			'six' => 6
102
		);
103
		$this->assertEquals($expected, $TestModel->validatorParams);
104
 
105
		$TestModel->validate['title'] = array(
106
			'rule' => array('customValidatorWithSixParams', 'one', array('two'), null, 'four', array('five' => 5)),
107
			'required' => true
108
		);
109
		$TestModel->create(array('title' => 'foo'));
110
		$TestModel->invalidFields();
111
		$expected = array(
112
			'data' => array(
113
				'title' => 'foo'
114
			),
115
			'one' => 'one',
116
			'two' => array('two'),
117
			'three' => null,
118
			'four' => 'four',
119
			'five' => array('five' => 5),
120
			'six' => array(
121
				'rule' => array(1 => 'one', 2 => array('two'), 3 => null, 4 => 'four', 5 => array('five' => 5)),
122
				'on' => null,
123
				'last' => true,
124
				'allowEmpty' => false,
125
				'required' => true,
126
				'message' => null
127
			)
128
		);
129
		$this->assertEquals($expected, $TestModel->validatorParams);
130
	}
131
 
132
/**
133
 * Tests validation parameter fieldList in invalidFields
134
 *
135
 * @return void
136
 */
137
	public function testInvalidFieldsWithFieldListParams() {
138
		$TestModel = new ValidationTest1();
139
		$TestModel->validate = $validate = array(
140
			'title' => array(
141
				'rule' => 'alphaNumeric',
142
				'required' => true
143
			),
144
			'name' => array(
145
				'rule' => 'alphaNumeric',
146
				'required' => true
147
		));
148
		$TestModel->set(array('title' => '$$', 'name' => '##'));
149
		$TestModel->invalidFields(array('fieldList' => array('title')));
150
		$expected = array(
151
			'title' => array('This field cannot be left blank')
152
		);
153
		$this->assertEquals($expected, $TestModel->validationErrors);
154
		$TestModel->validationErrors = array();
155
 
156
		$TestModel->invalidFields(array('fieldList' => array('name')));
157
		$expected = array(
158
			'name' => array('This field cannot be left blank')
159
		);
160
		$this->assertEquals($expected, $TestModel->validationErrors);
161
		$TestModel->validationErrors = array();
162
 
163
		$TestModel->invalidFields(array('fieldList' => array('name', 'title')));
164
		$expected = array(
165
			'name' => array('This field cannot be left blank'),
166
			'title' => array('This field cannot be left blank')
167
		);
168
		$this->assertEquals($expected, $TestModel->validationErrors);
169
		$TestModel->validationErrors = array();
170
 
171
		$TestModel->whitelist = array('name');
172
		$TestModel->invalidFields();
173
		$expected = array('name' => array('This field cannot be left blank'));
174
		$this->assertEquals($expected, $TestModel->validationErrors);
175
 
176
		$this->assertEquals($TestModel->validate, $validate);
177
	}
178
 
179
/**
180
 * Test that invalidFields() integrates well with save(). And that fieldList can be an empty type.
181
 *
182
 * @return void
183
 */
184
	public function testInvalidFieldsWhitelist() {
185
		$TestModel = new ValidationTest1();
186
		$TestModel->validate = array(
187
			'title' => array(
188
				'rule' => 'alphaNumeric',
189
				'required' => true
190
			),
191
			'name' => array(
192
				'rule' => 'alphaNumeric',
193
				'required' => true
194
		));
195
 
196
		$TestModel->whitelist = array('name');
197
		$TestModel->save(array('name' => '#$$#', 'title' => '$$$$'));
198
 
199
		$expected = array('name' => array('This field cannot be left blank'));
200
		$this->assertEquals($expected, $TestModel->validationErrors);
201
	}
202
 
203
/**
204
 * testValidates method
205
 *
206
 * @return void
207
 */
208
	public function testValidates() {
209
		$TestModel = new TestValidate();
210
 
211
		$TestModel->validate = array(
212
			'user_id' => 'numeric',
213
			'title' => array('allowEmpty' => false, 'rule' => 'notEmpty'),
214
			'body' => 'notEmpty'
215
		);
216
 
217
		$data = array('TestValidate' => array(
218
			'user_id' => '1',
219
			'title' => '',
220
			'body' => 'body'
221
		));
222
		$result = $TestModel->create($data);
223
		$this->assertEquals($data, $result);
224
		$result = $TestModel->validates();
225
		$this->assertFalse($result);
226
 
227
		$data = array('TestValidate' => array(
228
			'user_id' => '1',
229
			'title' => 'title',
230
			'body' => 'body'
231
		));
232
		$result = $TestModel->create($data) && $TestModel->validates();
233
		$this->assertTrue($result);
234
 
235
		$data = array('TestValidate' => array(
236
			'user_id' => '1',
237
			'title' => '0',
238
			'body' => 'body'
239
		));
240
		$result = $TestModel->create($data);
241
		$this->assertEquals($data, $result);
242
		$result = $TestModel->validates();
243
		$this->assertTrue($result);
244
 
245
		$data = array('TestValidate' => array(
246
			'user_id' => '1',
247
			'title' => 0,
248
			'body' => 'body'
249
		));
250
		$result = $TestModel->create($data);
251
		$this->assertEquals($data, $result);
252
		$result = $TestModel->validates();
253
		$this->assertTrue($result);
254
 
255
		$TestModel->validate['modified'] = array('allowEmpty' => true, 'rule' => 'date');
256
 
257
		$data = array('TestValidate' => array(
258
			'user_id' => '1',
259
			'title' => 0,
260
			'body' => 'body',
261
			'modified' => ''
262
		));
263
		$result = $TestModel->create($data);
264
		$this->assertEquals($data, $result);
265
		$result = $TestModel->validates();
266
		$this->assertTrue($result);
267
 
268
		$data = array('TestValidate' => array(
269
			'user_id' => '1',
270
			'title' => 0,
271
			'body' => 'body',
272
			'modified' => '2007-05-01'
273
		));
274
		$result = $TestModel->create($data);
275
		$this->assertEquals($data, $result);
276
		$result = $TestModel->validates();
277
		$this->assertTrue($result);
278
 
279
		$data = array('TestValidate' => array(
280
			'user_id' => '1',
281
			'title' => 0,
282
			'body' => 'body',
283
			'modified' => 'invalid-date-here'
284
		));
285
		$result = $TestModel->create($data);
286
		$this->assertEquals($data, $result);
287
		$result = $TestModel->validates();
288
		$this->assertFalse($result);
289
 
290
		$data = array('TestValidate' => array(
291
			'user_id' => '1',
292
			'title' => 0,
293
			'body' => 'body',
294
			'modified' => 0
295
		));
296
		$result = $TestModel->create($data);
297
		$this->assertEquals($data, $result);
298
		$result = $TestModel->validates();
299
		$this->assertFalse($result);
300
 
301
		$data = array('TestValidate' => array(
302
			'user_id' => '1',
303
			'title' => 0,
304
			'body' => 'body',
305
			'modified' => '0'
306
		));
307
		$result = $TestModel->create($data);
308
		$this->assertEquals($data, $result);
309
		$result = $TestModel->validates();
310
		$this->assertFalse($result);
311
 
312
		$TestModel->validate['modified'] = array('allowEmpty' => false, 'rule' => 'date');
313
 
314
		$data = array('TestValidate' => array('modified' => null));
315
		$result = $TestModel->create($data);
316
		$this->assertEquals($data, $result);
317
		$result = $TestModel->validates();
318
		$this->assertFalse($result);
319
 
320
		$data = array('TestValidate' => array('modified' => false));
321
		$result = $TestModel->create($data);
322
		$this->assertEquals($data, $result);
323
		$result = $TestModel->validates();
324
		$this->assertFalse($result);
325
 
326
		$data = array('TestValidate' => array('modified' => ''));
327
		$result = $TestModel->create($data);
328
		$this->assertEquals($data, $result);
329
		$result = $TestModel->validates();
330
		$this->assertFalse($result);
331
 
332
		$data = array('TestValidate' => array(
333
			'modified' => '2007-05-01'
334
		));
335
		$result = $TestModel->create($data);
336
		$this->assertEquals($data, $result);
337
		$result = $TestModel->validates();
338
		$this->assertTrue($result);
339
 
340
		$TestModel->validate['slug'] = array('allowEmpty' => false, 'rule' => array('maxLength', 45));
341
 
342
		$data = array('TestValidate' => array(
343
			'user_id' => '1',
344
			'title' => 0,
345
			'body' => 'body',
346
			'slug' => ''
347
		));
348
		$result = $TestModel->create($data);
349
		$this->assertEquals($data, $result);
350
		$result = $TestModel->validates();
351
		$this->assertFalse($result);
352
 
353
		$data = array('TestValidate' => array(
354
			'user_id' => '1',
355
			'title' => 0,
356
			'body' => 'body',
357
			'slug' => 'slug-right-here'
358
		));
359
		$result = $TestModel->create($data);
360
		$this->assertEquals($data, $result);
361
		$result = $TestModel->validates();
362
		$this->assertTrue($result);
363
 
364
		$data = array('TestValidate' => array(
365
			'user_id' => '1',
366
			'title' => 0,
367
			'body' => 'body',
368
			'slug' => 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz'
369
		));
370
		$result = $TestModel->create($data);
371
		$this->assertEquals($data, $result);
372
		$result = $TestModel->validates();
373
		$this->assertFalse($result);
374
 
375
		$TestModel->validate = array(
376
			'number' => array(
377
				'rule' => 'validateNumber',
378
				'min' => 3,
379
				'max' => 5
380
			),
381
			'title' => array(
382
				'allowEmpty' => false,
383
				'rule' => 'notEmpty'
384
		));
385
 
386
		$data = array('TestValidate' => array(
387
			'title' => 'title',
388
			'number' => '0'
389
		));
390
		$result = $TestModel->create($data);
391
		$this->assertEquals($data, $result);
392
		$result = $TestModel->validates();
393
		$this->assertFalse($result);
394
 
395
		$data = array('TestValidate' => array(
396
			'title' => 'title',
397
			'number' => 0
398
		));
399
		$result = $TestModel->create($data);
400
		$this->assertEquals($data, $result);
401
		$result = $TestModel->validates();
402
		$this->assertFalse($result);
403
 
404
		$data = array('TestValidate' => array(
405
			'title' => 'title',
406
			'number' => '3'
407
		));
408
		$result = $TestModel->create($data);
409
		$this->assertEquals($data, $result);
410
		$result = $TestModel->validates();
411
		$this->assertTrue($result);
412
 
413
		$data = array('TestValidate' => array(
414
			'title' => 'title',
415
			'number' => 3
416
		));
417
		$result = $TestModel->create($data);
418
		$this->assertEquals($data, $result);
419
		$result = $TestModel->validates();
420
		$this->assertTrue($result);
421
 
422
		$TestModel->validate = array(
423
			'number' => array(
424
				'rule' => 'validateNumber',
425
				'min' => 5,
426
				'max' => 10
427
			),
428
			'title' => array(
429
				'allowEmpty' => false,
430
				'rule' => 'notEmpty'
431
		));
432
 
433
		$data = array('TestValidate' => array(
434
			'title' => 'title',
435
			'number' => '3'
436
		));
437
		$result = $TestModel->create($data);
438
		$this->assertEquals($data, $result);
439
		$result = $TestModel->validates();
440
		$this->assertFalse($result);
441
 
442
		$data = array('TestValidate' => array(
443
			'title' => 'title',
444
			'number' => 3
445
		));
446
		$result = $TestModel->create($data);
447
		$this->assertEquals($data, $result);
448
		$result = $TestModel->validates();
449
		$this->assertFalse($result);
450
 
451
		$TestModel->validate = array(
452
			'title' => array(
453
				'allowEmpty' => false,
454
				'rule' => 'validateTitle'
455
		));
456
 
457
		$data = array('TestValidate' => array('title' => ''));
458
		$result = $TestModel->create($data);
459
		$this->assertEquals($data, $result);
460
		$result = $TestModel->validates();
461
		$this->assertFalse($result);
462
 
463
		$data = array('TestValidate' => array('title' => 'new title'));
464
		$result = $TestModel->create($data);
465
		$this->assertEquals($data, $result);
466
		$result = $TestModel->validates();
467
		$this->assertFalse($result);
468
 
469
		$data = array('TestValidate' => array('title' => 'title-new'));
470
		$result = $TestModel->create($data);
471
		$this->assertEquals($data, $result);
472
		$result = $TestModel->validates();
473
		$this->assertTrue($result);
474
 
475
		$TestModel->validate = array('title' => array(
476
			'allowEmpty' => true,
477
			'rule' => 'validateTitle'
478
		));
479
		$data = array('TestValidate' => array('title' => ''));
480
		$result = $TestModel->create($data);
481
		$this->assertEquals($data, $result);
482
		$result = $TestModel->validates();
483
		$this->assertTrue($result);
484
 
485
		$TestModel->validate = array(
486
			'title' => array(
487
				'length' => array(
488
					'allowEmpty' => true,
489
					'rule' => array('maxLength', 10)
490
		)));
491
		$data = array('TestValidate' => array('title' => ''));
492
		$result = $TestModel->create($data);
493
		$this->assertEquals($data, $result);
494
		$result = $TestModel->validates();
495
		$this->assertTrue($result);
496
 
497
		$TestModel->validate = array(
498
			'title' => array(
499
				'rule' => array('userDefined', 'Article', 'titleDuplicate')
500
		));
501
		$data = array('TestValidate' => array('title' => 'My Article Title'));
502
		$result = $TestModel->create($data);
503
		$this->assertEquals($data, $result);
504
		$result = $TestModel->validates();
505
		$this->assertFalse($result);
506
 
507
		$data = array('TestValidate' => array(
508
			'title' => 'My Article With a Different Title'
509
		));
510
		$result = $TestModel->create($data);
511
		$this->assertEquals($data, $result);
512
		$result = $TestModel->validates();
513
		$this->assertTrue($result);
514
 
515
		$TestModel->validate = array(
516
			'title' => array(
517
				'tooShort' => array('rule' => array('minLength', 50)),
518
				'onlyLetters' => array('rule' => '/^[a-z]+$/i')
519
			),
520
		);
521
		$data = array('TestValidate' => array(
522
			'title' => 'I am a short string'
523
		));
524
		$TestModel->create($data);
525
		$result = $TestModel->validates();
526
		$this->assertFalse($result);
527
		$result = $TestModel->validationErrors;
528
		$expected = array(
529
			'title' => array('tooShort')
530
		);
531
		$this->assertEquals($expected, $result);
532
 
533
		$TestModel->validate = array(
534
			'title' => array(
535
				'tooShort' => array(
536
					'rule' => array('minLength', 50),
537
					'last' => false
538
				),
539
				'onlyLetters' => array('rule' => '/^[a-z]+$/i')
540
			),
541
		);
542
		$data = array('TestValidate' => array(
543
			'title' => 'I am a short string'
544
		));
545
		$TestModel->create($data);
546
		$result = $TestModel->validates();
547
		$this->assertFalse($result);
548
		$result = $TestModel->validationErrors;
549
		$expected = array(
550
			'title' => array('tooShort', 'onlyLetters')
551
		);
552
		$this->assertEquals($expected, $result);
553
		$result = $TestModel->validationErrors;
554
		$this->assertEquals($expected, $result);
555
	}
556
 
557
/**
558
 * test that validates() checks all the 'with' associations as well for validation
559
 * as this can cause partial/wrong data insertion.
560
 *
561
 * @return void
562
 */
563
	public function testValidatesWithAssociations() {
564
		$this->loadFixtures('Something', 'SomethingElse', 'JoinThing');
565
		$data = array(
566
			'Something' => array(
567
				'id' => 5,
568
				'title' => 'Extra Fields',
569
				'body' => 'Extra Fields Body',
570
				'published' => '1'
571
			),
572
			'SomethingElse' => array(
573
				array('something_else_id' => 1, 'doomed' => '')
574
			)
575
		);
576
 
577
		$Something = new Something();
578
		$JoinThing = $Something->JoinThing;
579
 
580
		$JoinThing->validate = array('doomed' => array('rule' => 'notEmpty'));
581
 
582
		$expectedError = array('doomed' => array('This field cannot be left blank'));
583
 
584
		$Something->create();
585
		$result = $Something->save($data);
586
		$this->assertFalse($result, 'Save occurred even when with models failed. %s');
587
		$this->assertEquals($expectedError, $JoinThing->validationErrors);
588
		$count = $Something->find('count', array('conditions' => array('Something.id' => $data['Something']['id'])));
589
		$this->assertSame(0, $count);
590
 
591
		$data = array(
592
			'Something' => array(
593
				'id' => 5,
594
				'title' => 'Extra Fields',
595
				'body' => 'Extra Fields Body',
596
				'published' => '1'
597
			),
598
			'SomethingElse' => array(
599
				array('something_else_id' => 1, 'doomed' => 1),
600
				array('something_else_id' => 1, 'doomed' => '')
601
			)
602
		);
603
		$Something->create();
604
		$result = $Something->save($data);
605
		$this->assertFalse($result, 'Save occurred even when with models failed. %s');
606
 
607
		$joinRecords = $JoinThing->find('count', array(
608
			'conditions' => array('JoinThing.something_id' => $data['Something']['id'])
609
		));
610
		$this->assertEquals(0, $joinRecords, 'Records were saved on the join table. %s');
611
	}
612
 
613
/**
614
 * Test that if a behavior modifies the model's whitelist validation gets triggered
615
 * properly for those fields.
616
 *
617
 * @return void
618
 */
619
	public function testValidateWithFieldListAndBehavior() {
620
		$TestModel = new ValidationTest1();
621
		$TestModel->validate = array(
622
			'title' => array(
623
				'rule' => 'notEmpty',
624
			),
625
			'name' => array(
626
				'rule' => 'notEmpty',
627
		));
628
		$TestModel->Behaviors->attach('ValidationRule', array('fields' => array('name')));
629
 
630
		$data = array(
631
			'title' => '',
632
			'name' => '',
633
		);
634
		$result = $TestModel->save($data, array('fieldList' => array('title')));
635
		$this->assertFalse($result);
636
 
637
		$expected = array('title' => array('This field cannot be left blank'), 'name' => array('This field cannot be left blank'));
638
		$this->assertEquals($expected, $TestModel->validationErrors);
639
	}
640
 
641
/**
642
 * test that saveAll and with models with validation interact well
643
 *
644
 * @return void
645
 */
646
	public function testValidatesWithModelsAndSaveAll() {
647
		$this->loadFixtures('Something', 'SomethingElse', 'JoinThing');
648
		$data = array(
649
			'Something' => array(
650
				'id' => 5,
651
				'title' => 'Extra Fields',
652
				'body' => 'Extra Fields Body',
653
				'published' => '1'
654
			),
655
			'SomethingElse' => array(
656
				array('something_else_id' => 1, 'doomed' => '')
657
			)
658
		);
659
		$Something = new Something();
660
		$JoinThing = $Something->JoinThing;
661
 
662
		$JoinThing->validate = array('doomed' => array('rule' => 'notEmpty'));
663
		$expectedError = array('doomed' => array('This field cannot be left blank'));
664
 
665
		$Something->create();
666
		$result = $Something->saveAll($data, array('validate' => 'only'));
667
		$this->assertFalse($result);
668
		$result = $Something->validateAssociated($data);
669
		$this->assertFalse($result);
670
		$this->assertEquals($expectedError, $JoinThing->validationErrors);
671
		$result = $Something->validator()->validateAssociated($data);
672
		$this->assertFalse($result);
673
 
674
		$Something->create();
675
		$result = $Something->saveAll($data, array('validate' => 'first'));
676
		$this->assertFalse($result);
677
		$this->assertEquals($expectedError, $JoinThing->validationErrors);
678
 
679
		$count = $Something->find('count', array('conditions' => array('Something.id' => $data['Something']['id'])));
680
		$this->assertSame(0, $count);
681
 
682
		$joinRecords = $JoinThing->find('count', array(
683
			'conditions' => array('JoinThing.something_id' => $data['Something']['id'])
684
		));
685
		$this->assertEquals(0, $joinRecords, 'Records were saved on the join table. %s');
686
	}
687
 
688
/**
689
 * test that saveAll and with models at initial insert (no id has set yet)
690
 * with validation interact well
691
 *
692
 * @return void
693
 */
694
	public function testValidatesWithModelsAndSaveAllWithoutId() {
695
		$this->loadFixtures('Post', 'Author');
696
 
697
		$data = array(
698
			'Author' => array(
699
				'name' => 'Foo Bar',
700
			),
701
			'Post' => array(
702
				array('title' => 'Hello'),
703
				array('title' => 'World'),
704
			)
705
		);
706
		$Author = new Author();
707
		$Post = $Author->Post;
708
 
709
		$Post->validate = array('author_id' => array('rule' => 'numeric'));
710
 
711
		$Author->create();
712
		$result = $Author->saveAll($data, array('validate' => 'only'));
713
		$this->assertTrue($result);
714
		$result = $Author->validateAssociated($data);
715
		$this->assertTrue($result);
716
		$this->assertTrue($result);
717
 
718
		$Author->create();
719
		$result = $Author->saveAll($data, array('validate' => 'first'));
720
		$this->assertTrue($result);
721
		$this->assertNotNull($Author->id);
722
 
723
		$id = $Author->id;
724
		$count = $Author->find('count', array('conditions' => array('Author.id' => $id)));
725
		$this->assertSame(1, $count);
726
 
727
		$count = $Post->find('count', array(
728
			'conditions' => array('Post.author_id' => $id)
729
		));
730
		$this->assertEquals($count, count($data['Post']));
731
	}
732
 
733
/**
734
 * Test that missing validation methods trigger errors in development mode.
735
 * Helps to make development easier.
736
 *
737
 * @expectedException PHPUnit_Framework_Error
738
 * @return void
739
 */
740
	public function testMissingValidationErrorTriggering() {
741
		Configure::write('debug', 2);
742
 
743
		$TestModel = new ValidationTest1();
744
		$TestModel->create(array('title' => 'foo'));
745
		$TestModel->validate = array(
746
			'title' => array(
747
				'rule' => array('thisOneBringsThePain'),
748
				'required' => true
749
			)
750
		);
751
		$TestModel->invalidFields(array('fieldList' => array('title')));
752
	}
753
 
754
/**
755
 * Test placeholder replacement when validation message is an array
756
 *
757
 * @return void
758
 */
759
	public function testValidationMessageAsArray() {
760
		$TestModel = new ValidationTest1();
761
		$TestModel->validate = array(
762
			'title' => array(
763
				'minLength' => array(
764
					'rule' => array('minLength', 6),
765
					'required' => true,
766
					'message' => 'Minimum length allowed is %d chars',
767
					'last' => false
768
				),
769
				'between' => array(
770
					'rule' => array('lengthBetween', 5, 15),
771
					'message' => array('You may enter up to %s chars (minimum is %s chars)', 14, 6)
772
				)
773
			)
774
		);
775
 
776
		$TestModel->create();
777
		$expected = array(
778
			'title' => array(
779
				'Minimum length allowed is 6 chars',
780
			)
781
		);
782
		$TestModel->invalidFields();
783
		$this->assertEquals($expected, $TestModel->validationErrors);
784
 
785
		$TestModel->create(array('title' => 'foo'));
786
		$expected = array(
787
			'title' => array(
788
				'Minimum length allowed is 6 chars',
789
				'You may enter up to 14 chars (minimum is 6 chars)'
790
			)
791
		);
792
		$TestModel->invalidFields();
793
		$this->assertEquals($expected, $TestModel->validationErrors);
794
	}
795
 
796
/**
797
 * Test validation message translation
798
 *
799
 * @return void
800
 */
801
	public function testValidationMessageTranslation() {
802
		$lang = Configure::read('Config.language');
803
		Configure::write('Config.language', 'en');
804
		App::build(array(
805
			'Locale' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Locale' . DS),
806
		), App::RESET);
807
 
808
		$TestModel = new ValidationTest1();
809
		$TestModel->validationDomain = 'validation_messages';
810
		$TestModel->validate = array(
811
			'title' => array(
812
				array(
813
					'rule' => array('customValidationMethod', 'arg1'),
814
					'required' => true,
815
					'message' => 'Validation failed: %s'
816
				)
817
			)
818
		);
819
 
820
		$TestModel->create();
821
		$expected = array(
822
			'title' => array(
823
				'Translated validation failed: Translated arg1',
824
			)
825
		);
826
		$TestModel->invalidFields();
827
		$this->assertEquals($expected, $TestModel->validationErrors);
828
 
829
		$TestModel->validationDomain = 'default';
830
		Configure::write('Config.language', $lang);
831
		App::build();
832
	}
833
 
834
/**
835
 * Test for 'on' => [create|update] in validation rules.
836
 *
837
 * @return void
838
 */
839
	public function testStateValidation() {
840
		$this->loadFixtures('Article');
841
		$Article = new Article();
842
 
843
		$data = array(
844
			'Article' => array(
845
				'title' => '',
846
				'body' => 'Extra Fields Body',
847
				'published' => '1'
848
			)
849
		);
850
 
851
		$Article->validate = array(
852
			'title' => array(
853
				'notempty' => array(
854
					'rule' => 'notEmpty',
855
					'on' => 'create'
856
				)
857
			)
858
		);
859
 
860
		$Article->create($data);
861
		$this->assertFalse($Article->validates());
862
 
863
		$Article->save(null, array('validate' => false));
864
		$data['Article']['id'] = $Article->id;
865
		$Article->set($data);
866
		$this->assertTrue($Article->validates());
867
 
868
		unset($data['Article']['id']);
869
		$Article->validate = array(
870
			'title' => array(
871
				'notempty' => array(
872
					'rule' => 'notEmpty',
873
					'on' => 'update'
874
				)
875
			)
876
		);
877
 
878
		$Article->create($data);
879
		$this->assertTrue($Article->validates());
880
 
881
		$Article->save(null, array('validate' => false));
882
		$data['Article']['id'] = $Article->id;
883
		$Article->set($data);
884
		$this->assertFalse($Article->validates());
885
	}
886
 
887
/**
888
 * Test for 'required' => [create|update] in validation rules.
889
 *
890
 * @return void
891
 */
892
	public function testStateRequiredValidation() {
893
		$this->loadFixtures('Article');
894
		$Article = new Article();
895
 
896
		// no title field present
897
		$data = array(
898
			'Article' => array(
899
				'body' => 'Extra Fields Body',
900
				'published' => '1'
901
			)
902
		);
903
 
904
		$Article->validate = array(
905
			'title' => array(
906
				'notempty' => array(
907
					'rule' => 'notEmpty',
908
					'required' => 'create'
909
				)
910
			)
911
		);
912
 
913
		$Article->create($data);
914
		$this->assertFalse($Article->validates());
915
 
916
		$Article->save(null, array('validate' => false));
917
		$data['Article']['id'] = $Article->id;
918
		$Article->set($data);
919
		$this->assertTrue($Article->validates());
920
 
921
		unset($data['Article']['id']);
922
		$Article->validate = array(
923
			'title' => array(
924
				'notempty' => array(
925
					'rule' => 'notEmpty',
926
					'required' => 'update'
927
				)
928
			)
929
		);
930
 
931
		$Article->create($data);
932
		$this->assertTrue($Article->validates());
933
 
934
		$Article->save(null, array('validate' => false));
935
		$data['Article']['id'] = $Article->id;
936
		$Article->set($data);
937
		$this->assertFalse($Article->validates());
938
	}
939
 
940
/**
941
 * Test that 'required' and 'on' are not conflicting
942
 *
943
 * @return void
944
 */
945
	public function testOnRequiredConflictValidation() {
946
		$this->loadFixtures('Article');
947
		$Article = new Article();
948
 
949
		// no title field present
950
		$data = array(
951
			'Article' => array(
952
				'body' => 'Extra Fields Body',
953
				'published' => '1'
954
			)
955
		);
956
 
957
		$Article->validate = array(
958
			'title' => array(
959
				'notempty' => array(
960
					'rule' => 'notEmpty',
961
					'required' => 'create',
962
					'on' => 'create'
963
				)
964
			)
965
		);
966
 
967
		$Article->create($data);
968
		$this->assertFalse($Article->validates());
969
 
970
		$Article->validate = array(
971
			'title' => array(
972
				'notempty' => array(
973
					'rule' => 'notEmpty',
974
					'required' => 'update',
975
					'on' => 'create'
976
				)
977
			)
978
		);
979
 
980
		$Article->create($data);
981
		$this->assertTrue($Article->validates());
982
 
983
		$Article->validate = array(
984
			'title' => array(
985
				'notempty' => array(
986
					'rule' => 'notEmpty',
987
					'required' => 'create',
988
					'on' => 'update'
989
				)
990
			)
991
		);
992
 
993
		$Article->create($data);
994
		$this->assertTrue($Article->validates());
995
 
996
		$Article->validate = array(
997
			'title' => array(
998
				'notempty' => array(
999
					'rule' => 'notEmpty',
1000
					'required' => 'update',
1001
					'on' => 'update'
1002
				)
1003
			)
1004
		);
1005
 
1006
		$Article->create($data);
1007
		$this->assertTrue($Article->validates());
1008
 
1009
		$Article->validate = array(
1010
			'title' => array(
1011
				'notempty' => array(
1012
					'rule' => 'notEmpty',
1013
					'required' => 'create',
1014
					'on' => 'create'
1015
				)
1016
			)
1017
		);
1018
 
1019
		$Article->save(null, array('validate' => false));
1020
		$data['Article']['id'] = $Article->id;
1021
		$Article->set($data);
1022
		$this->assertTrue($Article->validates());
1023
 
1024
		$Article->validate = array(
1025
			'title' => array(
1026
				'notempty' => array(
1027
					'rule' => 'notEmpty',
1028
					'required' => 'update',
1029
					'on' => 'create'
1030
				)
1031
			)
1032
		);
1033
 
1034
		$Article->set($data);
1035
		$this->assertTrue($Article->validates());
1036
 
1037
		$Article->validate = array(
1038
			'title' => array(
1039
				'notempty' => array(
1040
					'rule' => 'notEmpty',
1041
					'required' => 'create',
1042
					'on' => 'update'
1043
				)
1044
			)
1045
		);
1046
 
1047
		$Article->set($data);
1048
		$this->assertTrue($Article->validates());
1049
 
1050
		$Article->validate = array(
1051
			'title' => array(
1052
				'notempty' => array(
1053
					'rule' => 'notEmpty',
1054
					'required' => 'update',
1055
					'on' => 'update'
1056
				)
1057
			)
1058
		);
1059
 
1060
		$Article->set($data);
1061
		$this->assertFalse($Article->validates());
1062
	}
1063
 
1064
/**
1065
 * testSaveAllDeepValidateOnly
1066
 * tests the validate methods with deeper recursive data
1067
 *
1068
 * @return void
1069
 */
1070
	public function testSaveAllDeepValidateOnly() {
1071
		$this->loadFixtures('Article', 'Comment', 'User', 'Attachment');
1072
		$TestModel = new Article();
1073
		$TestModel->hasMany['Comment']['order'] = array('Comment.created' => 'ASC');
1074
		$TestModel->hasAndBelongsToMany = array();
1075
		$TestModel->Comment->Attachment->validate['attachment'] = 'notEmpty';
1076
		$TestModel->Comment->validate['comment'] = 'notEmpty';
1077
 
1078
		$data = array(
1079
			'Article' => array('id' => 2),
1080
			'Comment' => array(
1081
				array('comment' => 'First new comment', 'published' => 'Y', 'User' => array('user' => 'newuser', 'password' => 'newuserpass')),
1082
				array('comment' => 'Second new comment', 'published' => 'Y', 'user_id' => 2)
1083
			)
1084
		);
1085
		$result = $TestModel->saveAll($data, array('validate' => 'only', 'deep' => true));
1086
		$this->assertTrue($result);
1087
		$result = $TestModel->validateAssociated($data, array('deep' => true));
1088
		$this->assertTrue($result);
1089
 
1090
		$data = array(
1091
			'Article' => array('id' => 2),
1092
			'Comment' => array(
1093
				array('comment' => 'First new comment', 'published' => 'Y', 'User' => array('user' => '', 'password' => 'newuserpass')),
1094
				array('comment' => 'Second new comment', 'published' => 'Y', 'user_id' => 2)
1095
			)
1096
		);
1097
		$result = $TestModel->saveAll($data, array('validate' => 'only', 'deep' => true));
1098
		$this->assertFalse($result);
1099
		$result = $TestModel->validateAssociated($data, array('deep' => true));
1100
		$this->assertFalse($result);
1101
 
1102
		$data = array(
1103
			'Article' => array('id' => 2),
1104
			'Comment' => array(
1105
				array('comment' => 'First new comment', 'published' => 'Y', 'User' => array('user' => 'newuser', 'password' => 'newuserpass')),
1106
				array('comment' => 'Second new comment', 'published' => 'Y', 'user_id' => 2)
1107
			)
1108
		);
1109
		$expected = array(
1110
			'Article' => true,
1111
			'Comment' => array(
1112
				true,
1113
				true
1114
			)
1115
		);
1116
		$result = $TestModel->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => true));
1117
		$this->assertSame($expected, $result);
1118
		$result = $TestModel->validateAssociated($data, array('atomic' => false, 'deep' => true));
1119
		$this->assertSame($expected, $result);
1120
 
1121
		$data = array(
1122
			'Article' => array('id' => 2),
1123
			'Comment' => array(
1124
				array('comment' => 'First new comment', 'published' => 'Y', 'User' => array('user' => '', 'password' => 'newuserpass')),
1125
				array('comment' => 'Second new comment', 'published' => 'Y', 'user_id' => 2)
1126
			)
1127
		);
1128
		$expected = array(
1129
			'Article' => true,
1130
			'Comment' => array(
1131
				false,
1132
				true
1133
			)
1134
		);
1135
		$result = $TestModel->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => true));
1136
		$this->assertSame($expected, $result);
1137
		$result = $TestModel->validateAssociated($data, array('atomic' => false, 'deep' => true));
1138
		$this->assertSame($expected, $result);
1139
 
1140
		$data = array(
1141
			'Article' => array('id' => 2),
1142
			'Comment' => array(
1143
				array('comment' => 'Third new comment', 'published' => 'Y', 'user_id' => 5),
1144
				array('comment' => 'Fourth new comment', 'published' => 'Y', 'user_id' => 2, 'Attachment' => array('attachment' => 'deepsaved'))
1145
			)
1146
		);
1147
		$result = $TestModel->saveAll($data, array('validate' => 'only', 'deep' => true));
1148
		$this->assertTrue($result);
1149
		$result = $TestModel->validateAssociated($data, array('deep' => true));
1150
		$this->assertTrue($result);
1151
 
1152
		$data = array(
1153
			'Article' => array('id' => 2),
1154
			'Comment' => array(
1155
				array('comment' => 'Third new comment', 'published' => 'Y', 'user_id' => 5),
1156
				array('comment' => 'Fourth new comment', 'published' => 'Y', 'user_id' => 2, 'Attachment' => array('attachment' => ''))
1157
			)
1158
		);
1159
		$result = $TestModel->saveAll($data, array('validate' => 'only', 'deep' => true));
1160
		$this->assertFalse($result);
1161
		$result = $TestModel->validateAssociated($data, array('deep' => true));
1162
		$this->assertFalse($result);
1163
 
1164
		$data = array(
1165
			'Article' => array('id' => 2),
1166
			'Comment' => array(
1167
				array('comment' => 'Third new comment', 'published' => 'Y', 'user_id' => 5),
1168
				array('comment' => 'Fourth new comment', 'published' => 'Y', 'user_id' => 2, 'Attachment' => array('attachment' => 'deepsave'))
1169
			)
1170
		);
1171
		$expected = array(
1172
			'Article' => true,
1173
			'Comment' => array(
1174
				true,
1175
				true
1176
			)
1177
		);
1178
		$result = $TestModel->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => true));
1179
		$this->assertSame($expected, $result);
1180
		$result = $TestModel->validateAssociated($data, array('atomic' => false, 'deep' => true));
1181
		$this->assertSame($expected, $result);
1182
 
1183
		$data = array(
1184
			'Article' => array('id' => 2),
1185
			'Comment' => array(
1186
				array('comment' => 'Third new comment', 'published' => 'Y', 'user_id' => 5),
1187
				array('comment' => 'Fourth new comment', 'published' => 'Y', 'user_id' => 2, 'Attachment' => array('attachment' => ''))
1188
			)
1189
		);
1190
		$expected = array(
1191
			'Article' => true,
1192
			'Comment' => array(
1193
				true,
1194
				false
1195
			)
1196
		);
1197
		$result = $TestModel->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => true));
1198
		$this->assertSame($expected, $result);
1199
		$result = $TestModel->validateAssociated($data, array('atomic' => false, 'deep' => true));
1200
		$this->assertSame($expected, $result);
1201
 
1202
		$expected = array(
1203
			'Comment' => array(
1204
				1 => array(
1205
					'Attachment' => array(
1206
						'attachment' => array('This field cannot be left blank')
1207
					)
1208
				)
1209
			)
1210
		);
1211
		$result = $TestModel->validationErrors;
1212
		$this->assertSame($expected, $result);
1213
 
1214
		$data = array(
1215
			'Attachment' => array(
1216
				'attachment' => 'deepsave insert',
1217
			),
1218
			'Comment' => array(
1219
				'comment' => 'First comment deepsave insert',
1220
				'published' => 'Y',
1221
				'user_id' => 5,
1222
				'Article' => array(
1223
					'title' => 'First Article deepsave insert',
1224
					'body' => 'First Article Body deepsave insert',
1225
					'User' => array(
1226
						'user' => 'deepsave',
1227
						'password' => 'magic'
1228
					),
1229
				),
1230
			)
1231
		);
1232
 
1233
		$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'deep' => true));
1234
		$this->assertTrue($result);
1235
		$result = $TestModel->Comment->Attachment->validateAssociated($data, array('deep' => true));
1236
		$this->assertTrue($result);
1237
 
1238
		$expected = array(
1239
			'Attachment' => true,
1240
			'Comment' => true
1241
		);
1242
		$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => true));
1243
		$this->assertSame($expected, $result);
1244
		$result = $TestModel->Comment->Attachment->validateAssociated($data, array('atomic' => false, 'deep' => true));
1245
		$this->assertSame($expected, $result);
1246
 
1247
		$data = array(
1248
			'Attachment' => array(
1249
				'attachment' => 'deepsave insert',
1250
			),
1251
			'Comment' => array(
1252
				'comment' => 'First comment deepsave insert',
1253
				'published' => 'Y',
1254
				'user_id' => 5,
1255
				'Article' => array(
1256
					'title' => 'First Article deepsave insert',
1257
					'body' => 'First Article Body deepsave insert',
1258
					'User' => array(
1259
						'user' => '',
1260
						'password' => 'magic'
1261
					),
1262
				),
1263
			)
1264
		);
1265
 
1266
		$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'deep' => true));
1267
		$this->assertFalse($result);
1268
		$result = $TestModel->Comment->Attachment->validateAssociated($data, array('deep' => true));
1269
		$this->assertFalse($result);
1270
 
1271
		$result = $TestModel->Comment->Attachment->validationErrors;
1272
		$expected = array(
1273
			'Comment' => array(
1274
				'Article' => array(
1275
					'User' => array(
1276
						'user' => array('This field cannot be left blank')
1277
					)
1278
				)
1279
			)
1280
		);
1281
		$this->assertSame($expected, $result);
1282
 
1283
		$expected = array(
1284
			'Attachment' => true,
1285
			'Comment' => false
1286
		);
1287
		$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => true));
1288
		$this->assertEquals($expected, $result);
1289
		$result = $TestModel->Comment->Attachment->validateAssociated($data, array('atomic' => false, 'deep' => true));
1290
		$this->assertEquals($expected, $result);
1291
 
1292
		$data['Comment']['Article']['body'] = '';
1293
		$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'deep' => true));
1294
		$this->assertFalse($result);
1295
		$result = $TestModel->Comment->Attachment->validateAssociated($data, array('deep' => true));
1296
		$this->assertFalse($result);
1297
 
1298
		$result = $TestModel->Comment->Attachment->validationErrors;
1299
		$expected = array(
1300
			'Comment' => array(
1301
				'Article' => array(
1302
					'body' => array('This field cannot be left blank'),
1303
					'User' => array(
1304
						'user' => array('This field cannot be left blank')
1305
					)
1306
				)
1307
			)
1308
		);
1309
		$this->assertSame($expected, $result);
1310
 
1311
		$expected = array(
1312
			'Attachment' => true,
1313
			'Comment' => false
1314
		);
1315
		$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => true));
1316
		$this->assertEquals($expected, $result);
1317
		$result = $TestModel->Comment->Attachment->validateAssociated($data, array('atomic' => false, 'deep' => true));
1318
		$this->assertEquals($expected, $result);
1319
 
1320
		$data['Comment']['comment'] = '';
1321
		$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'deep' => true));
1322
		$this->assertFalse($result);
1323
		$result = $TestModel->Comment->Attachment->validateAssociated($data, array('deep' => true));
1324
		$this->assertFalse($result);
1325
 
1326
		$result = $TestModel->Comment->Attachment->validationErrors;
1327
		$expected = array(
1328
			'Comment' => array(
1329
				'comment' => array('This field cannot be left blank'),
1330
				'Article' => array(
1331
					'body' => array('This field cannot be left blank'),
1332
					'User' => array(
1333
						'user' => array('This field cannot be left blank')
1334
					)
1335
				)
1336
			)
1337
		);
1338
		$this->assertSame($expected, $result);
1339
 
1340
		$expected = array(
1341
			'Attachment' => true,
1342
			'Comment' => false
1343
		);
1344
		$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => true));
1345
		$this->assertEquals($expected, $result);
1346
		$result = $TestModel->Comment->Attachment->validateAssociated($data, array('atomic' => false, 'deep' => true));
1347
		$this->assertEquals($expected, $result);
1348
 
1349
		$data['Attachment']['attachment'] = '';
1350
		$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'deep' => true));
1351
		$this->assertFalse($result);
1352
		$result = $TestModel->Comment->Attachment->validateAssociated($data, array('deep' => true));
1353
		$this->assertFalse($result);
1354
 
1355
		$result = $TestModel->Comment->Attachment->validationErrors;
1356
		$expected = array(
1357
			'attachment' => array('This field cannot be left blank'),
1358
			'Comment' => array(
1359
				'comment' => array('This field cannot be left blank'),
1360
				'Article' => array(
1361
					'body' => array('This field cannot be left blank'),
1362
					'User' => array(
1363
						'user' => array('This field cannot be left blank')
1364
					)
1365
				)
1366
			)
1367
		);
1368
		$this->assertSame($expected, $result);
1369
 
1370
		$result = $TestModel->Comment->validationErrors;
1371
		$expected = array(
1372
			'comment' => array('This field cannot be left blank'),
1373
			'Article' => array(
1374
					'body' => array('This field cannot be left blank'),
1375
					'User' => array(
1376
						'user' => array('This field cannot be left blank')
1377
					)
1378
				)
1379
		);
1380
		$this->assertSame($expected, $result);
1381
 
1382
		$expected = array(
1383
			'Attachment' => false,
1384
			'Comment' => false
1385
		);
1386
		$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => true));
1387
		$this->assertEquals($expected, $result);
1388
		$result = $TestModel->Comment->Attachment->validateAssociated($data, array('atomic' => false, 'deep' => true));
1389
		$this->assertEquals($expected, $result);
1390
	}
1391
 
1392
/**
1393
 * testSaveAllNotDeepValidateOnly
1394
 * tests the validate methods to not validate deeper recursive data
1395
 *
1396
 * @return void
1397
 */
1398
	public function testSaveAllNotDeepValidateOnly() {
1399
		$this->loadFixtures('Article', 'Comment', 'User', 'Attachment');
1400
		$TestModel = new Article();
1401
		$TestModel->hasMany['Comment']['order'] = array('Comment.created' => 'ASC');
1402
		$TestModel->hasAndBelongsToMany = array();
1403
		$TestModel->Comment->Attachment->validate['attachment'] = 'notEmpty';
1404
		$TestModel->Comment->validate['comment'] = 'notEmpty';
1405
 
1406
		$data = array(
1407
			'Article' => array('id' => 2, 'body' => ''),
1408
			'Comment' => array(
1409
				array('comment' => 'First new comment', 'published' => 'Y', 'User' => array('user' => '', 'password' => 'newuserpass')),
1410
				array('comment' => 'Second new comment', 'published' => 'Y', 'user_id' => 2)
1411
			)
1412
		);
1413
		$result = $TestModel->saveAll($data, array('validate' => 'only', 'deep' => false));
1414
		$this->assertFalse($result);
1415
		$result = $TestModel->validateAssociated($data, array('deep' => false));
1416
		$this->assertFalse($result);
1417
 
1418
		$expected = array('body' => array('This field cannot be left blank'));
1419
		$result = $TestModel->validationErrors;
1420
		$this->assertSame($expected, $result);
1421
 
1422
		$data = array(
1423
			'Article' => array('id' => 2, 'body' => 'Ignore invalid user data'),
1424
			'Comment' => array(
1425
				array('comment' => 'First new comment', 'published' => 'Y', 'User' => array('user' => '', 'password' => 'newuserpass')),
1426
				array('comment' => 'Second new comment', 'published' => 'Y', 'user_id' => 2)
1427
			)
1428
		);
1429
		$result = $TestModel->saveAll($data, array('validate' => 'only', 'deep' => false));
1430
		$this->assertTrue($result);
1431
		$result = $TestModel->validateAssociated($data, array('deep' => false));
1432
		$this->assertTrue($result);
1433
 
1434
		$data = array(
1435
			'Article' => array('id' => 2, 'body' => 'Ignore invalid user data'),
1436
			'Comment' => array(
1437
				array('comment' => 'First new comment', 'published' => 'Y', 'User' => array('user' => '', 'password' => 'newuserpass')),
1438
				array('comment' => 'Second new comment', 'published' => 'Y', 'user_id' => 2)
1439
			)
1440
		);
1441
		$expected = array(
1442
			'Article' => true,
1443
			'Comment' => array(
1444
				true,
1445
				true
1446
			)
1447
		);
1448
		$result = $TestModel->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => false));
1449
		$this->assertSame($expected, $result);
1450
		$result = $TestModel->validateAssociated($data, array('atomic' => false, 'deep' => false));
1451
		$this->assertSame($expected, $result);
1452
 
1453
		$data = array(
1454
			'Article' => array('id' => 2, 'body' => 'Ignore invalid attachment data'),
1455
			'Comment' => array(
1456
				array('comment' => 'Third new comment', 'published' => 'Y', 'user_id' => 5),
1457
				array('comment' => 'Fourth new comment', 'published' => 'Y', 'user_id' => 2, 'Attachment' => array('attachment' => ''))
1458
			)
1459
		);
1460
		$result = $TestModel->saveAll($data, array('validate' => 'only', 'deep' => false));
1461
		$this->assertTrue($result);
1462
		$result = $TestModel->validateAssociated($data, array('deep' => false));
1463
		$this->assertTrue($result);
1464
 
1465
		$data = array(
1466
			'Article' => array('id' => 2, 'body' => 'Ignore invalid attachment data'),
1467
			'Comment' => array(
1468
				array('comment' => 'Third new comment', 'published' => 'Y', 'user_id' => 5),
1469
				array('comment' => 'Fourth new comment', 'published' => 'Y', 'user_id' => 2, 'Attachment' => array('attachment' => ''))
1470
			)
1471
		);
1472
		$expected = array(
1473
			'Article' => true,
1474
			'Comment' => array(
1475
				true,
1476
				true
1477
			)
1478
		);
1479
		$result = $TestModel->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => false));
1480
		$this->assertSame($expected, $result);
1481
		$result = $TestModel->validateAssociated($data, array('atomic' => false, 'deep' => false));
1482
		$this->assertSame($expected, $result);
1483
 
1484
		$expected = array();
1485
		$result = $TestModel->validationErrors;
1486
		$this->assertSame($expected, $result);
1487
 
1488
		$data = array(
1489
			'Attachment' => array(
1490
				'attachment' => 'deepsave insert',
1491
			),
1492
			'Comment' => array(
1493
				'comment' => 'First comment deepsave insert',
1494
				'published' => 'Y',
1495
				'user_id' => 5,
1496
				'Article' => array(
1497
					'title' => 'First Article deepsave insert ignored',
1498
					'body' => 'First Article Body deepsave insert',
1499
					'User' => array(
1500
						'user' => '',
1501
						'password' => 'magic'
1502
					),
1503
				),
1504
			)
1505
		);
1506
 
1507
		$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'deep' => false));
1508
		$this->assertTrue($result);
1509
		$result = $TestModel->Comment->Attachment->validateAssociated($data, array('deep' => false));
1510
		$this->assertTrue($result);
1511
 
1512
		$result = $TestModel->Comment->Attachment->validationErrors;
1513
		$expected = array();
1514
		$this->assertSame($expected, $result);
1515
 
1516
		$expected = array(
1517
			'Attachment' => true,
1518
			'Comment' => true
1519
		);
1520
		$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => false));
1521
		$this->assertEquals($expected, $result);
1522
		$result = $TestModel->Comment->Attachment->validateAssociated($data, array('atomic' => false, 'deep' => false));
1523
		$this->assertEquals($expected, $result);
1524
 
1525
		$data['Comment']['Article']['body'] = '';
1526
		$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'deep' => false));
1527
		$this->assertTrue($result);
1528
		$result = $TestModel->Comment->Attachment->validateAssociated($data, array('deep' => false));
1529
		$this->assertTrue($result);
1530
 
1531
		$result = $TestModel->Comment->Attachment->validationErrors;
1532
		$expected = array();
1533
		$this->assertSame($expected, $result);
1534
 
1535
		$expected = array(
1536
			'Attachment' => true,
1537
			'Comment' => true
1538
		);
1539
		$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => false));
1540
		$this->assertEquals($expected, $result);
1541
		$result = $TestModel->Comment->Attachment->validateAssociated($data, array('atomic' => false, 'deep' => false));
1542
		$this->assertEquals($expected, $result);
1543
	}
1544
 
1545
/**
1546
 * testValidateAssociated method
1547
 *
1548
 * @return void
1549
 */
1550
	public function testValidateAssociated() {
1551
		$this->loadFixtures('Comment', 'Attachment', 'Article', 'User');
1552
		$TestModel = new Comment();
1553
		$TestModel->Attachment->validate = array('attachment' => 'notEmpty');
1554
 
1555
		$data = array(
1556
			'Comment' => array(
1557
				'comment' => 'This is the comment'
1558
			),
1559
			'Attachment' => array(
1560
				'attachment' => ''
1561
			)
1562
		);
1563
		$result = $TestModel->saveAll($data, array('validate' => 'only'));
1564
		$this->assertFalse($result);
1565
		$result = $TestModel->validateAssociated($data);
1566
		$this->assertFalse($result);
1567
 
1568
		$fieldList = array(
1569
			'Attachment' => array('comment_id')
1570
		);
1571
		$result = $TestModel->saveAll($data, array(
1572
			'fieldList' => $fieldList, 'validate' => 'only'
1573
		));
1574
		$this->assertTrue($result);
1575
		$this->assertEmpty($TestModel->validationErrors);
1576
		$result = $TestModel->validateAssociated($data, array('fieldList' => $fieldList));
1577
		$this->assertTrue($result);
1578
		$this->assertEmpty($TestModel->validationErrors);
1579
 
1580
		$TestModel->validate = array('comment' => 'notEmpty');
1581
		$record = array(
1582
			'Comment' => array(
1583
				'user_id' => 1,
1584
				'article_id' => 1,
1585
				'comment' => '',
1586
			),
1587
			'Attachment' => array(
1588
				'attachment' => ''
1589
			)
1590
		);
1591
		$result = $TestModel->saveAll($record, array('validate' => 'only'));
1592
		$this->assertFalse($result);
1593
		$result = $TestModel->validateAssociated($record);
1594
		$this->assertFalse($result);
1595
 
1596
		$fieldList = array(
1597
			'Comment' => array('id', 'article_id', 'user_id'),
1598
			'Attachment' => array('comment_id')
1599
		);
1600
		$result = $TestModel->saveAll($record, array(
1601
			'fieldList' => $fieldList, 'validate' => 'only'
1602
		));
1603
		$this->assertTrue($result);
1604
		$this->assertEmpty($TestModel->validationErrors);
1605
		$result = $TestModel->validateAssociated($record, array('fieldList' => $fieldList));
1606
		$this->assertTrue($result);
1607
		$this->assertEmpty($TestModel->validationErrors);
1608
 
1609
		$TestModel = new Article();
1610
		$TestModel->belongsTo = $TestModel->hasAndBelongsToMany = array();
1611
		$TestModel->Comment->validate = array('comment' => 'notEmpty');
1612
		$data = array(
1613
			'Article' => array('id' => 2),
1614
			'Comment' => array(
1615
				array(
1616
					'id' => 1,
1617
					'comment' => '',
1618
					'published' => 'Y',
1619
					'user_id' => 1,
1620
				),
1621
				array(
1622
					'id' => 2,
1623
					'comment' =>
1624
					'comment',
1625
					'published' => 'Y',
1626
					'user_id' => 1
1627
				),
1628
				array(
1629
					'id' => 3,
1630
					'comment' => '',
1631
					'published' => 'Y',
1632
					'user_id' => 1
1633
		)));
1634
		$result = $TestModel->saveAll($data, array('validate' => 'only'));
1635
		$this->assertFalse($result);
1636
		$result = $TestModel->validateAssociated($data);
1637
		$this->assertFalse($result);
1638
 
1639
		$expected = array(
1640
			'Article' => true,
1641
			'Comment' => array(false, true, false)
1642
		);
1643
		$result = $TestModel->saveAll($data, array('atomic' => false, 'validate' => 'only'));
1644
		$this->assertSame($expected, $result);
1645
		$result = $TestModel->validateAssociated($data, array('atomic' => false));
1646
		$this->assertSame($expected, $result);
1647
 
1648
		$expected = array('Comment' => array(
1649
 
1650
			2 => array('comment' => array('This field cannot be left blank'))
1651
		));
1652
		$this->assertEquals($expected['Comment'], $TestModel->Comment->validationErrors);
1653
 
1654
		$model = new Comment();
1655
		$model->deleteAll(true);
1656
		$model->validate = array('comment' => 'notEmpty');
1657
		$model->Attachment->validate = array('attachment' => 'notEmpty');
1658
		$model->Attachment->bindModel(array('belongsTo' => array('Comment')));
1659
		$expected = array(
1660
			'comment' => array('This field cannot be left blank'),
1661
			'Attachment' => array(
1662
				'attachment' => array('This field cannot be left blank')
1663
			)
1664
		);
1665
 
1666
		$data = array(
1667
			'Comment' => array('comment' => '', 'article_id' => 1, 'user_id' => 1),
1668
			'Attachment' => array('attachment' => '')
1669
		);
1670
		$result = $model->saveAll($data, array('validate' => 'only'));
1671
		$this->assertFalse($result);
1672
		$result = $model->validateAssociated($data);
1673
		$this->assertFalse($result);
1674
		$this->assertEquals($expected, $model->validationErrors);
1675
		$this->assertEquals($expected['Attachment'], $model->Attachment->validationErrors);
1676
	}
1677
 
1678
/**
1679
 * testValidateMany method
1680
 *
1681
 * @return void
1682
 */
1683
	public function testValidateMany() {
1684
		$TestModel = new Article();
1685
		$TestModel->validate = array('title' => 'notEmpty');
1686
		$data = array(
1687
 
1688
			1 => array('title' => 'title 1'),
1689
			2 => array('title' => 'title 2'),
1690
		);
1691
		$expected = array(
1692
 
1693
		);
1694
 
1695
		$result = $TestModel->saveAll($data, array('validate' => 'only'));
1696
		$this->assertFalse($result);
1697
		$this->assertEquals($expected, $TestModel->validationErrors);
1698
		$result = $TestModel->validateMany($data);
1699
		$this->assertFalse($result);
1700
		$this->assertEquals($expected, $TestModel->validationErrors);
1701
 
1702
		$data = array(
1703
 
1704
			1 => array('title' => ''),
1705
			2 => array('title' => 'title 2'),
1706
		);
1707
		$expected = array(
1708
			1 => array('title' => array('This field cannot be left blank')),
1709
		);
1710
		$result = $TestModel->saveAll($data, array('validate' => 'only'));
1711
		$this->assertFalse($result);
1712
		$this->assertEquals($expected, $TestModel->validationErrors);
1713
		$result = $TestModel->validateMany($data);
1714
		$this->assertFalse($result);
1715
		$this->assertEquals($expected, $TestModel->validationErrors);
1716
	}
1717
 
1718
/**
1719
 * testGetMethods method
1720
 *
1721
 * @return void
1722
 */
1723
	public function testGetMethods() {
1724
		$this->loadFixtures('Article', 'Comment');
1725
		$TestModel = new Article();
1726
		$Validator = $TestModel->validator();
1727
 
1728
		$result = $Validator->getMethods();
1729
 
1730
		$expected = array_map('strtolower', get_class_methods('Article'));
1731
		$this->assertEquals($expected, array_keys($result));
1732
	}
1733
 
1734
/**
1735
 *  Tests that methods are refreshed when the list of behaviors change
1736
 *
1737
 * @return void
1738
 */
1739
	public function testGetMethodsRefresh() {
1740
		$this->loadFixtures('Article', 'Comment');
1741
		$TestModel = new Article();
1742
		$Validator = $TestModel->validator();
1743
 
1744
		$result = $Validator->getMethods();
1745
 
1746
		$expected = array_map('strtolower', get_class_methods('Article'));
1747
		$this->assertEquals($expected, array_keys($result));
1748
 
1749
		$TestModel->Behaviors->load('Containable');
1750
		$newList = array(
1751
			'contain',
1752
			'resetbindings',
1753
			'containments',
1754
			'fielddependencies',
1755
			'containmentsmap'
1756
		);
1757
		$this->assertEquals(array_merge($expected, $newList), array_keys($Validator->getMethods()));
1758
 
1759
		$TestModel->Behaviors->unload('Containable');
1760
		$this->assertEquals($expected, array_keys($Validator->getMethods()));
1761
	}
1762
 
1763
/**
1764
 * testSetValidationDomain method
1765
 *
1766
 * @return void
1767
 */
1768
	public function testSetValidationDomain() {
1769
		$this->loadFixtures('Article', 'Comment');
1770
		$TestModel = new Article();
1771
		$Validator = $TestModel->validator();
1772
 
1773
		$result = $Validator->setValidationDomain('default');
1774
		$this->assertEquals('default', $TestModel->validationDomain);
1775
 
1776
		$result = $Validator->setValidationDomain('other');
1777
		$this->assertEquals('other', $TestModel->validationDomain);
1778
	}
1779
 
1780
/**
1781
 * testGetModel method
1782
 *
1783
 * @return void
1784
 */
1785
	public function testGetModel() {
1786
		$TestModel = new Article();
1787
		$Validator = $TestModel->validator();
1788
 
1789
		$result = $Validator->getModel();
1790
		$this->assertInstanceOf('Article', $result);
1791
	}
1792
 
1793
/**
1794
 * Tests it is possible to get validation sets for a field using an array inteface
1795
 *
1796
 * @return void
1797
 */
1798
	public function testArrayAccessGet() {
1799
		$TestModel = new Article();
1800
		$Validator = $TestModel->validator();
1801
 
1802
		$titleValidator = $Validator['title'];
1803
		$this->assertEquals('title', $titleValidator->field);
1804
		$this->assertCount(1, $titleValidator->getRules());
1805
		$rule = current($titleValidator->getRules());
1806
		$this->assertEquals('notEmpty', $rule->rule);
1807
 
1808
		$titleValidator = $Validator['body'];
1809
		$this->assertEquals('body', $titleValidator->field);
1810
		$this->assertCount(1, $titleValidator->getRules());
1811
		$rule = current($titleValidator->getRules());
1812
		$this->assertEquals('notEmpty', $rule->rule);
1813
 
1814
		$titleValidator = $Validator['user_id'];
1815
		$this->assertEquals('user_id', $titleValidator->field);
1816
		$this->assertCount(1, $titleValidator->getRules());
1817
		$rule = current($titleValidator->getRules());
1818
		$this->assertEquals('numeric', $rule->rule);
1819
	}
1820
 
1821
/**
1822
 * Tests it is possible to check for validation sets for a field using an array inteface
1823
 *
1824
 * @return void
1825
 */
1826
	public function testArrayAccessExists() {
1827
		$TestModel = new Article();
1828
		$Validator = $TestModel->validator();
1829
 
1830
		$this->assertTrue(isset($Validator['title']));
1831
		$this->assertTrue(isset($Validator['body']));
1832
		$this->assertTrue(isset($Validator['user_id']));
1833
		$this->assertFalse(isset($Validator['other']));
1834
	}
1835
 
1836
/**
1837
 * Tests it is possible to set validation rules for a field using an array inteface
1838
 *
1839
 * @return void
1840
 */
1841
	public function testArrayAccessSet() {
1842
		$TestModel = new Article();
1843
		$Validator = $TestModel->validator();
1844
 
1845
		$set = array(
1846
			'numeric' => array('rule' => 'numeric', 'allowEmpty' => false),
1847
			'between' => array('rule' => array('lengthBetween', 1, 5), 'allowEmpty' => false),
1848
		);
1849
		$Validator['other'] = $set;
1850
		$rules = $Validator['other'];
1851
		$this->assertEquals('other', $rules->field);
1852
 
1853
		$validators = $rules->getRules();
1854
		$this->assertCount(2, $validators);
1855
		$this->assertEquals('numeric', $validators['numeric']->rule);
1856
		$this->assertEquals(array('lengthBetween', 1, 5), $validators['between']->rule);
1857
 
1858
		$Validator['new'] = new CakeValidationSet('new', $set, array());
1859
		$rules = $Validator['new'];
1860
		$this->assertEquals('new', $rules->field);
1861
 
1862
		$validators = $rules->getRules();
1863
		$this->assertCount(2, $validators);
1864
		$this->assertEquals('numeric', $validators['numeric']->rule);
1865
		$this->assertEquals(array('lengthBetween', 1, 5), $validators['between']->rule);
1866
	}
1867
 
1868
/**
1869
 * Tests it is possible to unset validation rules
1870
 *
1871
 * @return void
1872
 */
1873
	public function testArrayAccessUset() {
1874
		$TestModel = new Article();
1875
		$Validator = $TestModel->validator();
1876
 
1877
		$this->assertTrue(isset($Validator['title']));
1878
		unset($Validator['title']);
1879
		$this->assertFalse(isset($Validator['title']));
1880
	}
1881
 
1882
/**
1883
 * Tests it is possible to iterate a validation object
1884
 *
1885
 * @return void
1886
 */
1887
	public function testIterator() {
1888
		$TestModel = new Article();
1889
		$Validator = $TestModel->validator();
1890
 
1891
		$i = 0;
1892
		foreach ($Validator as $field => $rules) {
1893
			if ($i === 0) {
1894
				$this->assertEquals('user_id', $field);
1895
			}
1896
			if ($i === 1) {
1897
				$this->assertEquals('title', $field);
1898
			}
1899
			if ($i === 2) {
1900
				$this->assertEquals('body', $field);
1901
			}
1902
			$this->assertInstanceOf('CakeValidationSet', $rules);
1903
			$i++;
1904
		}
1905
		$this->assertEquals(3, $i);
1906
	}
1907
 
1908
/**
1909
 * Tests countable interface in ModelValidator
1910
 *
1911
 * @return void
1912
 */
1913
	public function testCount() {
1914
		$TestModel = new Article();
1915
		$Validator = $TestModel->validator();
1916
		$this->assertCount(3, $Validator);
1917
 
1918
		$set = array(
1919
			'numeric' => array('rule' => 'numeric', 'allowEmpty' => false),
1920
			'range' => array('rule' => array('lengthBetween', 1, 5), 'allowEmpty' => false),
1921
		);
1922
		$Validator['other'] = $set;
1923
		$this->assertCount(4, $Validator);
1924
 
1925
		unset($Validator['title']);
1926
		$this->assertCount(3, $Validator);
1927
		unset($Validator['body']);
1928
		$this->assertCount(2, $Validator);
1929
	}
1930
 
1931
/**
1932
 * Tests it is possible to add validation rules
1933
 *
1934
 * @return void
1935
 */
1936
	public function testAddRule() {
1937
		$TestModel = new Article();
1938
		$Validator = $TestModel->validator();
1939
 
1940
		$Validator->add('other', 'numeric', array('rule' => 'numeric', 'allowEmpty' => false));
1941
		$Validator->add('other', 'between', array('rule' => array('lengthBetween', 1, 5), 'allowEmpty' => false));
1942
		$rules = $Validator['other'];
1943
		$this->assertEquals('other', $rules->field);
1944
 
1945
		$validators = $rules->getRules();
1946
		$this->assertCount(2, $validators);
1947
		$this->assertEquals('numeric', $validators['numeric']->rule);
1948
		$this->assertEquals(array('lengthBetween', 1, 5), $validators['between']->rule);
1949
	}
1950
 
1951
/**
1952
 * Tests it is possible to remove validation rules
1953
 *
1954
 * @return void
1955
 */
1956
	public function testRemoveRule() {
1957
		$TestModel = new Article();
1958
		$Validator = $TestModel->validator();
1959
 
1960
		$this->assertTrue(isset($Validator['title']));
1961
		$Validator->remove('title');
1962
		$this->assertFalse(isset($Validator['title']));
1963
 
1964
		$Validator->add('other', 'numeric', array('rule' => 'numeric', 'allowEmpty' => false));
1965
		$Validator->add('other', 'between', array('rule' => array('lengthBetween', 1, 5), 'allowEmpty' => false));
1966
		$this->assertTrue(isset($Validator['other']));
1967
 
1968
		$Validator->remove('other', 'numeric');
1969
		$this->assertTrue(isset($Validator['other']));
1970
		$this->assertFalse(isset($Validator['other']['numeric']));
1971
		$this->assertTrue(isset($Validator['other']['between']));
1972
	}
1973
 
1974
/**
1975
 * Tests validation callbacks are triggered
1976
 *
1977
 * @return void
1978
 */
1979
	public function testValidateCallbacks() {
1980
		$TestModel = $this->getMock('Article', array('beforeValidate', 'afterValidate'));
1981
		$TestModel->expects($this->once())->method('beforeValidate');
1982
		$TestModel->expects($this->once())->method('afterValidate');
1983
 
1984
		$TestModel->set(array('title' => '', 'body' => 'body'));
1985
		$TestModel->validates();
1986
	}
1987
 
1988
/**
1989
 * Tests that altering data in a beforeValidate callback will lead to saving those
1990
 * values in database
1991
 *
1992
 * @return void
1993
 */
1994
	public function testValidateFirstWithBeforeValidate() {
1995
		$this->loadFixtures('Article', 'User');
1996
		$model = new CustomArticle();
1997
		$model->validate = array(
1998
			'title' => array(
1999
				'notempty' => array(
2000
					'rule' => 'notEmpty',
2001
					'required' => true,
2002
					'allowEmpty' => false
2003
				)
2004
			)
2005
		);
2006
		$data = array(
2007
			'CustomArticle' => array(
2008
				'body' => 'foo0'
2009
			)
2010
		);
2011
		$result = $model->saveAll($data, array('validate' => 'first'));
2012
		$this->assertTrue($result);
2013
 
2014
		$this->assertFalse($model->findMethods['unPublished'], 'beforeValidate was run twice');
2015
 
2016
		$model->findMethods['unPublished'] = true;
2017
		$data = array(
2018
			'CustomArticle' => array(
2019
				'body' => 'foo1'
2020
			)
2021
		);
2022
		$result = $model->saveAll($data, array('validate' => 'first', 'deep' => true));
2023
		$this->assertTrue($result);
2024
		$title = $model->field('title', array('body' => 'foo1'));
2025
		$this->assertEquals('foo', $title);
2026
		$this->assertFalse($model->findMethods['unPublished'], 'beforeValidate was run twice');
2027
 
2028
		$data = array(
2029
			array('body' => 'foo2'),
2030
			array('body' => 'foo3'),
2031
			array('body' => 'foo4')
2032
		);
2033
 
2034
		$result = $model->saveAll($data, array('validate' => 'first', 'deep' => true));
2035
		$this->assertTrue($result);
2036
 
2037
		$this->assertEquals('foo', $model->field('title', array('body' => 'foo2')));
2038
		$this->assertEquals('foo', $model->field('title', array('body' => 'foo3')));
2039
		$this->assertEquals('foo', $model->field('title', array('body' => 'foo4')));
2040
	}
2041
 
2042
/**
2043
 * Tests that altering data in a beforeValidate callback will lead to saving those
2044
 * values in database
2045
 *
2046
 * @return void
2047
 */
2048
	public function testValidateFirstAssociatedWithBeforeValidate() {
2049
		$this->loadFixtures('Article', 'User');
2050
		$model = new CustomArticle();
2051
		$model->validate = array(
2052
			'title' => array(
2053
				'notempty' => array(
2054
					'rule' => 'notEmpty',
2055
					'required' => true
2056
				)
2057
			)
2058
		);
2059
		$articles = array(
2060
			array('body' => 'foo1'),
2061
			array('body' => 'foo2'),
2062
			array('body' => 'foo3')
2063
		);
2064
		$user = new User();
2065
		$user->bindModel(array('hasMany' => array('CustomArticle')));
2066
		$data = array(
2067
			'User' => array('user' => 'foo', 'password' => 'bar'),
2068
			'CustomArticle' => $articles
2069
		);
2070
		$result = $user->saveAll($data, array('validate' => 'first'));
2071
		$this->assertTrue($result);
2072
 
2073
		$this->assertEquals('foo', $model->field('title', array('body' => 'foo1')));
2074
		$this->assertEquals('foo', $model->field('title', array('body' => 'foo2')));
2075
		$this->assertEquals('foo', $model->field('title', array('body' => 'foo3')));
2076
	}
2077
 
2078
/**
2079
 * testValidateFirstWithDefaults method
2080
 *
2081
 * @return void
2082
 */
2083
	public function testFirstWithDefaults() {
2084
		$this->loadFixtures('Article', 'Tag', 'Comment', 'User', 'ArticlesTag');
2085
		$TestModel = new Article();
2086
 
2087
		$result = $TestModel->find('first', array(
2088
			'conditions' => array('Article.id' => 1)
2089
		));
2090
		$expected = array(
2091
			'Article' => array(
2092
				'id' => 1,
2093
				'user_id' => 1,
2094
				'title' => 'First Article',
2095
				'body' => 'First Article Body',
2096
				'published' => 'Y',
2097
				'created' => '2007-03-18 10:39:23'
2098
			),
2099
		);
2100
		unset($result['Article']['updated']);
2101
		$this->assertEquals($expected['Article'], $result['Article']);
2102
 
2103
		$data = array(
2104
			'Article' => array(
2105
				'id' => 1,
2106
				'title' => 'First Article (modified)'
2107
			),
2108
			'Comment' => array(
2109
				array('comment' => 'Article comment', 'user_id' => 1)
2110
			)
2111
		);
2112
		$result = $TestModel->saveAll($data, array('validate' => 'first'));
2113
		$this->assertTrue($result);
2114
 
2115
		$result = $TestModel->find('first', array(
2116
			'conditions' => array('Article.id' => 1)
2117
		));
2118
		$expected['Article']['title'] = 'First Article (modified)';
2119
		unset($result['Article']['updated']);
2120
		$this->assertEquals($expected['Article'], $result['Article']);
2121
	}
2122
 
2123
	public function testAddMultipleRules() {
2124
		$TestModel = new Article();
2125
		$Validator = $TestModel->validator();
2126
 
2127
		$set = array(
2128
			'numeric' => array('rule' => 'numeric', 'allowEmpty' => false),
2129
			'between' => array('rule' => array('lengthBetween', 1, 5), 'allowEmpty' => false),
2130
		);
2131
 
2132
		$Validator->add('other', $set);
2133
		$rules = $Validator['other'];
2134
		$this->assertEquals('other', $rules->field);
2135
 
2136
		$validators = $rules->getRules();
2137
		$this->assertCount(2, $validators);
2138
		$this->assertEquals('numeric', $validators['numeric']->rule);
2139
		$this->assertEquals(array('lengthBetween', 1, 5), $validators['between']->rule);
2140
 
2141
		$set = new CakeValidationSet('other', array(
2142
			'a' => array('rule' => 'numeric', 'allowEmpty' => false),
2143
			'b' => array('rule' => array('lengthBetween', 1, 5), 'allowEmpty' => false),
2144
		));
2145
 
2146
		$Validator->add('other', $set);
2147
		$this->assertSame($set, $Validator->getField('other'));
2148
	}
2149
 
2150
/**
2151
 * Test that rules are parsed correctly when calling getField()
2152
 *
2153
 * @return void
2154
 */
2155
	public function testValidator() {
2156
		$TestModel = new Article();
2157
		$Validator = $TestModel->validator();
2158
 
2159
		$result = $Validator->getField();
2160
		$expected = array('user_id', 'title', 'body');
2161
		$this->assertEquals($expected, array_keys($result));
2162
		$this->assertTrue($result['user_id'] instanceof CakeValidationSet);
2163
 
2164
		$result = $TestModel->validator()->getField('title');
2165
		$this->assertTrue($result instanceof CakeValidationSet);
2166
	}
2167
 
2168
/**
2169
 * Test that validator override works as expected
2170
 *
2171
 * @return void
2172
 */
2173
	public function testValidatorOverride() {
2174
		$TestModel = new Article();
2175
		$ValidatorA = new ModelValidator($TestModel);
2176
		$ValidatorB = new ModelValidator($TestModel);
2177
 
2178
		$TestModel->validator($ValidatorA);
2179
		$TestModel->validator($ValidatorB);
2180
 
2181
		$this->assertSame($ValidatorB, $TestModel->validator());
2182
		$this->assertNotSame($ValidatorA, $TestModel->validator());
2183
	}
2184
 
2185
/**
2186
 * Test that type hint exception is thrown
2187
 *
2188
 * @expectedException PHPUnit_Framework_Error
2189
 * @return void
2190
 */
2191
	public function testValidatorTypehintException() {
2192
		new ModelValidator('asdasds');
2193
	}
2194
 
2195
/**
2196
 * Tests that altering data in a beforeValidate callback will lead to saving those
2197
 * values in database, this time with belongsTo associations
2198
 *
2199
 * @return void
2200
 */
2201
	public function testValidateFirstAssociatedWithBeforeValidate2() {
2202
		$this->loadFixtures('Article', 'User');
2203
		$model = new CustomArticle();
2204
		$model->validate = array(
2205
			'title' => array(
2206
				'notempty' => array(
2207
					'rule' => 'notEmpty',
2208
					'required' => true
2209
				)
2210
			)
2211
		);
2212
 
2213
		$data = array(
2214
			'User' => array('user' => 'foo', 'password' => 'bar'),
2215
			'CustomArticle' => array(
2216
				'body' => 'a test'
2217
			)
2218
		);
2219
		$result = $model->saveAll($data, array('validate' => 'first'));
2220
		$this->assertTrue($result);
2221
 
2222
		$this->assertEquals('foo', $model->field('title', array('body' => 'a test')));
2223
	}
2224
 
2225
/**
2226
 * Testing you can dynamically add rules to a field, added this to dispel doubts
2227
 * after a presentation made to show off this new feature
2228
 *
2229
 * @return void
2230
 */
2231
	public function testDynamicValidationRuleBuilding() {
2232
		$model = new Article;
2233
		$validator = $model->validator();
2234
		$validator->add('body', 'isSpecial', array('rule' => 'special'));
2235
		$rules = $validator['body']->getRules();
2236
		$this->assertCount(2, $rules);
2237
		$this->assertEquals('special', $rules['isSpecial']->rule);
2238
		$validator['body']->setRule('isAwesome', array('rule' => 'awesome'));
2239
		$rules = $validator['body']->getRules();
2240
		$this->assertCount(3, $rules);
2241
		$this->assertEquals('awesome', $rules['isAwesome']->rule);
2242
	}
2243
 
2244
/**
2245
 * Test to ensure custom validation methods work with CakeValidationSet
2246
 *
2247
 * @return void
2248
 */
2249
	public function testCustomMethodsWithCakeValidationSet() {
2250
		$TestModel = new TestValidate();
2251
		$Validator = $TestModel->validator();
2252
 
2253
		$Validator->add('title', 'validateTitle', array(
2254
			'rule' => 'validateTitle',
2255
			'message' => 'That aint right',
2256
		));
2257
		$data = array('title' => 'notatitle');
2258
		$result = $Validator->getField('title')->validate($data);
2259
		$expected = array(0 => 'That aint right');
2260
		$this->assertEquals($expected, $result);
2261
 
2262
		$data = array('title' => 'title-is-good');
2263
		$result = $Validator->getField('title')->validate($data);
2264
		$expected = array();
2265
		$this->assertEquals($expected, $result);
2266
	}
2267
 
2268
	public function testCustomMethodWithEmptyValue() {
2269
		$this->loadFixtures('Article');
2270
 
2271
		$model = $this->getMock('Article', array('isLegit'));
2272
		$model->validate = array(
2273
			'title' => array(
2274
				'custom' => array(
2275
					'rule' => array('isLegit'),
2276
					'message' => 'is no good'
2277
				)
2278
			)
2279
		);
2280
		$model->expects($this->once())
2281
			->method('isLegit')
2282
			->will($this->returnValue(false));
2283
 
2284
		$model->set(array('title' => ''));
2285
		$this->assertFalse($model->validates());
2286
	}
2287
 
2288
/**
2289
 * Test validateAssociated with atomic=false & deep=true
2290
 *
2291
 * @return void
2292
 */
2293
	public function testValidateAssociatedAtomicFalseDeepTrueWithErrors() {
2294
		$this->loadFixtures('Comment', 'Article', 'User', 'Attachment');
2295
		$Attachment = ClassRegistry::init('Attachment');
2296
		$Attachment->Comment->validator()->add('comment', array(
2297
			array('rule' => 'notEmpty')
2298
		));
2299
		$Attachment->Comment->User->bindModel(array(
2300
			'hasMany' => array(
2301
				'Article',
2302
				'Comment'
2303
			)),
2304
			false
2305
		);
2306
 
2307
		$data = array(
2308
			'Attachment' => array(
2309
				'attachment' => 'text',
2310
				'Comment' => array(
2311
					'comment' => '',
2312
					'published' => 'N',
2313
					'User' => array(
2314
						'user' => 'Foo',
2315
						'password' => 'mypassword',
2316
						'Comment' => array(
2317
							array(
2318
								'comment' => ''
2319
							)
2320
						)
2321
					)
2322
				)
2323
			)
2324
		);
2325
		$result = $Attachment->validateAssociated($data, array('atomic' => false, 'deep' => true));
2326
 
2327
		$result = $Attachment->validationErrors;
2328
		$expected = array(
2329
			'Comment' => array(
2330
				'comment' => array(
2331
 
2332
				),
2333
				'User' => array(
2334
					'Comment' => array(
2335
 
2336
							'comment' => array(
2337
 
2338
							),
2339
						),
2340
					),
2341
				),
2342
			),
2343
		);
2344
		$this->assertEquals($expected, $result);
2345
	}
2346
 
2347
/**
2348
 * Test validateMany with atomic=false & deep=true
2349
 *
2350
 * @return void
2351
 */
2352
	public function testValidateManyAtomicFalseDeepTrueWithErrors() {
2353
		$this->loadFixtures('Comment', 'Article', 'User');
2354
		$Article = ClassRegistry::init('Article');
2355
		$Article->Comment->validator()->add('comment', array(
2356
			array('rule' => 'notEmpty')
2357
		));
2358
 
2359
		$data = array(
2360
			array(
2361
				'Article' => array(
2362
					'user_id' => 1,
2363
					'title' => 'Foo',
2364
					'body' => 'text',
2365
					'published' => 'N'
2366
				),
2367
				'Comment' => array(
2368
					array(
2369
						'user_id' => 1,
2370
						'comment' => 'Baz',
2371
						'published' => 'N',
2372
					)
2373
				),
2374
			),
2375
			array(
2376
				'Article' => array(
2377
					'user_id' => 1,
2378
					'title' => 'Bar',
2379
					'body' => 'text',
2380
					'published' => 'N'
2381
				),
2382
				'Comment' => array(
2383
					array(
2384
						'user_id' => 1,
2385
						'comment' => '',
2386
						'published' => 'N',
2387
					)
2388
				),
2389
			),
2390
		);
2391
		$Article->validateMany($data, array('atomic' => false, 'deep' => true));
2392
 
2393
		$result = $Article->validationErrors;
2394
		$expected = array(
2395
			1 => array(
2396
				'Comment' => array(
2397
 
2398
						'comment' => array(
2399
 
2400
						),
2401
					),
2402
				),
2403
			),
2404
		);
2405
		$this->assertEquals($expected, $result);
2406
	}
2407
 
2408
/**
2409
 * Test the isUnique method when used as a validator for multiple fields.
2410
 *
2411
 * @return void
2412
 */
2413
	public function testIsUniqueValidator() {
2414
		$this->loadFixtures('Article');
2415
		$Article = ClassRegistry::init('Article');
2416
		$Article->validate = array(
2417
			'user_id' => array(
2418
				'duplicate' => array(
2419
					'rule' => array('isUnique', array('user_id', 'title'), false)
2420
				)
2421
			)
2422
		);
2423
		$data = array(
2424
			'user_id' => 1,
2425
			'title' => 'First Article',
2426
		);
2427
		$Article->create($data);
2428
		$this->assertFalse($Article->validates(), 'Contains a dupe');
2429
 
2430
		$data = array(
2431
			'user_id' => 1,
2432
			'title' => 'Unique Article',
2433
		);
2434
		$Article->create($data);
2435
		$this->assertTrue($Article->validates(), 'Should pass');
2436
 
2437
		$Article->validate = array(
2438
			'user_id' => array(
2439
				'duplicate' => array(
2440
					'rule' => array('isUnique', array('user_id', 'title'))
2441
				)
2442
			)
2443
		);
2444
		$data = array(
2445
			'user_id' => 1,
2446
			'title' => 'Unique Article',
2447
		);
2448
		$Article->create($data);
2449
		$this->assertFalse($Article->validates(), 'Should fail, conditions are combined with or');
2450
	}
2451
 
2452
/**
2453
 * Test backward compatibility of the isUnique method when used as a validator for a single field.
2454
 *
2455
 * @return void
2456
 */
2457
	public function testBackwardCompatIsUniqueValidator() {
2458
		$this->loadFixtures('Article');
2459
		$Article = ClassRegistry::init('Article');
2460
		$Article->validate = array(
2461
			'title' => array(
2462
				'duplicate' => array(
2463
					'rule' => 'isUnique',
2464
					'message' => 'Title must be unique',
2465
				),
2466
				'minLength' => array(
2467
					'rule' => array('minLength', 1),
2468
					'message' => 'Title cannot be empty',
2469
				),
2470
			)
2471
		);
2472
		$data = array(
2473
			'title' => 'First Article',
2474
		);
2475
		$data = $Article->create($data);
2476
		$this->assertFalse($Article->validates(), 'Contains a dupe');
2477
	}
2478
 
2479
}
2480
 
2481
/**
2482
 * Behavior for testing validation rules.
2483
 */
2484
class ValidationRuleBehavior extends ModelBehavior {
2485
 
2486
	public function setup(Model $Model, $config = array()) {
2487
		$this->settings[$Model->alias] = $config;
2488
	}
2489
 
2490
	public function beforeValidate(Model $Model, $options = array()) {
2491
		$fields = $this->settings[$Model->alias]['fields'];
2492
		foreach ($fields as $field) {
2493
			$Model->whitelist[] = $field;
2494
		}
2495
	}
2496
 
2497
}