統計
| ブランチ: | リビジョン:

pictcode / lib / Cake / Test / Case / Model / ModelValidationTest.php @ 0b1b8047

履歴 | 表示 | アノテート | ダウンロード (70.861 KB)

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' => 'notBlank'),
214
                        'body' => 'notBlank'
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' => 'notBlank'
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' => 'notBlank'
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() still performs correctly when useTable = false on the model.
559
 *
560
 * @return void
561
 */
562
        public function testValidatesWithNoTable() {
563
                $TestModel = new TheVoid();
564
                $TestModel->validate = array(
565
                        'title' => array(
566
                                'notEmpty' => array(
567
                                        'rule' => array('notBlank'),
568
                                        'required' => true,
569
                                ),
570
                                'tooShort' => array(
571
                                        'rule' => array('minLength', 10),
572
                                ),
573
                        ),
574
                );
575
                $data = array(
576
                        'TheVoid' => array(
577
                                'title' => 'too short',
578
                        ),
579
                );
580
                $TestModel->create($data);
581
                $result = $TestModel->validates();
582
                $this->assertFalse($result);
583

    
584
                $data = array(
585
                        'TheVoid' => array(
586
                                'id' => '1',
587
                                'title' => 'A good title',
588
                        ),
589
                );
590
                $TestModel->create($data);
591
                $result = $TestModel->validates();
592
                $this->assertTrue($result);
593
        }
594

    
595
/**
596
 * test that validates() checks all the 'with' associations as well for validation
597
 * as this can cause partial/wrong data insertion.
598
 *
599
 * @return void
600
 */
601
        public function testValidatesWithAssociations() {
602
                $this->loadFixtures('Something', 'SomethingElse', 'JoinThing');
603
                $data = array(
604
                        'Something' => array(
605
                                'id' => 5,
606
                                'title' => 'Extra Fields',
607
                                'body' => 'Extra Fields Body',
608
                                'published' => '1'
609
                        ),
610
                        'SomethingElse' => array(
611
                                array('something_else_id' => 1, 'doomed' => '')
612
                        )
613
                );
614

    
615
                $Something = new Something();
616
                $JoinThing = $Something->JoinThing;
617

    
618
                $JoinThing->validate = array('doomed' => array('rule' => 'notBlank'));
619

    
620
                $expectedError = array('doomed' => array('This field cannot be left blank'));
621

    
622
                $Something->create();
623
                $result = $Something->save($data);
624
                $this->assertFalse($result, 'Save occurred even when with models failed. %s');
625
                $this->assertEquals($expectedError, $JoinThing->validationErrors);
626
                $count = $Something->find('count', array('conditions' => array('Something.id' => $data['Something']['id'])));
627
                $this->assertSame(0, $count);
628

    
629
                $data = array(
630
                        'Something' => array(
631
                                'id' => 5,
632
                                'title' => 'Extra Fields',
633
                                'body' => 'Extra Fields Body',
634
                                'published' => '1'
635
                        ),
636
                        'SomethingElse' => array(
637
                                array('something_else_id' => 1, 'doomed' => 1),
638
                                array('something_else_id' => 1, 'doomed' => '')
639
                        )
640
                );
641
                $Something->create();
642
                $result = $Something->save($data);
643
                $this->assertFalse($result, 'Save occurred even when with models failed. %s');
644

    
645
                $joinRecords = $JoinThing->find('count', array(
646
                        'conditions' => array('JoinThing.something_id' => $data['Something']['id'])
647
                ));
648
                $this->assertEquals(0, $joinRecords, 'Records were saved on the join table. %s');
649
        }
650

    
651
/**
652
 * Test that if a behavior modifies the model's whitelist validation gets triggered
653
 * properly for those fields.
654
 *
655
 * @return void
656
 */
657
        public function testValidateWithFieldListAndBehavior() {
658
                $TestModel = new ValidationTest1();
659
                $TestModel->validate = array(
660
                        'title' => array(
661
                                'rule' => 'notBlank',
662
                        ),
663
                        'name' => array(
664
                                'rule' => 'notBlank',
665
                ));
666
                $TestModel->Behaviors->attach('ValidationRule', array('fields' => array('name')));
667

    
668
                $data = array(
669
                        'title' => '',
670
                        'name' => '',
671
                );
672
                $result = $TestModel->save($data, array('fieldList' => array('title')));
673
                $this->assertFalse($result);
674

    
675
                $expected = array('title' => array('This field cannot be left blank'), 'name' => array('This field cannot be left blank'));
676
                $this->assertEquals($expected, $TestModel->validationErrors);
677
        }
678

    
679
/**
680
 * test that saveAll and with models with validation interact well
681
 *
682
 * @return void
683
 */
684
        public function testValidatesWithModelsAndSaveAll() {
685
                $this->loadFixtures('Something', 'SomethingElse', 'JoinThing');
686
                $data = array(
687
                        'Something' => array(
688
                                'id' => 5,
689
                                'title' => 'Extra Fields',
690
                                'body' => 'Extra Fields Body',
691
                                'published' => '1'
692
                        ),
693
                        'SomethingElse' => array(
694
                                array('something_else_id' => 1, 'doomed' => '')
695
                        )
696
                );
697
                $Something = new Something();
698
                $JoinThing = $Something->JoinThing;
699

    
700
                $JoinThing->validate = array('doomed' => array('rule' => 'notBlank'));
701
                $expectedError = array('doomed' => array('This field cannot be left blank'));
702

    
703
                $Something->create();
704
                $result = $Something->saveAll($data, array('validate' => 'only'));
705
                $this->assertFalse($result);
706
                $result = $Something->validateAssociated($data);
707
                $this->assertFalse($result);
708
                $this->assertEquals($expectedError, $JoinThing->validationErrors);
709
                $result = $Something->validator()->validateAssociated($data);
710
                $this->assertFalse($result);
711

    
712
                $Something->create();
713
                $result = $Something->saveAll($data, array('validate' => 'first'));
714
                $this->assertFalse($result);
715
                $this->assertEquals($expectedError, $JoinThing->validationErrors);
716

    
717
                $count = $Something->find('count', array('conditions' => array('Something.id' => $data['Something']['id'])));
718
                $this->assertSame(0, $count);
719

    
720
                $joinRecords = $JoinThing->find('count', array(
721
                        'conditions' => array('JoinThing.something_id' => $data['Something']['id'])
722
                ));
723
                $this->assertEquals(0, $joinRecords, 'Records were saved on the join table. %s');
724
        }
725

    
726
/**
727
 * test that saveAll and with models at initial insert (no id has set yet)
728
 * with validation interact well
729
 *
730
 * @return void
731
 */
732
        public function testValidatesWithModelsAndSaveAllWithoutId() {
733
                $this->loadFixtures('Post', 'Author');
734

    
735
                $data = array(
736
                        'Author' => array(
737
                                'name' => 'Foo Bar',
738
                        ),
739
                        'Post' => array(
740
                                array('title' => 'Hello'),
741
                                array('title' => 'World'),
742
                        )
743
                );
744
                $Author = new Author();
745
                $Post = $Author->Post;
746

    
747
                $Post->validate = array('author_id' => array('rule' => 'numeric'));
748

    
749
                $Author->create();
750
                $result = $Author->saveAll($data, array('validate' => 'only'));
751
                $this->assertTrue($result);
752
                $result = $Author->validateAssociated($data);
753
                $this->assertTrue($result);
754
                $this->assertTrue($result);
755

    
756
                $Author->create();
757
                $result = $Author->saveAll($data, array('validate' => 'first'));
758
                $this->assertTrue($result);
759
                $this->assertNotNull($Author->id);
760

    
761
                $id = $Author->id;
762
                $count = $Author->find('count', array('conditions' => array('Author.id' => $id)));
763
                $this->assertSame(1, $count);
764

    
765
                $count = $Post->find('count', array(
766
                        'conditions' => array('Post.author_id' => $id)
767
                ));
768
                $this->assertEquals($count, count($data['Post']));
769
        }
770

    
771
/**
772
 * Test that missing validation methods trigger errors in development mode.
773
 * Helps to make development easier.
774
 *
775
 * @expectedException PHPUnit_Framework_Error
776
 * @return void
777
 */
778
        public function testMissingValidationErrorTriggering() {
779
                Configure::write('debug', 2);
780

    
781
                $TestModel = new ValidationTest1();
782
                $TestModel->create(array('title' => 'foo'));
783
                $TestModel->validate = array(
784
                        'title' => array(
785
                                'rule' => array('thisOneBringsThePain'),
786
                                'required' => true
787
                        )
788
                );
789
                $TestModel->invalidFields(array('fieldList' => array('title')));
790
        }
791

    
792
/**
793
 * Test placeholder replacement when validation message is an array
794
 *
795
 * @return void
796
 */
