diff options
Diffstat (limited to 'qa/spec/specs/helpers/feature_flag_spec.rb')
-rw-r--r-- | qa/spec/specs/helpers/feature_flag_spec.rb | 164 |
1 files changed, 164 insertions, 0 deletions
diff --git a/qa/spec/specs/helpers/feature_flag_spec.rb b/qa/spec/specs/helpers/feature_flag_spec.rb new file mode 100644 index 00000000000..a1300ecf073 --- /dev/null +++ b/qa/spec/specs/helpers/feature_flag_spec.rb @@ -0,0 +1,164 @@ +# frozen_string_literal: true + +require 'rspec/core/sandbox' + +RSpec.describe QA::Specs::Helpers::FeatureFlag do + include QA::Support::Helpers::StubEnv + include QA::Specs::Helpers::RSpec + + around do |ex| + RSpec::Core::Sandbox.sandboxed do |config| + config.add_formatter QA::Support::Formatters::ContextFormatter + config.add_formatter QA::Support::Formatters::QuarantineFormatter + config.add_formatter QA::Support::Formatters::FeatureFlagFormatter + + # If there is an example-within-an-example, we want to make sure the inner example + # does not get a reference to the outer example (the real spec) if it calls + # something like `pending` + config.before(:context) { RSpec.current_example = nil } + + config.color_mode = :off + + ex.run + end + end + + describe '.skip_or_run_feature_flag_tests_or_contexts' do + shared_examples 'runs with given feature flag metadata' do |metadata| + it do + group = describe_successfully 'Feature flag test', feature_flag: metadata do + it('passes') {} + end + + expect(group.examples.first.execution_result.status).to eq(:passed) + end + end + + shared_examples 'skips with given feature flag metadata' do |metadata| + it do + group = describe_successfully 'Feature flag test', feature_flag: metadata do + it('is skipped') {} + end + + expect(group.examples.first.execution_result.status).to eq(:pending) + end + end + + context 'when run on staging' do + before(:context) do + QA::Runtime::Scenario.define(:gitlab_address, 'https://staging.gitlab.com') + end + + context 'when no scope is defined' do + it_behaves_like 'runs with given feature flag metadata', { name: 'no_scope_ff' } + + it 'is skipped if quarantine tag is also applied' do + group = describe_successfully( + 'Feature flag with no scope', + feature_flag: { name: 'quarantine_with_ff' }, + quarantine: { + issue: 'https://gitlab.com/test-group/test/-/issues/123', + type: 'bug' + } + ) do + it('is skipped') {} + end + + expect(group.examples.first.execution_result.status).to eq(:pending) + end + end + + it_behaves_like 'runs with given feature flag metadata', { name: 'actor_ff', scope: :project } + + it_behaves_like 'skips with given feature flag metadata', { name: 'global_ff', scope: :global } + + context 'when should be skipped in a specific job' do + before do + stub_env('CI_JOB_NAME', 'job-to-skip') + end + + it 'is skipped for that job' do + group = describe_successfully( + 'Test should be skipped', + feature_flag: { name: 'skip_job_ff' }, + except: { job: 'job-to-skip' } + ) do + it('does not run on staging in specified job') {} + end + + expect(group.examples.first.execution_result.status).to eq(:pending) + end + end + + context 'when should only run in a specific job' do + before do + stub_env('CI_JOB_NAME', 'job-to-run') + end + + it 'is run for that job' do + group = describe_successfully( + 'Test should run', + feature_flag: { name: 'run_job_ff' }, + only: { job: 'job-to-run' } + ) do + it('runs on staging in specified job') {} + end + + expect(group.examples.first.execution_result.status).to eq(:passed) + end + + it 'skips if test is set to only run in a job different from current CI job' do + group = describe_successfully( + 'Test should be skipped', + feature_flag: { name: 'skip_job_ff' }, + only: { job: 'other-job' } + ) do + it('does not run on staging in specified job') {} + end + + expect(group.examples.first.execution_result.status).to eq(:pending) + end + end + end + + context 'when run on production' do + before(:context) do + QA::Runtime::Scenario.define(:gitlab_address, 'https://gitlab.com') + end + + context 'when no scope is defined' do + it_behaves_like 'skips with given feature flag metadata', { name: 'no_scope_ff' } + + context 'for only one test in the example group' do + it 'only skips specified test and runs all others' do + group = describe_successfully 'Feature flag set for one test' do + it('is skipped', feature_flag: { name: 'single_test_ff' }) {} + it('passes') {} + end + + expect(group.examples[0].execution_result.status).to eq(:pending) + expect(group.examples[1].execution_result.status).to eq(:passed) + end + end + end + + it_behaves_like 'skips with given feature flag metadata', { name: 'actor_ff', scope: :project } + + it_behaves_like 'skips with given feature flag metadata', { name: 'global_ff', scope: :global } + end + + # The nightly package job, for example, does not run against a live environment with + # a defined gitlab_address. In this case, feature_flag tag logic can be safely ignored + context 'when run without a gitlab address specified' do + before(:context) do + QA::Runtime::Scenario.define(:gitlab_address, nil) + end + + it_behaves_like 'runs with given feature flag metadata', { name: 'no_scope_ff' } + + it_behaves_like 'runs with given feature flag metadata', { name: 'actor_ff', scope: :project } + + it_behaves_like 'runs with given feature flag metadata', { name: 'global_ff', scope: :global } + end + end +end |