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..f57e740bc4 100644 --- a/lib/open_food_network/feature_toggle.rb +++ b/lib/open_food_network/feature_toggle.rb @@ -30,11 +30,9 @@ 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, &block) Thread.current[:features] ||= {} - Thread.current[:features][feature_name] = Feature.new(user_emails) + Thread.current[:features][feature_name] = Feature.new(block) end def initialize @@ -68,17 +66,17 @@ module OpenFoodNetwork end class Feature - def initialize(users = []) - @users = users + def initialize(block) + @block = block end def enabled?(user) - users.include?(user.email) + block.call(user) end private - attr_reader :users + attr_reader :block end class NullFeature diff --git a/spec/initializers/feature_toggles_spec.rb b/spec/initializers/feature_toggles_spec.rb new file mode 100644 index 0000000000..0433d4508b --- /dev/null +++ b/spec/initializers/feature_toggles_spec.rb @@ -0,0 +1,65 @@ +require 'spec_helper' + +describe 'config/initializers/feature_toggles.rb' do + # Executes the initializer's code block by reading the Ruby file. Note that `Kernel#require` would + # prevent this from happening twice. + subject(:execute_initializer) do + load Rails.root.join('config/initializers/feature_toggles.rb') + end + + 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 + execute_initializer + + enabled = OpenFoodNetwork::FeatureToggle.enabled?(:customer_balance, user) + expect(enabled).to eq(true) + end + end + + context 'when beta_testers is a list of emails' do + let(:other_user) { build(:user) } + + context 'and the user is in the list' do + before { ENV['BETA_TESTERS'] = "#{user.email}, #{other_user.email}" } + + it 'enables the feature' do + execute_initializer + + 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'] = "#{other_user.email}" } + + it 'disables the feature' do + execute_initializer + + enabled = OpenFoodNetwork::FeatureToggle.enabled?(:customer_balance, user) + expect(enabled).to eq(false) + end + end + + context 'and the list is empty' do + before { ENV['BETA_TESTERS'] = '' } + + it 'disables the feature' do + execute_initializer + + 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..d9904b0fd6 100644 --- a/spec/lib/open_food_network/feature_toggle_spec.rb +++ b/spec/lib/open_food_network/feature_toggle_spec.rb @@ -32,19 +32,25 @@ module OpenFoodNetwork context 'when specifying users' do let(:user) { build(:user) } - context 'and the feature is enabled for them' do - before { FeatureToggle.enable(:foo, [user.email]) } + context 'and the block does not specify arguments' do + before do + FeatureToggle.enable(:foo) { 'return value' } + end - it 'returns true' do - expect(FeatureToggle.enabled?(:foo, user)).to eq(true) + it "returns the block's return value" do + expect(FeatureToggle.enabled?(:foo, user)).to eq('return value') end end - context 'and the feature is disabled for them' do - before { FeatureToggle.enable(:foo, []) } + context 'and the block specifies arguments' do + let(:users) { [user.email] } - it 'returns false' do - expect(FeatureToggle.enabled?(:foo, user)).to eq(false) + 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