Commit f2d30a01 authored by Vijay Hawoldar's avatar Vijay Hawoldar

Add support for files in ProjectSnippets REST API

This change adds support for an array of files when creating
a ProjectSnippet via the REST API
parent 0838bbc8
...@@ -56,16 +56,20 @@ module API ...@@ -56,16 +56,20 @@ module API
end end
params do params do
requires :title, type: String, allow_blank: false, desc: 'The title of the snippet' 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' optional :description, type: String, desc: 'The description of a snippet'
requires :visibility, type: String, requires :visibility, type: String,
values: Gitlab::VisibilityLevel.string_values, values: Gitlab::VisibilityLevel.string_values,
desc: 'The visibility of the snippet' desc: 'The visibility of the snippet'
use :create_file_params
end end
post ":id/snippets" do post ":id/snippets" do
authorize! :create_snippet, user_project 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 service_response = ::Snippets::CreateService.new(user_project, current_user, snippet_params).execute
snippet = service_response.payload[:snippet] snippet = service_response.payload[:snippet]
......
...@@ -123,16 +123,19 @@ RSpec.describe API::ProjectSnippets do ...@@ -123,16 +123,19 @@ RSpec.describe API::ProjectSnippets do
end end
describe 'POST /projects/:project_id/snippets/' do describe 'POST /projects/:project_id/snippets/' do
let(:params) do let(:base_params) do
{ {
title: 'Test Title', title: 'Test Title',
file_name: 'test.rb',
description: 'test description', description: 'test description',
content: 'puts "hello world"',
visibility: 'public' visibility: 'public'
} }
end 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 shared_examples 'project snippet repository actions' do
let(:snippet) { ProjectSnippet.find(json_response['id']) } let(:snippet) { ProjectSnippet.find(json_response['id']) }
...@@ -145,9 +148,9 @@ RSpec.describe API::ProjectSnippets do ...@@ -145,9 +148,9 @@ RSpec.describe API::ProjectSnippets do
it 'commit the files to the repository' do it 'commit the files to the repository' do
subject 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
end end
...@@ -184,63 +187,60 @@ RSpec.describe API::ProjectSnippets do ...@@ -184,63 +187,60 @@ RSpec.describe API::ProjectSnippets do
params['visibility'] = 'internal' params['visibility'] = 'internal'
end end
subject { post api("/projects/#{project.id}/snippets/", user), params: params }
it 'creates a new snippet' do it 'creates a new snippet' do
post api("/projects/#{project.id}/snippets/", user), params: params subject
expect(response).to have_gitlab_http_status(:created) expect(response).to have_gitlab_http_status(:created)
snippet = ProjectSnippet.find(json_response['id']) 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.description).to eq(params[:description])
expect(snippet.title).to eq(params[:title]) 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) expect(snippet.visibility_level).to eq(Snippet::INTERNAL)
end end
it_behaves_like 'project snippet repository actions' do it_behaves_like 'project snippet repository actions'
subject { post api("/projects/#{project.id}/snippets/", user), params: params }
end
end end
it 'creates a new snippet' do context 'with an admin' do
post api("/projects/#{project.id}/snippets/", admin), params: params subject { post api("/projects/#{project.id}/snippets/", admin), params: params }
expect(response).to have_gitlab_http_status(:created) it 'creates a new snippet' do
snippet = ProjectSnippet.find(json_response['id']) subject
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_behaves_like 'project snippet repository actions' do expect(response).to have_gitlab_http_status(:created)
subject { post api("/projects/#{project.id}/snippets/", admin), params: params } snippet = ProjectSnippet.find(json_response['id'])
end 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 it_behaves_like 'project snippet repository actions'
params.delete(:title)
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) subject
end
it 'returns 400 if content is blank' do expect(response).to have_gitlab_http_status(:bad_request)
params[:content] = '' 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) it_behaves_like 'snippet creation without files parameter'
expect(json_response['error']).to eq 'content is empty'
end
it 'returns 400 if title is blank' do it 'returns 400 if title is blank' do
params[:title] = '' params[:title] = ''
post api("/projects/#{project.id}/snippets/", admin), params: params subject
expect(response).to have_gitlab_http_status(:bad_request) expect(response).to have_gitlab_http_status(:bad_request)
expect(json_response['error']).to eq 'title is empty' expect(json_response['error']).to eq 'title is empty'
end
end end
context 'when save fails because the repository could not be created' do context 'when save fails because the repository could not be created' do
......
...@@ -274,52 +274,7 @@ RSpec.describe API::Snippets do ...@@ -274,52 +274,7 @@ RSpec.describe API::Snippets do
end end
context 'with files parameter' do context 'with files parameter' do
using RSpec::Parameterized::TableSyntax it_behaves_like 'snippet creation with files parameter'
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
context 'with multiple files' do context 'with multiple files' do
let(:file_params) do let(:file_params) do
...@@ -335,24 +290,7 @@ RSpec.describe API::Snippets do ...@@ -335,24 +290,7 @@ RSpec.describe API::Snippets do
end end
end end
context 'without files parameter' do it_behaves_like 'snippet creation without files parameter'
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
context 'with restricted visibility settings' do context 'with restricted visibility settings' do
before do before do
......
...@@ -106,3 +106,80 @@ RSpec.shared_examples 'snippet_multiple_files feature disabled' do ...@@ -106,3 +106,80 @@ RSpec.shared_examples 'snippet_multiple_files feature disabled' do
expect(json_response).not_to have_key('files') expect(json_response).not_to have_key('files')
end end
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