diff --git a/.editorconfig b/.editorconfig index a7c44dd..d9f90ab 100644 --- a/.editorconfig +++ b/.editorconfig @@ -2,14 +2,14 @@ root = true [*] charset = utf-8 -indent_size = 4 -indent_style = space end_of_line = lf insert_final_newline = true +indent_style = space +indent_size = 4 trim_trailing_whitespace = true [*.md] trim_trailing_whitespace = false [*.{yml,yaml}] -indent_size = 2 +indent_size = 2 \ No newline at end of file diff --git a/.gitattributes b/.gitattributes index 9e9519b..34091f0 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,19 +1,11 @@ -# Path-based git attributes -# https://www.kernel.org/pub/software/scm/git/docs/gitattributes.html - -# Ignore all test and documentation with "export-ignore". -/.github export-ignore /.gitattributes export-ignore +/.github export-ignore /.gitignore export-ignore -/phpunit.xml.dist export-ignore -/art export-ignore -/docs export-ignore -/tests export-ignore +# /art export-ignore +# /docs export-ignore /.editorconfig export-ignore -/.php_cs.dist.php export-ignore -/psalm.xml export-ignore -/psalm.xml.dist export-ignore -/testbench.yaml export-ignore +/phpstan.neon export-ignore +/phpunit.xml export-ignore +# /pint.json export-ignore +/tests export-ignore /UPGRADING.md export-ignore -/phpstan.neon.dist export-ignore -/phpstan-baseline.neon export-ignore diff --git a/.gitignore b/.gitignore index 9a43686..f8573f5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ .idea .php_cs .php_cs.cache +.phpunit.cache .phpunit.result.cache build composer.lock @@ -8,7 +9,6 @@ coverage docs phpunit.xml phpstan.neon -testbench.yaml vendor node_modules .php-cs-fixer.cache diff --git a/composer.json b/composer.json index f03f3c1..fd8c733 100644 --- a/composer.json +++ b/composer.json @@ -21,20 +21,22 @@ "spatie/laravel-package-tools": "^1.14.0" }, "require-dev": { - "laravel/pint": "^1.0", "nunomaduro/collision": "^7.0|^8.0", "orchestra/testbench": "^7.0|^8.0|^9.0", "pestphp/pest": "^2.0", - "pestphp/pest-plugin-type-coverage": "^2.0" + "pestphp/pest-plugin-arch": "^2.0", + "pestphp/pest-plugin-laravel": "^2.0", + "pestphp/pest-plugin-type-coverage": "^2.0", + "laravel/pint": "^1.0" }, "autoload": { "psr-4": { - "Cjmellor\\Approval\\": "src" + "Approval\\Approval\\": "src/" } }, "autoload-dev": { "psr-4": { - "Cjmellor\\Approval\\Tests\\": "tests" + "Approval\\Approval\\Tests\\": "tests/" } }, "scripts": { @@ -43,18 +45,18 @@ "test-coverage": "vendor/bin/pest --coverage" }, "config": { - "sort-packages": true, "allow-plugins": { "pestphp/pest-plugin": true - } + }, + "sort-packages": true }, "extra": { "laravel": { "providers": [ - "Cjmellor\\Approval\\ApprovalServiceProvider" + "Approval\\Approval\\ApprovalServiceProvider" ], "aliases": { - "Approval": "Cjmellor\\Approval\\Facades\\Approval" + "Approval": "Approval\\Approval\\Facades\\Approval" } } }, diff --git a/database/migrations/2024_03_16_173148_add_foreign_id_column_to_approvals_table.php b/database/migrations/2024_03_16_173148_add_foreign_id_column_to_approvals_table.php new file mode 100644 index 0000000..3780c61 --- /dev/null +++ b/database/migrations/2024_03_16_173148_add_foreign_id_column_to_approvals_table.php @@ -0,0 +1,22 @@ +unsignedBigInteger('foreign_key')->nullable()->after('original_data'); + }); + } + + public function down(): void + { + Schema::table('approvals', function (Blueprint $table) { + $table->dropColumn('foreign_key'); + }); + } +}; diff --git a/phpunit.xml.dist b/phpunit.xml.dist index eb5ce8c..58d1bc2 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,14 +1,19 @@ - + - ./tests + ./tests - ./src + ./src diff --git a/src/ApprovalServiceProvider.php b/src/ApprovalServiceProvider.php index b361180..5b90b2d 100644 --- a/src/ApprovalServiceProvider.php +++ b/src/ApprovalServiceProvider.php @@ -1,6 +1,6 @@ static::insertApprovalRequest($model)); - static::updating(callback: fn ($model) => static::insertApprovalRequest($model)); + static::creating(callback: fn ($model): ?bool => static::insertApprovalRequest($model)); + static::updating(callback: fn ($model): ?bool => static::insertApprovalRequest($model)); } /** * Create an Approval request before committing to the database. */ - protected static function insertApprovalRequest($model) + protected static function insertApprovalRequest($model): ?bool { $filteredDirty = $model->getDirtyAttributes(); + $foreignKey = $model->getApprovalForeignKeyName(); + $foreignKeyValue = $filteredDirty[$foreignKey] ?? null; + + // Remove the foreign key from the dirty attributes + unset($filteredDirty[$foreignKey]); foreach ($filteredDirty as $key => $value) { if (isset($model->casts[$key]) && $model->casts[$key] === 'json') { @@ -30,40 +35,37 @@ protected static function insertApprovalRequest($model) } if ($model->isApprovalBypassed() || empty($filteredDirty)) { - return; + return null; } - $noNeedToProceed = true; $approvalAttributes = $model->getApprovalAttributes(); if (! empty($approvalAttributes)) { - $noNeedToProceed = collect($model->getDirty()) + $noApprovalNeeded = collect($model->getDirty()) ->except($approvalAttributes) - ->isEmpty(); - - if (! $noNeedToProceed) { - $noApprovalNeeded = collect($model->getDirty()) - ->except($approvalAttributes) - ->toArray(); + ->toArray(); + if (! empty($noApprovalNeeded)) { $model->discardChanges(); - $model->forceFill($noApprovalNeeded); } } - if (self::approvalModelExists($model) && $noNeedToProceed) { + if (self::approvalModelExists($model) && empty($noApprovalNeeded)) { return false; } $model->approvals()->create([ 'new_data' => $filteredDirty, 'original_data' => $model->getOriginalMatchingChanges(), + 'foreign_key' => $foreignKeyValue, ]); - if ($noNeedToProceed) { + if (empty($noApprovalNeeded)) { return false; } + + return true; } /** @@ -85,6 +87,14 @@ public function getApprovalAttributes(): array return $this->approvalAttributes ?? []; } + /** + * Get the name of the foreign key for the model. + */ + public function getApprovalForeignKeyName(): string + { + return 'user_id'; + } + /** * Check is the approval can be bypassed. */ diff --git a/src/Enums/ApprovalStatus.php b/src/Enums/ApprovalStatus.php index 1ee303f..7b76a35 100644 --- a/src/Enums/ApprovalStatus.php +++ b/src/Enums/ApprovalStatus.php @@ -1,6 +1,6 @@ expect(['dd', 'ddd', 'dump']) + ->each + ->not + ->toBeUsed(); diff --git a/tests/Feature/Models/ApprovalTest.php b/tests/Feature/Models/ApprovalTest.php index 6899a58..261d8da 100644 --- a/tests/Feature/Models/ApprovalTest.php +++ b/tests/Feature/Models/ApprovalTest.php @@ -1,22 +1,21 @@ name = 'Bob'; - $fakeModel->meta = 'green'; + $fakeModel->comment = 'I like pie'; // Save the model, bypassing approval $fakeModel->withoutApproval()->save(); // Update a fresh instance of the model - $fakeModel->fresh()->update(['name' => 'Chris']); + $fakeModel->fresh()->update(['comment' => 'The weather is nice']); // Approve the new changes $fakeModel->fresh()->approvals()->first()->approve(); @@ -30,8 +29,8 @@ // Check the model has been rolled back expect($fakeModel->fresh()->approvals()->first()) ->state->toBe(expected: ApprovalStatus::Pending) - ->new_data->toMatchArray(['name' => 'Bob']) - ->original_data->toMatchArray(['name' => 'Chris']) + ->new_data->toMatchArray(['comment' => 'I like pie']) + ->original_data->toMatchArray(['comment' => 'The weather is nice']) ->rolled_back_at->not->toBeNull(); // Assert the Events were fired @@ -41,16 +40,15 @@ test(description: 'an Approved Model can be rolled back and bypass', closure: function (): void { // Build a query - $fakeModel = new FakeModel(); + $fakeModel = new Comment(); - $fakeModel->name = 'Bob'; - $fakeModel->meta = 'green'; + $fakeModel->comment = 'I like pie'; // Save the model, bypassing approval $fakeModel->withoutApproval()->save(); // Update a fresh instance of the model - $fakeModel->fresh()->update(['name' => 'Chris']); + $fakeModel->fresh()->update(['comment' => 'The weather is nice']); // Approve the new changes $fakeModel->fresh()->approvals()->first()->approve(); @@ -61,23 +59,22 @@ // Check the model has been rolled back expect($fakeModel->fresh()->approvals()->first()) ->state->toBe(expected: ApprovalStatus::Approved) - ->new_data->toMatchArray(['name' => 'Bob']) - ->original_data->toMatchArray(['name' => 'Chris']) + ->new_data->toMatchArray(['comment' => 'I like pie']) + ->original_data->toMatchArray(['comment' => 'The weather is nice']) ->rolled_back_at->not->toBeNull(); }); test(description: 'a rolled back Approval can be conditionally set', closure: function () { // Build a query - $fakeModel = new FakeModel(); + $fakeModel = new Comment(); - $fakeModel->name = 'Bob'; - $fakeModel->meta = 'green'; + $fakeModel->comment = 'I like pie'; // Save the model, bypassing approval $fakeModel->withoutApproval()->save(); // Update a fresh instance of the model - $fakeModel->fresh()->update(['name' => 'Chris']); + $fakeModel->fresh()->update(['comment' => 'The weather is nice']); // Approve the new changes $fakeModel->fresh()->approvals()->first()->approve(); @@ -88,7 +85,7 @@ // Check the model has been rolled back expect($fakeModel->fresh()->approvals()->first()) ->state->toBe(expected: ApprovalStatus::Pending) - ->new_data->toMatchArray(['name' => 'Bob']) - ->original_data->toMatchArray(['name' => 'Chris']) + ->new_data->toMatchArray(['comment' => 'I like pie']) + ->original_data->toMatchArray(['comment' => 'The weather is nice']) ->rolled_back_at->not->toBeNull(); }); diff --git a/tests/Feature/MustBeApprovedTraitTest.php b/tests/Feature/MustBeApprovedTraitTest.php index 6baa288..8bcd4be 100644 --- a/tests/Feature/MustBeApprovedTraitTest.php +++ b/tests/Feature/MustBeApprovedTraitTest.php @@ -1,65 +1,60 @@ defer( - fn (): Approval => Approval::create($this->approvalData) + fn(): Approval => Approval::create($this->approvalData) )->assertDatabaseHas('approvals', [ - 'approvalable_type' => FakeModel::class, + 'approvalable_type' => Comment::class, 'approvalable_id' => 1, 'state' => ApprovalStatus::Pending, ]); test(description: 'an approvals model is created when a model is created with MustBeApproved trait set') // create a fake model - ->defer(callable: fn () => FakeModel::create($this->fakeModelData)) + ->defer(callable: fn() => Comment::create($this->fakeModelData)) // check it has been put in the approvals' table before the fake_models table ->assertDatabaseHas('approvals', [ 'new_data' => json_encode([ - 'name' => 'Chris', - 'meta' => 'red', - 'user_id' => null, + 'comment' => 'I have a radio in my car', ]), 'original_data' => json_encode([]), ]) // this should be blank as the trait has intervened - ->assertDatabaseMissing('fake_models', [ - 'name' => 'Chris', - 'meta' => 'red', + ->assertDatabaseMissing('comments', [ + 'comment' => 'I have a radio in my car', ]); test(description: 'a model is added when the "withoutApproval()" method is used', closure: function () { // build a query - $fakeModel = new FakeModel(); + $fakeModel = new Comment(); - $fakeModel->name = 'Bob'; - $fakeModel->meta = 'green'; + $fakeModel->comment = 'I like pie'; // save the model, bypassing approval $fakeModel->withoutApproval()->save(); - $this->assertDatabaseHas('fake_models', [ - 'name' => 'Bob', - 'meta' => 'green', + $this->assertDatabaseHas('comments', [ + 'comment' => 'I like pie', ]); $this->assertDatabaseMissing('approvals', [ 'new_data' => json_encode([ - 'name' => 'Bob', + 'comment' => 'I like pie', ]), ]); }); test(description: 'an approval model cannot be duplicated', closure: function () { // create a fake model with data - FakeModel::create($this->fakeModelData); + Comment::create($this->fakeModelData); // check it was added to the db $this->assertDatabaseHas('approvals', [ @@ -67,7 +62,7 @@ ]); // add another model with the same data... - FakeModel::create($this->fakeModelData); + Comment::create($this->fakeModelData); // as it is a duplicate, it should not be added to the DB $this->assertDatabaseCount('approvals', 1); @@ -75,7 +70,7 @@ test(description: 'a Model is added to the corresponding table when approved', closure: function () { // create a fake model with data - FakeModel::create($this->fakeModelData); + Comment::create($this->fakeModelData); // check it was added to the db $this->assertDatabaseHas('approvals', [ @@ -83,32 +78,32 @@ ]); // check that it hasn't been added to the fake_models table - $this->assertDatabaseMissing('fake_models', $this->fakeModelData); + $this->assertDatabaseMissing('comments', $this->fakeModelData); // approve the model Approval::first()->approve(); // check it was added to the fake_models table - $this->assertDatabaseHas('fake_models', $this->fakeModelData); + $this->assertDatabaseHas('comments', $this->fakeModelData); }); test(description: 'A Model that is only being updated, is persisted correctly to the database', closure: function () { // create a fake model with data - (new FakeModel($this->fakeModelData)) + (new Comment($this->fakeModelData)) ->withoutApproval() ->save(); // update the model with new data - FakeModel::first() - ->update(['name' => 'Bob']); + Comment::first() + ->update(['comment' => 'I like pie']); // check it was added to the db $this->assertDatabaseHas('approvals', [ 'new_data' => json_encode([ - 'name' => 'Bob', + 'comment' => 'I like pie', ]), 'original_data' => json_encode([ - 'name' => 'Chris', + 'comment' => 'I have a radio in my car', ]), ]); @@ -116,15 +111,14 @@ Approval::first()->approve(); // check the fake_models table was updated correctly - $this->assertDatabaseHas('fake_models', [ - 'name' => 'Bob', - 'meta' => 'red', + $this->assertDatabaseHas('comments', [ + 'comment' => 'I like pie', ]); }); test(description: 'a Model cannot be persisted when given a flag', closure: function () { // create a fake model with data - FakeModel::create($this->fakeModelData); + Comment::create($this->fakeModelData); // check it was added to the db $this->assertDatabaseHas('approvals', [ @@ -135,37 +129,30 @@ Approval::first()->approve(false); // check it was added to the fake_models table - $this->assertDatabaseCount('fake_models', 0); + $this->assertDatabaseCount('comments', 0); }); test(description: 'an approvals model is created when a model is created with MustBeApproved trait set and has the approvalInclude array set', closure: function () { $model = new class extends Model { use MustBeApproved; - protected $table = 'fake_models'; + protected $table = 'comments'; - protected array $approvalAttributes = ['name']; + protected array $approvalAttributes = ['comment']; protected $guarded = []; - - public $timestamps = false; }; // create a model - $model->create([ - 'name' => 'Neo', - 'meta' => 'blue', - ]); + $model->create(['comment' => 'Hello']); - // there should only be an approval model for the 'name' attribute, the 'meta' should be stored $this->assertDatabaseHas(table: Approval::class, data: [ - 'new_data' => json_encode(['name' => 'Neo']), + 'new_data' => json_encode(['comment' => 'Hello']), 'original_data' => json_encode([]), ]); - // Since the 'meta' attribute was not included in approvalInclude, it should be stored - $this->assertDatabaseHas(table: FakeModel::class, data: [ - 'meta' => 'blue', + $this->assertDatabaseMissing(table: Comment::class, data: [ + 'comment' => 'Hello', ]); }); @@ -174,8 +161,8 @@ $table->id(); $table->string('name')->nullable(); $table->string('meta')->nullable(); - $table->json('data')->nullable(); + $table->foreignId('user_id')->nullable(); }); $model = new class extends Model { @@ -198,7 +185,10 @@ // check if the data is stored correctly in the approval table $this->assertDatabaseHas(table: Approval::class, data: [ - 'new_data' => json_encode(['name' => 'Neo', 'data' => json_encode(['foo', 'bar'])]), + 'new_data' => json_encode([ + 'name' => 'Neo', + 'data' => json_encode(['foo', 'bar']), + ]), 'original_data' => json_encode([]), ]); @@ -230,6 +220,7 @@ $table->string('title'); $table->string('content'); $table->json('config'); + $table->foreignId('user_id')->nullable(); $table->timestamps(); }); @@ -282,3 +273,31 @@ expect($modelFromDatabase->config) ->toBe(['checked' => true]); }); + +test('the foreign key is extracted from the payload and stored in a separate column', function () { + $model = new class extends Model { + use MustBeApproved; + + protected $table = 'comments'; + + protected $guarded = []; + + public $timestamps = false; + + public function getApprovalForeignKeyName(): string + { + return 'user_id'; + } + }; + + // create a model + $model->create([ + 'name' => 'Neo', + ]); + + $this->assertDatabaseHas(table: Approval::class, data: [ + 'new_data' => json_encode(['name' => 'Neo']), + 'original_data' => json_encode([]), + 'foreign_key' => null, + ]); +}); diff --git a/tests/Feature/Scopes/ApprovalStateScopeTest.php b/tests/Feature/Scopes/ApprovalStateScopeTest.php index 119c4fa..2b71991 100644 --- a/tests/Feature/Scopes/ApprovalStateScopeTest.php +++ b/tests/Feature/Scopes/ApprovalStateScopeTest.php @@ -1,93 +1,68 @@ approvalData = [ - 'approvalable_type' => 'App\Models\FakeModel', + 'approvalable_type' => 'App\Models\Comment', 'approvalable_id' => 1, - 'state' => ApprovalStatus::Approved, - 'new_data' => json_encode(['name' => 'Chris']), - 'original_data' => json_encode(['name' => 'Bob']), + 'state' => $state, + 'new_data' => json_encode(['comment' => 'Hello']), + 'original_data' => json_encode(['comment' => 'Goodbye']), ]; $approval = Approval::create($this->approvalData); - expect($approval)->state->toBe(ApprovalStatus::Approved); -}); - -// same but for pending and rejected -test('Check if an Approval Model is pending', closure: function (): void { - $this->approvalData = [ - 'approvalable_type' => 'App\Models\FakeModel', - 'approvalable_id' => 1, - 'state' => ApprovalStatus::Pending, - 'new_data' => json_encode(['name' => 'Chris']), - 'original_data' => json_encode(['name' => 'Bob']), - ]; - - $approval = Approval::create($this->approvalData); - - expect($approval)->state->toBe(ApprovalStatus::Pending); -}); - -test('Check if an Approval Model is rejected', closure: function (): void { - $this->approvalData = [ - 'approvalable_type' => 'App\Models\FakeModel', - 'approvalable_id' => 1, - 'state' => ApprovalStatus::Rejected, - 'new_data' => json_encode(['name' => 'Chris']), - 'original_data' => json_encode(['name' => 'Bob']), - ]; - - $approval = Approval::create($this->approvalData); - - expect($approval)->state->toBe(ApprovalStatus::Rejected); -}); + expect($approval)->state->toBe($state); +})->with([ + ApprovalStatus::Approved, + ApprovalStatus::Pending, + ApprovalStatus::Rejected, +]); test(description: 'A Model can be Approved', closure: function (): void { - FakeModel::create($this->fakeModelData); + Comment::create($this->fakeModelData); $approval = Approval::first(); $approval->approve(); expect($approval)->fresh()->state->toBe(ApprovalStatus::Approved); - $this->assertDatabaseHas(table: 'fake_models', data: $this->fakeModelData); + $this->assertDatabaseHas(table: 'comments', data: $this->fakeModelData); }); test(description: 'A Model can be Rejected', closure: function (): void { - FakeModel::create($this->fakeModelData); + Comment::create($this->fakeModelData); $approval = Approval::first(); $approval->reject(); expect($approval)->fresh()->state->toBe(ApprovalStatus::Rejected); - $this->assertDatabaseMissing(table: 'fake_models', data: $this->fakeModelData); + $this->assertDatabaseMissing(table: 'comments', data: $this->fakeModelData); }); test(description: 'A Model can be Postponed', closure: function (): void { - FakeModel::create($this->fakeModelData); + Comment::create($this->fakeModelData); $approval = Approval::first(); $approval->postpone(); expect($approval)->fresh()->state->toBe(ApprovalStatus::Pending); - $this->assertDatabaseMissing(table: 'fake_models', data: $this->fakeModelData); + $this->assertDatabaseMissing(table: 'comments', data: $this->fakeModelData); }); it(description: 'only changes the status of the requested model', closure: function () { - FakeModel::create($this->fakeModelData); - FakeModel::create(['name' => 'Bob', 'meta' => 'green']); + Comment::create($this->fakeModelData); + Comment::create(['name' => 'Bob', 'meta' => 'green']); $modelOneApproval = Approval::first(); $modelOneApproval->approve(); @@ -97,7 +72,7 @@ }); test(description: 'An event is fired when a Model\'s state is changed', closure: function (string $state): void { - FakeModel::create($this->fakeModelData); + Comment::create($this->fakeModelData); Event::fake(); @@ -112,7 +87,7 @@ })->with(['approve', 'reject', 'postpone']); test(description: 'A Model can be Approved if a condition is met', closure: function (): void { - FakeModel::create($this->fakeModelData); + Comment::create($this->fakeModelData); Event::fake(); @@ -123,11 +98,11 @@ Event::assertDispatched(event: ModelApproved::class); - $this->assertDatabaseHas(table: 'fake_models', data: $this->fakeModelData); + $this->assertDatabaseHas(table: 'comments', data: $this->fakeModelData); }); test(description: 'A Model can be Approved unless a condition is met', closure: function (): void { - FakeModel::create($this->fakeModelData); + Comment::create($this->fakeModelData); Event::fake(); @@ -138,11 +113,11 @@ Event::assertDispatched(event: ModelApproved::class); - $this->assertDatabaseHas(table: 'fake_models', data: $this->fakeModelData); + $this->assertDatabaseHas(table: 'comments', data: $this->fakeModelData); }); test(description: 'A Model can be Rejected if a condition is met', closure: function (): void { - FakeModel::create($this->fakeModelData); + Comment::create($this->fakeModelData); Event::fake(); @@ -153,11 +128,11 @@ Event::assertDispatched(event: ModelRejected::class); - $this->assertDatabaseMissing(table: 'fake_models', data: $this->fakeModelData); + $this->assertDatabaseMissing(table: 'comments', data: $this->fakeModelData); }); test(description: 'A Model can be Rejected unless a condition is met', closure: function (): void { - FakeModel::create($this->fakeModelData); + Comment::create($this->fakeModelData); Event::fake(); @@ -168,11 +143,11 @@ Event::assertDispatched(event: ModelRejected::class); - $this->assertDatabaseMissing(table: 'fake_models', data: $this->fakeModelData); + $this->assertDatabaseMissing(table: 'comments', data: $this->fakeModelData); }); test(description: 'A Model can be Postponed if a condition is met', closure: function (): void { - FakeModel::create($this->fakeModelData); + Comment::create($this->fakeModelData); Event::fake(); @@ -183,11 +158,11 @@ Event::assertDispatched(event: ModelSetPending::class); - $this->assertDatabaseMissing(table: 'fake_models', data: $this->fakeModelData); + $this->assertDatabaseMissing(table: 'comments', data: $this->fakeModelData); }); test(description: 'A Model can be Postponed unless a condition is met', closure: function (): void { - FakeModel::create($this->fakeModelData); + Comment::create($this->fakeModelData); Event::fake(); @@ -198,7 +173,7 @@ Event::assertDispatched(event: ModelSetPending::class); - $this->assertDatabaseMissing(table: 'fake_models', data: $this->fakeModelData); + $this->assertDatabaseMissing(table: 'comments', data: $this->fakeModelData); }); test(description: 'The model approver is listed correctly', closure: function () { @@ -226,7 +201,7 @@ class FakeUser extends \Illuminate\Foundation\Auth\User $this->be($user); - FakeModel::create($this->fakeModelData); + Comment::create($this->fakeModelData); $approval = Approval::first(); $approval->approve(); diff --git a/tests/Models/Comment.php b/tests/Models/Comment.php new file mode 100644 index 0000000..8b73c8d --- /dev/null +++ b/tests/Models/Comment.php @@ -0,0 +1,13 @@ +beforeEach(hook: function (): void { $this->approvalData = [ - 'approvalable_type' => FakeModel::class, + 'approvalable_type' => Comment::class, 'approvalable_id' => 1, 'state' => ApprovalStatus::Pending, - 'new_data' => json_encode(['name' => 'Chris']), - 'original_data' => json_encode(['name' => 'Bob']), + 'new_data' => json_encode(['comment' => 'Hello']), + 'original_data' => json_encode(['comment' => 'Goodbye']), ]; $this->fakeModelData = [ - 'name' => 'Chris', - 'meta' => 'red', - 'user_id' => auth()->id(), + 'comment' => 'I have a radio in my car', ]; }) ->in(__DIR__); diff --git a/tests/TestCase.php b/tests/TestCase.php index 93e35a6..e4fe7e6 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -1,27 +1,12 @@ loadLaravelMigrations(); - - $this->loadMigrationsFrom(__DIR__.'/../database/migrations'); - - // Use this for the FakeModel in tests. - $this->loadMigrationsFrom(__DIR__.'/database/migrations'); - } - protected function getPackageProviders($app): array { return [ @@ -29,13 +14,28 @@ protected function getPackageProviders($app): array ]; } - public function getEnvironmentSetUp($app) + public function getEnvironmentSetUp($app): void { - config()->set('database.default', 'sqlite'); - config()->set('database.connections.sqlite', [ - 'driver' => 'sqlite', - 'database' => ':memory:', - 'prefix' => '', - ]); + config()->set('database.default', 'testing'); + + app('db')->connection()->getSchemaBuilder()->create('comments', function ($table) { + $table->id(); + $table->foreignId('user_id')->nullable(); + $table->string('comment'); + $table->timestamps(); + }); + + $migrationFiles = [ + '2022_02_12_195950_create_approvals_table.php', + '2023_10_09_204810_add_rolled_back_at_column_to_approvals_table.php', + '2023_11_17_002135_add_audited_by_column_to_approvals_table.php', + '2024_03_16_173148_add_foreign_id_column_to_approvals_table.php', + ]; + + foreach ($migrationFiles as $migrationFile) { + $migration = include __DIR__."/../database/migrations/$migrationFile"; + + $migration->up(); + } } } diff --git a/tests/database/migrations/2022_06_20_231650_create_fake_model_table.php b/tests/database/migrations/2022_06_20_231650_create_fake_model_table.php deleted file mode 100644 index b3af8fe..0000000 --- a/tests/database/migrations/2022_06_20_231650_create_fake_model_table.php +++ /dev/null @@ -1,18 +0,0 @@ -id(); - $table->string('name')->nullable(); - $table->unsignedBigInteger('user_id')->nullable(); - $table->string('meta')->nullable(); - }); - } -};