diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-09-20 13:18:24 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-09-20 13:18:24 +0000 |
commit | 0653e08efd039a5905f3fa4f6e9cef9f5d2f799c (patch) | |
tree | 4dcc884cf6d81db44adae4aa99f8ec1233a41f55 /spec/models/concerns | |
parent | 744144d28e3e7fddc117924fef88de5d9674fe4c (diff) | |
download | gitlab-ce-0653e08efd039a5905f3fa4f6e9cef9f5d2f799c.tar.gz |
Add latest changes from gitlab-org/gitlab@14-3-stable-eev14.3.0-rc42
Diffstat (limited to 'spec/models/concerns')
-rw-r--r-- | spec/models/concerns/approvable_base_spec.rb | 28 | ||||
-rw-r--r-- | spec/models/concerns/calloutable_spec.rb | 26 | ||||
-rw-r--r-- | spec/models/concerns/featurable_spec.rb | 5 | ||||
-rw-r--r-- | spec/models/concerns/issuable_spec.rb | 17 | ||||
-rw-r--r-- | spec/models/concerns/loose_foreign_key_spec.rb | 83 | ||||
-rw-r--r-- | spec/models/concerns/partitioned_table_spec.rb | 6 | ||||
-rw-r--r-- | spec/models/concerns/sanitizable_spec.rb | 101 | ||||
-rw-r--r-- | spec/models/concerns/taggable_queries_spec.rb | 9 |
8 files changed, 268 insertions, 7 deletions
diff --git a/spec/models/concerns/approvable_base_spec.rb b/spec/models/concerns/approvable_base_spec.rb index c7ea2631a24..79053e98db7 100644 --- a/spec/models/concerns/approvable_base_spec.rb +++ b/spec/models/concerns/approvable_base_spec.rb @@ -60,6 +60,34 @@ RSpec.describe ApprovableBase do end end + describe '#can_be_unapproved_by?' do + subject { merge_request.can_be_unapproved_by?(user) } + + before do + merge_request.project.add_developer(user) + end + + it 'returns false' do + is_expected.to be_falsy + end + + context 'when a user has approved' do + let!(:approval) { create(:approval, merge_request: merge_request, user: user) } + + it 'returns true' do + is_expected.to be_truthy + end + end + + context 'when a user is nil' do + let(:user) { nil } + + it 'returns false' do + is_expected.to be_falsy + end + end + end + describe '.not_approved_by_users_with_usernames' do subject { MergeRequest.not_approved_by_users_with_usernames([user.username, user2.username]) } diff --git a/spec/models/concerns/calloutable_spec.rb b/spec/models/concerns/calloutable_spec.rb new file mode 100644 index 00000000000..d847413de88 --- /dev/null +++ b/spec/models/concerns/calloutable_spec.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Calloutable do + subject { build(:user_callout) } + + describe "Associations" do + it { is_expected.to belong_to(:user) } + end + + describe 'validations' do + it { is_expected.to validate_presence_of(:user) } + end + + describe '#dismissed_after?' do + let(:some_feature_name) { UserCallout.feature_names.keys.second } + let(:callout_dismissed_month_ago) { create(:user_callout, feature_name: some_feature_name, dismissed_at: 1.month.ago )} + let(:callout_dismissed_day_ago) { create(:user_callout, feature_name: some_feature_name, dismissed_at: 1.day.ago )} + + it 'returns whether a callout dismissed after specified date' do + expect(callout_dismissed_month_ago.dismissed_after?(15.days.ago)).to eq(false) + expect(callout_dismissed_day_ago.dismissed_after?(15.days.ago)).to eq(true) + end + end +end diff --git a/spec/models/concerns/featurable_spec.rb b/spec/models/concerns/featurable_spec.rb index 295f3523dd5..453b6f7f29a 100644 --- a/spec/models/concerns/featurable_spec.rb +++ b/spec/models/concerns/featurable_spec.rb @@ -30,8 +30,11 @@ RSpec.describe Featurable do describe '.set_available_features' do let!(:klass) do - Class.new do + Class.new(ApplicationRecord) do include Featurable + + self.table_name = 'project_features' + set_available_features %i(feature1 feature2) def feature1_access_level diff --git a/spec/models/concerns/issuable_spec.rb b/spec/models/concerns/issuable_spec.rb index 071e0dcba44..2a3f639a8ac 100644 --- a/spec/models/concerns/issuable_spec.rb +++ b/spec/models/concerns/issuable_spec.rb @@ -368,6 +368,23 @@ RSpec.describe Issuable do expect(sorted_issue_ids).to eq(sorted_issue_ids.uniq) end end + + context 'by title' do + let!(:issue1) { create(:issue, project: project, title: 'foo') } + let!(:issue2) { create(:issue, project: project, title: 'bar') } + let!(:issue3) { create(:issue, project: project, title: 'baz') } + let!(:issue4) { create(:issue, project: project, title: 'Baz 2') } + + it 'sorts asc' do + issues = project.issues.sort_by_attribute('title_asc') + expect(issues).to eq([issue2, issue3, issue4, issue1]) + end + + it 'sorts desc' do + issues = project.issues.sort_by_attribute('title_desc') + expect(issues).to eq([issue1, issue4, issue3, issue2]) + end + end end describe '#subscribed?' do diff --git a/spec/models/concerns/loose_foreign_key_spec.rb b/spec/models/concerns/loose_foreign_key_spec.rb new file mode 100644 index 00000000000..ce5e33261a9 --- /dev/null +++ b/spec/models/concerns/loose_foreign_key_spec.rb @@ -0,0 +1,83 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe LooseForeignKey do + let(:project_klass) do + Class.new(ApplicationRecord) do + include LooseForeignKey + + self.table_name = 'projects' + + loose_foreign_key :issues, :project_id, on_delete: :async_delete, gitlab_schema: :gitlab_main + loose_foreign_key 'merge_requests', 'project_id', 'on_delete' => 'async_nullify', 'gitlab_schema' => :gitlab_main + end + end + + it 'exposes the loose foreign key definitions' do + definitions = project_klass.loose_foreign_key_definitions + + tables = definitions.map(&:to_table) + expect(tables).to eq(%w[issues merge_requests]) + end + + it 'casts strings to symbol' do + definition = project_klass.loose_foreign_key_definitions.last + + expect(definition.from_table).to eq('projects') + expect(definition.to_table).to eq('merge_requests') + expect(definition.column).to eq('project_id') + expect(definition.on_delete).to eq(:async_nullify) + expect(definition.options[:gitlab_schema]).to eq(:gitlab_main) + end + + context 'validation' do + context 'on_delete validation' do + let(:invalid_class) do + Class.new(ApplicationRecord) do + include LooseForeignKey + + self.table_name = 'projects' + + loose_foreign_key :issues, :project_id, on_delete: :async_delete, gitlab_schema: :gitlab_main + loose_foreign_key :merge_requests, :project_id, on_delete: :async_nullify, gitlab_schema: :gitlab_main + loose_foreign_key :merge_requests, :project_id, on_delete: :destroy, gitlab_schema: :gitlab_main + end + end + + it 'raises error when invalid `on_delete` option was given' do + expect { invalid_class }.to raise_error /Invalid on_delete option given: destroy/ + end + end + + context 'gitlab_schema validation' do + let(:invalid_class) do + Class.new(ApplicationRecord) do + include LooseForeignKey + + self.table_name = 'projects' + + loose_foreign_key :merge_requests, :project_id, on_delete: :async_nullify, gitlab_schema: :unknown + end + end + + it 'raises error when invalid `gitlab_schema` option was given' do + expect { invalid_class }.to raise_error /Invalid gitlab_schema option given: unknown/ + end + end + + context 'inheritance validation' do + let(:inherited_project_class) do + Class.new(Project) do + include LooseForeignKey + + loose_foreign_key :issues, :project_id, on_delete: :async_delete, gitlab_schema: :gitlab_main + end + end + + it 'raises error when loose_foreign_key is defined in a child ActiveRecord model' do + expect { inherited_project_class }.to raise_error /Please define the loose_foreign_key on the Project class/ + end + end + end +end diff --git a/spec/models/concerns/partitioned_table_spec.rb b/spec/models/concerns/partitioned_table_spec.rb index c37fb81a1cf..714db4e21bd 100644 --- a/spec/models/concerns/partitioned_table_spec.rb +++ b/spec/models/concerns/partitioned_table_spec.rb @@ -35,11 +35,5 @@ RSpec.describe PartitionedTable do expect(my_class.partitioning_strategy.partitioning_key).to eq(key) end - - it 'registers itself with the PartitionCreator' do - expect(Gitlab::Database::Partitioning::PartitionManager).to receive(:register).with(my_class) - - subject - end end end diff --git a/spec/models/concerns/sanitizable_spec.rb b/spec/models/concerns/sanitizable_spec.rb new file mode 100644 index 00000000000..4a1d463d666 --- /dev/null +++ b/spec/models/concerns/sanitizable_spec.rb @@ -0,0 +1,101 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Sanitizable do + let_it_be(:klass) do + Class.new do + include ActiveModel::Model + include ActiveModel::Attributes + include ActiveModel::Validations + include ActiveModel::Validations::Callbacks + include Sanitizable + + attribute :id, :integer + attribute :name, :string + attribute :description, :string + attribute :html_body, :string + + sanitizes! :name, :description + + def self.model_name + ActiveModel::Name.new(self, nil, 'SomeModel') + end + end + end + + shared_examples 'noop' do + it 'has no effect' do + expect(subject).to eq(input) + end + end + + shared_examples 'a sanitizable field' do |field| + let(:record) { klass.new(id: 1, name: input, description: input, html_body: input) } + + before do + record.valid? + end + + subject { record.public_send(field) } + + describe field do + context 'when input is nil' do + let_it_be(:input) { nil } + + it_behaves_like 'noop' + end + + context 'when input does not contain any html' do + let_it_be(:input) { 'hello, world!' } + + it_behaves_like 'noop' + end + + context 'when input contains html' do + let_it_be(:input) { 'hello<script>alert(1)</script>' } + + it 'sanitizes the input' do + expect(subject).to eq('hello') + end + + context 'when input includes html entities' do + let(:input) { '<div>hello&world</div>' } + + it 'does not escape them' do + expect(subject).to eq(' hello&world ') + end + end + end + + context 'when input contains pre-escaped html entities' do + let_it_be(:input) { '<script>alert(1)</script>' } + + it_behaves_like 'noop' + + it 'is not valid', :aggregate_failures do + expect(record).not_to be_valid + expect(record.errors.full_messages).to include('Name cannot contain escaped HTML entities') + end + end + end + end + + shared_examples 'a non-sanitizable field' do |field, input| + describe field do + subject { klass.new(field => input).valid? } + + it 'has no effect' do + expect(Sanitize).not_to receive(:fragment) + + subject + end + end + end + + it_behaves_like 'a non-sanitizable field', :id, 1 + it_behaves_like 'a non-sanitizable field', :html_body, 'hello<script>alert(1)</script>' + + it_behaves_like 'a sanitizable field', :name + it_behaves_like 'a sanitizable field', :description +end diff --git a/spec/models/concerns/taggable_queries_spec.rb b/spec/models/concerns/taggable_queries_spec.rb new file mode 100644 index 00000000000..0d248c4636e --- /dev/null +++ b/spec/models/concerns/taggable_queries_spec.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe TaggableQueries do + it 'keeps MAX_TAGS_IDS in sync with TAGS_LIMIT' do + expect(described_class::MAX_TAGS_IDS).to eq(Gitlab::Ci::Config::Entry::Tags::TAGS_LIMIT) + end +end |