797
        public function testValidationMessageAsArray() {
798
                $TestModel = new ValidationTest1();
799
                $TestModel->validate = array(
800
                        'title' => array(
801
                                'minLength' => array(
802
                                        'rule' => array('minLength', 6),
803
                                        'required' => true,
804
                                        'message' => 'Minimum length allowed is %d chars',
805
                                        'last' => false
806
                                ),
807
                                'between' => array(
808
                                        'rule' => array('lengthBetween', 5, 15),
809
                                        'message' => array('You may enter up to %s chars (minimum is %s chars)', 14, 6)
810
                                )
811
                        )
812
                );
813

    
814
                $TestModel->create();
815
                $expected = array(
816
                        'title' => array(
817
                                'Minimum length allowed is 6 chars',
818
                        )
819
                );
820
                $TestModel->invalidFields();
821
                $this->assertEquals($expected, $TestModel->validationErrors);
822

    
823
                $TestModel->create(array('title' => 'foo'));
824
                $expected = array(
825
                        'title' => array(
826
                                'Minimum length allowed is 6 chars',
827
                                'You may enter up to 14 chars (minimum is 6 chars)'
828
                        )
829
                );
830
                $TestModel->invalidFields();
831
                $this->assertEquals($expected, $TestModel->validationErrors);
832
        }
833

    
834
/**
835
 * Test validation message translation
836
 *
837
 * @return void
838
 */
839
        public function testValidationMessageTranslation() {
840
                $lang = Configure::read('Config.language');
841
                Configure::write('Config.language', 'en');
842
                App::build(array(
843
                        'Locale' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Locale' . DS),
844
                ), App::RESET);
845

    
846
                $TestModel = new ValidationTest1();
847
                $TestModel->validationDomain = 'validation_messages';
848
                $TestModel->validate = array(
849
                        'title' => array(
850
                                array(
851
                                        'rule' => array('customValidationMethod', 'arg1'),
852
                                        'required' => true,
853
                                        'message' => 'Validation failed: %s'
854
                                )
855
                        )
856
                );
857

    
858
                $TestModel->create();
859
                $expected = array(
860
                        'title' => array(
861
                                'Translated validation failed: Translated arg1',
862
                        )
863
                );
864
                $TestModel->invalidFields();
865
                $this->assertEquals($expected, $TestModel->validationErrors);
866

    
867
                $TestModel->validationDomain = 'default';
868
                Configure::write('Config.language', $lang);
869
                App::build();
870
        }
871

    
872
/**
873
 * Test for 'on' => [create|update] in validation rules.
874
 *
875
 * @return void
876
 */
877
        public function testStateValidation() {
878
                $this->loadFixtures('Article');
879
                $Article = new Article();
880

    
881
                $data = array(
882
                        'Article' => array(
883
                                'title' => '',
884
                                'body' => 'Extra Fields Body',
885
                                'published' => '1'
886
                        )
887
                );
888

    
889
                $Article->validate = array(
890
                        'title' => array(
891
                                'notBlank' => array(
892
                                        'rule' => 'notBlank',
893
                                        'on' => 'create'
894
                                )
895
                        )
896
                );
897

    
898
                $Article->create($data);
899
                $this->assertFalse($Article->validates());
900

    
901
                $Article->save(null, array('validate' => false));
902
                $data['Article']['id'] = $Article->id;
903
                $Article->set($data);
904
                $this->assertTrue($Article->validates());
905

    
906
                unset($data['Article']['id']);
907
                $Article->validate = array(
908
                        'title' => array(
909
                                'notBlank' => array(
910
                                        'rule' => 'notBlank',
911
                                        'on' => 'update'
912
                                )
913
                        )
914
                );
915

    
916
                $Article->create($data);
917
                $this->assertTrue($Article->validates());
918

    
919
                $Article->save(null, array('validate' => false));
920
                $data['Article']['id'] = $Article->id;
921
                $Article->set($data);
922
                $this->assertFalse($Article->validates());
923
        }
924

    
925
/**
926
 * Test for 'required' => [create|update] in validation rules.
927
 *
928
 * @return void
929
 */
930
        public function testStateRequiredValidation() {
931
                $this->loadFixtures('Article');
932
                $Article = new Article();
933

    
934
                // no title field present
935
                $data = array(
936
                        'Article' => array(
937
                                'body' => 'Extra Fields Body',
938
                                'published' => '1'
939
                        )
940
                );
941

    
942
                $Article->validate = array(
943
                        'title' => array(
944
                                'notBlank' => array(
945
                                        'rule' => 'notBlank',
946
                                        'required' => 'create'
947
                                )
948
                        )
949
                );
950

    
951
                $Article->create($data);
952
                $this->assertFalse($Article->validates());
953

    
954
                $Article->save(null, array('validate' => false));
955
                $data['Article']['id'] = $Article->id;
956
                $Article->set($data);
957
                $this->assertTrue($Article->validates());
958

    
959
                unset($data['Article']['id']);
960
                $Article->validate = array(
961
                        'title' => array(
962
                                'notBlank' => array(
963
                                        'rule' => 'notBlank',
964
                                        'required' => 'update'
965
                                )
966
                        )
967
                );
968

    
969
                $Article->create($data);
970
                $this->assertTrue($Article->validates());
971

    
972
                $Article->save(null, array('validate' => false));
973
                $data['Article']['id'] = $Article->id;
974
                $Article->set($data);
975
                $this->assertFalse($Article->validates());
976
        }
977

    
978
/**
979
 * Test that 'required' and 'on' are not conflicting
980
 *
981
 * @return void
982
 */
983
        public function testOnRequiredConflictValidation() {
984
                $this->loadFixtures('Article');
985
                $Article = new Article();
986

    
987
                // no title field present
988
                $data = array(
989
                        'Article' => array(
990
                                'body' => 'Extra Fields Body',
991
                                'published' => '1'
992
                        )
993
                );
994

    
995
                $Article->validate = array(
996
                        'title' => array(
997
                                'notBlank' => array(
998
                                        'rule' => 'notBlank',
999
                                        'required' => 'create',
1000
                                        'on' => 'create'
1001
                                )
1002
                        )
1003
                );
1004

    
1005
                $Article->create($data);
1006
                $this->assertFalse($Article->validates());
1007

    
1008
                $Article->validate = array(
1009
                        'title' => array(
1010
                                'notBlank' => array(
1011
                                        'rule' => 'notBlank',
1012
                                        'required' => 'update',
1013
                                        'on' => 'create'
1014
                                )
1015
                        )
1016
                );
1017

    
1018
                $Article->create($data);
1019
                $this->assertTrue($Article->validates());
1020

    
1021
                $Article->validate = array(
1022
                        'title' => array(
1023
                                'notBlank' => array(
1024
                                        'rule' => 'notBlank',
1025
                                        'required' => 'create',
1026
                                        'on' => 'update'
1027
                                )
1028
                        )
1029
                );
1030

    
1031
                $Article->create($data);
1032
                $this->assertTrue($Article->validates());
1033

    
1034
                $Article->validate = array(
1035
                        'title' => array(
1036
                                'notBlank' => array(
1037
                                        'rule' => 'notBlank',
1038
                                        'required' => 'update',
1039
                                        'on' => 'update'
1040
                                )
1041
                        )
1042
                );
1043

    
1044
                $Article->create($data);
1045
                $this->assertTrue($Article->validates());
1046

    
1047
                $Article->validate = array(
1048
                        'title' => array(
1049
                                'notBlank' => array(
1050
                                        'rule' => 'notBlank',
1051
                                        'required' => 'create',
1052
                                        'on' => 'create'
1053
                                )
1054
                        )
1055
                );
1056

    
1057
                $Article->save(null, array('validate' => false));
1058
                $data['Article']['id'] = $Article->id;
1059
                $Article->set($data);
1060
                $this->assertTrue($Article->validates());
1061

    
1062
                $Article->validate = array(
1063
                        'title' => array(
1064
                                'notBlank' => array(
1065
                                        'rule' => 'notBlank',
1066
                                        'required' => 'update',
1067
                                        'on' => 'create'
1068
                                )
1069
                        )
1070
                );
1071

    
1072
                $Article->set($data);
1073
                $this->assertTrue($Article->validates());
1074

    
1075
                $Article->validate = array(
1076
                        'title' => array(
1077
                                'notBlank' => array(
1078
                                        'rule' => 'notBlank',
1079
                                        'required' => 'create',
1080
                                        'on' => 'update'
1081
                                )
1082
                        )
1083
                );
1084

    
1085
                $Article->set($data);
1086
                $this->assertTrue($Article->validates());
1087

    
1088
                $Article->validate = array(
1089
                        'title' => array(
1090
                                'notBlank' => array(
1091
                                        'rule' => 'notBlank',
1092
                                        'required' => 'update',
1093
                                        'on' => 'update'
1094
                                )
1095
                        )
1096
                );
1097

    
1098
                $Article->set($data);
1099
                $this->assertFalse($Article->validates());
1100
        }
1101

    
1102
/**
1103
 * testSaveAllDeepValidateOnly
1104
 * tests the validate methods with deeper recursive data
1105
 *
1106
 * @return void
1107
 */
