diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index 432d5a58..1f3d6d2a 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -72,4 +72,7 @@ jobs: - name: Execute tests run: | vendor/bin/phpunit - vendor/bin/phpunit tests/Unit/AuditTest.php --group command-line-url-resolver \ No newline at end of file + vendor/bin/phpunit tests/Unit/AuditTest.php --group command-line-url-resolver + + - name: Run PHPStan + run: composer analyse diff --git a/composer.json b/composer.json index f2039acf..c52db2c2 100644 --- a/composer.json +++ b/composer.json @@ -49,16 +49,27 @@ "phpunit/phpunit": "^9.6|^10.5|^11.0", "mockery/mockery": "^1.0", "orchestra/testbench": "^5.0|^6.0|^7.0|^8.0|^9.0", - "laravel/legacy-factories": "*" + "laravel/legacy-factories": "*", + "phpstan/phpstan": "^1.12", + "phpstan/phpstan-phpunit": "*", + "larastan/larastan": "*", + "phpstan/phpstan-mockery": "^1.1", + "phpstan/phpstan-strict-rules": "^1.6" + }, + "scripts": { + "analyse": "vendor/bin/phpstan analyse --memory-limit=1G", + "test": "vendor/bin/phpunit" }, "autoload": { "psr-4": { - "OwenIt\\Auditing\\": "src/" + "OwenIt\\Auditing\\": "src/", + "OwenIt\\Auditing\\Database\\Factories\\": "database/factories/" } }, "autoload-dev": { "psr-4": { - "OwenIt\\Auditing\\Tests\\": "tests/" + "OwenIt\\Auditing\\Tests\\": "tests/", + "OwenIt\\Auditing\\Tests\\Database\\Factories\\": "tests/database/factories/" } }, "suggest": { diff --git a/database/factories/AuditFactory.php b/database/factories/AuditFactory.php new file mode 100644 index 00000000..8890a57a --- /dev/null +++ b/database/factories/AuditFactory.php @@ -0,0 +1,42 @@ + + */ +class AuditFactory extends Factory +{ + protected $model = Audit::class; + + /** + * @return array + */ + public function definition(): array + { + $morphPrefix = Config::get('audit.user.morph_prefix', 'user'); + + return [ + $morphPrefix . '_id' => function () { + return User::factory()->create()->id; + }, + $morphPrefix . '_type' => User::class, + 'event' => 'updated', + 'auditable_id' => function () { + return Article::factory()->create()->id; + }, + 'auditable_type' => Article::class, + 'old_values' => [], + 'new_values' => [], + 'url' => fake()->url, + 'ip_address' => fake()->ipv4, + 'user_agent' => fake()->userAgent, + 'tags' => implode(',', fake()->words(4)), + ]; + } +} diff --git a/phpstan.neon b/phpstan.neon new file mode 100644 index 00000000..4eec7826 --- /dev/null +++ b/phpstan.neon @@ -0,0 +1,22 @@ +includes: + - vendor/larastan/larastan/extension.neon + - vendor/phpstan/phpstan-mockery/extension.neon + - vendor/phpstan/phpstan-phpunit/extension.neon +parameters: + level: 1 + paths: + - ./config + - ./database + - ./src + - ./tests + exceptions: + implicitThrows: false + check: + tooWideThrowType: true + excludePaths: + - tests/database/migrations +services: + - + class: PHPStan\Rules\Classes\RequireParentConstructCallRule + tags: + - phpstan.rules.rule diff --git a/phpunit.xml b/phpunit.xml index e4003711..e8781fa9 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -2,17 +2,19 @@ + + + src + config + database + + ./tests @@ -27,7 +29,7 @@ command-line-url-resolver - + ./src diff --git a/src/Auditable.php b/src/Auditable.php index 3696afb2..791c9c51 100644 --- a/src/Auditable.php +++ b/src/Auditable.php @@ -118,6 +118,7 @@ protected function resolveAuditExclusions() $this->excludedAttributes[] = $this->getUpdatedAtColumn(); } if (in_array(SoftDeletes::class, class_uses_recursive(get_class($this)))) { + assert(method_exists($this, 'getDeletedAtColumn')); $this->excludedAttributes[] = $this->getDeletedAtColumn(); } } @@ -707,7 +708,6 @@ public function transitionTo(Contracts\Audit $audit, bool $old = false): Contrac * @param array $columns * @param \Closure|null $callback * @return void - * @throws AuditingException */ public function auditAttach(string $relationName, $id, array $attributes = [], $touch = true, $columns = ['*'], $callback = null) { @@ -733,7 +733,6 @@ public function auditAttach(string $relationName, $id, array $attributes = [], $ * @param array $columns * @param \Closure|null $callback * @return int - * @throws AuditingException */ public function auditDetach(string $relationName, $ids = null, $touch = true, $columns = ['*'], $callback = null) { @@ -761,7 +760,6 @@ public function auditDetach(string $relationName, $ids = null, $touch = true, $c * @param array $columns * @param \Closure|null $callback * @return array - * @throws AuditingException */ public function auditSync(string $relationName, $ids, $detaching = true, $columns = ['*'], $callback = null) { @@ -854,6 +852,12 @@ private function dispatchRelationAuditEvent($relationName, $event, $old, $new) $this->isCustomEvent = false; } + /** + * @param string $relationName + * @param string $methodName + * @return void + * @throws AuditingException + */ private function validateRelationshipMethodExistence(string $relationName, string $methodName): void { if (!method_exists($this, $relationName) || !method_exists($this->{$relationName}(), $methodName)) { @@ -861,6 +865,12 @@ private function validateRelationshipMethodExistence(string $relationName, strin } } + /** + * @param BelongsToMany $relation + * @param \Closure $closure + * @return void + * @throws AuditingException + */ private function applyClosureToRelationship(BelongsToMany $relation, \Closure $closure): void { try { diff --git a/src/AuditableObserver.php b/src/AuditableObserver.php index 92bd562b..42867c14 100644 --- a/src/AuditableObserver.php +++ b/src/AuditableObserver.php @@ -107,7 +107,8 @@ protected function dispatchAudit(Auditable $model) $model->preloadResolverData(); if (!Config::get('audit.queue.enable', false)) { - return Auditor::execute($model); + Auditor::execute($model); + return; } if (!$this->fireDispatchingAuditEvent($model)) { diff --git a/src/Models/Audit.php b/src/Models/Audit.php index 187b01b9..44ec2d87 100644 --- a/src/Models/Audit.php +++ b/src/Models/Audit.php @@ -2,7 +2,9 @@ namespace OwenIt\Auditing\Models; +use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; +use OwenIt\Auditing\Database\Factories\AuditFactory; /** * @property string $tags @@ -15,6 +17,7 @@ class Audit extends Model implements \OwenIt\Auditing\Contracts\Audit { use \OwenIt\Auditing\Audit; + use HasFactory; /** * {@inheritdoc} @@ -41,4 +44,9 @@ public function getSerializedDate($date) { return $this->serializeDate($date); } + + public static function newFactory(): AuditFactory + { + return new AuditFactory(); + } } diff --git a/tests/AuditingTestCase.php b/tests/AuditingTestCase.php index c5565022..c8a5e7dd 100644 --- a/tests/AuditingTestCase.php +++ b/tests/AuditingTestCase.php @@ -66,17 +66,4 @@ protected function getPackageProviders($app) AuditingServiceProvider::class, ]; } - - /** - * Locate the Illuminate testing class. It changed namespace with v7 - * @see https://readouble.com/laravel/7.x/en/upgrade.html - * @return class-string<\Illuminate\Foundation\Testing\Assert|\Illuminate\Testing\Assert> - */ - public static function Assert(): string - { - if (class_exists('Illuminate\Foundation\Testing\Assert')) { - return '\Illuminate\Foundation\Testing\Assert'; - } - return '\Illuminate\Testing\Assert'; - } } diff --git a/tests/Functional/AuditingTest.php b/tests/Functional/AuditingTest.php index 6bc063d6..c2eabf74 100644 --- a/tests/Functional/AuditingTest.php +++ b/tests/Functional/AuditingTest.php @@ -29,11 +29,11 @@ class AuditingTest extends AuditingTestCase /** * @test */ - public function itWillNotAuditModelsWhenRunningFromTheConsole() + public function itWillNotAuditModelsWhenRunningFromTheConsole(): void { $this->app['config']->set('audit.console', false); - factory(User::class)->create(); + User::factory()->create(); $this->assertSame(1, User::query()->count()); $this->assertSame(0, Audit::query()->count()); @@ -42,11 +42,11 @@ public function itWillNotAuditModelsWhenRunningFromTheConsole() /** * @test */ - public function itWillAuditModelsWhenRunningFromTheConsole() + public function itWillAuditModelsWhenRunningFromTheConsole(): void { $this->app['config']->set('audit.console', true); - factory(User::class)->create(); + User::factory()->create(); $this->assertSame(1, User::query()->count()); $this->assertSame(1, Audit::query()->count()); @@ -55,14 +55,14 @@ public function itWillAuditModelsWhenRunningFromTheConsole() /** * @test */ - public function itWillAlwaysAuditModelsWhenNotRunningFromTheConsole() + public function itWillAlwaysAuditModelsWhenNotRunningFromTheConsole(): void { App::shouldReceive('runningInConsole') ->andReturn(false); $this->app['config']->set('audit.console', false); - factory(User::class)->create(); + User::factory()->create(); $this->assertSame(1, User::query()->count()); $this->assertSame(1, Audit::query()->count()); @@ -71,11 +71,11 @@ public function itWillAlwaysAuditModelsWhenNotRunningFromTheConsole() /** * @test */ - public function itWillNotAuditTheRetrievingEvent() + public function itWillNotAuditTheRetrievingEvent(): void { $this->app['config']->set('audit.console', true); - factory(User::class)->create(); + User::factory()->create(); $this->assertSame(1, User::query()->count()); $this->assertSame(1, Audit::query()->count()); @@ -89,7 +89,7 @@ public function itWillNotAuditTheRetrievingEvent() /** * @test */ - public function itWillAuditTheRetrievingEvent() + public function itWillAuditTheRetrievingEvent(): void { $this->app['config']->set('audit.console', true); $this->app['config']->set('audit.events', [ @@ -97,7 +97,7 @@ public function itWillAuditTheRetrievingEvent() 'retrieved', ]); - factory(User::class)->create(); + User::factory()->create(); $this->assertSame(1, User::query()->count()); $this->assertSame(1, Audit::query()->count()); @@ -110,13 +110,13 @@ public function itWillAuditTheRetrievingEvent() /** * @test */ - public function itWillAuditTheRetrievedEvent() + public function itWillAuditTheRetrievedEvent(): void { $this->app['config']->set('audit.events', [ 'retrieved', ]); - factory(Article::class)->create([ + Article::factory()->create([ 'title' => 'How To Audit Eloquent Models', 'content' => 'N/A', 'published_at' => null, @@ -135,47 +135,41 @@ public function itWillAuditTheRetrievedEvent() /** * @test */ - public function itWillAuditTheCreatedEvent() + public function itWillAuditTheCreatedEvent(): void { $this->app['config']->set('audit.events', [ 'created', ]); - factory(Article::class)->create([ + $testData = [ 'title' => 'How To Audit Eloquent Models', 'content' => 'N/A', 'published_at' => null, 'reviewed' => 0, - ]); + 'id' => 1, + ]; + Article::factory()->create($testData); $audit = Audit::first(); $this->assertEmpty($audit->old_values); - - self::Assert()::assertArraySubset([ - 'title' => 'How To Audit Eloquent Models', - 'content' => 'N/A', - 'published_at' => null, - 'reviewed' => 0, - 'id' => 1, - ], $audit->new_values, true); + self::assertSame($testData, $audit->new_values); } /** * @test */ - public function itWillAuditTheUpdatedEvent() + public function itWillAuditTheUpdatedEvent(): void { $this->app['config']->set('audit.events', [ 'updated', ]); - - $article = factory(Article::class)->create([ - 'title' => 'How To Audit Eloquent Models', - 'content' => 'N/A', - 'published_at' => null, - 'reviewed' => 0, - ]); + $article = Article::factory()->create([ + 'title' => 'How To Audit Eloquent Models', + 'content' => 'N/A', + 'published_at' => null, + 'reviewed' => 0, + ]); $now = Carbon::now(); @@ -187,29 +181,29 @@ public function itWillAuditTheUpdatedEvent() $audit = Audit::first(); - self::Assert()::assertArraySubset([ + self::assertSame([ 'content' => 'N/A', 'published_at' => null, 'reviewed' => 0, - ], $audit->old_values, true); + ], $audit->old_values); - self::Assert()::assertArraySubset([ + self::assertSame([ 'content' => Article::contentMutate('First step: install the laravel-auditing package.'), 'published_at' => $now->toDateTimeString(), 'reviewed' => 1, - ], $audit->new_values, true); + ], $audit->new_values); } /** * @test */ - public function itWillAuditTheDeletedEvent() + public function itWillAuditTheDeletedEvent(): void { $this->app['config']->set('audit.events', [ 'deleted', ]); - $article = factory(Article::class)->create([ + $article = Article::factory()->create([ 'title' => 'How To Audit Eloquent Models', 'content' => 'N/A', 'published_at' => null, @@ -220,13 +214,13 @@ public function itWillAuditTheDeletedEvent() $audit = Audit::first(); - self::Assert()::assertArraySubset([ + self::assertSame([ 'title' => 'How To Audit Eloquent Models', 'content' => 'N/A', 'published_at' => null, 'reviewed' => 0, 'id' => 1, - ], $audit->old_values, true); + ], $audit->old_values); $this->assertEmpty($audit->new_values); } @@ -234,13 +228,13 @@ public function itWillAuditTheDeletedEvent() /** * @test */ - public function itWillAuditTheRestoredEvent() + public function itWillAuditTheRestoredEvent(): void { $this->app['config']->set('audit.events', [ 'restored', ]); - $article = factory(Article::class)->create([ + $article = Article::factory()->create([ 'title' => 'How To Audit Eloquent Models', 'content' => 'N/A', 'published_at' => null, @@ -254,26 +248,26 @@ public function itWillAuditTheRestoredEvent() $this->assertEmpty($audit->old_values); - self::Assert()::assertArraySubset([ + self::assertSame([ 'title' => 'How To Audit Eloquent Models', 'content' => 'N/A', 'published_at' => null, 'reviewed' => 0, 'id' => 1, - ], $audit->new_values, true); + ], $audit->new_values); } /** * @test */ - public function itWillKeepAllAudits() + public function itWillKeepAllAudits(): void { $this->app['config']->set('audit.threshold', 0); $this->app['config']->set('audit.events', [ 'updated', ]); - $article = factory(Article::class)->create([ + $article = Article::factory()->create([ 'reviewed' => 1, ]); @@ -289,14 +283,14 @@ public function itWillKeepAllAudits() /** * @test */ - public function itWillRemoveOlderAuditsAboveTheThreshold() + public function itWillRemoveOlderAuditsAboveTheThreshold(): void { $this->app['config']->set('audit.threshold', 10); $this->app['config']->set('audit.events', [ 'updated', ]); - $article = factory(Article::class)->create([ + $article = Article::factory()->create([ 'title' => 'Title #0', ]); @@ -319,20 +313,20 @@ public function itWillRemoveOlderAuditsAboveTheThreshold() /** * @test */ - public function itWillNotAuditDueToUnsupportedDriver() + public function itWillNotAuditDueToUnsupportedDriver(): void { $this->app['config']->set('audit.driver', 'foo'); $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Driver [foo] not supported.'); - factory(Article::class)->create(); + Article::factory()->create(); } /** * @test */ - public function itWillNotAuditDueToClassWithoutDriverInterface() + public function itWillNotAuditDueToClassWithoutDriverInterface(): void { // We just pass a FQCN that does not implement the AuditDriver interface $this->app['config']->set('audit.driver', Article::class); @@ -340,17 +334,17 @@ public function itWillNotAuditDueToClassWithoutDriverInterface() $this->expectException(AuditingException::class); $this->expectExceptionMessage('The driver must implement the AuditDriver contract'); - factory(Article::class)->create(); + Article::factory()->create(); } /** * @test */ - public function itWillAuditUsingTheDefaultDriver() + public function itWillAuditUsingTheDefaultDriver(): void { $this->app['config']->set('audit.driver', null); - factory(Article::class)->create([ + Article::factory()->create([ 'title' => 'How To Audit Using The Fallback Driver', 'content' => 'N/A', 'published_at' => null, @@ -361,25 +355,25 @@ public function itWillAuditUsingTheDefaultDriver() $this->assertEmpty($audit->old_values); - self::Assert()::assertArraySubset([ + self::assertSame([ 'title' => 'How To Audit Using The Fallback Driver', 'content' => 'N/A', 'published_at' => null, 'reviewed' => 0, 'id' => 1, - ], $audit->new_values, true); + ], $audit->new_values); } /** * @test */ - public function itWillCancelTheAuditFromAnEventListener() + public function itWillCancelTheAuditFromAnEventListener(): void { Event::listen(Auditing::class, function () { return false; }); - factory(Article::class)->create(); + Article::factory()->create(); $this->assertNull(Audit::first()); } @@ -387,12 +381,12 @@ public function itWillCancelTheAuditFromAnEventListener() /** * @test */ - public function itDisablesAndEnablesAuditingBackAgain() + public function itDisablesAndEnablesAuditingBackAgain(): void { // Auditing is enabled by default $this->assertFalse(Article::$auditingDisabled); - factory(Article::class)->create(); + Article::factory()->create(); $this->assertSame(1, Article::count()); $this->assertSame(1, Audit::count()); @@ -401,7 +395,7 @@ public function itDisablesAndEnablesAuditingBackAgain() Article::disableAuditing(); $this->assertTrue(Article::$auditingDisabled); - factory(Article::class)->create(); + Article::factory()->create(); $this->assertSame(2, Article::count()); $this->assertSame(1, Audit::count()); @@ -410,7 +404,7 @@ public function itDisablesAndEnablesAuditingBackAgain() Article::enableAuditing(); $this->assertFalse(Article::$auditingDisabled); - factory(Article::class)->create(); + Article::factory()->create(); $this->assertSame(2, Audit::count()); $this->assertSame(3, Article::count()); @@ -419,14 +413,14 @@ public function itDisablesAndEnablesAuditingBackAgain() /** * @test */ - public function itDisablesAndEnablesAuditingBackAgainViaFacade() + public function itDisablesAndEnablesAuditingBackAgainViaFacade(): void { // Auditing is enabled by default $this->assertFalse(Article::$auditingDisabled); Article::disableAuditing(); - factory(Article::class)->create(); + Article::factory()->create(); $this->assertSame(1, Article::count()); $this->assertSame(0, Audit::count()); @@ -435,7 +429,7 @@ public function itDisablesAndEnablesAuditingBackAgainViaFacade() Article::enableAuditing(); $this->assertFalse(Article::$auditingDisabled); - factory(Article::class)->create(); + Article::factory()->create(); $this->assertSame(2, Article::count()); $this->assertSame(1, Audit::count()); @@ -444,13 +438,13 @@ public function itDisablesAndEnablesAuditingBackAgainViaFacade() /** * @test */ - public function itDisablesAndEnablesAuditingBackAgainViaWithoutAuditingMethod() + public function itDisablesAndEnablesAuditingBackAgainViaWithoutAuditingMethod(): void { // Auditing is enabled by default $this->assertFalse(Article::$auditingDisabled); Article::withoutAuditing(function () { - factory(Article::class)->create(); + Article::factory()->create(); }); $this->assertSame(1, Article::count()); @@ -458,7 +452,7 @@ public function itDisablesAndEnablesAuditingBackAgainViaWithoutAuditingMethod() $this->assertFalse(Article::$auditingDisabled); - factory(Article::class)->create(); + Article::factory()->create(); $this->assertSame(2, Article::count()); $this->assertSame(1, Audit::count()); @@ -468,9 +462,9 @@ public function itDisablesAndEnablesAuditingBackAgainViaWithoutAuditingMethod() * @test * @return void */ - public function itHandlesJsonColumnsCorrectly() + public function itHandlesJsonColumnsCorrectly(): void { - $article = factory(Article::class)->create(['config' => ['articleIsGood' => true, 'authorsJob' => 'vampire']]); + $article = Article::factory()->create(['config' => ['articleIsGood' => true, 'authorsJob' => 'vampire']]); $article->refresh(); $article->config = ['articleIsGood' => false, 'authorsJob' => 'vampire']; @@ -486,12 +480,12 @@ public function itHandlesJsonColumnsCorrectly() * @return void * @test */ - public function canAddAdditionalResolver() + public function canAddAdditionalResolver(): void { // added new resolver $this->app['config']->set('audit.resolvers.tenant_id', TenantResolver::class); - $article = factory(Article::class)->create(); + $article = Article::factory()->create(); $this->assertTrue(true); $audit = $article->audits()->first(); @@ -502,12 +496,12 @@ public function canAddAdditionalResolver() * @return void * @test */ - public function canDisableResolver() + public function canDisableResolver(): void { // added new resolver $this->app['config']->set('audit.resolvers.ip_address', null); - $article = factory(Article::class)->create(); + $article = Article::factory()->create(); $audit = $article->audits()->first(); $this->assertEmpty($audit->ip_address); @@ -517,7 +511,7 @@ public function canDisableResolver() * @test * @return void */ - public function itWillExcludeIfGlobalExcludeIsSet() + public function itWillExcludeIfGlobalExcludeIsSet(): void { $this->app['config']->set('audit.exclude', ['content']); @@ -534,7 +528,7 @@ public function itWillExcludeIfGlobalExcludeIsSet() * @test * @return void */ - public function localExcludeOverridesGlobalExclude() + public function localExcludeOverridesGlobalExclude(): void { $this->app['config']->set('audit.exclude', ['content']); @@ -552,7 +546,7 @@ public function localExcludeOverridesGlobalExclude() * @test * */ - public function itWillNotAuditModelsWhenValuesAreEmpty() + public function itWillNotAuditModelsWhenValuesAreEmpty(): void { $this->app['config']->set('audit.empty_values', false); @@ -579,7 +573,7 @@ public function itWillNotAuditModelsWhenValuesAreEmpty() * @return void * @test */ - public function itWillAuditRetrievedEventEvenIfAuditEmptyIsDisabled() + public function itWillAuditRetrievedEventEvenIfAuditEmptyIsDisabled(): void { $this->app['config']->set('audit.empty_values', false); $this->app['config']->set('audit.allowed_empty_values', ['retrieved']); @@ -591,7 +585,7 @@ public function itWillAuditRetrievedEventEvenIfAuditEmptyIsDisabled() $this->app['config']->set('audit.empty_values', false); /** @var Article $model */ - factory(Article::class)->create(); + Article::factory()->create(); Article::find(1); @@ -601,9 +595,9 @@ public function itWillAuditRetrievedEventEvenIfAuditEmptyIsDisabled() /** * @test */ - public function itWillAuditModelsWhenValuesAreEmpty() + public function itWillAuditModelsWhenValuesAreEmpty(): void { - $model = factory(Article::class)->create([ + $model = Article::factory()->create([ 'reviewed' => 0, ]); @@ -618,11 +612,11 @@ public function itWillAuditModelsWhenValuesAreEmpty() * @test * @return void */ - public function itWillAuditAttach() + public function itWillAuditAttach(): void { - $firstCategory = factory(Category::class)->create(); - $secondCategory = factory(Category::class)->create(); - $article = factory(Article::class)->create(); + $firstCategory = Category::factory()->create(); + $secondCategory = Category::factory()->create(); + $article = Article::factory()->create(); $article->auditAttach('categories', $firstCategory); $article->auditAttach('categories', $secondCategory); @@ -638,10 +632,10 @@ public function itWillAuditAttach() * @test * @return void */ - public function itWillNotAuditAttachByInvalidRelationName() + public function itWillNotAuditAttachByInvalidRelationName(): void { - $firstCategory = factory(Category::class)->create(); - $article = factory(Article::class)->create(); + $firstCategory = Category::factory()->create(); + $article = Article::factory()->create(); $this->expectExceptionMessage("Relationship invalidRelation was not found or does not support method attach"); @@ -652,11 +646,11 @@ public function itWillNotAuditAttachByInvalidRelationName() * @test * @return void */ - public function itWillAuditSync() + public function itWillAuditSync(): void { - $firstCategory = factory(Category::class)->create(); - $secondCategory = factory(Category::class)->create(); - $article = factory(Article::class)->create(); + $firstCategory = Category::factory()->create(); + $secondCategory = Category::factory()->create(); + $article = Article::factory()->create(); $article->categories()->attach($firstCategory); @@ -678,12 +672,12 @@ public function itWillAuditSync() * @test * @return void */ - public function itWillAuditSyncIndividually() + public function itWillAuditSyncIndividually(): void { Article::disableAuditing(); - $user = factory(User::class)->create(); - $category = factory(Category::class)->create(); - $article = factory(Article::class)->create(); + $user = User::factory()->create(); + $category = Category::factory()->create(); + $article = Article::factory()->create(); Article::enableAuditing(); $no_of_audits_before = Audit::where('auditable_type', Article::class)->count(); @@ -712,15 +706,15 @@ public function itWillAuditSyncIndividually() * @test * @return void */ - public function itWillAuditSyncWithPivotValues() + public function itWillAuditSyncWithPivotValues(): void { if (version_compare($this->app->version(), '8.0.0', '<')) { $this->markTestSkipped('This test is only for Laravel 8.0.0+'); } - $firstCategory = factory(Category::class)->create(); - $secondCategory = factory(Category::class)->create(); - $article = factory(Article::class)->create(); + $firstCategory = Category::factory()->create(); + $secondCategory = Category::factory()->create(); + $article = Article::factory()->create(); $article->categories()->attach([$firstCategory->getKey() => [ 'pivot_type' => 'PIVOT_1' ]]); @@ -755,12 +749,12 @@ public function itWillAuditSyncWithPivotValues() * @test * @return void */ - public function itWillAuditSyncByClosure() + public function itWillAuditSyncByClosure(): void { - $firstCategory = factory(Category::class)->create(); - $secondCategory = factory(Category::class)->create(); - $thirdCategory = factory(Category::class)->create(); - $article = factory(Article::class)->create(); + $firstCategory = Category::factory()->create(); + $secondCategory = Category::factory()->create(); + $thirdCategory = Category::factory()->create(); + $article = Article::factory()->create(); $article->categories()->attach([$firstCategory->getKey() => [ 'pivot_type' => 'PIVOT_1' ]]); $article->categories()->attach([$secondCategory->getKey() => [ 'pivot_type' => 'PIVOT_2' ]]); @@ -803,11 +797,11 @@ function ($categories) { return $categories->wherePivot('pivot_type', 'PIVOT_1') * @test * @return void */ - public function itWillNotAuditSyncByInvalidClosure() + public function itWillNotAuditSyncByInvalidClosure(): void { - $firstCategory = factory(Category::class)->create(); - $secondCategory = factory(Category::class)->create(); - $article = factory(Article::class)->create(); + $firstCategory = Category::factory()->create(); + $secondCategory = Category::factory()->create(); + $article = Article::factory()->create(); $article->categories()->attach($firstCategory); @@ -826,11 +820,11 @@ function ($categories) { return $categories->wherePivot('invalid_pivot_column', * @test * @return void */ - public function itWillAuditDetach() + public function itWillAuditDetach(): void { - $firstCategory = factory(Category::class)->create(); - $secondCategory = factory(Category::class)->create(); - $article = factory(Article::class)->create(); + $firstCategory = Category::factory()->create(); + $secondCategory = Category::factory()->create(); + $article = Article::factory()->create(); $article->categories()->attach($firstCategory); $article->categories()->attach($secondCategory); @@ -853,12 +847,12 @@ public function itWillAuditDetach() * @test * @return void */ - public function itWillAuditDetachByClosure() + public function itWillAuditDetachByClosure(): void { - $firstCategory = factory(Category::class)->create(); - $secondCategory = factory(Category::class)->create(); - $thirdCategory = factory(Category::class)->create(); - $article = factory(Article::class)->create(); + $firstCategory = Category::factory()->create(); + $secondCategory = Category::factory()->create(); + $thirdCategory = Category::factory()->create(); + $article = Article::factory()->create(); $article->categories()->attach([$firstCategory->getKey() => [ 'pivot_type' => 'PIVOT_1' ]]); $article->categories()->attach([$secondCategory->getKey() => [ 'pivot_type' => 'PIVOT_2' ]]); @@ -893,10 +887,10 @@ function ($categories) { return $categories->wherePivot('pivot_type', 'PIVOT_1') * @test * @return void */ - public function itWillNotAuditDetachByInvalidClosure() + public function itWillNotAuditDetachByInvalidClosure(): void { - $firstCategory = factory(Category::class)->create(); - $article = factory(Article::class)->create(); + $firstCategory = Category::factory()->create(); + $article = Article::factory()->create(); $article->categories()->attach($firstCategory); @@ -915,10 +909,10 @@ function ($categories) { return $categories->invalid(); } * @test * @return void */ - public function itWillAuditSyncWithoutChanges() + public function itWillAuditSyncWithoutChanges(): void { - $firstCategory = factory(Category::class)->create(); - $article = factory(Article::class)->create(); + $firstCategory = Category::factory()->create(); + $article = Article::factory()->create(); $article->categories()->attach($firstCategory); @@ -940,13 +934,13 @@ public function itWillAuditSyncWithoutChanges() * @test * @return void */ - public function itWillAuditSyncWhenSkippingEmptyValues() + public function itWillAuditSyncWhenSkippingEmptyValues(): void { $this->app['config']->set('audit.empty_values', false); - $firstCategory = factory(Category::class)->create(); - $secondCategory = factory(Category::class)->create(); - $article = factory(Article::class)->create(); + $firstCategory = Category::factory()->create(); + $secondCategory = Category::factory()->create(); + $article = Article::factory()->create(); $article->categories()->attach($firstCategory); @@ -968,12 +962,12 @@ public function itWillAuditSyncWhenSkippingEmptyValues() * @test * @return void */ - public function itWillNotAuditSyncWhenSkippingEmptyValuesAndNoChangesMade() + public function itWillNotAuditSyncWhenSkippingEmptyValuesAndNoChangesMade(): void { $this->app['config']->set('audit.empty_values', false); - $firstCategory = factory(Category::class)->create(); - $article = factory(Article::class)->create(); + $firstCategory = Category::factory()->create(); + $article = Article::factory()->create(); $article->categories()->attach($firstCategory); @@ -995,12 +989,12 @@ public function itWillNotAuditSyncWhenSkippingEmptyValuesAndNoChangesMade() * @test * @return void */ - public function itWillNotAuditAttachWhenSkippingEmptyValuesAndNoChangesMade() + public function itWillNotAuditAttachWhenSkippingEmptyValuesAndNoChangesMade(): void { $this->app['config']->set('audit.empty_values', false); - $firstCategory = factory(Category::class)->create(); - $article = factory(Article::class)->create(); + $firstCategory = Category::factory()->create(); + $article = Article::factory()->create(); $article->categories()->attach($firstCategory); @@ -1022,13 +1016,13 @@ public function itWillNotAuditAttachWhenSkippingEmptyValuesAndNoChangesMade() * @test * @return void */ - public function itWillNotAuditDetachWhenSkippingEmptyValuesAndNoChangesMade() + public function itWillNotAuditDetachWhenSkippingEmptyValuesAndNoChangesMade(): void { $this->app['config']->set('audit.empty_values', false); - $firstCategory = factory(Category::class)->create(); - $secondCategory = factory(Category::class)->create(); - $article = factory(Article::class)->create(); + $firstCategory = Category::factory()->create(); + $secondCategory = Category::factory()->create(); + $article = Article::factory()->create(); $article->categories()->attach($firstCategory); @@ -1050,9 +1044,9 @@ public function itWillNotAuditDetachWhenSkippingEmptyValuesAndNoChangesMade() * @test * @return void */ - public function canAuditAnyCustomEvent() + public function canAuditAnyCustomEvent(): void { - $article = factory(Article::class)->create(); + $article = Article::factory()->create(); $article->auditEvent = 'whateverYouWant'; $article->isCustomEvent = true; $article->auditCustomOld = [ @@ -1076,7 +1070,7 @@ public function canAuditAnyCustomEvent() * @test * @return void */ - public function canAuditCustomAuditModelImplementation() + public function canAuditCustomAuditModelImplementation(): void { $audit = null; Event::listen(Audited::class, function ($event) use (&$audit) { diff --git a/tests/Models/ApiModel.php b/tests/Models/ApiModel.php index 530ca074..09ff4529 100644 --- a/tests/Models/ApiModel.php +++ b/tests/Models/ApiModel.php @@ -5,11 +5,14 @@ use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\SoftDeletes; use OwenIt\Auditing\Contracts\Auditable; +use OwenIt\Auditing\Tests\Database\Factories\ApiModelFactory; +use Illuminate\Database\Eloquent\Factories\HasFactory; class ApiModel extends Model implements Auditable { use \OwenIt\Auditing\Auditable; use SoftDeletes; + use HasFactory; /** * @var string UUID key @@ -41,4 +44,9 @@ class ApiModel extends Model implements Auditable 'content', 'published_at', ]; + + public static function newFactory(): ApiModelFactory + { + return new ApiModelFactory(); + } } diff --git a/tests/Models/Article.php b/tests/Models/Article.php index eefb07c6..1ce8253e 100644 --- a/tests/Models/Article.php +++ b/tests/Models/Article.php @@ -3,15 +3,18 @@ namespace OwenIt\Auditing\Tests\Models; use Illuminate\Database\Eloquent\Casts\Attribute; +use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\SoftDeletes; use OwenIt\Auditing\Contracts\Auditable; use OwenIt\Auditing\Tests\Casts\Money; +use OwenIt\Auditing\Tests\Database\Factories\ArticleFactory; class Article extends Model implements Auditable { use \OwenIt\Auditing\Auditable; use SoftDeletes; + use HasFactory; protected $laravel_version; @@ -98,4 +101,9 @@ public static function contentMutate($value) return ucwords($value); } + + public static function newFactory(): ArticleFactory + { + return new ArticleFactory(); + } } diff --git a/tests/Models/Category.php b/tests/Models/Category.php index 99a9a607..1c6258c6 100644 --- a/tests/Models/Category.php +++ b/tests/Models/Category.php @@ -2,6 +2,15 @@ namespace OwenIt\Auditing\Tests\Models; +use Illuminate\Database\Eloquent\Factories\HasFactory; +use OwenIt\Auditing\Tests\Database\Factories\CategoryFactory; + class Category extends \Illuminate\Database\Eloquent\Model { + use HasFactory; + + public static function newFactory(): CategoryFactory + { + return new CategoryFactory(); + } } diff --git a/tests/Models/User.php b/tests/Models/User.php index c2bceae2..b9b5fe51 100644 --- a/tests/Models/User.php +++ b/tests/Models/User.php @@ -3,13 +3,16 @@ namespace OwenIt\Auditing\Tests\Models; use Illuminate\Contracts\Auth\Authenticatable; +use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use OwenIt\Auditing\Contracts\Auditable; +use OwenIt\Auditing\Tests\Database\Factories\UserFactory; class User extends Model implements Auditable, Authenticatable { use \Illuminate\Auth\Authenticatable; use \OwenIt\Auditing\Auditable; + use HasFactory; /** * {@inheritdoc} @@ -29,4 +32,9 @@ public function getFirstNameAttribute(string $value): string { return ucfirst($value); } + + public static function newFactory(): UserFactory + { + return new UserFactory(); + } } diff --git a/tests/Unit/AuditTest.php b/tests/Unit/AuditTest.php index 637d0432..f4d7c4e3 100644 --- a/tests/Unit/AuditTest.php +++ b/tests/Unit/AuditTest.php @@ -18,50 +18,50 @@ class AuditTest extends AuditingTestCase * @group Audit::resolveData * @test */ - public function itResolvesAuditData() + public function itResolvesAuditData(): void { $now = Carbon::now(); - - $article = factory(Article::class)->create([ + $article = Article::factory()->create([ 'title' => 'How To Audit Eloquent Models', 'content' => 'First step: install the laravel-auditing package.', 'reviewed' => 1, 'published_at' => $now, ]); + /** @var Audit $audit */ $audit = $article->audits()->first(); $resolvedData = $audit->resolveData(); $this->assertCount(15, $resolvedData); - self::Assert()::assertArraySubset([ + self::assertSame([ 'audit_id' => 1, 'audit_event' => 'created', - 'audit_url' => UrlResolver::resolveCommandLine(), - 'audit_ip_address' => '127.0.0.1', - 'audit_user_agent' => 'Symfony', 'audit_tags' => null, 'audit_created_at' => $audit->getSerializedDate($audit->created_at), 'audit_updated_at' => $audit->getSerializedDate($audit->updated_at), 'user_id' => null, 'user_type' => null, + 'audit_url' => UrlResolver::resolveCommandLine(), + 'audit_ip_address' => '127.0.0.1', + 'audit_user_agent' => 'Symfony', 'new_title' => 'How To Audit Eloquent Models', 'new_content' => Article::contentMutate('First step: install the laravel-auditing package.'), 'new_published_at' => $now->toDateTimeString(), 'new_reviewed' => 1, 'new_id' => 1, - ], $resolvedData, true); + ], $resolvedData); } /** * @group Audit::resolveData * @test */ - public function itResolvesAuditDataIncludingUserAttributes() + public function itResolvesAuditDataIncludingUserAttributes(): void { $now = Carbon::now(); - $user = factory(User::class)->create([ + $user = User::factory()->create([ 'is_admin' => 1, 'first_name' => 'rick', 'last_name' => 'Sanchez', @@ -70,7 +70,7 @@ public function itResolvesAuditDataIncludingUserAttributes() $this->actingAs($user); - $article = factory(Article::class)->create([ + $article = Article::factory()->create([ 'title' => 'How To Audit Eloquent Models', 'content' => 'First step: install the laravel-auditing package.', 'reviewed' => 1, @@ -78,19 +78,21 @@ public function itResolvesAuditDataIncludingUserAttributes() ]); $audit = $article->audits()->first(); + $resolvedData = $audit->resolveData(); - $this->assertCount(21, $resolvedData = $audit->resolveData()); - - self::Assert()::assertArraySubset([ + $this->assertCount(21, $resolvedData); + self::assertSame([ 'audit_id' => 2, 'audit_event' => 'created', - 'audit_url' => UrlResolver::resolveCommandLine(), - 'audit_ip_address' => '127.0.0.1', - 'audit_user_agent' => 'Symfony', 'audit_tags' => null, 'audit_created_at' => $audit->getSerializedDate($audit->created_at), 'audit_updated_at' => $audit->getSerializedDate($audit->updated_at), + 'user_id' => 1, 'user_type' => User::class, + 'audit_url' => UrlResolver::resolveCommandLine(), + 'audit_ip_address' => '127.0.0.1', + 'audit_user_agent' => 'Symfony', + 'user_is_admin' => 1, 'user_first_name' => 'rick', 'user_last_name' => 'Sanchez', 'user_email' => 'rick@wubba-lubba-dub.dub', @@ -101,7 +103,7 @@ public function itResolvesAuditDataIncludingUserAttributes() 'new_published_at' => $now->toDateTimeString(), 'new_reviewed' => 1, 'new_id' => 1, - ], $resolvedData, true); + ], $resolvedData); } /** @@ -109,9 +111,10 @@ public function itResolvesAuditDataIncludingUserAttributes() * @group Audit::getDataValue * @test */ - public function itReturnsTheAppropriateAuditableDataValues() + public function itReturnsTheAppropriateAuditableDataValues(): void { - $user = factory(User::class)->create([ + + $user = User::factory()->create([ 'is_admin' => 1, 'first_name' => 'rick', 'last_name' => 'Sanchez', @@ -120,7 +123,7 @@ public function itReturnsTheAppropriateAuditableDataValues() $this->actingAs($user); - $audit = factory(Article::class)->create([ + $audit = Article::factory()->create([ 'title' => 'How To Audit Eloquent Models', 'content' => 'First step: install the laravel-auditing package.', 'reviewed' => 1, @@ -155,9 +158,9 @@ public function itReturnsTheAppropriateAuditableDataValues() * @group Audit::getDataValue * @test */ - public function itReturnsTheAppropriateAuditableDataValuesWithCustomCastValueObject() + public function itReturnsTheAppropriateAuditableDataValuesWithCustomCastValueObject(): void { - $user = factory(User::class)->create([ + $user = User::factory()->create([ 'is_admin' => 1, 'first_name' => 'rick', 'last_name' => 'Sanchez', @@ -166,7 +169,7 @@ public function itReturnsTheAppropriateAuditableDataValuesWithCustomCastValueObj $this->actingAs($user); - $article = factory(Article::class)->create([ + $article = Article::factory()->create([ 'title' => 'How To Audit Eloquent Models', 'content' => 'First step: install the laravel-auditing package.', 'reviewed' => 1, @@ -187,24 +190,24 @@ public function itReturnsTheAppropriateAuditableDataValuesWithCustomCastValueObj * @group Audit::getMetadata * @test */ - public function itReturnsAuditMetadataAsArray() + public function itReturnsAuditMetadataAsArray(): void { - $audit = factory(Article::class)->create()->audits()->first(); + $audit = Article::factory()->create()->audits()->first(); $this->assertCount(10, $metadata = $audit->getMetadata()); - self::Assert()::assertArraySubset([ + self::assertSame([ 'audit_id' => 1, 'audit_event' => 'created', - 'audit_url' => UrlResolver::resolveCommandLine(), - 'audit_ip_address' => '127.0.0.1', - 'audit_user_agent' => 'Symfony', 'audit_tags' => null, 'audit_created_at' => $audit->getSerializedDate($audit->created_at), 'audit_updated_at' => $audit->getSerializedDate($audit->updated_at), 'user_id' => null, 'user_type' => null, - ], $metadata, true); + 'audit_url' => UrlResolver::resolveCommandLine(), + 'audit_ip_address' => '127.0.0.1', + 'audit_user_agent' => 'Symfony', + ], $metadata); } /** @@ -213,20 +216,20 @@ public function itReturnsAuditMetadataAsArray() * @group command-line-url-resolver * @test */ - public function itReturnsProperCommandLineInUrlAuditMetadata() + public function itReturnsProperCommandLineInUrlAuditMetadata(): void { - $audit = factory(Article::class)->create()->audits()->first(); + $audit = Article::factory()->create()->audits()->first(); - self::Assert()::assertEquals($audit->getMetadata()['audit_url'], 'vendor/bin/phpunit tests/Unit/AuditTest.php --group command-line-url-resolver'); + self::assertEquals($audit->getMetadata()['audit_url'], 'vendor/bin/phpunit tests/Unit/AuditTest.php --group command-line-url-resolver'); } /** * @group Audit::getMetadata * @test */ - public function itReturnsAuditMetadataIncludingUserAttributesAsArray() + public function itReturnsAuditMetadataIncludingUserAttributesAsArray(): void { - $user = factory(User::class)->create([ + $user = User::factory()->create([ 'is_admin' => 1, 'first_name' => 'rick', 'last_name' => 'Sanchez', @@ -236,37 +239,37 @@ public function itReturnsAuditMetadataIncludingUserAttributesAsArray() $this->actingAs($user); /** @var Audit $audit */ - $audit = factory(Article::class)->create()->audits()->first(); + $audit = Article::factory()->create()->audits()->first(); $this->assertCount(16, $metadata = $audit->getMetadata()); - self::Assert()::assertArraySubset([ + self::assertSame([ 'audit_id' => 2, 'audit_event' => 'created', - 'audit_url' => UrlResolver::resolveCommandLine(), - 'audit_ip_address' => '127.0.0.1', - 'audit_user_agent' => 'Symfony', 'audit_tags' => null, 'audit_created_at' => $audit->getSerializedDate($audit->created_at), 'audit_updated_at' => $audit->getSerializedDate($audit->updated_at), 'user_id' => 1, 'user_type' => User::class, + 'audit_url' => UrlResolver::resolveCommandLine(), + 'audit_ip_address' => '127.0.0.1', + 'audit_user_agent' => 'Symfony', 'user_is_admin' => true, 'user_first_name' => 'Rick', 'user_last_name' => 'Sanchez', 'user_email' => 'rick@wubba-lubba-dub.dub', 'user_created_at' => $audit->getSerializedDate($user->created_at), 'user_updated_at' => $audit->getSerializedDate($user->updated_at), - ], $metadata, true); + ], $metadata); } /** * @group Audit::getMetadata * @test */ - public function itReturnsAuditMetadataAsJsonString() + public function itReturnsAuditMetadataAsJsonString(): void { - $audit = factory(Article::class)->create()->audits()->first(); + $audit = Article::factory()->create()->audits()->first(); $metadata = $audit->getMetadata(true, JSON_PRETTY_PRINT); @@ -292,9 +295,9 @@ public function itReturnsAuditMetadataAsJsonString() * @group Audit::getMetadata * @test */ - public function itReturnsAuditMetadataIncludingUserAttributesAsJsonString() + public function itReturnsAuditMetadataIncludingUserAttributesAsJsonString(): void { - $user = factory(User::class)->create([ + $user = User::factory()->create([ 'is_admin' => 1, 'first_name' => 'rick', 'last_name' => 'Sanchez', @@ -303,7 +306,7 @@ public function itReturnsAuditMetadataIncludingUserAttributesAsJsonString() $this->actingAs($user); - $audit = factory(Article::class)->create()->audits()->first(); + $audit = Article::factory()->create()->audits()->first(); $metadata = $audit->getMetadata(true, JSON_PRETTY_PRINT); @@ -337,11 +340,11 @@ public function itReturnsAuditMetadataIncludingUserAttributesAsJsonString() * @group Audit::getModified * @test */ - public function itReturnsAuditableModifiedAttributesAsArray() + public function itReturnsAuditableModifiedAttributesAsArray(): void { $now = Carbon::now()->second(0)->microsecond(0); - $audit = factory(Article::class)->create([ + $audit = Article::factory()->create([ 'title' => 'How To Audit Eloquent Models', 'content' => 'First step: install the laravel-auditing package.', 'reviewed' => 1, @@ -350,7 +353,7 @@ public function itReturnsAuditableModifiedAttributesAsArray() $this->assertCount(5, $modified = $audit->getModified()); - self::Assert()::assertArraySubset([ + self::assertSame([ 'title' => [ 'new' => 'HOW TO AUDIT ELOQUENT MODELS', ], @@ -366,19 +369,19 @@ public function itReturnsAuditableModifiedAttributesAsArray() 'id' => [ 'new' => 1, ], - ], $modified, true); + ], $modified); } /** * @group Audit::getModified * @test */ - public function itReturnsAuditableModifiedAttributesAsJsonString() + public function itReturnsAuditableModifiedAttributesAsJsonString(): void { $now = Carbon::now()->second(0)->microsecond(0); /** @var Audit $audit */ - $audit = factory(Article::class)->create([ + $audit = Article::factory()->create([ 'title' => 'How To Audit Eloquent Models', 'content' => 'First step: install the laravel-auditing package.', 'reviewed' => 1, @@ -413,12 +416,12 @@ public function itReturnsAuditableModifiedAttributesAsJsonString() * @group Audit::getModified * @test */ - public function itReturnsDecodedAuditableAttributes() + public function itReturnsDecodedAuditableAttributes(): void { $article = new itReturnsDecodedAuditableAttributesArticle(); // Audit with redacted/encoded attributes - $audit = factory(Audit::class)->create([ + $audit = Audit::factory()->create([ 'auditable_type' => get_class($article), 'old_values' => [ 'title' => 'SG93IFRvIEF1ZGl0IE1vZGVscw==', @@ -434,7 +437,7 @@ public function itReturnsDecodedAuditableAttributes() $this->assertCount(3, $modified = $audit->getModified()); - self::Assert()::assertArraySubset([ + self::assertSame([ 'title' => [ 'new' => 'HOW TO AUDIT ELOQUENT MODELS', 'old' => 'HOW TO AUDIT MODELS', @@ -447,34 +450,34 @@ public function itReturnsDecodedAuditableAttributes() 'new' => true, 'old' => false, ], - ], $modified, true); + ], $modified); } /** * @group Audit::getTags * @test */ - public function itReturnsTags() + public function itReturnsTags(): void { - $audit = factory(Audit::class)->create([ + $audit = Audit::factory()->create([ 'tags' => 'foo,bar,baz', ]); $this->assertIsArray($audit->getTags()); - self::Assert()::assertArraySubset([ + self::assertSame([ 'foo', 'bar', 'baz', - ], $audit->getTags(), true); + ], $audit->getTags()); } /** * @group Audit::getTags * @test */ - public function itReturnsEmptyTags() + public function itReturnsEmptyTags(): void { - $audit = factory(Audit::class)->create([ + $audit = Audit::factory()->create([ 'tags' => null, ]); @@ -491,4 +494,4 @@ class itReturnsDecodedAuditableAttributesArticle extends Article 'title' => Base64Encoder::class, 'content' => LeftRedactor::class, ]; -} \ No newline at end of file +} diff --git a/tests/Unit/AuditableObserverTest.php b/tests/Unit/AuditableObserverTest.php index ac0a1a49..55c9ac58 100644 --- a/tests/Unit/AuditableObserverTest.php +++ b/tests/Unit/AuditableObserverTest.php @@ -18,6 +18,7 @@ class AuditableObserverTest extends AuditingTestCase */ public function itWillCancelTheAuditDispatchingFromAnEventListener($eventMethod) { + Event::fake( [ DispatchAudit::class, @@ -29,7 +30,7 @@ public function itWillCancelTheAuditDispatchingFromAnEventListener($eventMethod) }); $observer = new AuditableObserver(); - $model = factory(Article::class)->create(); + $model = Article::factory()->create(); $observer->$eventMethod($model); @@ -48,7 +49,7 @@ public function itDispatchesTheCorrectEvents(string $eventMethod) Event::fake(); $observer = new AuditableObserver(); - $model = factory(Article::class)->create(); + $model = Article::factory()->create(); $observer->$eventMethod($model); @@ -79,7 +80,7 @@ public function itDispatchesTheCorrectEvents(string $eventMethod) public function itExecutesTheAuditorSuccessfully(string $eventMethod, bool $expectedBefore, bool $expectedAfter) { $observer = new AuditableObserver(); - $model = factory(Article::class)->create(); + $model = Article::factory()->create(); $this->assertSame($expectedBefore, $observer::$restoring); diff --git a/tests/Unit/AuditableTest.php b/tests/Unit/AuditableTest.php index 4ee3e083..f43cfbbf 100644 --- a/tests/Unit/AuditableTest.php +++ b/tests/Unit/AuditableTest.php @@ -174,12 +174,12 @@ public function itReturnsTheDefaultAuditEvents() { $model = new Article(); - self::Assert()::assertArraySubset([ + self::assertSame([ 'created', 'updated', 'deleted', 'restored', - ], $model->getAuditEvents(), true); + ], $model->getAuditEvents()); } /** @@ -195,10 +195,10 @@ public function itReturnsTheCustomAuditEventsFromAttribute() 'archived', ]; - self::Assert()::assertArraySubset([ + self::assertSame([ 'published' => 'getPublishedEventAttributes', 'archived', - ], $model->getAuditEvents(), true); + ], $model->getAuditEvents()); } /** @@ -214,10 +214,10 @@ public function itReturnsTheCustomAuditEventsFromConfig() $model = new Article(); - self::Assert()::assertArraySubset([ + self::assertSame([ 'published' => 'getPublishedEventAttributes', 'archived', - ], $model->getAuditEvents(), true); + ], $model->getAuditEvents()); } /** @@ -447,7 +447,7 @@ public function itReturnsTheAuditData() { $now = Carbon::now(); - $model = factory(Article::class)->make([ + $model = Article::factory()->make([ 'title' => 'How To Audit Eloquent Models', 'content' => 'First step: install the laravel-auditing package.', 'reviewed' => 1, @@ -459,24 +459,24 @@ public function itReturnsTheAuditData() $this->assertCount(11, $auditData = $model->toAudit()); $morphPrefix = config('audit.user.morph_prefix', 'user'); - self::Assert()::assertArraySubset([ + self::assertSame([ 'old_values' => [], 'new_values' => [ 'title' => 'How To Audit Eloquent Models', 'content' => Article::contentMutate('First step: install the laravel-auditing package.'), - 'reviewed' => 1, 'published_at' => $now->toDateTimeString(), + 'reviewed' => 1, ], 'event' => 'created', 'auditable_id' => null, 'auditable_type' => Article::class, $morphPrefix . '_id' => null, $morphPrefix . '_type' => null, + 'tags' => null, 'url' => UrlResolver::resolveCommandLine(), 'ip_address' => '127.0.0.1', 'user_agent' => 'Symfony', - 'tags' => null, - ], $auditData, true); + ], $auditData); } /** @@ -501,13 +501,13 @@ public function itReturnsTheAuditDataIncludingUserAttributes( $guard, ]); - $user = factory(User::class)->create(); + $user = User::factory()->create(); $this->actingAs($user, $driver); $now = Carbon::now(); - $model = factory(Article::class)->make([ + $model = Article::factory()->make([ 'title' => 'How To Audit Eloquent Models', 'content' => 'First step: install the laravel-auditing package.', 'reviewed' => 1, @@ -519,24 +519,24 @@ public function itReturnsTheAuditDataIncludingUserAttributes( $this->assertCount(11, $auditData = $model->toAudit()); $morphPrefix = config('audit.user.morph_prefix', 'user'); - self::Assert()::assertArraySubset([ + self::assertSame([ 'old_values' => [], 'new_values' => [ 'title' => 'How To Audit Eloquent Models', 'content' => Article::contentMutate('First step: install the laravel-auditing package.'), - 'reviewed' => 1, 'published_at' => $now->toDateTimeString(), + 'reviewed' => 1, ], 'event' => 'created', 'auditable_id' => null, 'auditable_type' => Article::class, $morphPrefix . '_id' => $id, $morphPrefix . '_type' => $type, + 'tags' => null, 'url' => UrlResolver::resolveCommandLine(), 'ip_address' => '127.0.0.1', 'user_agent' => 'Symfony', - 'tags' => null, - ], $auditData, true); + ], $auditData); } /** @@ -581,7 +581,7 @@ public function itExcludesAttributesFromTheAuditDataWhenInStrictMode() { $this->app['config']->set('audit.strict', true); - $model = factory(Article::class)->make([ + $model = Article::factory()->make([ 'title' => 'How To Audit Eloquent Models', 'content' => 'First step: install the laravel-auditing package.', 'reviewed' => 1, @@ -602,7 +602,7 @@ public function itExcludesAttributesFromTheAuditDataWhenInStrictMode() $this->assertCount(11, $auditData = $model->toAudit()); $morphPrefix = config('audit.user.morph_prefix', 'user'); - self::Assert()::assertArraySubset([ + self::assertSame([ 'old_values' => [], 'new_values' => [ 'title' => 'How To Audit Eloquent Models', @@ -613,11 +613,11 @@ public function itExcludesAttributesFromTheAuditDataWhenInStrictMode() 'auditable_type' => Article::class, $morphPrefix . '_id' => null, $morphPrefix . '_type' => null, + 'tags' => null, 'url' => UrlResolver::resolveCommandLine(), 'ip_address' => '127.0.0.1', 'user_agent' => 'Symfony', - 'tags' => null, - ], $auditData, true); + ], $auditData); } /** @@ -630,7 +630,7 @@ public function itFailsWhenTheAttributeModifierImplementationIsInvalid() $this->expectException(AuditingException::class); $this->expectExceptionMessage('Invalid AttributeModifier implementation: invalidAttributeRedactorOrEncoder'); - $model = factory(Article::class)->make(); + $model = Article::factory()->make(); $model->attributeModifiers = [ 'title' => 'invalidAttributeRedactorOrEncoder', @@ -648,7 +648,7 @@ public function itFailsWhenTheAttributeModifierImplementationIsInvalid() */ public function itModifiesTheAuditAttributesSuccessfully() { - $model = factory(Article::class)->make([ + $model = Article::factory()->make([ 'title' => 'How To Audit Models', 'content' => 'N/A', 'reviewed' => 0, @@ -672,7 +672,7 @@ public function itModifiesTheAuditAttributesSuccessfully() 'reviewed' => Base64Encoder::class, ]; - self::Assert()::assertArraySubset([ + self::assertSame([ 'old_values' => [ 'title' => 'Ho#################', 'content' => '##A', @@ -685,7 +685,16 @@ public function itModifiesTheAuditAttributesSuccessfully() 'published_at' => $now->toDateTimeString(), 'reviewed' => 'MQ==', ], - ], $model->toAudit(), true); + 'event' => 'updated', + 'auditable_id' => null, + 'auditable_type' => 'OwenIt\Auditing\Tests\Models\Article', + 'prefix_id' => null, + 'prefix_type' => null, + 'tags' => null, + 'url' => UrlResolver::resolveCommandLine(), + 'ip_address' => '127.0.0.1', + 'user_agent' => 'Symfony', + ], $model->toAudit()); } /** @@ -716,15 +725,14 @@ public function transformAudit(array $data): array $this->assertCount(11, $auditData = $model->toAudit()); - self::Assert()::assertArraySubset([ - 'new_values' => [ + self::assertSame([], $auditData['old_values']); + self::assertSame([ 'title' => 'How To Audit Eloquent Models', 'content' => 'First step: install the laravel-auditing package.', 'reviewed' => 1, 'published_at' => '2012-06-14 15:03:00', 'slug' => 'how-to-audit-eloquent-models', - ], - ], $auditData, true); + ], $auditData['new_values']); } /** @@ -735,7 +743,7 @@ public function itReturnsTheDefaultAttributesToBeIncludedInTheAudit() { $model = new Article(); - self::Assert()::assertArraySubset([], $model->getAuditInclude(), true); + self::assertSame([], $model->getAuditInclude()); } /** @@ -751,10 +759,10 @@ public function itReturnsTheCustomAttributesToBeIncludedInTheAudit() 'content', ]; - self::Assert()::assertArraySubset([ + self::assertSame([ 'title', 'content', - ], $model->getAuditInclude(), true); + ], $model->getAuditInclude()); } /** @@ -765,7 +773,7 @@ public function itReturnsTheDefaultAttributesToBeExcludedFromTheAudit() { $model = new Article(); - self::Assert()::assertArraySubset([], $model->getAuditExclude(), true); + self::assertSame([], $model->getAuditExclude()); } /** @@ -780,9 +788,9 @@ public function itReturnsTheCustomAttributesToBeExcludedFromTheAudit() 'published_at', ]; - self::Assert()::assertArraySubset([ + self::assertSame([ 'published_at', - ], $model->getAuditExclude(), true); + ], $model->getAuditExclude()); } /** @@ -799,7 +807,7 @@ public function itExcludesAttributesFromExclude() $model->save(); /** @var Audit $audit */ - $audit = Audit::all()->first(); + $audit = Audit::first(); $this->assertArrayNotHasKey('title', $audit->getModified()); } @@ -959,7 +967,7 @@ public function itReturnsTheDefaultGeneratedAuditTags() { $model = new Article(); - self::Assert()::assertArraySubset([], $model->generateTags(), true); + self::assertSame([], $model->generateTags(), true); } /** @@ -978,7 +986,7 @@ public function generateTags(): array } }; - self::Assert()::assertArraySubset([ + self::assertSame([ 'foo', 'bar', ], $model->generateTags(), true); @@ -993,7 +1001,7 @@ public function itFailsToTransitionWhenTheAuditAuditableTypeDoesNotMatchTheModel $this->expectException(AuditableTransitionException::class); $this->expectExceptionMessage('Expected Auditable type OwenIt\Auditing\Tests\Models\Article, got OwenIt\Auditing\Tests\Models\User instead'); - $audit = factory(Audit::class)->make([ + $audit = Audit::factory()->make([ 'auditable_type' => User::class, ]); @@ -1013,7 +1021,7 @@ public function itWorksOnTimesRestoredCorrectly() $originalStart = new Carbon('2022-01-01 12:00:00'); - $article = factory(Article::class)->create([ + $article = Article::factory()->create([ 'title' => 'How To Audit Eloquent Models', 'content' => 'First step: install the laravel-auditing package.', 'reviewed' => 1, @@ -1047,7 +1055,7 @@ public function itFailsToTransitionWhenTheAuditAuditableTypeDoesNotMatchTheMorph 'articles' => Article::class, ]); - $audit = factory(Audit::class)->make([ + $audit = Audit::factory()->make([ 'auditable_type' => 'users', ]); @@ -1065,11 +1073,11 @@ public function itFailsToTransitionWhenTheAuditAuditableIdDoesNotMatchTheModelId $this->expectException(AuditableTransitionException::class); $this->expectExceptionMessage('Expected Auditable id (integer)2, got (integer)1 instead'); - $firstModel = factory(Article::class)->create(); + $firstModel = Article::factory()->create(); $firstAudit = $firstModel->audits()->first(); $firstAudit->auditable_id = $firstModel->id; - $secondModel = factory(Article::class)->create(); + $secondModel = Article::factory()->create(); $secondModel->transitionTo($firstAudit); } @@ -1083,9 +1091,9 @@ public function itFailsToTransitionWhenTheAuditAuditableIdTypeDoesNotMatchTheMod $this->expectException(AuditableTransitionException::class); $this->expectExceptionMessage('Expected Auditable id (integer)1, got (string)1 instead'); - $model = factory(Article::class)->create(); + $model = Article::factory()->create(); - $audit = factory(Audit::class)->create([ + $audit = Audit::factory()->create([ 'auditable_type' => Article::class, 'auditable_id' => (string)$model->id, ]); @@ -1109,7 +1117,7 @@ public function itFailsToTransitionWhenTheAuditAuditableIdTypeDoesNotMatchTheMod */ public function itTransitionsWhenTheAuditAuditableIdTypeDoesNotMatchTheModelIdType() { - $model = factory(Article::class)->create(); + $model = Article::factory()->create(); // Key depends on type if ($model->getKeyType() == 'string') { @@ -1118,7 +1126,7 @@ public function itTransitionsWhenTheAuditAuditableIdTypeDoesNotMatchTheModelIdTy $key = (int)$model->id; } - $audit = factory(Audit::class)->create([ + $audit = Audit::factory()->create([ 'auditable_type' => Article::class, 'auditable_id' => $key, ]); @@ -1135,13 +1143,13 @@ public function itFailsToTransitionWhenAnAttributeRedactorIsSet() $this->expectException(AuditableTransitionException::class); $this->expectExceptionMessage('Cannot transition states when an AttributeRedactor is set'); - $model = factory(Article::class)->create(); + $model = Article::factory()->create(); $model->attributeModifiers = [ 'title' => RightRedactor::class, ]; - $audit = factory(Audit::class)->create([ + $audit = Audit::factory()->create([ 'auditable_id' => $model->getKey(), 'auditable_type' => Article::class, ]); @@ -1155,9 +1163,9 @@ public function itFailsToTransitionWhenAnAttributeRedactorIsSet() */ public function itFailsToTransitionWhenTheAuditableAttributeCompatibilityIsNotMet() { - $model = factory(Article::class)->create(); + $model = Article::factory()->create(); - $incompatibleAudit = factory(Audit::class)->create([ + $incompatibleAudit = Audit::factory()->create([ 'event' => 'created', 'auditable_id' => $model->getKey(), 'auditable_type' => Article::class, @@ -1176,10 +1184,10 @@ public function itFailsToTransitionWhenTheAuditableAttributeCompatibilityIsNotMe $e->getMessage() ); - self::Assert()::assertArraySubset([ + self::assertSame([ 'subject', 'text', - ], $e->getIncompatibilities(), true); + ], $e->getIncompatibilities()); } } @@ -1202,11 +1210,11 @@ public function itTransitionsToAnotherModelState( array $oldExpectation, array $newExpectation ) { - $models = factory(Article::class, 2)->create([ + $models = Article::factory(2)->create([ 'title' => 'Facilis voluptas qui impedit deserunt vitae quidem.', 'content' => 'Consectetur distinctio nihil eveniet cum. Expedita dolores animi dolorum eos repellat rerum.', ]); - + if ($morphMap) { Relation::morphMap([ 'articles' => Article::class, @@ -1216,14 +1224,13 @@ public function itTransitionsToAnotherModelState( $auditableType = $morphMap ? 'articles' : Article::class; $audits = $models->map(function (Article $model) use ($auditableType, $oldValues, $newValues) { - return factory(Audit::class)->create([ + return Audit::factory()->create([ 'auditable_id' => $model->getKey(), 'auditable_type' => $auditableType, 'old_values' => $oldValues, 'new_values' => $newValues, ]); }); - // Transition with old values $this->assertInstanceOf(Auditable::class, $models[0]->transitionTo($audits[0], true)); $this->assertSame($oldExpectation, $models[0]->getDirty()); @@ -1238,7 +1245,8 @@ public function itTransitionsToAnotherModelState( */ public function itWorksWithStringKeyModels() { - $model = factory(ApiModel::class)->create(); + $model = ApiModel::factory() + ->create(); $model->save(); $model->refresh(); @@ -1370,7 +1378,7 @@ public function itWorksWhenConfigAllowedArrayValueIsTrue() { $this->app['config']->set('audit.allowed_array_values', true); - $model = factory(Article::class)->make([ + $model = Article::factory()->make([ 'title' => 'How To Audit Eloquent Models', 'content' => 'First step: install the laravel-auditing package.', 'reviewed' => 1, @@ -1385,11 +1393,12 @@ public function itWorksWhenConfigAllowedArrayValueIsTrue() $auditData = $model->toAudit(); $morphPrefix = config('audit.user.morph_prefix', 'user'); - self::Assert()::assertArraySubset([ + self::assertSame([ 'old_values' => [], 'new_values' => [ 'title' => 'How To Audit Eloquent Models', 'content' => Article::contentMutate('First step: install the laravel-auditing package.'), + 'published_at' => null, 'reviewed' => 1, 'images' => [ 'https://example.com/image1.jpg', @@ -1401,11 +1410,11 @@ public function itWorksWhenConfigAllowedArrayValueIsTrue() 'auditable_type' => Article::class, $morphPrefix . '_id' => null, $morphPrefix . '_type' => null, + 'tags' => null, 'url' => UrlResolver::resolveCommandLine(), 'ip_address' => '127.0.0.1', 'user_agent' => 'Symfony', - 'tags' => null, - ], $auditData, true); + ], $auditData); } /** @@ -1414,8 +1423,8 @@ public function itWorksWhenConfigAllowedArrayValueIsTrue() public function itWorksWhenConfigAllowedArrayValueIsFalse() { $this->app['config']->set('audit.allowed_array_values', false); - - $model = factory(Article::class)->make([ + + $model = Article::factory()->make([ 'title' => 'How To Audit Eloquent Models', 'content' => 'First step: install the laravel-auditing package.', 'reviewed' => 1, @@ -1430,11 +1439,12 @@ public function itWorksWhenConfigAllowedArrayValueIsFalse() $auditData = $model->toAudit(); $morphPrefix = config('audit.user.morph_prefix', 'user'); - self::Assert()::assertArraySubset([ + self::assertSame([ 'old_values' => [], 'new_values' => [ 'title' => 'How To Audit Eloquent Models', 'content' => Article::contentMutate('First step: install the laravel-auditing package.'), + 'published_at' => null, 'reviewed' => 1, ], 'event' => 'created', @@ -1442,10 +1452,10 @@ public function itWorksWhenConfigAllowedArrayValueIsFalse() 'auditable_type' => Article::class, $morphPrefix . '_id' => null, $morphPrefix . '_type' => null, + 'tags' => null, 'url' => UrlResolver::resolveCommandLine(), 'ip_address' => '127.0.0.1', 'user_agent' => 'Symfony', - 'tags' => null, - ], $auditData, true); + ], $auditData); } } diff --git a/tests/Unit/ProcessDispatchAuditTest.php b/tests/Unit/ProcessDispatchAuditTest.php index 80d292aa..0f7d46b8 100644 --- a/tests/Unit/ProcessDispatchAuditTest.php +++ b/tests/Unit/ProcessDispatchAuditTest.php @@ -20,7 +20,7 @@ public function itIsListeningToTheCorrectEvent() if (version_compare($this->app->version(), '8.0.0', '<')) { $this->markTestSkipped('This test is only for Laravel 8.0.0+'); } - + Event::fake(); Event::assertListening( @@ -36,7 +36,7 @@ public function itGetsProperlyQueued() { Queue::fake(); - $model = factory(Article::class)->create(); + $model = Article::factory()->create(); app()->make('events')->dispatch(new DispatchAudit($model)); @@ -55,10 +55,10 @@ public function itCanHaveConnectionAndQueueSet() $this->app['config']->set('audit.queue.connection', 'redis'); $this->app['config']->set('audit.queue.queue', 'audits'); $this->app['config']->set('audit.queue.delay', 60); - + Queue::fake(); - $model = factory(Article::class)->create(); + $model = Article::factory()->create(); app()->make('events')->dispatch(new DispatchAudit($model)); @@ -72,4 +72,4 @@ public function itCanHaveConnectionAndQueueSet() && $instantiatedJob->withDelay(new DispatchAudit($model)) == 60; }); } -} \ No newline at end of file +} diff --git a/tests/database/factories/ApiModelFactory.php b/tests/database/factories/ApiModelFactory.php index 96589b1e..aa3bdb98 100644 --- a/tests/database/factories/ApiModelFactory.php +++ b/tests/database/factories/ApiModelFactory.php @@ -1,20 +1,28 @@ + */ +class ApiModelFactory extends Factory +{ -/* -|-------------------------------------------------------------------------- -| APIModel Factories -|-------------------------------------------------------------------------- -| -*/ + protected $model = ApiModel::class; -$factory->define(ApiModel::class, function (Faker $faker) { - return [ - 'api_model_id' => Uuid::uuid4(), - 'content' => $faker->unique()->paragraph(6), - 'published_at' => null, - ]; -}); + /** + * @return array + */ + public function definition(): array + { + return [ + 'api_model_id' => Str::uuid(), + 'content' => fake()->unique()->paragraph(6), + 'published_at' => null, + ]; + } +} diff --git a/tests/database/factories/ArticleFactory.php b/tests/database/factories/ArticleFactory.php index 024587d7..c911c822 100644 --- a/tests/database/factories/ArticleFactory.php +++ b/tests/database/factories/ArticleFactory.php @@ -1,20 +1,26 @@ + */ +class ArticleFactory extends Factory +{ + protected $model = Article::class; -$factory->define(Article::class, function (Faker $faker) { - return [ - 'title' => $faker->unique()->sentence, - 'content' => $faker->unique()->paragraph(6), - 'published_at' => null, - 'reviewed' => $faker->randomElement([0, 1]), - ]; -}); + /** + * @return array + */ + public function definition(): array + { + return [ + 'title' => fake()->unique()->sentence, + 'content' => fake()->unique()->paragraph(6), + 'published_at' => null, + 'reviewed' => fake()->randomElement([0, 1]), + ]; + } +} diff --git a/tests/database/factories/AuditFactory.php b/tests/database/factories/AuditFactory.php deleted file mode 100644 index 1725c5fa..00000000 --- a/tests/database/factories/AuditFactory.php +++ /dev/null @@ -1,35 +0,0 @@ -define(Audit::class, function (Faker $faker) { - $morphPrefix = Config::get('audit.user.morph_prefix', 'user'); - - return [ - $morphPrefix . '_id' => function () { - return factory(User::class)->create()->id; - }, - $morphPrefix . '_type' => User::class, - 'event' => 'updated', - 'auditable_id' => function () { - return factory(Article::class)->create()->id; - }, - 'auditable_type' => Article::class, - 'old_values' => [], - 'new_values' => [], - 'url' => $faker->url, - 'ip_address' => $faker->ipv4, - 'user_agent' => $faker->userAgent, - 'tags' => implode(',', $faker->words(4)), - ]; -}); diff --git a/tests/database/factories/CategoryFactory.php b/tests/database/factories/CategoryFactory.php index 8b8b4386..b201f67c 100644 --- a/tests/database/factories/CategoryFactory.php +++ b/tests/database/factories/CategoryFactory.php @@ -1,16 +1,23 @@ + */ +class CategoryFactory extends Factory +{ + protected $model = Category::class; -$factory->define(\OwenIt\Auditing\Tests\Models\Category::class, function (Faker $faker) { - return [ - 'name' => $faker->unique()->colorName(), - ]; -}); + /** + * @return array + */ + public function definition(): array + { + return [ + 'name' => fake()->unique()->colorName(), + ]; + } +} diff --git a/tests/database/factories/UserFactory.php b/tests/database/factories/UserFactory.php index e89bf227..51aa9d3a 100644 --- a/tests/database/factories/UserFactory.php +++ b/tests/database/factories/UserFactory.php @@ -1,20 +1,26 @@ + */ +class UserFactory extends Factory +{ + protected $model = User::class; -$factory->define(User::class, function (Faker $faker) { - return [ - 'is_admin' => $faker->randomElement([0, 1]), - 'first_name' => $faker->firstName, - 'last_name' => $faker->lastName, - 'email' => $faker->unique()->safeEmail, - ]; -}); + /** + * @return array + */ + public function definition(): array + { + return [ + 'is_admin' => fake()->randomElement([0, 1]), + 'first_name' => fake()->firstName, + 'last_name' => fake()->lastName, + 'email' => fake()->unique()->safeEmail, + ]; + } +} diff --git a/tests/database/migrations/0000_00_00_000001_create_audits_test_table.php b/tests/database/migrations/0000_00_00_000001_create_audits_test_table.php index d0dc3b71..129c6885 100644 --- a/tests/database/migrations/0000_00_00_000001_create_audits_test_table.php +++ b/tests/database/migrations/0000_00_00_000001_create_audits_test_table.php @@ -12,7 +12,7 @@ class CreateAuditsTestTable extends CreateAuditsTable * * @return void */ - public function up() + public function up(): void { parent::up();