diff --git a/config/initializers/feature_toggles.rb b/config/initializers/feature_toggles.rb index 13d083979c..9c31940462 100644 --- a/config/initializers/feature_toggles.rb +++ b/config/initializers/feature_toggles.rb @@ -1,5 +1,11 @@ require 'open_food_network/feature_toggle' -beta_testers = ENV['BETA_TESTERS']&.split(/[\s,]+/) +beta_testers = ENV['BETA_TESTERS']&.split(/[\s,]+/) || [] -OpenFoodNetwork::FeatureToggle.enable(:customer_balance, beta_testers) +OpenFoodNetwork::FeatureToggle.enable(:customer_balance) do |user| + if beta_testers == ['all'] + true + else + beta_testers.include?(user.email) + end +end diff --git a/lib/open_food_network/feature_toggle.rb b/lib/open_food_network/feature_toggle.rb index 5ee51a82f9..fb62be5553 100644 --- a/lib/open_food_network/feature_toggle.rb +++ b/lib/open_food_network/feature_toggle.rb @@ -30,11 +30,14 @@ module OpenFoodNetwork new.enabled?(feature_name, user) end - def self.enable(feature_name, user_emails) - return unless user_emails.present? - + def self.enable(feature_name, user_emails = nil, &block) Thread.current[:features] ||= {} - Thread.current[:features][feature_name] = Feature.new(user_emails) + + if user_emails.nil? + Thread.current[:features][feature_name] = BlockFeature.new(block) + else + Thread.current[:features][feature_name] = Feature.new(user_emails) + end end def initialize @@ -86,4 +89,18 @@ module OpenFoodNetwork false end end + + class BlockFeature + def initialize(block) + @block = block + end + + def enabled?(user) + block.call(user) + end + + private + + attr_reader :block + end end diff --git a/spec/initializers/feature_toggles_spec.rb b/spec/initializers/feature_toggles_spec.rb new file mode 100644 index 0000000000..daea8a2f73 --- /dev/null +++ b/spec/initializers/feature_toggles_spec.rb @@ -0,0 +1,47 @@ +require 'spec_helper' + +describe 'config/initializers/feature_toggles.rb' do + let(:user) { build(:user) } + + around do |example| + original = ENV['BETA_TESTERS'] + example.run + ENV['BETA_TESTERS'] = original + end + + context 'when beta_testers is ["all"]' do + before { ENV['BETA_TESTERS'] = 'all' } + + it 'returns true' do + require './config/initializers/feature_toggles' # execute the initializer's code block + + enabled = OpenFoodNetwork::FeatureToggle.enabled?(:customer_balance, user) + expect(enabled).to eq(true) + end + end + + context 'when beta_testers is a list of emails' do + context 'and the user is in the list' do + let(:other_user) { build(:user) } + before { ENV['BETA_TESTERS'] = "#{user.email}, #{other_user.email}" } + + it 'enables the feature' do + require './config/initializers/feature_toggles' # execute the initializer's code block + + enabled = OpenFoodNetwork::FeatureToggle.enabled?(:customer_balance, user) + expect(enabled).to eq(true) + end + end + + context 'and the user is not in the list' do + before { ENV['BETA_TESTERS'] = '' } + + it 'disables the feature' do + require './config/initializers/feature_toggles' # execute the initializer's code block + + enabled = OpenFoodNetwork::FeatureToggle.enabled?(:customer_balance, user) + expect(enabled).to eq(false) + end + end + end +end diff --git a/spec/lib/open_food_network/feature_toggle_spec.rb b/spec/lib/open_food_network/feature_toggle_spec.rb index 73407d671d..f8074410c1 100644 --- a/spec/lib/open_food_network/feature_toggle_spec.rb +++ b/spec/lib/open_food_network/feature_toggle_spec.rb @@ -48,5 +48,31 @@ module OpenFoodNetwork end end end + + context 'when passing in a block' do + let(:user) { build(:user) } + + context 'and the block does not specify arguments' do + before do + FeatureToggle.enable(:foo) { 'return value' } + end + + it "returns the block's return value" do + expect(FeatureToggle.enabled?(:foo, user)).to eq('return value') + end + end + + context 'and the block specifies arguments' do + let(:users) { [user.email] } + + before do + FeatureToggle.enable(:foo) { |user| users.include?(user.email) } + end + + it "returns the block's return value" do + expect(FeatureToggle.enabled?(:foo, user)).to eq(true) + end + end + end end end