From 8b573c94895dc0ac0e1d9d59cf3e8745e8b539ca Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Thu, 17 Dec 2020 11:59:07 +0000 Subject: Add latest changes from gitlab-org/gitlab@13-7-stable-ee --- spec/lib/feature_spec.rb | 173 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 172 insertions(+), 1 deletion(-) (limited to 'spec/lib/feature_spec.rb') diff --git a/spec/lib/feature_spec.rb b/spec/lib/feature_spec.rb index 5dff9dbd995..1bcb2223012 100644 --- a/spec/lib/feature_spec.rb +++ b/spec/lib/feature_spec.rb @@ -249,10 +249,12 @@ RSpec.describe Feature, stub_feature_flags: false do Feature::Definition.new('development/my_feature_flag.yml', name: 'my_feature_flag', type: 'development', - default_enabled: false + default_enabled: default_enabled ).tap(&:validate!) end + let(:default_enabled) { false } + before do stub_env('LAZILY_CREATE_FEATURE_FLAG', '0') @@ -275,6 +277,63 @@ RSpec.describe Feature, stub_feature_flags: false do expect { described_class.enabled?(:my_feature_flag, default_enabled: true) } .to raise_error(/The `default_enabled:` of/) end + + context 'when `default_enabled: :yaml` is used in code' do + it 'reads the default from the YAML definition' do + expect(described_class.enabled?(:my_feature_flag, default_enabled: :yaml)).to eq(false) + end + + context 'when default_enabled is true in the YAML definition' do + let(:default_enabled) { true } + + it 'reads the default from the YAML definition' do + expect(described_class.enabled?(:my_feature_flag, default_enabled: :yaml)).to eq(true) + end + end + + context 'when YAML definition does not exist for an optional type' do + let(:optional_type) { described_class::Shared::TYPES.find { |name, attrs| attrs[:optional] }.first } + + context 'when in dev or test environment' do + it 'raises an error for dev' do + expect { described_class.enabled?(:non_existent_flag, type: optional_type, default_enabled: :yaml) } + .to raise_error( + Feature::InvalidFeatureFlagError, + "The feature flag YAML definition for 'non_existent_flag' does not exist") + end + end + + context 'when in production' do + before do + allow(Gitlab::ErrorTracking).to receive(:should_raise_for_dev?).and_return(false) + end + + context 'when database exists' do + before do + allow(Gitlab::Database).to receive(:exists?).and_return(true) + end + + it 'checks the persisted status and returns false' do + expect(described_class).to receive(:get).with(:non_existent_flag).and_call_original + + expect(described_class.enabled?(:non_existent_flag, type: optional_type, default_enabled: :yaml)).to eq(false) + end + end + + context 'when database does not exist' do + before do + allow(Gitlab::Database).to receive(:exists?).and_return(false) + end + + it 'returns false without checking the status in the database' do + expect(described_class).not_to receive(:get) + + expect(described_class.enabled?(:non_existent_flag, type: optional_type, default_enabled: :yaml)).to eq(false) + end + end + end + end + end end end @@ -300,7 +359,119 @@ RSpec.describe Feature, stub_feature_flags: false do end end + shared_examples_for 'logging' do + let(:expected_action) { } + let(:expected_extra) { } + + it 'logs the event' do + expect(Feature.logger).to receive(:info).with(key: key, action: expected_action, **expected_extra) + + subject + end + end + + describe '.enable' do + subject { described_class.enable(key, thing) } + + let(:key) { :awesome_feature } + let(:thing) { true } + + it_behaves_like 'logging' do + let(:expected_action) { :enable } + let(:expected_extra) { { "extra.thing" => "true" } } + end + + context 'when thing is an actor' do + let(:thing) { create(:project) } + + it_behaves_like 'logging' do + let(:expected_action) { :enable } + let(:expected_extra) { { "extra.thing" => "#{thing.flipper_id}" } } + end + end + end + + describe '.disable' do + subject { described_class.disable(key, thing) } + + let(:key) { :awesome_feature } + let(:thing) { false } + + it_behaves_like 'logging' do + let(:expected_action) { :disable } + let(:expected_extra) { { "extra.thing" => "false" } } + end + + context 'when thing is an actor' do + let(:thing) { create(:project) } + + it_behaves_like 'logging' do + let(:expected_action) { :disable } + let(:expected_extra) { { "extra.thing" => "#{thing.flipper_id}" } } + end + end + end + + describe '.enable_percentage_of_time' do + subject { described_class.enable_percentage_of_time(key, percentage) } + + let(:key) { :awesome_feature } + let(:percentage) { 50 } + + it_behaves_like 'logging' do + let(:expected_action) { :enable_percentage_of_time } + let(:expected_extra) { { "extra.percentage" => "#{percentage}" } } + end + end + + describe '.disable_percentage_of_time' do + subject { described_class.disable_percentage_of_time(key) } + + let(:key) { :awesome_feature } + + it_behaves_like 'logging' do + let(:expected_action) { :disable_percentage_of_time } + let(:expected_extra) { {} } + end + end + + describe '.enable_percentage_of_actors' do + subject { described_class.enable_percentage_of_actors(key, percentage) } + + let(:key) { :awesome_feature } + let(:percentage) { 50 } + + it_behaves_like 'logging' do + let(:expected_action) { :enable_percentage_of_actors } + let(:expected_extra) { { "extra.percentage" => "#{percentage}" } } + end + end + + describe '.disable_percentage_of_actors' do + subject { described_class.disable_percentage_of_actors(key) } + + let(:key) { :awesome_feature } + + it_behaves_like 'logging' do + let(:expected_action) { :disable_percentage_of_actors } + let(:expected_extra) { {} } + end + end + describe '.remove' do + subject { described_class.remove(key) } + + let(:key) { :awesome_feature } + + before do + described_class.enable(key) + end + + it_behaves_like 'logging' do + let(:expected_action) { :remove } + let(:expected_extra) { {} } + end + context 'for a non-persisted feature' do it 'returns nil' do expect(described_class.remove(:non_persisted_feature_flag)).to be_nil -- cgit v1.2.3