Commit 39264445 authored by Alex Pooley's avatar Alex Pooley Committed by Imre Farkas

Stub feature flags before specs executes

Feature flags are stubbed as true by default during tests. The stub
creation can occur after spec code has already executed.

This MR stubs all feature flags to true before any spec code can
execute.
parent e94295cc
......@@ -17,9 +17,9 @@ RSpec.describe Groups::SharedProjectsController do
).execute(group)
end
let_it_be(:group) { create(:group) }
let_it_be(:user) { create(:user) }
let_it_be(:shared_project) do
let!(:group) { create(:group) }
let!(:user) { create(:user) }
let!(:shared_project) do
shared_project = create(:project, namespace: user.namespace)
share_project(shared_project)
......
......@@ -107,7 +107,6 @@ RSpec.configure do |config|
config.include FixtureHelpers
config.include NonExistingRecordsHelpers
config.include GitlabRoutingHelper
config.include StubFeatureFlags
config.include StubExperiments
config.include StubGitlabCalls
config.include StubGitlabData
......@@ -140,6 +139,8 @@ RSpec.configure do |config|
config.include SidekiqMiddleware
config.include StubActionCableConnection, type: :channel
include StubFeatureFlags
if ENV['CI'] || ENV['RETRIES']
# This includes the first try, i.e. tests will be run 4 times before failing.
config.default_retry_count = ENV.fetch('RETRIES', 3).to_i + 1
......@@ -158,6 +159,10 @@ RSpec.configure do |config|
# Reload all feature flags definitions
Feature.register_definitions
# Enable all features by default for testing
# Reset any changes in after hook.
stub_all_feature_flags
end
config.after(:all) do
......@@ -176,9 +181,6 @@ RSpec.configure do |config|
config.before do |example|
if example.metadata.fetch(:stub_feature_flags, true)
# Enable all features by default for testing
stub_all_feature_flags
# The following can be removed when we remove the staged rollout strategy
# and we can just enable it using instance wide settings
# (ie. ApplicationSetting#auto_devops_enabled)
......@@ -203,6 +205,8 @@ RSpec.configure do |config|
stub_feature_flags(file_identifier_hash: false)
allow(Gitlab::GitalyClient).to receive(:can_use_disk?).and_return(enable_rugged)
else
unstub_all_feature_flags
end
# Enable Marginalia feature for all specs in the test suite.
......@@ -314,6 +318,9 @@ RSpec.configure do |config|
config.after do
Fog.unmock! if Fog.mock?
Gitlab::CurrentSettings.clear_in_memory_application_settings!
# Reset all feature flag stubs to default for testing
stub_all_feature_flags
end
config.before(:example, :mailer) do
......
# frozen_string_literal: true
module StubFeatureFlags
def self.included(base)
# Extend Feature class with methods that can stub feature flags.
Feature.prepend(StubbedFeature)
end
class StubFeatureGate
attr_reader :flipper_id
......@@ -9,28 +14,14 @@ module StubFeatureFlags
end
end
# Ensure feature flags are stubbed and reset.
def stub_all_feature_flags
adapter = Flipper::Adapters::Memory.new
flipper = Flipper.new(adapter)
allow(Feature).to receive(:flipper).and_return(flipper)
# All new requested flags are enabled by default
allow(Feature).to receive(:enabled?).and_wrap_original do |m, *args|
feature_flag = m.call(*args)
# If feature flag is not persisted we mark the feature flag as enabled
# We do `m.call` as we want to validate the execution of method arguments
# and a feature flag state if it is not persisted
unless Feature.persisted_name?(args.first)
# TODO: this is hack to support `promo_feature_available?`
# We enable all feature flags by default unless they are `promo_`
# Issue: https://gitlab.com/gitlab-org/gitlab/-/issues/218667
feature_flag = true unless args.first.to_s.start_with?('promo_')
Feature.stub = true
Feature.reset_flipper
end
feature_flag
end
def unstub_all_feature_flags
Feature.stub = false
end
# Stub Feature flags with `flag_name: true/false`
......
# frozen_string_literal: true
# Extend the Feature class with the ability to stub feature flags.
module StubbedFeature
extend ActiveSupport::Concern
class_methods do
# Turn stubbed feature flags on or off.
def stub=(stub)
@stub = stub
end
def stub?
@stub.nil? ? true : @stub
end
# Wipe any previously set feature flags.
def reset_flipper
@flipper = nil
end
# Replace #flipper method with the optional stubbed/unstubbed version.
def flipper
if stub?
@flipper ||= Flipper.new(Flipper::Adapters::Memory.new)
else
super
end
end
# Replace #enabled? method with the optional stubbed/unstubbed version.
def enabled?(*args)
feature_flag = super(*args)
return feature_flag unless stub?
# If feature flag is not persisted we mark the feature flag as enabled
# We do `m.call` as we want to validate the execution of method arguments
# and a feature flag state if it is not persisted
unless Feature.persisted_name?(args.first)
# TODO: this is hack to support `promo_feature_available?`
# We enable all feature flags by default unless they are `promo_`
# Issue: https://gitlab.com/gitlab-org/gitlab/-/issues/218667
feature_flag = true unless args.first.to_s.start_with?('promo_')
end
feature_flag
end
end
end
......@@ -119,6 +119,42 @@ RSpec.describe StubFeatureFlags do
end
end
describe 'stub timing' do
context 'let_it_be variable' do
let_it_be(:let_it_be_var) { Feature.enabled?(:any_feature_flag) }
it { expect(let_it_be_var).to eq true }
end
context 'before_all variable' do
before_all do
@suite_var = Feature.enabled?(:any_feature_flag)
end
it { expect(@suite_var).to eq true }
end
context 'before(:all) variable' do
before(:all) do
@suite_var = Feature.enabled?(:any_feature_flag)
end
it { expect(@suite_var).to eq true }
end
context 'with stub_feature_flags meta' do
let(:var) { Feature.enabled?(:any_feature_flag) }
context 'as true', :stub_feature_flags do
it { expect(var).to eq true }
end
context 'as false', stub_feature_flags: false do
it { expect(var).to eq false }
end
end
end
def actor(actor)
case actor
when Array
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment