Skip to content
Snippets Groups Projects
Commit d8c06be4 authored by GitLab Bot's avatar GitLab Bot
Browse files

Add latest changes from gitlab-org/gitlab@master

parent 2fa7d2dd
No related branches found
No related tags found
No related merge requests found
Loading
Loading
@@ -10,7 +10,7 @@ describe GitlabSchema.types['Commit'] do
it 'contains attributes related to commit' do
expect(described_class).to have_graphql_fields(
:id, :sha, :title, :description, :message, :authored_date,
:author, :web_url, :latest_pipeline, :signature_html
:author, :web_url, :latest_pipeline, :pipelines, :signature_html
)
end
end
Loading
Loading
@@ -3,7 +3,7 @@ import MockAdapter from 'axios-mock-adapter';
import axios from '~/lib/utils/axios_utils';
import AjaxFormVariableList from '~/ci_variable_list/ajax_variable_list';
 
const VARIABLE_PATCH_ENDPOINT = 'http://test.host/frontend-fixtures/builds-project/variables';
const VARIABLE_PATCH_ENDPOINT = 'http://test.host/frontend-fixtures/builds-project/-/variables';
const HIDE_CLASS = 'hide';
 
describe('AjaxFormVariableList', () => {
Loading
Loading
# frozen_string_literal: true
require 'spec_helper'
 
describe Gitlab::FogbugzImport::Client do
Loading
Loading
require 'spec_helper'
describe Gitlab::Graphql::Loaders::PipelineForShaLoader do
include GraphqlHelpers
describe '#find_last' do
it 'batch-resolves latest pipeline' do
project = create(:project, :repository)
pipeline1 = create(:ci_pipeline, project: project, ref: project.default_branch, sha: project.commit.sha)
pipeline2 = create(:ci_pipeline, project: project, ref: project.default_branch, sha: project.commit.sha)
pipeline3 = create(:ci_pipeline, project: project, ref: 'improve/awesome', sha: project.commit('improve/awesome').sha)
result = batch_sync(max_queries: 1) do
[pipeline1.sha, pipeline3.sha].map { |sha| described_class.new(project, sha).find_last }
end
expect(result).to contain_exactly(pipeline2, pipeline3)
end
end
end
Loading
Loading
@@ -378,6 +378,14 @@ describe MergeRequestDiff do
expect(diff_with_commits.commit_shas).not_to be_empty
expect(diff_with_commits.commit_shas).to all(match(/\h{40}/))
end
context 'with limit attribute' do
it 'returns limited number of shas' do
expect(diff_with_commits.commit_shas(limit: 2).size).to eq(2)
expect(diff_with_commits.commit_shas(limit: 100).size).to eq(29)
expect(diff_with_commits.commit_shas.size).to eq(29)
end
end
end
 
describe '#compare_with' do
Loading
Loading
Loading
Loading
@@ -1261,13 +1261,49 @@ describe MergeRequest do
end
 
describe '#commit_shas' do
before do
allow(subject.merge_request_diff).to receive(:commit_shas)
.and_return(['sha1'])
context 'persisted merge request' do
context 'with a limit' do
it 'returns a limited number of commit shas' do
expect(subject.commit_shas(limit: 2)).to eq(%w[
b83d6e391c22777fca1ed3012fce84f633d7fed0 498214de67004b1da3d820901307bed2a68a8ef6
])
end
end
context 'without a limit' do
it 'returns all commit shas of the merge request diff' do
expect(subject.commit_shas.size).to eq(29)
end
end
end
 
it 'delegates to merge request diff' do
expect(subject.commit_shas).to eq ['sha1']
context 'new merge request' do
subject { build(:merge_request) }
context 'compare commits' do
before do
subject.compare_commits = [
double(sha: 'sha1'), double(sha: 'sha2')
]
end
context 'without a limit' do
it 'returns all shas of compare commits' do
expect(subject.commit_shas).to eq(%w[sha2 sha1])
end
end
context 'with a limit' do
it 'returns a limited number of shas' do
expect(subject.commit_shas(limit: 1)).to eq(['sha2'])
end
end
end
it 'returns diff_head_sha as an array' do
expect(subject.commit_shas).to eq([subject.diff_head_sha])
expect(subject.commit_shas(limit: 2)).to eq([subject.diff_head_sha])
end
end
end
 
Loading
Loading
# frozen_string_literal: true
require 'spec_helper'
describe API::GroupExport do
let_it_be(:group) { create(:group) }
let_it_be(:user) { create(:user) }
let(:path) { "/groups/#{group.id}/export" }
let(:download_path) { "/groups/#{group.id}/export/download" }
let(:export_path) { "#{Dir.tmpdir}/group_export_spec" }
before do
allow_next_instance_of(Gitlab::ImportExport) do |import_export|
expect(import_export).to receive(:storage_path).and_return(export_path)
end
end
after do
FileUtils.rm_rf(export_path, secure: true)
end
describe 'GET /groups/:group_id/export/download' do
let(:upload) { ImportExportUpload.new(group: group) }
before do
stub_uploads_object_storage(ImportExportUploader)
group.add_owner(user)
end
context 'when export file exists' do
before do
upload.export_file = fixture_file_upload('spec/fixtures/group_export.tar.gz', "`/tar.gz")
upload.save!
end
it 'downloads exported group archive' do
get api(download_path, user)
expect(response).to have_gitlab_http_status(200)
end
context 'when export_file.file does not exist' do
before do
expect_next_instance_of(ImportExportUploader) do |uploader|
expect(uploader).to receive(:file).and_return(nil)
end
end
it 'returns 404' do
get api(download_path, user)
expect(response).to have_gitlab_http_status(404)
end
end
end
context 'when export file does not exist' do
it 'returns 404' do
get api(download_path, user)
expect(response).to have_gitlab_http_status(404)
end
end
end
describe 'POST /groups/:group_id/export' do
context 'when user is a group owner' do
before do
group.add_owner(user)
end
it 'accepts download' do
post api(path, user)
expect(response).to have_gitlab_http_status(202)
end
end
context 'when user is not a group owner' do
before do
group.add_developer(user)
end
it 'forbids the request' do
post api(path, user)
expect(response).to have_gitlab_http_status(403)
end
end
end
end
# frozen_string_literal: true
module AccessMatchersHelpers
USER_ACCESSOR_METHOD_NAME = 'user'
def provide_user(role, membership = nil)
case role
when :admin
create(:admin)
when :auditor
create(:user, :auditor)
when :user
create(:user)
when :external
create(:user, :external)
when :visitor, :anonymous
nil
when User
role
when *Gitlab::Access.sym_options_with_owner.keys # owner, maintainer, developer, reporter, guest
raise ArgumentError, "cannot provide #{role} when membership reference is blank" unless membership
provide_user_by_membership(role, membership)
else
raise ArgumentError, "cannot provide user of an unknown role #{role}"
end
end
def provide_user_by_membership(role, membership)
if role == :owner && membership.owner
membership.owner
else
create(:user).tap do |user|
membership.public_send(:"add_#{role}", user)
end
end
end
def raise_if_non_block_expectation!(actual)
raise ArgumentError, 'This matcher supports block expectations only.' unless actual.is_a?(Proc)
end
def update_owner(objects, user)
return unless objects
objects.each do |object|
if object.respond_to?(:owner)
object.update_attribute(:owner, user)
elsif object.respond_to?(:user)
object.update_attribute(:user, user)
else
raise ArgumentError, "cannot own this object #{object}"
end
end
end
def patch_example_group(user)
return if user.nil? # for anonymous users
# This call is evaluated in context of ExampleGroup instance in which the matcher is called. Overrides the `user`
# (or defined by `method_name`) method generated by `let` definition in example group before it's used by `subject`.
# This override is per concrete example only because the example group class gets re-created for each example.
instance_eval(<<~CODE, __FILE__, __LINE__ + 1)
if instance_variable_get(:@__#{USER_ACCESSOR_METHOD_NAME}_patched)
raise ArgumentError, 'An access matcher be_allowed_for/be_denied_for can be used only once per example (`it` block)'
end
instance_variable_set(:@__#{USER_ACCESSOR_METHOD_NAME}_patched, true)
def #{USER_ACCESSOR_METHOD_NAME}
@#{USER_ACCESSOR_METHOD_NAME} ||= User.find(#{user.id})
end
CODE
end
def prepare_matcher_environment(role, membership, owned_objects)
user = provide_user(role, membership)
if user
update_owner(owned_objects, user)
patch_example_group(user)
end
end
def run_matcher(action, role, membership, owned_objects)
raise_if_non_block_expectation!(action)
prepare_matcher_environment(role, membership, owned_objects)
if block_given?
yield action
else
action.call
end
end
end
# frozen_string_literal: true
# AccessMatchersForRequest
#
# Matchers to test the access permissions for requests specs (most useful for API tests).
module AccessMatchersForRequest
extend RSpec::Matchers::DSL
include AccessMatchersHelpers
EXPECTED_STATUS_CODES_ALLOWED = [200, 201, 204, 302, 304].freeze
EXPECTED_STATUS_CODES_DENIED = [401, 403, 404].freeze
def description_for(role, type, expected, result)
"be #{type} for #{role} role. Expected status code: any of #{expected.join(', ')} Got: #{result}"
end
matcher :be_allowed_for do |role|
match do |action|
# methods called in this and negated block are being run in context of ExampleGroup
# (not matcher) instance so we have to pass data via local vars
run_matcher(action, role, @membership, @owned_objects)
EXPECTED_STATUS_CODES_ALLOWED.include?(response.status)
end
match_when_negated do |action|
run_matcher(action, role, @membership, @owned_objects)
EXPECTED_STATUS_CODES_DENIED.include?(response.status)
end
chain :of do |membership|
@membership = membership
end
chain :own do |*owned_objects|
@owned_objects = owned_objects
end
failure_message do
"expected this action to #{description_for(role, 'allowed', EXPECTED_STATUS_CODES_ALLOWED, response.status)}"
end
failure_message_when_negated do
"expected this action to #{description_for(role, 'denied', EXPECTED_STATUS_CODES_DENIED, response.status)}"
end
supports_block_expectations
end
RSpec::Matchers.define_negated_matcher :be_denied_for, :be_allowed_for
end
# frozen_string_literal: true
# AccessMatchersGeneric
#
# Matchers to test the access permissions for service classes or other generic pieces of business logic.
module AccessMatchersGeneric
extend RSpec::Matchers::DSL
include AccessMatchersHelpers
ERROR_CLASS = Gitlab::Access::AccessDeniedError
def error_message(error)
str = error.class.name
str += ": #{error.message}" if error.message != error.class.name
str
end
def error_expectation_message(allowed, error)
if allowed
"Expected to raise nothing but #{error_message(error)} was raised."
else
"Expected to raise #{ERROR_CLASS} but nothing was raised."
end
end
def description_for(role, type, error)
allowed = type == 'allowed'
"be #{type} for #{role} role. #{error_expectation_message(allowed, error)}"
end
matcher :be_allowed_for do |role|
match do |action|
# methods called in this and negated block are being run in context of ExampleGroup
# (not matcher) instance so we have to pass data via local vars
run_matcher(action, role, @membership, @owned_objects) do |action|
action.call
rescue => e
@error = e
raise unless e.is_a?(ERROR_CLASS)
end
@error.nil?
end
chain :of do |membership|
@membership = membership
end
chain :own do |*owned_objects|
@owned_objects = owned_objects
end
failure_message do
"expected this action to #{description_for(role, 'allowed', @error)}"
end
failure_message_when_negated do
"expected this action to #{description_for(role, 'denied', @error)}"
end
supports_block_expectations
end
RSpec::Matchers.define_negated_matcher :be_denied_for, :be_allowed_for
end
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment