homeos/tests/Feature/NotificationTest.php

97 lines
3.7 KiB
PHP

<?php
namespace Tests\Feature;
use App\Livewire\Modals\SmtpSetup;
use App\Models\Addon;
use App\Models\Device;
use App\Models\User;
use App\Services\NotificationService;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Mail;
use Livewire\Livewire;
use Tests\TestCase;
class NotificationTest extends TestCase
{
use RefreshDatabase;
private function configureSmtp(array $events = ['device_offline' => true, 'low_battery' => true, 'automation' => true]): void
{
Addon::create([
'key' => 'smtp',
'installed' => true,
'status' => 'connected',
'config' => [
'host' => 'smtp.example.com', 'port' => 587, 'encryption' => 'tls',
'username' => 'u', 'password' => 'p', 'from_email' => 'homeos@example.com',
'from_name' => 'HomeOS', 'to_email' => 'me@example.com', 'events' => $events,
],
]);
}
public function test_notify_does_nothing_without_the_smtp_addon(): void
{
Mail::fake();
$this->assertFalse(app(NotificationService::class)->notify('device_offline', 's', 'b'));
}
public function test_notify_respects_the_per_event_toggle(): void
{
Mail::fake();
$this->configureSmtp(['device_offline' => false, 'low_battery' => true, 'automation' => true]);
$this->assertFalse(app(NotificationService::class)->notify('device_offline', 's', 'b'));
$this->assertTrue(app(NotificationService::class)->notify('low_battery', 's', 'b'));
}
public function test_smtp_setup_persists_config_and_keeps_password(): void
{
$this->actingAs(User::factory()->create());
Livewire::test(SmtpSetup::class)
->set('host', 'smtp.gmail.com')->set('port', '587')->set('encryption', 'tls')
->set('username', 'me')->set('password', 'secret')
->set('fromEmail', 'from@x.com')->set('toEmail', 'to@x.com')
->set('evLowBattery', false)
->call('save')
->assertRedirect(route('addons.index'));
$cfg = Addon::where('key', 'smtp')->first()->config;
$this->assertSame('smtp.gmail.com', $cfg['host']);
$this->assertSame('secret', $cfg['password']);
$this->assertFalse($cfg['events']['low_battery']);
// Re-saving with a blank password keeps the stored one.
Livewire::test(SmtpSetup::class)
->set('host', 'smtp.gmail.com')->set('port', '465')->set('encryption', 'ssl')
->set('fromEmail', 'from@x.com')->set('toEmail', 'to@x.com')
->set('password', '')
->call('save');
$this->assertSame('secret', Addon::where('key', 'smtp')->first()->config['password']);
}
public function test_sweep_emails_once_per_offline_device(): void
{
Mail::fake();
$this->configureSmtp();
// Active, not demo, stale last_seen → offline.
$device = Device::create(['name' => 'Lampe', 'vendor' => 'Shelly', 'protocol' => 'http', 'status' => 'active', 'demo' => false, 'last_seen_at' => now()->subHour(), 'config' => ['ip' => '1.2.3.4']]);
$this->artisan('notifications:sweep')->assertSuccessful();
$this->assertTrue(Cache::has("notified:offline:{$device->id}"));
// Second sweep — still flagged, no re-notify (flag unchanged).
$this->artisan('notifications:sweep')->assertSuccessful();
$this->assertTrue(Cache::has("notified:offline:{$device->id}"));
// Back online → flag cleared so a future outage notifies again.
$device->update(['last_seen_at' => now()]);
$this->artisan('notifications:sweep')->assertSuccessful();
$this->assertFalse(Cache::has("notified:offline:{$device->id}"));
}
}