set('database.default', 'logging_test'); config()->set('database.connections.logging_test', [ 'driver' => 'sqlite', 'database' => ':memory:', 'foreign_key_constraints' => true, ]); Schema::create('users', function (Blueprint $table): void { $table->id(); }); Schema::create('logging_test_products', function (Blueprint $table): void { $table->id(); $table->string('name'); $table->unsignedInteger('price'); $table->text('description')->nullable(); $table->timestamps(); }); $migration = require database_path('migrations/2026_08_03_000200_create_value_changes_table.php'); $migration->up(); } public function test_it_creates_one_system_record_per_configured_change(): void { $product = LoggingTestProduct::create([ 'name' => 'Original', 'price' => 100, 'description' => 'Old description', ]); $product->update([ 'name' => 'Updated', 'price' => 150, 'description' => 'New description', ]); $this->assertDatabaseCount('value_changes', 2); $this->assertDatabaseHas('value_changes', [ 'attribute' => 'name', 'old_value' => 'Original', 'new_value' => 'Updated', 'actor_type' => ValueChangeActorType::System->value, 'user_id' => null, ]); $this->assertDatabaseHas('value_changes', [ 'attribute' => 'price', 'old_value' => '100', 'new_value' => '150', 'actor_type' => ValueChangeActorType::System->value, 'user_id' => null, ]); $this->assertTrue(ValueChange::firstOrFail()->trackable->is($product)); } public function test_it_associates_an_authenticated_user_with_the_change(): void { Schema::getConnection()->table('users')->insert(['id' => 7]); Auth::shouldReceive('id')->once()->andReturn(7); $product = LoggingTestProduct::create([ 'name' => 'Original', 'price' => 100, ]); $product->update(['price' => 200]); $change = ValueChange::firstOrFail(); $this->assertSame(ValueChangeActorType::User, $change->actor_type); $this->assertSame(7, $change->user_id); } public function test_it_does_not_log_updates_to_unconfigured_attributes(): void { $product = LoggingTestProduct::create([ 'name' => 'Original', 'price' => 100, 'description' => 'Old description', ]); $product->update(['description' => 'New description']); $this->assertDatabaseCount('value_changes', 0); } } #[Fillable(['name', 'price', 'description'])] class LoggingTestProduct extends Model { use LogsValueChanges; protected $table = 'logging_test_products'; /** @var array */ protected array $loggedAttributes = [ 'name', 'price', ]; }