API: Endpoint to expose personal snippets as /snippets
Adding the necessary API for the new /snippets Restful resource added with this commit. Added a new Grape class `Snippets`, as well as a `PersonalSnippet` entity. Issue: #20042 Merge-Request: !6373 Signed-off-by: Guyzmo <guyzmo+gitlab+pub@m0g.net>
This commit is contained in:
parent
cf1a31a345
commit
fde754e267
|
|
@ -1,12 +1,15 @@
|
|||
class SnippetsFinder
|
||||
def execute(current_user, params = {})
|
||||
filter = params[:filter]
|
||||
user = params.fetch(:user, current_user)
|
||||
|
||||
case filter
|
||||
when :all then
|
||||
snippets(current_user).fresh
|
||||
when :public then
|
||||
Snippet.are_public.fresh
|
||||
when :by_user then
|
||||
by_user(current_user, params[:user], params[:scope])
|
||||
by_user(current_user, user, params[:scope])
|
||||
when :by_project
|
||||
by_project(current_user, params[:project])
|
||||
end
|
||||
|
|
|
|||
|
|
@ -159,6 +159,11 @@ module GitlabRoutingHelper
|
|||
resend_invite_namespace_project_project_member_path(project_member.source.namespace, project_member.source, project_member)
|
||||
end
|
||||
|
||||
# Snippets
|
||||
def personal_snippet_url(snippet, *args)
|
||||
snippet_url(snippet)
|
||||
end
|
||||
|
||||
# Groups
|
||||
|
||||
## Members
|
||||
|
|
|
|||
|
|
@ -6,9 +6,14 @@ class PersonalSnippetPolicy < BasePolicy
|
|||
if @subject.author == @user
|
||||
can! :read_personal_snippet
|
||||
can! :update_personal_snippet
|
||||
can! :destroy_personal_snippet
|
||||
can! :admin_personal_snippet
|
||||
end
|
||||
|
||||
unless @user.external?
|
||||
can! :create_personal_snippet
|
||||
end
|
||||
|
||||
if @subject.internal? && !@user.external?
|
||||
can! :read_personal_snippet
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
title: 'API: Endpoint to expose personal snippets as /snippets'
|
||||
merge_request: 6373
|
||||
author: Bernard Guyzmo Pratz
|
||||
|
|
@ -0,0 +1,232 @@
|
|||
# Snippets
|
||||
|
||||
> [Introduced][ce-6373] in GitLab 8.15.
|
||||
|
||||
### Snippet visibility level
|
||||
|
||||
Snippets in GitLab can be either private, internal, or public.
|
||||
You can set it with the `visibility_level` field in the snippet.
|
||||
|
||||
Constants for snippet visibility levels are:
|
||||
|
||||
| Visibility | Visibility level | Description |
|
||||
| ---------- | ---------------- | ----------- |
|
||||
| Private | `0` | The snippet is visible only to the snippet creator |
|
||||
| Internal | `10` | The snippet is visible for any logged in user |
|
||||
| Public | `20` | The snippet can be accessed without any authentication |
|
||||
|
||||
## List snippets
|
||||
|
||||
Get a list of current user's snippets.
|
||||
|
||||
```
|
||||
GET /snippets
|
||||
```
|
||||
|
||||
## Single snippet
|
||||
|
||||
Get a single snippet.
|
||||
|
||||
```
|
||||
GET /snippets/:id
|
||||
```
|
||||
|
||||
Parameters:
|
||||
|
||||
| Attribute | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `id` | Integer | yes | The ID of a snippet |
|
||||
|
||||
``` bash
|
||||
curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/snippets/1
|
||||
```
|
||||
|
||||
Example response:
|
||||
|
||||
``` json
|
||||
{
|
||||
"id": 1,
|
||||
"title": "test",
|
||||
"file_name": "add.rb",
|
||||
"author": {
|
||||
"id": 1,
|
||||
"username": "john_smith",
|
||||
"email": "john@example.com",
|
||||
"name": "John Smith",
|
||||
"state": "active",
|
||||
"created_at": "2012-05-23T08:00:58Z"
|
||||
},
|
||||
"expires_at": null,
|
||||
"updated_at": "2012-06-28T10:52:04Z",
|
||||
"created_at": "2012-06-28T10:52:04Z",
|
||||
"web_url": "http://example.com/snippets/1",
|
||||
}
|
||||
```
|
||||
|
||||
## Create new snippet
|
||||
|
||||
Creates a new snippet. The user must have permission to create new snippets.
|
||||
|
||||
```
|
||||
POST /snippets
|
||||
```
|
||||
|
||||
Parameters:
|
||||
|
||||
| Attribute | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `title` | String | yes | The title of a snippet |
|
||||
| `file_name` | String | yes | The name of a snippet file |
|
||||
| `content` | String | yes | The content of a snippet |
|
||||
| `visibility_level` | Integer | yes | The snippet's visibility |
|
||||
|
||||
|
||||
``` bash
|
||||
curl --request POST --data '{"title": "This is a snippet", "content": "Hello world", "file_name": "test.txt", "visibility_level": 10 }' --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/snippets
|
||||
```
|
||||
|
||||
Example response:
|
||||
|
||||
``` json
|
||||
{
|
||||
"id": 1,
|
||||
"title": "This is a snippet",
|
||||
"file_name": "test.txt",
|
||||
"author": {
|
||||
"id": 1,
|
||||
"username": "john_smith",
|
||||
"email": "john@example.com",
|
||||
"name": "John Smith",
|
||||
"state": "active",
|
||||
"created_at": "2012-05-23T08:00:58Z"
|
||||
},
|
||||
"expires_at": null,
|
||||
"updated_at": "2012-06-28T10:52:04Z",
|
||||
"created_at": "2012-06-28T10:52:04Z",
|
||||
"web_url": "http://example.com/snippets/1",
|
||||
}
|
||||
```
|
||||
|
||||
## Update snippet
|
||||
|
||||
Updates an existing snippet. The user must have permission to change an existing snippet.
|
||||
|
||||
```
|
||||
PUT /snippets/:id
|
||||
```
|
||||
|
||||
Parameters:
|
||||
|
||||
| Attribute | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `id` | Integer | yes | The ID of a snippet |
|
||||
| `title` | String | no | The title of a snippet |
|
||||
| `file_name` | String | no | The name of a snippet file |
|
||||
| `content` | String | no | The content of a snippet |
|
||||
| `visibility_level` | Integer | no | The snippet's visibility |
|
||||
|
||||
|
||||
``` bash
|
||||
curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --data '{"title": "foo", "content": "bar"}' https://gitlab.example.com/api/v3/snippets/1
|
||||
```
|
||||
|
||||
Example response:
|
||||
|
||||
``` json
|
||||
{
|
||||
"id": 1,
|
||||
"title": "test",
|
||||
"file_name": "add.rb",
|
||||
"author": {
|
||||
"id": 1,
|
||||
"username": "john_smith",
|
||||
"email": "john@example.com",
|
||||
"name": "John Smith",
|
||||
"state": "active",
|
||||
"created_at": "2012-05-23T08:00:58Z"
|
||||
},
|
||||
"expires_at": null,
|
||||
"updated_at": "2012-06-28T10:52:04Z",
|
||||
"created_at": "2012-06-28T10:52:04Z",
|
||||
"web_url": "http://example.com/snippets/1",
|
||||
}
|
||||
```
|
||||
|
||||
## Delete snippet
|
||||
|
||||
Deletes an existing snippet.
|
||||
|
||||
```
|
||||
DELETE /snippets/:id
|
||||
```
|
||||
|
||||
Parameters:
|
||||
|
||||
| Attribute | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `id` | Integer | yes | The ID of a snippet |
|
||||
|
||||
|
||||
```
|
||||
curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/snippets/1"
|
||||
```
|
||||
|
||||
upon successful delete a `204 No content` HTTP code shall be expected, with no data,
|
||||
but if the snippet is non-existent, a `404 Not Found` will be returned.
|
||||
|
||||
## Explore all public snippets
|
||||
|
||||
```
|
||||
GET /snippets/public
|
||||
```
|
||||
|
||||
| Attribute | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `per_page` | Integer | no | number of snippets to return per page |
|
||||
| `page` | Integer | no | the page to retrieve |
|
||||
|
||||
``` bash
|
||||
curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/snippets/public?per_page=2&page=1
|
||||
```
|
||||
|
||||
Example response:
|
||||
|
||||
``` json
|
||||
[
|
||||
{
|
||||
"author": {
|
||||
"avatar_url": "http://www.gravatar.com/avatar/edaf55a9e363ea263e3b981d09e0f7f7?s=80&d=identicon",
|
||||
"id": 12,
|
||||
"name": "Libby Rolfson",
|
||||
"state": "active",
|
||||
"username": "elton_wehner",
|
||||
"web_url": "http://localhost:3000/elton_wehner"
|
||||
},
|
||||
"created_at": "2016-11-25T16:53:34.504Z",
|
||||
"file_name": "oconnerrice.rb",
|
||||
"id": 49,
|
||||
"raw_url": "http://localhost:3000/snippets/49/raw",
|
||||
"title": "Ratione cupiditate et laborum temporibus.",
|
||||
"updated_at": "2016-11-25T16:53:34.504Z",
|
||||
"web_url": "http://localhost:3000/snippets/49"
|
||||
},
|
||||
{
|
||||
"author": {
|
||||
"avatar_url": "http://www.gravatar.com/avatar/36583b28626de71061e6e5a77972c3bd?s=80&d=identicon",
|
||||
"id": 16,
|
||||
"name": "Llewellyn Flatley",
|
||||
"state": "active",
|
||||
"username": "adaline",
|
||||
"web_url": "http://localhost:3000/adaline"
|
||||
},
|
||||
"created_at": "2016-11-25T16:53:34.479Z",
|
||||
"file_name": "muellershields.rb",
|
||||
"id": 48,
|
||||
"raw_url": "http://localhost:3000/snippets/48/raw",
|
||||
"title": "Minus similique nesciunt vel fugiat qui ullam sunt.",
|
||||
"updated_at": "2016-11-25T16:53:34.479Z",
|
||||
"web_url": "http://localhost:3000/snippets/48"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
|
|
@ -64,6 +64,7 @@ module API
|
|||
mount ::API::Session
|
||||
mount ::API::Settings
|
||||
mount ::API::SidekiqMetrics
|
||||
mount ::API::Snippets
|
||||
mount ::API::Subscriptions
|
||||
mount ::API::SystemHooks
|
||||
mount ::API::Tags
|
||||
|
|
|
|||
|
|
@ -200,6 +200,19 @@ module API
|
|||
end
|
||||
end
|
||||
|
||||
class PersonalSnippet < Grape::Entity
|
||||
expose :id, :title, :file_name
|
||||
expose :author, using: Entities::UserBasic
|
||||
expose :updated_at, :created_at
|
||||
|
||||
expose :web_url do |snippet|
|
||||
Gitlab::UrlBuilder.build(snippet)
|
||||
end
|
||||
expose :raw_url do |snippet|
|
||||
Gitlab::UrlBuilder.build(snippet) + "/raw"
|
||||
end
|
||||
end
|
||||
|
||||
class ProjectEntity < Grape::Entity
|
||||
expose :id, :iid
|
||||
expose(:project_id) { |entity| entity.project.id }
|
||||
|
|
|
|||
|
|
@ -0,0 +1,137 @@
|
|||
module API
|
||||
# Snippets API
|
||||
class Snippets < Grape::API
|
||||
include PaginationParams
|
||||
|
||||
before { authenticate! }
|
||||
|
||||
resource :snippets do
|
||||
helpers do
|
||||
def snippets_for_current_user
|
||||
SnippetsFinder.new.execute(current_user, filter: :by_user, user: current_user)
|
||||
end
|
||||
|
||||
def public_snippets
|
||||
SnippetsFinder.new.execute(current_user, filter: :public)
|
||||
end
|
||||
end
|
||||
|
||||
desc 'Get a snippets list for authenticated user' do
|
||||
detail 'This feature was introduced in GitLab 8.15.'
|
||||
success Entities::PersonalSnippet
|
||||
end
|
||||
params do
|
||||
use :pagination
|
||||
end
|
||||
get do
|
||||
present paginate(snippets_for_current_user), with: Entities::PersonalSnippet
|
||||
end
|
||||
|
||||
desc 'List all public snippets current_user has access to' do
|
||||
detail 'This feature was introduced in GitLab 8.15.'
|
||||
success Entities::PersonalSnippet
|
||||
end
|
||||
params do
|
||||
use :pagination
|
||||
end
|
||||
get 'public' do
|
||||
present paginate(public_snippets), with: Entities::PersonalSnippet
|
||||
end
|
||||
|
||||
desc 'Get a single snippet' do
|
||||
detail 'This feature was introduced in GitLab 8.15.'
|
||||
success Entities::PersonalSnippet
|
||||
end
|
||||
params do
|
||||
requires :id, type: Integer, desc: 'The ID of a snippet'
|
||||
end
|
||||
get ':id' do
|
||||
snippet = snippets_for_current_user.find(params[:id])
|
||||
present snippet, with: Entities::PersonalSnippet
|
||||
end
|
||||
|
||||
desc 'Create new snippet' do
|
||||
detail 'This feature was introduced in GitLab 8.15.'
|
||||
success Entities::PersonalSnippet
|
||||
end
|
||||
params do
|
||||
requires :title, type: String, desc: 'The title of a snippet'
|
||||
requires :file_name, type: String, desc: 'The name of a snippet file'
|
||||
requires :content, type: String, desc: 'The content of a snippet'
|
||||
optional :visibility_level, type: Integer,
|
||||
values: Gitlab::VisibilityLevel.values,
|
||||
default: Gitlab::VisibilityLevel::INTERNAL,
|
||||
desc: 'The visibility level of the snippet'
|
||||
end
|
||||
post do
|
||||
attrs = declared_params(include_missing: false)
|
||||
snippet = CreateSnippetService.new(nil, current_user, attrs).execute
|
||||
|
||||
if snippet.persisted?
|
||||
present snippet, with: Entities::PersonalSnippet
|
||||
else
|
||||
render_validation_error!(snippet)
|
||||
end
|
||||
end
|
||||
|
||||
desc 'Update an existing snippet' do
|
||||
detail 'This feature was introduced in GitLab 8.15.'
|
||||
success Entities::PersonalSnippet
|
||||
end
|
||||
params do
|
||||
requires :id, type: Integer, desc: 'The ID of a snippet'
|
||||
optional :title, type: String, desc: 'The title of a snippet'
|
||||
optional :file_name, type: String, desc: 'The name of a snippet file'
|
||||
optional :content, type: String, desc: 'The content of a snippet'
|
||||
optional :visibility_level, type: Integer,
|
||||
values: Gitlab::VisibilityLevel.values,
|
||||
desc: 'The visibility level of the snippet'
|
||||
at_least_one_of :title, :file_name, :content, :visibility_level
|
||||
end
|
||||
put ':id' do
|
||||
snippet = snippets_for_current_user.find_by(id: params.delete(:id))
|
||||
return not_found!('Snippet') unless snippet
|
||||
authorize! :update_personal_snippet, snippet
|
||||
|
||||
attrs = declared_params(include_missing: false)
|
||||
|
||||
UpdateSnippetService.new(nil, current_user, snippet, attrs).execute
|
||||
if snippet.persisted?
|
||||
present snippet, with: Entities::PersonalSnippet
|
||||
else
|
||||
render_validation_error!(snippet)
|
||||
end
|
||||
end
|
||||
|
||||
desc 'Remove snippet' do
|
||||
detail 'This feature was introduced in GitLab 8.15.'
|
||||
success Entities::PersonalSnippet
|
||||
end
|
||||
params do
|
||||
requires :id, type: Integer, desc: 'The ID of a snippet'
|
||||
end
|
||||
delete ':id' do
|
||||
snippet = snippets_for_current_user.find_by(id: params.delete(:id))
|
||||
return not_found!('Snippet') unless snippet
|
||||
authorize! :destroy_personal_snippet, snippet
|
||||
snippet.destroy
|
||||
no_content!
|
||||
end
|
||||
|
||||
desc 'Get a raw snippet' do
|
||||
detail 'This feature was introduced in GitLab 8.15.'
|
||||
end
|
||||
params do
|
||||
requires :id, type: Integer, desc: 'The ID of a snippet'
|
||||
end
|
||||
get ":id/raw" do
|
||||
snippet = snippets_for_current_user.find_by(id: params.delete(:id))
|
||||
return not_found!('Snippet') unless snippet
|
||||
|
||||
env['api.format'] = :txt
|
||||
content_type 'text/plain'
|
||||
present snippet.content
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -24,6 +24,8 @@ module Gitlab
|
|||
wiki_page_url
|
||||
when ProjectSnippet
|
||||
project_snippet_url(object)
|
||||
when Snippet
|
||||
personal_snippet_url(object)
|
||||
else
|
||||
raise NotImplementedError.new("No URL builder defined for #{object.class}")
|
||||
end
|
||||
|
|
|
|||
|
|
@ -9,65 +9,74 @@ describe SnippetsFinder do
|
|||
let(:project2) { create(:empty_project, :private, group: group) }
|
||||
|
||||
context ':all filter' do
|
||||
before do
|
||||
@snippet1 = create(:personal_snippet, :private)
|
||||
@snippet2 = create(:personal_snippet, :internal)
|
||||
@snippet3 = create(:personal_snippet, :public)
|
||||
end
|
||||
let!(:snippet1) { create(:personal_snippet, :private) }
|
||||
let!(:snippet2) { create(:personal_snippet, :internal) }
|
||||
let!(:snippet3) { create(:personal_snippet, :public) }
|
||||
|
||||
it "returns all private and internal snippets" do
|
||||
snippets = SnippetsFinder.new.execute(user, filter: :all)
|
||||
expect(snippets).to include(@snippet2, @snippet3)
|
||||
expect(snippets).not_to include(@snippet1)
|
||||
expect(snippets).to include(snippet2, snippet3)
|
||||
expect(snippets).not_to include(snippet1)
|
||||
end
|
||||
|
||||
it "returns all public snippets" do
|
||||
snippets = SnippetsFinder.new.execute(nil, filter: :all)
|
||||
expect(snippets).to include(@snippet3)
|
||||
expect(snippets).not_to include(@snippet1, @snippet2)
|
||||
expect(snippets).to include(snippet3)
|
||||
expect(snippets).not_to include(snippet1, snippet2)
|
||||
end
|
||||
end
|
||||
|
||||
context ':public filter' do
|
||||
let!(:snippet1) { create(:personal_snippet, :private) }
|
||||
let!(:snippet2) { create(:personal_snippet, :internal) }
|
||||
let!(:snippet3) { create(:personal_snippet, :public) }
|
||||
|
||||
it "returns public public snippets" do
|
||||
snippets = SnippetsFinder.new.execute(nil, filter: :public)
|
||||
|
||||
expect(snippets).to include(snippet3)
|
||||
expect(snippets).not_to include(snippet1, snippet2)
|
||||
end
|
||||
end
|
||||
|
||||
context ':by_user filter' do
|
||||
before do
|
||||
@snippet1 = create(:personal_snippet, :private, author: user)
|
||||
@snippet2 = create(:personal_snippet, :internal, author: user)
|
||||
@snippet3 = create(:personal_snippet, :public, author: user)
|
||||
end
|
||||
let!(:snippet1) { create(:personal_snippet, :private, author: user) }
|
||||
let!(:snippet2) { create(:personal_snippet, :internal, author: user) }
|
||||
let!(:snippet3) { create(:personal_snippet, :public, author: user) }
|
||||
|
||||
it "returns all public and internal snippets" do
|
||||
snippets = SnippetsFinder.new.execute(user1, filter: :by_user, user: user)
|
||||
expect(snippets).to include(@snippet2, @snippet3)
|
||||
expect(snippets).not_to include(@snippet1)
|
||||
expect(snippets).to include(snippet2, snippet3)
|
||||
expect(snippets).not_to include(snippet1)
|
||||
end
|
||||
|
||||
it "returns internal snippets" do
|
||||
snippets = SnippetsFinder.new.execute(user, filter: :by_user, user: user, scope: "are_internal")
|
||||
expect(snippets).to include(@snippet2)
|
||||
expect(snippets).not_to include(@snippet1, @snippet3)
|
||||
expect(snippets).to include(snippet2)
|
||||
expect(snippets).not_to include(snippet1, snippet3)
|
||||
end
|
||||
|
||||
it "returns private snippets" do
|
||||
snippets = SnippetsFinder.new.execute(user, filter: :by_user, user: user, scope: "are_private")
|
||||
expect(snippets).to include(@snippet1)
|
||||
expect(snippets).not_to include(@snippet2, @snippet3)
|
||||
expect(snippets).to include(snippet1)
|
||||
expect(snippets).not_to include(snippet2, snippet3)
|
||||
end
|
||||
|
||||
it "returns public snippets" do
|
||||
snippets = SnippetsFinder.new.execute(user, filter: :by_user, user: user, scope: "are_public")
|
||||
expect(snippets).to include(@snippet3)
|
||||
expect(snippets).not_to include(@snippet1, @snippet2)
|
||||
expect(snippets).to include(snippet3)
|
||||
expect(snippets).not_to include(snippet1, snippet2)
|
||||
end
|
||||
|
||||
it "returns all snippets" do
|
||||
snippets = SnippetsFinder.new.execute(user, filter: :by_user, user: user)
|
||||
expect(snippets).to include(@snippet1, @snippet2, @snippet3)
|
||||
expect(snippets).to include(snippet1, snippet2, snippet3)
|
||||
end
|
||||
|
||||
it "returns only public snippets if unauthenticated user" do
|
||||
snippets = SnippetsFinder.new.execute(nil, filter: :by_user, user: user)
|
||||
expect(snippets).to include(@snippet3)
|
||||
expect(snippets).not_to include(@snippet2, @snippet1)
|
||||
expect(snippets).to include(snippet3)
|
||||
expect(snippets).not_to include(snippet2, snippet1)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,157 @@
|
|||
require 'rails_helper'
|
||||
|
||||
describe API::Snippets, api: true do
|
||||
include ApiHelpers
|
||||
let!(:user) { create(:user) }
|
||||
|
||||
describe 'GET /snippets/' do
|
||||
it 'returns snippets available' do
|
||||
public_snippet = create(:personal_snippet, :public, author: user)
|
||||
private_snippet = create(:personal_snippet, :private, author: user)
|
||||
internal_snippet = create(:personal_snippet, :internal, author: user)
|
||||
|
||||
get api("/snippets/", user)
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
expect(json_response.map { |snippet| snippet['id']} ).to contain_exactly(
|
||||
public_snippet.id,
|
||||
internal_snippet.id,
|
||||
private_snippet.id)
|
||||
expect(json_response.last).to have_key('web_url')
|
||||
expect(json_response.last).to have_key('raw_url')
|
||||
end
|
||||
|
||||
it 'hides private snippets from regular user' do
|
||||
create(:personal_snippet, :private)
|
||||
|
||||
get api("/snippets/", user)
|
||||
expect(response).to have_http_status(200)
|
||||
expect(json_response.size).to eq(0)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET /snippets/public' do
|
||||
let!(:other_user) { create(:user) }
|
||||
let!(:public_snippet) { create(:personal_snippet, :public, author: user) }
|
||||
let!(:private_snippet) { create(:personal_snippet, :private, author: user) }
|
||||
let!(:internal_snippet) { create(:personal_snippet, :internal, author: user) }
|
||||
let!(:public_snippet_other) { create(:personal_snippet, :public, author: other_user) }
|
||||
let!(:private_snippet_other) { create(:personal_snippet, :private, author: other_user) }
|
||||
let!(:internal_snippet_other) { create(:personal_snippet, :internal, author: other_user) }
|
||||
|
||||
it 'returns all snippets with public visibility from all users' do
|
||||
get api("/snippets/public", user)
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
expect(json_response.map { |snippet| snippet['id']} ).to contain_exactly(
|
||||
public_snippet.id,
|
||||
public_snippet_other.id)
|
||||
expect(json_response.map{ |snippet| snippet['web_url']} ).to include(
|
||||
"http://localhost/snippets/#{public_snippet.id}",
|
||||
"http://localhost/snippets/#{public_snippet_other.id}")
|
||||
expect(json_response.map{ |snippet| snippet['raw_url']} ).to include(
|
||||
"http://localhost/snippets/#{public_snippet.id}/raw",
|
||||
"http://localhost/snippets/#{public_snippet_other.id}/raw")
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET /snippets/:id/raw' do
|
||||
let(:snippet) { create(:personal_snippet, author: user) }
|
||||
|
||||
it 'returns raw text' do
|
||||
get api("/snippets/#{snippet.id}/raw", user)
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
expect(response.content_type).to eq 'text/plain'
|
||||
expect(response.body).to eq(snippet.content)
|
||||
end
|
||||
|
||||
it 'returns 404 for invalid snippet id' do
|
||||
delete api("/snippets/1234", user)
|
||||
|
||||
expect(response).to have_http_status(404)
|
||||
expect(json_response['message']).to eq('404 Snippet Not Found')
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST /snippets/' do
|
||||
let(:params) do
|
||||
{
|
||||
title: 'Test Title',
|
||||
file_name: 'test.rb',
|
||||
content: 'puts "hello world"',
|
||||
visibility_level: Gitlab::VisibilityLevel::PUBLIC
|
||||
}
|
||||
end
|
||||
|
||||
it 'creates a new snippet' do
|
||||
expect do
|
||||
post api("/snippets/", user), params
|
||||
end.to change { PersonalSnippet.count }.by(1)
|
||||
|
||||
expect(response).to have_http_status(201)
|
||||
expect(json_response['title']).to eq(params[:title])
|
||||
expect(json_response['file_name']).to eq(params[:file_name])
|
||||
end
|
||||
|
||||
it 'returns 400 for missing parameters' do
|
||||
params.delete(:title)
|
||||
|
||||
post api("/snippets/", user), params
|
||||
|
||||
expect(response).to have_http_status(400)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'PUT /snippets/:id' do
|
||||
let(:other_user) { create(:user) }
|
||||
let(:public_snippet) { create(:personal_snippet, :public, author: user) }
|
||||
it 'updates snippet' do
|
||||
new_content = 'New content'
|
||||
|
||||
put api("/snippets/#{public_snippet.id}", user), content: new_content
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
public_snippet.reload
|
||||
expect(public_snippet.content).to eq(new_content)
|
||||
end
|
||||
|
||||
it 'returns 404 for invalid snippet id' do
|
||||
put api("/snippets/1234", user), title: 'foo'
|
||||
|
||||
expect(response).to have_http_status(404)
|
||||
expect(json_response['message']).to eq('404 Snippet Not Found')
|
||||
end
|
||||
|
||||
it "returns 404 for another user's snippet" do
|
||||
put api("/snippets/#{public_snippet.id}", other_user), title: 'fubar'
|
||||
|
||||
expect(response).to have_http_status(404)
|
||||
expect(json_response['message']).to eq('404 Snippet Not Found')
|
||||
end
|
||||
|
||||
it 'returns 400 for missing parameters' do
|
||||
put api("/snippets/1234", user)
|
||||
|
||||
expect(response).to have_http_status(400)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'DELETE /snippets/:id' do
|
||||
let!(:public_snippet) { create(:personal_snippet, :public, author: user) }
|
||||
it 'deletes snippet' do
|
||||
expect do
|
||||
delete api("/snippets/#{public_snippet.id}", user)
|
||||
|
||||
expect(response).to have_http_status(204)
|
||||
end.to change { PersonalSnippet.count }.by(-1)
|
||||
end
|
||||
|
||||
it 'returns 404 for invalid snippet id' do
|
||||
delete api("/snippets/1234", user)
|
||||
|
||||
expect(response).to have_http_status(404)
|
||||
expect(json_response['message']).to eq('404 Snippet Not Found')
|
||||
end
|
||||
end
|
||||
end
|
||||
Loading…
Reference in New Issue