summaryrefslogtreecommitdiff
path: root/spec/requests
diff options
context:
space:
mode:
authorRégis Freyd (GitLab) <regis@gitlab.com>2016-09-06 14:06:16 +0000
committerRégis Freyd (GitLab) <regis@gitlab.com>2016-09-06 14:06:16 +0000
commitb44636c259e7a655a60cc2b98431d6d00a73e002 (patch)
tree93545ea821319c23410a444f676c8e5a66daeecf /spec/requests
parent310beb9002f1bbdd07abe5bba6712769773a99b2 (diff)
parente9e8c67fb7d58288dbac1777b63ea7d3128d6268 (diff)
downloadgitlab-ce-email-in-slash-commands.tar.gz
Merge branch 'master' into 'email-in-slash-commands'email-in-slash-commands
# Conflicts: # doc/user/project/slash_commands.md # doc/workflow/README.md
Diffstat (limited to 'spec/requests')
-rw-r--r--spec/requests/api/api_helpers_spec.rb27
-rw-r--r--spec/requests/api/award_emoji_spec.rb18
-rw-r--r--spec/requests/api/broadcast_messages_spec.rb180
-rw-r--r--spec/requests/api/builds_spec.rb20
-rw-r--r--spec/requests/api/commits_spec.rb4
-rw-r--r--spec/requests/api/internal_spec.rb62
-rw-r--r--spec/requests/api/issues_spec.rb91
-rw-r--r--spec/requests/api/merge_request_diffs_spec.rb49
-rw-r--r--spec/requests/api/merge_requests_spec.rb10
-rw-r--r--spec/requests/api/notes_spec.rb2
-rw-r--r--spec/requests/api/project_hooks_spec.rb8
-rw-r--r--spec/requests/api/project_snippets_spec.rb1
-rw-r--r--spec/requests/api/projects_spec.rb37
-rw-r--r--spec/requests/api/users_spec.rb1
-rw-r--r--spec/requests/git_http_spec.rb3
-rw-r--r--spec/requests/jwt_controller_spec.rb13
-rw-r--r--spec/requests/lfs_http_spec.rb107
-rw-r--r--spec/requests/projects/artifacts_controller_spec.rb117
18 files changed, 730 insertions, 20 deletions
diff --git a/spec/requests/api/api_helpers_spec.rb b/spec/requests/api/api_helpers_spec.rb
index c65510fadec..bbdf8f03c2b 100644
--- a/spec/requests/api/api_helpers_spec.rb
+++ b/spec/requests/api/api_helpers_spec.rb
@@ -3,6 +3,7 @@ require 'spec_helper'
describe API::Helpers, api: true do
include API::Helpers
include ApiHelpers
+ include SentryHelper
let(:user) { create(:user) }
let(:admin) { create(:admin) }
@@ -234,4 +235,30 @@ describe API::Helpers, api: true do
expect(to_boolean(nil)).to be_nil
end
end
+
+ describe '.handle_api_exception' do
+ before do
+ allow_any_instance_of(self.class).to receive(:sentry_enabled?).and_return(true)
+ allow_any_instance_of(self.class).to receive(:rack_response)
+ end
+
+ it 'does not report a MethodNotAllowed exception to Sentry' do
+ exception = Grape::Exceptions::MethodNotAllowed.new({ 'X-GitLab-Test' => '1' })
+ allow(exception).to receive(:backtrace).and_return(caller)
+
+ expect(Raven).not_to receive(:capture_exception).with(exception)
+
+ handle_api_exception(exception)
+ end
+
+ it 'does report RuntimeError to Sentry' do
+ exception = RuntimeError.new('test error')
+ allow(exception).to receive(:backtrace).and_return(caller)
+
+ expect_any_instance_of(self.class).to receive(:sentry_context)
+ expect(Raven).to receive(:capture_exception).with(exception)
+
+ handle_api_exception(exception)
+ end
+ end
end
diff --git a/spec/requests/api/award_emoji_spec.rb b/spec/requests/api/award_emoji_spec.rb
index 73c268c0d1e..981a6791881 100644
--- a/spec/requests/api/award_emoji_spec.rb
+++ b/spec/requests/api/award_emoji_spec.rb
@@ -4,7 +4,7 @@ describe API::API, api: true do
include ApiHelpers
let(:user) { create(:user) }
let!(:project) { create(:project) }
- let(:issue) { create(:issue, project: project, author: user) }
+ let(:issue) { create(:issue, project: project) }
let!(:award_emoji) { create(:award_emoji, awardable: issue, user: user) }
let!(:merge_request) { create(:merge_request, source_project: project, target_project: project) }
let!(:downvote) { create(:award_emoji, :downvote, awardable: merge_request, user: user) }
@@ -115,6 +115,8 @@ describe API::API, api: true do
end
describe "POST /projects/:id/awardable/:awardable_id/award_emoji" do
+ let(:issue2) { create(:issue, project: project, author: user) }
+
context "on an issue" do
it "creates a new award emoji" do
post api("/projects/#{project.id}/issues/#{issue.id}/award_emoji", user), name: 'blowfish'
@@ -136,6 +138,12 @@ describe API::API, api: true do
expect(response).to have_http_status(401)
end
+ it "returns a 404 error if the user authored issue" do
+ post api("/projects/#{project.id}/issues/#{issue2.id}/award_emoji", user), name: 'thumbsup'
+
+ expect(response).to have_http_status(404)
+ end
+
it "normalizes +1 as thumbsup award" do
post api("/projects/#{project.id}/issues/#{issue.id}/award_emoji", user), name: '+1'
@@ -155,6 +163,8 @@ describe API::API, api: true do
end
describe "POST /projects/:id/awardable/:awardable_id/notes/:note_id/award_emoji" do
+ let(:note2) { create(:note, project: project, noteable: issue, author: user) }
+
it 'creates a new award emoji' do
expect do
post api("/projects/#{project.id}/issues/#{issue.id}/notes/#{note.id}/award_emoji", user), name: 'rocket'
@@ -164,6 +174,12 @@ describe API::API, api: true do
expect(json_response['user']['username']).to eq(user.username)
end
+ it "it returns 404 error when user authored note" do
+ post api("/projects/#{project.id}/issues/#{issue.id}/notes/#{note2.id}/award_emoji", user), name: 'thumbsup'
+
+ expect(response).to have_http_status(404)
+ end
+
it "normalizes +1 as thumbsup award" do
post api("/projects/#{project.id}/issues/#{issue.id}/notes/#{note.id}/award_emoji", user), name: '+1'
diff --git a/spec/requests/api/broadcast_messages_spec.rb b/spec/requests/api/broadcast_messages_spec.rb
new file mode 100644
index 00000000000..7c9078b2864
--- /dev/null
+++ b/spec/requests/api/broadcast_messages_spec.rb
@@ -0,0 +1,180 @@
+require 'spec_helper'
+
+describe API::BroadcastMessages, api: true do
+ include ApiHelpers
+
+ let(:user) { create(:user) }
+ let(:admin) { create(:admin) }
+
+ describe 'GET /broadcast_messages' do
+ it 'returns a 401 for anonymous users' do
+ get api('/broadcast_messages')
+
+ expect(response).to have_http_status(401)
+ end
+
+ it 'returns a 403 for users' do
+ get api('/broadcast_messages', user)
+
+ expect(response).to have_http_status(403)
+ end
+
+ it 'returns an Array of BroadcastMessages for admins' do
+ create(:broadcast_message)
+
+ get api('/broadcast_messages', admin)
+
+ expect(response).to have_http_status(200)
+ expect(json_response).to be_kind_of(Array)
+ expect(json_response.first.keys)
+ .to match_array(%w(id message starts_at ends_at color font active))
+ end
+ end
+
+ describe 'GET /broadcast_messages/:id' do
+ let!(:message) { create(:broadcast_message) }
+
+ it 'returns a 401 for anonymous users' do
+ get api("/broadcast_messages/#{message.id}")
+
+ expect(response).to have_http_status(401)
+ end
+
+ it 'returns a 403 for users' do
+ get api("/broadcast_messages/#{message.id}", user)
+
+ expect(response).to have_http_status(403)
+ end
+
+ it 'returns the specified message for admins' do
+ get api("/broadcast_messages/#{message.id}", admin)
+
+ expect(response).to have_http_status(200)
+ expect(json_response['id']).to eq message.id
+ expect(json_response.keys)
+ .to match_array(%w(id message starts_at ends_at color font active))
+ end
+ end
+
+ describe 'POST /broadcast_messages' do
+ it 'returns a 401 for anonymous users' do
+ post api('/broadcast_messages'), attributes_for(:broadcast_message)
+
+ expect(response).to have_http_status(401)
+ end
+
+ it 'returns a 403 for users' do
+ post api('/broadcast_messages', user), attributes_for(:broadcast_message)
+
+ expect(response).to have_http_status(403)
+ end
+
+ context 'as an admin' do
+ it 'requires the `message` parameter' do
+ attrs = attributes_for(:broadcast_message)
+ attrs.delete(:message)
+
+ post api('/broadcast_messages', admin), attrs
+
+ expect(response).to have_http_status(400)
+ expect(json_response['error']).to eq 'message is missing'
+ end
+
+ it 'defines sane default start and end times' do
+ time = Time.zone.parse('2016-07-02 10:11:12')
+ travel_to(time) do
+ post api('/broadcast_messages', admin), message: 'Test message'
+
+ expect(response).to have_http_status(201)
+ expect(json_response['starts_at']).to eq '2016-07-02T10:11:12.000Z'
+ expect(json_response['ends_at']).to eq '2016-07-02T11:11:12.000Z'
+ end
+ end
+
+ it 'accepts a custom background and foreground color' do
+ attrs = attributes_for(:broadcast_message, color: '#000000', font: '#cecece')
+
+ post api('/broadcast_messages', admin), attrs
+
+ expect(response).to have_http_status(201)
+ expect(json_response['color']).to eq attrs[:color]
+ expect(json_response['font']).to eq attrs[:font]
+ end
+ end
+ end
+
+ describe 'PUT /broadcast_messages/:id' do
+ let!(:message) { create(:broadcast_message) }
+
+ it 'returns a 401 for anonymous users' do
+ put api("/broadcast_messages/#{message.id}"),
+ attributes_for(:broadcast_message)
+
+ expect(response).to have_http_status(401)
+ end
+
+ it 'returns a 403 for users' do
+ put api("/broadcast_messages/#{message.id}", user),
+ attributes_for(:broadcast_message)
+
+ expect(response).to have_http_status(403)
+ end
+
+ context 'as an admin' do
+ it 'accepts new background and foreground colors' do
+ attrs = { color: '#000000', font: '#cecece' }
+
+ put api("/broadcast_messages/#{message.id}", admin), attrs
+
+ expect(response).to have_http_status(200)
+ expect(json_response['color']).to eq attrs[:color]
+ expect(json_response['font']).to eq attrs[:font]
+ end
+
+ it 'accepts new start and end times' do
+ time = Time.zone.parse('2016-07-02 10:11:12')
+ travel_to(time) do
+ attrs = { starts_at: Time.zone.now, ends_at: 3.hours.from_now }
+
+ put api("/broadcast_messages/#{message.id}", admin), attrs
+
+ expect(response).to have_http_status(200)
+ expect(json_response['starts_at']).to eq '2016-07-02T10:11:12.000Z'
+ expect(json_response['ends_at']).to eq '2016-07-02T13:11:12.000Z'
+ end
+ end
+
+ it 'accepts a new message' do
+ attrs = { message: 'new message' }
+
+ put api("/broadcast_messages/#{message.id}", admin), attrs
+
+ expect(response).to have_http_status(200)
+ expect { message.reload }.to change { message.message }.to('new message')
+ end
+ end
+ end
+
+ describe 'DELETE /broadcast_messages/:id' do
+ let!(:message) { create(:broadcast_message) }
+
+ it 'returns a 401 for anonymous users' do
+ delete api("/broadcast_messages/#{message.id}"),
+ attributes_for(:broadcast_message)
+
+ expect(response).to have_http_status(401)
+ end
+
+ it 'returns a 403 for users' do
+ delete api("/broadcast_messages/#{message.id}", user),
+ attributes_for(:broadcast_message)
+
+ expect(response).to have_http_status(403)
+ end
+
+ it 'deletes the broadcast message for admins' do
+ expect { delete api("/broadcast_messages/#{message.id}", admin) }
+ .to change { BroadcastMessage.count }.by(-1)
+ end
+ end
+end
diff --git a/spec/requests/api/builds_spec.rb b/spec/requests/api/builds_spec.rb
index 9a17a705b1e..ee0b61e2ca4 100644
--- a/spec/requests/api/builds_spec.rb
+++ b/spec/requests/api/builds_spec.rb
@@ -15,7 +15,9 @@ describe API::API, api: true do
describe 'GET /projects/:id/builds ' do
let(:query) { '' }
- before { get api("/projects/#{project.id}/builds?#{query}", api_user) }
+ before do
+ get api("/projects/#{project.id}/builds?#{query}", api_user)
+ end
context 'authorized user' do
it 'returns project builds' do
@@ -122,7 +124,9 @@ describe API::API, api: true do
end
describe 'GET /projects/:id/builds/:build_id' do
- before { get api("/projects/#{project.id}/builds/#{build.id}", api_user) }
+ before do
+ get api("/projects/#{project.id}/builds/#{build.id}", api_user)
+ end
context 'authorized user' do
it 'returns specific build data' do
@@ -141,7 +145,9 @@ describe API::API, api: true do
end
describe 'GET /projects/:id/builds/:build_id/artifacts' do
- before { get api("/projects/#{project.id}/builds/#{build.id}/artifacts", api_user) }
+ before do
+ get api("/projects/#{project.id}/builds/#{build.id}/artifacts", api_user)
+ end
context 'build with artifacts' do
let(:build) { create(:ci_build, :artifacts, pipeline: pipeline) }
@@ -292,7 +298,9 @@ describe API::API, api: true do
end
describe 'POST /projects/:id/builds/:build_id/cancel' do
- before { post api("/projects/#{project.id}/builds/#{build.id}/cancel", api_user) }
+ before do
+ post api("/projects/#{project.id}/builds/#{build.id}/cancel", api_user)
+ end
context 'authorized user' do
context 'user with :update_build persmission' do
@@ -323,7 +331,9 @@ describe API::API, api: true do
describe 'POST /projects/:id/builds/:build_id/retry' do
let(:build) { create(:ci_build, :canceled, pipeline: pipeline) }
- before { post api("/projects/#{project.id}/builds/#{build.id}/retry", api_user) }
+ before do
+ post api("/projects/#{project.id}/builds/#{build.id}/retry", api_user)
+ end
context 'authorized user' do
context 'user with :update_build permission' do
diff --git a/spec/requests/api/commits_spec.rb b/spec/requests/api/commits_spec.rb
index 7ca75d77673..5b3dc60aba2 100644
--- a/spec/requests/api/commits_spec.rb
+++ b/spec/requests/api/commits_spec.rb
@@ -95,7 +95,7 @@ describe API::API, api: true do
end
it "returns status for CI" do
- pipeline = project.ensure_pipeline(project.repository.commit.sha, 'master')
+ pipeline = project.ensure_pipeline('master', project.repository.commit.sha)
pipeline.update(status: 'success')
get api("/projects/#{project.id}/repository/commits/#{project.repository.commit.id}", user)
@@ -105,7 +105,7 @@ describe API::API, api: true do
end
it "returns status for CI when pipeline is created" do
- project.ensure_pipeline(project.repository.commit.sha, 'master')
+ project.ensure_pipeline('master', project.repository.commit.sha)
get api("/projects/#{project.id}/repository/commits/#{project.repository.commit.id}", user)
diff --git a/spec/requests/api/internal_spec.rb b/spec/requests/api/internal_spec.rb
index be52f88831f..46d1b868782 100644
--- a/spec/requests/api/internal_spec.rb
+++ b/spec/requests/api/internal_spec.rb
@@ -38,6 +38,68 @@ describe API::API, api: true do
end
end
+ describe 'GET /internal/two_factor_recovery_codes' do
+ it 'returns an error message when the key does not exist' do
+ post api('/internal/two_factor_recovery_codes'),
+ secret_token: secret_token,
+ key_id: 12345
+
+ expect(json_response['success']).to be_falsey
+ expect(json_response['message']).to eq('Could not find the given key')
+ end
+
+ it 'returns an error message when the key is a deploy key' do
+ deploy_key = create(:deploy_key)
+
+ post api('/internal/two_factor_recovery_codes'),
+ secret_token: secret_token,
+ key_id: deploy_key.id
+
+ expect(json_response['success']).to be_falsey
+ expect(json_response['message']).to eq('Deploy keys cannot be used to retrieve recovery codes')
+ end
+
+ it 'returns an error message when the user does not exist' do
+ key_without_user = create(:key, user: nil)
+
+ post api('/internal/two_factor_recovery_codes'),
+ secret_token: secret_token,
+ key_id: key_without_user.id
+
+ expect(json_response['success']).to be_falsey
+ expect(json_response['message']).to eq('Could not find a user for the given key')
+ expect(json_response['recovery_codes']).to be_nil
+ end
+
+ context 'when two-factor is enabled' do
+ it 'returns new recovery codes when the user exists' do
+ allow_any_instance_of(User).to receive(:two_factor_enabled?).and_return(true)
+ allow_any_instance_of(User)
+ .to receive(:generate_otp_backup_codes!).and_return(%w(119135e5a3ebce8e 34bd7b74adbc8861))
+
+ post api('/internal/two_factor_recovery_codes'),
+ secret_token: secret_token,
+ key_id: key.id
+
+ expect(json_response['success']).to be_truthy
+ expect(json_response['recovery_codes']).to match_array(%w(119135e5a3ebce8e 34bd7b74adbc8861))
+ end
+ end
+
+ context 'when two-factor is not enabled' do
+ it 'returns an error message' do
+ allow_any_instance_of(User).to receive(:two_factor_enabled?).and_return(false)
+
+ post api('/internal/two_factor_recovery_codes'),
+ secret_token: secret_token,
+ key_id: key.id
+
+ expect(json_response['success']).to be_falsey
+ expect(json_response['recovery_codes']).to be_nil
+ end
+ end
+ end
+
describe "GET /internal/discover" do
it do
get(api("/internal/discover"), key_id: key.id, secret_token: secret_token)
diff --git a/spec/requests/api/issues_spec.rb b/spec/requests/api/issues_spec.rb
index a40e1a93b71..47344a13b5e 100644
--- a/spec/requests/api/issues_spec.rb
+++ b/spec/requests/api/issues_spec.rb
@@ -2,6 +2,7 @@ require 'spec_helper'
describe API::API, api: true do
include ApiHelpers
+
let(:user) { create(:user) }
let(:user2) { create(:user) }
let(:non_member) { create(:user) }
@@ -61,6 +62,7 @@ describe API::API, api: true do
expect(response).to have_http_status(200)
expect(json_response).to be_an Array
expect(json_response.first['title']).to eq(issue.title)
+ expect(json_response.last).to have_key('web_url')
end
it "adds pagination headers and keep query params" do
@@ -403,6 +405,7 @@ describe API::API, api: true do
expect(json_response['milestone']).to be_a Hash
expect(json_response['assignee']).to be_a Hash
expect(json_response['author']).to be_a Hash
+ expect(json_response['confidential']).to be_falsy
end
it "returns a project issue by id" do
@@ -468,13 +471,63 @@ describe API::API, api: true do
end
describe "POST /projects/:id/issues" do
- it "creates a new project issue" do
+ it 'creates a new project issue' do
post api("/projects/#{project.id}/issues", user),
title: 'new issue', labels: 'label, label2'
+
expect(response).to have_http_status(201)
expect(json_response['title']).to eq('new issue')
expect(json_response['description']).to be_nil
expect(json_response['labels']).to eq(['label', 'label2'])
+ expect(json_response['confidential']).to be_falsy
+ end
+
+ it 'creates a new confidential project issue' do
+ post api("/projects/#{project.id}/issues", user),
+ title: 'new issue', confidential: true
+
+ expect(response).to have_http_status(201)
+ expect(json_response['title']).to eq('new issue')
+ expect(json_response['confidential']).to be_truthy
+ end
+
+ it 'creates a new confidential project issue with a different param' do
+ post api("/projects/#{project.id}/issues", user),
+ title: 'new issue', confidential: 'y'
+
+ expect(response).to have_http_status(201)
+ expect(json_response['title']).to eq('new issue')
+ expect(json_response['confidential']).to be_truthy
+ end
+
+ it 'creates a public issue when confidential param is false' do
+ post api("/projects/#{project.id}/issues", user),
+ title: 'new issue', confidential: false
+
+ expect(response).to have_http_status(201)
+ expect(json_response['title']).to eq('new issue')
+ expect(json_response['confidential']).to be_falsy
+ end
+
+ it 'creates a public issue when confidential param is invalid' do
+ post api("/projects/#{project.id}/issues", user),
+ title: 'new issue', confidential: 'foo'
+
+ expect(response).to have_http_status(201)
+ expect(json_response['title']).to eq('new issue')
+ expect(json_response['confidential']).to be_falsy
+ end
+
+ it "sends notifications for subscribers of newly added labels" do
+ label = project.labels.first
+ label.toggle_subscription(user2)
+
+ perform_enqueued_jobs do
+ post api("/projects/#{project.id}/issues", user),
+ title: 'new issue', labels: label.title
+ end
+
+ should_email(user2)
end
it "returns a 400 bad request if title not given" do
@@ -618,6 +671,30 @@ describe API::API, api: true do
expect(response).to have_http_status(200)
expect(json_response['title']).to eq('updated title')
end
+
+ it 'sets an issue to confidential' do
+ put api("/projects/#{project.id}/issues/#{issue.id}", user),
+ confidential: true
+
+ expect(response).to have_http_status(200)
+ expect(json_response['confidential']).to be_truthy
+ end
+
+ it 'makes a confidential issue public' do
+ put api("/projects/#{project.id}/issues/#{confidential_issue.id}", user),
+ confidential: false
+
+ expect(response).to have_http_status(200)
+ expect(json_response['confidential']).to be_falsy
+ end
+
+ it 'does not update a confidential issue with wrong confidential flag' do
+ put api("/projects/#{project.id}/issues/#{confidential_issue.id}", user),
+ confidential: 'foo'
+
+ expect(response).to have_http_status(200)
+ expect(json_response['confidential']).to be_truthy
+ end
end
end
@@ -632,6 +709,18 @@ describe API::API, api: true do
expect(json_response['labels']).to eq([label.title])
end
+ it "sends notifications for subscribers of newly added labels when issue is updated" do
+ label = create(:label, title: 'foo', color: '#FFAABB', project: project)
+ label.toggle_subscription(user2)
+
+ perform_enqueued_jobs do
+ put api("/projects/#{project.id}/issues/#{issue.id}", user),
+ title: 'updated title', labels: label.title
+ end
+
+ should_email(user2)
+ end
+
it 'removes all labels' do
put api("/projects/#{project.id}/issues/#{issue.id}", user),
labels: ''
diff --git a/spec/requests/api/merge_request_diffs_spec.rb b/spec/requests/api/merge_request_diffs_spec.rb
new file mode 100644
index 00000000000..8f1e5ac9891
--- /dev/null
+++ b/spec/requests/api/merge_request_diffs_spec.rb
@@ -0,0 +1,49 @@
+require "spec_helper"
+
+describe API::API, 'MergeRequestDiffs', api: true do
+ include ApiHelpers
+
+ let!(:user) { create(:user) }
+ let!(:merge_request) { create(:merge_request, importing: true) }
+ let!(:project) { merge_request.target_project }
+
+ before do
+ merge_request.merge_request_diffs.create(head_commit_sha: '6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9')
+ merge_request.merge_request_diffs.create(head_commit_sha: '5937ac0a7beb003549fc5fd26fc247adbce4a52e')
+ project.team << [user, :master]
+ end
+
+ describe 'GET /projects/:id/merge_requests/:merge_request_id/versions' do
+ context 'valid merge request' do
+ before { get api("/projects/#{project.id}/merge_requests/#{merge_request.id}/versions", user) }
+ let(:merge_request_diff) { merge_request.merge_request_diffs.first }
+
+ it { expect(response.status).to eq 200 }
+ it { expect(json_response.size).to eq(merge_request.merge_request_diffs.size) }
+ it { expect(json_response.first['id']).to eq(merge_request_diff.id) }
+ it { expect(json_response.first['head_commit_sha']).to eq(merge_request_diff.head_commit_sha) }
+ end
+
+ it 'returns a 404 when merge_request_id not found' do
+ get api("/projects/#{project.id}/merge_requests/999/versions", user)
+ expect(response).to have_http_status(404)
+ end
+ end
+
+ describe 'GET /projects/:id/merge_requests/:merge_request_id/versions/:version_id' do
+ context 'valid merge request' do
+ before { get api("/projects/#{project.id}/merge_requests/#{merge_request.id}/versions/#{merge_request_diff.id}", user) }
+ let(:merge_request_diff) { merge_request.merge_request_diffs.first }
+
+ it { expect(response.status).to eq 200 }
+ it { expect(json_response['id']).to eq(merge_request_diff.id) }
+ it { expect(json_response['head_commit_sha']).to eq(merge_request_diff.head_commit_sha) }
+ it { expect(json_response['diffs'].size).to eq(merge_request_diff.diffs.size) }
+ end
+
+ it 'returns a 404 when merge_request_id not found' do
+ get api("/projects/#{project.id}/merge_requests/#{merge_request.id}/versions/999", user)
+ expect(response).to have_http_status(404)
+ end
+ end
+end
diff --git a/spec/requests/api/merge_requests_spec.rb b/spec/requests/api/merge_requests_spec.rb
index 617600d6173..a7930c59df9 100644
--- a/spec/requests/api/merge_requests_spec.rb
+++ b/spec/requests/api/merge_requests_spec.rb
@@ -9,7 +9,7 @@ describe API::API, api: true do
let!(:project) { create(:project, creator_id: user.id, namespace: user.namespace) }
let!(:merge_request) { create(:merge_request, :simple, author: user, assignee: user, source_project: project, target_project: project, title: "Test", created_at: base_time) }
let!(:merge_request_closed) { create(:merge_request, state: "closed", author: user, assignee: user, source_project: project, target_project: project, title: "Closed test", created_at: base_time + 1.second) }
- let!(:merge_request_merged) { create(:merge_request, state: "merged", author: user, assignee: user, source_project: project, target_project: project, title: "Merged test", created_at: base_time + 2.seconds) }
+ let!(:merge_request_merged) { create(:merge_request, state: "merged", author: user, assignee: user, source_project: project, target_project: project, title: "Merged test", created_at: base_time + 2.seconds, merge_commit_sha: '9999999999999999999999999999999999999999') }
let!(:note) { create(:note_on_merge_request, author: user, project: project, noteable: merge_request, note: "a comment on a MR") }
let!(:note2) { create(:note_on_merge_request, author: user, project: project, noteable: merge_request, note: "another comment on a MR") }
let(:milestone) { create(:milestone, title: '1.0.0', project: project) }
@@ -33,6 +33,14 @@ describe API::API, api: true do
expect(json_response).to be_an Array
expect(json_response.length).to eq(3)
expect(json_response.last['title']).to eq(merge_request.title)
+ expect(json_response.last).to have_key('web_url')
+ expect(json_response.last['sha']).to eq(merge_request.diff_head_sha)
+ expect(json_response.last['merge_commit_sha']).to be_nil
+ expect(json_response.last['merge_commit_sha']).to eq(merge_request.merge_commit_sha)
+ expect(json_response.first['title']).to eq(merge_request_merged.title)
+ expect(json_response.first['sha']).to eq(merge_request_merged.diff_head_sha)
+ expect(json_response.first['merge_commit_sha']).not_to be_nil
+ expect(json_response.first['merge_commit_sha']).to eq(merge_request_merged.merge_commit_sha)
end
it "returns an array of all merge_requests" do
diff --git a/spec/requests/api/notes_spec.rb b/spec/requests/api/notes_spec.rb
index 737fa14cbb0..223444ea39f 100644
--- a/spec/requests/api/notes_spec.rb
+++ b/spec/requests/api/notes_spec.rb
@@ -25,7 +25,7 @@ describe API::API, api: true do
let!(:cross_reference_note) do
create :note,
noteable: ext_issue, project: ext_proj,
- note: "mentioned in issue #{private_issue.to_reference(ext_proj)}",
+ note: "Mentioned in issue #{private_issue.to_reference(ext_proj)}",
system: true
end
diff --git a/spec/requests/api/project_hooks_spec.rb b/spec/requests/api/project_hooks_spec.rb
index 914e88c9487..765dc8a8f66 100644
--- a/spec/requests/api/project_hooks_spec.rb
+++ b/spec/requests/api/project_hooks_spec.rb
@@ -34,6 +34,7 @@ describe API::API, 'ProjectHooks', api: true do
expect(json_response.first['note_events']).to eq(true)
expect(json_response.first['build_events']).to eq(true)
expect(json_response.first['pipeline_events']).to eq(true)
+ expect(json_response.first['wiki_page_events']).to eq(true)
expect(json_response.first['enable_ssl_verification']).to eq(true)
end
end
@@ -57,6 +58,9 @@ describe API::API, 'ProjectHooks', api: true do
expect(json_response['merge_requests_events']).to eq(hook.merge_requests_events)
expect(json_response['tag_push_events']).to eq(hook.tag_push_events)
expect(json_response['note_events']).to eq(hook.note_events)
+ expect(json_response['build_events']).to eq(hook.build_events)
+ expect(json_response['pipeline_events']).to eq(hook.pipeline_events)
+ expect(json_response['wiki_page_events']).to eq(hook.wiki_page_events)
expect(json_response['enable_ssl_verification']).to eq(hook.enable_ssl_verification)
end
@@ -93,6 +97,7 @@ describe API::API, 'ProjectHooks', api: true do
expect(json_response['note_events']).to eq(false)
expect(json_response['build_events']).to eq(false)
expect(json_response['pipeline_events']).to eq(false)
+ expect(json_response['wiki_page_events']).to eq(false)
expect(json_response['enable_ssl_verification']).to eq(true)
end
@@ -118,6 +123,9 @@ describe API::API, 'ProjectHooks', api: true do
expect(json_response['merge_requests_events']).to eq(hook.merge_requests_events)
expect(json_response['tag_push_events']).to eq(hook.tag_push_events)
expect(json_response['note_events']).to eq(hook.note_events)
+ expect(json_response['build_events']).to eq(hook.build_events)
+ expect(json_response['pipeline_events']).to eq(hook.pipeline_events)
+ expect(json_response['wiki_page_events']).to eq(hook.wiki_page_events)
expect(json_response['enable_ssl_verification']).to eq(hook.enable_ssl_verification)
end
diff --git a/spec/requests/api/project_snippets_spec.rb b/spec/requests/api/project_snippets_spec.rb
index 42757ff21b0..01148f0a05e 100644
--- a/spec/requests/api/project_snippets_spec.rb
+++ b/spec/requests/api/project_snippets_spec.rb
@@ -30,6 +30,7 @@ describe API::API, api: true do
expect(response).to have_http_status(200)
expect(json_response.size).to eq(3)
expect(json_response.map{ |snippet| snippet['id']} ).to include(public_snippet.id, internal_snippet.id, private_snippet.id)
+ expect(json_response.last).to have_key('web_url')
end
it 'hides private snippets from regular user' do
diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb
index 4742b3d0e37..28aa56e8644 100644
--- a/spec/requests/api/projects_spec.rb
+++ b/spec/requests/api/projects_spec.rb
@@ -73,7 +73,7 @@ describe API::API, api: true do
end
it 'does not include open_issues_count' do
- project.update_attributes( { issues_enabled: false } )
+ project.project_feature.update_attribute(:issues_access_level, ProjectFeature::DISABLED)
get api('/projects', user)
expect(response.status).to eq 200
@@ -224,14 +224,22 @@ describe API::API, api: true do
description: FFaker::Lorem.sentence,
issues_enabled: false,
merge_requests_enabled: false,
- wiki_enabled: false
+ wiki_enabled: false,
+ only_allow_merge_if_build_succeeds: false
})
post api('/projects', user), project
project.each_pair do |k, v|
+ next if %i{ issues_enabled merge_requests_enabled wiki_enabled }.include?(k)
expect(json_response[k.to_s]).to eq(v)
end
+
+ # Check feature permissions attributes
+ project = Project.find_by_path(project[:path])
+ expect(project.project_feature.issues_access_level).to eq(ProjectFeature::DISABLED)
+ expect(project.project_feature.merge_requests_access_level).to eq(ProjectFeature::DISABLED)
+ expect(project.project_feature.wiki_access_level).to eq(ProjectFeature::DISABLED)
end
it 'sets a project as public' do
@@ -276,6 +284,18 @@ describe API::API, api: true do
expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::PRIVATE)
end
+ it 'sets a project as allowing merge even if build fails' do
+ project = attributes_for(:project, { only_allow_merge_if_build_succeeds: false })
+ post api('/projects', user), project
+ expect(json_response['only_allow_merge_if_build_succeeds']).to be_falsey
+ end
+
+ it 'sets a project as allowing merge only if build succeeds' do
+ project = attributes_for(:project, { only_allow_merge_if_build_succeeds: true })
+ post api('/projects', user), project
+ expect(json_response['only_allow_merge_if_build_succeeds']).to be_truthy
+ end
+
context 'when a visibility level is restricted' do
before do
@project = attributes_for(:project, { public: true })
@@ -384,6 +404,18 @@ describe API::API, api: true do
expect(json_response['public']).to be_falsey
expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::PRIVATE)
end
+
+ it 'sets a project as allowing merge even if build fails' do
+ project = attributes_for(:project, { only_allow_merge_if_build_succeeds: false })
+ post api("/projects/user/#{user.id}", admin), project
+ expect(json_response['only_allow_merge_if_build_succeeds']).to be_falsey
+ end
+
+ it 'sets a project as allowing merge only if build succeeds' do
+ project = attributes_for(:project, { only_allow_merge_if_build_succeeds: true })
+ post api("/projects/user/#{user.id}", admin), project
+ expect(json_response['only_allow_merge_if_build_succeeds']).to be_truthy
+ end
end
describe "POST /projects/:id/uploads" do
@@ -444,6 +476,7 @@ describe API::API, api: true do
expect(json_response['shared_with_groups'][0]['group_id']).to eq(group.id)
expect(json_response['shared_with_groups'][0]['group_name']).to eq(group.name)
expect(json_response['shared_with_groups'][0]['group_access_level']).to eq(link.group_access)
+ expect(json_response['only_allow_merge_if_build_succeeds']).to eq(project.only_allow_merge_if_build_succeeds)
end
it 'returns a project by path name' do
diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb
index 0bbba64a6d5..ef73778efa9 100644
--- a/spec/requests/api/users_spec.rb
+++ b/spec/requests/api/users_spec.rb
@@ -605,6 +605,7 @@ describe API::API, api: true do
expect(json_response['can_create_project']).to eq(user.can_create_project?)
expect(json_response['can_create_group']).to eq(user.can_create_group?)
expect(json_response['projects_limit']).to eq(user.projects_limit)
+ expect(json_response['private_token']).to be_blank
end
it "returns 401 error if user is unauthenticated" do
diff --git a/spec/requests/git_http_spec.rb b/spec/requests/git_http_spec.rb
index afaf4b7cefb..9ca3b021aa2 100644
--- a/spec/requests/git_http_spec.rb
+++ b/spec/requests/git_http_spec.rb
@@ -289,7 +289,8 @@ describe 'Git HTTP requests', lib: true do
let(:project) { FactoryGirl.create :empty_project }
before do
- project.update_attributes(runners_token: token, builds_enabled: true)
+ project.update_attributes(runners_token: token)
+ project.project_feature.update_attributes(builds_access_level: ProjectFeature::ENABLED)
end
it "downloads get status 200" do
diff --git a/spec/requests/jwt_controller_spec.rb b/spec/requests/jwt_controller_spec.rb
index c6172b9cc7d..fc42b534dca 100644
--- a/spec/requests/jwt_controller_spec.rb
+++ b/spec/requests/jwt_controller_spec.rb
@@ -22,19 +22,20 @@ describe JwtController do
context 'when using authorized request' do
context 'using CI token' do
- let(:project) { create(:empty_project, runners_token: 'token', builds_enabled: builds_enabled) }
+ let(:project) { create(:empty_project, runners_token: 'token') }
let(:headers) { { authorization: credentials('gitlab-ci-token', project.runners_token) } }
- subject! { get '/jwt/auth', parameters, headers }
-
context 'project with enabled CI' do
- let(:builds_enabled) { true }
-
+ subject! { get '/jwt/auth', parameters, headers }
it { expect(service_class).to have_received(:new).with(project, nil, parameters) }
end
context 'project with disabled CI' do
- let(:builds_enabled) { false }
+ before do
+ project.project_feature.update_attribute(:builds_access_level, ProjectFeature::DISABLED)
+ end
+
+ subject! { get '/jwt/auth', parameters, headers }
it { expect(response).to have_http_status(403) }
end
diff --git a/spec/requests/lfs_http_spec.rb b/spec/requests/lfs_http_spec.rb
index 4c9b4a8ba42..fcd6521317a 100644
--- a/spec/requests/lfs_http_spec.rb
+++ b/spec/requests/lfs_http_spec.rb
@@ -44,6 +44,113 @@ describe 'Git LFS API and storage' do
end
end
+ context 'project specific LFS settings' do
+ let(:project) { create(:empty_project) }
+ let(:body) do
+ {
+ 'objects' => [
+ { 'oid' => '91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897',
+ 'size' => 1575078
+ },
+ { 'oid' => sample_oid,
+ 'size' => sample_size
+ }
+ ],
+ 'operation' => 'upload'
+ }
+ end
+ let(:authorization) { authorize_user }
+
+ context 'with LFS disabled globally' do
+ before do
+ project.team << [user, :master]
+ allow(Gitlab.config.lfs).to receive(:enabled).and_return(false)
+ end
+
+ describe 'LFS disabled in project' do
+ before do
+ project.update_attribute(:lfs_enabled, false)
+ end
+
+ it 'responds with a 501 message on upload' do
+ post_lfs_json "#{project.http_url_to_repo}/info/lfs/objects/batch", body, headers
+
+ expect(response).to have_http_status(501)
+ end
+
+ it 'responds with a 501 message on download' do
+ get "#{project.http_url_to_repo}/gitlab-lfs/objects/#{sample_oid}", nil, headers
+
+ expect(response).to have_http_status(501)
+ end
+ end
+
+ describe 'LFS enabled in project' do
+ before do
+ project.update_attribute(:lfs_enabled, true)
+ end
+
+ it 'responds with a 501 message on upload' do
+ post_lfs_json "#{project.http_url_to_repo}/info/lfs/objects/batch", body, headers
+
+ expect(response).to have_http_status(501)
+ end
+
+ it 'responds with a 501 message on download' do
+ get "#{project.http_url_to_repo}/gitlab-lfs/objects/#{sample_oid}", nil, headers
+
+ expect(response).to have_http_status(501)
+ end
+ end
+ end
+
+ context 'with LFS enabled globally' do
+ before do
+ project.team << [user, :master]
+ enable_lfs
+ end
+
+ describe 'LFS disabled in project' do
+ before do
+ project.update_attribute(:lfs_enabled, false)
+ end
+
+ it 'responds with a 403 message on upload' do
+ post_lfs_json "#{project.http_url_to_repo}/info/lfs/objects/batch", body, headers
+
+ expect(response).to have_http_status(403)
+ expect(json_response).to include('message' => 'Access forbidden. Check your access level.')
+ end
+
+ it 'responds with a 403 message on download' do
+ get "#{project.http_url_to_repo}/gitlab-lfs/objects/#{sample_oid}", nil, headers
+
+ expect(response).to have_http_status(403)
+ expect(json_response).to include('message' => 'Access forbidden. Check your access level.')
+ end
+ end
+
+ describe 'LFS enabled in project' do
+ before do
+ project.update_attribute(:lfs_enabled, true)
+ end
+
+ it 'responds with a 200 message on upload' do
+ post_lfs_json "#{project.http_url_to_repo}/info/lfs/objects/batch", body, headers
+
+ expect(response).to have_http_status(200)
+ expect(json_response['objects'].first['size']).to eq(1575078)
+ end
+
+ it 'responds with a 200 message on download' do
+ get "#{project.http_url_to_repo}/gitlab-lfs/objects/#{sample_oid}", nil, headers
+
+ expect(response).to have_http_status(200)
+ end
+ end
+ end
+ end
+
describe 'deprecated API' do
let(:project) { create(:empty_project) }
diff --git a/spec/requests/projects/artifacts_controller_spec.rb b/spec/requests/projects/artifacts_controller_spec.rb
new file mode 100644
index 00000000000..e02f0eacc93
--- /dev/null
+++ b/spec/requests/projects/artifacts_controller_spec.rb
@@ -0,0 +1,117 @@
+require 'spec_helper'
+
+describe Projects::ArtifactsController do
+ let(:user) { create(:user) }
+ let(:project) { create(:project) }
+
+ let(:pipeline) do
+ create(:ci_pipeline,
+ project: project,
+ sha: project.commit.sha,
+ ref: project.default_branch,
+ status: 'success')
+ end
+
+ let(:build) { create(:ci_build, :success, :artifacts, pipeline: pipeline) }
+
+ describe 'GET /:project/builds/artifacts/:ref_name/browse?job=name' do
+ before do
+ project.team << [user, :developer]
+
+ login_as(user)
+ end
+
+ def path_from_ref(
+ ref = pipeline.ref, job = build.name, path = 'browse')
+ latest_succeeded_namespace_project_artifacts_path(
+ project.namespace,
+ project,
+ [ref, path].join('/'),
+ job: job)
+ end
+
+ context 'cannot find the build' do
+ shared_examples 'not found' do
+ it { expect(response).to have_http_status(:not_found) }
+ end
+
+ context 'has no such ref' do
+ before do
+ get path_from_ref('TAIL', build.name)
+ end
+
+ it_behaves_like 'not found'
+ end
+
+ context 'has no such build' do
+ before do
+ get path_from_ref(pipeline.ref, 'NOBUILD')
+ end
+
+ it_behaves_like 'not found'
+ end
+
+ context 'has no path' do
+ before do
+ get path_from_ref(pipeline.sha, build.name, '')
+ end
+
+ it_behaves_like 'not found'
+ end
+ end
+
+ context 'found the build and redirect' do
+ shared_examples 'redirect to the build' do
+ it 'redirects' do
+ path = browse_namespace_project_build_artifacts_path(
+ project.namespace,
+ project,
+ build)
+
+ expect(response).to redirect_to(path)
+ end
+ end
+
+ context 'with regular branch' do
+ before do
+ pipeline.update(ref: 'master',
+ sha: project.commit('master').sha)
+
+ get path_from_ref('master')
+ end
+
+ it_behaves_like 'redirect to the build'
+ end
+
+ context 'with branch name containing slash' do
+ before do
+ pipeline.update(ref: 'improve/awesome',
+ sha: project.commit('improve/awesome').sha)
+
+ get path_from_ref('improve/awesome')
+ end
+
+ it_behaves_like 'redirect to the build'
+ end
+
+ context 'with branch name and path containing slashes' do
+ before do
+ pipeline.update(ref: 'improve/awesome',
+ sha: project.commit('improve/awesome').sha)
+
+ get path_from_ref('improve/awesome', build.name, 'file/README.md')
+ end
+
+ it 'redirects' do
+ path = file_namespace_project_build_artifacts_path(
+ project.namespace,
+ project,
+ build,
+ 'README.md')
+
+ expect(response).to redirect_to(path)
+ end
+ end
+ end
+ end
+end