diff options
Diffstat (limited to 'spec/models/concerns/featurable_spec.rb')
-rw-r--r-- | spec/models/concerns/featurable_spec.rb | 184 |
1 files changed, 184 insertions, 0 deletions
diff --git a/spec/models/concerns/featurable_spec.rb b/spec/models/concerns/featurable_spec.rb new file mode 100644 index 00000000000..89720e3652c --- /dev/null +++ b/spec/models/concerns/featurable_spec.rb @@ -0,0 +1,184 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Featurable do + let_it_be(:user) { create(:user) } + let(:project) { create(:project) } + let(:feature_class) { subject.class } + let(:features) { feature_class::FEATURES } + + subject { project.project_feature } + + describe '.quoted_access_level_column' do + it 'returns the table name and quoted column name for a feature' do + expected = '"project_features"."issues_access_level"' + + expect(feature_class.quoted_access_level_column(:issues)).to eq(expected) + end + end + + describe '.access_level_attribute' do + it { expect(feature_class.access_level_attribute(:wiki)).to eq :wiki_access_level } + + it 'raises error for unspecified feature' do + expect { feature_class.access_level_attribute(:unknown) } + .to raise_error(ArgumentError, /invalid feature: unknown/) + end + end + + describe '.set_available_features' do + let!(:klass) do + Class.new do + include Featurable + set_available_features %i(feature1 feature2) + + def feature1_access_level + Featurable::DISABLED + end + + def feature2_access_level + Featurable::ENABLED + end + end + end + let!(:instance) { klass.new } + + it { expect(klass.available_features).to eq [:feature1, :feature2] } + it { expect(instance.feature1_enabled?).to be_falsey } + it { expect(instance.feature2_enabled?).to be_truthy } + end + + describe '.available_features' do + it { expect(feature_class.available_features).to include(*features) } + end + + describe '#access_level' do + it 'returns access level' do + expect(subject.access_level(:wiki)).to eq(subject.wiki_access_level) + end + end + + describe '#feature_available?' do + let(:features) { %w(issues wiki builds merge_requests snippets repository pages metrics_dashboard) } + + context 'when features are disabled' do + it "returns false" do + update_all_project_features(project, features, ProjectFeature::DISABLED) + + features.each do |feature| + expect(project.feature_available?(feature.to_sym, user)).to eq(false), "#{feature} failed" + end + end + end + + context 'when features are enabled only for team members' do + it "returns false when user is not a team member" do + update_all_project_features(project, features, ProjectFeature::PRIVATE) + + features.each do |feature| + expect(project.feature_available?(feature.to_sym, user)).to eq(false), "#{feature} failed" + end + end + + it "returns true when user is a team member" do + project.add_developer(user) + + update_all_project_features(project, features, ProjectFeature::PRIVATE) + + features.each do |feature| + expect(project.feature_available?(feature.to_sym, user)).to eq(true), "#{feature} failed" + end + end + + it "returns true when user is a member of project group" do + group = create(:group) + project = create(:project, namespace: group) + group.add_developer(user) + + update_all_project_features(project, features, ProjectFeature::PRIVATE) + + features.each do |feature| + expect(project.feature_available?(feature.to_sym, user)).to eq(true), "#{feature} failed" + end + end + + context 'when admin mode is enabled', :enable_admin_mode do + it "returns true if user is an admin" do + user.update_attribute(:admin, true) + + update_all_project_features(project, features, ProjectFeature::PRIVATE) + + features.each do |feature| + expect(project.feature_available?(feature.to_sym, user)).to eq(true), "#{feature} failed" + end + end + end + + context 'when admin mode is disabled' do + it "returns false when user is an admin" do + user.update_attribute(:admin, true) + + update_all_project_features(project, features, ProjectFeature::PRIVATE) + + features.each do |feature| + expect(project.feature_available?(feature.to_sym, user)).to eq(false), "#{feature} failed" + end + end + end + end + + context 'when feature is enabled for everyone' do + it "returns true" do + expect(project.feature_available?(:issues, user)).to eq(true) + end + end + + context 'when feature is disabled by a feature flag' do + it 'returns false' do + stub_feature_flags(issues: false) + + expect(project.feature_available?(:issues, user)).to eq(false) + end + end + + context 'when feature is enabled by a feature flag' do + it 'returns true' do + stub_feature_flags(issues: true) + + expect(project.feature_available?(:issues, user)).to eq(true) + end + end + end + + describe '#*_enabled?' do + let(:features) { %w(wiki builds merge_requests) } + + it "returns false when feature is disabled" do + update_all_project_features(project, features, ProjectFeature::DISABLED) + + features.each do |feature| + expect(project.public_send("#{feature}_enabled?")).to eq(false), "#{feature} failed" + end + end + + it "returns true when feature is enabled only for team members" do + update_all_project_features(project, features, ProjectFeature::PRIVATE) + + features.each do |feature| + expect(project.public_send("#{feature}_enabled?")).to eq(true), "#{feature} failed" + end + end + + it "returns true when feature is enabled for everyone" do + features.each do |feature| + expect(project.public_send("#{feature}_enabled?")).to eq(true), "#{feature} failed" + end + end + end + + def update_all_project_features(project, features, value) + project_feature_attributes = features.map { |f| ["#{f}_access_level", value] }.to_h + project.project_feature.update(project_feature_attributes) + end +end |