diff options
author | Timothy Andrew <mail@timothyandrew.net> | 2016-09-20 14:48:13 +0530 |
---|---|---|
committer | Timothy Andrew <mail@timothyandrew.net> | 2016-09-20 14:48:13 +0530 |
commit | fa890604aaf15b9e4f0199e6a4cff24c29955a37 (patch) | |
tree | 1606c5585a93d3c0449effbe7b5cc901900833dd /spec/models | |
parent | 0b97b42d60a662c0d138c44f6dbd05a3048ac349 (diff) | |
parent | 95b9421ad3b2678da6e0af0131eafd52cdd0b2a5 (diff) | |
download | gitlab-ce-fa890604aaf15b9e4f0199e6a4cff24c29955a37.tar.gz |
Merge remote-tracking branch 'origin/master' into 21170-cycle-analytics
Diffstat (limited to 'spec/models')
42 files changed, 838 insertions, 680 deletions
diff --git a/spec/models/blob_spec.rb b/spec/models/blob_spec.rb index cee20234e1f..03d02b4d382 100644 --- a/spec/models/blob_spec.rb +++ b/spec/models/blob_spec.rb @@ -1,3 +1,4 @@ +# encoding: utf-8 require 'rails_helper' describe Blob do @@ -7,6 +8,25 @@ describe Blob do end end + describe '#data' do + context 'using a binary blob' do + it 'returns the data as-is' do + data = "\n\xFF\xB9\xC3" + blob = described_class.new(double(binary?: true, data: data)) + + expect(blob.data).to eq(data) + end + end + + context 'using a text blob' do + it 'converts the data to UTF-8' do + blob = described_class.new(double(binary?: false, data: "\n\xFF\xB9\xC3")) + + expect(blob.data).to eq("\n���") + end + end + end + describe '#svg?' do it 'is falsey when not text' do git_blob = double(text?: false) diff --git a/spec/models/build_spec.rb b/spec/models/build_spec.rb index c45c2635cf4..e7864b7ad33 100644 --- a/spec/models/build_spec.rb +++ b/spec/models/build_spec.rb @@ -88,9 +88,7 @@ describe Ci::Build, models: true do end describe '#trace' do - subject { build.trace_html } - - it { is_expected.to be_empty } + it { expect(build.trace).to be_nil } context 'when build.trace contains text' do let(:text) { 'example output' } @@ -98,16 +96,80 @@ describe Ci::Build, models: true do build.trace = text end - it { is_expected.to include(text) } - it { expect(subject.length).to be >= text.length } + it { expect(build.trace).to eq(text) } + end + + context 'when build.trace hides runners token' do + let(:token) { 'my_secret_token' } + + before do + build.update(trace: token) + build.project.update(runners_token: token) + end + + it { expect(build.trace).not_to include(token) } + it { expect(build.raw_trace).to include(token) } + end + + context 'when build.trace hides build token' do + let(:token) { 'my_secret_token' } + + before do + build.update(trace: token) + build.update(token: token) + end + + it { expect(build.trace).not_to include(token) } + it { expect(build.raw_trace).to include(token) } + end + end + + describe '#raw_trace' do + subject { build.raw_trace } + + context 'when build.trace hides runners token' do + let(:token) { 'my_secret_token' } + + before do + build.project.update(runners_token: token) + build.update(trace: token) + end + + it { is_expected.not_to include(token) } + end + + context 'when build.trace hides build token' do + let(:token) { 'my_secret_token' } + + before do + build.update(token: token) + build.update(trace: token) + end + + it { is_expected.not_to include(token) } + end + end + + context '#append_trace' do + subject { build.trace_html } + + context 'when build.trace hides runners token' do + let(:token) { 'my_secret_token' } + + before do + build.project.update(runners_token: token) + build.append_trace(token, 0) + end + + it { is_expected.not_to include(token) } end - context 'when build.trace hides token' do + context 'when build.trace hides build token' do let(:token) { 'my_secret_token' } before do - build.project.update_attributes(runners_token: token) - build.update_attributes(trace: token) + build.update(token: token) + build.append_trace(token, 0) end it { is_expected.not_to include(token) } @@ -231,6 +293,34 @@ describe Ci::Build, models: true do it { is_expected.to eq(predefined_variables) } end + context 'when build has user' do + let(:user) { create(:user, username: 'starter') } + let(:user_variables) do + [ + { key: 'GITLAB_USER_ID', value: user.id.to_s, public: true }, + { key: 'GITLAB_USER_EMAIL', value: user.email, public: true } + ] + end + + before do + build.update_attributes(user: user) + end + + it { user_variables.each { |v| is_expected.to include(v) } } + end + + context 'when build started manually' do + before do + build.update_attributes(when: :manual) + end + + let(:manual_variable) do + { key: 'CI_BUILD_MANUAL', value: 'true', public: true } + end + + it { is_expected.to include(manual_variable) } + end + context 'when build is for tag' do let(:tag_variable) do { key: 'CI_BUILD_TAG', value: 'master', public: true } diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb index bce18b4e99e..a37a00f461a 100644 --- a/spec/models/ci/build_spec.rb +++ b/spec/models/ci/build_spec.rb @@ -8,7 +8,7 @@ describe Ci::Build, models: true do it 'obfuscates project runners token' do allow(build).to receive(:raw_trace).and_return("Test: #{build.project.runners_token}") - expect(build.trace).to eq("Test: xxxxxx") + expect(build.trace).to eq("Test: xxxxxxxxxxxxxxxxxxxx") end it 'empty project runners token' do diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb index 5bafcc13f61..0b989b98b61 100644 --- a/spec/models/ci/pipeline_spec.rb +++ b/spec/models/ci/pipeline_spec.rb @@ -124,21 +124,38 @@ describe Ci::Pipeline, models: true do describe 'state machine' do let(:current) { Time.now.change(usec: 0) } - let(:build) { create :ci_build, name: 'build1', pipeline: pipeline } + let(:build) { create_build('build1', current, 10) } + let(:build_b) { create_build('build2', current, 20) } + let(:build_c) { create_build('build3', current + 50, 10) } describe '#duration' do before do - travel_to(current - 120) do + pipeline.update(created_at: current) + + travel_to(current + 5) do pipeline.run + pipeline.save + end + + travel_to(current + 30) do + build.success + end + + travel_to(current + 40) do + build_b.drop end - travel_to(current) do - pipeline.succeed + travel_to(current + 70) do + build_c.success end + + pipeline.drop end it 'matches sum of builds duration' do - expect(pipeline.reload.duration).to eq(120) + pipeline.reload + + expect(pipeline.duration).to eq(40) end end @@ -200,6 +217,14 @@ describe Ci::Pipeline, models: true do end end end + + def create_build(name, queued_at = current, started_from = 0) + create(:ci_build, + name: name, + pipeline: pipeline, + queued_at: queued_at, + started_at: queued_at + started_from) + end end describe '#branch?' do @@ -379,8 +404,8 @@ describe Ci::Pipeline, models: true do end describe '#execute_hooks' do - let!(:build_a) { create_build('a') } - let!(:build_b) { create_build('b') } + let!(:build_a) { create_build('a', 0) } + let!(:build_b) { create_build('b', 1) } let!(:hook) do create(:project_hook, project: project, pipeline_events: enabled) @@ -404,7 +429,7 @@ describe Ci::Pipeline, models: true do build_b.enqueue end - it 'receive a pending event once' do + it 'receives a pending event once' do expect(WebMock).to have_requested_pipeline_hook('pending').once end end @@ -417,7 +442,7 @@ describe Ci::Pipeline, models: true do build_b.run end - it 'receive a running event once' do + it 'receives a running event once' do expect(WebMock).to have_requested_pipeline_hook('running').once end end @@ -428,11 +453,21 @@ describe Ci::Pipeline, models: true do build_b.success end - it 'receive a success event once' do + it 'receives a success event once' do expect(WebMock).to have_requested_pipeline_hook('success').once end end + context 'when stage one failed' do + before do + build_a.drop + end + + it 'receives a failed event once' do + expect(WebMock).to have_requested_pipeline_hook('failed').once + end + end + def have_requested_pipeline_hook(status) have_requested(:post, hook.url).with do |req| json_body = JSON.parse(req.body) @@ -456,8 +491,12 @@ describe Ci::Pipeline, models: true do end end - def create_build(name) - create(:ci_build, :created, pipeline: pipeline, name: name) + def create_build(name, stage_idx) + create(:ci_build, + :created, + pipeline: pipeline, + name: name, + stage_idx: stage_idx) end end diff --git a/spec/models/commit_status_spec.rb b/spec/models/commit_status_spec.rb index fcfa3138ce5..2f1baff5d66 100644 --- a/spec/models/commit_status_spec.rb +++ b/spec/models/commit_status_spec.rb @@ -40,7 +40,7 @@ describe CommitStatus, models: true do it { is_expected.to be_falsey } end - %w(running success failed).each do |status| + %w[running success failed].each do |status| context "if commit status is #{status}" do before { commit_status.status = status } @@ -48,7 +48,7 @@ describe CommitStatus, models: true do end end - %w(pending canceled).each do |status| + %w[pending canceled].each do |status| context "if commit status is #{status}" do before { commit_status.status = status } @@ -60,7 +60,7 @@ describe CommitStatus, models: true do describe '#active?' do subject { commit_status.active? } - %w(pending running).each do |state| + %w[pending running].each do |state| context "if commit_status.status is #{state}" do before { commit_status.status = state } @@ -68,7 +68,7 @@ describe CommitStatus, models: true do end end - %w(success failed canceled).each do |state| + %w[success failed canceled].each do |state| context "if commit_status.status is #{state}" do before { commit_status.status = state } @@ -80,7 +80,7 @@ describe CommitStatus, models: true do describe '#complete?' do subject { commit_status.complete? } - %w(success failed canceled).each do |state| + %w[success failed canceled].each do |state| context "if commit_status.status is #{state}" do before { commit_status.status = state } @@ -88,7 +88,7 @@ describe CommitStatus, models: true do end end - %w(pending running).each do |state| + %w[pending running].each do |state| context "if commit_status.status is #{state}" do before { commit_status.status = state } @@ -187,7 +187,7 @@ describe CommitStatus, models: true do subject { CommitStatus.where(pipeline: pipeline).stages } it 'returns ordered list of stages' do - is_expected.to eq(%w(build test deploy)) + is_expected.to eq(%w[build test deploy]) end end @@ -223,4 +223,33 @@ describe CommitStatus, models: true do expect(commit_status.commit).to eq project.commit end end + + describe '#group_name' do + subject { commit_status.group_name } + + tests = { + 'rspec:windows' => 'rspec:windows', + 'rspec:windows 0' => 'rspec:windows 0', + 'rspec:windows 0 test' => 'rspec:windows 0 test', + 'rspec:windows 0 1' => 'rspec:windows', + 'rspec:windows 0 1 name' => 'rspec:windows name', + 'rspec:windows 0/1' => 'rspec:windows', + 'rspec:windows 0/1 name' => 'rspec:windows name', + 'rspec:windows 0:1' => 'rspec:windows', + 'rspec:windows 0:1 name' => 'rspec:windows name', + 'rspec:windows 10000 20000' => 'rspec:windows', + 'rspec:windows 0 : / 1' => 'rspec:windows', + 'rspec:windows 0 : / 1 name' => 'rspec:windows name', + '0 1 name ruby' => 'name ruby', + '0 :/ 1 name ruby' => 'name ruby' + } + + tests.each do |name, group_name| + it "'#{name}' puts in '#{group_name}'" do + commit_status.name = name + + is_expected.to eq(group_name) + end + end + end end diff --git a/spec/models/diff_note_spec.rb b/spec/models/diff_note_spec.rb index 6a640474cfe..3db5937a4f3 100644 --- a/spec/models/diff_note_spec.rb +++ b/spec/models/diff_note_spec.rb @@ -31,6 +31,43 @@ describe DiffNote, models: true do subject { create(:diff_note_on_merge_request, project: project, position: position, noteable: merge_request) } + describe ".resolve!" do + let(:current_user) { create(:user) } + let!(:commit_note) { create(:diff_note_on_commit) } + let!(:resolved_note) { create(:diff_note_on_merge_request, :resolved) } + let!(:unresolved_note) { create(:diff_note_on_merge_request) } + + before do + described_class.resolve!(current_user) + + commit_note.reload + resolved_note.reload + unresolved_note.reload + end + + it 'resolves only the resolvable, not yet resolved notes' do + expect(commit_note.resolved_at).to be_nil + expect(resolved_note.resolved_by).not_to eq(current_user) + expect(unresolved_note.resolved_at).not_to be_nil + expect(unresolved_note.resolved_by).to eq(current_user) + end + end + + describe ".unresolve!" do + let!(:resolved_note) { create(:diff_note_on_merge_request, :resolved) } + + before do + described_class.unresolve! + + resolved_note.reload + end + + it 'unresolves the resolved notes' do + expect(resolved_note.resolved_by).to be_nil + expect(resolved_note.resolved_at).to be_nil + end + end + describe "#position=" do context "when provided a string" do it "sets the position" do diff --git a/spec/models/discussion_spec.rb b/spec/models/discussion_spec.rb index 179f2e73662..0142706d140 100644 --- a/spec/models/discussion_spec.rb +++ b/spec/models/discussion_spec.rb @@ -238,27 +238,19 @@ describe Discussion, model: true do context "when resolvable" do let(:user) { create(:user) } + let(:second_note) { create(:diff_note_on_commit) } # unresolvable before do allow(subject).to receive(:resolvable?).and_return(true) - - allow(first_note).to receive(:resolvable?).and_return(true) - allow(second_note).to receive(:resolvable?).and_return(false) - allow(third_note).to receive(:resolvable?).and_return(true) end context "when all resolvable notes are resolved" do before do first_note.resolve!(user) third_note.resolve!(user) - end - it "calls resolve! on every resolvable note" do - expect(first_note).to receive(:resolve!).with(current_user) - expect(second_note).not_to receive(:resolve!) - expect(third_note).to receive(:resolve!).with(current_user) - - subject.resolve!(current_user) + first_note.reload + third_note.reload end it "doesn't change resolved_at on the resolved notes" do @@ -309,46 +301,44 @@ describe Discussion, model: true do first_note.resolve!(user) end - it "calls resolve! on every resolvable note" do - expect(first_note).to receive(:resolve!).with(current_user) - expect(second_note).not_to receive(:resolve!) - expect(third_note).to receive(:resolve!).with(current_user) - - subject.resolve!(current_user) - end - it "doesn't change resolved_at on the resolved note" do expect(first_note.resolved_at).not_to be_nil - expect { subject.resolve!(current_user) }.not_to change { first_note.resolved_at } + expect { subject.resolve!(current_user) }. + not_to change { first_note.reload.resolved_at } end it "doesn't change resolved_by on the resolved note" do expect(first_note.resolved_by).to eq(user) - expect { subject.resolve!(current_user) }.not_to change { first_note.resolved_by } + expect { subject.resolve!(current_user) }. + not_to change { first_note.reload && first_note.resolved_by } end it "doesn't change the resolved state on the resolved note" do expect(first_note.resolved?).to be true - expect { subject.resolve!(current_user) }.not_to change { first_note.resolved? } + expect { subject.resolve!(current_user) }. + not_to change { first_note.reload && first_note.resolved? } end it "sets resolved_at on the unresolved note" do subject.resolve!(current_user) + third_note.reload expect(third_note.resolved_at).not_to be_nil end it "sets resolved_by on the unresolved note" do subject.resolve!(current_user) + third_note.reload expect(third_note.resolved_by).to eq(current_user) end it "marks the unresolved note as resolved" do subject.resolve!(current_user) + third_note.reload expect(third_note.resolved?).to be true end @@ -373,16 +363,10 @@ describe Discussion, model: true do end context "when no resolvable notes are resolved" do - it "calls resolve! on every resolvable note" do - expect(first_note).to receive(:resolve!).with(current_user) - expect(second_note).not_to receive(:resolve!) - expect(third_note).to receive(:resolve!).with(current_user) - - subject.resolve!(current_user) - end - it "sets resolved_at on the unresolved notes" do subject.resolve!(current_user) + first_note.reload + third_note.reload expect(first_note.resolved_at).not_to be_nil expect(third_note.resolved_at).not_to be_nil @@ -390,6 +374,8 @@ describe Discussion, model: true do it "sets resolved_by on the unresolved notes" do subject.resolve!(current_user) + first_note.reload + third_note.reload expect(first_note.resolved_by).to eq(current_user) expect(third_note.resolved_by).to eq(current_user) @@ -397,6 +383,8 @@ describe Discussion, model: true do it "marks the unresolved notes as resolved" do subject.resolve!(current_user) + first_note.reload + third_note.reload expect(first_note.resolved?).to be true expect(third_note.resolved?).to be true @@ -404,18 +392,24 @@ describe Discussion, model: true do it "sets resolved_at" do subject.resolve!(current_user) + first_note.reload + third_note.reload expect(subject.resolved_at).not_to be_nil end it "sets resolved_by" do subject.resolve!(current_user) + first_note.reload + third_note.reload expect(subject.resolved_by).to eq(current_user) end it "marks as resolved" do subject.resolve!(current_user) + first_note.reload + third_note.reload expect(subject.resolved?).to be true end @@ -451,16 +445,10 @@ describe Discussion, model: true do third_note.resolve!(user) end - it "calls unresolve! on every resolvable note" do - expect(first_note).to receive(:unresolve!) - expect(second_note).not_to receive(:unresolve!) - expect(third_note).to receive(:unresolve!) - - subject.unresolve! - end - it "unsets resolved_at on the resolved notes" do subject.unresolve! + first_note.reload + third_note.reload expect(first_note.resolved_at).to be_nil expect(third_note.resolved_at).to be_nil @@ -468,6 +456,8 @@ describe Discussion, model: true do it "unsets resolved_by on the resolved notes" do subject.unresolve! + first_note.reload + third_note.reload expect(first_note.resolved_by).to be_nil expect(third_note.resolved_by).to be_nil @@ -475,6 +465,8 @@ describe Discussion, model: true do it "unmarks the resolved notes as resolved" do subject.unresolve! + first_note.reload + third_note.reload expect(first_note.resolved?).to be false expect(third_note.resolved?).to be false @@ -482,12 +474,16 @@ describe Discussion, model: true do it "unsets resolved_at" do subject.unresolve! + first_note.reload + third_note.reload expect(subject.resolved_at).to be_nil end it "unsets resolved_by" do subject.unresolve! + first_note.reload + third_note.reload expect(subject.resolved_by).to be_nil end @@ -504,40 +500,22 @@ describe Discussion, model: true do first_note.resolve!(user) end - it "calls unresolve! on every resolvable note" do - expect(first_note).to receive(:unresolve!) - expect(second_note).not_to receive(:unresolve!) - expect(third_note).to receive(:unresolve!) - - subject.unresolve! - end - it "unsets resolved_at on the resolved note" do subject.unresolve! - expect(first_note.resolved_at).to be_nil + expect(subject.first_note.resolved_at).to be_nil end it "unsets resolved_by on the resolved note" do subject.unresolve! - expect(first_note.resolved_by).to be_nil + expect(subject.first_note.resolved_by).to be_nil end it "unmarks the resolved note as resolved" do subject.unresolve! - expect(first_note.resolved?).to be false - end - end - - context "when no resolvable notes are resolved" do - it "calls unresolve! on every resolvable note" do - expect(first_note).to receive(:unresolve!) - expect(second_note).not_to receive(:unresolve!) - expect(third_note).to receive(:unresolve!) - - subject.unresolve! + expect(subject.first_note.resolved?).to be false end end end diff --git a/spec/models/environment_spec.rb b/spec/models/environment_spec.rb index c881897926e..6b1867a44e1 100644 --- a/spec/models/environment_spec.rb +++ b/spec/models/environment_spec.rb @@ -63,4 +63,20 @@ describe Environment, models: true do end end end + + describe '#environment_type' do + subject { environment.environment_type } + + it 'sets a environment type if name has multiple segments' do + environment.update!(name: 'production/worker.gitlab.com') + + is_expected.to eq('production') + end + + it 'nullifies a type if it\'s a simple name' do + environment.update!(name: 'production') + + is_expected.to be_nil + end + end end diff --git a/spec/models/event_spec.rb b/spec/models/event_spec.rb index b5d0d79e14e..8600eb4d2c4 100644 --- a/spec/models/event_spec.rb +++ b/spec/models/event_spec.rb @@ -16,18 +16,12 @@ describe Event, models: true do describe 'Callbacks' do describe 'after_create :reset_project_activity' do - let(:project) { create(:project) } + let(:project) { create(:empty_project) } - context "project's last activity was less than 5 minutes ago" do - it 'does not update project.last_activity_at if it has been touched less than 5 minutes ago' do - create_event(project, project.owner) - project.update_column(:last_activity_at, 5.minutes.ago) - project_last_activity_at = project.last_activity_at + it 'calls the reset_project_activity method' do + expect_any_instance_of(Event).to receive(:reset_project_activity) - create_event(project, project.owner) - - expect(project.last_activity_at).to eq(project_last_activity_at) - end + create_event(project, project.owner) end end end @@ -161,6 +155,35 @@ describe Event, models: true do end end + describe '#reset_project_activity' do + let(:project) { create(:empty_project) } + + context 'when a project was updated less than 1 hour ago' do + it 'does not update the project' do + project.update(last_activity_at: Time.now) + + expect(project).not_to receive(:update_column). + with(:last_activity_at, a_kind_of(Time)) + + create_event(project, project.owner) + end + end + + context 'when a project was updated more than 1 hour ago' do + it 'updates the project' do + project.update(last_activity_at: 1.year.ago) + + expect_any_instance_of(Gitlab::ExclusiveLease). + to receive(:try_obtain).and_return(true) + + expect(project).to receive(:update_column). + with(:last_activity_at, a_kind_of(Time)) + + create_event(project, project.owner) + end + end + end + def create_event(project, user, attrs = {}) data = { before: Gitlab::Git::BLANK_SHA, diff --git a/spec/models/group_spec.rb b/spec/models/group_spec.rb index ea4b59c26b1..0b3ef9b98fd 100644 --- a/spec/models/group_spec.rb +++ b/spec/models/group_spec.rb @@ -187,6 +187,52 @@ describe Group, models: true do it { expect(group.has_master?(@members[:requester])).to be_falsey } end + describe '#lfs_enabled?' do + context 'LFS enabled globally' do + before do + allow(Gitlab.config.lfs).to receive(:enabled).and_return(true) + end + + it 'returns true when nothing is set' do + expect(group.lfs_enabled?).to be_truthy + end + + it 'returns false when set to false' do + group.update_attribute(:lfs_enabled, false) + + expect(group.lfs_enabled?).to be_falsey + end + + it 'returns true when set to true' do + group.update_attribute(:lfs_enabled, true) + + expect(group.lfs_enabled?).to be_truthy + end + end + + context 'LFS disabled globally' do + before do + allow(Gitlab.config.lfs).to receive(:enabled).and_return(false) + end + + it 'returns false when nothing is set' do + expect(group.lfs_enabled?).to be_falsey + end + + it 'returns false when set to false' do + group.update_attribute(:lfs_enabled, false) + + expect(group.lfs_enabled?).to be_falsey + end + + it 'returns false when set to true' do + group.update_attribute(:lfs_enabled, true) + + expect(group.lfs_enabled?).to be_falsey + end + end + end + describe '#owners' do let(:owner) { create(:user) } let(:developer) { create(:user) } diff --git a/spec/models/hooks/project_hook_spec.rb b/spec/models/hooks/project_hook_spec.rb index 4a457997a4f..474ae62ccec 100644 --- a/spec/models/hooks/project_hook_spec.rb +++ b/spec/models/hooks/project_hook_spec.rb @@ -1,21 +1,3 @@ -# == Schema Information -# -# Table name: web_hooks -# -# id :integer not null, primary key -# url :string(255) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# type :string(255) default("ProjectHook") -# service_id :integer -# push_events :boolean default(TRUE), not null -# issues_events :boolean default(FALSE), not null -# merge_requests_events :boolean default(FALSE), not null -# tag_push_events :boolean default(FALSE) -# note_events :boolean default(FALSE), not null -# - require 'spec_helper' describe ProjectHook, models: true do diff --git a/spec/models/hooks/service_hook_spec.rb b/spec/models/hooks/service_hook_spec.rb index 534e1b4f128..1a83c836652 100644 --- a/spec/models/hooks/service_hook_spec.rb +++ b/spec/models/hooks/service_hook_spec.rb @@ -1,21 +1,3 @@ -# == Schema Information -# -# Table name: web_hooks -# -# id :integer not null, primary key -# url :string(255) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# type :string(255) default("ProjectHook") -# service_id :integer -# push_events :boolean default(TRUE), not null -# issues_events :boolean default(FALSE), not null -# merge_requests_events :boolean default(FALSE), not null -# tag_push_events :boolean default(FALSE) -# note_events :boolean default(FALSE), not null -# - require "spec_helper" describe ServiceHook, models: true do diff --git a/spec/models/hooks/system_hook_spec.rb b/spec/models/hooks/system_hook_spec.rb index cbdf7eec082..ad2b710041a 100644 --- a/spec/models/hooks/system_hook_spec.rb +++ b/spec/models/hooks/system_hook_spec.rb @@ -1,21 +1,3 @@ -# == Schema Information -# -# Table name: web_hooks -# -# id :integer not null, primary key -# url :string(255) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# type :string(255) default("ProjectHook") -# service_id :integer -# push_events :boolean default(TRUE), not null -# issues_events :boolean default(FALSE), not null -# merge_requests_events :boolean default(FALSE), not null -# tag_push_events :boolean default(FALSE) -# note_events :boolean default(FALSE), not null -# - require "spec_helper" describe SystemHook, models: true do @@ -48,7 +30,7 @@ describe SystemHook, models: true do it "user_create hook" do create(:user) - + expect(WebMock).to have_requested(:post, system_hook.url).with( body: /user_create/, headers: { 'Content-Type' => 'application/json', 'X-Gitlab-Event' => 'System Hook' } diff --git a/spec/models/hooks/web_hook_spec.rb b/spec/models/hooks/web_hook_spec.rb index f9bab487b96..e52b9d75cef 100644 --- a/spec/models/hooks/web_hook_spec.rb +++ b/spec/models/hooks/web_hook_spec.rb @@ -1,21 +1,3 @@ -# == Schema Information -# -# Table name: web_hooks -# -# id :integer not null, primary key -# url :string(255) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# type :string(255) default("ProjectHook") -# service_id :integer -# push_events :boolean default(TRUE), not null -# issues_events :boolean default(FALSE), not null -# merge_requests_events :boolean default(FALSE), not null -# tag_push_events :boolean default(FALSE) -# note_events :boolean default(FALSE), not null -# - require 'spec_helper' describe WebHook, models: true do diff --git a/spec/models/member_spec.rb b/spec/models/member_spec.rb index fef90d9b5cb..0b1634f654a 100644 --- a/spec/models/member_spec.rb +++ b/spec/models/member_spec.rb @@ -57,7 +57,7 @@ describe Member, models: true do describe 'Scopes & finders' do before do - project = create(:project) + project = create(:empty_project) group = create(:group) @owner_user = create(:user).tap { |u| group.add_owner(u) } @owner = group.members.find_by(user_id: @owner_user.id) @@ -65,6 +65,15 @@ describe Member, models: true do @master_user = create(:user).tap { |u| project.team << [u, :master] } @master = project.members.find_by(user_id: @master_user.id) + @blocked_user = create(:user).tap do |u| + project.team << [u, :master] + project.team << [u, :developer] + + u.block! + end + @blocked_master = project.members.find_by(user_id: @blocked_user.id, access_level: Gitlab::Access::MASTER) + @blocked_developer = project.members.find_by(user_id: @blocked_user.id, access_level: Gitlab::Access::DEVELOPER) + Member.add_user( project.members, 'toto1@example.com', @@ -73,7 +82,7 @@ describe Member, models: true do ) @invited_member = project.members.invite.find_by_invite_email('toto1@example.com') - accepted_invite_user = build(:user) + accepted_invite_user = build(:user, state: :active) Member.add_user( project.members, 'toto2@example.com', @@ -91,7 +100,7 @@ describe Member, models: true do describe '.access_for_user_ids' do it 'returns the right access levels' do - users = [@owner_user.id, @master_user.id] + users = [@owner_user.id, @master_user.id, @blocked_user.id] expected = { @owner_user.id => Gitlab::Access::OWNER, @master_user.id => Gitlab::Access::MASTER @@ -125,6 +134,19 @@ describe Member, models: true do it { expect(described_class.request).not_to include @accepted_request_member } end + describe '.developers' do + subject { described_class.developers.to_a } + + it { is_expected.not_to include @owner } + it { is_expected.not_to include @master } + it { is_expected.to include @invited_member } + it { is_expected.to include @accepted_invite_member } + it { is_expected.not_to include @requested_member } + it { is_expected.to include @accepted_request_member } + it { is_expected.not_to include @blocked_master } + it { is_expected.not_to include @blocked_developer } + end + describe '.owners_and_masters' do it { expect(described_class.owners_and_masters).to include @owner } it { expect(described_class.owners_and_masters).to include @master } @@ -132,6 +154,20 @@ describe Member, models: true do it { expect(described_class.owners_and_masters).not_to include @accepted_invite_member } it { expect(described_class.owners_and_masters).not_to include @requested_member } it { expect(described_class.owners_and_masters).not_to include @accepted_request_member } + it { expect(described_class.owners_and_masters).not_to include @blocked_master } + end + + describe '.has_access' do + subject { described_class.has_access.to_a } + + it { is_expected.to include @owner } + it { is_expected.to include @master } + it { is_expected.to include @invited_member } + it { is_expected.to include @accepted_invite_member } + it { is_expected.not_to include @requested_member } + it { is_expected.to include @accepted_request_member } + it { is_expected.not_to include @blocked_master } + it { is_expected.not_to include @blocked_developer } end end diff --git a/spec/models/members/group_member_spec.rb b/spec/models/members/group_member_spec.rb index 4f875fd257a..56fa7fa6134 100644 --- a/spec/models/members/group_member_spec.rb +++ b/spec/models/members/group_member_spec.rb @@ -1,22 +1,3 @@ -# == Schema Information -# -# Table name: members -# -# id :integer not null, primary key -# access_level :integer not null -# source_id :integer not null -# source_type :string(255) not null -# user_id :integer -# notification_level :integer not null -# type :string(255) -# created_at :datetime -# updated_at :datetime -# created_by_id :integer -# invite_email :string(255) -# invite_token :string(255) -# invite_accepted_at :datetime -# - require 'spec_helper' describe GroupMember, models: true do diff --git a/spec/models/members/project_member_spec.rb b/spec/models/members/project_member_spec.rb index be57957b569..805c15a4e5e 100644 --- a/spec/models/members/project_member_spec.rb +++ b/spec/models/members/project_member_spec.rb @@ -1,22 +1,3 @@ -# == Schema Information -# -# Table name: members -# -# id :integer not null, primary key -# access_level :integer not null -# source_id :integer not null -# source_type :string(255) not null -# user_id :integer -# notification_level :integer not null -# type :string(255) -# created_at :datetime -# updated_at :datetime -# created_by_id :integer -# invite_email :string(255) -# invite_token :string(255) -# invite_accepted_at :datetime -# - require 'spec_helper' describe ProjectMember, models: true do diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb index 5bf3b8e609e..06feeb1bbba 100644 --- a/spec/models/merge_request_spec.rb +++ b/spec/models/merge_request_spec.rb @@ -703,16 +703,24 @@ describe MergeRequest, models: true do describe "#environments" do let(:project) { create(:project) } - let!(:environment) { create(:environment, project: project) } - let!(:environment1) { create(:environment, project: project) } - let!(:environment2) { create(:environment, project: project) } let(:merge_request) { create(:merge_request, source_project: project) } it 'selects deployed environments' do - create(:deployment, environment: environment, sha: project.commit('master').id) - create(:deployment, environment: environment1, sha: project.commit('feature').id) + environments = create_list(:environment, 3, project: project) + create(:deployment, environment: environments.first, sha: project.commit('master').id) + create(:deployment, environment: environments.second, sha: project.commit('feature').id) - expect(merge_request.environments).to eq [environment] + expect(merge_request.environments).to eq [environments.first] + end + + context 'without a diff_head_commit' do + before do + expect(merge_request).to receive(:diff_head_commit).and_return(nil) + end + + it 'returns an empty array' do + expect(merge_request.environments).to be_empty + end end end @@ -1038,4 +1046,81 @@ describe MergeRequest, models: true do end end end + + describe '#closed_without_source_project?' do + let(:project) { create(:project) } + let(:user) { create(:user) } + let(:fork_project) { create(:project, forked_from_project: project, namespace: user.namespace) } + let(:destroy_service) { Projects::DestroyService.new(fork_project, user) } + + context 'when the merge request is closed' do + let(:closed_merge_request) do + create(:closed_merge_request, + source_project: fork_project, + target_project: project) + end + + it 'returns false if the source project exists' do + expect(closed_merge_request.closed_without_source_project?).to be_falsey + end + + it 'returns true if the source project does not exist' do + destroy_service.execute + closed_merge_request.reload + + expect(closed_merge_request.closed_without_source_project?).to be_truthy + end + end + + context 'when the merge request is open' do + it 'returns false' do + expect(subject.closed_without_source_project?).to be_falsey + end + end + end + + describe '#reopenable?' do + context 'when the merge request is closed' do + it 'returns true' do + subject.close + + expect(subject.reopenable?).to be_truthy + end + + context 'forked project' do + let(:project) { create(:project) } + let(:user) { create(:user) } + let(:fork_project) { create(:project, forked_from_project: project, namespace: user.namespace) } + let(:merge_request) do + create(:closed_merge_request, + source_project: fork_project, + target_project: project) + end + + it 'returns false if unforked' do + Projects::UnlinkForkService.new(fork_project, user).execute + + expect(merge_request.reload.reopenable?).to be_falsey + end + + it 'returns false if the source project is deleted' do + Projects::DestroyService.new(fork_project, user).execute + + expect(merge_request.reload.reopenable?).to be_falsey + end + + it 'returns false if the merge request is merged' do + merge_request.update_attributes(state: 'merged') + + expect(merge_request.reload.reopenable?).to be_falsey + end + end + end + + context 'when the merge request is opened' do + it 'returns false' do + expect(subject.reopenable?).to be_falsey + end + end + end end diff --git a/spec/models/project_services/asana_service_spec.rb b/spec/models/project_services/asana_service_spec.rb index dc702cfc42c..8e5145e824b 100644 --- a/spec/models/project_services/asana_service_spec.rb +++ b/spec/models/project_services/asana_service_spec.rb @@ -1,23 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string(255) -# title :string(255) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# active :boolean default(FALSE), not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# - require 'spec_helper' describe AsanaService, models: true do diff --git a/spec/models/project_services/assembla_service_spec.rb b/spec/models/project_services/assembla_service_spec.rb index d672d80156c..4c5acb7990b 100644 --- a/spec/models/project_services/assembla_service_spec.rb +++ b/spec/models/project_services/assembla_service_spec.rb @@ -1,23 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string(255) -# title :string(255) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# active :boolean default(FALSE), not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# - require 'spec_helper' describe AssemblaService, models: true do diff --git a/spec/models/project_services/bamboo_service_spec.rb b/spec/models/project_services/bamboo_service_spec.rb index 9ae461f8c2d..d7e1a4e3b6c 100644 --- a/spec/models/project_services/bamboo_service_spec.rb +++ b/spec/models/project_services/bamboo_service_spec.rb @@ -1,23 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string(255) -# title :string(255) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# active :boolean default(FALSE), not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# - require 'spec_helper' describe BambooService, models: true do diff --git a/spec/models/project_services/bugzilla_service_spec.rb b/spec/models/project_services/bugzilla_service_spec.rb index a6d9717ccb5..739cc72b2ff 100644 --- a/spec/models/project_services/bugzilla_service_spec.rb +++ b/spec/models/project_services/bugzilla_service_spec.rb @@ -1,23 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string(255) -# title :string(255) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# active :boolean default(FALSE), not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# - require 'spec_helper' describe BugzillaService, models: true do diff --git a/spec/models/project_services/buildkite_service_spec.rb b/spec/models/project_services/buildkite_service_spec.rb index 0866e1532dd..6f65beb79d0 100644 --- a/spec/models/project_services/buildkite_service_spec.rb +++ b/spec/models/project_services/buildkite_service_spec.rb @@ -1,23 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string(255) -# title :string(255) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# active :boolean default(FALSE), not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# - require 'spec_helper' describe BuildkiteService, models: true do diff --git a/spec/models/project_services/campfire_service_spec.rb b/spec/models/project_services/campfire_service_spec.rb index c76ae21421b..a3b9d084a75 100644 --- a/spec/models/project_services/campfire_service_spec.rb +++ b/spec/models/project_services/campfire_service_spec.rb @@ -1,23 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string(255) -# title :string(255) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# active :boolean default(FALSE), not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# - require 'spec_helper' describe CampfireService, models: true do diff --git a/spec/models/project_services/custom_issue_tracker_service_spec.rb b/spec/models/project_services/custom_issue_tracker_service_spec.rb index ff976f8ec59..7020667ea58 100644 --- a/spec/models/project_services/custom_issue_tracker_service_spec.rb +++ b/spec/models/project_services/custom_issue_tracker_service_spec.rb @@ -1,23 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string(255) -# title :string(255) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# active :boolean default(FALSE), not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# - require 'spec_helper' describe CustomIssueTrackerService, models: true do diff --git a/spec/models/project_services/drone_ci_service_spec.rb b/spec/models/project_services/drone_ci_service_spec.rb index 8ef892259f2..f13bb1e8adf 100644 --- a/spec/models/project_services/drone_ci_service_spec.rb +++ b/spec/models/project_services/drone_ci_service_spec.rb @@ -1,23 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string(255) -# title :string(255) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# active :boolean default(FALSE), not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# - require 'spec_helper' describe DroneCiService, models: true do diff --git a/spec/models/project_services/external_wiki_service_spec.rb b/spec/models/project_services/external_wiki_service_spec.rb index d7c5ea95d71..342d86aeca9 100644 --- a/spec/models/project_services/external_wiki_service_spec.rb +++ b/spec/models/project_services/external_wiki_service_spec.rb @@ -1,24 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string(255) -# title :string(255) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# active :boolean default(FALSE), not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# build_events :boolean default(FALSE), not null -# - require 'spec_helper' describe ExternalWikiService, models: true do diff --git a/spec/models/project_services/flowdock_service_spec.rb b/spec/models/project_services/flowdock_service_spec.rb index d2557019756..d6db02d6e76 100644 --- a/spec/models/project_services/flowdock_service_spec.rb +++ b/spec/models/project_services/flowdock_service_spec.rb @@ -1,23 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string(255) -# title :string(255) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# active :boolean default(FALSE), not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# - require 'spec_helper' describe FlowdockService, models: true do diff --git a/spec/models/project_services/gemnasium_service_spec.rb b/spec/models/project_services/gemnasium_service_spec.rb index 3d0b6c9816b..529044d1d8b 100644 --- a/spec/models/project_services/gemnasium_service_spec.rb +++ b/spec/models/project_services/gemnasium_service_spec.rb @@ -1,23 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string(255) -# title :string(255) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# active :boolean default(FALSE), not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# - require 'spec_helper' describe GemnasiumService, models: true do diff --git a/spec/models/project_services/gitlab_issue_tracker_service_spec.rb b/spec/models/project_services/gitlab_issue_tracker_service_spec.rb index 8ef79a17d50..652804fb444 100644 --- a/spec/models/project_services/gitlab_issue_tracker_service_spec.rb +++ b/spec/models/project_services/gitlab_issue_tracker_service_spec.rb @@ -1,23 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string(255) -# title :string(255) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# active :boolean default(FALSE), not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# - require 'spec_helper' describe GitlabIssueTrackerService, models: true do diff --git a/spec/models/project_services/hipchat_service_spec.rb b/spec/models/project_services/hipchat_service_spec.rb index 34eafbe555d..cf713684463 100644 --- a/spec/models/project_services/hipchat_service_spec.rb +++ b/spec/models/project_services/hipchat_service_spec.rb @@ -1,23 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string(255) -# title :string(255) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# active :boolean default(FALSE), not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# - require 'spec_helper' describe HipchatService, models: true do diff --git a/spec/models/project_services/irker_service_spec.rb b/spec/models/project_services/irker_service_spec.rb index ffb17fd3259..f8c45b37561 100644 --- a/spec/models/project_services/irker_service_spec.rb +++ b/spec/models/project_services/irker_service_spec.rb @@ -1,23 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string(255) -# title :string(255) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# active :boolean default(FALSE), not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# - require 'spec_helper' require 'socket' require 'json' diff --git a/spec/models/project_services/jira_service_spec.rb b/spec/models/project_services/jira_service_spec.rb index 9037ca5cc20..b48a3176007 100644 --- a/spec/models/project_services/jira_service_spec.rb +++ b/spec/models/project_services/jira_service_spec.rb @@ -1,23 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string(255) -# title :string(255) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# active :boolean default(FALSE), not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# - require 'spec_helper' describe JiraService, models: true do diff --git a/spec/models/project_services/pivotaltracker_service_spec.rb b/spec/models/project_services/pivotaltracker_service_spec.rb index d098d988521..45b2f1068bf 100644 --- a/spec/models/project_services/pivotaltracker_service_spec.rb +++ b/spec/models/project_services/pivotaltracker_service_spec.rb @@ -1,23 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string(255) -# title :string(255) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# active :boolean default(FALSE), not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# - require 'spec_helper' describe PivotaltrackerService, models: true do diff --git a/spec/models/project_services/pushover_service_spec.rb b/spec/models/project_services/pushover_service_spec.rb index 5959c81577d..8fc92a9ab51 100644 --- a/spec/models/project_services/pushover_service_spec.rb +++ b/spec/models/project_services/pushover_service_spec.rb @@ -1,23 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string(255) -# title :string(255) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# active :boolean default(FALSE), not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# - require 'spec_helper' describe PushoverService, models: true do diff --git a/spec/models/project_services/redmine_service_spec.rb b/spec/models/project_services/redmine_service_spec.rb index 7d14f6e8280..b8679cd2563 100644 --- a/spec/models/project_services/redmine_service_spec.rb +++ b/spec/models/project_services/redmine_service_spec.rb @@ -1,23 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string(255) -# title :string(255) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# active :boolean default(FALSE), not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# - require 'spec_helper' describe RedmineService, models: true do diff --git a/spec/models/project_services/slack_service/build_message_spec.rb b/spec/models/project_services/slack_service/build_message_spec.rb index 7fcfdf0eacd..452f4e2782c 100644 --- a/spec/models/project_services/slack_service/build_message_spec.rb +++ b/spec/models/project_services/slack_service/build_message_spec.rb @@ -10,7 +10,7 @@ describe SlackService::BuildMessage do tag: false, project_name: 'project_name', - project_url: 'somewhere.com', + project_url: 'example.gitlab.com', commit: { status: status, @@ -20,42 +20,38 @@ describe SlackService::BuildMessage do } end - context 'succeeded' do + let(:message) { build_message } + + context 'build succeeded' do let(:status) { 'success' } let(:color) { 'good' } let(:duration) { 10 } - + let(:message) { build_message('passed') } + it 'returns a message with information about succeeded build' do - message = '<somewhere.com|project_name>: Commit <somewhere.com/commit/97de212e80737a608d939f648d959671fb0a0142/builds|97de212e> of <somewhere.com/commits/develop|develop> branch by hacker passed in 10 seconds' expect(subject.pretext).to be_empty expect(subject.fallback).to eq(message) expect(subject.attachments).to eq([text: message, color: color]) end end - context 'failed' do + context 'build failed' do let(:status) { 'failed' } let(:color) { 'danger' } let(:duration) { 10 } it 'returns a message with information about failed build' do - message = '<somewhere.com|project_name>: Commit <somewhere.com/commit/97de212e80737a608d939f648d959671fb0a0142/builds|97de212e> of <somewhere.com/commits/develop|develop> branch by hacker failed in 10 seconds' expect(subject.pretext).to be_empty expect(subject.fallback).to eq(message) expect(subject.attachments).to eq([text: message, color: color]) end - end - - describe '#seconds_name' do - let(:status) { 'failed' } - let(:color) { 'danger' } - let(:duration) { 1 } + end - it 'returns seconds as singular when there is only one' do - message = '<somewhere.com|project_name>: Commit <somewhere.com/commit/97de212e80737a608d939f648d959671fb0a0142/builds|97de212e> of <somewhere.com/commits/develop|develop> branch by hacker failed in 1 second' - expect(subject.pretext).to be_empty - expect(subject.fallback).to eq(message) - expect(subject.attachments).to eq([text: message, color: color]) - end + def build_message(status_text = status) + "<example.gitlab.com|project_name>:" \ + " Commit <example.gitlab.com/commit/" \ + "97de212e80737a608d939f648d959671fb0a0142/builds|97de212e>" \ + " of <example.gitlab.com/commits/develop|develop> branch" \ + " by hacker #{status_text} in #{duration} #{'second'.pluralize(duration)}" end end diff --git a/spec/models/project_services/slack_service/pipeline_message_spec.rb b/spec/models/project_services/slack_service/pipeline_message_spec.rb new file mode 100644 index 00000000000..babb3909f56 --- /dev/null +++ b/spec/models/project_services/slack_service/pipeline_message_spec.rb @@ -0,0 +1,55 @@ +require 'spec_helper' + +describe SlackService::PipelineMessage do + subject { SlackService::PipelineMessage.new(args) } + + let(:args) do + { + object_attributes: { + id: 123, + sha: '97de212e80737a608d939f648d959671fb0a0142', + tag: false, + ref: 'develop', + status: status, + duration: duration + }, + project: { path_with_namespace: 'project_name', + web_url: 'example.gitlab.com' }, + commit: { author_name: 'hacker' } + } + end + + let(:message) { build_message } + + context 'pipeline succeeded' do + let(:status) { 'success' } + let(:color) { 'good' } + let(:duration) { 10 } + let(:message) { build_message('passed') } + + it 'returns a message with information about succeeded build' do + expect(subject.pretext).to be_empty + expect(subject.fallback).to eq(message) + expect(subject.attachments).to eq([text: message, color: color]) + end + end + + context 'pipeline failed' do + let(:status) { 'failed' } + let(:color) { 'danger' } + let(:duration) { 10 } + + it 'returns a message with information about failed build' do + expect(subject.pretext).to be_empty + expect(subject.fallback).to eq(message) + expect(subject.attachments).to eq([text: message, color: color]) + end + end + + def build_message(status_text = status) + "<example.gitlab.com|project_name>:" \ + " Pipeline <example.gitlab.com/pipelines/123|97de212e>" \ + " of <example.gitlab.com/commits/develop|develop> branch" \ + " by hacker #{status_text} in #{duration} #{'second'.pluralize(duration)}" + end +end diff --git a/spec/models/project_services/slack_service_spec.rb b/spec/models/project_services/slack_service_spec.rb index 28af68d13b4..c07a70a8069 100644 --- a/spec/models/project_services/slack_service_spec.rb +++ b/spec/models/project_services/slack_service_spec.rb @@ -1,26 +1,9 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string(255) -# title :string(255) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# active :boolean default(FALSE), not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# - require 'spec_helper' describe SlackService, models: true do + let(:slack) { SlackService.new } + let(:webhook_url) { 'https://example.gitlab.com/' } + describe "Associations" do it { is_expected.to belong_to :project } it { is_expected.to have_one :service_hook } @@ -42,15 +25,14 @@ describe SlackService, models: true do end describe "Execute" do - let(:slack) { SlackService.new } let(:user) { create(:user) } let(:project) { create(:project) } + let(:username) { 'slack_username' } + let(:channel) { 'slack_channel' } + let(:push_sample_data) do Gitlab::DataBuilder::Push.build_sample(project, user) end - let(:webhook_url) { 'https://hooks.slack.com/services/SVRWFV0VVAR97N/B02R25XN3/ZBqu7xMupaEEICInN685' } - let(:username) { 'slack_username' } - let(:channel) { 'slack_channel' } before do allow(slack).to receive_messages( @@ -212,10 +194,8 @@ describe SlackService, models: true do end describe "Note events" do - let(:slack) { SlackService.new } let(:user) { create(:user) } let(:project) { create(:project, creator_id: user.id) } - let(:webhook_url) { 'https://hooks.slack.com/services/SVRWFV0VVAR97N/B02R25XN3/ZBqu7xMupaEEICInN685' } before do allow(slack).to receive_messages( @@ -285,4 +265,63 @@ describe SlackService, models: true do end end end + + describe 'Pipeline events' do + let(:user) { create(:user) } + let(:project) { create(:project) } + + let(:pipeline) do + create(:ci_pipeline, + project: project, status: status, + sha: project.commit.sha, ref: project.default_branch) + end + + before do + allow(slack).to receive_messages( + project: project, + service_hook: true, + webhook: webhook_url + ) + end + + shared_examples 'call Slack API' do + before do + WebMock.stub_request(:post, webhook_url) + end + + it 'calls Slack API for pipeline events' do + data = Gitlab::DataBuilder::Pipeline.build(pipeline) + slack.execute(data) + + expect(WebMock).to have_requested(:post, webhook_url).once + end + end + + context 'with failed pipeline' do + let(:status) { 'failed' } + + it_behaves_like 'call Slack API' + end + + context 'with succeeded pipeline' do + let(:status) { 'success' } + + context 'with default to notify_only_broken_pipelines' do + it 'does not call Slack API for pipeline events' do + data = Gitlab::DataBuilder::Pipeline.build(pipeline) + result = slack.execute(data) + + expect(result).to be_falsy + end + end + + context 'with setting notify_only_broken_pipelines to false' do + before do + slack.notify_only_broken_pipelines = false + end + + it_behaves_like 'call Slack API' + end + end + end end diff --git a/spec/models/project_services/teamcity_service_spec.rb b/spec/models/project_services/teamcity_service_spec.rb index 474715d24c3..f7e878844dc 100644 --- a/spec/models/project_services/teamcity_service_spec.rb +++ b/spec/models/project_services/teamcity_service_spec.rb @@ -1,23 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string(255) -# title :string(255) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# active :boolean default(FALSE), not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# - require 'spec_helper' describe TeamcityService, models: true do diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 4a41fafb84d..a388ff703a6 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -6,6 +6,7 @@ describe Project, models: true do it { is_expected.to belong_to(:namespace) } it { is_expected.to belong_to(:creator).class_name('User') } it { is_expected.to have_many(:users) } + it { is_expected.to have_many(:services) } it { is_expected.to have_many(:events).dependent(:destroy) } it { is_expected.to have_many(:merge_requests).dependent(:destroy) } it { is_expected.to have_many(:issues).dependent(:destroy) } @@ -24,6 +25,30 @@ 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_one(:board).dependent(:destroy) } + it { is_expected.to have_one(:campfire_service).dependent(:destroy) } + it { is_expected.to have_one(:drone_ci_service).dependent(:destroy) } + it { is_expected.to have_one(:emails_on_push_service).dependent(:destroy) } + it { is_expected.to have_one(:builds_email_service).dependent(:destroy) } + it { is_expected.to have_one(:emails_on_push_service).dependent(:destroy) } + it { is_expected.to have_one(:irker_service).dependent(:destroy) } + it { is_expected.to have_one(:pivotaltracker_service).dependent(:destroy) } + it { is_expected.to have_one(:hipchat_service).dependent(:destroy) } + it { is_expected.to have_one(:flowdock_service).dependent(:destroy) } + it { is_expected.to have_one(:assembla_service).dependent(:destroy) } + it { is_expected.to have_one(:gemnasium_service).dependent(:destroy) } + it { is_expected.to have_one(:buildkite_service).dependent(:destroy) } + it { is_expected.to have_one(:bamboo_service).dependent(:destroy) } + it { is_expected.to have_one(:teamcity_service).dependent(:destroy) } + it { is_expected.to have_one(:jira_service).dependent(:destroy) } + it { is_expected.to have_one(:redmine_service).dependent(:destroy) } + it { is_expected.to have_one(:custom_issue_tracker_service).dependent(:destroy) } + it { is_expected.to have_one(:bugzilla_service).dependent(:destroy) } + it { is_expected.to have_one(:gitlab_issue_tracker_service).dependent(:destroy) } + it { is_expected.to have_one(:external_wiki_service).dependent(:destroy) } + it { is_expected.to have_one(:project_feature).dependent(:destroy) } + it { is_expected.to have_one(:import_data).class_name('ProjectImportData').dependent(:destroy) } + it { is_expected.to have_one(:last_event).class_name('Event') } + it { is_expected.to have_one(:forked_from_project).through(:forked_project_link) } it { is_expected.to have_many(:commit_statuses) } it { is_expected.to have_many(:pipelines) } it { is_expected.to have_many(:builds) } @@ -31,9 +56,16 @@ describe Project, models: true do it { is_expected.to have_many(:runners) } it { is_expected.to have_many(:variables) } it { is_expected.to have_many(:triggers) } + it { is_expected.to have_many(:labels).dependent(:destroy) } + it { is_expected.to have_many(:users_star_projects).dependent(:destroy) } it { is_expected.to have_many(:environments).dependent(:destroy) } it { is_expected.to have_many(:deployments).dependent(:destroy) } it { is_expected.to have_many(:todos).dependent(:destroy) } + it { is_expected.to have_many(:releases).dependent(:destroy) } + it { is_expected.to have_many(:lfs_objects_projects).dependent(:destroy) } + it { is_expected.to have_many(:project_group_links).dependent(:destroy) } + it { is_expected.to have_many(:notification_settings).dependent(:destroy) } + it { is_expected.to have_many(:forks).through(:forked_project_links) } describe '#members & #requesters' do let(:project) { create(:project) } @@ -178,7 +210,7 @@ describe Project, models: true do expect(project.runners_token).not_to eq('') end - it 'does not set an random toke if one provided' do + it 'does not set an random token if one provided' do project = FactoryGirl.create :empty_project, runners_token: 'my-token' expect(project.runners_token).to eq('my-token') end @@ -276,20 +308,23 @@ describe Project, models: true do end describe 'last_activity methods' do - let(:project) { create(:project) } - let(:last_event) { double(created_at: Time.now) } + let(:timestamp) { Time.now - 2.hours } + let(:project) { create(:project, created_at: timestamp, updated_at: timestamp) } describe 'last_activity' do it 'alias last_activity to last_event' do - allow(project).to receive(:last_event).and_return(last_event) + last_event = create(:event, project: project) + expect(project.last_activity).to eq(last_event) end end describe 'last_activity_date' do it 'returns the creation date of the project\'s last event if present' do - create(:event, project: project) - expect(project.last_activity_at.to_i).to eq(last_event.created_at.to_i) + expect_any_instance_of(Event).to receive(:try_obtain_lease).and_return(true) + new_event = create(:event, project: project, created_at: Time.now) + + expect(project.last_activity_at.to_i).to eq(new_event.created_at.to_i) end it 'returns the project\'s last update date if it has no events' do @@ -1385,6 +1420,68 @@ describe Project, models: true do end end + describe '#lfs_enabled?' do + let(:project) { create(:project) } + + shared_examples 'project overrides group' do + it 'returns true when enabled in project' do + project.update_attribute(:lfs_enabled, true) + + expect(project.lfs_enabled?).to be_truthy + end + + it 'returns false when disabled in project' do + project.update_attribute(:lfs_enabled, false) + + expect(project.lfs_enabled?).to be_falsey + end + + it 'returns the value from the namespace, when no value is set in project' do + expect(project.lfs_enabled?).to eq(project.namespace.lfs_enabled?) + end + end + + context 'LFS disabled in group' do + before do + project.namespace.update_attribute(:lfs_enabled, false) + enable_lfs + end + + it_behaves_like 'project overrides group' + end + + context 'LFS enabled in group' do + before do + project.namespace.update_attribute(:lfs_enabled, true) + enable_lfs + end + + it_behaves_like 'project overrides group' + end + + describe 'LFS disabled globally' do + shared_examples 'it always returns false' do + it do + expect(project.lfs_enabled?).to be_falsey + expect(project.namespace.lfs_enabled?).to be_falsey + end + end + + context 'when no values are set' do + it_behaves_like 'it always returns false' + end + + context 'when all values are set to true' do + before do + project.namespace.update_attribute(:lfs_enabled, true) + project.update_attribute(:lfs_enabled, true) + end + + it_behaves_like 'it always returns false' + end + end + end + describe '.where_paths_in' do context 'without any paths' do it 'returns an empty relation' do @@ -1497,4 +1594,60 @@ describe Project, models: true do project.change_head(project.default_branch) end end + + describe '#pushes_since_gc' do + let(:project) { create(:project) } + + after do + project.reset_pushes_since_gc + end + + context 'without any pushes' do + it 'returns 0' do + expect(project.pushes_since_gc).to eq(0) + end + end + + context 'with a number of pushes' do + it 'returns the number of pushes' do + 3.times { project.increment_pushes_since_gc } + + expect(project.pushes_since_gc).to eq(3) + end + end + end + + describe '#increment_pushes_since_gc' do + let(:project) { create(:project) } + + after do + project.reset_pushes_since_gc + end + + it 'increments the number of pushes since the last GC' do + 3.times { project.increment_pushes_since_gc } + + expect(project.pushes_since_gc).to eq(3) + end + end + + describe '#reset_pushes_since_gc' do + let(:project) { create(:project) } + + after do + project.reset_pushes_since_gc + end + + it 'resets the number of pushes since the last GC' do + 3.times { project.increment_pushes_since_gc } + + project.reset_pushes_since_gc + + expect(project.pushes_since_gc).to eq(0) + end + end + + def enable_lfs + allow(Gitlab.config.lfs).to receive(:enabled).and_return(true) + end end diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb index afc7dc5db81..94681004c96 100644 --- a/spec/models/repository_spec.rb +++ b/spec/models/repository_spec.rb @@ -186,32 +186,6 @@ describe Repository, models: true do it { is_expected.to be_an String } it { expect(subject.lines[2]).to eq("master:CHANGELOG:188: - Feature: Replace teams with group membership\n") } end - - describe 'parsing result' do - subject { repository.parse_search_result(search_result) } - let(:search_result) { results.first } - - it { is_expected.to be_an OpenStruct } - it { expect(subject.filename).to eq('CHANGELOG') } - it { expect(subject.basename).to eq('CHANGELOG') } - it { expect(subject.ref).to eq('master') } - it { expect(subject.startline).to eq(186) } - it { expect(subject.data.lines[2]).to eq(" - Feature: Replace teams with group membership\n") } - - context "when filename has extension" do - let(:search_result) { "master:CONTRIBUTE.md:5:- [Contribute to GitLab](#contribute-to-gitlab)\n" } - - it { expect(subject.filename).to eq('CONTRIBUTE.md') } - it { expect(subject.basename).to eq('CONTRIBUTE') } - end - - context "when file under directory" do - let(:search_result) { "master:a/b/c.md:5:a b c\n" } - - it { expect(subject.filename).to eq('a/b/c.md') } - it { expect(subject.basename).to eq('a/b/c') } - end - end end describe "#changelog" do @@ -441,7 +415,7 @@ describe Repository, models: true do end end - describe '#commit_with_hooks' do + describe '#update_branch_with_hooks' do let(:old_rev) { '0b4bc9a49b562e85de7cc9e834518ea6828729b9' } # git rev-parse feature let(:new_rev) { 'a74ae73c1ccde9b974a70e82b901588071dc142a' } # commit whose parent is old_rev @@ -454,31 +428,64 @@ describe Repository, models: true do it 'runs without errors' do expect do - repository.commit_with_hooks(user, 'feature') { new_rev } + repository.update_branch_with_hooks(user, 'feature') { new_rev } end.not_to raise_error end it 'ensures the autocrlf Git option is set to :input' do expect(repository).to receive(:update_autocrlf_option) - repository.commit_with_hooks(user, 'feature') { new_rev } + repository.update_branch_with_hooks(user, 'feature') { new_rev } end context "when the branch wasn't empty" do it 'updates the head' do expect(repository.find_branch('feature').target.id).to eq(old_rev) - repository.commit_with_hooks(user, 'feature') { new_rev } + repository.update_branch_with_hooks(user, 'feature') { new_rev } expect(repository.find_branch('feature').target.id).to eq(new_rev) end end end + context 'when the update adds more than one commit' do + it 'runs without errors' do + old_rev = '33f3729a45c02fc67d00adb1b8bca394b0e761d9' + + # old_rev is an ancestor of new_rev + expect(repository.rugged.merge_base(old_rev, new_rev)).to eq(old_rev) + + # old_rev is not a direct ancestor (parent) of new_rev + expect(repository.rugged.lookup(new_rev).parent_ids).not_to include(old_rev) + + branch = 'feature-ff-target' + repository.add_branch(user, branch, old_rev) + + expect { repository.update_branch_with_hooks(user, branch) { new_rev } }.not_to raise_error + end + end + + context 'when the update would remove commits from the target branch' do + it 'raises an exception' do + branch = 'master' + old_rev = repository.find_branch(branch).target.sha + + # The 'master' branch is NOT an ancestor of new_rev. + expect(repository.rugged.merge_base(old_rev, new_rev)).not_to eq(old_rev) + + # Updating 'master' to new_rev would lose the commits on 'master' that + # are not contained in new_rev. This should not be allowed. + expect do + repository.update_branch_with_hooks(user, branch) { new_rev } + end.to raise_error(Repository::CommitError) + end + end + context 'when pre hooks failed' do it 'gets an error' do allow_any_instance_of(Gitlab::Git::Hook).to receive(:trigger).and_return([false, '']) expect do - repository.commit_with_hooks(user, 'feature') { new_rev } + repository.update_branch_with_hooks(user, 'feature') { new_rev } end.to raise_error(GitHooksService::PreReceiveError) end end @@ -497,7 +504,7 @@ describe Repository, models: true do expect(repository).to receive(:expire_has_visible_content_cache) expect(repository).to receive(:expire_branch_count_cache) - repository.commit_with_hooks(user, 'new-feature') { new_rev } + repository.update_branch_with_hooks(user, 'new-feature') { new_rev } end end |