summaryrefslogtreecommitdiff
path: root/spec/models
diff options
context:
space:
mode:
Diffstat (limited to 'spec/models')
-rw-r--r--spec/models/commit_spec.rb13
-rw-r--r--spec/models/concerns/mentionable_spec.rb5
-rw-r--r--spec/models/concerns/milestoneish_spec.rb104
-rw-r--r--spec/models/event_spec.rb36
-rw-r--r--spec/models/merge_request_spec.rb48
-rw-r--r--spec/models/milestone_spec.rb20
-rw-r--r--spec/models/repository_spec.rb111
-rw-r--r--spec/models/todo_spec.rb85
8 files changed, 401 insertions, 21 deletions
diff --git a/spec/models/commit_spec.rb b/spec/models/commit_spec.rb
index 253902512c3..0e9111c8029 100644
--- a/spec/models/commit_spec.rb
+++ b/spec/models/commit_spec.rb
@@ -86,10 +86,21 @@ eos
let(:issue) { create :issue, project: project }
let(:other_project) { create :project, :public }
let(:other_issue) { create :issue, project: other_project }
+ let(:commiter) { create :user }
+
+ before do
+ project.team << [commiter, :developer]
+ other_project.team << [commiter, :developer]
+ end
it 'detects issues that this commit is marked as closing' do
ext_ref = "#{other_project.path_with_namespace}##{other_issue.iid}"
- allow(commit).to receive(:safe_message).and_return("Fixes ##{issue.iid} and #{ext_ref}")
+
+ allow(commit).to receive_messages(
+ safe_message: "Fixes ##{issue.iid} and #{ext_ref}",
+ committer_email: commiter.email
+ )
+
expect(commit.closes_issues).to include(issue)
expect(commit.closes_issues).to include(other_issue)
end
diff --git a/spec/models/concerns/mentionable_spec.rb b/spec/models/concerns/mentionable_spec.rb
index 20f0c561e44..cb33edde820 100644
--- a/spec/models/concerns/mentionable_spec.rb
+++ b/spec/models/concerns/mentionable_spec.rb
@@ -48,7 +48,8 @@ describe Issue, "Mentionable" do
describe '#create_new_cross_references!' do
let(:project) { create(:project) }
- let(:issues) { create_list(:issue, 2, project: project) }
+ let(:author) { create(:author) }
+ let(:issues) { create_list(:issue, 2, project: project, author: author) }
context 'before changes are persisted' do
it 'ignores pre-existing references' do
@@ -91,7 +92,7 @@ describe Issue, "Mentionable" do
end
def create_issue(description:)
- create(:issue, project: project, description: description)
+ create(:issue, project: project, description: description, author: author)
end
end
end
diff --git a/spec/models/concerns/milestoneish_spec.rb b/spec/models/concerns/milestoneish_spec.rb
new file mode 100644
index 00000000000..47c3be673c5
--- /dev/null
+++ b/spec/models/concerns/milestoneish_spec.rb
@@ -0,0 +1,104 @@
+require 'spec_helper'
+
+describe Milestone, 'Milestoneish' do
+ let(:author) { create(:user) }
+ let(:assignee) { create(:user) }
+ let(:non_member) { create(:user) }
+ let(:member) { create(:user) }
+ let(:admin) { create(:admin) }
+ let(:project) { create(:project, :public) }
+ let(:milestone) { create(:milestone, project: project) }
+ let!(:issue) { create(:issue, project: project, milestone: milestone) }
+ let!(:security_issue_1) { create(:issue, :confidential, project: project, author: author, milestone: milestone) }
+ let!(:security_issue_2) { create(:issue, :confidential, project: project, assignee: assignee, milestone: milestone) }
+ let!(:closed_issue_1) { create(:issue, :closed, project: project, milestone: milestone) }
+ let!(:closed_issue_2) { create(:issue, :closed, project: project, milestone: milestone) }
+ let!(:closed_security_issue_1) { create(:issue, :confidential, :closed, project: project, author: author, milestone: milestone) }
+ let!(:closed_security_issue_2) { create(:issue, :confidential, :closed, project: project, assignee: assignee, milestone: milestone) }
+ let!(:closed_security_issue_3) { create(:issue, :confidential, :closed, project: project, author: author, milestone: milestone) }
+ let!(:closed_security_issue_4) { create(:issue, :confidential, :closed, project: project, assignee: assignee, milestone: milestone) }
+ let!(:merge_request) { create(:merge_request, source_project: project, target_project: project, milestone: milestone) }
+
+ before do
+ project.team << [member, :developer]
+ end
+
+ describe '#closed_items_count' do
+ it 'should not count confidential issues for non project members' do
+ expect(milestone.closed_items_count(non_member)).to eq 2
+ end
+
+ it 'should count confidential issues for author' do
+ expect(milestone.closed_items_count(author)).to eq 4
+ end
+
+ it 'should count confidential issues for assignee' do
+ expect(milestone.closed_items_count(assignee)).to eq 4
+ end
+
+ it 'should count confidential issues for project members' do
+ expect(milestone.closed_items_count(member)).to eq 6
+ end
+
+ it 'should count all issues for admin' do
+ expect(milestone.closed_items_count(admin)).to eq 6
+ end
+ end
+
+ describe '#total_items_count' do
+ it 'should not count confidential issues for non project members' do
+ expect(milestone.total_items_count(non_member)).to eq 4
+ end
+
+ it 'should count confidential issues for author' do
+ expect(milestone.total_items_count(author)).to eq 7
+ end
+
+ it 'should count confidential issues for assignee' do
+ expect(milestone.total_items_count(assignee)).to eq 7
+ end
+
+ it 'should count confidential issues for project members' do
+ expect(milestone.total_items_count(member)).to eq 10
+ end
+
+ it 'should count all issues for admin' do
+ expect(milestone.total_items_count(admin)).to eq 10
+ end
+ end
+
+ describe '#complete?' do
+ it 'returns false when has items opened' do
+ expect(milestone.complete?(non_member)).to eq false
+ end
+
+ it 'returns true when all items are closed' do
+ issue.close
+ merge_request.close
+
+ expect(milestone.complete?(non_member)).to eq true
+ end
+ end
+
+ describe '#percent_complete' do
+ it 'should not count confidential issues for non project members' do
+ expect(milestone.percent_complete(non_member)).to eq 50
+ end
+
+ it 'should count confidential issues for author' do
+ expect(milestone.percent_complete(author)).to eq 57
+ end
+
+ it 'should count confidential issues for assignee' do
+ expect(milestone.percent_complete(assignee)).to eq 57
+ end
+
+ it 'should count confidential issues for project members' do
+ expect(milestone.percent_complete(member)).to eq 60
+ end
+
+ it 'should count confidential issues for admin' do
+ expect(milestone.percent_complete(admin)).to eq 60
+ end
+ end
+end
diff --git a/spec/models/event_spec.rb b/spec/models/event_spec.rb
index ec2a923f91b..5fe44246738 100644
--- a/spec/models/event_spec.rb
+++ b/spec/models/event_spec.rb
@@ -65,6 +65,42 @@ describe Event, models: true do
it { expect(@event.author).to eq(@user) }
end
+ describe '#proper?' do
+ context 'issue event' do
+ let(:project) { create(:empty_project, :public) }
+ let(:non_member) { create(:user) }
+ let(:member) { create(:user) }
+ let(:author) { create(:author) }
+ let(:assignee) { create(:user) }
+ let(:admin) { create(:admin) }
+ let(:event) { Event.new(project: project, action: Event::CREATED, target: issue, author_id: author.id) }
+
+ before do
+ project.team << [member, :developer]
+ end
+
+ context 'for non confidential issues' do
+ let(:issue) { create(:issue, project: project, author: author, assignee: assignee) }
+
+ it { expect(event.proper?(non_member)).to eq true }
+ it { expect(event.proper?(author)).to eq true }
+ it { expect(event.proper?(assignee)).to eq true }
+ it { expect(event.proper?(member)).to eq true }
+ it { expect(event.proper?(admin)).to eq true }
+ end
+
+ context 'for confidential issues' do
+ let(:issue) { create(:issue, :confidential, project: project, author: author, assignee: assignee) }
+
+ it { expect(event.proper?(non_member)).to eq false }
+ it { expect(event.proper?(author)).to eq true }
+ it { expect(event.proper?(assignee)).to eq true }
+ it { expect(event.proper?(member)).to eq true }
+ it { expect(event.proper?(admin)).to eq true }
+ end
+ end
+ end
+
describe '.limit_recent' do
let!(:event1) { create(:closed_issue_event) }
let!(:event2) { create(:closed_issue_event) }
diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb
index 8bf68013fd2..2165cfb7a32 100644
--- a/spec/models/merge_request_spec.rb
+++ b/spec/models/merge_request_spec.rb
@@ -86,6 +86,41 @@ describe MergeRequest, models: true do
end
end
+ describe '#target_sha' do
+ context 'when the target branch does not exist anymore' do
+ subject { create(:merge_request).tap { |mr| mr.update_attribute(:target_branch, 'deleted') } }
+
+ it 'returns nil' do
+ expect(subject.target_sha).to be_nil
+ end
+ end
+ end
+
+ describe '#source_sha' do
+ let(:last_branch_commit) { subject.source_project.repository.commit(subject.source_branch) }
+
+ context 'with diffs' do
+ subject { create(:merge_request, :with_diffs) }
+ it 'returns the sha of the source branch last commit' do
+ expect(subject.source_sha).to eq(last_branch_commit.sha)
+ end
+ end
+
+ context 'without diffs' do
+ subject { create(:merge_request, :without_diffs) }
+ it 'returns the sha of the source branch last commit' do
+ expect(subject.source_sha).to eq(last_branch_commit.sha)
+ end
+ end
+
+ context 'when the merge request is being created' do
+ subject { build(:merge_request, source_branch: nil, compare_commits: []) }
+ it 'returns nil' do
+ expect(subject.source_sha).to be_nil
+ end
+ end
+ end
+
describe '#to_reference' do
it 'returns a String reference to the object' do
expect(subject.to_reference).to eq "!#{subject.iid}"
@@ -150,6 +185,7 @@ describe MergeRequest, models: true do
let(:commit2) { double('commit2', safe_message: "Fixes #{issue1.to_reference}") }
before do
+ subject.project.team << [subject.author, :developer]
allow(subject).to receive(:commits).and_return([commit0, commit1, commit2])
end
@@ -284,6 +320,18 @@ describe MergeRequest, models: true do
let(:project) { create(:project) }
let(:fork_project) { create(:project, forked_from_project: project) }
+ context 'when the target branch does not exist anymore' do
+ subject { create(:merge_request).tap { |mr| mr.update_attribute(:target_branch, 'deleted') } }
+
+ it 'does not crash' do
+ expect{ subject.diverged_commits_count }.not_to raise_error
+ end
+
+ it 'returns 0' do
+ expect(subject.diverged_commits_count).to eq(0)
+ end
+ end
+
context 'diverged on same repository' do
subject(:merge_request_with_divergence) { create(:merge_request, :diverged, source_project: project, target_project: project) }
diff --git a/spec/models/milestone_spec.rb b/spec/models/milestone_spec.rb
index de1757bf67a..72a4ea70228 100644
--- a/spec/models/milestone_spec.rb
+++ b/spec/models/milestone_spec.rb
@@ -32,6 +32,7 @@ describe Milestone, models: true do
let(:milestone) { create(:milestone) }
let(:issue) { create(:issue) }
+ let(:user) { create(:user) }
describe "unique milestone title per project" do
it "shouldn't accept the same title in a project twice" do
@@ -50,18 +51,17 @@ describe Milestone, models: true do
describe "#percent_complete" do
it "should not count open issues" do
milestone.issues << issue
- expect(milestone.percent_complete).to eq(0)
+ expect(milestone.percent_complete(user)).to eq(0)
end
it "should count closed issues" do
issue.close
milestone.issues << issue
- expect(milestone.percent_complete).to eq(100)
+ expect(milestone.percent_complete(user)).to eq(100)
end
it "should recover from dividing by zero" do
- expect(milestone.issues).to receive(:size).and_return(0)
- expect(milestone.percent_complete).to eq(0)
+ expect(milestone.percent_complete(user)).to eq(0)
end
end
@@ -103,7 +103,7 @@ describe Milestone, models: true do
)
end
- it { expect(milestone.percent_complete).to eq(75) }
+ it { expect(milestone.percent_complete(user)).to eq(75) }
end
describe :items_count do
@@ -113,23 +113,23 @@ describe Milestone, models: true do
milestone.merge_requests << create(:merge_request)
end
- it { expect(milestone.closed_items_count).to eq(1) }
- it { expect(milestone.total_items_count).to eq(3) }
- it { expect(milestone.is_empty?).to be_falsey }
+ it { expect(milestone.closed_items_count(user)).to eq(1) }
+ it { expect(milestone.total_items_count(user)).to eq(3) }
+ it { expect(milestone.is_empty?(user)).to be_falsey }
end
describe :can_be_closed? do
it { expect(milestone.can_be_closed?).to be_truthy }
end
- describe :is_empty? do
+ describe :total_items_count do
before do
create :closed_issue, milestone: milestone
create :merge_request, milestone: milestone
end
it 'Should return total count of issues and merge requests assigned to milestone' do
- expect(milestone.total_items_count).to eq 2
+ expect(milestone.total_items_count(user)).to eq 2
end
end
diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb
index fc2ab2d9931..a57229a4fdf 100644
--- a/spec/models/repository_spec.rb
+++ b/spec/models/repository_spec.rb
@@ -597,9 +597,9 @@ describe Repository, models: true do
describe '#after_push_commit' do
it 'flushes the cache' do
- expect(repository).to receive(:expire_cache).with('master')
+ expect(repository).to receive(:expire_cache).with('master', '123')
- repository.after_push_commit('master')
+ repository.after_push_commit('master', '123')
end
end
@@ -703,4 +703,111 @@ describe Repository, models: true do
repository.rm_tag('8.5')
end
end
+
+ describe '#avatar' do
+ it 'returns the first avatar file found in the repository' do
+ expect(repository).to receive(:blob_at_branch).
+ with('master', 'logo.png').
+ and_return(true)
+
+ expect(repository.avatar).to eq('logo.png')
+ end
+
+ it 'caches the output' do
+ allow(repository).to receive(:blob_at_branch).
+ with('master', 'logo.png').
+ and_return(true)
+
+ expect(repository.avatar).to eq('logo.png')
+
+ expect(repository).to_not receive(:blob_at_branch)
+ expect(repository.avatar).to eq('logo.png')
+ end
+ end
+
+ describe '#expire_avatar_cache' do
+ let(:cache) { repository.send(:cache) }
+
+ before do
+ allow(repository).to receive(:cache).and_return(cache)
+ end
+
+ context 'without a branch or revision' do
+ it 'flushes the cache' do
+ expect(cache).to receive(:expire).with(:avatar)
+
+ repository.expire_avatar_cache
+ end
+ end
+
+ context 'with a branch' do
+ it 'does not flush the cache if the branch is not the default branch' do
+ expect(cache).not_to receive(:expire)
+
+ repository.expire_avatar_cache('cats')
+ end
+
+ it 'flushes the cache if the branch equals the default branch' do
+ expect(cache).to receive(:expire).with(:avatar)
+
+ repository.expire_avatar_cache(repository.root_ref)
+ end
+ end
+
+ context 'with a branch and revision' do
+ let(:commit) { double(:commit) }
+
+ before do
+ allow(repository).to receive(:commit).and_return(commit)
+ end
+
+ it 'does not flush the cache if the commit does not change any logos' do
+ diff = double(:diff, new_path: 'test.txt')
+
+ expect(commit).to receive(:diffs).and_return([diff])
+ expect(cache).not_to receive(:expire)
+
+ repository.expire_avatar_cache(repository.root_ref, '123')
+ end
+
+ it 'flushes the cache if the commit changes any of the logos' do
+ diff = double(:diff, new_path: Repository::AVATAR_FILES[0])
+
+ expect(commit).to receive(:diffs).and_return([diff])
+ expect(cache).to receive(:expire).with(:avatar)
+
+ repository.expire_avatar_cache(repository.root_ref, '123')
+ end
+ end
+ end
+
+ describe '#build_cache' do
+ let(:cache) { repository.send(:cache) }
+
+ it 'builds the caches if they do not already exist' do
+ expect(cache).to receive(:exist?).
+ exactly(repository.cache_keys.length).
+ times.
+ and_return(false)
+
+ repository.cache_keys.each do |key|
+ expect(repository).to receive(key)
+ end
+
+ repository.build_cache
+ end
+
+ it 'does not build any caches that already exist' do
+ expect(cache).to receive(:exist?).
+ exactly(repository.cache_keys.length).
+ times.
+ and_return(true)
+
+ repository.cache_keys.each do |key|
+ expect(repository).to_not receive(key)
+ end
+
+ repository.build_cache
+ end
+ end
end
diff --git a/spec/models/todo_spec.rb b/spec/models/todo_spec.rb
index fe9ea7e7d1e..d9b86b9368f 100644
--- a/spec/models/todo_spec.rb
+++ b/spec/models/todo_spec.rb
@@ -5,19 +5,24 @@
# id :integer not null, primary key
# user_id :integer not null
# project_id :integer not null
-# target_id :integer not null
+# target_id :integer
# target_type :string not null
# author_id :integer
-# note_id :integer
# action :integer not null
# state :string not null
# created_at :datetime
# updated_at :datetime
+# note_id :integer
+# commit_id :string
#
require 'spec_helper'
describe Todo, models: true do
+ let(:project) { create(:project) }
+ let(:commit) { project.commit }
+ let(:issue) { create(:issue) }
+
describe 'relationships' do
it { is_expected.to belong_to(:author).class_name("User") }
it { is_expected.to belong_to(:note) }
@@ -33,8 +38,22 @@ describe Todo, models: true do
describe 'validations' do
it { is_expected.to validate_presence_of(:action) }
- it { is_expected.to validate_presence_of(:target) }
+ it { is_expected.to validate_presence_of(:target_type) }
it { is_expected.to validate_presence_of(:user) }
+
+ context 'for commits' do
+ subject { described_class.new(target_type: 'Commit') }
+
+ it { is_expected.to validate_presence_of(:commit_id) }
+ it { is_expected.not_to validate_presence_of(:target_id) }
+ end
+
+ context 'for issuables' do
+ subject { described_class.new(target: issue) }
+
+ it { is_expected.to validate_presence_of(:target_id) }
+ it { is_expected.not_to validate_presence_of(:commit_id) }
+ end
end
describe '#body' do
@@ -55,15 +74,69 @@ describe Todo, models: true do
end
end
- describe '#done!' do
+ describe '#done' do
it 'changes state to done' do
todo = create(:todo, state: :pending)
- expect { todo.done! }.to change(todo, :state).from('pending').to('done')
+ expect { todo.done }.to change(todo, :state).from('pending').to('done')
end
it 'does not raise error when is already done' do
todo = create(:todo, state: :done)
- expect { todo.done! }.not_to raise_error
+ expect { todo.done }.not_to raise_error
+ end
+ end
+
+ describe '#for_commit?' do
+ it 'returns true when target is a commit' do
+ subject.target_type = 'Commit'
+ expect(subject.for_commit?).to eq true
+ end
+
+ it 'returns false when target is an issuable' do
+ subject.target_type = 'Issue'
+ expect(subject.for_commit?).to eq false
+ end
+ end
+
+ describe '#target' do
+ context 'for commits' do
+ it 'returns an instance of Commit when exists' do
+ subject.project = project
+ subject.target_type = 'Commit'
+ subject.commit_id = commit.id
+
+ expect(subject.target).to be_a(Commit)
+ expect(subject.target).to eq commit
+ end
+
+ it 'returns nil when does not exists' do
+ subject.project = project
+ subject.target_type = 'Commit'
+ subject.commit_id = 'xxxx'
+
+ expect(subject.target).to be_nil
+ end
+ end
+
+ it 'returns the issuable for issuables' do
+ subject.target_id = issue.id
+ subject.target_type = issue.class.name
+ expect(subject.target).to eq issue
+ end
+ end
+
+ describe '#target_reference' do
+ it 'returns the short commit id for commits' do
+ subject.project = project
+ subject.target_type = 'Commit'
+ subject.commit_id = commit.id
+
+ expect(subject.target_reference).to eq commit.short_id
+ end
+
+ it 'returns reference for issuables' do
+ subject.target = issue
+ expect(subject.target_reference).to eq issue.to_reference
end
end
end