create(['email' => 'admin@clusev.local']); $this->actingAs($user); return $user; } public function test_saving_persists_settings_and_stores_password_encrypted(): void { $this->actingUser(); Livewire::test(Email::class) ->set('mail_host', 'smtp.example.com') ->set('mail_port', 2525) ->set('mail_username', 'panel') ->set('mail_password', 's3cr3t-pw') ->set('mail_encryption', 'tls') ->set('mail_from_address', 'panel@example.com') ->set('mail_from_name', 'Clusev') ->call('save') ->assertHasNoErrors(); $this->assertSame('smtp.example.com', Setting::get('mail_host')); $this->assertSame('2525', Setting::get('mail_port')); $this->assertSame('panel', Setting::get('mail_username')); $this->assertSame('tls', Setting::get('mail_encryption')); $this->assertSame('panel@example.com', Setting::get('mail_from_address')); $this->assertSame('Clusev', Setting::get('mail_from_name')); // Stored value must NOT be the plaintext, but must decrypt back to it. $stored = Setting::get('mail_password'); $this->assertNotNull($stored); $this->assertNotSame('s3cr3t-pw', $stored, 'password must be encrypted at rest'); $this->assertSame('s3cr3t-pw', Crypt::decryptString($stored)); $this->assertDatabaseHas('audit_events', ['action' => 'mail.configure', 'target' => 'smtp.example.com']); } public function test_clear_config_removes_all_mail_settings(): void { $this->actingUser(); Setting::put('mail_host', 'smtp.example.com'); Setting::put('mail_port', '2525'); Setting::put('mail_username', 'panel'); Setting::put('mail_password', Crypt::encryptString('s3cr3t-pw')); Setting::put('mail_encryption', 'ssl'); Setting::put('mail_from_address', 'panel@example.com'); Setting::put('mail_from_name', 'Clusev'); Livewire::test(Email::class) ->assertSet('mail_host', 'smtp.example.com') // mounted from the stored value ->call('clearConfig') ->assertHasNoErrors() ->assertSet('mail_host', '') ->assertSet('mail_from_address', '') ->assertSet('passwordSet', false); foreach (['mail_host', 'mail_port', 'mail_username', 'mail_password', 'mail_encryption', 'mail_from_address', 'mail_from_name'] as $key) { $this->assertNull(Setting::get($key), "$key must be cleared"); } $this->assertDatabaseHas('audit_events', ['action' => 'mail.reset']); } public function test_password_is_not_overwritten_when_left_blank(): void { $this->actingUser(); Setting::put('mail_host', 'smtp.example.com'); Setting::put('mail_from_address', 'panel@example.com'); Setting::put('mail_password', Crypt::encryptString('original-pw')); Livewire::test(Email::class) ->set('mail_from_name', 'Clusev') ->set('mail_password', '') // left blank -> keep the stored one ->call('save') ->assertHasNoErrors(); $this->assertSame('original-pw', Crypt::decryptString(Setting::get('mail_password'))); } public function test_configured_reflects_host_and_from_presence(): void { $this->actingUser(); $component = Livewire::test(Email::class); $this->assertFalse($component->instance()->configured()); $component->set('mail_host', 'smtp.example.com'); $this->assertFalse($component->instance()->configured(), 'host alone is not enough'); $component->set('mail_from_address', 'panel@example.com'); $this->assertTrue($component->instance()->configured()); } public function test_runtime_override_switches_to_smtp_when_configured(): void { config(['mail.default' => 'log']); Setting::put('mail_host', 'smtp.example.com'); Setting::put('mail_port', '2525'); Setting::put('mail_username', 'panel'); Setting::put('mail_password', Crypt::encryptString('s3cr3t-pw')); Setting::put('mail_encryption', 'ssl'); Setting::put('mail_from_address', 'panel@example.com'); Setting::put('mail_from_name', 'Clusev'); // Re-run the provider's boot, which applies the mail settings. $this->app->register(AppServiceProvider::class, true); $this->assertSame('smtp', config('mail.default')); $this->assertSame('smtp.example.com', config('mail.mailers.smtp.host')); $this->assertSame(2525, config('mail.mailers.smtp.port')); $this->assertSame('panel', config('mail.mailers.smtp.username')); $this->assertSame('s3cr3t-pw', config('mail.mailers.smtp.password')); $this->assertSame('ssl', config('mail.mailers.smtp.encryption')); $this->assertSame('panel@example.com', config('mail.from.address')); } public function test_runtime_override_leaves_default_mailer_when_unconfigured(): void { config(['mail.default' => 'log']); // No settings -> default mailer must stay untouched. $this->app->register(AppServiceProvider::class, true); $this->assertSame('log', config('mail.default')); } public function test_encryption_none_maps_to_null(): void { config(['mail.default' => 'log']); Setting::put('mail_host', 'smtp.example.com'); Setting::put('mail_encryption', 'none'); Setting::put('mail_from_address', 'panel@example.com'); $this->app->register(AppServiceProvider::class, true); $this->assertSame('smtp', config('mail.default')); $this->assertNull(config('mail.mailers.smtp.encryption')); } public function test_test_send_dispatches_a_mail_to_the_current_user(): void { // Force the smtp mailer onto the in-memory `array` transport so the test-send // captures the message WITHOUT opening a real SMTP connection. The component's // runtime config() only sets host/port/etc., never `transport`, so this sticks // across its Mail::purge('smtp') rebuild — fully deterministic, no network. config(['mail.mailers.smtp.transport' => 'array']); $user = $this->actingUser(); Setting::put('mail_host', 'smtp.example.com'); Setting::put('mail_from_address', 'panel@example.com'); Livewire::test(Email::class) ->set('mail_host', 'smtp.example.com') ->set('mail_from_address', 'panel@example.com') ->call('sendTest') ->assertHasNoErrors(); $messages = app('mailer')->getSymfonyTransport()->messages(); $this->assertCount(1, $messages, 'exactly one test mail must be sent'); $sent = $messages[0]->getOriginalMessage(); $recipients = array_map(fn ($a) => $a->getAddress(), $sent->getTo()); $this->assertSame([$user->email], $recipients, 'test mail must go only to the current user'); } public function test_test_send_does_nothing_when_unconfigured(): void { Mail::fake(); $this->actingUser(); Livewire::test(Email::class) ->call('sendTest') ->assertHasNoErrors(); Mail::assertNothingSent(); } public function test_audit_event_is_recorded_on_save(): void { $this->actingUser(); Livewire::test(Email::class) ->set('mail_host', 'smtp.example.com') ->set('mail_from_address', 'panel@example.com') ->set('mail_from_name', 'Clusev') ->call('save') ->assertHasNoErrors(); $this->assertSame(1, AuditEvent::where('action', 'mail.configure')->count()); } }