firstWhere('key', 'ring'); $this->assertNotNull($ring); $this->assertTrue($ring['cloud']); $this->assertFalse($ring['installed']); $this->assertSame('disconnected', $ring['status']); } public function test_install_marks_installed(): void { app(AddonService::class)->install('ring'); $this->assertDatabaseHas('addons', ['key' => 'ring', 'installed' => true]); } public function test_installing_unknown_addon_aborts(): void { $this->expectException(\Symfony\Component\HttpKernel\Exception\HttpException::class); app(AddonService::class)->install('nope'); } public function test_save_connection_encrypts_config_and_sets_connecting(): void { app(AddonService::class)->saveConnection('ring', [ 'email' => 'me@example.com', 'password' => 'secret-pw', 'code' => '123456', ]); $addon = Addon::where('key', 'ring')->first(); $this->assertSame('connecting', $addon->status); $this->assertSame('me@example.com', $addon->config['email']); $this->assertSame('secret-pw', $addon->config['password']); // Stored ciphertext must not contain the plaintext secret. $raw = DB::table('addons')->where('key', 'ring')->value('config'); $this->assertStringNotContainsString('secret-pw', $raw); } public function test_blank_password_keeps_previously_stored_one(): void { $service = app(AddonService::class); $service->saveConnection('ring', ['email' => 'me@example.com', 'password' => 'first-pw']); $service->saveConnection('ring', ['email' => 'me@example.com', 'password' => '']); $addon = Addon::where('key', 'ring')->first(); $this->assertSame('first-pw', $addon->config['password']); } public function test_uninstall_wipes_secrets(): void { $service = app(AddonService::class); $service->saveConnection('ring', ['email' => 'me@example.com', 'password' => 'secret-pw']); $service->uninstall('ring'); $addon = Addon::where('key', 'ring')->first(); $this->assertFalse($addon->installed); $this->assertSame('disconnected', $addon->status); $this->assertNull($addon->config); } public function test_install_and_uninstall_invalidate_the_ingest_gate_cache(): void { $key = AddonService::installedCacheKey('ring'); $service = app(AddonService::class); // Prime a stale "not installed" value, then install → cache must be cleared. Cache::put($key, false, 60); $service->install('ring'); $this->assertFalse(Cache::has($key)); // Prime a stale "installed" value, then uninstall → cache must be cleared. Cache::put($key, true, 60); $service->uninstall('ring'); $this->assertFalse(Cache::has($key)); } public function test_mark_status_only_applies_to_installed_addons(): void { $service = app(AddonService::class); // Not installed → ignored. $service->markStatus('ring', 'connected'); $this->assertNull(Addon::where('key', 'ring')->first()?->connected_at); $service->install('ring'); $service->markStatus('ring', 'connected'); $this->assertNotNull(Addon::where('key', 'ring')->first()->connected_at); } }