diff options
Diffstat (limited to 'spec/lib/api')
41 files changed, 756 insertions, 30 deletions
diff --git a/spec/lib/api/api_spec.rb b/spec/lib/api/api_spec.rb index c83d068ca50..cf08eaa7653 100644 --- a/spec/lib/api/api_spec.rb +++ b/spec/lib/api/api_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe API::API do +RSpec.describe API::API do describe '.prefix' do it 'has a prefix defined' do expect(described_class.prefix).to eq :api diff --git a/spec/lib/api/entities/branch_spec.rb b/spec/lib/api/entities/branch_spec.rb index 604f56c0cb2..e07b431964c 100644 --- a/spec/lib/api/entities/branch_spec.rb +++ b/spec/lib/api/entities/branch_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe API::Entities::Branch do +RSpec.describe API::Entities::Branch do describe '#as_json' do subject { entity.as_json } diff --git a/spec/lib/api/entities/deploy_key_spec.rb b/spec/lib/api/entities/deploy_key_spec.rb index 704dabae63b..6427d6eac8f 100644 --- a/spec/lib/api/entities/deploy_key_spec.rb +++ b/spec/lib/api/entities/deploy_key_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe API::Entities::DeployKey do +RSpec.describe API::Entities::DeployKey do describe '#as_json' do subject { entity.as_json } diff --git a/spec/lib/api/entities/deploy_keys_project_spec.rb b/spec/lib/api/entities/deploy_keys_project_spec.rb index a357467d7ce..57ffdc55736 100644 --- a/spec/lib/api/entities/deploy_keys_project_spec.rb +++ b/spec/lib/api/entities/deploy_keys_project_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe API::Entities::DeployKeysProject do +RSpec.describe API::Entities::DeployKeysProject do describe '#as_json' do subject { entity.as_json } diff --git a/spec/lib/api/entities/design_management/design_spec.rb b/spec/lib/api/entities/design_management/design_spec.rb index 50ca3b43c6a..fe449e3e9bc 100644 --- a/spec/lib/api/entities/design_management/design_spec.rb +++ b/spec/lib/api/entities/design_management/design_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe API::Entities::DesignManagement::Design do +RSpec.describe API::Entities::DesignManagement::Design do let_it_be(:design) { create(:design) } let(:entity) { described_class.new(design, request: double) } diff --git a/spec/lib/api/entities/job_request/image_spec.rb b/spec/lib/api/entities/job_request/image_spec.rb index 092c181ae9c..f13eab6a752 100644 --- a/spec/lib/api/entities/job_request/image_spec.rb +++ b/spec/lib/api/entities/job_request/image_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe API::Entities::JobRequest::Image do +RSpec.describe API::Entities::JobRequest::Image do let(:ports) { [{ number: 80, protocol: 'http', name: 'name' }]} let(:image) { double(name: 'image_name', entrypoint: ['foo'], ports: ports)} let(:entity) { described_class.new(image) } diff --git a/spec/lib/api/entities/job_request/port_spec.rb b/spec/lib/api/entities/job_request/port_spec.rb index 40ab4cd6231..4820c4a691b 100644 --- a/spec/lib/api/entities/job_request/port_spec.rb +++ b/spec/lib/api/entities/job_request/port_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe ::API::Entities::JobRequest::Port do +RSpec.describe ::API::Entities::JobRequest::Port do let(:port) { double(number: 80, protocol: 'http', name: 'name')} let(:entity) { described_class.new(port) } diff --git a/spec/lib/api/entities/merge_request_approvals_spec.rb b/spec/lib/api/entities/merge_request_approvals_spec.rb new file mode 100644 index 00000000000..cbbb037100a --- /dev/null +++ b/spec/lib/api/entities/merge_request_approvals_spec.rb @@ -0,0 +1,36 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe API::Entities::MergeRequestApprovals do + let(:user) { create(:user) } + let(:merge_request) { create(:merge_request) } + + subject { described_class.new(merge_request, current_user: user).as_json } + + before do + merge_request.project.add_developer(user) + end + + it 'serializes an approved merge request' do + create(:approval, merge_request: merge_request, user: user) + + is_expected.to eq({ + user_has_approved: true, + user_can_approve: false, + approved: true, + approved_by: [{ + user: API::Entities::UserBasic.new(user).as_json + }] + }) + end + + it 'serializes a merge request that is not approved' do + is_expected.to eq({ + user_has_approved: false, + user_can_approve: true, + approved: false, + approved_by: [] + }) + end +end diff --git a/spec/lib/api/entities/merge_request_basic_spec.rb b/spec/lib/api/entities/merge_request_basic_spec.rb new file mode 100644 index 00000000000..715fcf4bcdb --- /dev/null +++ b/spec/lib/api/entities/merge_request_basic_spec.rb @@ -0,0 +1,43 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe ::API::Entities::MergeRequestBasic do + let_it_be(:user) { create(:user) } + let_it_be(:project) { create(:project, :public) } + let_it_be(:merge_request) { create(:merge_request) } + let_it_be(:labels) { create_list(:label, 3) } + let_it_be(:merge_requests) { create_list(:labeled_merge_request, 10, :unique_branches, :with_diffs, labels: labels) } + + # This mimics the behavior of the `Grape::Entity` serializer + def present(obj) + described_class.new(obj).presented + end + + context "with :with_api_entity_associations scope" do + let(:scope) { MergeRequest.with_api_entity_associations } + + it "avoids N+1 queries" do + query = scope.find(merge_request.id) + + control = ActiveRecord::QueryRecorder.new do + present(query).to_json + end + + # stub the `head_commit_sha` as it will trigger a + # backward compatibility query that is out-of-scope + # for this test whenever it is `nil` + allow_any_instance_of(MergeRequestDiff).to receive(:head_commit_sha).and_return(Gitlab::Git::BLANK_SHA) + + query = scope.all + batch = ActiveRecord::QueryRecorder.new do + entities = query.map(&method(:present)) + + entities.to_json + end + + # The current threshold is 3 query per entity maximum. + expect(batch.count).to be_within(3 * query.count).of(control.count) + end + end +end diff --git a/spec/lib/api/entities/nuget/dependency_group_spec.rb b/spec/lib/api/entities/nuget/dependency_group_spec.rb new file mode 100644 index 00000000000..5a649be846b --- /dev/null +++ b/spec/lib/api/entities/nuget/dependency_group_spec.rb @@ -0,0 +1,50 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe API::Entities::Nuget::DependencyGroup do + let(:dependency_group) do + { + id: 'http://gitlab.com/Sandbox.App/1.0.0.json#dependencygroup', + type: 'PackageDependencyGroup', + target_framework: 'fwk test', + dependencies: [ + { + id: 'http://gitlab.com/Sandbox.App/1.0.0.json#dependency', + type: 'PackageDependency', + name: 'Dependency', + range: '2.0.0' + } + ] + } + end + + let(:expected) do + { + '@id': 'http://gitlab.com/Sandbox.App/1.0.0.json#dependencygroup', + '@type': 'PackageDependencyGroup', + 'targetFramework': 'fwk test', + 'dependencies': [ + { + '@id': 'http://gitlab.com/Sandbox.App/1.0.0.json#dependency', + '@type': 'PackageDependency', + 'id': 'Dependency', + 'range': '2.0.0' + } + ] + } + end + let(:entity) { described_class.new(dependency_group) } + + subject { entity.as_json } + + it { is_expected.to eq(expected) } + + context 'dependency group without target framework' do + let(:dependency_group_with_no_target_framework) { dependency_group.tap { |dg| dg[:target_framework] = nil } } + let(:expected_no_target_framework) { expected.except(:targetFramework) } + let(:entity) { described_class.new(dependency_group_with_no_target_framework) } + + it { is_expected.to eq(expected_no_target_framework) } + end +end diff --git a/spec/lib/api/entities/nuget/dependency_spec.rb b/spec/lib/api/entities/nuget/dependency_spec.rb new file mode 100644 index 00000000000..13897cc91f0 --- /dev/null +++ b/spec/lib/api/entities/nuget/dependency_spec.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe API::Entities::Nuget::Dependency do + let(:dependency) do + { + id: 'http://gitlab.com/Sandbox.App/1.0.0.json#dependency', + type: 'PackageDependency', + name: 'Dependency', + range: '2.0.0' + } + end + + let(:expected) do + { + '@id': 'http://gitlab.com/Sandbox.App/1.0.0.json#dependency', + '@type': 'PackageDependency', + 'id': 'Dependency', + 'range': '2.0.0' + } + end + let(:entity) { described_class.new(dependency) } + + subject { entity.as_json } + + it { is_expected.to eq(expected) } +end diff --git a/spec/lib/api/entities/nuget/metadatum_spec.rb b/spec/lib/api/entities/nuget/metadatum_spec.rb new file mode 100644 index 00000000000..fe94ea3a69a --- /dev/null +++ b/spec/lib/api/entities/nuget/metadatum_spec.rb @@ -0,0 +1,35 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe API::Entities::Nuget::Metadatum do + let(:metadatum) do + { + project_url: 'http://sandbox.com/project', + license_url: 'http://sandbox.com/license', + icon_url: 'http://sandbox.com/icon' + } + end + let(:expected) do + { + 'projectUrl': 'http://sandbox.com/project', + 'licenseUrl': 'http://sandbox.com/license', + 'iconUrl': 'http://sandbox.com/icon' + } + end + let(:entity) { described_class.new(metadatum) } + + subject { entity.as_json } + + it { is_expected.to eq(expected) } + + %i[project_url license_url icon_url].each do |optional_field| + context "metadatum without #{optional_field}" do + let(:metadatum_without_a_field) { metadatum.except(optional_field) } + let(:expected_without_a_field) { expected.except(optional_field.to_s.camelize(:lower).to_sym) } + let(:entity) { described_class.new(metadatum_without_a_field) } + + it { is_expected.to eq(expected_without_a_field) } + end + end +end diff --git a/spec/lib/api/entities/nuget/package_metadata_catalog_entry_spec.rb b/spec/lib/api/entities/nuget/package_metadata_catalog_entry_spec.rb new file mode 100644 index 00000000000..c422b51bf3b --- /dev/null +++ b/spec/lib/api/entities/nuget/package_metadata_catalog_entry_spec.rb @@ -0,0 +1,43 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe API::Entities::Nuget::PackageMetadataCatalogEntry do + let(:entry) do + { + json_url: 'http://sandbox.com/json/package', + authors: 'Authors', + dependency_groups: [], + package_name: 'PackageTest', + package_version: '1.2.3', + tags: 'tag1 tag2 tag3', + archive_url: 'http://sandbox.com/archive/package', + summary: 'Summary', + metadatum: { + project_url: 'http://sandbox.com/project', + license_url: 'http://sandbox.com/license', + icon_url: 'http://sandbox.com/icon' + } + } + end + + let(:expected) do + { + '@id': 'http://sandbox.com/json/package', + 'id': 'PackageTest', + 'version': '1.2.3', + 'authors': 'Authors', + 'dependencyGroups': [], + 'tags': 'tag1 tag2 tag3', + 'packageContent': 'http://sandbox.com/archive/package', + 'summary': 'Summary', + 'projectUrl': 'http://sandbox.com/project', + 'licenseUrl': 'http://sandbox.com/license', + 'iconUrl': 'http://sandbox.com/icon' + } + end + + subject { described_class.new(entry).as_json } + + it { is_expected.to eq(expected) } +end diff --git a/spec/lib/api/entities/nuget/search_result_spec.rb b/spec/lib/api/entities/nuget/search_result_spec.rb new file mode 100644 index 00000000000..2a760c70224 --- /dev/null +++ b/spec/lib/api/entities/nuget/search_result_spec.rb @@ -0,0 +1,57 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe API::Entities::Nuget::SearchResult do + let(:search_result) do + { + type: 'Package', + authors: 'Author', + name: 'PackageTest', + version: '1.2.3', + versions: [ + { + json_url: 'http://sandbox.com/json/package', + downloads: 100, + version: '1.2.3' + } + ], + summary: 'Summary', + total_downloads: 100, + verified: true, + tags: 'tag1 tag2 tag3', + metadatum: { + project_url: 'http://sandbox.com/project', + license_url: 'http://sandbox.com/license', + icon_url: 'http://sandbox.com/icon' + } + } + end + let(:expected) do + { + '@type': 'Package', + 'authors': 'Author', + 'id': 'PackageTest', + 'title': 'PackageTest', + 'summary': 'Summary', + 'totalDownloads': 100, + 'verified': true, + 'version': '1.2.3', + 'tags': 'tag1 tag2 tag3', + 'projectUrl': 'http://sandbox.com/project', + 'licenseUrl': 'http://sandbox.com/license', + 'iconUrl': 'http://sandbox.com/icon', + 'versions': [ + { + '@id': 'http://sandbox.com/json/package', + 'downloads': 100, + 'version': '1.2.3' + } + ] + } + end + + subject { described_class.new(search_result).as_json } + + it { is_expected.to eq(expected) } +end diff --git a/spec/lib/api/entities/project_import_failed_relation_spec.rb b/spec/lib/api/entities/project_import_failed_relation_spec.rb index f8330713480..51a684c4564 100644 --- a/spec/lib/api/entities/project_import_failed_relation_spec.rb +++ b/spec/lib/api/entities/project_import_failed_relation_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe API::Entities::ProjectImportFailedRelation do +RSpec.describe API::Entities::ProjectImportFailedRelation do describe '#as_json' do subject { entity.as_json } diff --git a/spec/lib/api/entities/project_import_status_spec.rb b/spec/lib/api/entities/project_import_status_spec.rb index a800d703496..5eda613a6a6 100644 --- a/spec/lib/api/entities/project_import_status_spec.rb +++ b/spec/lib/api/entities/project_import_status_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe API::Entities::ProjectImportStatus do +RSpec.describe API::Entities::ProjectImportStatus do describe '#as_json' do subject { entity.as_json } diff --git a/spec/lib/api/entities/project_repository_storage_move_spec.rb b/spec/lib/api/entities/project_repository_storage_move_spec.rb index 1c38c8231d4..b0102dc376a 100644 --- a/spec/lib/api/entities/project_repository_storage_move_spec.rb +++ b/spec/lib/api/entities/project_repository_storage_move_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe API::Entities::ProjectRepositoryStorageMove do +RSpec.describe API::Entities::ProjectRepositoryStorageMove do describe '#as_json' do subject { entity.as_json } diff --git a/spec/lib/api/entities/release_spec.rb b/spec/lib/api/entities/release_spec.rb index fa9e1e74f9b..d57c283c1f4 100644 --- a/spec/lib/api/entities/release_spec.rb +++ b/spec/lib/api/entities/release_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe API::Entities::Release do +RSpec.describe API::Entities::Release do let_it_be(:project) { create(:project) } let(:release) { create(:release, project: project) } let(:evidence) { release.evidences.first } diff --git a/spec/lib/api/entities/snippet_spec.rb b/spec/lib/api/entities/snippet_spec.rb index dada0942e49..bcb8c364392 100644 --- a/spec/lib/api/entities/snippet_spec.rb +++ b/spec/lib/api/entities/snippet_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe ::API::Entities::Snippet do +RSpec.describe ::API::Entities::Snippet do let_it_be(:user) { create(:user) } let_it_be(:personal_snippet) { create(:personal_snippet, :repository, author: user ) } let_it_be(:project_snippet) { create(:project_snippet, :repository, author: user) } @@ -21,6 +21,16 @@ describe ::API::Entities::Snippet do it { expect(subject[:visibility]).to eq snippet.visibility } it { expect(subject).to include(:author) } + context 'with snippet_multiple_files feature disabled' do + before do + stub_feature_flags(snippet_multiple_files: false) + end + + it 'does not return files' do + expect(subject).not_to include(:files) + end + end + describe 'file_name' do it 'returns attribute from repository' do expect(subject[:file_name]).to eq snippet.blobs.first.path @@ -62,6 +72,49 @@ describe ::API::Entities::Snippet do end end end + + describe 'files' do + let(:blob) { snippet.blobs.first } + let(:ref) { blob.repository.root_ref } + + context 'when repository does not exist' do + it 'does not include the files attribute' do + allow(snippet).to receive(:repository_exists?).and_return(false) + + expect(subject).not_to include(:files) + end + end + + shared_examples 'snippet files' do + let(:file) { subject[:files].first } + + it 'returns all snippet files' do + expect(subject[:files].count).to eq snippet.blobs.count + end + + it 'has the file path' do + expect(file[:path]).to eq blob.path + end + + it 'has the raw url' do + expect(file[:raw_url]).to match(raw_url) + end + end + + context 'with PersonalSnippet' do + it_behaves_like 'snippet files' do + let(:snippet) { personal_snippet } + let(:raw_url) { "/-/snippets/#{snippet.id}/raw/#{ref}/#{blob.path}" } + end + end + + context 'with ProjectSnippet' do + it_behaves_like 'snippet files' do + let(:snippet) { project_snippet } + let(:raw_url) { "#{snippet.project.full_path}/-/snippets/#{snippet.id}/raw/#{ref}/#{blob.path}" } + end + end + end end context 'with PersonalSnippet' do diff --git a/spec/lib/api/entities/ssh_key_spec.rb b/spec/lib/api/entities/ssh_key_spec.rb index 25a0fecfb75..768ad416fbe 100644 --- a/spec/lib/api/entities/ssh_key_spec.rb +++ b/spec/lib/api/entities/ssh_key_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe API::Entities::SSHKey do +RSpec.describe API::Entities::SSHKey do describe '#as_json' do subject { entity.as_json } diff --git a/spec/lib/api/entities/user_spec.rb b/spec/lib/api/entities/user_spec.rb index 20524b197e0..99ffe0eb925 100644 --- a/spec/lib/api/entities/user_spec.rb +++ b/spec/lib/api/entities/user_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe API::Entities::User do +RSpec.describe API::Entities::User do let(:user) { create(:user) } let(:current_user) { create(:user) } diff --git a/spec/lib/api/helpers/common_helpers_spec.rb b/spec/lib/api/helpers/common_helpers_spec.rb new file mode 100644 index 00000000000..5162d2f1000 --- /dev/null +++ b/spec/lib/api/helpers/common_helpers_spec.rb @@ -0,0 +1,51 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe API::Helpers::CommonHelpers do + include Rack::Test::Methods + + subject do + Class.new(Grape::API) do + helpers API::Helpers::CommonHelpers + + before do + coerce_nil_params_to_array! + end + + params do + requires :id, type: String + optional :array, type: Array, coerce_with: ::API::Validations::Types::CommaSeparatedToArray.coerce + optional :array_of_strings, type: Array[String], coerce_with: ::API::Validations::Types::CommaSeparatedToArray.coerce + optional :array_of_ints, type: Array[Integer], coerce_with: ::API::Validations::Types::CommaSeparatedToIntegerArray.coerce + end + get ":id" do + params.to_json + end + end + end + + def app + subject + end + + describe '.coerce_nil_params_to_array!' do + let(:json_response) { Gitlab::Json.parse(last_response.body) } + + it 'converts all nil parameters to empty arrays' do + get '/test?array=&array_of_strings=&array_of_ints=' + + expect(json_response['array']).to eq([]) + expect(json_response['array_of_strings']).to eq([]) + expect(json_response['array_of_ints']).to eq([]) + end + + it 'leaves non-nil parameters alone' do + get '/test?array=&array_of_strings=test,me&array_of_ints=1,2' + + expect(json_response['array']).to eq([]) + expect(json_response['array_of_strings']).to eq(%w(test me)) + expect(json_response['array_of_ints']).to eq([1, 2]) + end + end +end diff --git a/spec/lib/api/helpers/graphql_helpers_spec.rb b/spec/lib/api/helpers/graphql_helpers_spec.rb index c775ba6d5e8..678f4f8a3e3 100644 --- a/spec/lib/api/helpers/graphql_helpers_spec.rb +++ b/spec/lib/api/helpers/graphql_helpers_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe API::Helpers::GraphqlHelpers do +RSpec.describe API::Helpers::GraphqlHelpers do describe 'run_graphql!' do let(:query) { '{ metadata { version } }' } diff --git a/spec/lib/api/helpers/label_helpers_spec.rb b/spec/lib/api/helpers/label_helpers_spec.rb index 138e9a22d70..007cb3248e2 100644 --- a/spec/lib/api/helpers/label_helpers_spec.rb +++ b/spec/lib/api/helpers/label_helpers_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe API::Helpers::LabelHelpers do +RSpec.describe API::Helpers::LabelHelpers do describe 'create_service_params' do let(:label_helper) do Class.new do diff --git a/spec/lib/api/helpers/packages/dependency_proxy_helpers_spec.rb b/spec/lib/api/helpers/packages/dependency_proxy_helpers_spec.rb new file mode 100644 index 00000000000..ccf96bcbad6 --- /dev/null +++ b/spec/lib/api/helpers/packages/dependency_proxy_helpers_spec.rb @@ -0,0 +1,72 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe API::Helpers::Packages::DependencyProxyHelpers do + let_it_be(:helper) { Class.new.include(described_class).new } + + describe 'redirect_registry_request' do + using RSpec::Parameterized::TableSyntax + + let(:options) { {} } + + subject { helper.redirect_registry_request(forward_to_registry, package_type, options) { helper.fallback } } + + shared_examples 'executing fallback' do + it 'redirects to package registry' do + expect(helper).to receive(:registry_url).never + expect(helper).to receive(:redirect).never + expect(helper).to receive(:fallback).once + + subject + end + end + + shared_examples 'executing redirect' do + it 'redirects to package registry' do + expect(helper).to receive(:registry_url).once + expect(helper).to receive(:redirect).once + expect(helper).to receive(:fallback).never + + subject + end + end + + context 'with npm packages' do + let(:package_type) { :npm } + + where(:application_setting, :forward_to_registry, :example_name) do + true | true | 'executing redirect' + true | false | 'executing fallback' + false | true | 'executing fallback' + false | false | 'executing fallback' + end + + with_them do + before do + stub_application_setting(npm_package_requests_forwarding: application_setting) + end + + it_behaves_like params[:example_name] + end + end + + context 'with non-forwardable packages' do + let(:forward_to_registry) { true } + + before do + stub_application_setting(npm_package_requests_forwarding: true) + end + + Packages::Package.package_types.keys.without('npm').each do |pkg_type| + context "#{pkg_type}" do + let(:package_type) { pkg_type } + + it 'raises an error' do + expect { subject }.to raise_error(ArgumentError, "Can't build registry_url for package_type #{package_type}") + end + end + end + end + end +end diff --git a/spec/lib/api/helpers/packages_helpers_spec.rb b/spec/lib/api/helpers/packages_helpers_spec.rb new file mode 100644 index 00000000000..0c51e25bad9 --- /dev/null +++ b/spec/lib/api/helpers/packages_helpers_spec.rb @@ -0,0 +1,104 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe API::Helpers::PackagesHelpers do + let_it_be(:helper) { Class.new.include(described_class).new } + let_it_be(:project) { create(:project) } + + describe 'authorize_packages_access!' do + subject { helper.authorize_packages_access!(project) } + + it 'authorizes packages access' do + expect(helper).to receive(:require_packages_enabled!) + expect(helper).to receive(:authorize_read_package!).with(project) + + expect(subject).to eq nil + end + end + + %i[read_package create_package destroy_package].each do |action| + describe "authorize_#{action}!" do + subject { helper.send("authorize_#{action}!", project) } + + it 'calls authorize!' do + expect(helper).to receive(:authorize!).with(action, project) + + expect(subject).to eq nil + end + end + end + + describe 'require_packages_enabled!' do + let(:packages_enabled) { true } + + subject { helper.require_packages_enabled! } + + before do + allow(::Gitlab.config.packages).to receive(:enabled).and_return(packages_enabled) + end + + context 'with packages enabled' do + it "doesn't call not_found!" do + expect(helper).to receive(:not_found!).never + + expect(subject).to eq nil + end + end + + context 'with package disabled' do + let(:packages_enabled) { false } + + it 'calls not_found!' do + expect(helper).to receive(:not_found!).once + + subject + end + end + end + + describe '#authorize_workhorse!' do + let_it_be(:headers) { {} } + + subject { helper.authorize_workhorse!(subject: project) } + + before do + allow(helper).to receive(:headers).and_return(headers) + end + + it 'authorizes workhorse' do + expect(helper).to receive(:authorize_upload!).with(project) + expect(helper).to receive(:status).with(200) + expect(helper).to receive(:content_type).with(Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE) + expect(Gitlab::Workhorse).to receive(:verify_api_request!).with(headers) + expect(::Packages::PackageFileUploader).to receive(:workhorse_authorize).with(has_length: true) + + expect(subject).to eq nil + end + + context 'without length' do + subject { helper.authorize_workhorse!(subject: project, has_length: false) } + + it 'authorizes workhorse' do + expect(helper).to receive(:authorize_upload!).with(project) + expect(helper).to receive(:status).with(200) + expect(helper).to receive(:content_type).with(Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE) + expect(Gitlab::Workhorse).to receive(:verify_api_request!).with(headers) + expect(::Packages::PackageFileUploader).to receive(:workhorse_authorize).with(has_length: false, maximum_size: ::API::Helpers::PackagesHelpers::MAX_PACKAGE_FILE_SIZE) + + expect(subject).to eq nil + end + end + end + + describe '#authorize_upload!' do + subject { helper.authorize_upload!(project) } + + it 'authorizes the upload' do + expect(helper).to receive(:authorize_create_package!).with(project) + expect(helper).to receive(:require_gitlab_workhorse!) + + expect(subject).to eq nil + end + end +end diff --git a/spec/lib/api/helpers/packages_manager_clients_helpers_spec.rb b/spec/lib/api/helpers/packages_manager_clients_helpers_spec.rb new file mode 100644 index 00000000000..80be5f7d10a --- /dev/null +++ b/spec/lib/api/helpers/packages_manager_clients_helpers_spec.rb @@ -0,0 +1,154 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe API::Helpers::PackagesManagerClientsHelpers do + let_it_be(:personal_access_token) { create(:personal_access_token) } + let_it_be(:username) { personal_access_token.user.username } + let_it_be(:helper) { Class.new.include(described_class).new } + let(:password) { personal_access_token.token } + + describe '#find_personal_access_token_from_http_basic_auth' do + let(:headers) { { Authorization: basic_http_auth(username, password) } } + + subject { helper.find_personal_access_token_from_http_basic_auth } + + before do + allow(helper).to receive(:headers).and_return(headers&.with_indifferent_access) + end + + context 'with a valid Authorization header' do + it { is_expected.to eq personal_access_token } + end + + context 'with an invalid Authorization header' do + where(:headers) do + [ + [{ Authorization: 'Invalid' }], + [{}], + [nil] + ] + end + + with_them do + it { is_expected.to be nil } + end + end + + context 'with an unknown Authorization header' do + let(:password) { 'Unknown' } + + it { is_expected.to be nil } + end + end + + describe '#find_job_from_http_basic_auth' do + let_it_be(:user) { personal_access_token.user } + + let(:job) { create(:ci_build, user: user) } + let(:password) { job.token } + let(:headers) { { Authorization: basic_http_auth(username, password) } } + + subject { helper.find_job_from_http_basic_auth } + + before do + allow(helper).to receive(:headers).and_return(headers&.with_indifferent_access) + end + + context 'with a valid Authorization header' do + it { is_expected.to eq job } + end + + context 'with an invalid Authorization header' do + where(:headers) do + [ + [{ Authorization: 'Invalid' }], + [{}], + [nil] + ] + end + + with_them do + it { is_expected.to be nil } + end + end + + context 'with an unknown Authorization header' do + let(:password) { 'Unknown' } + + it { is_expected.to be nil } + end + end + + describe '#find_deploy_token_from_http_basic_auth' do + let_it_be(:deploy_token) { create(:deploy_token) } + let(:token) { deploy_token.token } + let(:headers) { { Authorization: basic_http_auth(deploy_token.username, token) } } + + subject { helper.find_deploy_token_from_http_basic_auth } + + before do + allow(helper).to receive(:headers).and_return(headers&.with_indifferent_access) + end + + context 'with a valid Authorization header' do + it { is_expected.to eq deploy_token } + end + + context 'with an invalid Authorization header' do + where(:headers) do + [ + [{ Authorization: 'Invalid' }], + [{}], + [nil] + ] + end + + with_them do + it { is_expected.to be nil } + end + end + + context 'with an invalid token' do + let(:token) { 'Unknown' } + + it { is_expected.to be nil } + end + end + + describe '#uploaded_package_file' do + let_it_be(:params) { {} } + + subject { helper.uploaded_package_file } + + before do + allow(helper).to receive(:params).and_return(params) + end + + context 'with valid uploaded package file' do + let_it_be(:uploaded_file) { Object.new } + + before do + allow(UploadedFile).to receive(:from_params).and_return(uploaded_file) + end + + it { is_expected.to be uploaded_file } + end + + context 'with invalid uploaded package file' do + before do + allow(UploadedFile).to receive(:from_params).and_return(nil) + end + + it 'fails with bad_request!' do + expect(helper).to receive(:bad_request!) + + expect(subject).to be nil + end + end + end + + def basic_http_auth(username, password) + ActionController::HttpAuthentication::Basic.encode_credentials(username, password) + end +end diff --git a/spec/lib/api/helpers/pagination_spec.rb b/spec/lib/api/helpers/pagination_spec.rb index 796c753d6c4..a008c1adeac 100644 --- a/spec/lib/api/helpers/pagination_spec.rb +++ b/spec/lib/api/helpers/pagination_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe API::Helpers::Pagination do +RSpec.describe API::Helpers::Pagination do subject { Class.new.include(described_class).new } let(:paginator) { double('paginator') } diff --git a/spec/lib/api/helpers/pagination_strategies_spec.rb b/spec/lib/api/helpers/pagination_strategies_spec.rb index eaa71159714..e8a4243b407 100644 --- a/spec/lib/api/helpers/pagination_strategies_spec.rb +++ b/spec/lib/api/helpers/pagination_strategies_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe API::Helpers::PaginationStrategies do +RSpec.describe API::Helpers::PaginationStrategies do subject { Class.new.include(described_class).new } let(:expected_result) { double("result") } diff --git a/spec/lib/api/helpers/related_resources_helpers_spec.rb b/spec/lib/api/helpers/related_resources_helpers_spec.rb index eeeb22abd10..a0dc69536b4 100644 --- a/spec/lib/api/helpers/related_resources_helpers_spec.rb +++ b/spec/lib/api/helpers/related_resources_helpers_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe API::Helpers::RelatedResourcesHelpers do +RSpec.describe API::Helpers::RelatedResourcesHelpers do subject(:helpers) do Class.new.include(described_class).new end diff --git a/spec/lib/api/helpers/version_spec.rb b/spec/lib/api/helpers/version_spec.rb index a9f33962537..a87a3c5a026 100644 --- a/spec/lib/api/helpers/version_spec.rb +++ b/spec/lib/api/helpers/version_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe API::Helpers::Version do +RSpec.describe API::Helpers::Version do describe '.new' do it 'is possible to initialize it with existing API version' do expect(described_class.new('v4').to_s).to eq 'v4' diff --git a/spec/lib/api/helpers_spec.rb b/spec/lib/api/helpers_spec.rb index 3595d06a184..8cba1e0794a 100644 --- a/spec/lib/api/helpers_spec.rb +++ b/spec/lib/api/helpers_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe API::Helpers do +RSpec.describe API::Helpers do subject { Class.new.include(described_class).new } describe '#find_project' do diff --git a/spec/lib/api/support/git_access_actor_spec.rb b/spec/lib/api/support/git_access_actor_spec.rb index 69637947c79..70753856419 100644 --- a/spec/lib/api/support/git_access_actor_spec.rb +++ b/spec/lib/api/support/git_access_actor_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe API::Support::GitAccessActor do +RSpec.describe API::Support::GitAccessActor do let(:user) { nil } let(:key) { nil } diff --git a/spec/lib/api/validations/validators/absence_spec.rb b/spec/lib/api/validations/validators/absence_spec.rb index 31120979d4f..bfecaf4e243 100644 --- a/spec/lib/api/validations/validators/absence_spec.rb +++ b/spec/lib/api/validations/validators/absence_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe API::Validations::Validators::Absence do +RSpec.describe API::Validations::Validators::Absence do include ApiValidatorsHelpers subject do diff --git a/spec/lib/api/validations/validators/array_none_any_spec.rb b/spec/lib/api/validations/validators/array_none_any_spec.rb index 03f1c63b117..833adea6554 100644 --- a/spec/lib/api/validations/validators/array_none_any_spec.rb +++ b/spec/lib/api/validations/validators/array_none_any_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe API::Validations::Validators::ArrayNoneAny do +RSpec.describe API::Validations::Validators::ArrayNoneAny do include ApiValidatorsHelpers subject do diff --git a/spec/lib/api/validations/validators/file_path_spec.rb b/spec/lib/api/validations/validators/file_path_spec.rb index 8679f102d23..2c79260b8d5 100644 --- a/spec/lib/api/validations/validators/file_path_spec.rb +++ b/spec/lib/api/validations/validators/file_path_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe API::Validations::Validators::FilePath do +RSpec.describe API::Validations::Validators::FilePath do include ApiValidatorsHelpers subject do diff --git a/spec/lib/api/validations/validators/git_ref_spec.rb b/spec/lib/api/validations/validators/git_ref_spec.rb index 84de6272fe1..0d2d9e8f39a 100644 --- a/spec/lib/api/validations/validators/git_ref_spec.rb +++ b/spec/lib/api/validations/validators/git_ref_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe API::Validations::Validators::GitRef do +RSpec.describe API::Validations::Validators::GitRef do include ApiValidatorsHelpers subject do diff --git a/spec/lib/api/validations/validators/git_sha_spec.rb b/spec/lib/api/validations/validators/git_sha_spec.rb index 39c2fe1dcf9..ae6be52a4c7 100644 --- a/spec/lib/api/validations/validators/git_sha_spec.rb +++ b/spec/lib/api/validations/validators/git_sha_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe API::Validations::Validators::GitSha do +RSpec.describe API::Validations::Validators::GitSha do include ApiValidatorsHelpers let(:sha) { RepoHelpers.sample_commit.id } diff --git a/spec/lib/api/validations/validators/integer_none_any_spec.rb b/spec/lib/api/validations/validators/integer_none_any_spec.rb index a42f69fd96e..33fa7688d18 100644 --- a/spec/lib/api/validations/validators/integer_none_any_spec.rb +++ b/spec/lib/api/validations/validators/integer_none_any_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe API::Validations::Validators::IntegerNoneAny do +RSpec.describe API::Validations::Validators::IntegerNoneAny do include ApiValidatorsHelpers subject do diff --git a/spec/lib/api/validations/validators/limit_spec.rb b/spec/lib/api/validations/validators/limit_spec.rb index 600f74e1fb2..d71dde470cc 100644 --- a/spec/lib/api/validations/validators/limit_spec.rb +++ b/spec/lib/api/validations/validators/limit_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe API::Validations::Validators::Limit do +RSpec.describe API::Validations::Validators::Limit do include ApiValidatorsHelpers subject do diff --git a/spec/lib/api/validations/validators/untrusted_regexp_spec.rb b/spec/lib/api/validations/validators/untrusted_regexp_spec.rb index 491bf94fd79..def67c94de0 100644 --- a/spec/lib/api/validations/validators/untrusted_regexp_spec.rb +++ b/spec/lib/api/validations/validators/untrusted_regexp_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe API::Validations::Validators::UntrustedRegexp do +RSpec.describe API::Validations::Validators::UntrustedRegexp do include ApiValidatorsHelpers subject do |