Commit 29777f4a authored by Sean McGivern's avatar Sean McGivern

Merge branch 'vij-add-files-to-project-snippets-endpoint' into 'master'

Add support for files in ProjectSnippets REST API

See merge request gitlab-org/gitlab!38485
parents 40fff8cc f2d30a01
......@@ -56,16 +56,20 @@ module API
end
params do
requires :title, type: String, allow_blank: false, desc: 'The title of the snippet'
requires :file_name, type: String, desc: 'The file name of the snippet'
requires :content, type: String, allow_blank: false, desc: 'The content of the snippet'
optional :description, type: String, desc: 'The description of a snippet'
requires :visibility, type: String,
values: Gitlab::VisibilityLevel.string_values,
desc: 'The visibility of the snippet'
use :create_file_params
end
post ":id/snippets" do
authorize! :create_snippet, user_project
snippet_params = declared_params(include_missing: false).merge(request: request, api: true)
snippet_params = declared_params(include_missing: false).tap do |create_args|
create_args[:request] = request
create_args[:api] = true
process_file_args(create_args)
end
service_response = ::Snippets::CreateService.new(user_project, current_user, snippet_params).execute
snippet = service_response.payload[:snippet]
......
......@@ -123,16 +123,19 @@ RSpec.describe API::ProjectSnippets do
end
describe 'POST /projects/:project_id/snippets/' do
let(:params) do
let(:base_params) do
{
title: 'Test Title',
file_name: 'test.rb',
description: 'test description',
content: 'puts "hello world"',
visibility: 'public'
}
end
let(:file_path) { 'file_1.rb' }
let(:file_content) { 'puts "hello world"' }
let(:params) { base_params.merge(file_params) }
let(:file_params) { { files: [{ file_path: file_path, content: file_content }] } }
shared_examples 'project snippet repository actions' do
let(:snippet) { ProjectSnippet.find(json_response['id']) }
......@@ -145,9 +148,9 @@ RSpec.describe API::ProjectSnippets do
it 'commit the files to the repository' do
subject
blob = snippet.repository.blob_at('master', params[:file_name])
blob = snippet.repository.blob_at('master', file_path)
expect(blob.data).to eq params[:content]
expect(blob.data).to eq file_content
end
end
......@@ -184,63 +187,60 @@ RSpec.describe API::ProjectSnippets do
params['visibility'] = 'internal'
end
subject { post api("/projects/#{project.id}/snippets/", user), params: params }
it 'creates a new snippet' do
post api("/projects/#{project.id}/snippets/", user), params: params
subject
expect(response).to have_gitlab_http_status(:created)
snippet = ProjectSnippet.find(json_response['id'])
expect(snippet.content).to eq(params[:content])
expect(snippet.content).to eq(file_content)
expect(snippet.description).to eq(params[:description])
expect(snippet.title).to eq(params[:title])
expect(snippet.file_name).to eq(params[:file_name])
expect(snippet.file_name).to eq(file_path)
expect(snippet.visibility_level).to eq(Snippet::INTERNAL)
end
it_behaves_like 'project snippet repository actions' do
subject { post api("/projects/#{project.id}/snippets/", user), params: params }
end
it_behaves_like 'project snippet repository actions'
end
it 'creates a new snippet' do
post api("/projects/#{project.id}/snippets/", admin), params: params
context 'with an admin' do
subject { post api("/projects/#{project.id}/snippets/", admin), params: params }
expect(response).to have_gitlab_http_status(:created)
snippet = ProjectSnippet.find(json_response['id'])
expect(snippet.content).to eq(params[:content])
expect(snippet.description).to eq(params[:description])
expect(snippet.title).to eq(params[:title])
expect(snippet.file_name).to eq(params[:file_name])
expect(snippet.visibility_level).to eq(Snippet::PUBLIC)
end
it 'creates a new snippet' do
subject
it_behaves_like 'project snippet repository actions' do
subject { post api("/projects/#{project.id}/snippets/", admin), params: params }
end
expect(response).to have_gitlab_http_status(:created)
snippet = ProjectSnippet.find(json_response['id'])
expect(snippet.content).to eq(file_content)
expect(snippet.description).to eq(params[:description])
expect(snippet.title).to eq(params[:title])
expect(snippet.file_name).to eq(file_path)
expect(snippet.visibility_level).to eq(Snippet::PUBLIC)
end
it 'returns 400 for missing parameters' do
params.delete(:title)
it_behaves_like 'project snippet repository actions'
post api("/projects/#{project.id}/snippets/", admin), params: params
it 'returns 400 for missing parameters' do
params.delete(:title)
expect(response).to have_gitlab_http_status(:bad_request)
end
subject
it 'returns 400 if content is blank' do
params[:content] = ''
expect(response).to have_gitlab_http_status(:bad_request)
end
post api("/projects/#{project.id}/snippets/", admin), params: params
it_behaves_like 'snippet creation with files parameter'
expect(response).to have_gitlab_http_status(:bad_request)
expect(json_response['error']).to eq 'content is empty'
end
it_behaves_like 'snippet creation without files parameter'
it 'returns 400 if title is blank' do
params[:title] = ''
it 'returns 400 if title is blank' do
params[:title] = ''
post api("/projects/#{project.id}/snippets/", admin), params: params
subject
expect(response).to have_gitlab_http_status(:bad_request)
expect(json_response['error']).to eq 'title is empty'
expect(response).to have_gitlab_http_status(:bad_request)
expect(json_response['error']).to eq 'title is empty'
end
end
context 'when save fails because the repository could not be created' do
......
......@@ -274,52 +274,7 @@ RSpec.describe API::Snippets do
end
context 'with files parameter' do
using RSpec::Parameterized::TableSyntax
where(:path, :content, :status, :error) do
'.gitattributes' | 'file content' | :created | nil
'valid/path/file.rb' | 'file content' | :created | nil
'.gitattributes' | nil | :bad_request | 'files[0][content] is empty'
'.gitattributes' | '' | :bad_request | 'files[0][content] is empty'
'' | 'file content' | :bad_request | 'files[0][file_path] is empty'
nil | 'file content' | :bad_request | 'files[0][file_path] should be a valid file path, files[0][file_path] is empty'
'../../etc/passwd' | 'file content' | :bad_request | 'files[0][file_path] should be a valid file path'
end
with_them do
let(:file_path) { path }
let(:file_content) { content }
before do
subject
end
it 'responds correctly' do
expect(response).to have_gitlab_http_status(status)
expect(json_response['error']).to eq(error)
end
end
it 'returns 400 if both files and content are provided' do
params[:file_name] = 'foo.rb'
params[:content] = 'bar'
subject
expect(response).to have_gitlab_http_status(:bad_request)
expect(json_response['error']).to eq 'files, content are mutually exclusive'
end
it 'returns 400 when neither files or content are provided' do
params.delete(:files)
subject
expect(response).to have_gitlab_http_status(:bad_request)
expect(json_response['error']).to eq 'files, content are missing, exactly one parameter must be provided'
end
it_behaves_like 'snippet creation with files parameter'
context 'with multiple files' do
let(:file_params) do
......@@ -335,24 +290,7 @@ RSpec.describe API::Snippets do
end
end
context 'without files parameter' do
let(:file_params) { { file_name: 'testing.rb', content: 'snippet content' } }
it 'allows file_name and content parameters' do
subject
expect(response).to have_gitlab_http_status(:created)
end
it 'returns 400 if file_name and content are not both provided' do
params.delete(:file_name)
subject
expect(response).to have_gitlab_http_status(:bad_request)
expect(json_response['error']).to eq 'file_name is missing'
end
end
it_behaves_like 'snippet creation without files parameter'
context 'with restricted visibility settings' do
before do
......
......@@ -106,3 +106,80 @@ RSpec.shared_examples 'snippet_multiple_files feature disabled' do
expect(json_response).not_to have_key('files')
end
end
RSpec.shared_examples 'snippet creation with files parameter' do
using RSpec::Parameterized::TableSyntax
where(:path, :content, :status, :error) do
'.gitattributes' | 'file content' | :created | nil
'valid/path/file.rb' | 'file content' | :created | nil
'.gitattributes' | nil | :bad_request | 'files[0][content] is empty'
'.gitattributes' | '' | :bad_request | 'files[0][content] is empty'
'' | 'file content' | :bad_request | 'files[0][file_path] is empty'
nil | 'file content' | :bad_request | 'files[0][file_path] should be a valid file path, files[0][file_path] is empty'
'../../etc/passwd' | 'file content' | :bad_request | 'files[0][file_path] should be a valid file path'
end
with_them do
let(:file_path) { path }
let(:file_content) { content }
before do
subject
end
it 'responds correctly' do
expect(response).to have_gitlab_http_status(status)
expect(json_response['error']).to eq(error)
end
end
it 'returns 400 if both files and content are provided' do
params[:file_name] = 'foo.rb'
params[:content] = 'bar'
subject
expect(response).to have_gitlab_http_status(:bad_request)
expect(json_response['error']).to eq 'files, content are mutually exclusive'
end
it 'returns 400 when neither files or content are provided' do
params.delete(:files)
subject
expect(response).to have_gitlab_http_status(:bad_request)
expect(json_response['error']).to eq 'files, content are missing, exactly one parameter must be provided'
end
end
RSpec.shared_examples 'snippet creation without files parameter' do
let(:file_params) { { file_name: 'testing.rb', content: 'snippet content' } }
it 'allows file_name and content parameters' do
subject
expect(response).to have_gitlab_http_status(:created)
end
it 'returns 400 if file_name and content are not both provided' do
params.delete(:file_name)
subject
expect(response).to have_gitlab_http_status(:bad_request)
expect(json_response['error']).to eq 'file_name is missing'
end
it 'returns 400 if content is blank' do
params[:content] = ''
subject
expect(response).to have_gitlab_http_status(:bad_request)
expect(json_response['error']).to eq 'content is empty'
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