Skip to content

Commit c4e1698

Browse files
committed
start work on tests
1 parent abf8b5c commit c4e1698

File tree

5 files changed

+263
-20
lines changed

5 files changed

+263
-20
lines changed
Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
<?php
2+
3+
use Illuminate\Support\Facades\Event;
4+
use StevenFox\LaravelModelValidation\Listeners\ValidateModel;
5+
use StevenFox\LaravelModelValidation\Tests\Fixtures\ValidatesWhenSavingModel;
6+
use StevenFox\LaravelModelValidation\Tests\Fixtures\ValidatingModel;
7+
8+
it('does stuff', function () {
9+
$m = new ValidatingModel();
10+
$mm = new ValidatesWhenSavingModel();
11+
12+
$mm->save();
13+
});
14+
15+
it('registers a "creating" model event listeners when shouldValidateWhenSaving() is true', function () {
16+
Event::forget('*');
17+
Event::fake();
18+
19+
$m = new ValidatesWhenSavingModel();
20+
$modelClassName = $m::class;
21+
22+
expect($m::shouldValidateWhenSaving())->toBeTrue();
23+
24+
Event::assertListening("eloquent.creating: {$modelClassName}", ValidateModel::class);
25+
});
26+
27+
it('registers an "updating" model event listeners when shouldValidateWhenSaving() is true', function () {
28+
Event::forget('*');
29+
Event::fake();
30+
31+
$m = new ValidatingModel();
32+
$modelClassName = $m::class;
33+
34+
expect($m::shouldValidateWhenSaving())->toBeTrue();
35+
36+
Event::assertListening("eloquent.updating: {$modelClassName}", Closure::class);
37+
});
38+
39+
it('will not register the model event listeners when shouldValidateOnSaving() is false', function () {
40+
Event::forget('*');
41+
Event::fake();
42+
43+
ValidatingModel::disableValidationWhenSaving();
44+
45+
$m = new ValidatingModel();
46+
$modelClassName = $m::class;
47+
48+
expect($m::shouldValidateWhenSaving())->toBeFalse()
49+
->and(Event::hasListeners("eloquent.updating: {$modelClassName}"))
50+
->toBeFalse()
51+
->and(Event::hasListeners("eloquent.creating: {$modelClassName}"))
52+
->toBeFalse();
53+
});
54+
it('will re-register the model event listeners when reactivateValidationWhenSaving() is invoked', function () {
55+
Event::forget('*');
56+
Event::fake();
57+
58+
ValidatingModel::disableValidationWhenSaving();
59+
60+
$m = new ValidatingModel();
61+
$modelClassName = $m::class;
62+
63+
ValidatingModel::reactivateValidationWhenSaving();
64+
65+
expect($m::shouldValidateWhenSaving())->toBeTrue()
66+
->and(Event::hasListeners("eloquent.updating: {$modelClassName}"))
67+
->toBeTrue()
68+
->and(Event::hasListeners("eloquent.creating: {$modelClassName}"))
69+
->toBeTrue();
70+
});
71+
72+
it('shouldNotValidateWhenSaving() will return the opposite of shouldValidateWhenSaving()', function () {
73+
expect(ValidatingModel::shouldNotValidateWhenSaving())
74+
->toBeFalse()
75+
->toBe(! ValidatingModel::shouldValidateWhenSaving());
76+
77+
ValidatingModel::disableValidationWhenSaving();
78+
79+
expect(ValidatingModel::shouldNotValidateWhenSaving())
80+
->toBeTrue()
81+
->toBe(! ValidatingModel::shouldValidateWhenSaving());
82+
});
83+
84+
it('provides a whileValidatingDisabled() function to run a callback while validation is disabled', function () {
85+
$this->markTestSkipped();
86+
});
87+
88+
it('can validate a model and throw the ModelValidationException upon failure', function () {
89+
$this->expectException(ModelValidationException::class);
90+
$this->expectExceptionMessage('The required string field is required.');
91+
92+
$m = new ValidatingModel();
93+
94+
$m->validate();
95+
});
96+
97+
it('will use database-prepared attribute values for validation by default', function () {
98+
$m = new ValidatingModel([
99+
'json' => ['foo' => 'bar'],
100+
]);
101+
102+
expect($m->validationData())->toBe([
103+
'json' => \Illuminate\Database\Eloquent\Casts\Json::encode(['foo' => 'bar']),
104+
]);
105+
});
106+
107+
it('will stop the validation process and return false if a "validating" event listener returns false', function () {
108+
Event::listen(
109+
'eloquent.validating: '.ValidatingModel::class,
110+
function (ValidatingModel $model, \Illuminate\Validation\Validator $validator) {
111+
return false;
112+
});
113+
114+
$m = new ValidatingModel();
115+
116+
expect($m->validate())->toBeFalse();
117+
});
118+
119+
it('will stop the validation process and return false if a "validated" event listener returns false', function () {
120+
Event::listen(
121+
'eloquent.validated: '.ValidatingModel::class,
122+
function (ValidatingModel $model, \Illuminate\Validation\Validator $validator) {
123+
return false;
124+
});
125+
126+
$m = new ValidatingModel();
127+
128+
expect($m->validate())->toBeFalse();
129+
});
130+
131+
it('can use temporary validation rules', function () {
132+
$m = new ValidatingModel([
133+
'required_string' => null,
134+
]);
135+
136+
$m->setTemporaryValidationRules([
137+
'required_string' => 'nullable|string',
138+
]);
139+
140+
expect($m->getTemporaryValidationRules())
141+
->toBe(['required_string' => 'nullable|string'])
142+
->and($m->makeValidator()->getRules())
143+
->toBe(['required_string' => ['nullable', 'string']])
144+
->and($m->validate()->fails())
145+
->toBeFalse();
146+
});
147+
148+
it('can clear the temporary validation rules', function () {
149+
$m = new ValidatingModel();
150+
151+
$m->setTemporaryValidationRules([
152+
'required_string' => 'nullable|string',
153+
]);
154+
155+
expect($m->getTemporaryValidationRules())->not()->toBeEmpty();
156+
157+
$m->clearTemporaryValidationRules();
158+
159+
expect($m->getTemporaryValidationRules())->toBeEmpty();
160+
});
161+
162+
it('uses independent rules for updating vs creating', function () {
163+
$m = new ValidatingModel();
164+
165+
expect($m->exists)->toBeFalse()
166+
->and($m->makeValidator()->getRules()['unique'])
167+
->toBe(['unique:short_urls,url_key,NULL,id']);
168+
169+
$m->id = 127;
170+
$m->exists = true;
171+
172+
expect($m->exists)->toBeTrue()
173+
->and($m->makeValidator()->getRules()['unique'])
174+
->toBe(['unique:short_urls,url_key,"127",id']); // The model key is now a part of the rule for ignoring
175+
});
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
namespace StevenFox\LaravelModelValidation\Tests\Fixtures;
4+
5+
use StevenFox\LaravelModelValidation\Contracts\ValidatesWhenSaving;
6+
7+
class ValidatesWhenSavingModel extends ValidatingModel implements ValidatesWhenSaving
8+
{
9+
//
10+
}

tests/Fixtures/ValidatingModel.php

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?php
2+
3+
namespace StevenFox\LaravelModelValidation\Tests\Fixtures;
4+
5+
use Illuminate\Database\Eloquent\Casts\AsArrayObject;
6+
use Illuminate\Database\Eloquent\Casts\AsCollection;
7+
use Illuminate\Database\Eloquent\Casts\AsEncryptedArrayObject;
8+
use Illuminate\Database\Eloquent\Casts\AsStringable;
9+
use Illuminate\Database\Eloquent\Model;
10+
use StevenFox\LaravelModelValidation\ValidatesAttributes;
11+
12+
class ValidatingModel extends Model
13+
{
14+
use ValidatesAttributes;
15+
16+
protected $guarded = [];
17+
18+
protected function commonValidationRules(): array
19+
{
20+
return [
21+
'required_string' => ['required', 'string'],
22+
'stringable' => ['string'],
23+
'unique_column' => $this->uniqueRule(),
24+
'datetime' => ['date'],
25+
'json' => ['json'],
26+
'array_object' => ['array'],
27+
'collection' => ['array'],
28+
'encrypted_object' => ['encrypted'],
29+
];
30+
}
31+
32+
protected function casts(): array
33+
{
34+
return [
35+
'required_string' => 'string',
36+
'stringable' => AsStringable::class,
37+
'datetime' => 'datetime',
38+
'json' => 'array',
39+
'array_object' => AsArrayObject::class,
40+
'collection' => AsCollection::class,
41+
'encrypted_object' => AsEncryptedArrayObject::class,
42+
];
43+
}
44+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?php
2+
3+
namespace StevenFox\LaravelModelValidation\Tests\Fixtures;
4+
5+
use Illuminate\Database\Migrations\Migration;
6+
use Illuminate\Database\Schema\Blueprint;
7+
use Illuminate\Support\Facades\Schema;
8+
9+
return new class extends Migration
10+
{
11+
public function up(): void
12+
{
13+
Schema::create('validating_models', static function (Blueprint $table) {
14+
$table->id();
15+
$table->unsignedInteger('unique_column')->unique();
16+
$table->string('required_string');
17+
$table->string('stringable')->nullable();
18+
$table->dateTime('datetime')->nullable();
19+
$table->json('json')->nullable();
20+
$table->json('array')->nullable();
21+
$table->json('collection')->nullable();
22+
$table->text('encrypted_object')->nullable();
23+
});
24+
}
25+
26+
public function down(): void
27+
{
28+
Schema::dropIfExists('validating_models');
29+
}
30+
};

tests/TestCase.php

Lines changed: 4 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,29 +8,13 @@
88

99
class TestCase extends Orchestra
1010
{
11-
protected function setUp(): void
11+
public function getEnvironmentSetUp($app): void
1212
{
13-
parent::setUp();
14-
15-
Factory::guessFactoryNamesUsing(
16-
fn (string $modelName) => 'StevenFox\\LaravelModelValidation\\Database\\Factories\\'.class_basename($modelName).'Factory'
17-
);
18-
}
19-
20-
protected function getPackageProviders($app)
21-
{
22-
return [
23-
LaravelModelValidationServiceProvider::class,
24-
];
13+
config()->set('database.default', 'testing');
2514
}
2615

27-
public function getEnvironmentSetUp($app)
16+
protected function defineDatabaseMigrations(): void
2817
{
29-
config()->set('database.default', 'testing');
30-
31-
/*
32-
$migration = include __DIR__.'/../database/migrations/create_laravel-model-validation_table.php.stub';
33-
$migration->up();
34-
*/
18+
$this->loadMigrationsFrom('./Migrations');
3519
}
3620
}

0 commit comments

Comments
 (0)