Commit 3007979c authored by David Fernandez's avatar David Fernandez Committed by Etienne Baqué

Refactor NPM requests specs for shared endpoints

Use tabled based specs to better test different conditions.
Make sure that we use the Bearer http authorization header and not the
request parameter.
Move package tags shared examples in a dedicated file for npm specs.
parent 0ebd272f
...@@ -6,7 +6,7 @@ RSpec.describe API::NpmInstancePackages do ...@@ -6,7 +6,7 @@ RSpec.describe API::NpmInstancePackages do
include_context 'npm api setup' include_context 'npm api setup'
describe 'GET /api/v4/packages/npm/*package_name' do describe 'GET /api/v4/packages/npm/*package_name' do
it_behaves_like 'handling get metadata requests' do it_behaves_like 'handling get metadata requests', scope: :instance do
let(:url) { api("/packages/npm/#{package_name}") } let(:url) { api("/packages/npm/#{package_name}") }
end end
end end
......
...@@ -6,25 +6,25 @@ RSpec.describe API::NpmProjectPackages do ...@@ -6,25 +6,25 @@ RSpec.describe API::NpmProjectPackages do
include_context 'npm api setup' include_context 'npm api setup'
describe 'GET /api/v4/projects/:id/packages/npm/*package_name' do describe 'GET /api/v4/projects/:id/packages/npm/*package_name' do
it_behaves_like 'handling get metadata requests' do it_behaves_like 'handling get metadata requests', scope: :project do
let(:url) { api("/projects/#{project.id}/packages/npm/#{package_name}") } let(:url) { api("/projects/#{project.id}/packages/npm/#{package_name}") }
end end
end end
describe 'GET /api/v4/projects/:id/packages/npm/-/package/*package_name/dist-tags' do describe 'GET /api/v4/projects/:id/packages/npm/-/package/*package_name/dist-tags' do
it_behaves_like 'handling get dist tags requests' do it_behaves_like 'handling get dist tags requests', scope: :project do
let(:url) { api("/projects/#{project.id}/packages/npm/-/package/#{package_name}/dist-tags") } let(:url) { api("/projects/#{project.id}/packages/npm/-/package/#{package_name}/dist-tags") }
end end
end end
describe 'PUT /api/v4/projects/:id/packages/npm/-/package/*package_name/dist-tags/:tag' do describe 'PUT /api/v4/projects/:id/packages/npm/-/package/*package_name/dist-tags/:tag' do
it_behaves_like 'handling create dist tag requests' do it_behaves_like 'handling create dist tag requests', scope: :project do
let(:url) { api("/projects/#{project.id}/packages/npm/-/package/#{package_name}/dist-tags/#{tag_name}") } let(:url) { api("/projects/#{project.id}/packages/npm/-/package/#{package_name}/dist-tags/#{tag_name}") }
end end
end end
describe 'DELETE /api/v4/projects/:id/packages/npm/-/package/*package_name/dist-tags/:tag' do describe 'DELETE /api/v4/projects/:id/packages/npm/-/package/*package_name/dist-tags/:tag' do
it_behaves_like 'handling delete dist tag requests' do it_behaves_like 'handling delete dist tag requests', scope: :project do
let(:url) { api("/projects/#{project.id}/packages/npm/-/package/#{package_name}/dist-tags/#{tag_name}") } let(:url) { api("/projects/#{project.id}/packages/npm/-/package/#{package_name}/dist-tags/#{tag_name}") }
end end
end end
...@@ -32,10 +32,14 @@ RSpec.describe API::NpmProjectPackages do ...@@ -32,10 +32,14 @@ RSpec.describe API::NpmProjectPackages do
describe 'GET /api/v4/projects/:id/packages/npm/*package_name/-/*file_name' do describe 'GET /api/v4/projects/:id/packages/npm/*package_name/-/*file_name' do
let_it_be(:package_file) { package.package_files.first } let_it_be(:package_file) { package.package_files.first }
let(:params) { {} } let(:headers) { {} }
let(:url) { api("/projects/#{project.id}/packages/npm/#{package_file.package.name}/-/#{package_file.file_name}") } let(:url) { api("/projects/#{project.id}/packages/npm/#{package.name}/-/#{package_file.file_name}") }
subject { get(url, params: params) } subject { get(url, headers: headers) }
before do
project.add_developer(user)
end
shared_examples 'a package file that requires auth' do shared_examples 'a package file that requires auth' do
it 'denies download with no token' do it 'denies download with no token' do
...@@ -45,7 +49,7 @@ RSpec.describe API::NpmProjectPackages do ...@@ -45,7 +49,7 @@ RSpec.describe API::NpmProjectPackages do
end end
context 'with access token' do context 'with access token' do
let(:params) { { access_token: token.token } } let(:headers) { build_token_auth_header(token.token) }
it 'returns the file' do it 'returns the file' do
subject subject
...@@ -56,7 +60,7 @@ RSpec.describe API::NpmProjectPackages do ...@@ -56,7 +60,7 @@ RSpec.describe API::NpmProjectPackages do
end end
context 'with job token' do context 'with job token' do
let(:params) { { job_token: job.token } } let(:headers) { build_token_auth_header(job.token) }
it 'returns the file' do it 'returns the file' do
subject subject
...@@ -86,7 +90,7 @@ RSpec.describe API::NpmProjectPackages do ...@@ -86,7 +90,7 @@ RSpec.describe API::NpmProjectPackages do
it_behaves_like 'a package file that requires auth' it_behaves_like 'a package file that requires auth'
context 'with guest' do context 'with guest' do
let(:params) { { access_token: token.token } } let(:headers) { build_token_auth_header(token.token) }
it 'denies download when not enough permissions' do it 'denies download when not enough permissions' do
project.add_guest(user) project.add_guest(user)
...@@ -108,7 +112,11 @@ RSpec.describe API::NpmProjectPackages do ...@@ -108,7 +112,11 @@ RSpec.describe API::NpmProjectPackages do
end end
describe 'PUT /api/v4/projects/:id/packages/npm/:package_name' do describe 'PUT /api/v4/projects/:id/packages/npm/:package_name' do
RSpec.shared_examples 'handling invalid record with 400 error' do before do
project.add_developer(user)
end
shared_examples 'handling invalid record with 400 error' do
it 'handles an ActiveRecord::RecordInvalid exception with 400 error' do it 'handles an ActiveRecord::RecordInvalid exception with 400 error' do
expect { upload_package_with_token(package_name, params) } expect { upload_package_with_token(package_name, params) }
.not_to change { project.packages.count } .not_to change { project.packages.count }
...@@ -261,7 +269,9 @@ RSpec.describe API::NpmProjectPackages do ...@@ -261,7 +269,9 @@ RSpec.describe API::NpmProjectPackages do
end end
def upload_package(package_name, params = {}) def upload_package(package_name, params = {})
put api("/projects/#{project.id}/packages/npm/#{package_name.sub('/', '%2f')}"), params: params token = params.delete(:access_token) || params.delete(:job_token)
headers = build_token_auth_header(token)
put api("/projects/#{project.id}/packages/npm/#{package_name.sub('/', '%2f')}"), params: params, headers: headers
end end
def upload_package_with_token(package_name, params = {}) def upload_package_with_token(package_name, params = {})
......
...@@ -4,10 +4,10 @@ RSpec.shared_context 'npm api setup' do ...@@ -4,10 +4,10 @@ RSpec.shared_context 'npm api setup' do
include PackagesManagerApiSpecHelpers include PackagesManagerApiSpecHelpers
include HttpBasicAuthHelpers include HttpBasicAuthHelpers
let_it_be(:user) { create(:user) } let_it_be(:user, reload: true) { create(:user) }
let_it_be(:group) { create(:group) } let_it_be(:group) { create(:group) }
let_it_be(:project, reload: true) { create(:project, :public, namespace: group) } let_it_be(:project, reload: true) { create(:project, :public, namespace: group) }
let_it_be(:package, reload: true) { create(:npm_package, project: project) } let_it_be(:package, reload: true) { create(:npm_package, project: project, name: "@#{group.path}/scoped_package") }
let_it_be(:token) { create(:oauth_access_token, scopes: 'api', resource_owner: user) } let_it_be(:token) { create(:oauth_access_token, scopes: 'api', resource_owner: user) }
let_it_be(:personal_access_token) { create(:personal_access_token, user: user) } let_it_be(:personal_access_token) { create(:personal_access_token, user: user) }
let_it_be(:job, reload: true) { create(:ci_build, user: user, status: :running) } let_it_be(:job, reload: true) { create(:ci_build, user: user, status: :running) }
...@@ -15,8 +15,15 @@ RSpec.shared_context 'npm api setup' do ...@@ -15,8 +15,15 @@ RSpec.shared_context 'npm api setup' do
let_it_be(:project_deploy_token) { create(:project_deploy_token, deploy_token: deploy_token, project: project) } let_it_be(:project_deploy_token) { create(:project_deploy_token, deploy_token: deploy_token, project: project) }
let(:package_name) { package.name } let(:package_name) { package.name }
end
before do RSpec.shared_context 'set package name from package name type' do
project.add_developer(user) let(:package_name) do
case package_name_type
when :scoped_naming_convention
"@#{group.path}/scoped-package"
when :non_existing
'non-existing-package'
end
end end
end end
# frozen_string_literal: true # frozen_string_literal: true
RSpec.shared_examples 'rejects package tags access' do |user_type, status| RSpec.shared_examples 'rejects package tags access' do |status:|
context "for user type #{user_type}" do
before do before do
project.send("add_#{user_type}", user) unless user_type == :no_type package.update!(name: package_name) unless package_name == 'non-existing-package'
end end
it_behaves_like 'returning response status', status it_behaves_like 'returning response status', status
end
end end
RSpec.shared_examples 'returns package tags' do |user_type| RSpec.shared_examples 'accept package tags request' do |status:|
using RSpec::Parameterized::TableSyntax using RSpec::Parameterized::TableSyntax
before do before do
stub_application_setting(npm_package_requests_forwarding: false) stub_application_setting(npm_package_requests_forwarding: false)
project.send("add_#{user_type}", user) unless user_type == :no_type
end end
it_behaves_like 'returning response status', :success context 'with valid package name' do
before do
package.update!(name: package_name) unless package_name == 'non-existing-package'
end
it_behaves_like 'returning response status', status
it 'returns a valid json response' do it 'returns a valid json response' do
subject subject
...@@ -36,6 +38,7 @@ RSpec.shared_examples 'returns package tags' do |user_type| ...@@ -36,6 +38,7 @@ RSpec.shared_examples 'returns package tags' do |user_type|
expect(json_response[package_tag2.name]).to eq(package.version) expect(json_response[package_tag2.name]).to eq(package.version)
expect(json_response['latest']).to eq(package.version) expect(json_response['latest']).to eq(package.version)
end end
end
context 'with invalid package name' do context 'with invalid package name' do
where(:package_name, :status) do where(:package_name, :status) do
...@@ -49,11 +52,12 @@ RSpec.shared_examples 'returns package tags' do |user_type| ...@@ -49,11 +52,12 @@ RSpec.shared_examples 'returns package tags' do |user_type|
end end
end end
RSpec.shared_examples 'create package tag' do |user_type| RSpec.shared_examples 'accept create package tag request' do |user_type|
using RSpec::Parameterized::TableSyntax using RSpec::Parameterized::TableSyntax
context 'with valid package name' do
before do before do
project.send("add_#{user_type}", user) unless user_type == :no_type package.update!(name: package_name) unless package_name == 'non-existing-package'
end end
it_behaves_like 'returning response status', :no_content it_behaves_like 'returning response status', :no_content
...@@ -92,6 +96,7 @@ RSpec.shared_examples 'create package tag' do |user_type| ...@@ -92,6 +96,7 @@ RSpec.shared_examples 'create package tag' do |user_type|
expect(response.body).to be_empty expect(response.body).to be_empty
end end
end end
end
context 'with invalid package name' do context 'with invalid package name' do
where(:package_name, :status) do where(:package_name, :status) do
...@@ -129,14 +134,14 @@ RSpec.shared_examples 'create package tag' do |user_type| ...@@ -129,14 +134,14 @@ RSpec.shared_examples 'create package tag' do |user_type|
end end
end end
RSpec.shared_examples 'delete package tag' do |user_type| RSpec.shared_examples 'accept delete package tag request' do |user_type|
using RSpec::Parameterized::TableSyntax using RSpec::Parameterized::TableSyntax
context 'with valid package name' do
before do before do
project.send("add_#{user_type}", user) unless user_type == :no_type package.update!(name: package_name) unless package_name == 'non-existing-package'
end end
context "for #{user_type} user" do
it_behaves_like 'returning response status', :no_content it_behaves_like 'returning response status', :no_content
it 'returns a valid response' do it 'returns a valid response' do
...@@ -157,6 +162,7 @@ RSpec.shared_examples 'delete package tag' do |user_type| ...@@ -157,6 +162,7 @@ RSpec.shared_examples 'delete package tag' do |user_type|
it_behaves_like 'returning response status', :not_found it_behaves_like 'returning response status', :not_found
end end
end
context 'with invalid package name' do context 'with invalid package name' do
where(:package_name, :status) do where(:package_name, :status) do
...@@ -181,5 +187,4 @@ RSpec.shared_examples 'delete package tag' do |user_type| ...@@ -181,5 +187,4 @@ RSpec.shared_examples 'delete package tag' do |user_type|
it_behaves_like 'returning response status', params[:status] it_behaves_like 'returning response status', params[:status]
end end
end end
end
end end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment