summaryrefslogtreecommitdiff
path: root/spec/models
diff options
context:
space:
mode:
authorTimothy Andrew <mail@timothyandrew.net>2016-06-09 14:40:14 +0530
committerTimothy Andrew <mail@timothyandrew.net>2016-06-09 14:40:14 +0530
commit1779d68bfe2872c36f475798c5e1b82678f3225d (patch)
tree8be5c6e486c1aa769ad95160219fe7f47ab1a57d /spec/models
parent1f5ecf916ee7b1d34fbf8775890b2aada2055384 (diff)
parent3d72cb897efddc14021afe8b064aa2bff14c7c15 (diff)
downloadgitlab-ce-1779d68bfe2872c36f475798c5e1b82678f3225d.tar.gz
Merge remote-tracking branch 'origin/master' into 2979-personal-access-tokens
Diffstat (limited to 'spec/models')
-rw-r--r--spec/models/award_emoji_spec.rb30
-rw-r--r--spec/models/build_spec.rb54
-rw-r--r--spec/models/ci/commit_spec.rb403
-rw-r--r--spec/models/ci/pipeline_spec.rb403
-rw-r--r--spec/models/commit_status_spec.rb50
-rw-r--r--spec/models/concerns/awardable_spec.rb48
-rw-r--r--spec/models/concerns/issuable_spec.rb34
-rw-r--r--spec/models/generic_commit_status_spec.rb4
-rw-r--r--spec/models/merge_request_spec.rb14
-rw-r--r--spec/models/note_spec.rb55
-rw-r--r--spec/models/project_spec.rb18
-rw-r--r--spec/models/user_spec.rb149
12 files changed, 738 insertions, 524 deletions
diff --git a/spec/models/award_emoji_spec.rb b/spec/models/award_emoji_spec.rb
new file mode 100644
index 00000000000..cb3c592f8cd
--- /dev/null
+++ b/spec/models/award_emoji_spec.rb
@@ -0,0 +1,30 @@
+require 'spec_helper'
+
+describe AwardEmoji, models: true do
+ describe 'Associations' do
+ it { is_expected.to belong_to(:awardable) }
+ it { is_expected.to belong_to(:user) }
+ end
+
+ describe 'modules' do
+ it { is_expected.to include_module(Participable) }
+ end
+
+ describe "validations" do
+ it { is_expected.to validate_presence_of(:awardable) }
+ it { is_expected.to validate_presence_of(:user) }
+ it { is_expected.to validate_presence_of(:name) }
+
+ # To circumvent a bug in the shoulda matchers
+ describe "scoped uniqueness validation" do
+ it "rejects duplicate award emoji" do
+ user = create(:user)
+ issue = create(:issue)
+ create(:award_emoji, user: user, awardable: issue)
+ new_award = build(:award_emoji, user: user, awardable: issue)
+
+ expect(new_award).not_to be_valid
+ end
+ end
+ end
+end
diff --git a/spec/models/build_spec.rb b/spec/models/build_spec.rb
index 5c6c30c20ea..7660ea2659c 100644
--- a/spec/models/build_spec.rb
+++ b/spec/models/build_spec.rb
@@ -2,16 +2,16 @@ require 'spec_helper'
describe Ci::Build, models: true do
let(:project) { create(:project) }
- let(:commit) { create(:ci_commit, project: project) }
- let(:build) { create(:ci_build, commit: commit) }
+ let(:pipeline) { create(:ci_pipeline, project: project) }
+ let(:build) { create(:ci_build, pipeline: pipeline) }
it { is_expected.to validate_presence_of :ref }
it { is_expected.to respond_to :trace_html }
describe '#first_pending' do
- let!(:first) { create(:ci_build, commit: commit, status: 'pending', created_at: Date.yesterday) }
- let!(:second) { create(:ci_build, commit: commit, status: 'pending') }
+ let!(:first) { create(:ci_build, pipeline: pipeline, status: 'pending', created_at: Date.yesterday) }
+ let!(:second) { create(:ci_build, pipeline: pipeline, status: 'pending') }
subject { Ci::Build.first_pending }
it { is_expected.to be_a(Ci::Build) }
@@ -97,7 +97,7 @@ describe Ci::Build, models: true do
# describe :timeout do
# subject { build.timeout }
#
- # it { is_expected.to eq(commit.project.timeout) }
+ # it { is_expected.to eq(pipeline.project.timeout) }
# end
describe '#options' do
@@ -124,13 +124,13 @@ describe Ci::Build, models: true do
describe '#project' do
subject { build.project }
- it { is_expected.to eq(commit.project) }
+ it { is_expected.to eq(pipeline.project) }
end
describe '#project_id' do
subject { build.project_id }
- it { is_expected.to eq(commit.project_id) }
+ it { is_expected.to eq(pipeline.project_id) }
end
describe '#project_name' do
@@ -219,7 +219,7 @@ describe Ci::Build, models: true do
context 'and trigger variables' do
let(:trigger) { create(:ci_trigger, project: project) }
- let(:trigger_request) { create(:ci_trigger_request_with_variables, commit: commit, trigger: trigger) }
+ let(:trigger_request) { create(:ci_trigger_request_with_variables, commit: pipeline, trigger: trigger) }
let(:trigger_variables) do
[
{ key: :TRIGGER_KEY, value: 'TRIGGER_VALUE', public: false }
@@ -428,10 +428,10 @@ describe Ci::Build, models: true do
end
describe '#depends_on_builds' do
- let!(:build) { create(:ci_build, commit: commit, name: 'build', stage_idx: 0, stage: 'build') }
- let!(:rspec_test) { create(:ci_build, commit: commit, name: 'rspec', stage_idx: 1, stage: 'test') }
- let!(:rubocop_test) { create(:ci_build, commit: commit, name: 'rubocop', stage_idx: 1, stage: 'test') }
- let!(:staging) { create(:ci_build, commit: commit, name: 'staging', stage_idx: 2, stage: 'deploy') }
+ let!(:build) { create(:ci_build, pipeline: pipeline, name: 'build', stage_idx: 0, stage: 'build') }
+ let!(:rspec_test) { create(:ci_build, pipeline: pipeline, name: 'rspec', stage_idx: 1, stage: 'test') }
+ let!(:rubocop_test) { create(:ci_build, pipeline: pipeline, name: 'rubocop', stage_idx: 1, stage: 'test') }
+ let!(:staging) { create(:ci_build, pipeline: pipeline, name: 'staging', stage_idx: 2, stage: 'deploy') }
it 'to have no dependents if this is first build' do
expect(build.depends_on_builds).to be_empty
@@ -451,19 +451,19 @@ describe Ci::Build, models: true do
end
end
- def create_mr(build, commit, factory: :merge_request, created_at: Time.now)
- create(factory, source_project_id: commit.gl_project_id,
- target_project_id: commit.gl_project_id,
+ def create_mr(build, pipeline, factory: :merge_request, created_at: Time.now)
+ create(factory, source_project_id: pipeline.gl_project_id,
+ target_project_id: pipeline.gl_project_id,
source_branch: build.ref,
created_at: created_at)
end
describe '#merge_request' do
- context 'when a MR has a reference to the commit' do
+ context 'when a MR has a reference to the pipeline' do
before do
- @merge_request = create_mr(build, commit, factory: :merge_request)
+ @merge_request = create_mr(build, pipeline, factory: :merge_request)
- commits = [double(id: commit.sha)]
+ commits = [double(id: pipeline.sha)]
allow(@merge_request).to receive(:commits).and_return(commits)
allow(MergeRequest).to receive_message_chain(:includes, :where, :reorder).and_return([@merge_request])
end
@@ -473,19 +473,19 @@ describe Ci::Build, models: true do
end
end
- context 'when there is not a MR referencing the commit' do
+ context 'when there is not a MR referencing the pipeline' do
it 'returns nil' do
expect(build.merge_request).to be_nil
end
end
- context 'when more than one MR have a reference to the commit' do
+ context 'when more than one MR have a reference to the pipeline' do
before do
- @merge_request = create_mr(build, commit, factory: :merge_request)
+ @merge_request = create_mr(build, pipeline, factory: :merge_request)
@merge_request.close!
- @merge_request2 = create_mr(build, commit, factory: :merge_request)
+ @merge_request2 = create_mr(build, pipeline, factory: :merge_request)
- commits = [double(id: commit.sha)]
+ commits = [double(id: pipeline.sha)]
allow(@merge_request).to receive(:commits).and_return(commits)
allow(@merge_request2).to receive(:commits).and_return(commits)
allow(MergeRequest).to receive_message_chain(:includes, :where, :reorder).and_return([@merge_request, @merge_request2])
@@ -498,11 +498,11 @@ describe Ci::Build, models: true do
context 'when a Build is created after the MR' do
before do
- @merge_request = create_mr(build, commit, factory: :merge_request_with_diffs)
- commit2 = create(:ci_commit, project: project)
- @build2 = create(:ci_build, commit: commit2)
+ @merge_request = create_mr(build, pipeline, factory: :merge_request_with_diffs)
+ pipeline2 = create(:ci_pipeline, project: project)
+ @build2 = create(:ci_build, pipeline: pipeline2)
- commits = [double(id: commit.sha), double(id: commit2.sha)]
+ commits = [double(id: pipeline.sha), double(id: pipeline2.sha)]
allow(@merge_request).to receive(:commits).and_return(commits)
allow(MergeRequest).to receive_message_chain(:includes, :where, :reorder).and_return([@merge_request])
end
diff --git a/spec/models/ci/commit_spec.rb b/spec/models/ci/commit_spec.rb
deleted file mode 100644
index 22f8639e5ab..00000000000
--- a/spec/models/ci/commit_spec.rb
+++ /dev/null
@@ -1,403 +0,0 @@
-require 'spec_helper'
-
-describe Ci::Commit, models: true do
- let(:project) { FactoryGirl.create :empty_project }
- let(:commit) { FactoryGirl.create :ci_commit, project: project }
-
- it { is_expected.to belong_to(:project) }
- it { is_expected.to have_many(:statuses) }
- it { is_expected.to have_many(:trigger_requests) }
- it { is_expected.to have_many(:builds) }
- it { is_expected.to validate_presence_of :sha }
- it { is_expected.to validate_presence_of :status }
-
- it { is_expected.to respond_to :git_author_name }
- it { is_expected.to respond_to :git_author_email }
- it { is_expected.to respond_to :short_sha }
-
- describe :valid_commit_sha do
- context 'commit.sha can not start with 00000000' do
- before do
- commit.sha = '0' * 40
- commit.valid_commit_sha
- end
-
- it('commit errors should not be empty') { expect(commit.errors).not_to be_empty }
- end
- end
-
- describe :short_sha do
- subject { commit.short_sha }
-
- it 'has 8 items' do
- expect(subject.size).to eq(8)
- end
- it { expect(commit.sha).to start_with(subject) }
- end
-
- describe :create_next_builds do
- end
-
- describe :retried do
- subject { commit.retried }
-
- before do
- @commit1 = FactoryGirl.create :ci_build, commit: commit, name: 'deploy'
- @commit2 = FactoryGirl.create :ci_build, commit: commit, name: 'deploy'
- end
-
- it 'returns old builds' do
- is_expected.to contain_exactly(@commit1)
- end
- end
-
- describe :create_builds do
- let!(:commit) { FactoryGirl.create :ci_commit, project: project, ref: 'master', tag: false }
-
- def create_builds(trigger_request = nil)
- commit.create_builds(nil, trigger_request)
- end
-
- def create_next_builds
- commit.create_next_builds(commit.builds.order(:id).last)
- end
-
- it 'creates builds' do
- expect(create_builds).to be_truthy
- commit.builds.update_all(status: "success")
- expect(commit.builds.count(:all)).to eq(2)
-
- expect(create_next_builds).to be_truthy
- commit.builds.update_all(status: "success")
- expect(commit.builds.count(:all)).to eq(4)
-
- expect(create_next_builds).to be_truthy
- commit.builds.update_all(status: "success")
- expect(commit.builds.count(:all)).to eq(5)
-
- expect(create_next_builds).to be_falsey
- end
-
- context 'custom stage with first job allowed to fail' do
- let(:yaml) do
- {
- stages: ['clean', 'test'],
- clean_job: {
- stage: 'clean',
- allow_failure: true,
- script: 'BUILD',
- },
- test_job: {
- stage: 'test',
- script: 'TEST',
- },
- }
- end
-
- before do
- stub_ci_commit_yaml_file(YAML.dump(yaml))
- create_builds
- end
-
- it 'properly schedules builds' do
- expect(commit.builds.pluck(:status)).to contain_exactly('pending')
- commit.builds.running_or_pending.each(&:drop)
- expect(commit.builds.pluck(:status)).to contain_exactly('pending', 'failed')
- end
- end
-
- context 'properly creates builds when "when" is defined' do
- let(:yaml) do
- {
- stages: ["build", "test", "test_failure", "deploy", "cleanup"],
- build: {
- stage: "build",
- script: "BUILD",
- },
- test: {
- stage: "test",
- script: "TEST",
- },
- test_failure: {
- stage: "test_failure",
- script: "ON test failure",
- when: "on_failure",
- },
- deploy: {
- stage: "deploy",
- script: "PUBLISH",
- },
- cleanup: {
- stage: "cleanup",
- script: "TIDY UP",
- when: "always",
- }
- }
- end
-
- before do
- stub_ci_commit_yaml_file(YAML.dump(yaml))
- end
-
- context 'when builds are successful' do
- it 'properly creates builds' do
- expect(create_builds).to be_truthy
- expect(commit.builds.pluck(:name)).to contain_exactly('build')
- expect(commit.builds.pluck(:status)).to contain_exactly('pending')
- commit.builds.running_or_pending.each(&:success)
-
- expect(commit.builds.pluck(:name)).to contain_exactly('build', 'test')
- expect(commit.builds.pluck(:status)).to contain_exactly('success', 'pending')
- commit.builds.running_or_pending.each(&:success)
-
- expect(commit.builds.pluck(:name)).to contain_exactly('build', 'test', 'deploy')
- expect(commit.builds.pluck(:status)).to contain_exactly('success', 'success', 'pending')
- commit.builds.running_or_pending.each(&:success)
-
- expect(commit.builds.pluck(:name)).to contain_exactly('build', 'test', 'deploy', 'cleanup')
- expect(commit.builds.pluck(:status)).to contain_exactly('success', 'success', 'success', 'pending')
- commit.builds.running_or_pending.each(&:success)
-
- expect(commit.builds.pluck(:status)).to contain_exactly('success', 'success', 'success', 'success')
- commit.reload
- expect(commit.status).to eq('success')
- end
- end
-
- context 'when test job fails' do
- it 'properly creates builds' do
- expect(create_builds).to be_truthy
- expect(commit.builds.pluck(:name)).to contain_exactly('build')
- expect(commit.builds.pluck(:status)).to contain_exactly('pending')
- commit.builds.running_or_pending.each(&:success)
-
- expect(commit.builds.pluck(:name)).to contain_exactly('build', 'test')
- expect(commit.builds.pluck(:status)).to contain_exactly('success', 'pending')
- commit.builds.running_or_pending.each(&:drop)
-
- expect(commit.builds.pluck(:name)).to contain_exactly('build', 'test', 'test_failure')
- expect(commit.builds.pluck(:status)).to contain_exactly('success', 'failed', 'pending')
- commit.builds.running_or_pending.each(&:success)
-
- expect(commit.builds.pluck(:name)).to contain_exactly('build', 'test', 'test_failure', 'cleanup')
- expect(commit.builds.pluck(:status)).to contain_exactly('success', 'failed', 'success', 'pending')
- commit.builds.running_or_pending.each(&:success)
-
- expect(commit.builds.pluck(:status)).to contain_exactly('success', 'failed', 'success', 'success')
- commit.reload
- expect(commit.status).to eq('failed')
- end
- end
-
- context 'when test and test_failure jobs fail' do
- it 'properly creates builds' do
- expect(create_builds).to be_truthy
- expect(commit.builds.pluck(:name)).to contain_exactly('build')
- expect(commit.builds.pluck(:status)).to contain_exactly('pending')
- commit.builds.running_or_pending.each(&:success)
-
- expect(commit.builds.pluck(:name)).to contain_exactly('build', 'test')
- expect(commit.builds.pluck(:status)).to contain_exactly('success', 'pending')
- commit.builds.running_or_pending.each(&:drop)
-
- expect(commit.builds.pluck(:name)).to contain_exactly('build', 'test', 'test_failure')
- expect(commit.builds.pluck(:status)).to contain_exactly('success', 'failed', 'pending')
- commit.builds.running_or_pending.each(&:drop)
-
- expect(commit.builds.pluck(:name)).to contain_exactly('build', 'test', 'test_failure', 'cleanup')
- expect(commit.builds.pluck(:status)).to contain_exactly('success', 'failed', 'failed', 'pending')
- commit.builds.running_or_pending.each(&:success)
-
- expect(commit.builds.pluck(:name)).to contain_exactly('build', 'test', 'test_failure', 'cleanup')
- expect(commit.builds.pluck(:status)).to contain_exactly('success', 'failed', 'failed', 'success')
- commit.reload
- expect(commit.status).to eq('failed')
- end
- end
-
- context 'when deploy job fails' do
- it 'properly creates builds' do
- expect(create_builds).to be_truthy
- expect(commit.builds.pluck(:name)).to contain_exactly('build')
- expect(commit.builds.pluck(:status)).to contain_exactly('pending')
- commit.builds.running_or_pending.each(&:success)
-
- expect(commit.builds.pluck(:name)).to contain_exactly('build', 'test')
- expect(commit.builds.pluck(:status)).to contain_exactly('success', 'pending')
- commit.builds.running_or_pending.each(&:success)
-
- expect(commit.builds.pluck(:name)).to contain_exactly('build', 'test', 'deploy')
- expect(commit.builds.pluck(:status)).to contain_exactly('success', 'success', 'pending')
- commit.builds.running_or_pending.each(&:drop)
-
- expect(commit.builds.pluck(:name)).to contain_exactly('build', 'test', 'deploy', 'cleanup')
- expect(commit.builds.pluck(:status)).to contain_exactly('success', 'success', 'failed', 'pending')
- commit.builds.running_or_pending.each(&:success)
-
- expect(commit.builds.pluck(:status)).to contain_exactly('success', 'success', 'failed', 'success')
- commit.reload
- expect(commit.status).to eq('failed')
- end
- end
-
- context 'when build is canceled in the second stage' do
- it 'does not schedule builds after build has been canceled' do
- expect(create_builds).to be_truthy
- expect(commit.builds.pluck(:name)).to contain_exactly('build')
- expect(commit.builds.pluck(:status)).to contain_exactly('pending')
- commit.builds.running_or_pending.each(&:success)
-
- expect(commit.builds.running_or_pending).not_to be_empty
-
- expect(commit.builds.pluck(:name)).to contain_exactly('build', 'test')
- expect(commit.builds.pluck(:status)).to contain_exactly('success', 'pending')
- commit.builds.running_or_pending.each(&:cancel)
-
- expect(commit.builds.running_or_pending).to be_empty
- expect(commit.reload.status).to eq('canceled')
- end
- end
- end
- end
-
- describe "#finished_at" do
- let(:commit) { FactoryGirl.create :ci_commit }
-
- it "returns finished_at of latest build" do
- build = FactoryGirl.create :ci_build, commit: commit, finished_at: Time.now - 60
- FactoryGirl.create :ci_build, commit: commit, finished_at: Time.now - 120
-
- expect(commit.finished_at.to_i).to eq(build.finished_at.to_i)
- end
-
- it "returns nil if there is no finished build" do
- FactoryGirl.create :ci_not_started_build, commit: commit
-
- expect(commit.finished_at).to be_nil
- end
- end
-
- describe "coverage" do
- let(:project) { FactoryGirl.create :empty_project, build_coverage_regex: "/.*/" }
- let(:commit) { FactoryGirl.create :ci_commit, project: project }
-
- it "calculates average when there are two builds with coverage" do
- FactoryGirl.create :ci_build, name: "rspec", coverage: 30, commit: commit
- FactoryGirl.create :ci_build, name: "rubocop", coverage: 40, commit: commit
- expect(commit.coverage).to eq("35.00")
- end
-
- it "calculates average when there are two builds with coverage and one with nil" do
- FactoryGirl.create :ci_build, name: "rspec", coverage: 30, commit: commit
- FactoryGirl.create :ci_build, name: "rubocop", coverage: 40, commit: commit
- FactoryGirl.create :ci_build, commit: commit
- expect(commit.coverage).to eq("35.00")
- end
-
- it "calculates average when there are two builds with coverage and one is retried" do
- FactoryGirl.create :ci_build, name: "rspec", coverage: 30, commit: commit
- FactoryGirl.create :ci_build, name: "rubocop", coverage: 30, commit: commit
- FactoryGirl.create :ci_build, name: "rubocop", coverage: 40, commit: commit
- expect(commit.coverage).to eq("35.00")
- end
-
- it "calculates average when there is one build without coverage" do
- FactoryGirl.create :ci_build, commit: commit
- expect(commit.coverage).to be_nil
- end
- end
-
- describe '#retryable?' do
- subject { commit.retryable? }
-
- context 'no failed builds' do
- before do
- FactoryGirl.create :ci_build, name: "rspec", commit: commit, status: 'success'
- end
-
- it 'be not retryable' do
- is_expected.to be_falsey
- end
- end
-
- context 'with failed builds' do
- before do
- FactoryGirl.create :ci_build, name: "rspec", commit: commit, status: 'running'
- FactoryGirl.create :ci_build, name: "rubocop", commit: commit, status: 'failed'
- end
-
- it 'be retryable' do
- is_expected.to be_truthy
- end
- end
- end
-
- describe '#stages' do
- let(:commit2) { FactoryGirl.create :ci_commit, project: project }
- subject { CommitStatus.where(commit: [commit, commit2]).stages }
-
- before do
- FactoryGirl.create :ci_build, commit: commit2, stage: 'test', stage_idx: 1
- FactoryGirl.create :ci_build, commit: commit, stage: 'build', stage_idx: 0
- end
-
- it 'return all stages' do
- is_expected.to eq(%w(build test))
- end
- end
-
- describe '#update_state' do
- it 'execute update_state after touching object' do
- expect(commit).to receive(:update_state).and_return(true)
- commit.touch
- end
-
- context 'dependent objects' do
- let(:commit_status) { build :commit_status, commit: commit }
-
- it 'execute update_state after saving dependent object' do
- expect(commit).to receive(:update_state).and_return(true)
- commit_status.save
- end
- end
-
- context 'update state' do
- let(:current) { Time.now.change(usec: 0) }
- let(:build) { FactoryGirl.create :ci_build, :success, commit: commit, started_at: current - 120, finished_at: current - 60 }
-
- before do
- build
- end
-
- [:status, :started_at, :finished_at, :duration].each do |param|
- it "update #{param}" do
- expect(commit.send(param)).to eq(build.send(param))
- end
- end
- end
- end
-
- describe '#branch?' do
- subject { commit.branch? }
-
- context 'is not a tag' do
- before do
- commit.tag = false
- end
-
- it 'return true when tag is set to false' do
- is_expected.to be_truthy
- end
- end
-
- context 'is not a tag' do
- before do
- commit.tag = true
- end
-
- it 'return false when tag is set to true' do
- is_expected.to be_falsey
- end
- end
- end
-end
diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb
new file mode 100644
index 00000000000..0d769ed7324
--- /dev/null
+++ b/spec/models/ci/pipeline_spec.rb
@@ -0,0 +1,403 @@
+require 'spec_helper'
+
+describe Ci::Pipeline, models: true do
+ let(:project) { FactoryGirl.create :empty_project }
+ let(:pipeline) { FactoryGirl.create :ci_pipeline, project: project }
+
+ it { is_expected.to belong_to(:project) }
+ it { is_expected.to have_many(:statuses) }
+ it { is_expected.to have_many(:trigger_requests) }
+ it { is_expected.to have_many(:builds) }
+ it { is_expected.to validate_presence_of :sha }
+ it { is_expected.to validate_presence_of :status }
+
+ it { is_expected.to respond_to :git_author_name }
+ it { is_expected.to respond_to :git_author_email }
+ it { is_expected.to respond_to :short_sha }
+
+ describe :valid_commit_sha do
+ context 'commit.sha can not start with 00000000' do
+ before do
+ pipeline.sha = '0' * 40
+ pipeline.valid_commit_sha
+ end
+
+ it('commit errors should not be empty') { expect(pipeline.errors).not_to be_empty }
+ end
+ end
+
+ describe :short_sha do
+ subject { pipeline.short_sha }
+
+ it 'has 8 items' do
+ expect(subject.size).to eq(8)
+ end
+ it { expect(pipeline.sha).to start_with(subject) }
+ end
+
+ describe :create_next_builds do
+ end
+
+ describe :retried do
+ subject { pipeline.retried }
+
+ before do
+ @build1 = FactoryGirl.create :ci_build, pipeline: pipeline, name: 'deploy'
+ @build2 = FactoryGirl.create :ci_build, pipeline: pipeline, name: 'deploy'
+ end
+
+ it 'returns old builds' do
+ is_expected.to contain_exactly(@build1)
+ end
+ end
+
+ describe :create_builds do
+ let!(:pipeline) { FactoryGirl.create :ci_pipeline, project: project, ref: 'master', tag: false }
+
+ def create_builds(trigger_request = nil)
+ pipeline.create_builds(nil, trigger_request)
+ end
+
+ def create_next_builds
+ pipeline.create_next_builds(pipeline.builds.order(:id).last)
+ end
+
+ it 'creates builds' do
+ expect(create_builds).to be_truthy
+ pipeline.builds.update_all(status: "success")
+ expect(pipeline.builds.count(:all)).to eq(2)
+
+ expect(create_next_builds).to be_truthy
+ pipeline.builds.update_all(status: "success")
+ expect(pipeline.builds.count(:all)).to eq(4)
+
+ expect(create_next_builds).to be_truthy
+ pipeline.builds.update_all(status: "success")
+ expect(pipeline.builds.count(:all)).to eq(5)
+
+ expect(create_next_builds).to be_falsey
+ end
+
+ context 'custom stage with first job allowed to fail' do
+ let(:yaml) do
+ {
+ stages: ['clean', 'test'],
+ clean_job: {
+ stage: 'clean',
+ allow_failure: true,
+ script: 'BUILD',
+ },
+ test_job: {
+ stage: 'test',
+ script: 'TEST',
+ },
+ }
+ end
+
+ before do
+ stub_ci_pipeline_yaml_file(YAML.dump(yaml))
+ create_builds
+ end
+
+ it 'properly schedules builds' do
+ expect(pipeline.builds.pluck(:status)).to contain_exactly('pending')
+ pipeline.builds.running_or_pending.each(&:drop)
+ expect(pipeline.builds.pluck(:status)).to contain_exactly('pending', 'failed')
+ end
+ end
+
+ context 'properly creates builds when "when" is defined' do
+ let(:yaml) do
+ {
+ stages: ["build", "test", "test_failure", "deploy", "cleanup"],
+ build: {
+ stage: "build",
+ script: "BUILD",
+ },
+ test: {
+ stage: "test",
+ script: "TEST",
+ },
+ test_failure: {
+ stage: "test_failure",
+ script: "ON test failure",
+ when: "on_failure",
+ },
+ deploy: {
+ stage: "deploy",
+ script: "PUBLISH",
+ },
+ cleanup: {
+ stage: "cleanup",
+ script: "TIDY UP",
+ when: "always",
+ }
+ }
+ end
+
+ before do
+ stub_ci_pipeline_yaml_file(YAML.dump(yaml))
+ end
+
+ context 'when builds are successful' do
+ it 'properly creates builds' do
+ expect(create_builds).to be_truthy
+ expect(pipeline.builds.pluck(:name)).to contain_exactly('build')
+ expect(pipeline.builds.pluck(:status)).to contain_exactly('pending')
+ pipeline.builds.running_or_pending.each(&:success)
+
+ expect(pipeline.builds.pluck(:name)).to contain_exactly('build', 'test')
+ expect(pipeline.builds.pluck(:status)).to contain_exactly('success', 'pending')
+ pipeline.builds.running_or_pending.each(&:success)
+
+ expect(pipeline.builds.pluck(:name)).to contain_exactly('build', 'test', 'deploy')
+ expect(pipeline.builds.pluck(:status)).to contain_exactly('success', 'success', 'pending')
+ pipeline.builds.running_or_pending.each(&:success)
+
+ expect(pipeline.builds.pluck(:name)).to contain_exactly('build', 'test', 'deploy', 'cleanup')
+ expect(pipeline.builds.pluck(:status)).to contain_exactly('success', 'success', 'success', 'pending')
+ pipeline.builds.running_or_pending.each(&:success)
+
+ expect(pipeline.builds.pluck(:status)).to contain_exactly('success', 'success', 'success', 'success')
+ pipeline.reload
+ expect(pipeline.status).to eq('success')
+ end
+ end
+
+ context 'when test job fails' do
+ it 'properly creates builds' do
+ expect(create_builds).to be_truthy
+ expect(pipeline.builds.pluck(:name)).to contain_exactly('build')
+ expect(pipeline.builds.pluck(:status)).to contain_exactly('pending')
+ pipeline.builds.running_or_pending.each(&:success)
+
+ expect(pipeline.builds.pluck(:name)).to contain_exactly('build', 'test')
+ expect(pipeline.builds.pluck(:status)).to contain_exactly('success', 'pending')
+ pipeline.builds.running_or_pending.each(&:drop)
+
+ expect(pipeline.builds.pluck(:name)).to contain_exactly('build', 'test', 'test_failure')
+ expect(pipeline.builds.pluck(:status)).to contain_exactly('success', 'failed', 'pending')
+ pipeline.builds.running_or_pending.each(&:success)
+
+ expect(pipeline.builds.pluck(:name)).to contain_exactly('build', 'test', 'test_failure', 'cleanup')
+ expect(pipeline.builds.pluck(:status)).to contain_exactly('success', 'failed', 'success', 'pending')
+ pipeline.builds.running_or_pending.each(&:success)
+
+ expect(pipeline.builds.pluck(:status)).to contain_exactly('success', 'failed', 'success', 'success')
+ pipeline.reload
+ expect(pipeline.status).to eq('failed')
+ end
+ end
+
+ context 'when test and test_failure jobs fail' do
+ it 'properly creates builds' do
+ expect(create_builds).to be_truthy
+ expect(pipeline.builds.pluck(:name)).to contain_exactly('build')
+ expect(pipeline.builds.pluck(:status)).to contain_exactly('pending')
+ pipeline.builds.running_or_pending.each(&:success)
+
+ expect(pipeline.builds.pluck(:name)).to contain_exactly('build', 'test')
+ expect(pipeline.builds.pluck(:status)).to contain_exactly('success', 'pending')
+ pipeline.builds.running_or_pending.each(&:drop)
+
+ expect(pipeline.builds.pluck(:name)).to contain_exactly('build', 'test', 'test_failure')
+ expect(pipeline.builds.pluck(:status)).to contain_exactly('success', 'failed', 'pending')
+ pipeline.builds.running_or_pending.each(&:drop)
+
+ expect(pipeline.builds.pluck(:name)).to contain_exactly('build', 'test', 'test_failure', 'cleanup')
+ expect(pipeline.builds.pluck(:status)).to contain_exactly('success', 'failed', 'failed', 'pending')
+ pipeline.builds.running_or_pending.each(&:success)
+
+ expect(pipeline.builds.pluck(:name)).to contain_exactly('build', 'test', 'test_failure', 'cleanup')
+ expect(pipeline.builds.pluck(:status)).to contain_exactly('success', 'failed', 'failed', 'success')
+ pipeline.reload
+ expect(pipeline.status).to eq('failed')
+ end
+ end
+
+ context 'when deploy job fails' do
+ it 'properly creates builds' do
+ expect(create_builds).to be_truthy
+ expect(pipeline.builds.pluck(:name)).to contain_exactly('build')
+ expect(pipeline.builds.pluck(:status)).to contain_exactly('pending')
+ pipeline.builds.running_or_pending.each(&:success)
+
+ expect(pipeline.builds.pluck(:name)).to contain_exactly('build', 'test')
+ expect(pipeline.builds.pluck(:status)).to contain_exactly('success', 'pending')
+ pipeline.builds.running_or_pending.each(&:success)
+
+ expect(pipeline.builds.pluck(:name)).to contain_exactly('build', 'test', 'deploy')
+ expect(pipeline.builds.pluck(:status)).to contain_exactly('success', 'success', 'pending')
+ pipeline.builds.running_or_pending.each(&:drop)
+
+ expect(pipeline.builds.pluck(:name)).to contain_exactly('build', 'test', 'deploy', 'cleanup')
+ expect(pipeline.builds.pluck(:status)).to contain_exactly('success', 'success', 'failed', 'pending')
+ pipeline.builds.running_or_pending.each(&:success)
+
+ expect(pipeline.builds.pluck(:status)).to contain_exactly('success', 'success', 'failed', 'success')
+ pipeline.reload
+ expect(pipeline.status).to eq('failed')
+ end
+ end
+
+ context 'when build is canceled in the second stage' do
+ it 'does not schedule builds after build has been canceled' do
+ expect(create_builds).to be_truthy
+ expect(pipeline.builds.pluck(:name)).to contain_exactly('build')
+ expect(pipeline.builds.pluck(:status)).to contain_exactly('pending')
+ pipeline.builds.running_or_pending.each(&:success)
+
+ expect(pipeline.builds.running_or_pending).not_to be_empty
+
+ expect(pipeline.builds.pluck(:name)).to contain_exactly('build', 'test')
+ expect(pipeline.builds.pluck(:status)).to contain_exactly('success', 'pending')
+ pipeline.builds.running_or_pending.each(&:cancel)
+
+ expect(pipeline.builds.running_or_pending).to be_empty
+ expect(pipeline.reload.status).to eq('canceled')
+ end
+ end
+ end
+ end
+
+ describe "#finished_at" do
+ let(:pipeline) { FactoryGirl.create :ci_pipeline }
+
+ it "returns finished_at of latest build" do
+ build = FactoryGirl.create :ci_build, pipeline: pipeline, finished_at: Time.now - 60
+ FactoryGirl.create :ci_build, pipeline: pipeline, finished_at: Time.now - 120
+
+ expect(pipeline.finished_at.to_i).to eq(build.finished_at.to_i)
+ end
+
+ it "returns nil if there is no finished build" do
+ FactoryGirl.create :ci_not_started_build, pipeline: pipeline
+
+ expect(pipeline.finished_at).to be_nil
+ end
+ end
+
+ describe "coverage" do
+ let(:project) { FactoryGirl.create :empty_project, build_coverage_regex: "/.*/" }
+ let(:pipeline) { FactoryGirl.create :ci_pipeline, project: project }
+
+ it "calculates average when there are two builds with coverage" do
+ FactoryGirl.create :ci_build, name: "rspec", coverage: 30, pipeline: pipeline
+ FactoryGirl.create :ci_build, name: "rubocop", coverage: 40, pipeline: pipeline
+ expect(pipeline.coverage).to eq("35.00")
+ end
+
+ it "calculates average when there are two builds with coverage and one with nil" do
+ FactoryGirl.create :ci_build, name: "rspec", coverage: 30, pipeline: pipeline
+ FactoryGirl.create :ci_build, name: "rubocop", coverage: 40, pipeline: pipeline
+ FactoryGirl.create :ci_build, pipeline: pipeline
+ expect(pipeline.coverage).to eq("35.00")
+ end
+
+ it "calculates average when there are two builds with coverage and one is retried" do
+ FactoryGirl.create :ci_build, name: "rspec", coverage: 30, pipeline: pipeline
+ FactoryGirl.create :ci_build, name: "rubocop", coverage: 30, pipeline: pipeline
+ FactoryGirl.create :ci_build, name: "rubocop", coverage: 40, pipeline: pipeline
+ expect(pipeline.coverage).to eq("35.00")
+ end
+
+ it "calculates average when there is one build without coverage" do
+ FactoryGirl.create :ci_build, pipeline: pipeline
+ expect(pipeline.coverage).to be_nil
+ end
+ end
+
+ describe '#retryable?' do
+ subject { pipeline.retryable? }
+
+ context 'no failed builds' do
+ before do
+ FactoryGirl.create :ci_build, name: "rspec", pipeline: pipeline, status: 'success'
+ end
+
+ it 'be not retryable' do
+ is_expected.to be_falsey
+ end
+ end
+
+ context 'with failed builds' do
+ before do
+ FactoryGirl.create :ci_build, name: "rspec", pipeline: pipeline, status: 'running'
+ FactoryGirl.create :ci_build, name: "rubocop", pipeline: pipeline, status: 'failed'
+ end
+
+ it 'be retryable' do
+ is_expected.to be_truthy
+ end
+ end
+ end
+
+ describe '#stages' do
+ let(:pipeline2) { FactoryGirl.create :ci_pipeline, project: project }
+ subject { CommitStatus.where(pipeline: [pipeline, pipeline2]).stages }
+
+ before do
+ FactoryGirl.create :ci_build, pipeline: pipeline2, stage: 'test', stage_idx: 1
+ FactoryGirl.create :ci_build, pipeline: pipeline, stage: 'build', stage_idx: 0
+ end
+
+ it 'return all stages' do
+ is_expected.to eq(%w(build test))
+ end
+ end
+
+ describe '#update_state' do
+ it 'execute update_state after touching object' do
+ expect(pipeline).to receive(:update_state).and_return(true)
+ pipeline.touch
+ end
+
+ context 'dependent objects' do
+ let(:commit_status) { build :commit_status, pipeline: pipeline }
+
+ it 'execute update_state after saving dependent object' do
+ expect(pipeline).to receive(:update_state).and_return(true)
+ commit_status.save
+ end
+ end
+
+ context 'update state' do
+ let(:current) { Time.now.change(usec: 0) }
+ let(:build) { FactoryGirl.create :ci_build, :success, pipeline: pipeline, started_at: current - 120, finished_at: current - 60 }
+
+ before do
+ build
+ end
+
+ [:status, :started_at, :finished_at, :duration].each do |param|
+ it "update #{param}" do
+ expect(pipeline.send(param)).to eq(build.send(param))
+ end
+ end
+ end
+ end
+
+ describe '#branch?' do
+ subject { pipeline.branch? }
+
+ context 'is not a tag' do
+ before do
+ pipeline.tag = false
+ end
+
+ it 'return true when tag is set to false' do
+ is_expected.to be_truthy
+ end
+ end
+
+ context 'is not a tag' do
+ before do
+ pipeline.tag = true
+ end
+
+ it 'return false when tag is set to true' do
+ is_expected.to be_falsey
+ end
+ end
+ end
+end
diff --git a/spec/models/commit_status_spec.rb b/spec/models/commit_status_spec.rb
index 434e58cfd06..8fb605fff8a 100644
--- a/spec/models/commit_status_spec.rb
+++ b/spec/models/commit_status_spec.rb
@@ -1,18 +1,18 @@
require 'spec_helper'
describe CommitStatus, models: true do
- let(:commit) { FactoryGirl.create :ci_commit }
- let(:commit_status) { FactoryGirl.create :commit_status, commit: commit }
+ let(:pipeline) { FactoryGirl.create :ci_pipeline }
+ let(:commit_status) { FactoryGirl.create :commit_status, pipeline: pipeline }
- it { is_expected.to belong_to(:commit) }
+ it { is_expected.to belong_to(:pipeline) }
it { is_expected.to belong_to(:user) }
it { is_expected.to belong_to(:project) }
it { is_expected.to validate_presence_of(:name) }
it { is_expected.to validate_inclusion_of(:status).in_array(%w(pending running failed success canceled)) }
- it { is_expected.to delegate_method(:sha).to(:commit) }
- it { is_expected.to delegate_method(:short_sha).to(:commit) }
+ it { is_expected.to delegate_method(:sha).to(:pipeline) }
+ it { is_expected.to delegate_method(:short_sha).to(:pipeline) }
it { is_expected.to respond_to :success? }
it { is_expected.to respond_to :failed? }
@@ -121,11 +121,11 @@ describe CommitStatus, models: true do
subject { CommitStatus.latest.order(:id) }
before do
- @commit1 = FactoryGirl.create :commit_status, commit: commit, name: 'aa', ref: 'bb', status: 'running'
- @commit2 = FactoryGirl.create :commit_status, commit: commit, name: 'cc', ref: 'cc', status: 'pending'
- @commit3 = FactoryGirl.create :commit_status, commit: commit, name: 'aa', ref: 'cc', status: 'success'
- @commit4 = FactoryGirl.create :commit_status, commit: commit, name: 'cc', ref: 'bb', status: 'success'
- @commit5 = FactoryGirl.create :commit_status, commit: commit, name: 'aa', ref: 'bb', status: 'success'
+ @commit1 = FactoryGirl.create :commit_status, pipeline: pipeline, name: 'aa', ref: 'bb', status: 'running'
+ @commit2 = FactoryGirl.create :commit_status, pipeline: pipeline, name: 'cc', ref: 'cc', status: 'pending'
+ @commit3 = FactoryGirl.create :commit_status, pipeline: pipeline, name: 'aa', ref: 'cc', status: 'success'
+ @commit4 = FactoryGirl.create :commit_status, pipeline: pipeline, name: 'cc', ref: 'bb', status: 'success'
+ @commit5 = FactoryGirl.create :commit_status, pipeline: pipeline, name: 'aa', ref: 'bb', status: 'success'
end
it 'return unique statuses' do
@@ -137,11 +137,11 @@ describe CommitStatus, models: true do
subject { CommitStatus.running_or_pending.order(:id) }
before do
- @commit1 = FactoryGirl.create :commit_status, commit: commit, name: 'aa', ref: 'bb', status: 'running'
- @commit2 = FactoryGirl.create :commit_status, commit: commit, name: 'cc', ref: 'cc', status: 'pending'
- @commit3 = FactoryGirl.create :commit_status, commit: commit, name: 'aa', ref: nil, status: 'success'
- @commit4 = FactoryGirl.create :commit_status, commit: commit, name: 'dd', ref: nil, status: 'failed'
- @commit5 = FactoryGirl.create :commit_status, commit: commit, name: 'ee', ref: nil, status: 'canceled'
+ @commit1 = FactoryGirl.create :commit_status, pipeline: pipeline, name: 'aa', ref: 'bb', status: 'running'
+ @commit2 = FactoryGirl.create :commit_status, pipeline: pipeline, name: 'cc', ref: 'cc', status: 'pending'
+ @commit3 = FactoryGirl.create :commit_status, pipeline: pipeline, name: 'aa', ref: nil, status: 'success'
+ @commit4 = FactoryGirl.create :commit_status, pipeline: pipeline, name: 'dd', ref: nil, status: 'failed'
+ @commit5 = FactoryGirl.create :commit_status, pipeline: pipeline, name: 'ee', ref: nil, status: 'canceled'
end
it 'return statuses that are running or pending' do
@@ -152,17 +152,17 @@ describe CommitStatus, models: true do
describe '#before_sha' do
subject { commit_status.before_sha }
- context 'when no before_sha is set for ci::commit' do
- before { commit.before_sha = nil }
+ context 'when no before_sha is set for pipeline' do
+ before { pipeline.before_sha = nil }
it 'return blank sha' do
is_expected.to eq(Gitlab::Git::BLANK_SHA)
end
end
- context 'for before_sha set for ci::commit' do
+ context 'for before_sha set for pipeline' do
let(:value) { '1234' }
- before { commit.before_sha = value }
+ before { pipeline.before_sha = value }
it 'return the set value' do
is_expected.to eq(value)
@@ -172,14 +172,14 @@ describe CommitStatus, models: true do
describe '#stages' do
before do
- FactoryGirl.create :commit_status, commit: commit, stage: 'build', stage_idx: 0, status: 'success'
- FactoryGirl.create :commit_status, commit: commit, stage: 'build', stage_idx: 0, status: 'failed'
- FactoryGirl.create :commit_status, commit: commit, stage: 'deploy', stage_idx: 2, status: 'running'
- FactoryGirl.create :commit_status, commit: commit, stage: 'test', stage_idx: 1, status: 'success'
+ FactoryGirl.create :commit_status, pipeline: pipeline, stage: 'build', stage_idx: 0, status: 'success'
+ FactoryGirl.create :commit_status, pipeline: pipeline, stage: 'build', stage_idx: 0, status: 'failed'
+ FactoryGirl.create :commit_status, pipeline: pipeline, stage: 'deploy', stage_idx: 2, status: 'running'
+ FactoryGirl.create :commit_status, pipeline: pipeline, stage: 'test', stage_idx: 1, status: 'success'
end
context 'stages list' do
- subject { CommitStatus.where(commit: commit).stages }
+ subject { CommitStatus.where(pipeline: pipeline).stages }
it 'return ordered list of stages' do
is_expected.to eq(%w(build test deploy))
@@ -187,7 +187,7 @@ describe CommitStatus, models: true do
end
context 'stages with statuses' do
- subject { CommitStatus.where(commit: commit).stages_status }
+ subject { CommitStatus.where(pipeline: pipeline).stages_status }
it 'return list of stages with statuses' do
is_expected.to eq({
diff --git a/spec/models/concerns/awardable_spec.rb b/spec/models/concerns/awardable_spec.rb
new file mode 100644
index 00000000000..a371c4a18a9
--- /dev/null
+++ b/spec/models/concerns/awardable_spec.rb
@@ -0,0 +1,48 @@
+require 'spec_helper'
+
+describe Issue, "Awardable" do
+ let!(:issue) { create(:issue) }
+ let!(:award_emoji) { create(:award_emoji, :downvote, awardable: issue) }
+
+ describe "Associations" do
+ it { is_expected.to have_many(:award_emoji).dependent(:destroy) }
+ end
+
+ describe "ClassMethods" do
+ let!(:issue2) { create(:issue) }
+
+ before do
+ create(:award_emoji, awardable: issue2)
+ end
+
+ it "orders on upvotes" do
+ expect(Issue.order_upvotes_desc.to_a).to eq [issue2, issue]
+ end
+
+ it "orders on downvotes" do
+ expect(Issue.order_downvotes_desc.to_a).to eq [issue, issue2]
+ end
+ end
+
+ describe "#upvotes" do
+ it "counts the number of upvotes" do
+ expect(issue.upvotes).to be 0
+ end
+ end
+
+ describe "#downvotes" do
+ it "counts the number of downvotes" do
+ expect(issue.downvotes).to be 1
+ end
+ end
+
+ describe "#toggle_award_emoji" do
+ it "adds an emoji if it isn't awarded yet" do
+ expect { issue.toggle_award_emoji("thumbsup", award_emoji.user) }.to change { AwardEmoji.count }.by(1)
+ end
+
+ it "toggles already awarded emoji" do
+ expect { issue.toggle_award_emoji("thumbsdown", award_emoji.user) }.to change { AwardEmoji.count }.by(-1)
+ end
+ end
+end
diff --git a/spec/models/concerns/issuable_spec.rb b/spec/models/concerns/issuable_spec.rb
index e9f827e9f50..efbcbf72f76 100644
--- a/spec/models/concerns/issuable_spec.rb
+++ b/spec/models/concerns/issuable_spec.rb
@@ -10,6 +10,20 @@ describe Issue, "Issuable" do
it { is_expected.to belong_to(:assignee) }
it { is_expected.to have_many(:notes).dependent(:destroy) }
it { is_expected.to have_many(:todos).dependent(:destroy) }
+
+ context 'Notes' do
+ let!(:note) { create(:note, noteable: issue, project: issue.project) }
+ let(:scoped_issue) { Issue.includes(notes: :author).find(issue.id) }
+
+ it 'indicates if the notes have their authors loaded' do
+ expect(issue.notes).not_to be_authors_loaded
+ expect(scoped_issue.notes).to be_authors_loaded
+ end
+ end
+ end
+
+ describe 'Included modules' do
+ it { is_expected.to include_module(Awardable) }
end
describe "Validation" do
@@ -241,12 +255,28 @@ describe Issue, "Issuable" do
end
end
+ describe '#user_notes_count' do
+ let(:project) { create(:project) }
+ let(:issue1) { create(:issue, project: project) }
+ let(:issue2) { create(:issue, project: project) }
+
+ before do
+ create_list(:note, 3, noteable: issue1, project: project)
+ create_list(:note, 6, noteable: issue2, project: project)
+ end
+
+ it 'counts the user notes' do
+ expect(issue1.user_notes_count).to be(3)
+ expect(issue2.user_notes_count).to be(6)
+ end
+ end
+
describe "votes" do
let(:project) { issue.project }
before do
- issue.notes.awards.create!(note: "thumbsup", author: user, project: project)
- issue.notes.awards.create!(note: "thumbsdown", author: user, project: project)
+ create(:award_emoji, :upvote, awardable: issue)
+ create(:award_emoji, :downvote, awardable: issue)
end
it "returns correct values" do
diff --git a/spec/models/generic_commit_status_spec.rb b/spec/models/generic_commit_status_spec.rb
index d0e02618b6b..c4e781dd1dc 100644
--- a/spec/models/generic_commit_status_spec.rb
+++ b/spec/models/generic_commit_status_spec.rb
@@ -1,8 +1,8 @@
require 'spec_helper'
describe GenericCommitStatus, models: true do
- let(:commit) { FactoryGirl.create :ci_commit }
- let(:generic_commit_status) { FactoryGirl.create :generic_commit_status, commit: commit }
+ let(:pipeline) { FactoryGirl.create :ci_pipeline }
+ let(:generic_commit_status) { FactoryGirl.create :generic_commit_status, pipeline: pipeline }
describe :context do
subject { generic_commit_status.context }
diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb
index a4c55cc2fd0..1b7cbc3efda 100644
--- a/spec/models/merge_request_spec.rb
+++ b/spec/models/merge_request_spec.rb
@@ -390,19 +390,19 @@ describe MergeRequest, models: true do
subject { create :merge_request, :simple }
end
- describe '#ci_commit' do
+ describe '#pipeline' do
describe 'when the source project exists' do
it 'returns the latest commit' do
- commit = double(:commit, id: '123abc')
- ci_commit = double(:ci_commit, ref: 'master')
+ commit = double(:commit, id: '123abc')
+ pipeline = double(:ci_pipeline, ref: 'master')
allow(subject).to receive(:last_commit).and_return(commit)
- expect(subject.source_project).to receive(:ci_commit).
+ expect(subject.source_project).to receive(:pipeline).
with('123abc', 'master').
- and_return(ci_commit)
+ and_return(pipeline)
- expect(subject.ci_commit).to eq(ci_commit)
+ expect(subject.pipeline).to eq(pipeline)
end
end
@@ -410,7 +410,7 @@ describe MergeRequest, models: true do
it 'returns nil' do
allow(subject).to receive(:source_project).and_return(nil)
- expect(subject.ci_commit).to be_nil
+ expect(subject.pipeline).to be_nil
end
end
end
diff --git a/spec/models/note_spec.rb b/spec/models/note_spec.rb
index e9d89c9a847..f15e96714b2 100644
--- a/spec/models/note_spec.rb
+++ b/spec/models/note_spec.rb
@@ -9,6 +9,16 @@ describe Note, models: true do
it { is_expected.to have_many(:todos).dependent(:destroy) }
end
+ describe 'modules' do
+ subject { described_class }
+
+ it { is_expected.to include_module(Participable) }
+ it { is_expected.to include_module(Mentionable) }
+ it { is_expected.to include_module(Awardable) }
+
+ it { is_expected.to include_module(Gitlab::CurrentSettings) }
+ end
+
describe 'validation' do
it { is_expected.to validate_presence_of(:note) }
it { is_expected.to validate_presence_of(:project) }
@@ -171,23 +181,6 @@ describe Note, models: true do
end
end
- describe '.grouped_awards' do
- before do
- create :note, note: "smile", is_award: true
- create :note, note: "smile", is_award: true
- end
-
- it "returns grouped hash of notes" do
- expect(Note.grouped_awards.keys.size).to eq(3)
- expect(Note.grouped_awards["smile"]).to match_array(Note.all)
- end
-
- it "returns thumbsup and thumbsdown always" do
- expect(Note.grouped_awards["thumbsup"]).to match_array(Note.none)
- expect(Note.grouped_awards["thumbsdown"]).to match_array(Note.none)
- end
- end
-
describe "editable?" do
it "returns true" do
note = build(:note)
@@ -198,11 +191,6 @@ describe Note, models: true do
note = build(:note, system: true)
expect(note.editable?).to be_falsy
end
-
- it "returns false" do
- note = build(:note, is_award: true, note: "smiley")
- expect(note.editable?).to be_falsy
- end
end
describe "cross_reference_not_visible_for?" do
@@ -229,29 +217,6 @@ describe Note, models: true do
end
end
- describe "set_award!" do
- let(:merge_request) { create :merge_request }
-
- it "converts aliases to actual name" do
- note = create(:note, note: ":+1:",
- noteable: merge_request,
- project: merge_request.project)
-
- expect(note.reload.note).to eq("thumbsup")
- end
-
- it "is not an award emoji when comment is on a diff" do
- note = create(:note_on_merge_request_diff, note: ":blowfish:",
- noteable: merge_request,
- project: merge_request.project,
- line_code: "11d5d2e667e9da4f7f610f81d86c974b146b13bd_0_2")
- note = note.reload
-
- expect(note.note).to eq(":blowfish:")
- expect(note.is_award?).to be_falsy
- end
- end
-
describe 'clear_blank_line_code!' do
it 'clears a blank line code before validation' do
note = build(:note, line_code: ' ')
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index 338a4c3d3f0..553556ed326 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -22,7 +22,7 @@ describe Project, models: true do
it { is_expected.to have_one(:pushover_service).dependent(:destroy) }
it { is_expected.to have_one(:asana_service).dependent(:destroy) }
it { is_expected.to have_many(:commit_statuses) }
- it { is_expected.to have_many(:ci_commits) }
+ it { is_expected.to have_many(:pipelines) }
it { is_expected.to have_many(:builds) }
it { is_expected.to have_many(:runner_projects) }
it { is_expected.to have_many(:runners) }
@@ -399,23 +399,23 @@ describe Project, models: true do
end
end
- describe :ci_commit do
+ describe :pipeline do
let(:project) { create :project }
- let(:commit) { create :ci_commit, project: project, ref: 'master' }
+ let(:pipeline) { create :ci_pipeline, project: project, ref: 'master' }
- subject { project.ci_commit(commit.sha, 'master') }
+ subject { project.pipeline(pipeline.sha, 'master') }
- it { is_expected.to eq(commit) }
+ it { is_expected.to eq(pipeline) }
context 'return latest' do
- let(:commit2) { create :ci_commit, project: project, ref: 'master' }
+ let(:pipeline2) { create :ci_pipeline, project: project, ref: 'master' }
before do
- commit
- commit2
+ pipeline
+ pipeline2
end
- it { is_expected.to eq(commit2) }
+ it { is_expected.to eq(pipeline2) }
end
end
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index 548bec364f8..73bee535fe3 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -30,6 +30,7 @@ describe User, models: true do
it { is_expected.to have_one(:abuse_report) }
it { is_expected.to have_many(:spam_logs).dependent(:destroy) }
it { is_expected.to have_many(:todos).dependent(:destroy) }
+ it { is_expected.to have_many(:award_emoji).dependent(:destroy) }
end
describe 'validations' do
@@ -67,7 +68,10 @@ describe User, models: true do
describe 'email' do
context 'when no signup domains listed' do
- before { allow_any_instance_of(ApplicationSetting).to receive(:restricted_signup_domains).and_return([]) }
+ before do
+ allow_any_instance_of(ApplicationSetting).to receive(:restricted_signup_domains).and_return([])
+ end
+
it 'accepts any email' do
user = build(:user, email: "info@example.com")
expect(user).to be_valid
@@ -75,7 +79,10 @@ describe User, models: true do
end
context 'when a signup domain is listed and subdomains are allowed' do
- before { allow_any_instance_of(ApplicationSetting).to receive(:restricted_signup_domains).and_return(['example.com', '*.example.com']) }
+ before do
+ allow_any_instance_of(ApplicationSetting).to receive(:restricted_signup_domains).and_return(['example.com', '*.example.com'])
+ end
+
it 'accepts info@example.com' do
user = build(:user, email: "info@example.com")
expect(user).to be_valid
@@ -93,7 +100,9 @@ describe User, models: true do
end
context 'when a signup domain is listed and subdomains are not allowed' do
- before { allow_any_instance_of(ApplicationSetting).to receive(:restricted_signup_domains).and_return(['example.com']) }
+ before do
+ allow_any_instance_of(ApplicationSetting).to receive(:restricted_signup_domains).and_return(['example.com'])
+ end
it 'accepts info@example.com' do
user = build(:user, email: "info@example.com")
@@ -120,6 +129,66 @@ describe User, models: true do
end
end
+ describe "scopes" do
+ describe ".with_two_factor" do
+ it "returns users with 2fa enabled via OTP" do
+ user_with_2fa = create(:user, :two_factor_via_otp)
+ user_without_2fa = create(:user)
+ users_with_two_factor = User.with_two_factor.pluck(:id)
+
+ expect(users_with_two_factor).to include(user_with_2fa.id)
+ expect(users_with_two_factor).not_to include(user_without_2fa.id)
+ end
+
+ it "returns users with 2fa enabled via U2F" do
+ user_with_2fa = create(:user, :two_factor_via_u2f)
+ user_without_2fa = create(:user)
+ users_with_two_factor = User.with_two_factor.pluck(:id)
+
+ expect(users_with_two_factor).to include(user_with_2fa.id)
+ expect(users_with_two_factor).not_to include(user_without_2fa.id)
+ end
+
+ it "returns users with 2fa enabled via OTP and U2F" do
+ user_with_2fa = create(:user, :two_factor_via_otp, :two_factor_via_u2f)
+ user_without_2fa = create(:user)
+ users_with_two_factor = User.with_two_factor.pluck(:id)
+
+ expect(users_with_two_factor).to eq([user_with_2fa.id])
+ expect(users_with_two_factor).not_to include(user_without_2fa.id)
+ end
+ end
+
+ describe ".without_two_factor" do
+ it "excludes users with 2fa enabled via OTP" do
+ user_with_2fa = create(:user, :two_factor_via_otp)
+ user_without_2fa = create(:user)
+ users_without_two_factor = User.without_two_factor.pluck(:id)
+
+ expect(users_without_two_factor).to include(user_without_2fa.id)
+ expect(users_without_two_factor).not_to include(user_with_2fa.id)
+ end
+
+ it "excludes users with 2fa enabled via U2F" do
+ user_with_2fa = create(:user, :two_factor_via_u2f)
+ user_without_2fa = create(:user)
+ users_without_two_factor = User.without_two_factor.pluck(:id)
+
+ expect(users_without_two_factor).to include(user_without_2fa.id)
+ expect(users_without_two_factor).not_to include(user_with_2fa.id)
+ end
+
+ it "excludes users with 2fa enabled via OTP and U2F" do
+ user_with_2fa = create(:user, :two_factor_via_otp, :two_factor_via_u2f)
+ user_without_2fa = create(:user)
+ users_without_two_factor = User.without_two_factor.pluck(:id)
+
+ expect(users_without_two_factor).to include(user_without_2fa.id)
+ expect(users_without_two_factor).not_to include(user_with_2fa.id)
+ end
+ end
+ end
+
describe "Respond to" do
it { is_expected.to respond_to(:is_admin?) }
it { is_expected.to respond_to(:name) }
@@ -141,7 +210,10 @@ describe User, models: true do
end
describe '#confirm' do
- before { allow_any_instance_of(ApplicationSetting).to receive(:send_user_confirmation_email).and_return(true) }
+ before do
+ allow_any_instance_of(ApplicationSetting).to receive(:send_user_confirmation_email).and_return(true)
+ end
+
let(:user) { create(:user, confirmed_at: nil, unconfirmed_email: 'test@gitlab.com') }
it 'returns unconfirmed' do
@@ -784,6 +856,75 @@ describe User, models: true do
it { is_expected.to eq([private_project]) }
end
+ describe '#ci_authorized_runners' do
+ let(:user) { create(:user) }
+ let(:runner) { create(:ci_runner) }
+
+ before do
+ project.runners << runner
+ end
+
+ context 'without any projects' do
+ let(:project) { create(:project) }
+
+ it 'does not load' do
+ expect(user.ci_authorized_runners).to be_empty
+ end
+ end
+
+ context 'with personal projects runners' do
+ let(:namespace) { create(:namespace, owner: user) }
+ let(:project) { create(:project, namespace: namespace) }
+
+ it 'loads' do
+ expect(user.ci_authorized_runners).to contain_exactly(runner)
+ end
+ end
+
+ shared_examples :member do
+ context 'when the user is a master' do
+ before do
+ add_user(Gitlab::Access::MASTER)
+ end
+
+ it 'loads' do
+ expect(user.ci_authorized_runners).to contain_exactly(runner)
+ end
+ end
+
+ context 'when the user is a developer' do
+ before do
+ add_user(Gitlab::Access::DEVELOPER)
+ end
+
+ it 'does not load' do
+ expect(user.ci_authorized_runners).to be_empty
+ end
+ end
+ end
+
+ context 'with groups projects runners' do
+ let(:group) { create(:group) }
+ let(:project) { create(:project, group: group) }
+
+ def add_user(access)
+ group.add_user(user, access)
+ end
+
+ it_behaves_like :member
+ end
+
+ context 'with other projects runners' do
+ let(:project) { create(:project) }
+
+ def add_user(access)
+ project.team << [user, access]
+ end
+
+ it_behaves_like :member
+ end
+ end
+
describe '#viewable_starred_projects' do
let(:user) { create(:user) }
let(:public_project) { create(:empty_project, :public) }