getProperty('resolvedSettings'); $prop->setAccessible(true); $prop->setValue(null, null); }; $reset(); Cache::flush(); $this->service = app(SystemConfigService::class); }); test('definitions returns non-empty array with expected meta keys', function () { $defs = SystemConfigService::definitions(); expect($defs)->toBeArray()->not->toBeEmpty(); expect($defs)->toHaveKey('app_name'); foreach ($defs as $key => $meta) { expect($meta)->toHaveKeys(['type', 'group', 'is_public']); } }); test('all returns definition defaults when DB is empty', function () { $all = $this->service->all(); expect($all['app_name'])->toBe('Laravel'); expect($all['regional_timezone'])->toBe('Asia/Jakarta'); }); test('all returns DB values when row exists', function () { SystemSetting::create([ 'key' => 'app_name', 'value' => 'CustomApp', 'type' => 'string', 'group' => 'branding', 'is_public' => true, ]); $all = $this->service->all(forceRefresh: true); expect($all['app_name'])->toBe('CustomApp'); }); test('get returns default for unknown key', function () { expect($this->service->get('nonexistent_key', 'fallback'))->toBe('fallback'); }); test('get returns value for known key', function () { expect($this->service->get('app_name'))->toBe('Laravel'); }); test('getPublicSettings only includes is_public=true keys', function () { $public = $this->service->getPublicSettings(); expect($public)->toHaveKey('app_name'); foreach ($public as $key => $value) { $meta = SystemConfigService::definitions()[$key]; expect($meta['is_public'])->toBeTrue(); } }); test('grouped returns settings keyed by group', function () { $grouped = $this->service->grouped(); expect($grouped)->toHaveKey('branding'); expect($grouped['branding'])->toHaveKey('app_name'); }); test('update creates new setting row', function () { $this->service->update(['app_name' => 'Updated']); $this->assertDatabaseHas('system_settings', [ 'key' => 'app_name', 'value' => 'Updated', ]); }); test('update overwrites existing setting row', function () { SystemSetting::create([ 'key' => 'app_name', 'value' => 'Old', 'type' => 'string', 'group' => 'branding', 'is_public' => true, ]); $this->service->update(['app_name' => 'New']); expect(SystemSetting::where('key', 'app_name')->count())->toBe(1); expect(SystemSetting::where('key', 'app_name')->first()->value)->toBe('New'); }); test('update writes a revision row', function () { $user = User::factory()->create(); $this->service->update(['app_name' => 'Revisioned'], actorId: $user->id); $rev = SystemSettingRevision::where('key', 'app_name')->first(); expect($rev)->not->toBeNull(); expect($rev->changed_by)->toBe($user->id); expect($rev->new_value)->toContain('Revisioned'); }); test('update does not write revision when value unchanged', function () { SystemSetting::create([ 'key' => 'app_name', 'value' => 'Same', 'type' => 'string', 'group' => 'branding', 'is_public' => true, ]); $this->service->update(['app_name' => 'Same']); expect(SystemSettingRevision::where('key', 'app_name')->count())->toBe(0); }); test('update serializes bool values to 1 or 0', function () { $this->service->update(['enable_landing_page' => false]); $row = SystemSetting::where('key', 'enable_landing_page')->first(); expect($row->value)->toBe('0'); $this->service->update(['enable_landing_page' => true]); $row->refresh(); expect($row->value)->toBe('1'); }); test('update clears the cache after writing', function () { Cache::put('system_settings.all', ['app_name' => 'StaleCached'], 60); $this->service->update(['app_name' => 'Fresh']); expect(Cache::has('system_settings.all'))->toBeFalse(); }); test('update normalizes bool input from string', function () { $this->service->update(['enable_landing_page' => 'false']); $row = SystemSetting::where('key', 'enable_landing_page')->first(); expect($row->value)->toBe('0'); }); test('update records request IP and user agent in revision', function () { $request = Request::create('/system-settings', 'POST', server: [ 'REMOTE_ADDR' => '203.0.113.7', 'HTTP_USER_AGENT' => 'pest-test-agent', ]); $this->service->update(['app_name' => 'Tracked'], request: $request); $rev = SystemSettingRevision::where('key', 'app_name')->first(); expect($rev->changed_ip)->toBe('203.0.113.7'); expect($rev->changed_agent)->toBe('pest-test-agent'); });