Files
chatwoot/spec/lib/config_loader_spec.rb
T
Sony MathewandGitHub 873d16f54c feat: Extend account feature flag storage (#14947)
# Pull Request Template

## Description

Extends account-level feature flags by adding a second bigint bitset
column, `feature_flags_ext_2`, while preserving the existing
`flag_shih_tzu` feature check and enable/disable APIs. Existing flags
continue to live on `feature_flags`; future flags can opt into the
extension column through `config/features.yml` metadata.

Fixes
[CW-7238](https://linear.app/chatwoot/issue/CW-7238/feature-flag-extension)

## Type of change

- [ ] Bug fix (non-breaking change which fixes an issue)
- [x] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing
functionality not to work as expected)
- [ ] This change requires a documentation update

## How Has This Been Tested?

- `eval "$(rbenv init -)" && RAILS_ENV=test
POSTGRES_DATABASE=chatwoot_test_31a6 bundle exec rspec
spec/models/concerns/featurable_spec.rb spec/models/account_spec.rb
spec/lib/config_loader_spec.rb
spec/controllers/platform/api/v1/accounts_controller_spec.rb
spec/controllers/super_admin/accounts_controller_spec.rb
spec/enterprise/models/account_spec.rb` - 144 examples, 0 failures
- `eval "$(rbenv init -)" && bundle exec rubocop
app/models/concerns/featurable.rb app/models/account.rb
db/migrate/20260706215758_add_feature_flags_ext_2_to_accounts.rb
spec/models/concerns/featurable_spec.rb spec/models/account_spec.rb
spec/lib/config_loader_spec.rb spec/enterprise/models/account_spec.rb` -
7 files inspected, no offenses detected
- `ruby -ryaml -e "features =
YAML.safe_load(File.read('config/features.yml')); abort unless
features.size == 63; puts features.group_by { |f| f['column'] ||
'feature_flags' }.transform_values(&:size).inspect"` - `{"feature_flags"
=> 63}`
- `git diff --check`

## Checklist:

- [x] My code follows the style guidelines of this project
- [x] I have performed a self-review of my code
- [x] I have commented on my code, particularly in hard-to-understand
areas
- [x] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [x] I have added tests that prove my fix is effective or that my
feature works
- [x] New and existing unit tests pass locally with my changes
- [x] Any dependent changes have been merged and published in downstream
modules
2026-07-08 17:38:26 +05:30

69 lines
2.5 KiB
Ruby

require 'rails_helper'
describe ConfigLoader do
subject(:trigger) { described_class.new.process }
describe 'execute' do
context 'when called with default options' do
it 'creates installation configs' do
expect(InstallationConfig.count).to eq(0)
subject
expect(InstallationConfig.count).to be > 0
end
it 'creates account level feature defaults as entry on config table' do
subject
expect(InstallationConfig.find_by(name: 'ACCOUNT_LEVEL_FEATURE_DEFAULTS')).to be_truthy
end
end
context 'with reconcile_only_new option' do
let(:class_instance) { described_class.new }
let(:config) { { name: 'WHO', value: 'corona' } }
let(:updated_config) { { name: 'WHO', value: 'covid 19' } }
before do
allow(described_class).to receive(:new).and_return(class_instance)
allow(class_instance).to receive(:general_configs).and_return([config])
described_class.new.process
end
it 'being true it should not update existing config value' do
expect(InstallationConfig.find_by(name: 'WHO').value).to eq('corona')
allow(class_instance).to receive(:general_configs).and_return([updated_config])
described_class.new.process({ reconcile_only_new: true })
expect(InstallationConfig.find_by(name: 'WHO').value).to eq('corona')
end
it 'updates the existing config value with new default value' do
expect(InstallationConfig.find_by(name: 'WHO').value).to eq('corona')
allow(class_instance).to receive(:general_configs).and_return([updated_config])
described_class.new.process({ reconcile_only_new: false })
expect(InstallationConfig.find_by(name: 'WHO').value).to eq('covid 19')
end
end
it 'preserves feature flag column metadata in account level defaults' do
Dir.mktmpdir do |config_path|
File.write("#{config_path}/installation_config.yml", <<~YAML)
- name: TEST_CONFIG
value: test
locked: true
YAML
File.write("#{config_path}/features.yml", <<~YAML)
- name: extension_feature
display_name: Extension Feature
enabled: false
column: feature_flags_ext_1
YAML
described_class.new.process(config_path: config_path)
expect(InstallationConfig.find_by(name: 'ACCOUNT_LEVEL_FEATURE_DEFAULTS').value).to include(
a_hash_including('name' => 'extension_feature', 'column' => 'feature_flags_ext_1')
)
end
end
end
end