1108
        public function testSaveAllDeepValidateOnly() {
1109
                $this->loadFixtures('Article', 'Comment', 'User', 'Attachment');
1110
                $TestModel = new Article();
1111
                $TestModel->hasMany['Comment']['order'] = array('Comment.created' => 'ASC');
1112
                $TestModel->hasAndBelongsToMany = array();
1113
                $TestModel->Comment->Attachment->validate['attachment'] = 'notBlank';
1114
                $TestModel->Comment->validate['comment'] = 'notBlank';
1115

    
1116
                $data = array(
1117
                        'Article' => array('id' => 2),
1118
                        'Comment' => array(
1119
                                array('comment' => 'First new comment', 'published' => 'Y', 'User' => array('user' => 'newuser', 'password' => 'newuserpass')),
1120
                                array('comment' => 'Second new comment', 'published' => 'Y', 'user_id' => 2)
1121
                        )
1122
                );
1123
                $result = $TestModel->saveAll($data, array('validate' => 'only', 'deep' => true));
1124
                $this->assertTrue($result);
1125
                $result = $TestModel->validateAssociated($data, array('deep' => true));
1126
                $this->assertTrue($result);
1127

    
1128
                $data = array(
1129
                        'Article' => array('id' => 2),
1130
                        'Comment' => array(
1131
                                array('comment' => 'First new comment', 'published' => 'Y', 'User' => array('user' => '', 'password' => 'newuserpass')),
1132
                                array('comment' => 'Second new comment', 'published' => 'Y', 'user_id' => 2)
1133
                        )
1134
                );
1135
                $result = $TestModel->saveAll($data, array('validate' => 'only', 'deep' => true));
1136
                $this->assertFalse($result);
1137
                $result = $TestModel->validateAssociated($data, array('deep' => true));
1138
                $this->assertFalse($result);
1139

    
1140
                $data = array(
1141
                        'Article' => array('id' => 2),
1142
                        'Comment' => array(
1143
                                array('comment' => 'First new comment', 'published' => 'Y', 'User' => array('user' => 'newuser', 'password' => 'newuserpass')),
1144
                                array('comment' => 'Second new comment', 'published' => 'Y', 'user_id' => 2)
1145
                        )
1146
                );
1147
                $expected = array(
1148
                        'Article' => true,
1149
                        'Comment' => array(
1150
                                true,
1151
                                true
1152
                        )
1153
                );
1154
                $result = $TestModel->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => true));
1155
                $this->assertSame($expected, $result);
1156
                $result = $TestModel->validateAssociated($data, array('atomic' => false, 'deep' => true));
1157
                $this->assertSame($expected, $result);
1158

    
1159
                $data = array(
1160
                        'Article' => array('id' => 2),
1161
                        'Comment' => array(
1162
                                array('comment' => 'First new comment', 'published' => 'Y', 'User' => array('user' => '', 'password' => 'newuserpass')),
1163
                                array('comment' => 'Second new comment', 'published' => 'Y', 'user_id' => 2)
1164
                        )
1165
                );
1166
                $expected = array(
1167
                        'Article' => true,
1168
                        'Comment' => array(
1169
                                false,
1170
                                true
1171
                        )
1172
                );
1173
                $result = $TestModel->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => true));
1174
                $this->assertSame($expected, $result);
1175
                $result = $TestModel->validateAssociated($data, array('atomic' => false, 'deep' => true));
1176
                $this->assertSame($expected, $result);
1177

    
1178
                $data = array(
1179
                        'Article' => array('id' => 2),
1180
                        'Comment' => array(
1181
                                array('comment' => 'Third new comment', 'published' => 'Y', 'user_id' => 5),
1182
                                array('comment' => 'Fourth new comment', 'published' => 'Y', 'user_id' => 2, 'Attachment' => array('attachment' => 'deepsaved'))
1183
                        )
1184
                );
1185
                $result = $TestModel->saveAll($data, array('validate' => 'only', 'deep' => true));
1186
                $this->assertTrue($result);
1187
                $result = $TestModel->validateAssociated($data, array('deep' => true));
1188
                $this->assertTrue($result);
1189

    
1190
                $data = array(
1191
                        'Article' => array('id' => 2),
1192
                        'Comment' => array(
1193
                                array('comment' => 'Third new comment', 'published' => 'Y', 'user_id' => 5),
1194
                                array('comment' => 'Fourth new comment', 'published' => 'Y', 'user_id' => 2, 'Attachment' => array('attachment' => ''))
1195
                        )
1196
                );
1197
                $result = $TestModel->saveAll($data, array('validate' => 'only', 'deep' => true));
1198
                $this->assertFalse($result);
1199
                $result = $TestModel->validateAssociated($data, array('deep' => true));
1200
                $this->assertFalse($result);
1201

    
1202
                $data = array(
1203
                        'Article' => array('id' => 2),
1204
                        'Comment' => array(
1205
                                array('comment' => 'Third new comment', 'published' => 'Y', 'user_id' => 5),
1206
                                array('comment' => 'Fourth new comment', 'published' => 'Y', 'user_id' => 2, 'Attachment' => array('attachment' => 'deepsave'))
1207
                        )
1208
                );
1209
                $expected = array(
1210
                        'Article' => true,
1211
                        'Comment' => array(
1212
                                true,
1213
                                true
1214
                        )
1215
                );
1216
                $result = $TestModel->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => true));
1217
                $this->assertSame($expected, $result);
1218
                $result = $TestModel->validateAssociated($data, array('atomic' => false, 'deep' => true));
1219
                $this->assertSame($expected, $result);
1220

    
1221
                $data = array(
1222
                        'Article' => array('id' => 2),
1223
                        'Comment' => array(
1224
                                array('comment' => 'Third new comment', 'published' => 'Y', 'user_id' => 5),
1225
                                array('comment' => 'Fourth new comment', 'published' => 'Y', 'user_id' => 2, 'Attachment' => array('attachment' => ''))
1226
                        )
1227
                );
1228
                $expected = array(
1229
                        'Article' => true,
1230
                        'Comment' => array(
1231
                                true,
1232
                                false
1233
                        )
1234
                );
1235
                $result = $TestModel->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => true));
1236
                $this->assertSame($expected, $result);
1237
                $result = $TestModel->validateAssociated($data, array('atomic' => false, 'deep' => true));
1238
                $this->assertSame($expected, $result);
1239

    
1240
                $expected = array(
1241
                        'Comment' => array(
1242
                                1 => array(
1243
                                        'Attachment' => array(
1244
                                                'attachment' => array('This field cannot be left blank')
1245
                                        )
1246
                                )
1247
                        )
1248
                );
1249
                $result = $TestModel->validationErrors;
1250
                $this->assertSame($expected, $result);
1251

    
1252
                $data = array(
1253
                        'Attachment' => array(
1254
                                'attachment' => 'deepsave insert',
1255
                        ),
1256
                        'Comment' => array(
1257
                                'comment' => 'First comment deepsave insert',
1258
                                'published' => 'Y',
1259
                                'user_id' => 5,
1260
                                'Article' => array(
1261
                                        'title' => 'First Article deepsave insert',
1262
                                        'body' => 'First Article Body deepsave insert',
1263
                                        'User' => array(
1264
                                                'user' => 'deepsave',
1265
                                                'password' => 'magic'
1266
                                        ),
1267
                                ),
1268
                        )
1269
                );
1270

    
1271
                $result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'deep' => true));
1272
                $this->assertTrue($result);
1273
                $result = $TestModel->Comment->Attachment->validateAssociated($data, array('deep' => true));
1274
                $this->assertTrue($result);
1275

    
1276
                $expected = array(
1277
                        'Attachment' => true,
1278
                        'Comment' => true
1279
                );
1280
                $result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => true));
1281
                $this->assertSame($expected, $result);
1282
                $result = $TestModel->Comment->Attachment->validateAssociated($data, array('atomic' => false, 'deep' => true));
1283
                $this->assertSame($expected, $result);
1284

    
1285
                $data = array(
1286
                        'Attachment' => array(
1287
                                'attachment' => 'deepsave insert',
1288
                        ),
1289
                        'Comment' => array(
1290
                                'comment' => 'First comment deepsave insert',
1291
                                'published' => 'Y',
1292
                                'user_id' => 5,
1293
                                'Article' => array(
1294
                                        'title' => 'First Article deepsave insert',
1295
                                        'body' => 'First Article Body deepsave insert',
1296
                                        'User' => array(
1297
                                                'user' => '',
1298
                                                'password' => 'magic'
1299
                                        ),
1300
                                ),
1301
                        )
1302
                );
1303

    
1304
                $result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'deep' => true));
1305
                $this->assertFalse($result);
1306
                $result = $TestModel->Comment->Attachment->validateAssociated($data, array('deep' => true));
1307
                $this->assertFalse($result);
1308

    
1309
                $result = $TestModel->Comment->Attachment->validationErrors;
1310
                $expected = array(
1311
                        'Comment' => array(
1312
                                'Article' => array(
1313
                                        'User' => array(
1314
                                                'user' => array('This field cannot be left blank')
1315
                                        )
1316
                                )
1317
                        )
1318
                );
1319
                $this->assertSame($expected, $result);
1320

    
1321
                $expected = array(
1322
                        'Attachment' => true,
1323
                        'Comment' => false
1324
                );
1325
                $result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => true));
1326
                $this->assertEquals($expected, $result);
1327
                $result = $TestModel->Comment->Attachment->validateAssociated($data, array('atomic' => false, 'deep' => true));
1328
                $this->assertEquals($expected, $result);
1329

    
1330
                $data['Comment']['Article']['body'] = '';
1331
                $result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'deep' => true));
1332
                $this->assertFalse($result);
1333
                $result = $TestModel->Comment->Attachment->validateAssociated($data, array('deep' => true));
1334
                $this->assertFalse($result);
1335

    
1336
                $result = $TestModel->Comment->Attachment->validationErrors;
