debian-mirror-gitlab/spec/controllers/projects/compare_controller_spec.rb

532 lines
16 KiB
Ruby
Raw Normal View History

2019-07-31 22:56:46 +05:30
# frozen_string_literal: true
2015-09-11 14:41:01 +05:30
require 'spec_helper'
2020-06-23 00:09:42 +05:30
RSpec.describe Projects::CompareController do
2021-04-17 20:07:23 +05:30
include ProjectForksHelper
using RSpec::Parameterized::TableSyntax
let_it_be(:project) { create(:project, :repository, :public) }
let_it_be(:user) { create(:user) }
let(:private_fork) { fork_project(project, nil, repository: true).tap { |fork| fork.update!(visibility: 'private') } }
let(:public_fork) do
fork_project(project, nil, repository: true).tap do |fork|
fork.update!(visibility: 'public')
# Create a reference that only exists in this project
fork.repository.create_ref('refs/heads/improve/awesome', 'refs/heads/improve/more-awesome')
end
end
2015-09-11 14:41:01 +05:30
before do
sign_in(user)
2018-11-18 11:00:15 +05:30
project.add_maintainer(user)
2015-09-11 14:41:01 +05:30
end
2018-10-15 14:42:47 +05:30
describe 'GET index' do
2022-04-04 11:22:00 +05:30
let(:params) { { namespace_id: project.namespace, project_id: project } }
2018-10-15 14:42:47 +05:30
render_views
before do
2022-04-04 11:22:00 +05:30
get :index, params: params
2018-10-15 14:42:47 +05:30
end
2015-09-11 14:41:01 +05:30
2018-10-15 14:42:47 +05:30
it 'returns successfully' do
2019-12-04 20:38:33 +05:30
expect(response).to be_successful
2018-10-15 14:42:47 +05:30
end
2022-04-04 11:22:00 +05:30
context 'with incorrect parameters' do
let(:params) { super().merge(from: { invalid: :param }, to: { also: :invalid }) }
it 'returns successfully' do
expect(response).to be_successful
end
end
2022-07-23 23:45:48 +05:30
context 'with missing parameters' do
let(:params) { super().merge(from: '', to: '') }
it 'returns successfully' do
expect(response).to be_successful
end
end
2015-09-11 14:41:01 +05:30
end
2015-09-25 12:07:36 +05:30
2018-10-15 14:42:47 +05:30
describe 'GET show' do
render_views
2019-02-15 15:39:39 +05:30
subject(:show_request) { get :show, params: request_params }
2018-10-15 14:42:47 +05:30
let(:request_params) do
{
2017-08-17 22:00:37 +05:30
namespace_id: project.namespace,
project_id: project,
2021-04-17 20:07:23 +05:30
from_project_id: from_project_id,
from: from_ref,
to: to_ref,
2022-06-21 17:19:12 +05:30
w: whitespace,
page: page
2018-10-15 14:42:47 +05:30
}
end
2015-11-26 14:37:03 +05:30
2018-10-15 14:42:47 +05:30
let(:whitespace) { nil }
2022-06-21 17:19:12 +05:30
let(:page) { nil }
2015-09-25 12:07:36 +05:30
2021-04-17 20:07:23 +05:30
context 'when the refs exist in the same project' do
2018-10-15 14:42:47 +05:30
context 'when we set the white space param' do
2021-04-17 20:07:23 +05:30
let(:from_project_id) { nil }
let(:from_ref) { '08f22f25' }
let(:to_ref) { '66eceea0' }
2018-10-15 14:42:47 +05:30
let(:whitespace) { 1 }
2015-09-25 12:07:36 +05:30
2018-10-15 14:42:47 +05:30
it 'shows some diffs with ignore whitespace change option' do
show_request
2015-09-25 12:07:36 +05:30
2019-12-04 20:38:33 +05:30
expect(response).to be_successful
2018-10-15 14:42:47 +05:30
diff_file = assigns(:diffs).diff_files.first
expect(diff_file).not_to be_nil
expect(assigns(:commits).length).to be >= 1
# without whitespace option, there are more than 2 diff_splits
diff_splits = diff_file.diff.diff.split("\n")
expect(diff_splits.length).to be <= 2
end
end
context 'when we do not set the white space param' do
2021-04-17 20:07:23 +05:30
let(:from_project_id) { nil }
let(:from_ref) { 'improve%2Fawesome' }
let(:to_ref) { 'feature' }
2018-10-15 14:42:47 +05:30
let(:whitespace) { nil }
2017-08-17 22:00:37 +05:30
2018-10-15 14:42:47 +05:30
it 'sets the diffs and commits ivars' do
show_request
2017-08-17 22:00:37 +05:30
2019-12-04 20:38:33 +05:30
expect(response).to be_successful
2018-10-15 14:42:47 +05:30
expect(assigns(:diffs).diff_files.first).not_to be_nil
expect(assigns(:commits).length).to be >= 1
end
end
2017-08-17 22:00:37 +05:30
end
2022-07-23 23:45:48 +05:30
context 'when refs have CI::Pipeline' do
let(:from_project_id) { nil }
let(:from_ref) { '08f22f25' }
let(:to_ref) { '59e29889' }
before do
create(:ci_pipeline, project: project)
end
it 'avoids N+1 queries' do
control = ActiveRecord::QueryRecorder.new { show_request }
# Only 1 query to ci/pipeline.rb is allowed
expect(control.find_query(/pipeline\.rb/, 1)).to be_empty
end
end
2021-04-17 20:07:23 +05:30
context 'when the refs exist in different projects that the user can see' do
let(:from_project_id) { public_fork.id }
let(:from_ref) { 'improve%2Fmore-awesome' }
let(:to_ref) { 'feature' }
let(:whitespace) { nil }
it 'shows the diff' do
show_request
expect(response).to be_successful
expect(assigns(:diffs).diff_files.first).not_to be_nil
expect(assigns(:commits).length).to be >= 1
end
end
context 'when the refs exist in different projects but the user cannot see' do
let(:from_project_id) { private_fork.id }
let(:from_ref) { 'improve%2Fmore-awesome' }
let(:to_ref) { 'feature' }
let(:whitespace) { nil }
it 'does not show the diff' do
show_request
expect(response).to be_successful
expect(assigns(:diffs)).to be_empty
expect(assigns(:commits)).to be_empty
end
end
2018-10-15 14:42:47 +05:30
context 'when the source ref does not exist' do
2021-04-17 20:07:23 +05:30
let(:from_project_id) { nil }
let(:from_ref) { 'non-existent-source-ref' }
let(:to_ref) { 'feature' }
2018-10-15 14:42:47 +05:30
it 'sets empty diff and commit ivars' do
show_request
2017-08-17 22:00:37 +05:30
2019-12-04 20:38:33 +05:30
expect(response).to be_successful
2019-07-31 22:56:46 +05:30
expect(assigns(:diffs)).to eq([])
2018-10-15 14:42:47 +05:30
expect(assigns(:commits)).to eq([])
end
2017-08-17 22:00:37 +05:30
end
2018-10-15 14:42:47 +05:30
context 'when the target ref does not exist' do
2021-04-17 20:07:23 +05:30
let(:from_project_id) { nil }
let(:from_ref) { 'improve%2Fawesome' }
let(:to_ref) { 'non-existent-target-ref' }
2017-08-17 22:00:37 +05:30
2018-10-15 14:42:47 +05:30
it 'sets empty diff and commit ivars' do
show_request
2019-12-04 20:38:33 +05:30
expect(response).to be_successful
2018-10-15 14:42:47 +05:30
expect(assigns(:diffs)).to eq([])
expect(assigns(:commits)).to eq([])
end
2018-12-13 13:39:08 +05:30
end
context 'when the target ref is invalid' do
2021-04-17 20:07:23 +05:30
let(:from_project_id) { nil }
let(:from_ref) { 'improve%2Fawesome' }
let(:to_ref) { "master%' AND 2554=4423 AND '%'='" }
2018-12-13 13:39:08 +05:30
it 'shows a flash message and redirects' do
show_request
2021-09-04 01:27:46 +05:30
expect(flash[:alert]).to eq("Invalid branch name(s): master%' AND 2554=4423 AND '%'='")
2020-03-13 15:44:24 +05:30
expect(response).to have_gitlab_http_status(:found)
2018-12-13 13:39:08 +05:30
end
end
context 'when the source ref is invalid' do
2021-04-17 20:07:23 +05:30
let(:from_project_id) { nil }
let(:from_ref) { "master%' AND 2554=4423 AND '%'='" }
let(:to_ref) { 'improve%2Fawesome' }
2018-12-13 13:39:08 +05:30
it 'shows a flash message and redirects' do
show_request
2021-09-04 01:27:46 +05:30
expect(flash[:alert]).to eq("Invalid branch name(s): master%' AND 2554=4423 AND '%'='")
expect(response).to have_gitlab_http_status(:found)
end
end
context 'when the both refs are invalid' do
let(:from_project_id) { nil }
let(:from_ref) { "master%' AND 2554=4423 AND '%'='" }
let(:to_ref) { "improve%' =,awesome" }
it 'shows a flash message and redirects' do
show_request
expect(flash[:alert]).to eq("Invalid branch name(s): improve%' =,awesome, master%' AND 2554=4423 AND '%'='")
2020-03-13 15:44:24 +05:30
expect(response).to have_gitlab_http_status(:found)
2018-12-13 13:39:08 +05:30
end
2017-08-17 22:00:37 +05:30
end
2022-06-21 17:19:12 +05:30
context 'when page is valid' do
let(:from_project_id) { nil }
2022-08-27 11:52:29 +05:30
let(:from_ref) { '6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9' }
let(:to_ref) { '5937ac0a7beb003549fc5fd26fc247adbce4a52e' }
2022-06-21 17:19:12 +05:30
let(:page) { 1 }
it 'shows the diff' do
show_request
expect(response).to be_successful
expect(assigns(:diffs).diff_files.first).to be_present
expect(assigns(:commits).length).to be >= 1
end
2022-08-27 11:52:29 +05:30
it 'only loads blobs in the current page' do
stub_const('Projects::CompareController::COMMIT_DIFFS_PER_PAGE', 1)
expect_next_instance_of(Repository) do |repository|
# This comparison contains 4 changed files but we expect only the blobs for the first one to be loaded
expect(repository).to receive(:blobs_at).with(
contain_exactly([from_ref, '.gitmodules'], [to_ref, '.gitmodules']), anything
).and_call_original
end
show_request
expect(response).to be_successful
end
2022-06-21 17:19:12 +05:30
end
context 'when page is not valid' do
let(:from_project_id) { nil }
let(:from_ref) { '08f22f25' }
let(:to_ref) { '66eceea0' }
let(:page) { ['invalid'] }
it 'does not return an error' do
show_request
expect(response).to be_successful
end
end
2015-09-25 12:07:36 +05:30
end
2016-08-24 12:49:21 +05:30
describe 'GET diff_for_path' do
2021-04-17 20:07:23 +05:30
subject(:diff_for_path_request) { get :diff_for_path, params: request_params }
let(:request_params) do
{
from_project_id: from_project_id,
from: from_ref,
to: to_ref,
2017-08-17 22:00:37 +05:30
namespace_id: project.namespace,
2021-04-17 20:07:23 +05:30
project_id: project,
old_path: old_path,
new_path: new_path
2016-08-24 12:49:21 +05:30
}
end
let(:existing_path) { 'files/ruby/feature.rb' }
2021-04-17 20:07:23 +05:30
let(:from_project_id) { nil }
let(:from_ref) { 'improve%2Fawesome' }
let(:to_ref) { 'feature' }
let(:old_path) { existing_path }
let(:new_path) { existing_path }
context 'when the source and target refs exist in the same project' do
2018-10-15 14:42:47 +05:30
context 'when the user has access target the project' do
2016-08-24 12:49:21 +05:30
context 'when the path exists in the diff' do
it 'disables diff notes' do
2021-04-17 20:07:23 +05:30
diff_for_path_request
2016-08-24 12:49:21 +05:30
expect(assigns(:diff_notes_disabled)).to be_truthy
end
it 'only renders the diffs for the path given' do
2016-09-13 17:45:13 +05:30
expect(controller).to receive(:render_diff_for_path).and_wrap_original do |meth, diffs|
expect(diffs.diff_files.map(&:new_path)).to contain_exactly(existing_path)
meth.call(diffs)
2016-08-24 12:49:21 +05:30
end
2021-04-17 20:07:23 +05:30
diff_for_path_request
2016-08-24 12:49:21 +05:30
end
end
context 'when the path does not exist in the diff' do
2021-04-17 20:07:23 +05:30
let(:old_path) { existing_path.succ }
let(:new_path) { existing_path.succ }
2016-08-24 12:49:21 +05:30
it 'returns a 404' do
2021-04-17 20:07:23 +05:30
diff_for_path_request
2020-03-13 15:44:24 +05:30
expect(response).to have_gitlab_http_status(:not_found)
2016-08-24 12:49:21 +05:30
end
end
end
2018-10-15 14:42:47 +05:30
context 'when the user does not have access target the project' do
2016-08-24 12:49:21 +05:30
before do
project.team.truncate
end
it 'returns a 404' do
2021-04-17 20:07:23 +05:30
diff_for_path_request
2020-03-13 15:44:24 +05:30
expect(response).to have_gitlab_http_status(:not_found)
2016-08-24 12:49:21 +05:30
end
end
end
2021-04-17 20:07:23 +05:30
context 'when the source and target refs exist in different projects and the user can see' do
let(:from_project_id) { public_fork.id }
let(:from_ref) { 'improve%2Fmore-awesome' }
it 'shows the diff for that path' do
expect(controller).to receive(:render_diff_for_path).and_wrap_original do |meth, diffs|
expect(diffs.diff_files.map(&:new_path)).to contain_exactly(existing_path)
meth.call(diffs)
end
diff_for_path_request
end
end
context 'when the source and target refs exist in different projects and the user cannot see' do
let(:from_project_id) { private_fork.id }
it 'does not show the diff for that path' do
diff_for_path_request
expect(response).to have_gitlab_http_status(:not_found)
2017-09-10 17:25:29 +05:30
end
2021-04-17 20:07:23 +05:30
end
context 'when the source ref does not exist' do
let(:from_ref) { 'this-ref-does-not-exist' }
2016-08-24 12:49:21 +05:30
it 'returns a 404' do
2021-04-17 20:07:23 +05:30
diff_for_path_request
2020-03-13 15:44:24 +05:30
expect(response).to have_gitlab_http_status(:not_found)
2016-08-24 12:49:21 +05:30
end
end
2018-10-15 14:42:47 +05:30
context 'when the target ref does not exist' do
2021-04-17 20:07:23 +05:30
let(:to_ref) { 'this-ref-does-not-exist' }
2016-08-24 12:49:21 +05:30
it 'returns a 404' do
2021-04-17 20:07:23 +05:30
diff_for_path_request
2020-03-13 15:44:24 +05:30
expect(response).to have_gitlab_http_status(:not_found)
2016-08-24 12:49:21 +05:30
end
end
end
2018-10-15 14:42:47 +05:30
describe 'POST create' do
2019-02-15 15:39:39 +05:30
subject(:create_request) { post :create, params: request_params }
2018-10-15 14:42:47 +05:30
let(:request_params) do
{
namespace_id: project.namespace,
project_id: project,
2021-04-17 20:07:23 +05:30
from_project_id: from_project_id,
from: from_ref,
to: to_ref
2018-10-15 14:42:47 +05:30
}
end
context 'when sending valid params' do
2021-04-17 20:07:23 +05:30
let(:from_ref) { 'awesome%2Ffeature' }
let(:to_ref) { 'feature' }
2018-10-15 14:42:47 +05:30
2021-04-17 20:07:23 +05:30
context 'without a from_project_id' do
let(:from_project_id) { nil }
2018-10-15 14:42:47 +05:30
2021-04-17 20:07:23 +05:30
it 'redirects to the show page' do
2018-10-15 14:42:47 +05:30
create_request
2021-04-17 20:07:23 +05:30
expect(response).to redirect_to(project_compare_path(project, from: from_ref, to: to_ref))
2018-10-15 14:42:47 +05:30
end
end
2021-04-17 20:07:23 +05:30
context 'with a from_project_id' do
let(:from_project_id) { 'something or another' }
2018-10-15 14:42:47 +05:30
2021-04-17 20:07:23 +05:30
it 'redirects to the show page without interpreting from_project_id' do
2018-10-15 14:42:47 +05:30
create_request
2021-04-17 20:07:23 +05:30
expect(response).to redirect_to(project_compare_path(project, from: from_ref, to: to_ref, from_project_id: from_project_id))
2018-10-15 14:42:47 +05:30
end
end
2021-04-17 20:07:23 +05:30
end
context 'when sending invalid params' do
where(:from_ref, :to_ref, :from_project_id, :expected_redirect_params) do
2022-04-04 11:22:00 +05:30
'' | '' | '' | {}
'main' | '' | '' | { from: 'main' }
'' | 'main' | '' | { to: 'main' }
'' | '' | '1' | { from_project_id: 1 }
'main' | '' | '1' | { from: 'main', from_project_id: 1 }
'' | 'main' | '1' | { to: 'main', from_project_id: 1 }
['a'] | ['b'] | ['c'] | {}
2021-04-17 20:07:23 +05:30
end
2018-10-15 14:42:47 +05:30
2021-04-17 20:07:23 +05:30
with_them do
let(:expected_redirect) { project_compare_index_path(project, expected_redirect_params) }
2018-10-15 14:42:47 +05:30
2021-04-17 20:07:23 +05:30
it 'redirects back to the index' do
2018-10-15 14:42:47 +05:30
create_request
2021-04-17 20:07:23 +05:30
expect(response).to redirect_to(expected_redirect)
2018-10-15 14:42:47 +05:30
end
end
end
end
describe 'GET signatures' do
2019-02-15 15:39:39 +05:30
subject(:signatures_request) { get :signatures, params: request_params }
2018-10-15 14:42:47 +05:30
let(:request_params) do
{
namespace_id: project.namespace,
project_id: project,
2021-04-17 20:07:23 +05:30
from: from_ref,
to: to_ref,
2018-10-15 14:42:47 +05:30
format: :json
}
end
context 'when the source and target refs exist' do
2021-04-17 20:07:23 +05:30
let(:from_ref) { 'improve%2Fawesome' }
let(:to_ref) { 'feature' }
2018-10-15 14:42:47 +05:30
context 'when the user has access to the project' do
render_views
2020-03-13 15:44:24 +05:30
let(:signature_commit) { project.commit_by(oid: '0b4bc9a49b562e85de7cc9e834518ea6828729b9') }
2018-10-15 14:42:47 +05:30
let(:non_signature_commit) { build(:commit, project: project, safe_message: "message", sha: 'non_signature_commit') }
before do
2021-04-17 20:07:23 +05:30
escaped_from_ref = Addressable::URI.unescape(from_ref)
escaped_to_ref = Addressable::URI.unescape(to_ref)
2018-10-15 14:42:47 +05:30
2021-04-17 20:07:23 +05:30
compare_service = CompareService.new(project, escaped_to_ref)
compare = compare_service.execute(project, escaped_from_ref)
2018-10-15 14:42:47 +05:30
2021-04-17 20:07:23 +05:30
expect(CompareService).to receive(:new).with(project, escaped_to_ref).and_return(compare_service)
expect(compare_service).to receive(:execute).with(project, escaped_from_ref).and_return(compare)
2018-10-15 14:42:47 +05:30
2022-07-23 23:45:48 +05:30
expect(compare).to receive(:commits).and_return(CommitCollection.new(project, [signature_commit, non_signature_commit]))
2018-10-15 14:42:47 +05:30
expect(non_signature_commit).to receive(:has_signature?).and_return(false)
end
it 'returns only the commit with a signature' do
signatures_request
2020-03-13 15:44:24 +05:30
expect(response).to have_gitlab_http_status(:ok)
2019-09-30 21:07:59 +05:30
signatures = json_response['signatures']
2018-10-15 14:42:47 +05:30
expect(signatures.size).to eq(1)
expect(signatures.first['commit_sha']).to eq(signature_commit.sha)
expect(signatures.first['html']).to be_present
end
end
2021-11-18 22:05:49 +05:30
context 'when the user does not have access to the project', :sidekiq_inline do
2018-10-15 14:42:47 +05:30
before do
project.team.truncate
2021-04-17 20:07:23 +05:30
project.update!(visibility: 'private')
2018-10-15 14:42:47 +05:30
end
it 'returns a 404' do
signatures_request
2020-03-13 15:44:24 +05:30
expect(response).to have_gitlab_http_status(:not_found)
2018-10-15 14:42:47 +05:30
end
end
end
context 'when the source ref does not exist' do
2021-04-17 20:07:23 +05:30
let(:from_ref) { 'non-existent-ref-source' }
let(:to_ref) { 'feature' }
2018-10-15 14:42:47 +05:30
it 'returns no signatures' do
signatures_request
2020-03-13 15:44:24 +05:30
expect(response).to have_gitlab_http_status(:ok)
2019-09-30 21:07:59 +05:30
expect(json_response['signatures']).to be_empty
2018-10-15 14:42:47 +05:30
end
end
context 'when the target ref does not exist' do
2021-04-17 20:07:23 +05:30
let(:from_ref) { 'improve%2Fawesome' }
let(:to_ref) { 'non-existent-ref-target' }
2018-10-15 14:42:47 +05:30
it 'returns no signatures' do
signatures_request
2020-03-13 15:44:24 +05:30
expect(response).to have_gitlab_http_status(:ok)
2019-09-30 21:07:59 +05:30
expect(json_response['signatures']).to be_empty
2018-10-15 14:42:47 +05:30
end
end
end
2015-09-11 14:41:01 +05:30
end