diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-10-21 07:08:36 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-10-21 07:08:36 +0000 |
commit | 48aff82709769b098321c738f3444b9bdaa694c6 (patch) | |
tree | e00c7c43e2d9b603a5a6af576b1685e400410dee /qa/spec/runtime/feature_spec.rb | |
parent | 879f5329ee916a948223f8f43d77fba4da6cd028 (diff) | |
download | gitlab-ce-48aff82709769b098321c738f3444b9bdaa694c6.tar.gz |
Add latest changes from gitlab-org/gitlab@13-5-stable-eev13.5.0-rc42
Diffstat (limited to 'qa/spec/runtime/feature_spec.rb')
-rw-r--r-- | qa/spec/runtime/feature_spec.rb | 252 |
1 files changed, 190 insertions, 62 deletions
diff --git a/qa/spec/runtime/feature_spec.rb b/qa/spec/runtime/feature_spec.rb index db3c2f65963..39c20dd3070 100644 --- a/qa/spec/runtime/feature_spec.rb +++ b/qa/spec/runtime/feature_spec.rb @@ -1,87 +1,215 @@ # frozen_string_literal: true -describe QA::Runtime::Feature do +RSpec.describe QA::Runtime::Feature do let(:api_client) { double('QA::Runtime::API::Client') } let(:request) { Struct.new(:url).new('http://api') } let(:response_post) { Struct.new(:code).new(201) } - let(:response_get) { Struct.new(:code, :body).new(200, '[{ "name": "a-flag", "state": "on" }]') } before do allow(described_class).to receive(:api_client).and_return(api_client) end - describe '.enable' do - it 'enables a feature flag' do - expect(QA::Runtime::API::Request) - .to receive(:new) - .with(api_client, "/features/a-flag") - .and_return(request) - expect(described_class) - .to receive(:post) - .with(request.url, { value: true }) - .and_return(response_post) - - subject.enable('a-flag') - end + where(:feature_flag) do + ['a_flag', :a_flag] end - describe '.enable_and_verify' do - it 'enables a feature flag' do - allow(described_class).to receive(:get).and_return(response_get) + with_them do + shared_examples 'enables a feature flag' do + it 'enables a feature flag for a scope' do + allow(described_class).to receive(:get) + .and_return(Struct.new(:code, :body).new(200, '[{ "name": "a_flag", "state": "on" }]')) - expect(QA::Runtime::API::Request).to receive(:new) - .with(api_client, "/features/a-flag").and_return(request) - expect(described_class).to receive(:post) - .with(request.url, { value: true }).and_return(response_post) - expect(QA::Runtime::API::Request).to receive(:new) - .with(api_client, "/features").and_return(request) + expect(QA::Runtime::API::Request).to receive(:new) + .with(api_client, "/features/a_flag").and_return(request) + expect(described_class).to receive(:post) + .with(request.url, { value: true, scope => actor_name }).and_return(response_post) + expect(QA::Runtime::API::Request).to receive(:new) + .with(api_client, "/features").and_return(request) + expect(QA::Runtime::Logger).to receive(:info).with("Enabling feature: a_flag for scope \"#{scope}: #{actor_name}\"") + expect(QA::Runtime::Logger).to receive(:info).with("Successfully enabled and verified feature flag: a_flag") - subject.enable_and_verify('a-flag') + described_class.enable(feature_flag, scope => actor) + end end - end - describe '.disable' do - it 'disables a feature flag' do - expect(QA::Runtime::API::Request) - .to receive(:new) - .with(api_client, "/features/a-flag") - .and_return(request) - expect(described_class) - .to receive(:post) - .with(request.url, { value: false }) - .and_return(response_post) - - subject.disable('a-flag') + shared_examples 'disables a feature flag' do + it 'disables a feature flag for a scope' do + allow(described_class).to receive(:get) + .and_return(Struct.new(:code, :body).new(200, '[{ "name": "a_flag", "state": "off" }]')) + + expect(QA::Runtime::API::Request).to receive(:new) + .with(api_client, "/features/a_flag").and_return(request) + expect(described_class).to receive(:post) + .with(request.url, { value: false, scope => actor_name }).and_return(response_post) + expect(QA::Runtime::API::Request).to receive(:new) + .with(api_client, "/features").and_return(request) + expect(QA::Runtime::Logger).to receive(:info).with("Disabling feature: a_flag for scope \"#{scope}: #{actor_name}\"") + expect(QA::Runtime::Logger).to receive(:info).with("Successfully disabled and verified feature flag: a_flag") + + described_class.disable(feature_flag, scope => actor ) + end end - end - describe '.disable_and_verify' do - it 'disables a feature flag' do - allow(described_class).to receive(:get) - .and_return(Struct.new(:code, :body).new(200, '[{ "name": "a-flag", "state": "off" }]')) + shared_examples 'checks a feature flag' do + context 'when the flag is enabled for a scope' do + it 'returns the feature flag state' do + expect(QA::Runtime::API::Request) + .to receive(:new) + .with(api_client, "/features") + .and_return(request) + expect(described_class) + .to receive(:get) + .and_return(Struct.new(:code, :body).new(200, %Q([{ "name": "a_flag", "state": "conditional", "gates": #{gates} }]))) + + expect(described_class.enabled?(feature_flag, scope => actor)).to be_truthy + end + end + end - expect(QA::Runtime::API::Request).to receive(:new) - .with(api_client, "/features/a-flag").and_return(request) - expect(described_class).to receive(:post) - .with(request.url, { value: false }).and_return(response_post) - expect(QA::Runtime::API::Request).to receive(:new) - .with(api_client, "/features").and_return(request) + describe '.enable' do + it 'enables a feature flag' do + allow(described_class).to receive(:get) + .and_return(Struct.new(:code, :body).new(200, '[{ "name": "a_flag", "state": "on" }]')) - subject.disable_and_verify('a-flag') + expect(QA::Runtime::API::Request).to receive(:new) + .with(api_client, "/features/a_flag").and_return(request) + expect(described_class).to receive(:post) + .with(request.url, { value: true }).and_return(response_post) + expect(QA::Runtime::API::Request).to receive(:new) + .with(api_client, "/features").and_return(request) + + described_class.enable(feature_flag) + end + + context 'when a project scope is provided' do + it_behaves_like 'enables a feature flag' do + let(:scope) { :project } + let(:actor_name) { 'group-name/project-name' } + let(:actor) { Struct.new(:full_path).new(actor_name) } + end + end + + context 'when a group scope is provided' do + it_behaves_like 'enables a feature flag' do + let(:scope) { :group } + let(:actor_name) { 'group-name' } + let(:actor) { Struct.new(:full_path).new(actor_name) } + end + end + + context 'when a user scope is provided' do + it_behaves_like 'enables a feature flag' do + let(:scope) { :user } + let(:actor_name) { 'user-name' } + let(:actor) { Struct.new(:username).new(actor_name) } + end + end + + context 'when a feature group scope is provided' do + it_behaves_like 'enables a feature flag' do + let(:scope) { :feature_group } + let(:actor_name) { 'foo' } + let(:actor) { "foo" } + end + end end - end - describe '.enabled?' do - it 'returns a feature flag state' do - expect(QA::Runtime::API::Request) - .to receive(:new) - .with(api_client, "/features") - .and_return(request) - expect(described_class) - .to receive(:get) - .and_return(response_get) - - expect(subject.enabled?('a-flag')).to be_truthy + describe '.disable' do + it 'disables a feature flag' do + allow(described_class).to receive(:get) + .and_return(Struct.new(:code, :body).new(200, '[{ "name": "a_flag", "state": "off" }]')) + + expect(QA::Runtime::API::Request).to receive(:new) + .with(api_client, "/features/a_flag").and_return(request) + expect(described_class).to receive(:post) + .with(request.url, { value: false }).and_return(response_post) + expect(QA::Runtime::API::Request).to receive(:new) + .with(api_client, "/features").and_return(request) + + described_class.disable(feature_flag) + end + + context 'when a project scope is provided' do + it_behaves_like 'disables a feature flag' do + let(:scope) { :project } + let(:actor_name) { 'group-name/project-name' } + let(:actor) { Struct.new(:full_path).new(actor_name) } + end + end + + context 'when a group scope is provided' do + it_behaves_like 'disables a feature flag' do + let(:scope) { :group } + let(:actor_name) { 'group-name' } + let(:actor) { Struct.new(:full_path).new(actor_name) } + end + end + + context 'when a user scope is provided' do + it_behaves_like 'disables a feature flag' do + let(:scope) { :user } + let(:actor_name) { 'user-name' } + let(:actor) { Struct.new(:username).new(actor_name) } + end + end + + context 'when a feature group scope is provided' do + it_behaves_like 'disables a feature flag' do + let(:scope) { :feature_group } + let(:actor_name) { 'foo' } + let(:actor) { "foo" } + end + end + end + + describe '.enabled?' do + it 'returns a feature flag state' do + expect(QA::Runtime::API::Request) + .to receive(:new) + .with(api_client, "/features") + .and_return(request) + expect(described_class) + .to receive(:get) + .and_return(Struct.new(:code, :body).new(200, '[{ "name": "a_flag", "state": "on" }]')) + + expect(described_class.enabled?(feature_flag)).to be_truthy + end + + context 'when a project scope is provided' do + it_behaves_like 'checks a feature flag' do + let(:scope) { :project } + let(:actor_name) { 'group-name/project-name' } + let(:actor) { Struct.new(:full_path, :id).new(actor_name, 270) } + let(:gates) { %q([{"key": "actors", "value": ["Project:270"]}]) } + end + end + + context 'when a group scope is provided' do + it_behaves_like 'checks a feature flag' do + let(:scope) { :group } + let(:actor_name) { 'group-name' } + let(:actor) { Struct.new(:full_path, :id).new(actor_name, 33) } + let(:gates) { %q([{"key": "actors", "value": ["Group:33"]}]) } + end + end + + context 'when a user scope is provided' do + it_behaves_like 'checks a feature flag' do + let(:scope) { :user } + let(:actor_name) { 'user-name' } + let(:actor) { Struct.new(:full_path, :id).new(actor_name, 13) } + let(:gates) { %q([{"key": "actors", "value": ["User:13"]}]) } + end + end + + context 'when a feature group scope is provided' do + it_behaves_like 'checks a feature flag' do + let(:scope) { :feature_group } + let(:actor_name) { 'foo' } + let(:actor) { "foo" } + let(:gates) { %q([{"key": "groups", "value": ["foo"]}]) } + end + end end end end |