1337
                $expected = array(
1338
                        'Comment' => array(
1339
                                'Article' => array(
1340
                                        'body' => array('This field cannot be left blank'),
1341
                                        'User' => array(
1342
                                                'user' => array('This field cannot be left blank')
1343
                                        )
1344
                                )
1345
                        )
1346
                );
1347
                $this->assertSame($expected, $result);
1348

    
1349
                $expected = array(
1350
                        'Attachment' => true,
1351
                        'Comment' => false
1352
                );
1353
                $result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => true));
1354
                $this->assertEquals($expected, $result);
1355
                $result = $TestModel->Comment->Attachment->validateAssociated($data, array('atomic' => false, 'deep' => true));
1356
                $this->assertEquals($expected, $result);
1357

    
1358
                $data['Comment']['comment'] = '';
1359
                $result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'deep' => true));
1360
                $this->assertFalse($result);
1361
                $result = $TestModel->Comment->Attachment->validateAssociated($data, array('deep' => true));
1362
                $this->assertFalse($result);
1363

    
1364
                $result = $TestModel->Comment->Attachment->validationErrors;
1365
                $expected = array(
1366
                        'Comment' => array(
1367
                                'comment' => array('This field cannot be left blank'),
1368
                                'Article' => array(
1369
                                        'body' => array('This field cannot be left blank'),
1370
                                        'User' => array(
1371
                                                'user' => array('This field cannot be left blank')
1372
                                        )
1373
                                )
1374
                        )
1375
                );
1376
                $this->assertSame($expected, $result);
1377

    
1378
                $expected = array(
1379
                        'Attachment' => true,
1380
                        'Comment' => false
1381
                );
1382
                $result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => true));
1383
                $this->assertEquals($expected, $result);
1384
                $result = $TestModel->Comment->Attachment->validateAssociated($data, array('atomic' => false, 'deep' => true));
1385
                $this->assertEquals($expected, $result);
1386

    
1387
                $data['Attachment']['attachment'] = '';
1388
                $result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'deep' => true));
1389
                $this->assertFalse($result);
1390
                $result = $TestModel->Comment->Attachment->validateAssociated($data, array('deep' => true));
1391
                $this->assertFalse($result);
1392

    
1393
                $result = $TestModel->Comment->Attachment->validationErrors;
1394
                $expected = array(
1395
                        'attachment' => array('This field cannot be left blank'),
1396
                        'Comment' => array(
1397
                                'comment' => array('This field cannot be left blank'),
1398
                                'Article' => array(
1399
                                        'body' => array('This field cannot be left blank'),
1400
                                        'User' => array(
1401
                                                'user' => array('This field cannot be left blank')
1402
                                        )
1403
                                )
1404
                        )
1405
                );
1406
                $this->assertSame($expected, $result);
1407

    
1408
                $result = $TestModel->Comment->validationErrors;
1409
                $expected = array(
1410
                        'comment' => array('This field cannot be left blank'),
1411
                        'Article' => array(
1412
                                        'body' => array('This field cannot be left blank'),
1413
                                        'User' => array(
1414
                                                'user' => array('This field cannot be left blank')
1415
                                        )
1416
                                )
1417
                );
1418
                $this->assertSame($expected, $result);
1419

    
1420
                $expected = array(
1421
                        'Attachment' => false,
1422
                        'Comment' => false
1423
                );
1424
                $result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => true));
1425
                $this->assertEquals($expected, $result);
1426
                $result = $TestModel->Comment->Attachment->validateAssociated($data, array('atomic' => false, 'deep' => true));
1427
                $this->assertEquals($expected, $result);
1428
        }
1429

    
1430
/**
1431
 * testSaveAllNotDeepValidateOnly
1432
 * tests the validate methods to not validate deeper recursive data
1433
 *
1434
 * @return void
1435
 */
1436
        public function testSaveAllNotDeepValidateOnly() {
1437
                $this->loadFixtures('Article', 'Comment', 'User', 'Attachment');
1438
                $TestModel = new Article();
1439
                $TestModel->hasMany['Comment']['order'] = array('Comment.created' => 'ASC');
1440
                $TestModel->hasAndBelongsToMany = array();
1441
                $TestModel->Comment->Attachment->validate['attachment'] = 'notBlank';
1442
                $TestModel->Comment->validate['comment'] = 'notBlank';
1443

    
1444
                $data = array(
1445
                        'Article' => array('id' => 2, 'body' => ''),
1446
                        'Comment' => array(
1447
                                array('comment' => 'First new comment', 'published' => 'Y', 'User' => array('user' => '', 'password' => 'newuserpass')),
1448
                                array('comment' => 'Second new comment', 'published' => 'Y', 'user_id' => 2)
1449
                        )
1450
                );
1451
                $result = $TestModel->saveAll($data, array('validate' => 'only', 'deep' => false));
1452
                $this->assertFalse($result);
1453
                $result = $TestModel->validateAssociated($data, array('deep' => false));
1454
                $this->assertFalse($result);
1455

    
1456
                $expected = array('body' => array('This field cannot be left blank'));
1457
                $result = $TestModel->validationErrors;
1458
                $this->assertSame($expected, $result);
1459

    
1460
                $data = array(
1461
                        'Article' => array('id' => 2, 'body' => 'Ignore invalid user data'),
1462
                        'Comment' => array(
1463
                                array('comment' => 'First new comment', 'published' => 'Y', 'User' => array('user' => '', 'password' => 'newuserpass')),
1464
                                array('comment' => 'Second new comment', 'published' => 'Y', 'user_id' => 2)
1465
                        )
1466
                );
1467
                $result = $TestModel->saveAll($data, array('validate' => 'only', 'deep' => false));
1468
                $this->assertTrue($result);
1469
                $result = $TestModel->validateAssociated($data, array('deep' => false));
1470
                $this->assertTrue($result);
1471

    
1472
                $data = array(
1473
                        'Article' => array('id' => 2, 'body' => 'Ignore invalid user data'),
1474
                        'Comment' => array(
1475
                                array('comment' => 'First new comment', 'published' => 'Y', 'User' => array('user' => '', 'password' => 'newuserpass')),
1476
                                array('comment' => 'Second new comment', 'published' => 'Y', 'user_id' => 2)
1477
                        )
1478
                );
1479
                $expected = array(
1480
                        'Article' => true,
1481
                        'Comment' => array(
1482
                                true,
1483
                                true
1484
                        )
1485
                );
1486
                $result = $TestModel->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => false));
1487
                $this->assertSame($expected, $result);
1488
                $result = $TestModel->validateAssociated($data, array('atomic' => false, 'deep' => false));
1489
                $this->assertSame($expected, $result);
1490

    
1491
                $data = array(
1492
                        'Article' => array('id' => 2, 'body' => 'Ignore invalid attachment data'),
1493
                        'Comment' => array(
1494
                                array('comment' => 'Third new comment', 'published' => 'Y', 'user_id' => 5),
1495
                                array('comment' => 'Fourth new comment', 'published' => 'Y', 'user_id' => 2, 'Attachment' => array('attachment' => ''))
1496
                        )
1497
                );
1498
                $result = $TestModel->saveAll($data, array('validate' => 'only', 'deep' => false));
1499
                $this->assertTrue($result);
1500
                $result = $TestModel->validateAssociated($data, array('deep' => false));
1501
                $this->assertTrue($result);
1502

    
1503
                $data = array(
1504
                        'Article' => array('id' => 2, 'body' => 'Ignore invalid attachment data'),
1505
                        'Comment' => array(
1506
                                array('comment' => 'Third new comment', 'published' => 'Y', 'user_id' => 5),
1507
                                array('comment' => 'Fourth new comment', 'published' => 'Y', 'user_id' => 2, 'Attachment' => array('attachment' => ''))
1508
                        )
1509
                );
1510
                $expected = array(
1511
                        'Article' => true,
1512
                        'Comment' => array(
1513
                                true,
1514
                                true
1515
                        )
1516
                );
1517
                $result = $TestModel->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => false));
1518
                $this->assertSame($expected, $result);
1519
                $result = $TestModel->validateAssociated($data, array('atomic' => false, 'deep' => false));
1520
                $this->assertSame($expected, $result);
1521

    
1522
                $expected = array();
1523
                $result = $TestModel->validationErrors;
1524
                $this->assertSame($expected, $result);
1525

    
1526
                $data = array(
1527
                        'Attachment' => array(
1528
                                'attachment' => 'deepsave insert',
1529
                        ),
1530
                        'Comment' => array(
1531
                                'comment' => 'First comment deepsave insert',
1532
                                'published' => 'Y',
1533
                                'user_id' => 5,
1534
                                'Article' => array(
1535
                                        'title' => 'First Article deepsave insert ignored',
1536
                                        'body' => 'First Article Body deepsave insert',
1537
                                        'User' => array(
1538
                                                'user' => '',
1539
                                                'password' => 'magic'
1540
                                        ),
1541
                                ),
1542
                        )
1543
                );
1544

    
1545
                $result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'deep' => false));
1546
                $this->assertTrue($result);
1547
                $result = $TestModel->Comment->Attachment->validateAssociated($data, array('deep' => false));
1548
                $this->assertTrue($result);
1549

    
1550
                $result = $TestModel->Comment->Attachment->validationErrors;
1551
                $expected = array();
1552
                $this->assertSame($expected, $result);
1553

    
1554
                $expected = array(
1555
                        'Attachment' => true,
1556
                        'Comment' => true
1557
                );
1558
                $result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => false));
1559
                $this->assertEquals($expected, $result);
1560
                $result = $TestModel->Comment->Attachment->validateAssociated($data, array('atomic' => false, 'deep' => false));
1561
                $this->assertEquals($expected, $result);
1562

    
1563
                $data['Comment']['Article']['body'] = '';
1564
                $result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'deep' => false));
1565
                $this->assertTrue($result);
1566
                $result = $TestModel->Comment->Attachment->validateAssociated($data, array('deep' => false));
1567
                $this->assertTrue($result);
1568

    
1569
                $result = $TestModel->Comment->Attachment->validationErrors;
1570
                $expected = array();
1571
                $this->assertSame($expected, $result);
1572

    
1573
                $expected = array(
1574
                        'Attachment' => true,
1575
                        'Comment' => true
1576
                );
1577
                $result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => false));
1578
                $this->assertEquals($expected, $result);
1579
                $result = $TestModel->Comment->Attachment->validateAssociated($data, array('atomic' => false, 'deep' => false));
1580
                $this->assertEquals($expected, $result);
1581
        }
1582

    
1583
/**
1584
 * testValidateAssociated method
1585
 *
1586
 * @return void
1587
 */
1588
        public function testValidateAssociated() {
1589
                $this->loadFixtures('Comment', 'Attachment', 'Article', 'User');
1590
                $TestModel = new Comment();
1591
                $TestModel->Attachment->validate = array('attachment' => 'notBlank');
1592

    
1593
                $data = array(
1594
                        'Comment' => array(
1595
                                'comment' => 'This is the comment'
1596
                        ),
1597
                        'Attachment' => array(
1598
                                'attachment' => ''
1599
                        )
1600
                );
1601
                $result = $TestModel->saveAll($data, array('validate' => 'only'));
1602
                $this->assertFalse($result);
1603
                $result = $TestModel->validateAssociated($data);
1604
                $this->assertFalse($result);
1605

    
1606
                $fieldList = array(
1607
                        'Attachment' => array('comment_id')
1608
                );
1609
                $result = $TestModel->saveAll($data, array(
1610
                        'fieldList' => $fieldList, 'validate' => 'only'
1611
                ));
1612
                $this->assertTrue($result);
1613
                $this->assertEmpty($TestModel->validationErrors);
1614
                $result = $TestModel->validateAssociated($data, array('fieldList' => $fieldList));
1615
                $this->assertTrue($result);
1616
                $this->assertEmpty($TestModel->validationErrors);
1617

    
1618
                $TestModel->validate = array('comment' => 'notBlank');
1619
                $record = array(
1620
                        'Comment' => array(
1621
                                'user_id' => 1,
1622
                                'article_id' => 1,
1623
                                'comment' => '',
1624
                        ),
1625
                        'Attachment' => array(
1626
                                'attachment' => ''
1627
                        )
1628
                );
1629
                $result = $TestModel->saveAll($record, array('validate' => 'only'));
1630
                $this->assertFalse($result);
1631
                $result = $TestModel->validateAssociated($record);
1632
                $this->assertFalse($result);
1633

    
1634
                $fieldList = array(
1635
                        'Comment' => array('id', 'article_id', 'user_id'),
1636
                        'Attachment' => array('comment_id')
1637
                );
1638
                $result = $TestModel->saveAll($record, array(
1639
                        'fieldList' => $fieldList, 'validate' => 'only'
1640
                ));
1641
                $this->assertTrue($result);
1642
                $this->assertEmpty($TestModel->validationErrors);
1643
                $result = $TestModel->validateAssociated($record, array('fieldList' => $fieldList));
1644
                $this->assertTrue($result);
1645
                $this->assertEmpty($TestModel->validationErrors);
1646

    
1647
                $TestModel = new Article();
1648
                $TestModel->belongsTo = $TestModel->hasAndBelongsToMany = array();
1649
                $TestModel->Comment->validate = array('comment' => 'notBlank');
1650
                $data = array(
1651
                        'Article' => array('id' => 2),
1652
                        'Comment' => array(
1653
                                array(
1654
                                        'id' => 1,
1655
                                        'comment' => '',
1656
                                        'published' => 'Y',
1657
                                        'user_id' => 1,
1658
                                ),
1659
                                array(
1660
                                        'id' => 2,
1661
                                        'comment' =>
1662
                                        'comment',
1663
                                        'published' => 'Y',
1664
                                        'user_id' => 1
1665
                                ),
1666
                                array(
1667
                                        'id' => 3,
1668
                                        'comment' => '',
1669
                                        'published' => 'Y',
1670
                                        'user_id' => 1
1671
                )));
1672
                $result = $TestModel->saveAll($data, array('validate' => 'only'));
1673
                $this->assertFalse($result);
1674
                $result = $TestModel->validateAssociated($data);
1675
                $this->assertFalse($result);
1676

    
1677
                $expected = array(
1678
                        'Article' => true,
1679
                        'Comment' => array(false, true, false)
1680
                );
1681
                $result = $TestModel->saveAll($data, array('atomic' => false, 'validate' => 'only'));
1682
                $this->assertSame($expected, $result);
1683
                $result = $TestModel->validateAssociated($data, array('atomic' => false));
1684
                $this->assertSame($expected, $result);
1685

    
1686
                $expected = array('Comment' => array(
1687
                        0 => array('comment' => array('This field cannot be left blank')),
1688
                        2 => array('comment' => array('This field cannot be left blank'))
1689
                ));
1690
                $this->assertEquals($expected['Comment'], $TestModel->Comment->validationErrors);
1691

    
1692
                $model = new Comment();
1693
                $model->deleteAll(true);
1694
                $model->validate = array('comment' => 'notBlank');
1695
                $model->Attachment->validate = array('attachment' => 'notBlank');
1696
                $model->Attachment->bindModel(array('belongsTo' => array('Comment')));
1697
                $expected = array(
1698
                        'comment' => array('This field cannot be left blank'),
1699
                        'Attachment' => array(
1700
                                'attachment' => array('This field cannot be left blank')
1701
                        )
1702
                );
1703

    
1704
                $data = array(
1705
                        'Comment' => array('comment' => '', 'article_id' => 1, 'user_id' => 1),
1706
                        'Attachment' => array('attachment' => '')
1707
                );
1708
                $result = $model->saveAll($data, array('validate' => 'only'));
1709
                $this->assertFalse($result);
1710
                $result = $model->validateAssociated($data);
1711
                $this->assertFalse($result);
1712
                $this->assertEquals($expected, $model->validationErrors);
1713
                $this->assertEquals($expected['Attachment'], $model->Attachment->validationErrors);
1714
        }
1715

    
1716
/**
1717
 * testValidateMany method
1718
 *
1719
 * @return void
1720
 */
1721
        public function testValidateMany() {
1722
                $TestModel = new Article();
1723
                $TestModel->validate = array('title' => 'notBlank');
1724
                $data = array(
1725
                        0 => array('title' => ''),
1726
                        1 => array('title' => 'title 1'),
1727
                        2 => array('title' => 'title 2'),
1728
                );
1729
                $expected = array(
1730
                        0 => array('title' => array('This field cannot be left blank')),
1731
                );
1732

    
1733
                $result = $TestModel->saveAll($data, array('validate' => 'only'));
1734
                $this->assertFalse($result);
1735
                $this->assertEquals($expected, $TestModel->validationErrors);
1736
                $result = $TestModel->validateMany($data);
1737
                $this->assertFalse($result);
1738
                $this->assertEquals($expected, $TestModel->validationErrors);
1739

    
1740
                $data = array(
1741
                        0 => array('title' => 'title 0'),
1742
                        1 => array('title' => ''),
1743
                        2 => array('title' => 'title 2'),
1744
                );
1745
                $expected = array(
1746
                        1 => array('title' => array('This field cannot be left blank')),
1747
                );
1748
                $result = $TestModel->saveAll($data, array('validate' => 'only'));
1749
                $this->assertFalse($result);
1750
                $this->assertEquals($expected, $TestModel->validationErrors);
1751
                $result = $TestModel->validateMany($data);
1752
                $this->assertFalse($result);
1753
                $this->assertEquals($expected, $TestModel->validationErrors);
1754
        }
1755

    
1756
/**
1757
 * testGetMethods method
1758
 *
1759
 * @return void
1760
 */
1761
        public function testGetMethods() {
1762
                $this->loadFixtures('Article', 'Comment');
1763
                $TestModel = new Article();
1764
                $Validator = $TestModel->validator();
1765

    
1766
                $result = $Validator->getMethods();
1767

    
1768
                $expected = array_map('strtolower', get_class_methods('Article'));
1769
                $this->assertEquals($expected, array_keys($result));
1770
        }
1771

    
1772
/**
1773
 *  Tests that methods are refreshed when the list of behaviors change
1774
 *
1775
 * @return void
1776
 */
1777
        public function testGetMethodsRefresh() {
1778
                $this->loadFixtures('Article', 'Comment');
1779
                $TestModel = new Article();
1780
                $Validator = $TestModel->validator();
1781

    
1782
                $result = $Validator->getMethods();
1783

    
1784
                $expected = array_map('strtolower', get_class_methods('Article'));
1785
                $this->assertEquals($expected, array_keys($result));
1786

    
1787
                $TestModel->Behaviors->load('Containable');
1788
                $newList = array(
1789
                        'contain',
1790
                        'resetbindings',
1791
                        'containments',
1792
                        'fielddependencies',
1793
                        'containmentsmap'
1794
                );
1795
                $this->assertEquals(array_merge($expected, $newList), array_keys($Validator->getMethods()));
1796

    
1797
                $TestModel->Behaviors->unload('Containable');
1798
                $this->assertEquals($expected, array_keys($Validator->getMethods()));
1799
        }
1800

    
1801
/**
1802
 * testSetValidationDomain method
1803
 *
1804
 * @return void
1805
 */
1806
        public function testSetValidationDomain() {
1807
                $this->loadFixtures('Article', 'Comment');
1808
                $TestModel = new Article();
1809
                $Validator = $TestModel->validator();
1810

    
1811
                $result = $Validator->setValidationDomain('default');
1812
                $this->assertEquals('default', $TestModel->validationDomain);
1813

    
1814
                $result = $Validator->setValidationDomain('other');
1815
                $this->assertEquals('other', $TestModel->validationDomain);
1816
        }
1817

    
1818
/**
1819
 * testGetModel method
1820
 *
1821
 * @return void
1822
 */
1823
        public function testGetModel() {
1824
                $TestModel = new Article();
1825
                $Validator = $TestModel->validator();
1826

    
1827
                $result = $Validator->getModel();
1828
                $this->assertInstanceOf('Article', $result);
1829
        }
1830

    
1831
/**
1832
 * Tests it is possible to get validation sets for a field using an array inteface
1833
 *
1834
 * @return void
1835
 */
1836
        public function testArrayAccessGet() {
1837
                $TestModel = new Article();
1838
                $Validator = $TestModel->validator();
1839

    
1840
                $titleValidator = $Validator['title'];
1841
                $this->assertEquals('title', $titleValidator->field);
1842
                $this->assertCount(1, $titleValidator->getRules());
1843
                $rule = current($titleValidator->getRules());
1844
                $this->assertEquals('notBlank', $rule->rule);
1845

    
1846
                $titleValidator = $Validator['body'];
1847
                $this->assertEquals('body', $titleValidator->field);
1848
                $this->assertCount(1, $titleValidator->getRules());
1849
                $rule = current($titleValidator->getRules());
1850
                $this->assertEquals('notBlank', $rule->rule);
1851

    
1852
                $titleValidator = $Validator['user_id'];
1853
                $this->assertEquals('user_id', $titleValidator->field);
1854
                $this->assertCount(1, $titleValidator->getRules());
1855
                $rule = current($titleValidator->getRules());
1856
                $this->assertEquals('numeric', $rule->rule);
1857
        }
1858

    
1859
/**
1860
 * Tests it is possible to check for validation sets for a field using an array inteface
1861
 *
1862
 * @return void
1863
 */
1864
        public function testArrayAccessExists() {
1865
                $TestModel = new Article();
1866
                $Validator = $TestModel->validator();
1867

    
1868
                $this->assertTrue(isset($Validator['title']));
1869
                $this->assertTrue(isset($Validator['body']));
1870
                $this->assertTrue(isset($Validator['user_id']));
1871
                $this->assertFalse(isset($Validator['other']));
1872
        }
1873

    
1874
/**
1875
 * Tests it is possible to set validation rules for a field using an array inteface
1876
 *
1877
 * @return void
1878
 */
1879
        public function testArrayAccessSet() {
1880
                $TestModel = new Article();
1881
                $Validator = $TestModel->validator();
1882

    
1883
                $set = array(
1884
                        'numeric' => array('rule' => 'numeric', 'allowEmpty' => false),
1885
                        'between' => array('rule' => array('lengthBetween', 1, 5), 'allowEmpty' => false),
1886
                );
1887
                $Validator['other'] = $set;
1888
                $rules = $Validator['other'];
1889
                $this->assertEquals('other', $rules->field);
1890

    
1891
                $validators = $rules->getRules();
1892
                $this->assertCount(2, $validators);
1893
                $this->assertEquals('numeric', $validators['numeric']->rule);
1894
                $this->assertEquals(array('lengthBetween', 1, 5), $validators['between']->rule);
1895

    
1896
                $Validator['new'] = new CakeValidationSet('new', $set, array());
1897
                $rules = $Validator['new'];
1898
                $this->assertEquals('new', $rules->field);
1899

    
1900
                $validators = $rules->getRules();
1901
                $this->assertCount(2, $validators);
1902
                $this->assertEquals('numeric', $validators['numeric']->rule);
1903
                $this->assertEquals(array('lengthBetween', 1, 5), $validators['between']->rule);
1904
        }
1905

    
1906
/**
1907
 * Tests it is possible to unset validation rules
1908
 *
1909
 * @return void
1910
 */
1911
        public function testArrayAccessUset() {
1912
                $TestModel = new Article();
1913
                $Validator = $TestModel->validator();
1914

    
1915
                $this->assertTrue(isset($Validator['title']));
1916
                unset($Validator['title']);
1917
                $this->assertFalse(isset($Validator['title']));
1918
        }
1919

    
1920
/**
1921
 * Tests it is possible to iterate a validation object
1922
 *
1923
 * @return void
1924
 */
1925
        public function testIterator() {
1926
                $TestModel = new Article();
1927
                $Validator = $TestModel->validator();
1928

    
1929
                $i = 0;
1930
                foreach ($Validator as $field => $rules) {
1931
                        if ($i === 0) {
1932
                                $this->assertEquals('user_id', $field);
1933
                        }
1934
                        if ($i === 1) {
1935
                                $this->assertEquals('title', $field);
1936
                        }
1937
                        if ($i === 2) {
1938
                                $this->assertEquals('body', $field);
1939
                        }
1940
                        $this->assertInstanceOf('CakeValidationSet', $rules);
1941
                        $i++;
1942
                }
1943
                $this->assertEquals(3, $i);
1944
        }
1945

    
1946
/**
1947
 * Tests countable interface in ModelValidator
1948
 *
1949
 * @return void
1950
 */
1951
        public function testCount() {
1952
                $TestModel = new Article();
1953
                $Validator = $TestModel->validator();
1954
                $this->assertCount(3, $Validator);
1955

    
1956
                $set = array(
1957
                        'numeric' => array('rule' => 'numeric', 'allowEmpty' => false),
1958
                        'range' => array('rule' => array('lengthBetween', 1, 5), 'allowEmpty' => false),
1959
                );
1960
                $Validator['other'] = $set;
1961
                $this->assertCount(4, $Validator);
1962

    
1963
                unset($Validator['title']);
1964
                $this->assertCount(3, $Validator);
1965
                unset($Validator['body']);
1966
                $this->assertCount(2, $Validator);
1967
        }
1968

    
1969
/**
1970
 * Tests it is possible to add validation rules
1971
 *
1972
 * @return void
1973
 */
1974
        public function testAddRule() {
1975
                $TestModel = new Article();
1976
                $Validator = $TestModel->validator();
1977

    
1978
                $Validator->add('other', 'numeric', array('rule' => 'numeric', 'allowEmpty' => false));
1979
                $Validator->add('other', 'between', array('rule' => array('lengthBetween', 1, 5), 'allowEmpty' => false));
1980
                $rules = $Validator['other'];
1981
                $this->assertEquals('other', $rules->field);
1982

    
1983
                $validators = $rules->getRules();
1984
                $this->assertCount(2, $validators);
1985
                $this->assertEquals('numeric', $validators['numeric']->rule);
1986
                $this->assertEquals(array('lengthBetween', 1, 5), $validators['between']->rule);
1987
        }
1988

    
1989
/**
1990
 * Tests it is possible to remove validation rules
1991
 *
1992
 * @return void
1993
 */
1994
        public function testRemoveRule() {
1995
                $TestModel = new Article();
1996
                $Validator = $TestModel->validator();
1997

    
1998
                $this->assertTrue(isset($Validator['title']));
1999
                $Validator->remove('title');
2000
                $this->assertFalse(isset($Validator['title']));
2001

    
2002
                $Validator->add('other', 'numeric', array('rule' => 'numeric', 'allowEmpty' => false));
2003
                $Validator->add('other', 'between', array('rule' => array('lengthBetween', 1, 5), 'allowEmpty' => false));
2004
                $this->assertTrue(isset($Validator['other']));
2005

    
2006
                $Validator->remove('other', 'numeric');
2007
                $this->assertTrue(isset($Validator['other']));
2008
                $this->assertFalse(isset($Validator['other']['numeric']));
2009
                $this->assertTrue(isset($Validator['other']['between']));
2010
        }
2011

    
2012
/**
2013
 * Tests validation callbacks are triggered
2014
 *
2015
 * @return void
2016
 */
2017
        public function testValidateCallbacks() {
2018
                $TestModel = $this->getMock('Article', array('beforeValidate', 'afterValidate'));
2019
                $TestModel->expects($this->once())->method('beforeValidate');
2020
                $TestModel->expects($this->once())->method('afterValidate');
2021

    
2022
                $TestModel->set(array('title' => '', 'body' => 'body'));
2023
                $TestModel->validates();
2024
        }
