summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
Diffstat (limited to 'spec')
-rw-r--r--spec/benchmarks/finders/issues_finder_spec.rb55
-rw-r--r--spec/controllers/abuse_reports_controller_spec.rb36
-rw-r--r--spec/controllers/autocomplete_controller_spec.rb9
-rw-r--r--spec/controllers/commit_controller_spec.rb15
-rw-r--r--spec/controllers/projects_controller_spec.rb16
-rw-r--r--spec/controllers/snippets_controller_spec.rb233
-rw-r--r--spec/factories.rb12
-rw-r--r--spec/features/admin/admin_users_spec.rb7
-rw-r--r--spec/finders/projects_finder_spec.rb17
-rw-r--r--spec/helpers/application_helper_spec.rb18
-rw-r--r--spec/helpers/issues_helper_spec.rb26
-rw-r--r--spec/lib/ci/gitlab_ci_yaml_processor_spec.rb6
-rw-r--r--spec/lib/gitlab/lfs/lfs_router_spec.rb545
-rw-r--r--spec/lib/gitlab/markdown/filter/label_reference_filter_spec.rb6
-rw-r--r--spec/lib/gitlab/sherlock/transaction_spec.rb13
-rw-r--r--spec/lib/votes_spec.rb188
-rw-r--r--spec/mailers/notify_spec.rb65
-rw-r--r--spec/models/ci/project_services/mail_service_spec.rb62
-rw-r--r--spec/models/concerns/strip_attribute_spec.rb20
-rw-r--r--spec/models/merge_request_spec.rb25
-rw-r--r--spec/models/note_spec.rb87
-rw-r--r--spec/models/project_services/jira_service_spec.rb6
-rw-r--r--spec/models/project_spec.rb11
-rw-r--r--spec/requests/api/tags_spec.rb71
-rw-r--r--spec/services/ci/create_commit_service_spec.rb24
-rw-r--r--spec/services/create_release_service_spec.rb34
-rw-r--r--spec/services/issues/close_service_spec.rb4
-rw-r--r--spec/services/issues/update_service_spec.rb88
-rw-r--r--spec/services/merge_requests/close_service_spec.rb4
-rw-r--r--spec/services/merge_requests/merge_service_spec.rb5
-rw-r--r--spec/services/merge_requests/reopen_service_spec.rb4
-rw-r--r--spec/services/merge_requests/update_service_spec.rb57
-rw-r--r--spec/services/notes/create_service_spec.rb34
-rw-r--r--spec/services/notification_service_spec.rb345
-rw-r--r--spec/services/update_release_service_spec.rb34
-rw-r--r--spec/spec_helper.rb1
-rw-r--r--spec/tasks/gitlab/backup_rake_spec.rb14
-rw-r--r--spec/workers/email_receiver_worker_spec.rb14
38 files changed, 1397 insertions, 814 deletions
diff --git a/spec/benchmarks/finders/issues_finder_spec.rb b/spec/benchmarks/finders/issues_finder_spec.rb
new file mode 100644
index 00000000000..b57a33004a4
--- /dev/null
+++ b/spec/benchmarks/finders/issues_finder_spec.rb
@@ -0,0 +1,55 @@
+require 'spec_helper'
+
+describe IssuesFinder, benchmark: true do
+ describe '#execute' do
+ let(:user) { create(:user) }
+ let(:project) { create(:project, :public) }
+
+ let(:label1) { create(:label, project: project, title: 'A') }
+ let(:label2) { create(:label, project: project, title: 'B') }
+
+ before do
+ 10.times do |n|
+ issue = create(:issue, author: user, project: project)
+
+ if n > 4
+ create(:label_link, label: label1, target: issue)
+ create(:label_link, label: label2, target: issue)
+ end
+ end
+ end
+
+ describe 'retrieving issues without labels' do
+ let(:finder) do
+ IssuesFinder.new(user, scope: 'all', label_name: Label::None.title,
+ state: 'opened')
+ end
+
+ benchmark_subject { finder.execute }
+
+ it { is_expected.to iterate_per_second(2000) }
+ end
+
+ describe 'retrieving issues with labels' do
+ let(:finder) do
+ IssuesFinder.new(user, scope: 'all', label_name: label1.title,
+ state: 'opened')
+ end
+
+ benchmark_subject { finder.execute }
+
+ it { is_expected.to iterate_per_second(1000) }
+ end
+
+ describe 'retrieving issues for a single project' do
+ let(:finder) do
+ IssuesFinder.new(user, scope: 'all', label_name: Label::None.title,
+ state: 'opened', project_id: project.id)
+ end
+
+ benchmark_subject { finder.execute }
+
+ it { is_expected.to iterate_per_second(2000) }
+ end
+ end
+end
diff --git a/spec/controllers/abuse_reports_controller_spec.rb b/spec/controllers/abuse_reports_controller_spec.rb
index 0faab8d7ff0..15824a1c67f 100644
--- a/spec/controllers/abuse_reports_controller_spec.rb
+++ b/spec/controllers/abuse_reports_controller_spec.rb
@@ -18,27 +18,31 @@ describe AbuseReportsController do
end
it "sends a notification email" do
- post :create,
- abuse_report: {
- user_id: user.id,
- message: message
- }
-
- email = ActionMailer::Base.deliveries.last
-
- expect(email.to).to eq([admin_email])
- expect(email.subject).to include(user.username)
- expect(email.text_part.body).to include(message)
- end
-
- it "saves the abuse report" do
- expect do
+ perform_enqueued_jobs do
post :create,
abuse_report: {
user_id: user.id,
message: message
}
- end.to change { AbuseReport.count }.by(1)
+
+ email = ActionMailer::Base.deliveries.last
+
+ expect(email.to).to eq([admin_email])
+ expect(email.subject).to include(user.username)
+ expect(email.text_part.body).to include(message)
+ end
+ end
+
+ it "saves the abuse report" do
+ perform_enqueued_jobs do
+ expect do
+ post :create,
+ abuse_report: {
+ user_id: user.id,
+ message: message
+ }
+ end.to change { AbuseReport.count }.by(1)
+ end
end
end
diff --git a/spec/controllers/autocomplete_controller_spec.rb b/spec/controllers/autocomplete_controller_spec.rb
index aa8d6cb807f..85379a8e984 100644
--- a/spec/controllers/autocomplete_controller_spec.rb
+++ b/spec/controllers/autocomplete_controller_spec.rb
@@ -114,7 +114,7 @@ describe AutocompleteController do
get(:users, project_id: project.id)
end
- it { expect(response.status).to eq(302) }
+ it { expect(response.status).to eq(404) }
end
describe 'GET #users with unknown project' do
@@ -122,7 +122,7 @@ describe AutocompleteController do
get(:users, project_id: 'unknown')
end
- it { expect(response.status).to eq(302) }
+ it { expect(response.status).to eq(404) }
end
describe 'GET #users with inaccessible group' do
@@ -131,7 +131,7 @@ describe AutocompleteController do
get(:users, group_id: user.namespace.id)
end
- it { expect(response.status).to eq(302) }
+ it { expect(response.status).to eq(404) }
end
describe 'GET #users with no project' do
@@ -139,7 +139,8 @@ describe AutocompleteController do
get(:users)
end
- it { expect(response.status).to eq(302) }
+ it { expect(body).to be_kind_of(Array) }
+ it { expect(body.size).to eq 0 }
end
end
end
diff --git a/spec/controllers/commit_controller_spec.rb b/spec/controllers/commit_controller_spec.rb
index bb3d87f3840..5337a69e84b 100644
--- a/spec/controllers/commit_controller_spec.rb
+++ b/spec/controllers/commit_controller_spec.rb
@@ -69,6 +69,21 @@ describe Projects::CommitController do
expect(response.body).to start_with("diff --git")
end
+
+ it "should really only be a git diff without whitespace changes" do
+ get(:show,
+ namespace_id: project.namespace.to_param,
+ project_id: project.to_param,
+ id: '66eceea0db202bb39c4e445e8ca28689645366c5',
+ # id: commit.id,
+ format: format,
+ w: 1)
+
+ expect(response.body).to start_with("diff --git")
+ # without whitespace option, there are more than 2 diff_splits
+ diff_splits = assigns(:diffs)[0].diff.split("\n")
+ expect(diff_splits.length).to be <= 2
+ end
end
describe "as patch" do
diff --git a/spec/controllers/projects_controller_spec.rb b/spec/controllers/projects_controller_spec.rb
index 4bb47c6b025..665526fde93 100644
--- a/spec/controllers/projects_controller_spec.rb
+++ b/spec/controllers/projects_controller_spec.rb
@@ -88,6 +88,22 @@ describe ProjectsController do
end
end
+ describe "#destroy" do
+ let(:admin) { create(:admin) }
+
+ it "redirects to the dashboard" do
+ controller.instance_variable_set(:@project, project)
+ sign_in(admin)
+
+ orig_id = project.id
+ delete :destroy, namespace_id: project.namespace.path, id: project.path
+
+ expect { Project.find(orig_id) }.to raise_error(ActiveRecord::RecordNotFound)
+ expect(response.status).to eq(302)
+ expect(response).to redirect_to(dashboard_projects_path)
+ end
+ end
+
describe "POST #toggle_star" do
it "toggles star if user is signed in" do
sign_in(user)
diff --git a/spec/controllers/snippets_controller_spec.rb b/spec/controllers/snippets_controller_spec.rb
new file mode 100644
index 00000000000..b3dcb52c500
--- /dev/null
+++ b/spec/controllers/snippets_controller_spec.rb
@@ -0,0 +1,233 @@
+require 'spec_helper'
+
+describe SnippetsController do
+ describe 'GET #show' do
+ let(:user) { create(:user) }
+
+ context 'when the personal snippet is private' do
+ let(:personal_snippet) { create(:personal_snippet, :private, author: user) }
+
+ context 'when signed in' do
+ before do
+ sign_in(user)
+ end
+
+ context 'when signed in user is not the author' do
+ let(:other_author) { create(:author) }
+ let(:other_personal_snippet) { create(:personal_snippet, :private, author: other_author) }
+
+ it 'responds with status 404' do
+ get :show, id: other_personal_snippet.to_param
+
+ expect(response.status).to eq(404)
+ end
+ end
+
+ context 'when signed in user is the author' do
+ it 'renders the snippet' do
+ get :show, id: personal_snippet.to_param
+
+ expect(assigns(:snippet)).to eq(personal_snippet)
+ expect(response.status).to eq(200)
+ end
+ end
+ end
+
+ context 'when not signed in' do
+ it 'redirects to the sign in page' do
+ get :show, id: personal_snippet.to_param
+
+ expect(response).to redirect_to(new_user_session_path)
+ end
+ end
+ end
+
+ context 'when the personal snippet is internal' do
+ let(:personal_snippet) { create(:personal_snippet, :internal, author: user) }
+
+ context 'when signed in' do
+ before do
+ sign_in(user)
+ end
+
+ it 'renders the snippet' do
+ get :show, id: personal_snippet.to_param
+
+ expect(assigns(:snippet)).to eq(personal_snippet)
+ expect(response.status).to eq(200)
+ end
+ end
+
+ context 'when not signed in' do
+ it 'redirects to the sign in page' do
+ get :show, id: personal_snippet.to_param
+
+ expect(response).to redirect_to(new_user_session_path)
+ end
+ end
+ end
+
+ context 'when the personal snippet is public' do
+ let(:personal_snippet) { create(:personal_snippet, :public, author: user) }
+
+ context 'when signed in' do
+ before do
+ sign_in(user)
+ end
+
+ it 'renders the snippet' do
+ get :show, id: personal_snippet.to_param
+
+ expect(assigns(:snippet)).to eq(personal_snippet)
+ expect(response.status).to eq(200)
+ end
+ end
+
+ context 'when not signed in' do
+ it 'renders the snippet' do
+ get :show, id: personal_snippet.to_param
+
+ expect(assigns(:snippet)).to eq(personal_snippet)
+ expect(response.status).to eq(200)
+ end
+ end
+ end
+
+ context 'when the personal snippet does not exist' do
+ context 'when signed in' do
+ before do
+ sign_in(user)
+ end
+
+ it 'responds with status 404' do
+ get :show, id: 'doesntexist'
+
+ expect(response.status).to eq(404)
+ end
+ end
+
+ context 'when not signed in' do
+ it 'responds with status 404' do
+ get :show, id: 'doesntexist'
+
+ expect(response.status).to eq(404)
+ end
+ end
+ end
+ end
+
+ describe 'GET #raw' do
+ let(:user) { create(:user) }
+
+ context 'when the personal snippet is private' do
+ let(:personal_snippet) { create(:personal_snippet, :private, author: user) }
+
+ context 'when signed in' do
+ before do
+ sign_in(user)
+ end
+
+ context 'when signed in user is not the author' do
+ let(:other_author) { create(:author) }
+ let(:other_personal_snippet) { create(:personal_snippet, :private, author: other_author) }
+
+ it 'responds with status 404' do
+ get :raw, id: other_personal_snippet.to_param
+
+ expect(response.status).to eq(404)
+ end
+ end
+
+ context 'when signed in user is the author' do
+ it 'renders the raw snippet' do
+ get :raw, id: personal_snippet.to_param
+
+ expect(assigns(:snippet)).to eq(personal_snippet)
+ expect(response.status).to eq(200)
+ end
+ end
+ end
+
+ context 'when not signed in' do
+ it 'redirects to the sign in page' do
+ get :raw, id: personal_snippet.to_param
+
+ expect(response).to redirect_to(new_user_session_path)
+ end
+ end
+ end
+
+ context 'when the personal snippet is internal' do
+ let(:personal_snippet) { create(:personal_snippet, :internal, author: user) }
+
+ context 'when signed in' do
+ before do
+ sign_in(user)
+ end
+
+ it 'renders the raw snippet' do
+ get :raw, id: personal_snippet.to_param
+
+ expect(assigns(:snippet)).to eq(personal_snippet)
+ expect(response.status).to eq(200)
+ end
+ end
+
+ context 'when not signed in' do
+ it 'redirects to the sign in page' do
+ get :raw, id: personal_snippet.to_param
+
+ expect(response).to redirect_to(new_user_session_path)
+ end
+ end
+ end
+
+ context 'when the personal snippet is public' do
+ let(:personal_snippet) { create(:personal_snippet, :public, author: user) }
+
+ context 'when signed in' do
+ before do
+ sign_in(user)
+ end
+
+ it 'renders the raw snippet' do
+ get :raw, id: personal_snippet.to_param
+
+ expect(assigns(:snippet)).to eq(personal_snippet)
+ expect(response.status).to eq(200)
+ end
+ end
+
+ context 'when not signed in' do
+ it 'renders the raw snippet' do
+ get :raw, id: personal_snippet.to_param
+
+ expect(assigns(:snippet)).to eq(personal_snippet)
+ expect(response.status).to eq(200)
+ end
+ end
+ end
+
+ context 'when the personal snippet does not exist' do
+ context 'when signed in' do
+ before do
+ sign_in(user)
+ end
+
+ it 'responds with status 404' do
+ get :raw, id: 'doesntexist'
+
+ expect(response.status).to eq(404)
+ end
+ end
+
+ context 'when not signed in' do
+ it 'responds with status 404' do
+ get :raw, id: 'doesntexist'
+
+ expect(response.status).to eq(404)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/factories.rb b/spec/factories.rb
index 200f18f660d..4bf93adabe2 100644
--- a/spec/factories.rb
+++ b/spec/factories.rb
@@ -165,6 +165,18 @@ FactoryGirl.define do
title
content
file_name
+
+ trait :public do
+ visibility_level Gitlab::VisibilityLevel::PUBLIC
+ end
+
+ trait :internal do
+ visibility_level Gitlab::VisibilityLevel::INTERNAL
+ end
+
+ trait :private do
+ visibility_level Gitlab::VisibilityLevel::PRIVATE
+ end
end
factory :snippet do
diff --git a/spec/features/admin/admin_users_spec.rb b/spec/features/admin/admin_users_spec.rb
index 4c756a8e732..86f01faffb4 100644
--- a/spec/features/admin/admin_users_spec.rb
+++ b/spec/features/admin/admin_users_spec.rb
@@ -87,13 +87,16 @@ describe "Admin::Users", feature: true do
end
it "should call send mail" do
- expect(Notify).to receive(:new_user_email)
+ expect_any_instance_of(NotificationService).to receive(:new_user)
click_button "Create user"
end
it "should send valid email to user with email & password" do
- click_button "Create user"
+ perform_enqueued_jobs do
+ click_button "Create user"
+ end
+
user = User.find_by(username: 'bang')
email = ActionMailer::Base.deliveries.last
expect(email.subject).to have_content('Account was created')
diff --git a/spec/finders/projects_finder_spec.rb b/spec/finders/projects_finder_spec.rb
index d1dede78f74..f32641ef0f6 100644
--- a/spec/finders/projects_finder_spec.rb
+++ b/spec/finders/projects_finder_spec.rb
@@ -3,10 +3,19 @@ require 'spec_helper'
describe ProjectsFinder do
describe '#execute' do
let(:user) { create(:user) }
+ let(:group) { create(:group) }
- let!(:private_project) { create(:project, :private) }
- let!(:internal_project) { create(:project, :internal) }
- let!(:public_project) { create(:project, :public) }
+ let!(:private_project) do
+ create(:project, :private, name: 'A', path: 'A')
+ end
+
+ let!(:internal_project) do
+ create(:project, :internal, group: group, name: 'B', path: 'B')
+ end
+
+ let!(:public_project) do
+ create(:project, :public, group: group, name: 'C', path: 'C')
+ end
let(:finder) { described_class.new }
@@ -38,8 +47,6 @@ describe ProjectsFinder do
end
describe 'with a group' do
- let(:group) { public_project.group }
-
describe 'without a user' do
subject { finder.execute(nil, group: group) }
diff --git a/spec/helpers/application_helper_spec.rb b/spec/helpers/application_helper_spec.rb
index 1dfae0fbd3f..0a64b70d6a6 100644
--- a/spec/helpers/application_helper_spec.rb
+++ b/spec/helpers/application_helper_spec.rb
@@ -59,7 +59,7 @@ describe ApplicationHelper do
avatar_url = "http://localhost/uploads/project/avatar/#{project.id}/banana_sample.gif"
expect(helper.project_icon("#{project.namespace.to_param}/#{project.to_param}").to_s).
- to eq "<img alt=\"Banana sample\" src=\"#{avatar_url}\" />"
+ to eq "<img src=\"#{avatar_url}\" alt=\"Banana sample\" />"
end
it 'should give uploaded icon when present' do
@@ -95,9 +95,9 @@ describe ApplicationHelper do
end
it 'should call gravatar_icon when no User exists with the given email' do
- expect(helper).to receive(:gravatar_icon).with('foo@example.com', 20)
+ expect(helper).to receive(:gravatar_icon).with('foo@example.com', 20, 2)
- helper.avatar_icon('foo@example.com', 20)
+ helper.avatar_icon('foo@example.com', 20, 2)
end
describe 'using a User' do
@@ -150,15 +150,19 @@ describe ApplicationHelper do
stub_gravatar_setting(plain_url: 'http://example.local/?s=%{size}&hash=%{hash}')
expect(gravatar_icon(user_email, 20)).
- to eq('http://example.local/?s=20&hash=b58c6f14d292556214bd64909bcdb118')
+ to eq('http://example.local/?s=40&hash=b58c6f14d292556214bd64909bcdb118')
end
it 'accepts a custom size argument' do
- expect(helper.gravatar_icon(user_email, 64)).to include '?s=64'
+ expect(helper.gravatar_icon(user_email, 64)).to include '?s=128'
end
- it 'defaults size to 40 when given an invalid size' do
- expect(helper.gravatar_icon(user_email, nil)).to include '?s=40'
+ it 'defaults size to 40@2x when given an invalid size' do
+ expect(helper.gravatar_icon(user_email, nil)).to include '?s=80'
+ end
+
+ it 'accepts a scaling factor' do
+ expect(helper.gravatar_icon(user_email, 40, 3)).to include '?s=120'
end
it 'ignores case and surrounding whitespace' do
diff --git a/spec/helpers/issues_helper_spec.rb b/spec/helpers/issues_helper_spec.rb
index 78a6b631eb2..1f2c4ee77b5 100644
--- a/spec/helpers/issues_helper_spec.rb
+++ b/spec/helpers/issues_helper_spec.rb
@@ -127,4 +127,30 @@ describe IssuesHelper do
it { is_expected.to eq("!1, !2, or !3") }
end
+ describe "#url_to_emoji" do
+ it "returns url" do
+ expect(url_to_emoji("smile")).to include("emoji/1F604.png")
+ end
+ end
+
+ describe "#emoji_list" do
+ it "returns url" do
+ expect(emoji_list).to be_kind_of(Array)
+ end
+ end
+
+ describe "#note_active_class" do
+ before do
+ @note = create :note
+ @note1 = create :note
+ end
+
+ it "returns empty string for unauthenticated user" do
+ expect(note_active_class(Note.all, nil)).to eq("")
+ end
+
+ it "returns active string for author" do
+ expect(note_active_class(Note.all, @note.author)).to eq("active")
+ end
+ end
end
diff --git a/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb b/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb
index 7d90f9877c6..6f287719ba6 100644
--- a/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb
+++ b/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb
@@ -425,8 +425,12 @@ module Ci
end
describe "Error handling" do
+ it "fails to parse YAML" do
+ expect{GitlabCiYamlProcessor.new("invalid: yaml: test")}.to raise_error(Psych::SyntaxError)
+ end
+
it "indicates that object is invalid" do
- expect{GitlabCiYamlProcessor.new("invalid_yaml\n!ccdvlf%612334@@@@")}.to raise_error(GitlabCiYamlProcessor::ValidationError)
+ expect{GitlabCiYamlProcessor.new("invalid_yaml")}.to raise_error(GitlabCiYamlProcessor::ValidationError)
end
it "returns errors if tags parameter is invalid" do
diff --git a/spec/lib/gitlab/lfs/lfs_router_spec.rb b/spec/lib/gitlab/lfs/lfs_router_spec.rb
index cebcb5bc887..5b13d65c7c0 100644
--- a/spec/lib/gitlab/lfs/lfs_router_spec.rb
+++ b/spec/lib/gitlab/lfs/lfs_router_spec.rb
@@ -26,113 +26,52 @@ describe Gitlab::Lfs::Router do
let(:sample_oid) { "b68143e6463773b1b6c6fd009a76c32aeec041faff32ba2ed42fd7f708a17f80" }
let(:sample_size) { 499013 }
+ let(:respond_with_deprecated) {[ 501, { "Content-Type"=>"application/json; charset=utf-8" }, ["{\"message\":\"Server supports batch API only, please update your Git LFS client to version 1.0.1 and up.\",\"documentation_url\":\"#{Gitlab.config.gitlab.url}/help\"}"]]}
+ let(:respond_with_disabled) {[ 501, { "Content-Type"=>"application/json; charset=utf-8" }, ["{\"message\":\"Git LFS is not enabled on this GitLab server, contact your admin.\",\"documentation_url\":\"#{Gitlab.config.gitlab.url}/help\"}"]]}
describe 'when lfs is disabled' do
before do
allow(Gitlab.config.lfs).to receive(:enabled).and_return(false)
- env["PATH_INFO"] = "#{project.repository.path_with_namespace}.git/info/lfs/objects/#{sample_oid}"
+ env['REQUEST_METHOD'] = 'POST'
+ body = {
+ 'objects' => [
+ { 'oid' => '91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897',
+ 'size' => 1575078
+ },
+ { 'oid' => sample_oid,
+ 'size' => sample_size
+ }
+ ],
+ 'operation' => 'upload'
+ }.to_json
+ env['rack.input'] = StringIO.new(body)
+ env["PATH_INFO"] = "#{project.repository.path_with_namespace}.git/info/lfs/objects/batch"
end
it 'responds with 501' do
- respond_with_disabled = [ 501,
- { "Content-Type"=>"application/vnd.git-lfs+json" },
- ["{\"message\":\"Git LFS is not enabled on this GitLab server, contact your admin.\",\"documentation_url\":\"#{Gitlab.config.gitlab.url}/help\"}"]
- ]
expect(lfs_router_auth.try_call).to match_array(respond_with_disabled)
end
end
- describe 'when fetching lfs object' do
+ describe 'when fetching lfs object using deprecated API' do
before do
enable_lfs
- env['HTTP_ACCEPT'] = "application/vnd.git-lfs+json; charset=utf-8"
env["PATH_INFO"] = "#{project.repository.path_with_namespace}.git/info/lfs/objects/#{sample_oid}"
end
- describe 'when user is authenticated' do
- context 'and user has project download access' do
- before do
- @auth = authorize(user)
- env["HTTP_AUTHORIZATION"] = @auth
- project.lfs_objects << lfs_object
- project.team << [user, :master]
- end
-
- it "responds with status 200" do
- expect(lfs_router_auth.try_call.first).to eq(200)
- end
-
- it "responds with download hypermedia" do
- json_response = ActiveSupport::JSON.decode(lfs_router_auth.try_call.last.first)
-
- expect(json_response['_links']['download']['href']).to eq("#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}.git/gitlab-lfs/objects/#{sample_oid}")
- expect(json_response['_links']['download']['header']).to eq("Authorization" => @auth, "Accept" => "application/vnd.git-lfs+json; charset=utf-8")
- end
- end
-
- context 'and user does not have project access' do
- it "responds with status 403" do
- expect(lfs_router_auth.try_call.first).to eq(403)
- end
- end
- end
-
- describe 'when user is unauthenticated' do
- context 'and user does not have download access' do
- it "responds with status 401" do
- expect(lfs_router_noauth.try_call.first).to eq(401)
- end
- end
-
- context 'and user has download access' do
- before do
- project.team << [user, :master]
- end
-
- it "responds with status 401" do
- expect(lfs_router_noauth.try_call.first).to eq(401)
- end
- end
+ it 'responds with 501' do
+ expect(lfs_router_auth.try_call).to match_array(respond_with_deprecated)
end
+ end
- describe 'and project is public' do
- context 'and project has access to the lfs object' do
- before do
- public_project.lfs_objects << lfs_object
- end
-
- context 'and user is authenticated' do
- it "responds with status 200 and sends download hypermedia" do
- expect(lfs_router_public_auth.try_call.first).to eq(200)
- json_response = ActiveSupport::JSON.decode(lfs_router_public_auth.try_call.last.first)
-
- expect(json_response['_links']['download']['href']).to eq("#{Gitlab.config.gitlab.url}/#{public_project.path_with_namespace}.git/gitlab-lfs/objects/#{sample_oid}")
- expect(json_response['_links']['download']['header']).to eq("Accept" => "application/vnd.git-lfs+json; charset=utf-8")
- end
- end
-
- context 'and user is unauthenticated' do
- it "responds with status 200 and sends download hypermedia" do
- expect(lfs_router_public_noauth.try_call.first).to eq(200)
- json_response = ActiveSupport::JSON.decode(lfs_router_public_noauth.try_call.last.first)
-
- expect(json_response['_links']['download']['href']).to eq("#{Gitlab.config.gitlab.url}/#{public_project.path_with_namespace}.git/gitlab-lfs/objects/#{sample_oid}")
- expect(json_response['_links']['download']['header']).to eq("Accept" => "application/vnd.git-lfs+json; charset=utf-8")
- end
- end
- end
-
- context 'and project does not have access to the lfs object' do
- it "responds with status 404" do
- expect(lfs_router_public_auth.try_call.first).to eq(404)
- end
- end
+ describe 'when fetching lfs object' do
+ before do
+ enable_lfs
+ env['HTTP_ACCEPT'] = "application/vnd.git-lfs+json; charset=utf-8"
+ env["PATH_INFO"] = "#{project.repository.path_with_namespace}.git/gitlab-lfs/objects/#{sample_oid}"
end
describe 'and request comes from gitlab-workhorse' do
- before do
- env["PATH_INFO"] = "#{project.repository.path_with_namespace}.git/gitlab-lfs/objects/#{sample_oid}"
- end
context 'without user being authorized' do
it "responds with status 401" do
expect(lfs_router_noauth.try_call.first).to eq(401)
@@ -173,200 +112,376 @@ describe Gitlab::Lfs::Router do
end
end
end
+ end
- describe 'from a forked public project' do
- before do
- env['HTTP_ACCEPT'] = "application/vnd.git-lfs+json; charset=utf-8"
- env["PATH_INFO"] = "#{forked_project.repository.path_with_namespace}.git/info/lfs/objects/#{sample_oid}"
- end
+ describe 'when handling lfs request using deprecated API' do
+ before do
+ enable_lfs
+ env['REQUEST_METHOD'] = 'POST'
+ env["PATH_INFO"] = "#{project.repository.path_with_namespace}.git/info/lfs/objects"
+ end
+
+ it 'responds with 501' do
+ expect(lfs_router_auth.try_call).to match_array(respond_with_deprecated)
+ end
+ end
+
+ describe 'when handling lfs batch request' do
+ before do
+ enable_lfs
+ env['REQUEST_METHOD'] = 'POST'
+ env['PATH_INFO'] = "#{project.repository.path_with_namespace}.git/info/lfs/objects/batch"
+ end
+
+ describe 'download' do
+ describe 'when user is authenticated' do
+ before do
+ body = { 'operation' => 'download',
+ 'objects' => [
+ { 'oid' => sample_oid,
+ 'size' => sample_size
+ }]
+ }.to_json
+ env['rack.input'] = StringIO.new(body)
+ end
- context "when fetching a lfs object" do
- context "and user has project download access" do
+ describe 'when user has download access' do
before do
- public_project.lfs_objects << lfs_object
+ @auth = authorize(user)
+ env["HTTP_AUTHORIZATION"] = @auth
+ project.team << [user, :reporter]
end
- it "can download the lfs object" do
- expect(lfs_router_forked_auth.try_call.first).to eq(200)
- json_response = ActiveSupport::JSON.decode(lfs_router_forked_auth.try_call.last.first)
+ context 'when downloading an lfs object that is assigned to our project' do
+ before do
+ project.lfs_objects << lfs_object
+ end
+
+ it 'responds with status 200 and href to download' do
+ response = lfs_router_auth.try_call
+ expect(response.first).to eq(200)
+ response_body = ActiveSupport::JSON.decode(response.last.first)
- expect(json_response['_links']['download']['href']).to eq("#{Gitlab.config.gitlab.url}/#{forked_project.path_with_namespace}.git/gitlab-lfs/objects/#{sample_oid}")
- expect(json_response['_links']['download']['header']).to eq("Accept" => "application/vnd.git-lfs+json; charset=utf-8")
+ expect(response_body).to eq('objects' => [
+ { 'oid' => sample_oid,
+ 'size' => sample_size,
+ 'actions' => {
+ 'download' => {
+ 'href' => "#{project.http_url_to_repo}/gitlab-lfs/objects/#{sample_oid}",
+ 'header' => { 'Authorization' => @auth }
+ }
+ }
+ }])
+ end
end
- end
- context "and user is not authenticated but project is public" do
- before do
- public_project.lfs_objects << lfs_object
+ context 'when downloading an lfs object that is assigned to other project' do
+ before do
+ public_project.lfs_objects << lfs_object
+ end
+
+ it 'responds with status 200 and error message' do
+ response = lfs_router_auth.try_call
+ expect(response.first).to eq(200)
+ response_body = ActiveSupport::JSON.decode(response.last.first)
+
+ expect(response_body).to eq('objects' => [
+ { 'oid' => sample_oid,
+ 'size' => sample_size,
+ 'error' => {
+ 'code' => 404,
+ 'message' => "Object does not exist on the server or you don't have permissions to access it",
+ }
+ }])
+ end
end
- it "can download the lfs object" do
- expect(lfs_router_forked_auth.try_call.first).to eq(200)
+ context 'when downloading a lfs object that does not exist' do
+ before do
+ body = { 'operation' => 'download',
+ 'objects' => [
+ { 'oid' => '91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897',
+ 'size' => 1575078
+ }]
+ }.to_json
+ env['rack.input'] = StringIO.new(body)
+ end
+
+ it "responds with status 200 and error message" do
+ response = lfs_router_auth.try_call
+ expect(response.first).to eq(200)
+ response_body = ActiveSupport::JSON.decode(response.last.first)
+
+ expect(response_body).to eq('objects' => [
+ { 'oid' => '91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897',
+ 'size' => 1575078,
+ 'error' => {
+ 'code' => 404,
+ 'message' => "Object does not exist on the server or you don't have permissions to access it",
+ }
+ }])
+ end
+ end
+
+ context 'when downloading one new and one existing lfs object' do
+ before do
+ body = { 'operation' => 'download',
+ 'objects' => [
+ { 'oid' => '91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897',
+ 'size' => 1575078
+ },
+ { 'oid' => sample_oid,
+ 'size' => sample_size
+ }
+ ]
+ }.to_json
+ env['rack.input'] = StringIO.new(body)
+ project.lfs_objects << lfs_object
+ end
+
+ it "responds with status 200 with upload hypermedia link for the new object" do
+ response = lfs_router_auth.try_call
+ expect(response.first).to eq(200)
+ response_body = ActiveSupport::JSON.decode(response.last.first)
+
+ expect(response_body).to eq('objects' => [
+ { 'oid' => '91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897',
+ 'size' => 1575078,
+ 'error' => {
+ 'code' => 404,
+ 'message' => "Object does not exist on the server or you don't have permissions to access it",
+ }
+ },
+ { 'oid' => sample_oid,
+ 'size' => sample_size,
+ 'actions' => {
+ 'download' => {
+ 'href' => "#{project.http_url_to_repo}/gitlab-lfs/objects/#{sample_oid}",
+ 'header' => { 'Authorization' => @auth }
+ }
+ }
+ }])
+ end
end
end
- context "and user has project download access" do
+ context 'when user does is not member of the project' do
before do
- env["PATH_INFO"] = "#{forked_project.repository.path_with_namespace}.git/info/lfs/objects/91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897"
- @auth = ActionController::HttpAuthentication::Basic.encode_credentials(user.username, user.password)
+ @auth = authorize(user)
env["HTTP_AUTHORIZATION"] = @auth
- lfs_object_two = create(:lfs_object, :with_file, oid: "91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897", size: 1575078)
- public_project.lfs_objects << lfs_object_two
+ project.team << [user, :guest]
end
- it "can get a lfs object that is not in the forked project" do
- expect(lfs_router_forked_auth.try_call.first).to eq(200)
-
- json_response = ActiveSupport::JSON.decode(lfs_router_forked_auth.try_call.last.first)
- expect(json_response['_links']['download']['href']).to eq("#{Gitlab.config.gitlab.url}/#{forked_project.path_with_namespace}.git/gitlab-lfs/objects/91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897")
- expect(json_response['_links']['download']['header']).to eq("Accept" => "application/vnd.git-lfs+json; charset=utf-8", "Authorization" => @auth)
+ it 'responds with 403' do
+ expect(lfs_router_auth.try_call.first).to eq(403)
end
end
- context "and user has project download access" do
+ context 'when user does not have download access' do
before do
- env["PATH_INFO"] = "#{forked_project.repository.path_with_namespace}.git/info/lfs/objects/267c8b1d876743971e3a9978405818ff5ca731c4c870b06507619cd9b1847b6b"
- lfs_object_three = create(:lfs_object, :with_file, oid: "267c8b1d876743971e3a9978405818ff5ca731c4c870b06507619cd9b1847b6b", size: 127192524)
- project.lfs_objects << lfs_object_three
+ @auth = authorize(user)
+ env["HTTP_AUTHORIZATION"] = @auth
+ project.team << [user, :guest]
end
- it "cannot get a lfs object that is not in the project" do
- expect(lfs_router_forked_auth.try_call.first).to eq(404)
+ it 'responds with 403' do
+ expect(lfs_router_auth.try_call.first).to eq(403)
end
end
end
- end
- end
-
- describe 'when initiating pushing of the lfs object' do
- before do
- enable_lfs
- env['REQUEST_METHOD'] = 'POST'
- env["PATH_INFO"] = "#{project.repository.path_with_namespace}.git/info/lfs/objects/batch"
- end
-
- describe 'when user is authenticated' do
- before do
- body = { 'objects' => [{
- 'oid' => sample_oid,
- 'size' => sample_size
- }]
- }.to_json
- env['rack.input'] = StringIO.new(body)
- end
- describe 'when user has project push access' do
+ context 'when user is not authenticated' do
before do
- @auth = authorize(user)
- env["HTTP_AUTHORIZATION"] = @auth
- project.team << [user, :master]
+ body = { 'operation' => 'download',
+ 'objects' => [
+ { 'oid' => sample_oid,
+ 'size' => sample_size
+ }],
+
+ }.to_json
+ env['rack.input'] = StringIO.new(body)
end
- context 'when pushing an lfs object that already exists' do
+ describe 'is accessing public project' do
before do
public_project.lfs_objects << lfs_object
end
- it "responds with status 200 and links the object to the project" do
- response_body = lfs_router_auth.try_call.last
- response = ActiveSupport::JSON.decode(response_body.first)
+ it 'responds with status 200 and href to download' do
+ response = lfs_router_public_noauth.try_call
+ expect(response.first).to eq(200)
+ response_body = ActiveSupport::JSON.decode(response.last.first)
- expect(response['objects']).to be_kind_of(Array)
- expect(response['objects'].first['oid']).to eq(sample_oid)
- expect(response['objects'].first['size']).to eq(sample_size)
- expect(lfs_object.projects.pluck(:id)).to_not include(project.id)
- expect(lfs_object.projects.pluck(:id)).to include(public_project.id)
- expect(response['objects'].first).to have_key('_links')
+ expect(response_body).to eq('objects' => [
+ { 'oid' => sample_oid,
+ 'size' => sample_size,
+ 'actions' => {
+ 'download' => {
+ 'href' => "#{public_project.http_url_to_repo}/gitlab-lfs/objects/#{sample_oid}",
+ 'header' => {}
+ }
+ }
+ }])
end
end
- context 'when pushing a lfs object that does not exist' do
+ describe 'is accessing non-public project' do
before do
- body = {
- 'objects' => [{
- 'oid' => '91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897',
- 'size' => 1575078
- }]
- }.to_json
- env['rack.input'] = StringIO.new(body)
+ project.lfs_objects << lfs_object
end
- it "responds with status 200 and upload hypermedia link" do
- response = lfs_router_auth.try_call
- expect(response.first).to eq(200)
-
- response_body = ActiveSupport::JSON.decode(response.last.first)
- expect(response_body['objects']).to be_kind_of(Array)
- expect(response_body['objects'].first['oid']).to eq("91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897")
- expect(response_body['objects'].first['size']).to eq(1575078)
- expect(lfs_object.projects.pluck(:id)).not_to include(project.id)
- expect(response_body['objects'].first['_links']['upload']['href']).to eq("#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}.git/gitlab-lfs/objects/91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897/1575078")
- expect(response_body['objects'].first['_links']['upload']['header']).to eq("Authorization" => @auth)
+ it 'responds with authorization required' do
+ expect(lfs_router_noauth.try_call.first).to eq(401)
end
end
+ end
+ end
- context 'when pushing one new and one existing lfs object' do
+ describe 'upload' do
+ describe 'when user is authenticated' do
+ before do
+ body = { 'operation' => 'upload',
+ 'objects' => [
+ { 'oid' => sample_oid,
+ 'size' => sample_size
+ }]
+ }.to_json
+ env['rack.input'] = StringIO.new(body)
+ end
+
+ describe 'when user has project push access' do
before do
- body = {
- 'objects' => [
- { 'oid' => '91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897',
- 'size' => 1575078
- },
- { 'oid' => sample_oid,
- 'size' => sample_size
- }
- ]
- }.to_json
- env['rack.input'] = StringIO.new(body)
- public_project.lfs_objects << lfs_object
+ @auth = authorize(user)
+ env["HTTP_AUTHORIZATION"] = @auth
+ project.team << [user, :developer]
end
- it "responds with status 200 with upload hypermedia link for the new object" do
- response = lfs_router_auth.try_call
- expect(response.first).to eq(200)
+ context 'when pushing an lfs object that already exists' do
+ before do
+ public_project.lfs_objects << lfs_object
+ end
- response_body = ActiveSupport::JSON.decode(response.last.first)
- expect(response_body['objects']).to be_kind_of(Array)
+ it "responds with status 200 and links the object to the project" do
+ response_body = lfs_router_auth.try_call.last
+ response = ActiveSupport::JSON.decode(response_body.first)
+ expect(response['objects']).to be_kind_of(Array)
+ expect(response['objects'].first['oid']).to eq(sample_oid)
+ expect(response['objects'].first['size']).to eq(sample_size)
+ expect(lfs_object.projects.pluck(:id)).to_not include(project.id)
+ expect(lfs_object.projects.pluck(:id)).to include(public_project.id)
+ expect(response['objects'].first['actions']['upload']['href']).to eq("#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}.git/gitlab-lfs/objects/#{sample_oid}/#{sample_size}")
+ expect(response['objects'].first['actions']['upload']['header']).to eq('Authorization' => @auth)
+ end
+ end
- expect(response_body['objects'].first['oid']).to eq("91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897")
- expect(response_body['objects'].first['size']).to eq(1575078)
- expect(response_body['objects'].first['_links']['upload']['href']).to eq("#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}.git/gitlab-lfs/objects/91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897/1575078")
- expect(response_body['objects'].first['_links']['upload']['header']).to eq("Authorization" => @auth)
+ context 'when pushing a lfs object that does not exist' do
+ before do
+ body = { 'operation' => 'upload',
+ 'objects' => [
+ { 'oid' => '91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897',
+ 'size' => 1575078
+ }]
+ }.to_json
+ env['rack.input'] = StringIO.new(body)
+ end
- expect(response_body['objects'].last['oid']).to eq(sample_oid)
- expect(response_body['objects'].last['size']).to eq(sample_size)
- expect(lfs_object.projects.pluck(:id)).to_not include(project.id)
- expect(lfs_object.projects.pluck(:id)).to include(public_project.id)
- expect(response_body['objects'].last).to have_key('_links')
+ it "responds with status 200 and upload hypermedia link" do
+ response = lfs_router_auth.try_call
+ expect(response.first).to eq(200)
+
+ response_body = ActiveSupport::JSON.decode(response.last.first)
+ expect(response_body['objects']).to be_kind_of(Array)
+ expect(response_body['objects'].first['oid']).to eq("91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897")
+ expect(response_body['objects'].first['size']).to eq(1575078)
+ expect(lfs_object.projects.pluck(:id)).not_to include(project.id)
+ expect(response_body['objects'].first['actions']['upload']['href']).to eq("#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}.git/gitlab-lfs/objects/91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897/1575078")
+ expect(response_body['objects'].first['actions']['upload']['header']).to eq('Authorization' => @auth)
+ end
+ end
+
+ context 'when pushing one new and one existing lfs object' do
+ before do
+ body = { 'operation' => 'upload',
+ 'objects' => [
+ { 'oid' => '91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897',
+ 'size' => 1575078
+ },
+ { 'oid' => sample_oid,
+ 'size' => sample_size
+ }
+ ]
+ }.to_json
+ env['rack.input'] = StringIO.new(body)
+ project.lfs_objects << lfs_object
+ end
+
+ it "responds with status 200 with upload hypermedia link for the new object" do
+ response = lfs_router_auth.try_call
+ expect(response.first).to eq(200)
+
+ response_body = ActiveSupport::JSON.decode(response.last.first)
+ expect(response_body['objects']).to be_kind_of(Array)
+
+ expect(response_body['objects'].first['oid']).to eq("91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897")
+ expect(response_body['objects'].first['size']).to eq(1575078)
+ expect(response_body['objects'].first['actions']['upload']['href']).to eq("#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}.git/gitlab-lfs/objects/91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897/1575078")
+ expect(response_body['objects'].first['actions']['upload']['header']).to eq("Authorization" => @auth)
+
+ expect(response_body['objects'].last['oid']).to eq(sample_oid)
+ expect(response_body['objects'].last['size']).to eq(sample_size)
+ expect(response_body['objects'].last).to_not have_key('actions')
+ end
end
end
- end
- context 'when user does not have push access' do
- it 'responds with 403' do
- expect(lfs_router_auth.try_call.first).to eq(403)
+ context 'when user does not have push access' do
+ it 'responds with 403' do
+ expect(lfs_router_auth.try_call.first).to eq(403)
+ end
end
end
- end
- context 'when user is not authenticated' do
- context 'when user has push access' do
+ context 'when user is not authenticated' do
before do
- project.team << [user, :master]
+ env['rack.input'] = StringIO.new(
+ { 'objects' => [], 'operation' => 'upload' }.to_json
+ )
end
- it "responds with status 401" do
- expect(lfs_router_public_noauth.try_call.first).to eq(401)
+ context 'when user has push access' do
+ before do
+ project.team << [user, :master]
+ end
+
+ it "responds with status 401" do
+ expect(lfs_router_public_noauth.try_call.first).to eq(401)
+ end
end
- end
- context 'when user does not have push access' do
- it "responds with status 401" do
- expect(lfs_router_public_noauth.try_call.first).to eq(401)
+ context 'when user does not have push access' do
+ it "responds with status 401" do
+ expect(lfs_router_public_noauth.try_call.first).to eq(401)
+ end
end
end
end
+
+ describe 'unsupported' do
+ before do
+ body = { 'operation' => 'other',
+ 'objects' => [
+ { 'oid' => sample_oid,
+ 'size' => sample_size
+ }]
+ }.to_json
+ env['rack.input'] = StringIO.new(body)
+ end
+
+ it 'responds with status 404' do
+ expect(lfs_router_public_noauth.try_call.first).to eq(404)
+ end
+ end
end
describe 'when pushing a lfs object' do
diff --git a/spec/lib/gitlab/markdown/filter/label_reference_filter_spec.rb b/spec/lib/gitlab/markdown/filter/label_reference_filter_spec.rb
index 5403e811aa3..962912d8ec7 100644
--- a/spec/lib/gitlab/markdown/filter/label_reference_filter_spec.rb
+++ b/spec/lib/gitlab/markdown/filter/label_reference_filter_spec.rb
@@ -70,7 +70,7 @@ describe Gitlab::Markdown::LabelReferenceFilter do
doc = filter("See #{reference}")
expect(doc.css('a').first.attr('href')).to eq urls.
- namespace_project_issues_url(project.namespace, project, label_name: label.name)
+ namespace_project_issues_path(project.namespace, project, label_name: label.name)
end
it 'links with adjacent text' do
@@ -93,7 +93,7 @@ describe Gitlab::Markdown::LabelReferenceFilter do
doc = filter("See #{reference}")
expect(doc.css('a').first.attr('href')).to eq urls.
- namespace_project_issues_url(project.namespace, project, label_name: label.name)
+ namespace_project_issues_path(project.namespace, project, label_name: label.name)
expect(doc.text).to eq 'See gfm'
end
@@ -117,7 +117,7 @@ describe Gitlab::Markdown::LabelReferenceFilter do
doc = filter("See #{reference}")
expect(doc.css('a').first.attr('href')).to eq urls.
- namespace_project_issues_url(project.namespace, project, label_name: label.name)
+ namespace_project_issues_path(project.namespace, project, label_name: label.name)
expect(doc.text).to eq 'See gfm references'
end
diff --git a/spec/lib/gitlab/sherlock/transaction_spec.rb b/spec/lib/gitlab/sherlock/transaction_spec.rb
index bb49fb65cf8..fb80c62c794 100644
--- a/spec/lib/gitlab/sherlock/transaction_spec.rb
+++ b/spec/lib/gitlab/sherlock/transaction_spec.rb
@@ -84,6 +84,19 @@ describe Gitlab::Sherlock::Transaction do
end
end
+ describe '#query_duration' do
+ it 'returns the total query duration in seconds' do
+ time = Time.now
+ query1 = Gitlab::Sherlock::Query.new('SELECT 1', time, time + 5)
+ query2 = Gitlab::Sherlock::Query.new('SELECT 2', time, time + 2)
+
+ transaction.queries << query1
+ transaction.queries << query2
+
+ expect(transaction.query_duration).to be_within(0.1).of(7.0)
+ end
+ end
+
describe '#to_param' do
it 'returns the transaction ID' do
expect(transaction.to_param).to eq(transaction.id)
diff --git a/spec/lib/votes_spec.rb b/spec/lib/votes_spec.rb
deleted file mode 100644
index 39e5d054e62..00000000000
--- a/spec/lib/votes_spec.rb
+++ /dev/null
@@ -1,188 +0,0 @@
-require 'spec_helper'
-
-describe Issue, 'Votes' do
- let(:issue) { create(:issue) }
-
- describe "#upvotes" do
- it "with no notes has a 0/0 score" do
- expect(issue.upvotes).to eq(0)
- end
-
- it "should recognize non-+1 notes" do
- add_note "No +1 here"
- expect(issue.notes.size).to eq(1)
- expect(issue.notes.first.upvote?).to be_falsey
- expect(issue.upvotes).to eq(0)
- end
-
- it "should recognize a single +1 note" do
- add_note "+1 This is awesome"
- expect(issue.upvotes).to eq(1)
- end
-
- it 'should recognize multiple +1 notes' do
- add_note '+1 This is awesome', create(:user)
- add_note '+1 I want this', create(:user)
- expect(issue.upvotes).to eq(2)
- end
-
- it 'should not count 2 +1 votes from the same user' do
- add_note '+1 This is awesome'
- add_note '+1 I want this'
- expect(issue.upvotes).to eq(1)
- end
- end
-
- describe "#downvotes" do
- it "with no notes has a 0/0 score" do
- expect(issue.downvotes).to eq(0)
- end
-
- it "should recognize non--1 notes" do
- add_note "Almost got a -1"
- expect(issue.notes.size).to eq(1)
- expect(issue.notes.first.downvote?).to be_falsey
- expect(issue.downvotes).to eq(0)
- end
-
- it "should recognize a single -1 note" do
- add_note "-1 This is bad"
- expect(issue.downvotes).to eq(1)
- end
-
- it "should recognize multiple -1 notes" do
- add_note('-1 This is bad', create(:user))
- add_note('-1 Away with this', create(:user))
- expect(issue.downvotes).to eq(2)
- end
- end
-
- describe "#votes_count" do
- it "with no notes has a 0/0 score" do
- expect(issue.votes_count).to eq(0)
- end
-
- it "should recognize non notes" do
- add_note "No +1 here"
- expect(issue.notes.size).to eq(1)
- expect(issue.votes_count).to eq(0)
- end
-
- it "should recognize a single +1 note" do
- add_note "+1 This is awesome"
- expect(issue.votes_count).to eq(1)
- end
-
- it "should recognize a single -1 note" do
- add_note "-1 This is bad"
- expect(issue.votes_count).to eq(1)
- end
-
- it "should recognize multiple notes" do
- add_note('+1 This is awesome', create(:user))
- add_note('-1 This is bad', create(:user))
- add_note('+1 I want this', create(:user))
- expect(issue.votes_count).to eq(3)
- end
-
- it 'should not count 2 -1 votes from the same user' do
- add_note '-1 This is suspicious'
- add_note '-1 This is bad'
- expect(issue.votes_count).to eq(1)
- end
- end
-
- describe "#upvotes_in_percent" do
- it "with no notes has a 0% score" do
- expect(issue.upvotes_in_percent).to eq(0)
- end
-
- it "should count a single 1 note as 100%" do
- add_note "+1 This is awesome"
- expect(issue.upvotes_in_percent).to eq(100)
- end
-
- it 'should count multiple +1 notes as 100%' do
- add_note('+1 This is awesome', create(:user))
- add_note('+1 I want this', create(:user))
- expect(issue.upvotes_in_percent).to eq(100)
- end
-
- it 'should count fractions for multiple +1 and -1 notes correctly' do
- add_note('+1 This is awesome', create(:user))
- add_note('+1 I want this', create(:user))
- add_note('-1 This is bad', create(:user))
- add_note('+1 me too', create(:user))
- expect(issue.upvotes_in_percent).to eq(75)
- end
- end
-
- describe "#downvotes_in_percent" do
- it "with no notes has a 0% score" do
- expect(issue.downvotes_in_percent).to eq(0)
- end
-
- it "should count a single -1 note as 100%" do
- add_note "-1 This is bad"
- expect(issue.downvotes_in_percent).to eq(100)
- end
-
- it 'should count multiple -1 notes as 100%' do
- add_note('-1 This is bad', create(:user))
- add_note('-1 Away with this', create(:user))
- expect(issue.downvotes_in_percent).to eq(100)
- end
-
- it 'should count fractions for multiple +1 and -1 notes correctly' do
- add_note('+1 This is awesome', create(:user))
- add_note('+1 I want this', create(:user))
- add_note('-1 This is bad', create(:user))
- add_note('+1 me too', create(:user))
- expect(issue.downvotes_in_percent).to eq(25)
- end
- end
-
- describe '#filter_superceded_votes' do
-
- it 'should count a users vote only once amongst multiple votes' do
- add_note('-1 This needs work before I will accept it')
- add_note('+1 I want this', create(:user))
- add_note('+1 This is is awesome', create(:user))
- add_note('+1 this looks good now')
- add_note('+1 This is awesome', create(:user))
- add_note('+1 me too', create(:user))
- expect(issue.downvotes).to eq(0)
- expect(issue.upvotes).to eq(5)
- end
-
- it 'should count each users vote only once' do
- add_note '-1 This needs work before it will be accepted'
- add_note '+1 I like this'
- add_note '+1 I still like this'
- add_note '+1 I really like this'
- add_note '+1 Give me this now!!!!'
- expect(issue.downvotes).to eq(0)
- expect(issue.upvotes).to eq(1)
- end
-
- it 'should count a users vote only once without caring about comments' do
- add_note '-1 This needs work before it will be accepted'
- add_note 'Comment 1'
- add_note 'Another comment'
- add_note '+1 vote'
- add_note 'final comment'
- expect(issue.downvotes).to eq(0)
- expect(issue.upvotes).to eq(1)
- end
-
- end
-
- def add_note(text, author = issue.author)
- created_at = Time.now - 1.hour + Note.count.seconds
- issue.notes << create(:note,
- note: text,
- project: issue.project,
- author_id: author.id,
- created_at: created_at)
- end
-end
diff --git a/spec/mailers/notify_spec.rb b/spec/mailers/notify_spec.rb
index 47863d54579..d6796b07a5b 100644
--- a/spec/mailers/notify_spec.rb
+++ b/spec/mailers/notify_spec.rb
@@ -77,6 +77,32 @@ describe Notify do
end
end
+ shared_examples 'it should have Gmail Actions links' do
+ it { is_expected.to have_body_text /ViewAction/ }
+ end
+
+ shared_examples 'it should not have Gmail Actions links' do
+ it { is_expected.to_not have_body_text /ViewAction/ }
+ end
+
+ shared_examples 'it should show Gmail Actions View Issue link' do
+ it_behaves_like 'it should have Gmail Actions links'
+
+ it { is_expected.to have_body_text /View Issue/ }
+ end
+
+ shared_examples 'it should show Gmail Actions View Merge request link' do
+ it_behaves_like 'it should have Gmail Actions links'
+
+ it { is_expected.to have_body_text /View Merge request/ }
+ end
+
+ shared_examples 'it should show Gmail Actions View Commit link' do
+ it_behaves_like 'it should have Gmail Actions links'
+
+ it { is_expected.to have_body_text /View Commit/ }
+ end
+
describe 'for new users, the email' do
let(:example_site_path) { root_path }
let(:new_user) { create(:user, email: new_user_address, created_by_id: 1) }
@@ -87,6 +113,7 @@ describe Notify do
it_behaves_like 'an email sent from GitLab'
it_behaves_like 'a new user email', new_user_address
+ it_behaves_like 'it should not have Gmail Actions links'
it 'contains the password text' do
is_expected.to have_body_text /Click here to set your password/
@@ -115,6 +142,7 @@ describe Notify do
it_behaves_like 'an email sent from GitLab'
it_behaves_like 'a new user email', new_user_address
+ it_behaves_like 'it should not have Gmail Actions links'
it 'should not contain the new user\'s password' do
is_expected.not_to have_body_text /password/
@@ -127,6 +155,7 @@ describe Notify do
subject { Notify.new_ssh_key_email(key.id) }
it_behaves_like 'an email sent from GitLab'
+ it_behaves_like 'it should not have Gmail Actions links'
it 'is sent to the new user' do
is_expected.to deliver_to key.user.email
@@ -150,6 +179,8 @@ describe Notify do
subject { Notify.new_email_email(email.id) }
+ it_behaves_like 'it should not have Gmail Actions links'
+
it 'is sent to the new user' do
is_expected.to deliver_to email.user.email
end
@@ -194,6 +225,7 @@ describe Notify do
it_behaves_like 'an assignee email'
it_behaves_like 'an email starting a new thread', 'issue'
+ it_behaves_like 'it should show Gmail Actions View Issue link'
it 'has the correct subject' do
is_expected.to have_subject /#{project.name} \| #{issue.title} \(##{issue.iid}\)/
@@ -207,6 +239,8 @@ describe Notify do
describe 'that are new with a description' do
subject { Notify.new_issue_email(issue_with_description.assignee_id, issue_with_description.id) }
+ it_behaves_like 'it should show Gmail Actions View Issue link'
+
it 'contains the description' do
is_expected.to have_body_text /#{issue_with_description.description}/
end
@@ -217,6 +251,7 @@ describe Notify do
it_behaves_like 'a multiple recipients email'
it_behaves_like 'an answer to an existing thread', 'issue'
+ it_behaves_like 'it should show Gmail Actions View Issue link'
it 'is sent as the author' do
sender = subject.header[:from].addrs[0]
@@ -246,6 +281,7 @@ describe Notify do
subject { Notify.issue_status_changed_email(recipient.id, issue.id, status, current_user) }
it_behaves_like 'an answer to an existing thread', 'issue'
+ it_behaves_like 'it should show Gmail Actions View Issue link'
it 'is sent as the author' do
sender = subject.header[:from].addrs[0]
@@ -269,7 +305,6 @@ describe Notify do
is_expected.to have_body_text /#{namespace_project_issue_path project.namespace, project, issue}/
end
end
-
end
context 'for merge requests' do
@@ -282,6 +317,7 @@ describe Notify do
it_behaves_like 'an assignee email'
it_behaves_like 'an email starting a new thread', 'merge_request'
+ it_behaves_like 'it should show Gmail Actions View Merge request link'
it 'has the correct subject' do
is_expected.to have_subject /#{merge_request.title} \(##{merge_request.iid}\)/
@@ -307,6 +343,8 @@ describe Notify do
describe 'that are new with a description' do
subject { Notify.new_merge_request_email(merge_request_with_description.assignee_id, merge_request_with_description.id) }
+ it_behaves_like 'it should show Gmail Actions View Merge request link'
+
it 'contains the description' do
is_expected.to have_body_text /#{merge_request_with_description.description}/
end
@@ -317,6 +355,7 @@ describe Notify do
it_behaves_like 'a multiple recipients email'
it_behaves_like 'an answer to an existing thread', 'merge_request'
+ it_behaves_like 'it should show Gmail Actions View Merge request link'
it 'is sent as the author' do
sender = subject.header[:from].addrs[0]
@@ -346,6 +385,7 @@ describe Notify do
subject { Notify.merge_request_status_email(recipient.id, merge_request.id, status, current_user) }
it_behaves_like 'an answer to an existing thread', 'merge_request'
+ it_behaves_like 'it should show Gmail Actions View Merge request link'
it 'is sent as the author' do
sender = subject.header[:from].addrs[0]
@@ -375,6 +415,7 @@ describe Notify do
it_behaves_like 'a multiple recipients email'
it_behaves_like 'an answer to an existing thread', 'merge_request'
+ it_behaves_like 'it should show Gmail Actions View Merge request link'
it 'is sent as the merge author' do
sender = subject.header[:from].addrs[0]
@@ -403,6 +444,7 @@ describe Notify do
subject { Notify.project_was_moved_email(project.id, user.id, "gitlab/gitlab") }
it_behaves_like 'an email sent from GitLab'
+ it_behaves_like 'it should not have Gmail Actions links'
it 'has the correct subject' do
is_expected.to have_subject /Project was moved/
@@ -424,13 +466,16 @@ describe Notify do
subject { Notify.project_access_granted_email(project_member.id) }
it_behaves_like 'an email sent from GitLab'
+ it_behaves_like 'it should not have Gmail Actions links'
it 'has the correct subject' do
is_expected.to have_subject /Access to project was granted/
end
+
it 'contains name of project' do
is_expected.to have_body_text /#{project.name}/
end
+
it 'contains new user role' do
is_expected.to have_body_text /#{project_member.human_access}/
end
@@ -445,6 +490,8 @@ describe Notify do
end
shared_examples 'a note email' do
+ it_behaves_like 'it should have Gmail Actions links'
+
it 'is sent as the author' do
sender = subject.header[:from].addrs[0]
expect(sender.display_name).to eq(note_author.name)
@@ -469,6 +516,7 @@ describe Notify do
it_behaves_like 'a note email'
it_behaves_like 'an answer to an existing thread', 'commit'
+ it_behaves_like 'it should show Gmail Actions View Commit link'
it 'has the correct subject' do
is_expected.to have_subject /#{commit.title} \(#{commit.short_id}\)/
@@ -488,6 +536,7 @@ describe Notify do
it_behaves_like 'a note email'
it_behaves_like 'an answer to an existing thread', 'merge_request'
+ it_behaves_like 'it should show Gmail Actions View Merge request link'
it 'has the correct subject' do
is_expected.to have_subject /#{merge_request.title} \(##{merge_request.iid}\)/
@@ -507,6 +556,7 @@ describe Notify do
it_behaves_like 'a note email'
it_behaves_like 'an answer to an existing thread', 'issue'
+ it_behaves_like 'it should show Gmail Actions View Issue link'
it 'has the correct subject' do
is_expected.to have_subject /#{issue.title} \(##{issue.iid}\)/
@@ -527,6 +577,7 @@ describe Notify do
subject { Notify.group_access_granted_email(membership.id) }
it_behaves_like 'an email sent from GitLab'
+ it_behaves_like 'it should not have Gmail Actions links'
it 'has the correct subject' do
is_expected.to have_subject /Access to group was granted/
@@ -574,6 +625,8 @@ describe Notify do
subject { Notify.repository_push_email(project.id, 'devs@company.name', author_id: user.id, ref: 'refs/heads/master', action: :create) }
+ it_behaves_like 'it should not have Gmail Actions links'
+
it 'is sent as the author' do
sender = subject.header[:from].addrs[0]
expect(sender.display_name).to eq(user.name)
@@ -600,6 +653,8 @@ describe Notify do
subject { Notify.repository_push_email(project.id, 'devs@company.name', author_id: user.id, ref: 'refs/tags/v1.0', action: :create) }
+ it_behaves_like 'it should not have Gmail Actions links'
+
it 'is sent as the author' do
sender = subject.header[:from].addrs[0]
expect(sender.display_name).to eq(user.name)
@@ -625,6 +680,8 @@ describe Notify do
subject { Notify.repository_push_email(project.id, 'devs@company.name', author_id: user.id, ref: 'refs/heads/master', action: :delete) }
+ it_behaves_like 'it should not have Gmail Actions links'
+
it 'is sent as the author' do
sender = subject.header[:from].addrs[0]
expect(sender.display_name).to eq(user.name)
@@ -646,6 +703,8 @@ describe Notify do
subject { Notify.repository_push_email(project.id, 'devs@company.name', author_id: user.id, ref: 'refs/tags/v1.0', action: :delete) }
+ it_behaves_like 'it should not have Gmail Actions links'
+
it 'is sent as the author' do
sender = subject.header[:from].addrs[0]
expect(sender.display_name).to eq(user.name)
@@ -671,6 +730,8 @@ describe Notify do
subject { Notify.repository_push_email(project.id, 'devs@company.name', author_id: user.id, ref: 'refs/heads/master', action: :push, compare: compare, reverse_compare: false, send_from_committer_email: send_from_committer_email) }
+ it_behaves_like 'it should not have Gmail Actions links'
+
it 'is sent as the author' do
sender = subject.header[:from].addrs[0]
expect(sender.display_name).to eq(user.name)
@@ -774,6 +835,8 @@ describe Notify do
subject { Notify.repository_push_email(project.id, 'devs@company.name', author_id: user.id, ref: 'refs/heads/master', action: :push, compare: compare) }
+ it_behaves_like 'it should show Gmail Actions View Commit link'
+
it 'is sent as the author' do
sender = subject.header[:from].addrs[0]
expect(sender.display_name).to eq(user.name)
diff --git a/spec/models/ci/project_services/mail_service_spec.rb b/spec/models/ci/project_services/mail_service_spec.rb
index d9b3d34ff15..c03be3ef75f 100644
--- a/spec/models/ci/project_services/mail_service_spec.rb
+++ b/spec/models/ci/project_services/mail_service_spec.rb
@@ -44,13 +44,10 @@ describe Ci::MailService do
end
it do
- should_email("git@example.com")
- mail.execute(build)
- end
-
- def should_email(email)
- expect(Ci::Notify).to receive(:build_fail_email).with(build.id, email)
- expect(Ci::Notify).not_to receive(:build_success_email).with(build.id, email)
+ perform_enqueued_jobs do
+ expect{ mail.execute(build) }.to change{ ActionMailer::Base.deliveries.size }.by(1)
+ expect(ActionMailer::Base.deliveries.last.to).to eq(["git@example.com"])
+ end
end
end
@@ -67,13 +64,10 @@ describe Ci::MailService do
end
it do
- should_email("git@example.com")
- mail.execute(build)
- end
-
- def should_email(email)
- expect(Ci::Notify).to receive(:build_success_email).with(build.id, email)
- expect(Ci::Notify).not_to receive(:build_fail_email).with(build.id, email)
+ perform_enqueued_jobs do
+ expect{ mail.execute(build) }.to change{ ActionMailer::Base.deliveries.size }.by(1)
+ expect(ActionMailer::Base.deliveries.last.to).to eq(["git@example.com"])
+ end
end
end
@@ -95,14 +89,12 @@ describe Ci::MailService do
end
it do
- should_email("git@example.com")
- should_email("jeroen@example.com")
- mail.execute(build)
- end
-
- def should_email(email)
- expect(Ci::Notify).to receive(:build_success_email).with(build.id, email)
- expect(Ci::Notify).not_to receive(:build_fail_email).with(build.id, email)
+ perform_enqueued_jobs do
+ expect{ mail.execute(build) }.to change{ ActionMailer::Base.deliveries.size }.by(2)
+ expect(
+ ActionMailer::Base.deliveries.map(&:to).flatten
+ ).to include("git@example.com", "jeroen@example.com")
+ end
end
end
@@ -124,14 +116,11 @@ describe Ci::MailService do
end
it do
- should_email(commit.git_author_email)
- should_email("jeroen@example.com")
- mail.execute(build) if mail.can_execute?(build)
- end
-
- def should_email(email)
- expect(Ci::Notify).not_to receive(:build_success_email).with(build.id, email)
- expect(Ci::Notify).not_to receive(:build_fail_email).with(build.id, email)
+ perform_enqueued_jobs do
+ expect do
+ mail.execute(build) if mail.can_execute?(build)
+ end.to_not change{ ActionMailer::Base.deliveries.size }
+ end
end
end
@@ -177,14 +166,11 @@ describe Ci::MailService do
it do
Ci::Build.retry(build)
- should_email(commit.git_author_email)
- should_email("jeroen@example.com")
- mail.execute(build) if mail.can_execute?(build)
- end
-
- def should_email(email)
- expect(Ci::Notify).not_to receive(:build_success_email).with(build.id, email)
- expect(Ci::Notify).not_to receive(:build_fail_email).with(build.id, email)
+ perform_enqueued_jobs do
+ expect do
+ mail.execute(build) if mail.can_execute?(build)
+ end.to_not change{ ActionMailer::Base.deliveries.size }
+ end
end
end
end
diff --git a/spec/models/concerns/strip_attribute_spec.rb b/spec/models/concerns/strip_attribute_spec.rb
new file mode 100644
index 00000000000..6445e29c3ef
--- /dev/null
+++ b/spec/models/concerns/strip_attribute_spec.rb
@@ -0,0 +1,20 @@
+require 'spec_helper'
+
+describe Milestone, "StripAttribute" do
+ let(:milestone) { create(:milestone) }
+
+ describe ".strip_attributes" do
+ it { expect(Milestone).to respond_to(:strip_attributes) }
+ it { expect(Milestone.strip_attrs).to include(:title) }
+ end
+
+ describe "#strip_attributes" do
+ before do
+ milestone.title = ' 8.3 '
+ milestone.valid?
+ end
+
+ it { expect(milestone.title).to eq('8.3') }
+ end
+
+end
diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb
index 90af75ff0e3..567c911425c 100644
--- a/spec/models/merge_request_spec.rb
+++ b/spec/models/merge_request_spec.rb
@@ -193,4 +193,29 @@ describe MergeRequest do
it_behaves_like 'a Taskable' do
subject { create :merge_request, :simple }
end
+
+ describe '#ci_commit' do
+ describe 'when the source project exists' do
+ it 'returns the latest commit' do
+ commit = double(:commit, id: '123abc')
+ ci_commit = double(:ci_commit)
+
+ allow(subject).to receive(:last_commit).and_return(commit)
+
+ expect(subject.source_project).to receive(:ci_commit).
+ with('123abc').
+ and_return(ci_commit)
+
+ expect(subject.ci_commit).to eq(ci_commit)
+ end
+ end
+
+ describe 'when the source project does not exist' do
+ it 'returns nil' do
+ allow(subject).to receive(:source_project).and_return(nil)
+
+ expect(subject.ci_commit).to be_nil
+ end
+ end
+ end
end
diff --git a/spec/models/note_spec.rb b/spec/models/note_spec.rb
index 75564839dcf..f347f537550 100644
--- a/spec/models/note_spec.rb
+++ b/spec/models/note_spec.rb
@@ -32,77 +32,6 @@ describe Note do
it { is_expected.to validate_presence_of(:project) }
end
- describe '#votable?' do
- it 'is true for issue notes' do
- note = build(:note_on_issue)
- expect(note).to be_votable
- end
-
- it 'is true for merge request notes' do
- note = build(:note_on_merge_request)
- expect(note).to be_votable
- end
-
- it 'is false for merge request diff notes' do
- note = build(:note_on_merge_request_diff)
- expect(note).not_to be_votable
- end
-
- it 'is false for commit notes' do
- note = build(:note_on_commit)
- expect(note).not_to be_votable
- end
-
- it 'is false for commit diff notes' do
- note = build(:note_on_commit_diff)
- expect(note).not_to be_votable
- end
- end
-
- describe 'voting score' do
- it 'recognizes a neutral note' do
- note = build(:votable_note, note: 'This is not a +1 note')
- expect(note).not_to be_upvote
- expect(note).not_to be_downvote
- end
-
- it 'recognizes a neutral emoji note' do
- note = build(:votable_note, note: "I would :+1: this, but I don't want to")
- expect(note).not_to be_upvote
- expect(note).not_to be_downvote
- end
-
- it 'recognizes a +1 note' do
- note = build(:votable_note, note: '+1 for this')
- expect(note).to be_upvote
- end
-
- it 'recognizes a +1 emoji as a vote' do
- note = build(:votable_note, note: ':+1: for this')
- expect(note).to be_upvote
- end
-
- it 'recognizes a thumbsup emoji as a vote' do
- note = build(:votable_note, note: ':thumbsup: for this')
- expect(note).to be_upvote
- end
-
- it 'recognizes a -1 note' do
- note = build(:votable_note, note: '-1 for this')
- expect(note).to be_downvote
- end
-
- it 'recognizes a -1 emoji as a vote' do
- note = build(:votable_note, note: ':-1: for this')
- expect(note).to be_downvote
- end
-
- it 'recognizes a thumbsdown emoji as a vote' do
- note = build(:votable_note, note: ':thumbsdown: for this')
- expect(note).to be_downvote
- end
- end
-
describe "Commit notes" do
let!(:note) { create(:note_on_commit, note: "+1 from me") }
let!(:commit) { note.noteable }
@@ -139,10 +68,6 @@ describe Note do
it "should be recognized by #for_commit_diff_line?" do
expect(note).to be_for_commit_diff_line
end
-
- it "should not be votable" do
- expect(note).not_to be_votable
- end
end
describe 'authorization' do
@@ -204,4 +129,16 @@ describe Note do
it { expect(Note.search('wow')).to include(note) }
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 array of notes" do
+ expect(Note.grouped_awards.first.first).to eq("smile")
+ expect(Note.grouped_awards.first.last).to match_array(Note.all)
+ end
+ end
end
diff --git a/spec/models/project_services/jira_service_spec.rb b/spec/models/project_services/jira_service_spec.rb
index ddd2cce212c..576f5fc79eb 100644
--- a/spec/models/project_services/jira_service_spec.rb
+++ b/spec/models/project_services/jira_service_spec.rb
@@ -94,9 +94,9 @@ describe JiraService do
end
it 'should be prepopulated with the settings' do
- expect(@service.properties[:project_url]).to eq('http://jira.sample/projects/project_a')
- expect(@service.properties[:issues_url]).to eq("http://jira.sample/issues/:id")
- expect(@service.properties[:new_issue_url]).to eq("http://jira.sample/projects/project_a/issues/new")
+ expect(@service.properties["project_url"]).to eq('http://jira.sample/projects/project_a')
+ expect(@service.properties["issues_url"]).to eq("http://jira.sample/issues/:id")
+ expect(@service.properties["new_issue_url"]).to eq("http://jira.sample/projects/project_a/issues/new")
end
end
end
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index c42e8870f8c..f80fada45e9 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -345,17 +345,6 @@ describe Project do
expect(project1.star_count).to eq(0)
expect(project2.star_count).to eq(0)
end
-
- it 'is decremented when an upvoter account is deleted' do
- user = create :user
- project = create :project, :public
- user.toggle_star(project)
- project.reload
- expect(project.star_count).to eq(1)
- user.destroy
- project.reload
- expect(project.star_count).to eq(0)
- end
end
describe :avatar_type do
diff --git a/spec/requests/api/tags_spec.rb b/spec/requests/api/tags_spec.rb
index cc9a5f47582..17f2643fd45 100644
--- a/spec/requests/api/tags_spec.rb
+++ b/spec/requests/api/tags_spec.rb
@@ -28,10 +28,10 @@ describe API::API, api: true do
before do
release = project.releases.find_or_initialize_by(tag: tag_name)
release.update_attributes(description: description)
- get api("/projects/#{project.id}/repository/tags", user)
end
it "should return an array of project tags with release info" do
+ get api("/projects/#{project.id}/repository/tags", user)
expect(response.status).to eq(200)
expect(json_response).to be_an Array
expect(json_response.first['name']).to eq(tag_name)
@@ -119,17 +119,78 @@ describe API::API, api: true do
end
end
- describe 'PUT /projects/:id/repository/:tag/release' do
+ describe 'POST /projects/:id/repository/tags/:tag_name/release' do
let(:tag_name) { project.repository.tag_names.first }
let(:description) { 'Awesome release!' }
it 'should create description for existing git tag' do
- put api("/projects/#{project.id}/repository/#{tag_name}/release", user),
+ post api("/projects/#{project.id}/repository/tags/#{tag_name}/release", user),
description: description
- expect(response.status).to eq(200)
- expect(json_response['tag']).to eq(tag_name)
+ expect(response.status).to eq(201)
+ expect(json_response['tag_name']).to eq(tag_name)
expect(json_response['description']).to eq(description)
end
+
+ it 'should return 404 if the tag does not exist' do
+ post api("/projects/#{project.id}/repository/tags/foobar/release", user),
+ description: description
+
+ expect(response.status).to eq(404)
+ expect(json_response['message']).to eq('Tag does not exist')
+ end
+
+ context 'on tag with existing release' do
+ before do
+ release = project.releases.find_or_initialize_by(tag: tag_name)
+ release.update_attributes(description: description)
+ end
+
+ it 'should return 409 if there is already a release' do
+ post api("/projects/#{project.id}/repository/tags/#{tag_name}/release", user),
+ description: description
+
+ expect(response.status).to eq(409)
+ expect(json_response['message']).to eq('Release already exists')
+ end
+ end
+ end
+
+ describe 'PUT id/repository/tags/:tag_name/release' do
+ let(:tag_name) { project.repository.tag_names.first }
+ let(:description) { 'Awesome release!' }
+ let(:new_description) { 'The best release!' }
+
+ context 'on tag with existing release' do
+ before do
+ release = project.releases.find_or_initialize_by(tag: tag_name)
+ release.update_attributes(description: description)
+ end
+
+ it 'should update the release description' do
+ put api("/projects/#{project.id}/repository/tags/#{tag_name}/release", user),
+ description: new_description
+
+ expect(response.status).to eq(200)
+ expect(json_response['tag_name']).to eq(tag_name)
+ expect(json_response['description']).to eq(new_description)
+ end
+ end
+
+ it 'should return 404 if the tag does not exist' do
+ put api("/projects/#{project.id}/repository/tags/foobar/release", user),
+ description: new_description
+
+ expect(response.status).to eq(404)
+ expect(json_response['message']).to eq('Tag does not exist')
+ end
+
+ it 'should return 404 if the release does not exist' do
+ put api("/projects/#{project.id}/repository/tags/#{tag_name}/release", user),
+ description: new_description
+
+ expect(response.status).to eq(404)
+ expect(json_response['message']).to eq('Release does not exist')
+ end
end
end
diff --git a/spec/services/ci/create_commit_service_spec.rb b/spec/services/ci/create_commit_service_spec.rb
index e3a8fe9681b..e0ede1d58b7 100644
--- a/spec/services/ci/create_commit_service_spec.rb
+++ b/spec/services/ci/create_commit_service_spec.rb
@@ -53,7 +53,7 @@ module Ci
end
end
- it 'fails commits without .gitlab-ci.yml' do
+ it 'skips commits without .gitlab-ci.yml' do
stub_ci_commit_yaml_file(nil)
result = service.execute(project, user,
ref: 'refs/heads/0_1',
@@ -63,7 +63,24 @@ module Ci
)
expect(result).to be_persisted
expect(result.builds.any?).to be_falsey
- expect(result.status).to eq('failed')
+ expect(result.status).to eq('skipped')
+ expect(result.yaml_errors).to be_nil
+ end
+
+ it 'skips commits if yaml is invalid' do
+ message = 'message'
+ allow_any_instance_of(Ci::Commit).to receive(:git_commit_message) { message }
+ stub_ci_commit_yaml_file('invalid: file: file')
+ commits = [{ message: message }]
+ commit = service.execute(project, user,
+ ref: 'refs/tags/0_1',
+ before: '00000000',
+ after: '31das312',
+ commits: commits
+ )
+ expect(commit.builds.any?).to be false
+ expect(commit.status).to eq('failed')
+ expect(commit.yaml_errors).to_not be_nil
end
describe :ci_skip? do
@@ -100,7 +117,7 @@ module Ci
end
it "skips builds creation if there is [ci skip] tag in commit message and yaml is invalid" do
- stub_ci_commit_yaml_file('invalid: file')
+ stub_ci_commit_yaml_file('invalid: file: fiile')
commits = [{ message: message }]
commit = service.execute(project, user,
ref: 'refs/tags/0_1',
@@ -110,6 +127,7 @@ module Ci
)
expect(commit.builds.any?).to be false
expect(commit.status).to eq("skipped")
+ expect(commit.yaml_errors).to be_nil
end
end
diff --git a/spec/services/create_release_service_spec.rb b/spec/services/create_release_service_spec.rb
new file mode 100644
index 00000000000..26d7f365bbb
--- /dev/null
+++ b/spec/services/create_release_service_spec.rb
@@ -0,0 +1,34 @@
+require 'spec_helper'
+
+describe CreateReleaseService do
+ let(:project) { create(:project) }
+ let(:user) { create(:user) }
+ let(:tag_name) { project.repository.tag_names.first }
+ let(:description) { 'Awesome release!' }
+ let(:service) { CreateReleaseService.new(project, user) }
+
+ it 'creates a new release' do
+ result = service.execute(tag_name, description)
+ expect(result[:status]).to eq(:success)
+ release = project.releases.find_by(tag: tag_name)
+ expect(release).not_to be_nil
+ expect(release.description).to eq(description)
+ end
+
+ it 'raises an error if the tag does not exist' do
+ result = service.execute("foobar", description)
+ expect(result[:status]).to eq(:error)
+ end
+
+ context 'there already exists a release on a tag' do
+ before do
+ service.execute(tag_name, description)
+ end
+
+ it 'raises an error and does not update the release' do
+ result = service.execute(tag_name, 'The best release!')
+ expect(result[:status]).to eq(:error)
+ expect(project.releases.find_by(tag: tag_name).description).to eq(description)
+ end
+ end
+end
diff --git a/spec/services/issues/close_service_spec.rb b/spec/services/issues/close_service_spec.rb
index db547ce0d50..d711e3da104 100644
--- a/spec/services/issues/close_service_spec.rb
+++ b/spec/services/issues/close_service_spec.rb
@@ -14,7 +14,9 @@ describe Issues::CloseService do
describe :execute do
context "valid params" do
before do
- @issue = Issues::CloseService.new(project, user, {}).execute(issue)
+ perform_enqueued_jobs do
+ @issue = Issues::CloseService.new(project, user, {}).execute(issue)
+ end
end
it { expect(@issue).to be_valid }
diff --git a/spec/services/issues/update_service_spec.rb b/spec/services/issues/update_service_spec.rb
index f55527ee9a3..73d0b7f7abe 100644
--- a/spec/services/issues/update_service_spec.rb
+++ b/spec/services/issues/update_service_spec.rb
@@ -15,6 +15,17 @@ describe Issues::UpdateService do
end
describe 'execute' do
+ def find_note(starting_with)
+ @issue.notes.find do |note|
+ note && note.note.start_with?(starting_with)
+ end
+ end
+
+ def update_issue(opts)
+ @issue = Issues::UpdateService.new(project, user, opts).execute(issue)
+ @issue.reload
+ end
+
context "valid params" do
before do
opts = {
@@ -25,7 +36,10 @@ describe Issues::UpdateService do
label_ids: [label.id]
}
- @issue = Issues::UpdateService.new(project, user, opts).execute(issue)
+ perform_enqueued_jobs do
+ @issue = Issues::UpdateService.new(project, user, opts).execute(issue)
+ end
+
@issue.reload
end
@@ -44,12 +58,6 @@ describe Issues::UpdateService do
expect(email.subject).to include(issue.title)
end
- def find_note(starting_with)
- @issue.notes.find do |note|
- note && note.note.start_with?(starting_with)
- end
- end
-
it 'should create system note about issue reassign' do
note = find_note('Reassigned to')
@@ -71,5 +79,71 @@ describe Issues::UpdateService do
expect(note.note).to eq 'Title changed from **Old title** to **New title**'
end
end
+
+ context 'when Issue has tasks' do
+ before { update_issue({ description: "- [ ] Task 1\n- [ ] Task 2" }) }
+
+ it { expect(@issue.tasks?).to eq(true) }
+
+ context 'when tasks are marked as completed' do
+ before { update_issue({ description: "- [x] Task 1\n- [X] Task 2" }) }
+
+ it 'creates system note about task status change' do
+ note1 = find_note('Marked the task **Task 1** as completed')
+ note2 = find_note('Marked the task **Task 2** as completed')
+
+ expect(note1).not_to be_nil
+ expect(note2).not_to be_nil
+ end
+ end
+
+ context 'when tasks are marked as incomplete' do
+ before do
+ update_issue({ description: "- [x] Task 1\n- [X] Task 2" })
+ update_issue({ description: "- [ ] Task 1\n- [ ] Task 2" })
+ end
+
+ it 'creates system note about task status change' do
+ note1 = find_note('Marked the task **Task 1** as incomplete')
+ note2 = find_note('Marked the task **Task 2** as incomplete')
+
+ expect(note1).not_to be_nil
+ expect(note2).not_to be_nil
+ end
+ end
+
+ context 'when tasks position has been modified' do
+ before do
+ update_issue({ description: "- [x] Task 1\n- [X] Task 2" })
+ update_issue({ description: "- [x] Task 1\n- [ ] Task 3\n- [ ] Task 2" })
+ end
+
+ it 'does not create a system note' do
+ note = find_note('Marked the task **Task 2** as incomplete')
+
+ expect(note).to be_nil
+ end
+ end
+
+ context 'when a Task list with a completed item is totally replaced' do
+ before do
+ update_issue({ description: "- [ ] Task 1\n- [X] Task 2" })
+ update_issue({ description: "- [ ] One\n- [ ] Two\n- [ ] Three" })
+ end
+
+ it 'does not create a system note referencing the position the old item' do
+ note = find_note('Marked the task **Two** as incomplete')
+
+ expect(note).to be_nil
+ end
+
+ it 'should not generate a new note at all' do
+ expect do
+ update_issue({ description: "- [ ] One\n- [ ] Two\n- [ ] Three" })
+ end.not_to change { Note.count }
+ end
+ end
+ end
+
end
end
diff --git a/spec/services/merge_requests/close_service_spec.rb b/spec/services/merge_requests/close_service_spec.rb
index b3cbfd4b5b8..272f3897938 100644
--- a/spec/services/merge_requests/close_service_spec.rb
+++ b/spec/services/merge_requests/close_service_spec.rb
@@ -18,7 +18,9 @@ describe MergeRequests::CloseService do
before do
allow(service).to receive(:execute_hooks)
- @merge_request = service.execute(merge_request)
+ perform_enqueued_jobs do
+ @merge_request = service.execute(merge_request)
+ end
end
it { expect(@merge_request).to be_valid }
diff --git a/spec/services/merge_requests/merge_service_spec.rb b/spec/services/merge_requests/merge_service_spec.rb
index 7483f51de03..c0961ceb11e 100644
--- a/spec/services/merge_requests/merge_service_spec.rb
+++ b/spec/services/merge_requests/merge_service_spec.rb
@@ -17,8 +17,9 @@ describe MergeRequests::MergeService do
before do
allow(service).to receive(:execute_hooks)
-
- service.execute(merge_request, 'Awesome message')
+ perform_enqueued_jobs do
+ service.execute(merge_request, 'Awesome message')
+ end
end
it { expect(merge_request).to be_valid }
diff --git a/spec/services/merge_requests/reopen_service_spec.rb b/spec/services/merge_requests/reopen_service_spec.rb
index 9401bc3b558..05146bf43f4 100644
--- a/spec/services/merge_requests/reopen_service_spec.rb
+++ b/spec/services/merge_requests/reopen_service_spec.rb
@@ -19,7 +19,9 @@ describe MergeRequests::ReopenService do
allow(service).to receive(:execute_hooks)
merge_request.state = :closed
- service.execute(merge_request)
+ perform_enqueued_jobs do
+ service.execute(merge_request)
+ end
end
it { expect(merge_request).to be_valid }
diff --git a/spec/services/merge_requests/update_service_spec.rb b/spec/services/merge_requests/update_service_spec.rb
index 2ed51d223b7..d899b1f01d1 100644
--- a/spec/services/merge_requests/update_service_spec.rb
+++ b/spec/services/merge_requests/update_service_spec.rb
@@ -14,6 +14,17 @@ describe MergeRequests::UpdateService do
end
describe 'execute' do
+ def find_note(starting_with)
+ @merge_request.notes.find do |note|
+ note && note.note.start_with?(starting_with)
+ end
+ end
+
+ def update_merge_request(opts)
+ @merge_request = MergeRequests::UpdateService.new(project, user, opts).execute(merge_request)
+ @merge_request.reload
+ end
+
context 'valid params' do
let(:opts) do
{
@@ -31,8 +42,10 @@ describe MergeRequests::UpdateService do
before do
allow(service).to receive(:execute_hooks)
- @merge_request = service.execute(merge_request)
- @merge_request.reload
+ perform_enqueued_jobs do
+ @merge_request = service.execute(merge_request)
+ @merge_request.reload
+ end
end
it { expect(@merge_request).to be_valid }
@@ -56,12 +69,6 @@ describe MergeRequests::UpdateService do
expect(email.subject).to include(merge_request.title)
end
- def find_note(starting_with)
- @merge_request.notes.find do |note|
- note && note.note.start_with?(starting_with)
- end
- end
-
it 'should create system note about merge_request reassign' do
note = find_note('Reassigned to')
@@ -90,5 +97,39 @@ describe MergeRequests::UpdateService do
expect(note.note).to eq 'Target branch changed from `master` to `target`'
end
end
+
+ context 'when MergeRequest has tasks' do
+ before { update_merge_request({ description: "- [ ] Task 1\n- [ ] Task 2" }) }
+
+ it { expect(@merge_request.tasks?).to eq(true) }
+
+ context 'when tasks are marked as completed' do
+ before { update_merge_request({ description: "- [x] Task 1\n- [X] Task 2" }) }
+
+ it 'creates system note about task status change' do
+ note1 = find_note('Marked the task **Task 1** as completed')
+ note2 = find_note('Marked the task **Task 2** as completed')
+
+ expect(note1).not_to be_nil
+ expect(note2).not_to be_nil
+ end
+ end
+
+ context 'when tasks are marked as incomplete' do
+ before do
+ update_merge_request({ description: "- [x] Task 1\n- [X] Task 2" })
+ update_merge_request({ description: "- [ ] Task 1\n- [ ] Task 2" })
+ end
+
+ it 'creates system note about task status change' do
+ note1 = find_note('Marked the task **Task 1** as incomplete')
+ note2 = find_note('Marked the task **Task 2** as incomplete')
+
+ expect(note1).not_to be_nil
+ expect(note2).not_to be_nil
+ end
+ end
+ end
+
end
end
diff --git a/spec/services/notes/create_service_spec.rb b/spec/services/notes/create_service_spec.rb
index f2ea0805b2f..cc38d257792 100644
--- a/spec/services/notes/create_service_spec.rb
+++ b/spec/services/notes/create_service_spec.rb
@@ -24,4 +24,38 @@ describe Notes::CreateService do
it { expect(@note.note).to eq('Awesome comment') }
end
end
+
+ describe "award emoji" do
+ before do
+ project.team << [user, :master]
+ end
+
+ it "creates emoji note" do
+ opts = {
+ note: ':smile: ',
+ noteable_type: 'Issue',
+ noteable_id: issue.id
+ }
+
+ @note = Notes::CreateService.new(project, user, opts).execute
+
+ expect(@note).to be_valid
+ expect(@note.note).to eq('smile')
+ expect(@note.is_award).to be_truthy
+ end
+
+ it "creates regular note if emoji name is invalid" do
+ opts = {
+ note: ':smile: moretext: ',
+ noteable_type: 'Issue',
+ noteable_id: issue.id
+ }
+
+ @note = Notes::CreateService.new(project, user, opts).execute
+
+ expect(@note).to be_valid
+ expect(@note.note).to eq(opts[:note])
+ expect(@note.is_award).to be_falsy
+ end
+ end
end
diff --git a/spec/services/notification_service_spec.rb b/spec/services/notification_service_spec.rb
index 520140917aa..a4e2b2953cc 100644
--- a/spec/services/notification_service_spec.rb
+++ b/spec/services/notification_service_spec.rb
@@ -3,6 +3,12 @@ require 'spec_helper'
describe NotificationService do
let(:notification) { NotificationService.new }
+ around(:each) do |example|
+ perform_enqueued_jobs do
+ example.run
+ end
+ end
+
describe 'Keys' do
describe :new_key do
let!(:key) { create(:personal_key) }
@@ -10,8 +16,7 @@ describe NotificationService do
it { expect(notification.new_key(key)).to be_truthy }
it 'should sent email to key owner' do
- expect(Notify).to receive(:new_ssh_key_email).with(key.id)
- notification.new_key(key)
+ expect{ notification.new_key(key) }.to change{ ActionMailer::Base.deliveries.size }.by(1)
end
end
end
@@ -23,8 +28,7 @@ describe NotificationService do
it { expect(notification.new_email(email)).to be_truthy }
it 'should send email to email owner' do
- expect(Notify).to receive(:new_email_email).with(email.id)
- notification.new_email(email)
+ expect{ notification.new_email(email) }.to change{ ActionMailer::Base.deliveries.size }.by(1)
end
end
end
@@ -47,18 +51,20 @@ describe NotificationService do
it do
add_users_with_subscription(note.project, issue)
- should_email(@u_watcher.id)
- should_email(note.noteable.author_id)
- should_email(note.noteable.assignee_id)
- should_email(@u_mentioned.id)
- should_email(@subscriber.id)
- should_not_email(note.author_id)
- should_not_email(@u_participating.id)
- should_not_email(@u_disabled.id)
- should_not_email(@unsubscriber.id)
- should_not_email(@u_outsider_mentioned)
+ ActionMailer::Base.deliveries.clear
notification.new_note(note)
+
+ should_email(@u_watcher)
+ should_email(note.noteable.author)
+ should_email(note.noteable.assignee)
+ should_email(@u_mentioned)
+ should_email(@subscriber)
+ should_not_email(note.author)
+ should_not_email(@u_participating)
+ should_not_email(@u_disabled)
+ should_not_email(@unsubscriber)
+ should_not_email(@u_outsider_mentioned)
end
it 'filters out "mentioned in" notes' do
@@ -82,26 +88,20 @@ describe NotificationService do
group_member = note.project.group.group_members.find_by_user_id(@u_watcher.id)
group_member.notification_level = Notification::N_GLOBAL
group_member.save
+ ActionMailer::Base.deliveries.clear
end
it do
- should_email(note.noteable.author_id)
- should_email(note.noteable.assignee_id)
- should_email(@u_mentioned.id)
- should_not_email(@u_watcher.id)
- should_not_email(note.author_id)
- should_not_email(@u_participating.id)
- should_not_email(@u_disabled.id)
notification.new_note(note)
- end
- end
- def should_email(user_id)
- expect(Notify).to receive(:note_issue_email).with(user_id, note.id)
- end
-
- def should_not_email(user_id)
- expect(Notify).not_to receive(:note_issue_email).with(user_id, note.id)
+ should_email(note.noteable.author)
+ should_email(note.noteable.assignee)
+ should_email(@u_mentioned)
+ should_not_email(@u_watcher)
+ should_not_email(note.author)
+ should_not_email(@u_participating)
+ should_not_email(@u_disabled)
+ end
end
end
@@ -113,24 +113,26 @@ describe NotificationService do
before do
build_team(note.project)
+ ActionMailer::Base.deliveries.clear
end
describe :new_note do
it do
+ notification.new_note(note)
+
# Notify all team members
note.project.team.members.each do |member|
# User with disabled notification should not be notified
next if member.id == @u_disabled.id
- should_email(member.id)
+ should_email(member)
end
- should_email(note.noteable.author_id)
- should_email(note.noteable.assignee_id)
- should_not_email(note.author_id)
- should_not_email(@u_mentioned.id)
- should_not_email(@u_disabled.id)
- should_not_email(@u_not_mentioned.id)
- notification.new_note(note)
+ should_email(note.noteable.author)
+ should_email(note.noteable.assignee)
+ should_not_email(note.author)
+ should_email(@u_mentioned)
+ should_not_email(@u_disabled)
+ should_email(@u_not_mentioned)
end
it 'filters out "mentioned in" notes' do
@@ -140,14 +142,6 @@ describe NotificationService do
notification.new_note(mentioned_note)
end
end
-
- def should_email(user_id)
- expect(Notify).to receive(:note_issue_email).with(user_id, note.id)
- end
-
- def should_not_email(user_id)
- expect(Notify).not_to receive(:note_issue_email).with(user_id, note.id)
- end
end
context 'commit note' do
@@ -156,43 +150,38 @@ describe NotificationService do
before do
build_team(note.project)
+ ActionMailer::Base.deliveries.clear
allow_any_instance_of(Commit).to receive(:author).and_return(@u_committer)
end
- describe :new_note do
+ describe :new_note, :perform_enqueued_jobs do
it do
- should_email(@u_committer.id, note)
- should_email(@u_watcher.id, note)
- should_not_email(@u_mentioned.id, note)
- should_not_email(note.author_id, note)
- should_not_email(@u_participating.id, note)
- should_not_email(@u_disabled.id, note)
notification.new_note(note)
+
+ should_email(@u_committer)
+ should_email(@u_watcher)
+ should_not_email(@u_mentioned)
+ should_not_email(note.author)
+ should_not_email(@u_participating)
+ should_not_email(@u_disabled)
end
it do
note.update_attribute(:note, '@mention referenced')
- should_email(@u_committer.id, note)
- should_email(@u_watcher.id, note)
- should_email(@u_mentioned.id, note)
- should_not_email(note.author_id, note)
- should_not_email(@u_participating.id, note)
- should_not_email(@u_disabled.id, note)
notification.new_note(note)
+
+ should_email(@u_committer)
+ should_email(@u_watcher)
+ should_email(@u_mentioned)
+ should_not_email(note.author)
+ should_not_email(@u_participating)
+ should_not_email(@u_disabled)
end
it do
@u_committer.update_attributes(notification_level: Notification::N_MENTION)
- should_not_email(@u_committer.id, note)
notification.new_note(note)
- end
-
- def should_email(user_id, n)
- expect(Notify).to receive(:note_commit_email).with(user_id, n.id)
- end
-
- def should_not_email(user_id, n)
- expect(Notify).not_to receive(:note_commit_email).with(user_id, n.id)
+ should_not_email(@u_committer)
end
end
end
@@ -205,99 +194,69 @@ describe NotificationService do
before do
build_team(issue.project)
add_users_with_subscription(issue.project, issue)
+ ActionMailer::Base.deliveries.clear
end
describe :new_issue do
it do
- should_email(issue.assignee_id)
- should_email(@u_watcher.id)
- should_email(@u_participant_mentioned.id)
- should_not_email(@u_mentioned.id)
- should_not_email(@u_participating.id)
- should_not_email(@u_disabled.id)
notification.new_issue(issue, @u_disabled)
+
+ should_email(issue.assignee)
+ should_email(@u_watcher)
+ should_email(@u_participant_mentioned)
+ should_not_email(@u_mentioned)
+ should_not_email(@u_participating)
+ should_not_email(@u_disabled)
end
it do
issue.assignee.update_attributes(notification_level: Notification::N_MENTION)
- should_not_email(issue.assignee_id)
notification.new_issue(issue, @u_disabled)
- end
-
- def should_email(user_id)
- expect(Notify).to receive(:new_issue_email).with(user_id, issue.id)
- end
- def should_not_email(user_id)
- expect(Notify).not_to receive(:new_issue_email).with(user_id, issue.id)
+ should_not_email(issue.assignee)
end
end
describe :reassigned_issue do
it 'should email new assignee' do
- should_email(issue.assignee_id)
- should_email(@u_watcher.id)
- should_email(@u_participant_mentioned.id)
- should_email(@subscriber.id)
- should_not_email(@unsubscriber.id)
- should_not_email(@u_participating.id)
- should_not_email(@u_disabled.id)
-
notification.reassigned_issue(issue, @u_disabled)
- end
-
- def should_email(user_id)
- expect(Notify).to receive(:reassigned_issue_email).with(user_id, issue.id, nil, @u_disabled.id)
- end
- def should_not_email(user_id)
- expect(Notify).not_to receive(:reassigned_issue_email).with(user_id, issue.id, issue.assignee_id, @u_disabled.id)
+ should_email(issue.assignee)
+ should_email(@u_watcher)
+ should_email(@u_participant_mentioned)
+ should_email(@subscriber)
+ should_not_email(@unsubscriber)
+ should_not_email(@u_participating)
+ should_not_email(@u_disabled)
end
end
describe :close_issue do
it 'should sent email to issue assignee and issue author' do
- should_email(issue.assignee_id)
- should_email(issue.author_id)
- should_email(@u_watcher.id)
- should_email(@u_participant_mentioned.id)
- should_email(@subscriber.id)
- should_not_email(@unsubscriber.id)
- should_not_email(@u_participating.id)
- should_not_email(@u_disabled.id)
-
notification.close_issue(issue, @u_disabled)
- end
- def should_email(user_id)
- expect(Notify).to receive(:closed_issue_email).with(user_id, issue.id, @u_disabled.id)
- end
-
- def should_not_email(user_id)
- expect(Notify).not_to receive(:closed_issue_email).with(user_id, issue.id, @u_disabled.id)
+ should_email(issue.assignee)
+ should_email(issue.author)
+ should_email(@u_watcher)
+ should_email(@u_participant_mentioned)
+ should_email(@subscriber)
+ should_not_email(@unsubscriber)
+ should_not_email(@u_participating)
+ should_not_email(@u_disabled)
end
end
describe :reopen_issue do
it 'should send email to issue assignee and issue author' do
- should_email(issue.assignee_id)
- should_email(issue.author_id)
- should_email(@u_watcher.id)
- should_email(@u_participant_mentioned.id)
- should_email(@subscriber.id)
- should_not_email(@unsubscriber.id)
- should_not_email(@u_participating.id)
- should_not_email(@u_disabled.id)
-
notification.reopen_issue(issue, @u_disabled)
- end
-
- def should_email(user_id)
- expect(Notify).to receive(:issue_status_changed_email).with(user_id, issue.id, 'reopened', @u_disabled.id)
- end
- def should_not_email(user_id)
- expect(Notify).not_to receive(:issue_status_changed_email).with(user_id, issue.id, 'reopened', @u_disabled.id)
+ should_email(issue.assignee)
+ should_email(issue.author)
+ should_email(@u_watcher)
+ should_email(@u_participant_mentioned)
+ should_email(@subscriber)
+ should_not_email(@unsubscriber)
+ should_not_email(@u_participating)
end
end
end
@@ -309,108 +268,74 @@ describe NotificationService do
before do
build_team(merge_request.target_project)
add_users_with_subscription(merge_request.target_project, merge_request)
+ ActionMailer::Base.deliveries.clear
end
describe :new_merge_request do
it do
- should_email(merge_request.assignee_id)
- should_email(@u_watcher.id)
- should_email(@u_participant_mentioned.id)
- should_not_email(@u_participating.id)
- should_not_email(@u_disabled.id)
notification.new_merge_request(merge_request, @u_disabled)
- end
- def should_email(user_id)
- expect(Notify).to receive(:new_merge_request_email).with(user_id, merge_request.id)
- end
-
- def should_not_email(user_id)
- expect(Notify).not_to receive(:new_merge_request_email).with(user_id, merge_request.id)
+ should_email(merge_request.assignee)
+ should_email(@u_watcher)
+ should_email(@u_participant_mentioned)
+ should_not_email(@u_participating)
+ should_not_email(@u_disabled)
end
end
describe :reassigned_merge_request do
it do
- should_email(merge_request.assignee_id)
- should_email(@u_watcher.id)
- should_email(@u_participant_mentioned.id)
- should_email(@subscriber.id)
- should_not_email(@unsubscriber.id)
- should_not_email(@u_participating.id)
- should_not_email(@u_disabled.id)
notification.reassigned_merge_request(merge_request, merge_request.author)
- end
-
- def should_email(user_id)
- expect(Notify).to receive(:reassigned_merge_request_email).with(user_id, merge_request.id, nil, merge_request.author_id)
- end
- def should_not_email(user_id)
- expect(Notify).not_to receive(:reassigned_merge_request_email).with(user_id, merge_request.id, merge_request.assignee_id, merge_request.author_id)
+ should_email(merge_request.assignee)
+ should_email(@u_watcher)
+ should_email(@u_participant_mentioned)
+ should_email(@subscriber)
+ should_not_email(@unsubscriber)
+ should_not_email(@u_participating)
+ should_not_email(@u_disabled)
end
end
describe :closed_merge_request do
it do
- should_email(merge_request.assignee_id)
- should_email(@u_watcher.id)
- should_email(@u_participant_mentioned.id)
- should_email(@subscriber.id)
- should_not_email(@unsubscriber.id)
- should_not_email(@u_participating.id)
- should_not_email(@u_disabled.id)
notification.close_mr(merge_request, @u_disabled)
- end
-
- def should_email(user_id)
- expect(Notify).to receive(:closed_merge_request_email).with(user_id, merge_request.id, @u_disabled.id)
- end
- def should_not_email(user_id)
- expect(Notify).not_to receive(:closed_merge_request_email).with(user_id, merge_request.id, @u_disabled.id)
+ should_email(merge_request.assignee)
+ should_email(@u_watcher)
+ should_email(@u_participant_mentioned)
+ should_email(@subscriber)
+ should_not_email(@unsubscriber)
+ should_not_email(@u_participating)
+ should_not_email(@u_disabled)
end
end
describe :merged_merge_request do
it do
- should_email(merge_request.assignee_id)
- should_email(@u_watcher.id)
- should_email(@u_participant_mentioned.id)
- should_email(@subscriber.id)
- should_not_email(@unsubscriber.id)
- should_not_email(@u_participating.id)
- should_not_email(@u_disabled.id)
notification.merge_mr(merge_request, @u_disabled)
- end
-
- def should_email(user_id)
- expect(Notify).to receive(:merged_merge_request_email).with(user_id, merge_request.id, @u_disabled.id)
- end
- def should_not_email(user_id)
- expect(Notify).not_to receive(:merged_merge_request_email).with(user_id, merge_request.id, @u_disabled.id)
+ should_email(merge_request.assignee)
+ should_email(@u_watcher)
+ should_email(@u_participant_mentioned)
+ should_email(@subscriber)
+ should_not_email(@unsubscriber)
+ should_not_email(@u_participating)
+ should_not_email(@u_disabled)
end
end
describe :reopen_merge_request do
it do
- should_email(merge_request.assignee_id)
- should_email(@u_watcher.id)
- should_email(@u_participant_mentioned.id)
- should_email(@subscriber.id)
- should_not_email(@unsubscriber.id)
- should_not_email(@u_participating.id)
- should_not_email(@u_disabled.id)
notification.reopen_mr(merge_request, @u_disabled)
- end
- def should_email(user_id)
- expect(Notify).to receive(:merge_request_status_email).with(user_id, merge_request.id, 'reopened', @u_disabled.id)
- end
-
- def should_not_email(user_id)
- expect(Notify).not_to receive(:merge_request_status_email).with(user_id, merge_request.id, 'reopened', @u_disabled.id)
+ should_email(merge_request.assignee)
+ should_email(@u_watcher)
+ should_email(@u_participant_mentioned)
+ should_email(@subscriber)
+ should_not_email(@unsubscriber)
+ should_not_email(@u_participating)
+ should_not_email(@u_disabled)
end
end
end
@@ -420,22 +345,16 @@ describe NotificationService do
before do
build_team(project)
+ ActionMailer::Base.deliveries.clear
end
describe :project_was_moved do
it do
- should_email(@u_watcher.id)
- should_email(@u_participating.id)
- should_not_email(@u_disabled.id)
notification.project_was_moved(project, "gitlab/gitlab")
- end
-
- def should_email(user_id)
- expect(Notify).to receive(:project_was_moved_email).with(project.id, user_id, "gitlab/gitlab")
- end
- def should_not_email(user_id)
- expect(Notify).not_to receive(:project_was_moved_email).with(project.id, user_id, "gitlab/gitlab")
+ should_email(@u_watcher)
+ should_email(@u_participating)
+ should_not_email(@u_disabled)
end
end
end
@@ -469,4 +388,18 @@ describe NotificationService do
issuable.subscriptions.create(user: @subscriber, subscribed: true)
issuable.subscriptions.create(user: @unsubscriber, subscribed: false)
end
+
+ def sent_to_user?(user)
+ ActionMailer::Base.deliveries.any? do |message|
+ message.to.include?(user.email)
+ end
+ end
+
+ def should_email(user)
+ expect(sent_to_user?(user)).to be_truthy
+ end
+
+ def should_not_email(user)
+ expect(sent_to_user?(user)).to be_falsey
+ end
end
diff --git a/spec/services/update_release_service_spec.rb b/spec/services/update_release_service_spec.rb
new file mode 100644
index 00000000000..93368c45b88
--- /dev/null
+++ b/spec/services/update_release_service_spec.rb
@@ -0,0 +1,34 @@
+require 'spec_helper'
+
+describe UpdateReleaseService do
+ let(:project) { create(:project) }
+ let(:user) { create(:user) }
+ let(:tag_name) { project.repository.tag_names.first }
+ let(:description) { 'Awesome release!' }
+ let(:new_description) { 'The best release!' }
+ let(:service) { UpdateReleaseService.new(project, user) }
+
+ context 'with an existing release' do
+ let(:create_service) { CreateReleaseService.new(project, user) }
+
+ before do
+ create_service.execute(tag_name, description)
+ end
+
+ it 'successfully updates an existing release' do
+ result = service.execute(tag_name, new_description)
+ expect(result[:status]).to eq(:success)
+ expect(project.releases.find_by(tag: tag_name).description).to eq(new_description)
+ end
+ end
+
+ it 'raises an error if the tag does not exist' do
+ result = service.execute("foobar", description)
+ expect(result[:status]).to eq(:error)
+ end
+
+ it 'raises an error if the release does not exist' do
+ result = service.execute(tag_name, description)
+ expect(result[:status]).to eq(:error)
+ end
+end
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index 2be13bb3e6a..0225a0ee53f 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -31,6 +31,7 @@ RSpec.configure do |config|
config.include StubConfiguration
config.include RelativeUrl, type: feature
config.include TestEnv
+ config.include ActiveJob::TestHelper
config.include StubGitlabCalls
config.include StubGitlabData
config.include BenchmarkMatchers, benchmark: true
diff --git a/spec/tasks/gitlab/backup_rake_spec.rb b/spec/tasks/gitlab/backup_rake_spec.rb
index fb5e74af648..63bed2414df 100644
--- a/spec/tasks/gitlab/backup_rake_spec.rb
+++ b/spec/tasks/gitlab/backup_rake_spec.rb
@@ -16,7 +16,7 @@ describe 'gitlab:app namespace rake task' do
end
def reenable_backup_sub_tasks
- %w{db repo uploads builds artifacts}.each do |subtask|
+ %w{db repo uploads builds artifacts lfs}.each do |subtask|
Rake::Task["gitlab:backup:#{subtask}:create"].reenable
end
end
@@ -49,7 +49,7 @@ describe 'gitlab:app namespace rake task' do
to raise_error(SystemExit)
end
- it 'should invoke restoration on mach' do
+ it 'should invoke restoration on match' do
allow(YAML).to receive(:load_file).
and_return({ gitlab_version: gitlab_version })
expect(Rake::Task["gitlab:backup:db:restore"]).to receive(:invoke)
@@ -57,6 +57,7 @@ describe 'gitlab:app namespace rake task' do
expect(Rake::Task["gitlab:backup:builds:restore"]).to receive(:invoke)
expect(Rake::Task["gitlab:backup:uploads:restore"]).to receive(:invoke)
expect(Rake::Task["gitlab:backup:artifacts:restore"]).to receive(:invoke)
+ expect(Rake::Task["gitlab:backup:lfs:restore"]).to receive(:invoke)
expect(Rake::Task["gitlab:shell:setup"]).to receive(:invoke)
expect { run_rake_task('gitlab:backup:restore') }.not_to raise_error
end
@@ -114,7 +115,7 @@ describe 'gitlab:app namespace rake task' do
it 'should set correct permissions on the tar contents' do
tar_contents, exit_status = Gitlab::Popen.popen(
- %W{tar -tvf #{@backup_tar} db uploads.tar.gz repositories builds.tar.gz artifacts.tar.gz}
+ %W{tar -tvf #{@backup_tar} db uploads.tar.gz repositories builds.tar.gz artifacts.tar.gz lfs.tar.gz}
)
expect(exit_status).to eq(0)
expect(tar_contents).to match('db/')
@@ -122,12 +123,13 @@ describe 'gitlab:app namespace rake task' do
expect(tar_contents).to match('repositories/')
expect(tar_contents).to match('builds.tar.gz')
expect(tar_contents).to match('artifacts.tar.gz')
+ expect(tar_contents).to match('lfs.tar.gz')
expect(tar_contents).not_to match(/^.{4,9}[rwx].* (database.sql.gz|uploads.tar.gz|repositories|builds.tar.gz|artifacts.tar.gz)\/$/)
end
it 'should delete temp directories' do
temp_dirs = Dir.glob(
- File.join(Gitlab.config.backup.path, '{db,repositories,uploads,builds,artifacts}')
+ File.join(Gitlab.config.backup.path, '{db,repositories,uploads,builds,artifacts,lfs}')
)
expect(temp_dirs).to be_empty
@@ -163,13 +165,14 @@ describe 'gitlab:app namespace rake task' do
it "does not contain skipped item" do
tar_contents, _exit_status = Gitlab::Popen.popen(
- %W{tar -tvf #{@backup_tar} db uploads.tar.gz repositories builds.tar.gz artifacts.tar.gz}
+ %W{tar -tvf #{@backup_tar} db uploads.tar.gz repositories builds.tar.gz artifacts.tar.gz lfs.tar.gz}
)
expect(tar_contents).to match('db/')
expect(tar_contents).to match('uploads.tar.gz')
expect(tar_contents).to match('builds.tar.gz')
expect(tar_contents).to match('artifacts.tar.gz')
+ expect(tar_contents).to match('lfs.tar.gz')
expect(tar_contents).not_to match('repositories/')
end
@@ -183,6 +186,7 @@ describe 'gitlab:app namespace rake task' do
expect(Rake::Task["gitlab:backup:uploads:restore"]).not_to receive :invoke
expect(Rake::Task["gitlab:backup:builds:restore"]).to receive :invoke
expect(Rake::Task["gitlab:backup:artifacts:restore"]).to receive :invoke
+ expect(Rake::Task["gitlab:backup:lfs:restore"]).to receive :invoke
expect(Rake::Task["gitlab:shell:setup"]).to receive :invoke
expect { run_rake_task('gitlab:backup:restore') }.not_to raise_error
end
diff --git a/spec/workers/email_receiver_worker_spec.rb b/spec/workers/email_receiver_worker_spec.rb
index 65a8d7d9197..de40a6f78af 100644
--- a/spec/workers/email_receiver_worker_spec.rb
+++ b/spec/workers/email_receiver_worker_spec.rb
@@ -21,12 +21,14 @@ describe EmailReceiverWorker do
end
it "sends out a rejection email" do
- described_class.new.perform(raw_message)
-
- email = ActionMailer::Base.deliveries.last
- expect(email).not_to be_nil
- expect(email.to).to eq(["jake@adventuretime.ooo"])
- expect(email.subject).to include("Rejected")
+ perform_enqueued_jobs do
+ described_class.new.perform(raw_message)
+
+ email = ActionMailer::Base.deliveries.last
+ expect(email).not_to be_nil
+ expect(email.to).to eq(["jake@adventuretime.ooo"])
+ expect(email.subject).to include("Rejected")
+ end
end
end
end