app->bind(UnifiClient::class, fn () => new class extends UnifiClient { public function __construct() {} public function clients(): array { return []; } public function connectedMacs(): array { return []; } public function isConfigured(): bool { return true; } }); } public function test_person_flips_to_away_only_after_the_debounce(): void { config()->set('homeos.presence.away_debounce_minutes', 3); // Seen 1 min ago (within debounce) → still home. $recent = Person::create(['name' => 'A', 'mac' => 'aa:bb', 'presence' => 'home', 'last_seen_home_at' => now()->subMinute()]); // Seen 10 min ago (past debounce) and off wifi → away. $stale = Person::create(['name' => 'B', 'mac' => 'cc:dd', 'presence' => 'home', 'last_seen_home_at' => now()->subMinutes(10)]); $this->artisan('presence:poll')->assertSuccessful(); $this->assertSame('home', $recent->fresh()->presence); $this->assertSame('away', $stale->fresh()->presence); } public function test_manage_person_creates_with_an_avatar(): void { Storage::fake('public'); $this->actingAs(User::factory()->create()); Livewire::test(ManagePerson::class) ->set('name', 'Boban') ->set('avatar', UploadedFile::fake()->create('me.jpg', 200, 'image/jpeg')) ->call('save') ->assertRedirect(route('persons.index')); $person = Person::where('name', 'Boban')->first(); $this->assertNotNull($person->avatar_path); Storage::disk('public')->assertExists($person->avatar_path); } public function test_manage_person_edits_an_existing_person(): void { $this->actingAs(User::factory()->create()); $person = Person::create(['name' => 'Old', 'presence' => 'unknown']); Livewire::test(ManagePerson::class, ['person' => $person->uuid]) ->assertSet('editing', true) ->set('name', 'New') ->call('save'); $this->assertSame('New', $person->fresh()->name); } public function test_deleting_a_person_removes_it_and_its_avatar(): void { Storage::fake('public'); $this->actingAs(User::factory()->create()); $path = UploadedFile::fake()->create('a.jpg', 200, 'image/jpeg')->store('avatars', 'public'); $person = Person::create(['name' => 'X', 'presence' => 'home', 'avatar_path' => $path]); Livewire::test(Index::class) ->set('pendingDelete', $person->uuid) ->call('deletePerson'); $this->assertModelMissing($person); Storage::disk('public')->assertMissing($path); } }