2025

    
2026
/**
2027
 * Tests that altering data in a beforeValidate callback will lead to saving those
2028
 * values in database
2029
 *
2030
 * @return void
2031
 */
2032
        public function testValidateFirstWithBeforeValidate() {
2033
                $this->loadFixtures('Article', 'User');
2034
                $model = new CustomArticle();
2035
                $model->validate = array(
2036
                        'title' => array(
2037
                                'notBlank' => array(
2038
                                        'rule' => 'notBlank',
2039
                                        'required' => true,
2040
                                        'allowEmpty' => false
2041
                                )
2042
                        )
2043
                );
2044
                $data = array(
2045
                        'CustomArticle' => array(
2046
                                'body' => 'foo0'
2047
                        )
2048
                );
2049
                $result = $model->saveAll($data, array('validate' => 'first'));
2050
                $this->assertTrue($result);
2051

    
2052
                $this->assertFalse($model->findMethods['unPublished'], 'beforeValidate was run twice');
2053

    
2054
                $model->findMethods['unPublished'] = true;
2055
                $data = array(
2056
                        'CustomArticle' => array(
2057
                                'body' => 'foo1'
2058
                        )
2059
                );
2060
                $result = $model->saveAll($data, array('validate' => 'first', 'deep' => true));
2061
                $this->assertTrue($result);
2062
                $title = $model->field('title', array('body' => 'foo1'));
2063
                $this->assertEquals('foo', $title);
2064
                $this->assertFalse($model->findMethods['unPublished'], 'beforeValidate was run twice');
2065

    
2066
                $data = array(
2067
                        array('body' => 'foo2'),
2068
                        array('body' => 'foo3'),
2069
                        array('body' => 'foo4')
2070
                );
2071

    
2072
                $result = $model->saveAll($data, array('validate' => 'first', 'deep' => true));
2073
                $this->assertTrue($result);
2074

    
2075
                $this->assertEquals('foo', $model->field('title', array('body' => 'foo2')));
2076
                $this->assertEquals('foo', $model->field('title', array('body' => 'foo3')));
2077
                $this->assertEquals('foo', $model->field('title', array('body' => 'foo4')));
2078
        }
2079

    
2080
/**
2081
 * Tests that altering data in a beforeValidate callback will lead to saving those
2082
 * values in database
2083
 *
2084
 * @return void
2085
 */
2086
        public function testValidateFirstAssociatedWithBeforeValidate() {
2087
                $this->loadFixtures('Article', 'User');
2088
                $model = new CustomArticle();
2089
                $model->validate = array(
2090
                        'title' => array(
2091
                                'notBlank' => array(
2092
                                        'rule' => 'notBlank',
2093
                                        'required' => true
2094
                                )
2095
                        )
2096
                );
2097
                $articles = array(
2098
                        array('body' => 'foo1'),
2099
                        array('body' => 'foo2'),
2100
                        array('body' => 'foo3')
2101
                );
2102
                $user = new User();
2103
                $user->bindModel(array('hasMany' => array('CustomArticle')));
2104
                $data = array(
2105
                        'User' => array('user' => 'foo', 'password' => 'bar'),
2106
                        'CustomArticle' => $articles
2107
                );
2108
                $result = $user->saveAll($data, array('validate' => 'first'));
2109
                $this->assertTrue($result);
2110

    
2111
                $this->assertEquals('foo', $model->field('title', array('body' => 'foo1')));
2112
                $this->assertEquals('foo', $model->field('title', array('body' => 'foo2')));
2113
                $this->assertEquals('foo', $model->field('title', array('body' => 'foo3')));
2114
        }
2115

    
2116
/**
2117
 * testValidateFirstWithDefaults method
2118
 *
2119
 * @return void
2120
 */
2121
        public function testFirstWithDefaults() {
2122
                $this->loadFixtures('Article', 'Tag', 'Comment', 'User', 'ArticlesTag');
2123
                $TestModel = new Article();
2124

    
2125
                $result = $TestModel->find('first', array(
2126
                        'conditions' => array('Article.id' => 1)
2127
                ));
2128
                $expected = array(
2129
                        'Article' => array(
2130
                                'id' => 1,
2131
                                'user_id' => 1,
2132
                                'title' => 'First Article',
2133
                                'body' => 'First Article Body',
2134
                                'published' => 'Y',
2135
                                'created' => '2007-03-18 10:39:23'
2136
                        ),
2137
                );
2138
                unset($result['Article']['updated']);
2139
                $this->assertEquals($expected['Article'], $result['Article']);
2140

    
2141
                $data = array(
2142
                        'Article' => array(
2143
                                'id' => 1,
2144
                                'title' => 'First Article (modified)'
2145
                        ),
2146
                        'Comment' => array(
2147
                                array('comment' => 'Article comment', 'user_id' => 1)
2148
                        )
2149
                );
2150
                $result = $TestModel->saveAll($data, array('validate' => 'first'));
2151
                $this->assertTrue($result);
2152

    
2153
                $result = $TestModel->find('first', array(
2154
                        'conditions' => array('Article.id' => 1)
2155
                ));
2156
                $expected['Article']['title'] = 'First Article (modified)';
2157
                unset($result['Article']['updated']);
2158
                $this->assertEquals($expected['Article'], $result['Article']);
2159
        }
2160

    
2161
        public function testAddMultipleRules() {
2162
                $TestModel = new Article();
2163
                $Validator = $TestModel->validator();
2164

    
2165
                $set = array(
2166
                        'numeric' => array('rule' => 'numeric', 'allowEmpty' => false),
2167
                        'between' => array('rule' => array('lengthBetween', 1, 5), 'allowEmpty' => false),
2168
                );
2169

    
2170
                $Validator->add('other', $set);
2171
                $rules = $Validator['other'];
2172
                $this->assertEquals('other', $rules->field);
2173

    
2174
                $validators = $rules->getRules();
2175
                $this->assertCount(2, $validators);
2176
                $this->assertEquals('numeric', $validators['numeric']->rule);
2177
                $this->assertEquals(array('lengthBetween', 1, 5), $validators['between']->rule);
2178

    
2179
                $set = new CakeValidationSet('other', array(
2180
                        'a' => array('rule' => 'numeric', 'allowEmpty' => false),
2181
                        'b' => array('rule' => array('lengthBetween', 1, 5), 'allowEmpty' => false),
2182
                ));
2183

    
2184
                $Validator->add('other', $set);
2185
                $this->assertSame($set, $Validator->getField('other'));
2186
        }
2187

    
2188
/**
2189
 * Test that rules are parsed correctly when calling getField()
2190
 *
2191
 * @return void
2192
 */
2193
        public function testValidator() {
2194
                $TestModel = new Article();
2195
                $Validator = $TestModel->validator();
2196

    
2197
                $result = $Validator->getField();
2198
                $expected = array('user_id', 'title', 'body');
2199
                $this->assertEquals($expected, array_keys($result));
2200
                $this->assertTrue($result['user_id'] instanceof CakeValidationSet);
2201

    
2202
                $result = $TestModel->validator()->getField('title');
2203
                $this->assertTrue($result instanceof CakeValidationSet);
2204
        }
2205

    
2206
/**
2207
 * Test that validator override works as expected
2208
 *
2209
 * @return void
2210
 */
2211
        public function testValidatorOverride() {
2212
                $TestModel = new Article();
2213
                $ValidatorA = new ModelValidator($TestModel);
2214
                $ValidatorB = new ModelValidator($TestModel);
2215

    
2216
                $TestModel->validator($ValidatorA);
2217
                $TestModel->validator($ValidatorB);
2218

    
2219
                $this->assertSame($ValidatorB, $TestModel->validator());
2220
                $this->assertNotSame($ValidatorA, $TestModel->validator());
2221
        }
2222

    
2223
/**
2224
 * Test that type hint exception is thrown
2225
 *
2226
 * @expectedException PHPUnit_Framework_Error
2227
 * @return void
2228
 */
2229
        public function testValidatorTypehintException() {
2230
                new ModelValidator('asdasds');
2231
        }
2232

    
2233
/**
2234
 * Tests that altering data in a beforeValidate callback will lead to saving those
2235
 * values in database, this time with belongsTo associations
2236
 *
2237
 * @return void
2238
 */
2239
        public function testValidateFirstAssociatedWithBeforeValidate2() {
2240
                $this->loadFixtures('Article', 'User');
2241
                $model = new CustomArticle();
2242
                $model->validate = array(
2243
                        'title' => array(
2244
                                'notBlank' => array(
2245
                                        'rule' => 'notBlank',
2246
                                        'required' => true
2247
                                )
2248
                        )
2249
                );
2250

    
2251
                $data = array(
2252
                        'User' => array('user' => 'foo', 'password' => 'bar'),
2253
                        'CustomArticle' => array(
2254
                                'body' => 'a test'
2255
                        )
2256
                );
2257
                $result = $model->saveAll($data, array('validate' => 'first'));
2258
                $this->assertTrue($result);
2259

    
2260
                $this->assertEquals('foo', $model->field('title', array('body' => 'a test')));
2261
        }
2262

    
2263
/**
2264
 * Testing you can dynamically add rules to a field, added this to dispel doubts
2265
 * after a presentation made to show off this new feature
2266
 *
2267
 * @return void
2268
 */
