summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-01-29 15:08:59 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2020-01-29 15:08:59 +0000
commit23288f62da73fb0e30d8e7ce306665e8fda1b932 (patch)
tree2baf1339e4d7c7c35d6b8a52cfb90597a5d4cdf1 /spec
parent7cc6872401eb487ed20dbb9d455f8bb9c97d9e39 (diff)
downloadgitlab-ce-23288f62da73fb0e30d8e7ce306665e8fda1b932.tar.gz
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r--spec/controllers/projects/merge_requests_controller_spec.rb15
-rw-r--r--spec/controllers/projects/repositories_controller_spec.rb12
-rw-r--r--spec/factories/merge_request_context_commit.rb12
-rw-r--r--spec/factories/merge_request_context_commit_diff_file.rb20
-rw-r--r--spec/features/groups/navbar_spec.rb51
-rw-r--r--spec/features/projects/files/user_browses_files_spec.rb25
-rw-r--r--spec/features/projects/navbar_spec.rb104
-rw-r--r--spec/finders/context_commits_finder_spec.rb28
-rw-r--r--spec/frontend/clusters/components/applications_spec.js3
-rw-r--r--spec/initializers/attr_encrypted_thread_safe_spec.rb28
-rw-r--r--spec/lib/gitlab/database/sha_attribute_spec.rb2
-rw-r--r--spec/lib/gitlab/import_export/all_models.yml5
-rw-r--r--spec/lib/gitlab/import_export/safe_model_attributes.yml25
-rw-r--r--spec/models/merge_request_context_commit_diff_file_spec.rb9
-rw-r--r--spec/models/merge_request_context_commit_spec.rb33
-rw-r--r--spec/models/merge_request_diff_commit_spec.rb7
-rw-r--r--spec/requests/api/internal/base_spec.rb6
-rw-r--r--spec/requests/api/merge_requests_spec.rb177
-rw-r--r--spec/serializers/diffs_metadata_entity_spec.rb1
-rw-r--r--spec/services/merge_requests/add_context_service_spec.rb44
-rw-r--r--spec/support/shared_examples/features/navbar_shared_examples.rb20
21 files changed, 614 insertions, 13 deletions
diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb
index 826c69ee5f0..da26eb94fb0 100644
--- a/spec/controllers/projects/merge_requests_controller_spec.rb
+++ b/spec/controllers/projects/merge_requests_controller_spec.rb
@@ -791,6 +791,21 @@ describe Projects::MergeRequestsController do
end
end
+ describe 'GET context commits' do
+ it 'returns the commits for context commits' do
+ get :context_commits,
+ params: {
+ namespace_id: project.namespace.to_param,
+ project_id: project,
+ id: merge_request.iid
+ },
+ format: 'json'
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(json_response).to be_an Array
+ end
+ end
+
describe 'GET exposed_artifacts' do
let(:merge_request) do
create(:merge_request,
diff --git a/spec/controllers/projects/repositories_controller_spec.rb b/spec/controllers/projects/repositories_controller_spec.rb
index aeb053fe9f6..42dfdd3115c 100644
--- a/spec/controllers/projects/repositories_controller_spec.rb
+++ b/spec/controllers/projects/repositories_controller_spec.rb
@@ -17,6 +17,7 @@ describe Projects::RepositoriesController do
context 'as a user' do
let(:user) { create(:user) }
+ let(:archive_name) { "#{project.path}-master" }
before do
project.add_developer(user)
@@ -30,9 +31,18 @@ describe Projects::RepositoriesController do
end
it 'responds with redirect to the short name archive if fully qualified' do
- get :archive, params: { namespace_id: project.namespace, project_id: project, id: "master/#{project.path}-master" }, format: "zip"
+ get :archive, params: { namespace_id: project.namespace, project_id: project, id: "master/#{archive_name}" }, format: "zip"
expect(assigns(:ref)).to eq("master")
+ expect(assigns(:filename)).to eq(archive_name)
+ expect(response.header[Gitlab::Workhorse::SEND_DATA_HEADER]).to start_with("git-archive:")
+ end
+
+ it 'responds with redirect for a path with multiple slashes' do
+ get :archive, params: { namespace_id: project.namespace, project_id: project, id: "improve/awesome/#{archive_name}" }, format: "zip"
+
+ expect(assigns(:ref)).to eq("improve/awesome")
+ expect(assigns(:filename)).to eq(archive_name)
expect(response.header[Gitlab::Workhorse::SEND_DATA_HEADER]).to start_with("git-archive:")
end
diff --git a/spec/factories/merge_request_context_commit.rb b/spec/factories/merge_request_context_commit.rb
new file mode 100644
index 00000000000..f9bfc9af02e
--- /dev/null
+++ b/spec/factories/merge_request_context_commit.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :merge_request_context_commit do
+ association :merge_request, factory: :merge_request
+ author_name { 'test' }
+ author_email { 'test@test.com' }
+ message { '' }
+ relative_order { 0 }
+ sha { Digest::SHA1.hexdigest(SecureRandom.hex) }
+ end
+end
diff --git a/spec/factories/merge_request_context_commit_diff_file.rb b/spec/factories/merge_request_context_commit_diff_file.rb
new file mode 100644
index 00000000000..eb497166d05
--- /dev/null
+++ b/spec/factories/merge_request_context_commit_diff_file.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :merge_request_context_commit_diff_file do
+ association :merge_request_context_commit
+
+ sha { Digest::SHA1.hexdigest(SecureRandom.hex) }
+ relative_order { 0 }
+ new_file { true }
+ renamed_file { false }
+ deleted_file { false }
+ too_large { false }
+ a_mode { 0 }
+ b_mode { 100644 }
+ new_path { 'foo' }
+ old_path { 'foo' }
+ diff { '' }
+ binary { false }
+ end
+end
diff --git a/spec/features/groups/navbar_spec.rb b/spec/features/groups/navbar_spec.rb
new file mode 100644
index 00000000000..e348eb80b1a
--- /dev/null
+++ b/spec/features/groups/navbar_spec.rb
@@ -0,0 +1,51 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'Group navbar' do
+ it_behaves_like 'verified navigation bar' do
+ let(:user) { create(:user) }
+ let(:group) { create(:group) }
+
+ let(:structure) do
+ [
+ {
+ nav_item: _('Group overview'),
+ nav_sub_items: [
+ _('Details'),
+ _('Activity'),
+ (_('Contribution Analytics') if Gitlab.ee?)
+ ]
+ },
+ {
+ nav_item: _('Issues'),
+ nav_sub_items: [
+ _('List'),
+ _('Board'),
+ _('Labels'),
+ _('Milestones')
+ ]
+ },
+ {
+ nav_item: _('Merge Requests'),
+ nav_sub_items: []
+ },
+ {
+ nav_item: _('Kubernetes'),
+ nav_sub_items: []
+ },
+ {
+ nav_item: _('Members'),
+ nav_sub_items: []
+ }
+ ]
+ end
+
+ before do
+ group.add_maintainer(user)
+ sign_in(user)
+
+ visit group_path(group)
+ end
+ end
+end
diff --git a/spec/features/projects/files/user_browses_files_spec.rb b/spec/features/projects/files/user_browses_files_spec.rb
index b8efabb0cab..5364bc10b2f 100644
--- a/spec/features/projects/files/user_browses_files_spec.rb
+++ b/spec/features/projects/files/user_browses_files_spec.rb
@@ -171,6 +171,31 @@ describe "User browses files" do
end
end
+ context "when browsing a `improve/awesome` branch", :js do
+ before do
+ visit(project_tree_path(project, "improve/awesome"))
+ end
+
+ it "shows files from a repository" do
+ expect(page).to have_content("VERSION")
+ .and have_content(".gitignore")
+ .and have_content("LICENSE")
+ end
+ end
+
+ context "when browsing a `test-#` branch", :js do
+ before do
+ project.repository.create_branch('test-#', project.repository.root_ref)
+ visit(project_tree_path(project, "test-#"))
+ end
+
+ it "shows files from a repository" do
+ expect(page).to have_content("VERSION")
+ .and have_content(".gitignore")
+ .and have_content("LICENSE")
+ end
+ end
+
context "when browsing a specific ref", :js do
let(:ref) { project_tree_path(project, "6d39438") }
diff --git a/spec/features/projects/navbar_spec.rb b/spec/features/projects/navbar_spec.rb
new file mode 100644
index 00000000000..f87bd5ca529
--- /dev/null
+++ b/spec/features/projects/navbar_spec.rb
@@ -0,0 +1,104 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'Project navbar' do
+ it_behaves_like 'verified navigation bar' do
+ let(:user) { create(:user) }
+ let(:project) { create(:project, :repository) }
+
+ let(:structure) do
+ [
+ {
+ nav_item: _('Project overview'),
+ nav_sub_items: [
+ _('Details'),
+ _('Activity'),
+ _('Releases')
+ ]
+ },
+ {
+ nav_item: _('Repository'),
+ nav_sub_items: [
+ _('Files'),
+ _('Commits'),
+ _('Branches'),
+ _('Tags'),
+ _('Contributors'),
+ _('Graph'),
+ _('Compare'),
+ (_('Locked Files') if Gitlab.ee?)
+ ]
+ },
+ {
+ nav_item: _('Issues'),
+ nav_sub_items: [
+ _('List'),
+ _('Boards'),
+ _('Labels'),
+ _('Milestones')
+ ]
+ },
+ {
+ nav_item: _('Merge Requests'),
+ nav_sub_items: []
+ },
+ {
+ nav_item: _('CI / CD'),
+ nav_sub_items: [
+ _('Pipelines'),
+ _('Jobs'),
+ _('Artifacts'),
+ _('Schedules')
+ ]
+ },
+ {
+ nav_item: _('Operations'),
+ nav_sub_items: [
+ _('Metrics'),
+ _('Environments'),
+ _('Error Tracking'),
+ _('Serverless'),
+ _('Kubernetes'),
+ _('Auto DevOps')
+ ]
+ },
+ {
+ nav_item: _('Analytics'),
+ nav_sub_items: [
+ (_('Code Review') if Gitlab.ee?),
+ _('Cycle Analytics'),
+ _('Repository Analytics')
+ ]
+ },
+ {
+ nav_item: _('Wiki'),
+ nav_sub_items: []
+ },
+ {
+ nav_item: _('Snippets'),
+ nav_sub_items: []
+ },
+ {
+ nav_item: _('Settings'),
+ nav_sub_items: [
+ _('General'),
+ _('Members'),
+ _('Integrations'),
+ _('Repository'),
+ _('CI / CD'),
+ _('Operations'),
+ (_('Audit Events') if Gitlab.ee?)
+ ].compact
+ }
+ ]
+ end
+
+ before do
+ project.add_maintainer(user)
+ sign_in(user)
+
+ visit project_path(project)
+ end
+ end
+end
diff --git a/spec/finders/context_commits_finder_spec.rb b/spec/finders/context_commits_finder_spec.rb
new file mode 100644
index 00000000000..13cfa32ecfc
--- /dev/null
+++ b/spec/finders/context_commits_finder_spec.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe ContextCommitsFinder do
+ describe "#execute" do
+ let(:project) { create(:project, :repository) }
+ let(:merge_request) { create(:merge_request) }
+ let(:commit) { create(:commit, id: '6d394385cf567f80a8fd85055db1ab4c5295806f') }
+
+ it 'filters commits by valid sha/commit message' do
+ params = { search: commit.id }
+
+ commits = described_class.new(project, merge_request, params).execute
+
+ expect(commits.length).to eq(1)
+ expect(commits[0].id).to eq(commit.id)
+ end
+
+ it 'returns nothing when searched by invalid sha/commit message' do
+ params = { search: 'zzz' }
+
+ commits = described_class.new(project, merge_request, params).execute
+
+ expect(commits).to be_empty
+ end
+ end
+end
diff --git a/spec/frontend/clusters/components/applications_spec.js b/spec/frontend/clusters/components/applications_spec.js
index 01e9b04dcd7..c3336edfe59 100644
--- a/spec/frontend/clusters/components/applications_spec.js
+++ b/spec/frontend/clusters/components/applications_spec.js
@@ -14,9 +14,6 @@ describe('Applications', () => {
beforeEach(() => {
Applications = Vue.extend(applications);
-
- gon.features = gon.features || {};
- gon.features.enableClusterApplicationElasticStack = true;
});
afterEach(() => {
diff --git a/spec/initializers/attr_encrypted_thread_safe_spec.rb b/spec/initializers/attr_encrypted_thread_safe_spec.rb
new file mode 100644
index 00000000000..096b8b196b4
--- /dev/null
+++ b/spec/initializers/attr_encrypted_thread_safe_spec.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe AttrEncrypted do
+ describe '#encrypted_attributes' do
+ subject do
+ Class.new(ActiveRecord::Base) do
+ self.table_name = 'projects'
+
+ attr_accessor :encrypted_foo
+ attr_accessor :encrypted_foo_iv
+
+ attr_encrypted :foo, key: 'This is a key that is 256 bits!!'
+ end
+ end
+
+ it 'does not share state with other instances' do
+ instance = subject.new
+ instance.foo = 'bar'
+
+ another_instance = subject.new
+
+ expect(instance.encrypted_attributes[:foo][:operation]).to eq(:encrypting)
+ expect(another_instance.encrypted_attributes[:foo][:operation]).to be_nil
+ end
+ end
+end
diff --git a/spec/lib/gitlab/database/sha_attribute_spec.rb b/spec/lib/gitlab/database/sha_attribute_spec.rb
index c6fc55291f5..15695bc8069 100644
--- a/spec/lib/gitlab/database/sha_attribute_spec.rb
+++ b/spec/lib/gitlab/database/sha_attribute_spec.rb
@@ -25,7 +25,7 @@ describe Gitlab::Database::ShaAttribute do
describe '#serialize' do
it 'converts a SHA String to binary data' do
- expect(attribute.serialize(sha).to_s).to eq(binary_sha)
+ expect(described_class.serialize(sha).to_s).to eq(binary_sha)
end
end
end
diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml
index 08e57e541a4..22c2fc5545e 100644
--- a/spec/lib/gitlab/import_export/all_models.yml
+++ b/spec/lib/gitlab/import_export/all_models.yml
@@ -125,6 +125,8 @@ merge_requests:
- merge_user
- merge_request_diffs
- merge_request_diff
+- merge_request_context_commits
+- merge_request_context_commit_diff_files
- events
- merge_requests_closing_issues
- cached_closes_issues
@@ -170,6 +172,9 @@ merge_request_diff_commits:
- merge_request_diff
merge_request_diff_files:
- merge_request_diff
+merge_request_context_commits:
+- merge_request
+- diff_files
ci_pipelines:
- project
- user
diff --git a/spec/lib/gitlab/import_export/safe_model_attributes.yml b/spec/lib/gitlab/import_export/safe_model_attributes.yml
index ad363233bfe..9c4854a30ad 100644
--- a/spec/lib/gitlab/import_export/safe_model_attributes.yml
+++ b/spec/lib/gitlab/import_export/safe_model_attributes.yml
@@ -225,6 +225,31 @@ MergeRequestDiffFile:
- b_mode
- too_large
- binary
+MergeRequestContextCommit:
+- id
+- authored_date
+- committed_date
+- relative_order
+- sha
+- author_name
+- author_email
+- committer_name
+- committer_email
+- message
+- merge_request_id
+MergeRequestContextCommitDiffFile:
+- sha
+- relative_order
+- new_file
+- renamed_file
+- deleted_file
+- new_path
+- old_path
+- a_mode
+- b_mode
+- too_large
+- binary
+- text
MergeRequest::Metrics:
- id
- created_at
diff --git a/spec/models/merge_request_context_commit_diff_file_spec.rb b/spec/models/merge_request_context_commit_diff_file_spec.rb
new file mode 100644
index 00000000000..37d44662326
--- /dev/null
+++ b/spec/models/merge_request_context_commit_diff_file_spec.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe MergeRequestContextCommitDiffFile do
+ describe 'associations' do
+ it { is_expected.to belong_to(:merge_request_context_commit) }
+ end
+end
diff --git a/spec/models/merge_request_context_commit_spec.rb b/spec/models/merge_request_context_commit_spec.rb
new file mode 100644
index 00000000000..5a1bf9874ac
--- /dev/null
+++ b/spec/models/merge_request_context_commit_spec.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe MergeRequestContextCommit do
+ let(:merge_request) { create(:merge_request) }
+ let(:project) { merge_request.project }
+ let(:raw_repository) { project.repository.raw_repository }
+ let(:commits) do
+ [
+ project.commit('5937ac0a7beb003549fc5fd26fc247adbce4a52e'),
+ project.commit('570e7b2abdd848b95f2f578043fc23bd6f6fd24d')
+ ]
+ end
+
+ describe 'associations' do
+ it { is_expected.to belong_to(:merge_request) }
+ it { is_expected.to have_many(:diff_files).class_name("MergeRequestContextCommitDiffFile") }
+ end
+
+ describe '.delete_bulk' do
+ let(:context_commit1) { create(:merge_request_context_commit, merge_request: merge_request, sha: '5937ac0a7beb003549fc5fd26fc247adbce4a52e') }
+ let(:context_commit2) { create(:merge_request_context_commit, merge_request: merge_request, sha: '570e7b2abdd848b95f2f578043fc23bd6f6fd24d') }
+
+ it 'deletes context commits for given commit sha\'s and returns the commit' do
+ expect(described_class.delete_bulk(merge_request, [context_commit1, context_commit2])).to eq(2)
+ end
+
+ it 'doesn\'t delete context commits when commit sha\'s are not passed' do
+ expect(described_class.delete_bulk(merge_request, [])).to eq(0)
+ end
+ end
+end
diff --git a/spec/models/merge_request_diff_commit_spec.rb b/spec/models/merge_request_diff_commit_spec.rb
index c0a09dab0b0..a74c0b20642 100644
--- a/spec/models/merge_request_diff_commit_spec.rb
+++ b/spec/models/merge_request_diff_commit_spec.rb
@@ -18,7 +18,6 @@ describe MergeRequestDiffCommit do
end
describe '.create_bulk' do
- let(:sha_attribute) { Gitlab::Database::ShaAttribute.new }
let(:merge_request_diff_id) { merge_request.merge_request_diff.id }
let(:commits) do
[
@@ -38,7 +37,7 @@ describe MergeRequestDiffCommit do
"committer_email": "dmitriy.zaporozhets@gmail.com",
"merge_request_diff_id": merge_request_diff_id,
"relative_order": 0,
- "sha": sha_attribute.serialize("5937ac0a7beb003549fc5fd26fc247adbce4a52e")
+ "sha": Gitlab::Database::ShaAttribute.serialize("5937ac0a7beb003549fc5fd26fc247adbce4a52e")
},
{
"message": "Change some files\n\nSigned-off-by: Dmitriy Zaporozhets \u003cdmitriy.zaporozhets@gmail.com\u003e\n",
@@ -50,7 +49,7 @@ describe MergeRequestDiffCommit do
"committer_email": "dmitriy.zaporozhets@gmail.com",
"merge_request_diff_id": merge_request_diff_id,
"relative_order": 1,
- "sha": sha_attribute.serialize("570e7b2abdd848b95f2f578043fc23bd6f6fd24d")
+ "sha": Gitlab::Database::ShaAttribute.serialize("570e7b2abdd848b95f2f578043fc23bd6f6fd24d")
}
]
end
@@ -81,7 +80,7 @@ describe MergeRequestDiffCommit do
"committer_email": "alejorro70@gmail.com",
"merge_request_diff_id": merge_request_diff_id,
"relative_order": 0,
- "sha": sha_attribute.serialize("ba3343bc4fa403a8dfbfcab7fc1a8c29ee34bd69")
+ "sha": Gitlab::Database::ShaAttribute.serialize("ba3343bc4fa403a8dfbfcab7fc1a8c29ee34bd69")
}]
end
diff --git a/spec/requests/api/internal/base_spec.rb b/spec/requests/api/internal/base_spec.rb
index 93feef83067..cb10bebfd98 100644
--- a/spec/requests/api/internal/base_spec.rb
+++ b/spec/requests/api/internal/base_spec.rb
@@ -326,7 +326,7 @@ describe API::Internal::Base do
expect(json_response["gitaly"]["repository"]["relative_path"]).to eq(project.repository.gitaly_repository.relative_path)
expect(json_response["gitaly"]["address"]).to eq(Gitlab::GitalyClient.address(project.repository_storage))
expect(json_response["gitaly"]["token"]).to eq(Gitlab::GitalyClient.token(project.repository_storage))
- expect(json_response["gitaly"]["features"]).to eq('gitaly-feature-inforef-uploadpack-cache' => 'true', 'gitaly-feature-cache-invalidator' => 'true', 'gitaly-feature-commit-without-batch-check' => 'true')
+ expect(json_response["gitaly"]["features"]).to eq('gitaly-feature-inforef-uploadpack-cache' => 'true', 'gitaly-feature-cache-invalidator' => 'true', 'gitaly-feature-commit-without-batch-check' => 'true', 'gitaly-feature-use-core-delta-islands' => 'true')
expect(user.reload.last_activity_on).to eql(Date.today)
end
end
@@ -346,7 +346,7 @@ describe API::Internal::Base do
expect(json_response["gitaly"]["repository"]["relative_path"]).to eq(project.repository.gitaly_repository.relative_path)
expect(json_response["gitaly"]["address"]).to eq(Gitlab::GitalyClient.address(project.repository_storage))
expect(json_response["gitaly"]["token"]).to eq(Gitlab::GitalyClient.token(project.repository_storage))
- expect(json_response["gitaly"]["features"]).to eq('gitaly-feature-inforef-uploadpack-cache' => 'true', 'gitaly-feature-cache-invalidator' => 'true', 'gitaly-feature-commit-without-batch-check' => 'true')
+ expect(json_response["gitaly"]["features"]).to eq('gitaly-feature-inforef-uploadpack-cache' => 'true', 'gitaly-feature-cache-invalidator' => 'true', 'gitaly-feature-commit-without-batch-check' => 'true', 'gitaly-feature-use-core-delta-islands' => 'true')
expect(user.reload.last_activity_on).to be_nil
end
end
@@ -594,7 +594,7 @@ describe API::Internal::Base do
expect(json_response["gitaly"]["repository"]["relative_path"]).to eq(project.repository.gitaly_repository.relative_path)
expect(json_response["gitaly"]["address"]).to eq(Gitlab::GitalyClient.address(project.repository_storage))
expect(json_response["gitaly"]["token"]).to eq(Gitlab::GitalyClient.token(project.repository_storage))
- expect(json_response["gitaly"]["features"]).to eq('gitaly-feature-inforef-uploadpack-cache' => 'true', 'gitaly-feature-cache-invalidator' => 'true', 'gitaly-feature-commit-without-batch-check' => 'true')
+ expect(json_response["gitaly"]["features"]).to eq('gitaly-feature-inforef-uploadpack-cache' => 'true', 'gitaly-feature-cache-invalidator' => 'true', 'gitaly-feature-commit-without-batch-check' => 'true', 'gitaly-feature-use-core-delta-islands' => 'true')
end
end
diff --git a/spec/requests/api/merge_requests_spec.rb b/spec/requests/api/merge_requests_spec.rb
index c3d92a90d11..58ae4565582 100644
--- a/spec/requests/api/merge_requests_spec.rb
+++ b/spec/requests/api/merge_requests_spec.rb
@@ -12,7 +12,8 @@ describe API::MergeRequests do
let(:project) { create(:project, :public, :repository, creator: user, namespace: user.namespace, only_allow_merge_if_pipeline_succeeds: false) }
let(:milestone) { create(:milestone, title: '1.0.0', project: project) }
let(:milestone1) { create(:milestone, title: '0.9', project: project) }
- let!(:merge_request) { create(:merge_request, :simple, milestone: milestone1, author: user, assignees: [user], source_project: project, target_project: project, source_branch: 'markdown', title: "Test", created_at: base_time) }
+ let(:merge_request_context_commit) {create(:merge_request_context_commit, message: 'test')}
+ let!(:merge_request) { create(:merge_request, :simple, milestone: milestone1, author: user, assignees: [user], merge_request_context_commits: [merge_request_context_commit], source_project: project, target_project: project, source_branch: 'markdown', title: "Test", created_at: base_time) }
let!(:merge_request_closed) { create(:merge_request, state: "closed", milestone: milestone1, author: user, assignees: [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, assignees: [user], source_project: project, target_project: project, title: "Merged test", created_at: base_time + 2.seconds, merge_commit_sha: '9999999999999999999999999999999999999999') }
let!(:merge_request_locked) { create(:merge_request, state: "locked", milestone: milestone1, author: user, assignees: [user], source_project: project, target_project: project, title: "Locked test", created_at: base_time + 1.second) }
@@ -1066,6 +1067,20 @@ describe API::MergeRequests do
end
end
+ describe 'GET /projects/:id/merge_requests/:merge_request_iid/:context_commits' do
+ it 'returns a 200 when merge request is valid' do
+ get api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/context_commits", user)
+ expect(response).to have_gitlab_http_status(200)
+ expect(json_response).to be_an Array
+ expect(json_response.size).to eq(merge_request.context_commits.size)
+ end
+
+ it 'returns a 404 when merge_request_iid not found' do
+ get api("/projects/#{project.id}/merge_requests/0/context_commits", user)
+ expect(response).to have_gitlab_http_status(404)
+ end
+ end
+
describe 'GET /projects/:id/merge_requests/:merge_request_iid/changes' do
it 'returns the change information of the merge_request' do
get api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/changes", user)
@@ -1540,6 +1555,93 @@ describe API::MergeRequests do
end
end
+ describe "POST /projects/:id/merge_requests/:merge_request_iid/context_commits" do
+ let(:merge_request_iid) { merge_request.iid }
+ let(:authenticated_user) { user }
+ let(:commit) { project.repository.commit }
+
+ let(:params) do
+ {
+ commits: [commit.id]
+ }
+ end
+
+ let(:params_empty_commits) do
+ {
+ commits: []
+ }
+ end
+
+ let(:params_invalid_shas) do
+ {
+ commits: ['invalid']
+ }
+ end
+
+ describe 'when authenticated' do
+ it 'creates and returns the new context commit' do
+ post api("/projects/#{project.id}/merge_requests/#{merge_request_iid}/context_commits", authenticated_user), params: params
+ expect(response).to have_gitlab_http_status(201)
+ expect(json_response).to be_an Array
+ expect(json_response.first['short_id']).to eq(commit.short_id)
+ expect(json_response.first['title']).to eq(commit.title)
+ expect(json_response.first['message']).to eq(commit.message)
+ expect(json_response.first['author_name']).to eq(commit.author_name)
+ expect(json_response.first['author_email']).to eq(commit.author_email)
+ expect(json_response.first['committer_name']).to eq(commit.committer_name)
+ expect(json_response.first['committer_email']).to eq(commit.committer_email)
+ end
+
+ context 'doesnt create when its already created' do
+ before do
+ create(:merge_request_context_commit, merge_request: merge_request, sha: commit.id)
+ end
+ it 'returns 400 when the context commit is already created' do
+ post api("/projects/#{project.id}/merge_requests/#{merge_request_iid}/context_commits", authenticated_user), params: params
+ expect(response).to have_gitlab_http_status(400)
+ expect(json_response['message']).to eq("Context commits: [\"#{commit.id}\"] are already created")
+ end
+ end
+
+ it 'returns 400 when one or more shas are invalid' do
+ post api("/projects/#{project.id}/merge_requests/#{merge_request_iid}/context_commits", authenticated_user), params: params_invalid_shas
+ expect(response).to have_gitlab_http_status(400)
+ expect(json_response['message']).to eq('One or more context commits\' sha is not valid.')
+ end
+
+ it 'returns 400 when the commits are empty' do
+ post api("/projects/#{project.id}/merge_requests/#{merge_request_iid}/context_commits", authenticated_user), params: params_empty_commits
+ expect(response).to have_gitlab_http_status(400)
+ end
+
+ it 'returns 400 when params is empty' do
+ post api("/projects/#{project.id}/merge_requests/#{merge_request_iid}/context_commits", authenticated_user)
+ expect(response).to have_gitlab_http_status(400)
+ end
+
+ it 'returns 403 when creating new context commit for guest role' do
+ guest = create(:user)
+ project.add_guest(guest)
+ post api("/projects/#{project.id}/merge_requests/#{merge_request_iid}/context_commits", guest), params: params
+ expect(response).to have_gitlab_http_status(403)
+ end
+
+ it 'returns 403 when creating new context commit for reporter role' do
+ reporter = create(:user)
+ project.add_reporter(reporter)
+ post api("/projects/#{project.id}/merge_requests/#{merge_request_iid}/context_commits", reporter), params: params
+ expect(response).to have_gitlab_http_status(403)
+ end
+ end
+
+ context 'when unauthenticated' do
+ it 'returns 401 if user tries to create context commits' do
+ post api("/projects/#{project.id}/merge_requests/#{merge_request_iid}/context_commits"), params: params
+ expect(response).to have_gitlab_http_status(401)
+ end
+ end
+ end
+
describe "DELETE /projects/:id/merge_requests/:merge_request_iid" do
context "when the user is developer" do
let(:developer) { create(:user) }
@@ -1579,6 +1681,79 @@ describe API::MergeRequests do
end
end
+ describe "DELETE /projects/:id/merge_requests/:merge_request_iid/context_commits" do
+ let(:merge_request_iid) { merge_request.iid }
+ let(:authenticated_user) { user }
+ let(:commit) { project.repository.commit }
+
+ context "when authenticated" do
+ let(:params) do
+ {
+ commits: [commit.id]
+ }
+ end
+
+ let(:params_invalid_shas) do
+ {
+ commits: ["invalid"]
+ }
+ end
+
+ let(:params_empty_commits) do
+ {
+ commits: []
+ }
+ end
+
+ it "deletes context commit" do
+ delete api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/context_commits", authenticated_user), params: params
+
+ expect(response).to have_gitlab_http_status(204)
+ end
+
+ it "returns 400 when invalid commit sha is passed" do
+ delete api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/context_commits", authenticated_user), params: params_invalid_shas
+
+ expect(response).to have_gitlab_http_status(400)
+ expect(json_response["message"]).to eq('One or more context commits\' sha is not valid.')
+ end
+
+ it "returns 400 when commits is empty" do
+ delete api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/context_commits", authenticated_user), params: params_empty_commits
+
+ expect(response).to have_gitlab_http_status(400)
+ end
+
+ it "returns 400 when no params is passed" do
+ delete api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/context_commits", authenticated_user)
+
+ expect(response).to have_gitlab_http_status(400)
+ end
+
+ it 'returns 403 when deleting existing context commit for guest role' do
+ guest = create(:user)
+ project.add_guest(guest)
+ delete api("/projects/#{project.id}/merge_requests/#{merge_request_iid}/context_commits", guest), params: params
+ expect(response).to have_gitlab_http_status(403)
+ end
+
+ it 'returns 403 when deleting existing context commit for reporter role' do
+ reporter = create(:user)
+ project.add_reporter(reporter)
+ delete api("/projects/#{project.id}/merge_requests/#{merge_request_iid}/context_commits", reporter), params: params
+ expect(response).to have_gitlab_http_status(403)
+ end
+ end
+
+ context "when unauthenticated" do
+ it "returns 401, unauthorised error" do
+ delete api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/context_commits")
+
+ expect(response).to have_gitlab_http_status(401)
+ end
+ end
+ end
+
describe "PUT /projects/:id/merge_requests/:merge_request_iid/merge", :clean_gitlab_redis_cache do
let(:pipeline) { create(:ci_pipeline) }
diff --git a/spec/serializers/diffs_metadata_entity_spec.rb b/spec/serializers/diffs_metadata_entity_spec.rb
index 0fa643d37b3..86438bd59d7 100644
--- a/spec/serializers/diffs_metadata_entity_spec.rb
+++ b/spec/serializers/diffs_metadata_entity_spec.rb
@@ -29,6 +29,7 @@ describe DiffsMetadataEntity do
:added_lines, :removed_lines, :render_overflow_warning,
:email_patch_path, :plain_diff_path,
:merge_request_diffs,
+ :context_commits,
# Attributes
:diff_files
)
diff --git a/spec/services/merge_requests/add_context_service_spec.rb b/spec/services/merge_requests/add_context_service_spec.rb
new file mode 100644
index 00000000000..d4e95c2f1ea
--- /dev/null
+++ b/spec/services/merge_requests/add_context_service_spec.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe MergeRequests::AddContextService do
+ let(:project) { create(:project, :repository) }
+ let(:admin) { create(:admin) }
+ let(:merge_request) { create(:merge_request, source_project: project, target_project: project, author: admin) }
+ let(:commits) { ["874797c3a73b60d2187ed6e2fcabd289ff75171e"] }
+ let(:raw_repository) { project.repository.raw }
+
+ subject(:service) { described_class.new(project, admin, merge_request: merge_request, commits: commits) }
+
+ describe "#execute" do
+ it "adds context commit" do
+ service.execute
+
+ expect(merge_request.merge_request_context_commit_diff_files.length).to eq(2)
+ end
+
+ context "when user doesn't have permission to update merge request" do
+ let(:user) { create(:user) }
+ let(:merge_request1) { create(:merge_request, source_project: project, author: user) }
+
+ subject(:service) { described_class.new(project, user, merge_request: merge_request, commits: commits) }
+
+ it "doesn't add context commit" do
+ subject.execute
+
+ expect(merge_request.merge_request_context_commit_diff_files.length).to eq(0)
+ end
+ end
+
+ context "when the commits array is empty" do
+ subject(:service) { described_class.new(project, admin, merge_request: merge_request, commits: []) }
+
+ it "doesn't add context commit" do
+ subject.execute
+
+ expect(merge_request.merge_request_context_commit_diff_files.length).to eq(0)
+ end
+ end
+ end
+end
diff --git a/spec/support/shared_examples/features/navbar_shared_examples.rb b/spec/support/shared_examples/features/navbar_shared_examples.rb
new file mode 100644
index 00000000000..a963739878e
--- /dev/null
+++ b/spec/support/shared_examples/features/navbar_shared_examples.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'verified navigation bar' do
+ it 'renders correctly' do
+ current_structure = page.find_all('.sidebar-top-level-items > li', class: ['!hidden']).map do |item|
+ nav_item = item.find_all('a').first.text.gsub(/\s+\d+$/, '') # remove counts at the end
+
+ nav_sub_items = item
+ .find_all('.sidebar-sub-level-items a')
+ .map(&:text)
+ .drop(1) # remove the first hidden item
+
+ { nav_item: nav_item, nav_sub_items: nav_sub_items }
+ end
+
+ structure.each { |s| s[:nav_sub_items].compact! }
+
+ expect(current_structure).to eq(structure)
+ end
+end