Skip to content

Commit 540689b

Browse files
committed
update tests
1 parent 83328a8 commit 540689b

File tree

3 files changed

+249
-11
lines changed

3 files changed

+249
-11
lines changed

tests/ExampleTest.php

Lines changed: 0 additions & 5 deletions
This file was deleted.

tests/Feature/ModelAttributeValidationTest.php

Lines changed: 227 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,20 @@
11
<?php
22

3+
use Illuminate\Database\QueryException;
4+
use Illuminate\Support\Facades\Date;
35
use Illuminate\Support\Facades\Event;
6+
use Illuminate\Validation\Validator;
47
use StevenFox\LaravelModelValidation\Exceptions\ModelValidationException;
58
use StevenFox\LaravelModelValidation\Listeners\ValidateModel;
69
use StevenFox\LaravelModelValidation\Tests\Fixtures\ValidatesWhenSavingModel;
710
use StevenFox\LaravelModelValidation\Tests\Fixtures\ValidatingModel;
811

12+
beforeEach(function() {
13+
// Reset the static variable on the trait prior to each test
14+
// to avoid state corruption.
15+
ValidatingModel::enableValidationWhenSaving();
16+
});
17+
918
it('registers a "creating" model event listeners when shouldValidateWhenSaving() is true', function () {
1019
Event::forget('*');
1120
Event::fake();
@@ -55,7 +64,7 @@
5564
$m = new ValidatesWhenSavingModel();
5665
$modelClassName = $m::class;
5766

58-
ValidatingModel::reactivateValidationWhenSaving();
67+
ValidatingModel::enableValidationWhenSaving();
5968

6069
expect($m::shouldValidateWhenSaving())->toBeTrue()
6170
->and(Event::hasListeners("eloquent.updating: {$modelClassName}"))
@@ -89,21 +98,70 @@
8998
$m->validate();
9099
});
91100

92-
it('will use database-prepared attribute values for validation by default', function () {
93-
$m = new ValidatingModel([
101+
it('will validate a model during the save process when applicable', function () {
102+
$this->expectException(ModelValidationException::class);
103+
$this->expectExceptionMessage('The required string field is required.');
104+
105+
$m = new ValidatesWhenSavingModel();
106+
107+
$m->save();
108+
// Exception should be thrown
109+
});
110+
111+
it('will NOT validate a model during the save process when inapplicable', function () {
112+
$this->expectException(QueryException::class);
113+
114+
$m = new ValidatingModel();
115+
116+
$m->save();
117+
// Exception should be thrown
118+
});
119+
120+
it('has a passesValidation method', function () {
121+
$m = new ValidatingModel();
122+
123+
expect($m->passesValidation())->toBeFalse();
124+
125+
$m->fill([
126+
'required_string' => 'foo',
94127
'stringable' => str('foo'),
95-
'datetime' => \Illuminate\Support\Facades\Date::create(2000, 1, 1),
128+
'datetime' => Date::create(2000, 1, 1),
96129
'json' => ['foo' => 'bar'],
97130
'array_object' => ['foo' => 'bar'],
98131
'collection' => collect(['foo' => 'bar']),
99132
]);
100133

134+
$m->validate();
135+
136+
expect($m->passesValidation())->toBeTrue();
137+
});
138+
139+
it('will use database-prepared attribute values for validation by default', function () {
140+
$m = new ValidatingModel([
141+
'stringable' => str('foo'),
142+
'datetime' => Date::create(2000, 1, 1),
143+
'json' => ['foo' => 'bar'],
144+
]);
145+
101146
expect($m->validationData())->toBe([
102147
'stringable' => 'foo',
103148
'datetime' => '2000-01-01 00:00:00',
104149
'json' => '{"foo":"bar"}',
105-
'array_object' => '{"foo":"bar"}',
106-
'collection' => '{"foo":"bar"}',
150+
'array_object' => null,
151+
'collection' => null,
152+
]);
153+
});
154+
155+
it('can prepare the validation data with the prepareAttributesForValidation method', function () {
156+
$m = new ValidatingModel([
157+
'array_object' => ['foo' => 'bar'],
158+
'collection' => ['foo' => 'bar'],
159+
]);
160+
161+
/** @see ValidatingModel::prepareAttributesForValidation() */
162+
expect($m->validationData())->toBe([
163+
'array_object' => ['foo' => 'bar'],
164+
'collection' => ['foo' => 'bar'],
107165
]);
108166
});
109167

@@ -140,6 +198,72 @@
140198
->and($m->makeValidator()->getRules())->not()->toBe(['required_string' => ['nullable', 'string']]);
141199
});
142200

201+
it('can use mixin validation rules', function () {
202+
$m = new ValidatingModel([
203+
'required_string' => null,
204+
]);
205+
206+
$m->addMixinValidationRules([
207+
'required_string' => 'nullable|string',
208+
'array_object' => 'nullable|array',
209+
'collection' => 'nullable|array',
210+
]);
211+
212+
expect($m->getMixinValidationRules())
213+
->toBe([
214+
'required_string' => 'nullable|string',
215+
'array_object' => 'nullable|array',
216+
'collection' => 'nullable|array',
217+
])
218+
->and($m->makeValidator()->getRules())
219+
->toBe([
220+
'required_string' => ['nullable', 'string'],
221+
'stringable' => ['string'],
222+
'unique_column' => ['unique:validating_models,NULL,NULL,id'],
223+
'datetime' => ['date'],
224+
'json' => ['json'],
225+
'array_object' => ['nullable', 'array'],
226+
'collection' => ['nullable', 'array'],
227+
'encrypted_object' => ['encrypted'],
228+
])
229+
->and($m->validate()->fails())
230+
->toBeFalse();
231+
});
232+
233+
it('can clear the mixin validation rules', function () {
234+
$m = new ValidatingModel();
235+
236+
$m->addMixinValidationRules([
237+
'required_string' => 'nullable|string',
238+
]);
239+
240+
expect($m->getMixinValidationRules())->not()->toBeEmpty()
241+
->and($m->makeValidator()->getRules())->toBe([
242+
'required_string' => ['nullable', 'string'],
243+
'stringable' => ['string'],
244+
'unique_column' => ['unique:validating_models,NULL,NULL,id'],
245+
'datetime' => ['date'],
246+
'json' => ['json'],
247+
'array_object' => ['array'],
248+
'collection' => ['array'],
249+
'encrypted_object' => ['encrypted'],
250+
]);
251+
252+
$m->clearMixinValidationRules();
253+
254+
expect($m->getMixinValidationRules())->toBeEmpty()
255+
->and($m->makeValidator()->getRules())->toBe([
256+
'required_string' => ['required', 'string'],
257+
'stringable' => ['string'],
258+
'unique_column' => ['unique:validating_models,NULL,NULL,id'],
259+
'datetime' => ['date'],
260+
'json' => ['json'],
261+
'array_object' => ['array'],
262+
'collection' => ['array'],
263+
'encrypted_object' => ['encrypted'],
264+
]);
265+
});
266+
143267
it('uses independent rules for updating vs creating', function () {
144268
$m = new ValidatingModel();
145269

@@ -154,3 +278,100 @@
154278
->and($m->makeValidator()->getRules()['unique_column'])
155279
->toBe(['unique:validating_models,NULL,"127",id']); // The model key is now a part of the rule for ignoring
156280
});
281+
282+
it('can use custom validation messages', function () {
283+
/** @see ValidatingModel::customValidationMessages() */
284+
$m = new ValidatingModel([
285+
'required_string' => 123,
286+
]);
287+
288+
$m->passesValidation();
289+
290+
expect($m->validator()->errors()->first('required_string'))
291+
->toBe('This is a custom message for the required_string.string rule');
292+
});
293+
294+
it('can use custom validation attribute names', function () {
295+
/** @see ValidatingModel::customValidationMessages() */
296+
$m = new ValidatingModel([
297+
'datetime' => Date::create(2000, 1, 1),
298+
]);
299+
300+
// Only test the datetime attribute...
301+
$m->setSupersedingValidationRules([
302+
'datetime' => ['date', 'after:2000-01-01'],
303+
]);
304+
305+
$m->passesValidation();
306+
307+
expect($m->validator()->errors()->first('datetime'))
308+
->toBe('The custom datetime attribute name field must be a date after 2000-01-01.');
309+
});
310+
311+
it('provides public access to the validation configuration', function () {
312+
$m = new ValidatingModel([
313+
'required_string' => 'foo',
314+
'stringable' => 'bar',
315+
]);
316+
317+
$rules = $m->validationRules();
318+
319+
expect($rules['required_string'])
320+
->toBe(['required', 'string'])
321+
->and($rules['stringable'])
322+
->toBe(['string'])
323+
->and($m->validationData())
324+
->toMatchArray([
325+
'required_string' => 'foo',
326+
'stringable' => 'bar',
327+
])
328+
->and($m->customValidationMessages())
329+
->toBe(['required_string.string' => 'This is a custom message for the required_string.string rule'])
330+
->and($m->customValidationAttributeNames())
331+
->toBe(['datetime' => 'custom datetime attribute name']);
332+
});
333+
334+
it('provides a static validating method to register an event hook', function () {
335+
ValidatingModel::validating(function (ValidatingModel $model, Validator $validator) {
336+
expect($model->id)->toBe(123)
337+
->and($validator->failed())->toBeEmpty();
338+
});
339+
340+
$m = new ValidatingModel([
341+
'id' => 123,
342+
]);
343+
344+
// The following should trigger the event.
345+
$m->passesValidation();
346+
});
347+
348+
it('provides a static validated method to register an event hook', function () {
349+
ValidatingModel::validated(function (ValidatingModel $model, Validator $validator) {
350+
expect($model->id)->toBe(123)
351+
->and($validator->failed())->not()->toBeEmpty();
352+
});
353+
354+
$m = new ValidatingModel([
355+
'id' => 123,
356+
]);
357+
358+
// The following should trigger the event.
359+
$m->passesValidation();
360+
});
361+
362+
it('registers observable events', function () {
363+
$m = new ValidatingModel();
364+
365+
expect($m->getObservableEvents())
366+
->toContain('validating', 'validated');
367+
});
368+
369+
it('throws a ModelValidationException', function () {
370+
$m = new ValidatingModel();
371+
372+
try {
373+
$m->validate();
374+
} catch (ModelValidationException $e) {
375+
expect($e->model)->toBe($m);
376+
}
377+
});

tests/Fixtures/ValidatingModel.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,26 @@ protected function casts(): array
4141
'encrypted_object' => AsEncryptedArrayObject::class,
4242
];
4343
}
44+
45+
protected function prepareAttributesForValidation(array $rawAttributes): array
46+
{
47+
$rawAttributes['array_object'] = $this->array_object?->toArray();
48+
$rawAttributes['collection'] = $this->collection?->toArray();
49+
50+
return $rawAttributes;
51+
}
52+
53+
public function customValidationMessages(): array
54+
{
55+
return [
56+
'required_string.string' => 'This is a custom message for the required_string.string rule',
57+
];
58+
}
59+
60+
public function customValidationAttributeNames(): array
61+
{
62+
return [
63+
'datetime' => 'custom datetime attribute name',
64+
];
65+
}
4466
}

0 commit comments

Comments
 (0)