2269
        public function testDynamicValidationRuleBuilding() {
2270
                $model = new Article;
2271
                $validator = $model->validator();
2272
                $validator->add('body', 'isSpecial', array('rule' => 'special'));
2273
                $rules = $validator['body']->getRules();
2274
                $this->assertCount(2, $rules);
2275
                $this->assertEquals('special', $rules['isSpecial']->rule);
2276
                $validator['body']->setRule('isAwesome', array('rule' => 'awesome'));
2277
                $rules = $validator['body']->getRules();
2278
                $this->assertCount(3, $rules);
2279
                $this->assertEquals('awesome', $rules['isAwesome']->rule);
2280
        }
2281

    
2282
/**
2283
 * Test to ensure custom validation methods work with CakeValidationSet
2284
 *
2285
 * @return void
2286
 */
2287
        public function testCustomMethodsWithCakeValidationSet() {
2288
                $TestModel = new TestValidate();
2289
                $Validator = $TestModel->validator();
2290

    
2291
                $Validator->add('title', 'validateTitle', array(
2292
                        'rule' => 'validateTitle',
2293
                        'message' => 'That aint right',
2294
                ));
2295
                $data = array('title' => 'notatitle');
2296
                $result = $Validator->getField('title')->validate($data);
2297
                $expected = array(0 => 'That aint right');
2298
                $this->assertEquals($expected, $result);
2299

    
2300
                $data = array('title' => 'title-is-good');
2301
                $result = $Validator->getField('title')->validate($data);
2302
                $expected = array();
2303
                $this->assertEquals($expected, $result);
2304
        }
2305

    
2306
        public function testCustomMethodWithEmptyValue() {
2307
                $this->loadFixtures('Article');
2308

    
2309
                $model = $this->getMock('Article', array('isLegit'));
2310
                $model->validate = array(
2311
                        'title' => array(
2312
                                'custom' => array(
2313
                                        'rule' => array('isLegit'),
2314
                                        'message' => 'is no good'
2315
                                )
2316
                        )
2317
                );
2318
                $model->expects($this->once())
2319
                        ->method('isLegit')
2320
                        ->will($this->returnValue(false));
2321

    
2322
                $model->set(array('title' => ''));
2323
                $this->assertFalse($model->validates());
2324
        }
2325

    
2326
/**
2327
 * Test validateAssociated with atomic=false & deep=true
2328
 *
2329
 * @return void
2330
 */
2331
        public function testValidateAssociatedAtomicFalseDeepTrueWithErrors() {
2332
                $this->loadFixtures('Comment', 'Article', 'User', 'Attachment');
2333
                $Attachment = ClassRegistry::init('Attachment');
2334
                $Attachment->Comment->validator()->add('comment', array(
2335
                        array('rule' => 'notBlank')
2336
                ));
2337
                $Attachment->Comment->User->bindModel(array(
2338
                        'hasMany' => array(
2339
                                'Article',
2340
                                'Comment'
2341
                        )),
2342
                        false
2343
                );
2344

    
2345
                $data = array(
2346
                        'Attachment' => array(
2347
                                'attachment' => 'text',
2348
                                'Comment' => array(
2349
                                        'comment' => '',
2350
                                        'published' => 'N',
2351
                                        'User' => array(
2352
                                                'user' => 'Foo',
2353
                                                'password' => 'mypassword',
2354
                                                'Comment' => array(
2355
                                                        array(
2356
                                                                'comment' => ''
2357
                                                        )
2358
                                                )
2359
                                        )
2360
                                )
2361
                        )
2362
                );
2363
                $result = $Attachment->validateAssociated($data, array('atomic' => false, 'deep' => true));
2364

    
2365
                $result = $Attachment->validationErrors;
2366
                $expected = array(
2367
                        'Comment' => array(
2368
                                'comment' => array(
2369
                                        0 => 'This field cannot be left blank',
2370
                                ),
2371
                                'User' => array(
2372
                                        'Comment' => array(
2373
                                                0 => array(
2374
                                                        'comment' => array(
2375
                                                                0 => 'This field cannot be left blank',
2376
                                                        ),
2377
                                                ),
2378
                                        ),
2379
                                ),
2380
                        ),
2381
                );
2382
                $this->assertEquals($expected, $result);
2383
        }
2384

    
2385
/**
2386
 * Test validateMany with atomic=false & deep=true
2387
 *
2388
 * @return void
2389
 */
2390
        public function testValidateManyAtomicFalseDeepTrueWithErrors() {
2391
                $this->loadFixtures('Comment', 'Article', 'User');
2392
                $Article = ClassRegistry::init('Article');
2393
                $Article->Comment->validator()->add('comment', array(
2394
                        array('rule' => 'notBlank')
2395
                ));
2396

    
2397
                $data = array(
2398
                        array(
2399
                                'Article' => array(
2400
                                        'user_id' => 1,
2401
                                        'title' => 'Foo',
2402
                                        'body' => 'text',
2403
                                        'published' => 'N'
2404
                                ),
2405
                                'Comment' => array(
2406
                                        array(
2407
                                                'user_id' => 1,
2408
                                                'comment' => 'Baz',
2409
                                                'published' => 'N',
2410
                                        )
2411
                                ),
2412
                        ),
2413
                        array(
2414
                                'Article' => array(
2415
                                        'user_id' => 1,
2416
                                        'title' => 'Bar',
2417
                                        'body' => 'text',
2418
                                        'published' => 'N'
2419
                                ),
2420
                                'Comment' => array(
2421
                                        array(
2422
                                                'user_id' => 1,
2423
                                                'comment' => '',
2424
                                                'published' => 'N',
2425
                                        )
2426
                                ),
2427
                        ),
2428
                );
2429
                $Article->validateMany($data, array('atomic' => false, 'deep' => true));
2430

    
2431
                $result = $Article->validationErrors;
2432
                $expected = array(
2433
                        1 => array(
2434
                                'Comment' => array(
2435
                                        0 => array(
2436
                                                'comment' => array(
2437
                                                        0 => 'This field cannot be left blank',
2438
                                                ),
2439
                                        ),
2440
                                ),
2441
                        ),
2442
                );
2443
                $this->assertEquals($expected, $result);
2444
        }
2445

    
2446
/**
2447
 * Test the isUnique method when used as a validator for multiple fields.
2448
 *
2449
 * @return void
2450
 */
2451
        public function testIsUniqueValidator() {
2452
                $this->loadFixtures('Article');
2453
                $Article = ClassRegistry::init('Article');
2454
                $Article->validate = array(
2455
                        'user_id' => array(
2456
                                'duplicate' => array(
2457
                                        'rule' => array('isUnique', array('user_id', 'title'), false)
2458
                                )
2459
                        )
2460
                );
2461
                $data = array(
2462
                        'user_id' => 1,
2463
                        'title' => 'First Article',
2464
                );
2465
                $Article->create($data);
2466
                $this->assertFalse($Article->validates(), 'Contains a dupe');
2467

    
2468
                $data = array(
2469
                        'user_id' => 1,
2470
                        'title' => 'Unique Article',
2471
                );
2472
                $Article->create($data);
2473
                $this->assertTrue($Article->validates(), 'Should pass');
2474

    
2475
                $Article->validate = array(
2476
                        'user_id' => array(
2477
                                'duplicate' => array(
2478
                                        'rule' => array('isUnique', array('user_id', 'title'))
2479
                                )
2480
                        )
2481
                );
2482
                $data = array(
2483
                        'user_id' => 1,
2484
                        'title' => 'Unique Article',
2485
                );
2486
                $Article->create($data);
2487
                $this->assertFalse($Article->validates(), 'Should fail, conditions are combined with or');
2488
        }
2489

    
2490
/**
2491
 * Test backward compatibility of the isUnique method when used as a validator for a single field.
2492
 *
2493
 * @return void
2494
 */
2495
        public function testBackwardCompatIsUniqueValidator() {
2496
                $this->loadFixtures('Article');
2497
                $Article = ClassRegistry::init('Article');
2498
                $Article->validate = array(
2499
                        'title' => array(
2500
                                'duplicate' => array(
2501
                                        'rule' => 'isUnique',
2502
                                        'message' => 'Title must be unique',
2503
                                ),
2504
                                'minLength' => array(
2505
                                        'rule' => array('minLength', 1),
2506
                                        'message' => 'Title cannot be empty',
2507
                                ),
2508
                        )
2509
                );
2510
                $data = array(
2511
                        'title' => 'First Article',
2512
                );
2513
                $data = $Article->create($data);
2514
                $this->assertFalse($Article->validates(), 'Contains a dupe');
2515
        }
2516

    
2517
}
2518

    
2519
/**
2520
 * Behavior for testing validation rules.
2521
 */
2522
class ValidationRuleBehavior extends ModelBehavior {
2523

    
2524
        public function setup(Model $Model, $config = array()) {
2525
                $this->settings[$Model->alias] = $config;
2526
        }
2527

    
2528
        public function beforeValidate(Model $Model, $options = array()) {
2529
                $fields = $this->settings[$Model->alias]['fields'];
2530
                foreach ($fields as $field) {
2531
                        $Model->whitelist[] = $field;
2532
                }
2533
        }
2534

    
2535
}