summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
authorDouwe Maan <douwe@gitlab.com>2017-03-02 17:10:25 +0000
committerDouwe Maan <douwe@gitlab.com>2017-03-02 17:10:25 +0000
commit8ec8b2da66c27124cf049ca77472f5aabc77b759 (patch)
tree6529f21c11fc7d3d98c906a00a699d86efe60e01 /spec
parentb8ca9bc43a9504dad94a66630170ab6311eb5c09 (diff)
parentc3b1cb71f0726bd9cd3916507337650e6546141f (diff)
downloadgitlab-ce-8ec8b2da66c27124cf049ca77472f5aabc77b759.tar.gz
Merge branch '27501-api-use-visibility-everywhere' into 'master'
API: Use `visibility` as string parameter everywhere Closes #27501 See merge request !9337
Diffstat (limited to 'spec')
-rw-r--r--spec/requests/api/environments_spec.rb1
-rw-r--r--spec/requests/api/groups_spec.rb6
-rw-r--r--spec/requests/api/project_snippets_spec.rb16
-rw-r--r--spec/requests/api/projects_spec.rb61
-rw-r--r--spec/requests/api/settings_spec.rb7
-rw-r--r--spec/requests/api/snippets_spec.rb12
-rw-r--r--spec/requests/api/v3/environments_spec.rb126
-rw-r--r--spec/requests/api/v3/groups_spec.rb530
-rw-r--r--spec/requests/api/v3/settings_spec.rb65
-rw-r--r--spec/requests/api/v3/snippets_spec.rb187
10 files changed, 963 insertions, 48 deletions
diff --git a/spec/requests/api/environments_spec.rb b/spec/requests/api/environments_spec.rb
index 8aac0546513..f2fd1dfc8db 100644
--- a/spec/requests/api/environments_spec.rb
+++ b/spec/requests/api/environments_spec.rb
@@ -24,6 +24,7 @@ describe API::Environments, api: true do
expect(json_response.first['name']).to eq(environment.name)
expect(json_response.first['external_url']).to eq(environment.external_url)
expect(json_response.first['project']['id']).to eq(project.id)
+ expect(json_response.first['project']['visibility']).to be_present
end
end
diff --git a/spec/requests/api/groups_spec.rb b/spec/requests/api/groups_spec.rb
index b0ba3ea912d..2b8fd7e31a1 100644
--- a/spec/requests/api/groups_spec.rb
+++ b/spec/requests/api/groups_spec.rb
@@ -176,7 +176,7 @@ describe API::Groups, api: true do
expect(json_response['name']).to eq(group1.name)
expect(json_response['path']).to eq(group1.path)
expect(json_response['description']).to eq(group1.description)
- expect(json_response['visibility_level']).to eq(group1.visibility_level)
+ expect(json_response['visibility']).to eq(Gitlab::VisibilityLevel.string_level(group1.visibility_level))
expect(json_response['avatar_url']).to eq(group1.avatar_url)
expect(json_response['web_url']).to eq(group1.web_url)
expect(json_response['request_access_enabled']).to eq(group1.request_access_enabled)
@@ -295,7 +295,7 @@ describe API::Groups, api: true do
expect(json_response.length).to eq(2)
project_names = json_response.map { |proj| proj['name'] }
expect(project_names).to match_array([project1.name, project3.name])
- expect(json_response.first['visibility_level']).to be_present
+ expect(json_response.first['visibility']).to be_present
end
it "returns the group's projects with simple representation" do
@@ -306,7 +306,7 @@ describe API::Groups, api: true do
expect(json_response.length).to eq(2)
project_names = json_response.map { |proj| proj['name'] }
expect(project_names).to match_array([project1.name, project3.name])
- expect(json_response.first['visibility_level']).not_to be_present
+ expect(json_response.first['visibility']).not_to be_present
end
it 'filters the groups projects' do
diff --git a/spec/requests/api/project_snippets_spec.rb b/spec/requests/api/project_snippets_spec.rb
index 2c4602faf2c..9e88c19b0bc 100644
--- a/spec/requests/api/project_snippets_spec.rb
+++ b/spec/requests/api/project_snippets_spec.rb
@@ -44,7 +44,7 @@ describe API::ProjectSnippets, api: true do
title: 'Test Title',
file_name: 'test.rb',
code: 'puts "hello world"',
- visibility_level: Snippet::PUBLIC
+ visibility: 'public'
}
end
@@ -56,7 +56,7 @@ describe API::ProjectSnippets, api: true do
expect(snippet.content).to eq(params[:code])
expect(snippet.title).to eq(params[:title])
expect(snippet.file_name).to eq(params[:file_name])
- expect(snippet.visibility_level).to eq(params[:visibility_level])
+ expect(snippet.visibility_level).to eq(Snippet::PUBLIC)
end
it 'returns 400 for missing parameters' do
@@ -80,14 +80,14 @@ describe API::ProjectSnippets, api: true do
context 'when the snippet is private' do
it 'creates the snippet' do
- expect { create_snippet(project, visibility_level: Snippet::PRIVATE) }.
+ expect { create_snippet(project, visibility: 'private') }.
to change { Snippet.count }.by(1)
end
end
context 'when the snippet is public' do
- it 'rejects the shippet' do
- expect { create_snippet(project, visibility_level: Snippet::PUBLIC) }.
+ it 'rejects the snippet' do
+ expect { create_snippet(project, visibility: 'public') }.
not_to change { Snippet.count }
expect(response).to have_http_status(400)
@@ -95,7 +95,7 @@ describe API::ProjectSnippets, api: true do
end
it 'creates a spam log' do
- expect { create_snippet(project, visibility_level: Snippet::PUBLIC) }.
+ expect { create_snippet(project, visibility: 'public') }.
to change { SpamLog.count }.by(1)
end
end
@@ -165,7 +165,7 @@ describe API::ProjectSnippets, api: true do
let(:visibility_level) { Snippet::PRIVATE }
it 'rejects the snippet' do
- expect { update_snippet(title: 'Foo', visibility_level: Snippet::PUBLIC) }.
+ expect { update_snippet(title: 'Foo', visibility: 'public') }.
not_to change { snippet.reload.title }
expect(response).to have_http_status(400)
@@ -173,7 +173,7 @@ describe API::ProjectSnippets, api: true do
end
it 'creates a spam log' do
- expect { update_snippet(title: 'Foo', visibility_level: Snippet::PUBLIC) }.
+ expect { update_snippet(title: 'Foo', visibility: 'public') }.
to change { SpamLog.count }.by(1)
end
end
diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb
index 7268016ee81..2e8b557e9e2 100644
--- a/spec/requests/api/projects_spec.rb
+++ b/spec/requests/api/projects_spec.rb
@@ -340,24 +340,27 @@ describe API::Projects, api: true do
end
it 'sets a project as public' do
- project = attributes_for(:project, :public)
+ project = attributes_for(:project, visibility: 'public')
+
post api('/projects', user), project
- expect(json_response['public']).to be_truthy
- expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::PUBLIC)
+
+ expect(json_response['visibility']).to eq('public')
end
it 'sets a project as internal' do
- project = attributes_for(:project, :internal)
+ project = attributes_for(:project, visibility: 'internal')
+
post api('/projects', user), project
- expect(json_response['public']).to be_falsey
- expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::INTERNAL)
+
+ expect(json_response['visibility']).to eq('internal')
end
it 'sets a project as private' do
- project = attributes_for(:project, :private)
+ project = attributes_for(:project, visibility: 'private')
+
post api('/projects', user), project
- expect(json_response['public']).to be_falsey
- expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::PRIVATE)
+
+ expect(json_response['visibility']).to eq('private')
end
it 'sets a project as allowing merge even if build fails' do
@@ -397,7 +400,7 @@ describe API::Projects, api: true do
end
context 'when a visibility level is restricted' do
- let(:project_param) { attributes_for(:project, :public) }
+ let(:project_param) { attributes_for(:project, visibility: 'public') }
before do
stub_application_setting(restricted_visibility_levels: [Gitlab::VisibilityLevel::PUBLIC])
@@ -415,10 +418,7 @@ describe API::Projects, api: true do
it 'allows an admin to override restricted visibility settings' do
post api('/projects', admin), project_param
- expect(json_response['public']).to be_truthy
- expect(json_response['visibility_level']).to(
- eq(Gitlab::VisibilityLevel::PUBLIC)
- )
+ expect(json_response['visibility']).to eq('public')
end
end
end
@@ -459,28 +459,29 @@ describe API::Projects, api: true do
end
it 'sets a project as public' do
- project = attributes_for(:project, :public)
+ project = attributes_for(:project, visibility: 'public')
+
post api("/projects/user/#{user.id}", admin), project
expect(response).to have_http_status(201)
- expect(json_response['public']).to be_truthy
- expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::PUBLIC)
+ expect(json_response['visibility']).to eq('public')
end
it 'sets a project as internal' do
- project = attributes_for(:project, :internal)
+ project = attributes_for(:project, visibility: 'internal')
+
post api("/projects/user/#{user.id}", admin), project
expect(response).to have_http_status(201)
- expect(json_response['public']).to be_falsey
- expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::INTERNAL)
+ expect(json_response['visibility']).to eq('internal')
end
it 'sets a project as private' do
- project = attributes_for(:project, :private)
+ project = attributes_for(:project, visibility: 'private')
+
post api("/projects/user/#{user.id}", admin), project
- expect(json_response['public']).to be_falsey
- expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::PRIVATE)
+
+ expect(json_response['visibility']).to eq('private')
end
it 'sets a project as allowing merge even if build fails' do
@@ -556,9 +557,8 @@ describe API::Projects, api: true do
expect(json_response['description']).to eq(project.description)
expect(json_response['default_branch']).to eq(project.default_branch)
expect(json_response['tag_list']).to be_an Array
- expect(json_response['public']).to be_falsey
expect(json_response['archived']).to be_falsey
- expect(json_response['visibility_level']).to be_present
+ expect(json_response['visibility']).to be_present
expect(json_response['ssh_url_to_repo']).to be_present
expect(json_response['http_url_to_repo']).to be_present
expect(json_response['web_url']).to be_present
@@ -812,8 +812,7 @@ describe API::Projects, api: true do
describe 'POST /projects/:id/snippets' do
it 'creates a new project snippet' do
post api("/projects/#{project.id}/snippets", user),
- title: 'api test', file_name: 'sample.rb', code: 'test',
- visibility_level: Gitlab::VisibilityLevel::PRIVATE
+ title: 'api test', file_name: 'sample.rb', code: 'test', visibility: 'private'
expect(response).to have_http_status(201)
expect(json_response['title']).to eq('api test')
end
@@ -1065,7 +1064,7 @@ describe API::Projects, api: true do
end
it 'updates visibility_level' do
- project_param = { visibility_level: Gitlab::VisibilityLevel::PUBLIC }
+ project_param = { visibility: 'public' }
put api("/projects/#{project3.id}", user), project_param
expect(response).to have_http_status(200)
project_param.each_pair do |k, v|
@@ -1075,13 +1074,13 @@ describe API::Projects, api: true do
it 'updates visibility_level from public to private' do
project3.update_attributes({ visibility_level: Gitlab::VisibilityLevel::PUBLIC })
- project_param = { visibility_level: Gitlab::VisibilityLevel::PRIVATE }
+ project_param = { visibility: 'private' }
put api("/projects/#{project3.id}", user), project_param
expect(response).to have_http_status(200)
project_param.each_pair do |k, v|
expect(json_response[k.to_s]).to eq(v)
end
- expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::PRIVATE)
+ expect(json_response['visibility']).to eq('private')
end
it 'does not update name to existing name' do
@@ -1148,7 +1147,7 @@ describe API::Projects, api: true do
end
it 'does not update visibility_level' do
- project_param = { visibility_level: Gitlab::VisibilityLevel::PUBLIC }
+ project_param = { visibility: 'public' }
put api("/projects/#{project3.id}", user4), project_param
expect(response).to have_http_status(403)
end
diff --git a/spec/requests/api/settings_spec.rb b/spec/requests/api/settings_spec.rb
index 411905edb49..11b4b718e2c 100644
--- a/spec/requests/api/settings_spec.rb
+++ b/spec/requests/api/settings_spec.rb
@@ -18,6 +18,9 @@ describe API::Settings, 'Settings', api: true do
expect(json_response['koding_url']).to be_nil
expect(json_response['plantuml_enabled']).to be_falsey
expect(json_response['plantuml_url']).to be_nil
+ expect(json_response['default_project_visibility']).to be_a String
+ expect(json_response['default_snippet_visibility']).to be_a String
+ expect(json_response['default_group_visibility']).to be_a String
end
end
@@ -37,6 +40,8 @@ describe API::Settings, 'Settings', api: true do
koding_url: 'http://koding.example.com',
plantuml_enabled: true,
plantuml_url: 'http://plantuml.example.com',
+ default_snippet_visibility: 'internal',
+ restricted_visibility_levels: ['public'],
default_artifacts_expire_in: '2 days'
expect(response).to have_http_status(200)
expect(json_response['default_projects_limit']).to eq(3)
@@ -47,6 +52,8 @@ describe API::Settings, 'Settings', api: true do
expect(json_response['koding_url']).to eq('http://koding.example.com')
expect(json_response['plantuml_enabled']).to be_truthy
expect(json_response['plantuml_url']).to eq('http://plantuml.example.com')
+ expect(json_response['default_snippet_visibility']).to eq('internal')
+ expect(json_response['restricted_visibility_levels']).to eq(['public'])
expect(json_response['default_artifacts_expire_in']).to eq('2 days')
end
end
diff --git a/spec/requests/api/snippets_spec.rb b/spec/requests/api/snippets_spec.rb
index 5219f6eed42..5d75b47b3cd 100644
--- a/spec/requests/api/snippets_spec.rb
+++ b/spec/requests/api/snippets_spec.rb
@@ -87,7 +87,7 @@ describe API::Snippets, api: true do
title: 'Test Title',
file_name: 'test.rb',
content: 'puts "hello world"',
- visibility_level: Snippet::PUBLIC
+ visibility: 'public'
}
end
@@ -120,14 +120,14 @@ describe API::Snippets, api: true do
context 'when the snippet is private' do
it 'creates the snippet' do
- expect { create_snippet(visibility_level: Snippet::PRIVATE) }.
+ expect { create_snippet(visibility: 'private') }.
to change { Snippet.count }.by(1)
end
end
context 'when the snippet is public' do
it 'rejects the shippet' do
- expect { create_snippet(visibility_level: Snippet::PUBLIC) }.
+ expect { create_snippet(visibility: 'public') }.
not_to change { Snippet.count }
expect(response).to have_http_status(400)
@@ -135,7 +135,7 @@ describe API::Snippets, api: true do
end
it 'creates a spam log' do
- expect { create_snippet(visibility_level: Snippet::PUBLIC) }.
+ expect { create_snippet(visibility: 'public') }.
to change { SpamLog.count }.by(1)
end
end
@@ -218,12 +218,12 @@ describe API::Snippets, api: true do
let(:visibility_level) { Snippet::PRIVATE }
it 'rejects the snippet' do
- expect { update_snippet(title: 'Foo', visibility_level: Snippet::PUBLIC) }.
+ expect { update_snippet(title: 'Foo', visibility: 'public') }.
not_to change { snippet.reload.title }
end
it 'creates a spam log' do
- expect { update_snippet(title: 'Foo', visibility_level: Snippet::PUBLIC) }.
+ expect { update_snippet(title: 'Foo', visibility: 'public') }.
to change { SpamLog.count }.by(1)
end
end
diff --git a/spec/requests/api/v3/environments_spec.rb b/spec/requests/api/v3/environments_spec.rb
index 1ac666ab240..216192c9d34 100644
--- a/spec/requests/api/v3/environments_spec.rb
+++ b/spec/requests/api/v3/environments_spec.rb
@@ -12,6 +12,132 @@ describe API::V3::Environments, api: true do
project.team << [user, :master]
end
+ shared_examples 'a paginated resources' do
+ before do
+ # Fires the request
+ request
+ end
+
+ it 'has pagination headers' do
+ expect(response.headers).to include('X-Total')
+ expect(response.headers).to include('X-Total-Pages')
+ expect(response.headers).to include('X-Per-Page')
+ expect(response.headers).to include('X-Page')
+ expect(response.headers).to include('X-Next-Page')
+ expect(response.headers).to include('X-Prev-Page')
+ expect(response.headers).to include('Link')
+ end
+ end
+
+ describe 'GET /projects/:id/environments' do
+ context 'as member of the project' do
+ it_behaves_like 'a paginated resources' do
+ let(:request) { get v3_api("/projects/#{project.id}/environments", user) }
+ end
+
+ it 'returns project environments' do
+ get v3_api("/projects/#{project.id}/environments", user)
+
+ expect(response).to have_http_status(200)
+ expect(json_response).to be_an Array
+ expect(json_response.size).to eq(1)
+ expect(json_response.first['name']).to eq(environment.name)
+ expect(json_response.first['external_url']).to eq(environment.external_url)
+ expect(json_response.first['project']['id']).to eq(project.id)
+ expect(json_response.first['project']['visibility_level']).to be_present
+ end
+ end
+
+ context 'as non member' do
+ it 'returns a 404 status code' do
+ get v3_api("/projects/#{project.id}/environments", non_member)
+
+ expect(response).to have_http_status(404)
+ end
+ end
+ end
+
+ describe 'POST /projects/:id/environments' do
+ context 'as a member' do
+ it 'creates a environment with valid params' do
+ post v3_api("/projects/#{project.id}/environments", user), name: "mepmep"
+
+ expect(response).to have_http_status(201)
+ expect(json_response['name']).to eq('mepmep')
+ expect(json_response['slug']).to eq('mepmep')
+ expect(json_response['external']).to be nil
+ end
+
+ it 'requires name to be passed' do
+ post v3_api("/projects/#{project.id}/environments", user), external_url: 'test.gitlab.com'
+
+ expect(response).to have_http_status(400)
+ end
+
+ it 'returns a 400 if environment already exists' do
+ post v3_api("/projects/#{project.id}/environments", user), name: environment.name
+
+ expect(response).to have_http_status(400)
+ end
+
+ it 'returns a 400 if slug is specified' do
+ post v3_api("/projects/#{project.id}/environments", user), name: "foo", slug: "foo"
+
+ expect(response).to have_http_status(400)
+ expect(json_response["error"]).to eq("slug is automatically generated and cannot be changed")
+ end
+ end
+
+ context 'a non member' do
+ it 'rejects the request' do
+ post v3_api("/projects/#{project.id}/environments", non_member), name: 'gitlab.com'
+
+ expect(response).to have_http_status(404)
+ end
+
+ it 'returns a 400 when the required params are missing' do
+ post v3_api("/projects/12345/environments", non_member), external_url: 'http://env.git.com'
+ end
+ end
+ end
+
+ describe 'PUT /projects/:id/environments/:environment_id' do
+ it 'returns a 200 if name and external_url are changed' do
+ url = 'https://mepmep.whatever.ninja'
+ put v3_api("/projects/#{project.id}/environments/#{environment.id}", user),
+ name: 'Mepmep', external_url: url
+
+ expect(response).to have_http_status(200)
+ expect(json_response['name']).to eq('Mepmep')
+ expect(json_response['external_url']).to eq(url)
+ end
+
+ it "won't allow slug to be changed" do
+ slug = environment.slug
+ api_url = v3_api("/projects/#{project.id}/environments/#{environment.id}", user)
+ put api_url, slug: slug + "-foo"
+
+ expect(response).to have_http_status(400)
+ expect(json_response["error"]).to eq("slug is automatically generated and cannot be changed")
+ end
+
+ it "won't update the external_url if only the name is passed" do
+ url = environment.external_url
+ put v3_api("/projects/#{project.id}/environments/#{environment.id}", user),
+ name: 'Mepmep'
+
+ expect(response).to have_http_status(200)
+ expect(json_response['name']).to eq('Mepmep')
+ expect(json_response['external_url']).to eq(url)
+ end
+
+ it 'returns a 404 if the environment does not exist' do
+ put v3_api("/projects/#{project.id}/environments/12345", user)
+
+ expect(response).to have_http_status(404)
+ end
+ end
+
describe 'DELETE /projects/:id/environments/:environment_id' do
context 'as a master' do
it 'returns a 200 for an existing environment' do
diff --git a/spec/requests/api/v3/groups_spec.rb b/spec/requests/api/v3/groups_spec.rb
index 8b29ad03737..a71b7d4b008 100644
--- a/spec/requests/api/v3/groups_spec.rb
+++ b/spec/requests/api/v3/groups_spec.rb
@@ -4,14 +4,144 @@ describe API::V3::Groups, api: true do
include ApiHelpers
include UploadHelpers
+ let(:user1) { create(:user, can_create_group: false) }
let(:user2) { create(:user) }
+ let(:user3) { create(:user) }
+ let(:admin) { create(:admin) }
+ let!(:group1) { create(:group, avatar: File.open(uploaded_image_temp_path)) }
let!(:group2) { create(:group, :private) }
+ let!(:project1) { create(:empty_project, namespace: group1) }
let!(:project2) { create(:empty_project, namespace: group2) }
+ let!(:project3) { create(:empty_project, namespace: group1, path: 'test', visibility_level: Gitlab::VisibilityLevel::PRIVATE) }
before do
+ group1.add_owner(user1)
group2.add_owner(user2)
end
+ describe "GET /groups" do
+ context "when unauthenticated" do
+ it "returns authentication error" do
+ get v3_api("/groups")
+
+ expect(response).to have_http_status(401)
+ end
+ end
+
+ context "when authenticated as user" do
+ it "normal user: returns an array of groups of user1" do
+ get v3_api("/groups", user1)
+
+ expect(response).to have_http_status(200)
+ expect(json_response).to be_an Array
+ expect(json_response.length).to eq(1)
+ expect(json_response)
+ .to satisfy_one { |group| group['name'] == group1.name }
+ end
+
+ it "does not include statistics" do
+ get v3_api("/groups", user1), statistics: true
+
+ expect(response).to have_http_status(200)
+ expect(json_response).to be_an Array
+ expect(json_response.first).not_to include 'statistics'
+ end
+ end
+
+ context "when authenticated as admin" do
+ it "admin: returns an array of all groups" do
+ get v3_api("/groups", admin)
+
+ expect(response).to have_http_status(200)
+ expect(json_response).to be_an Array
+ expect(json_response.length).to eq(2)
+ end
+
+ it "does not include statistics by default" do
+ get v3_api("/groups", admin)
+
+ expect(response).to have_http_status(200)
+ expect(json_response).to be_an Array
+ expect(json_response.first).not_to include('statistics')
+ end
+
+ it "includes statistics if requested" do
+ attributes = {
+ storage_size: 702,
+ repository_size: 123,
+ lfs_objects_size: 234,
+ build_artifacts_size: 345,
+ }.stringify_keys
+
+ project1.statistics.update!(attributes)
+
+ get v3_api("/groups", admin), statistics: true
+
+ expect(response).to have_http_status(200)
+ expect(json_response).to be_an Array
+ expect(json_response)
+ .to satisfy_one { |group| group['statistics'] == attributes }
+ end
+ end
+
+ context "when using skip_groups in request" do
+ it "returns all groups excluding skipped groups" do
+ get v3_api("/groups", admin), skip_groups: [group2.id]
+
+ expect(response).to have_http_status(200)
+ expect(json_response).to be_an Array
+ expect(json_response.length).to eq(1)
+ end
+ end
+
+ context "when using all_available in request" do
+ let(:response_groups) { json_response.map { |group| group['name'] } }
+
+ it "returns all groups you have access to" do
+ public_group = create :group, :public
+
+ get v3_api("/groups", user1), all_available: true
+
+ expect(response).to have_http_status(200)
+ expect(json_response).to be_an Array
+ expect(response_groups).to contain_exactly(public_group.name, group1.name)
+ end
+ end
+
+ context "when using sorting" do
+ let(:group3) { create(:group, name: "a#{group1.name}", path: "z#{group1.path}") }
+ let(:response_groups) { json_response.map { |group| group['name'] } }
+
+ before do
+ group3.add_owner(user1)
+ end
+
+ it "sorts by name ascending by default" do
+ get v3_api("/groups", user1)
+
+ expect(response).to have_http_status(200)
+ expect(json_response).to be_an Array
+ expect(response_groups).to eq([group3.name, group1.name])
+ end
+
+ it "sorts in descending order when passed" do
+ get v3_api("/groups", user1), sort: "desc"
+
+ expect(response).to have_http_status(200)
+ expect(json_response).to be_an Array
+ expect(response_groups).to eq([group1.name, group3.name])
+ end
+
+ it "sorts by the order_by param" do
+ get v3_api("/groups", user1), order_by: "path"
+
+ expect(response).to have_http_status(200)
+ expect(json_response).to be_an Array
+ expect(response_groups).to eq([group1.name, group3.name])
+ end
+ end
+ end
+
describe 'GET /groups/owned' do
context 'when unauthenticated' do
it 'returns authentication error' do
@@ -32,4 +162,404 @@ describe API::V3::Groups, api: true do
end
end
end
+
+ describe "GET /groups/:id" do
+ context "when authenticated as user" do
+ it "returns one of user1's groups" do
+ project = create(:empty_project, namespace: group2, path: 'Foo')
+ create(:project_group_link, project: project, group: group1)
+
+ get v3_api("/groups/#{group1.id}", user1)
+
+ expect(response).to have_http_status(200)
+ expect(json_response['id']).to eq(group1.id)
+ expect(json_response['name']).to eq(group1.name)
+ expect(json_response['path']).to eq(group1.path)
+ expect(json_response['description']).to eq(group1.description)
+ expect(json_response['visibility_level']).to eq(group1.visibility_level)
+ expect(json_response['avatar_url']).to eq(group1.avatar_url)
+ expect(json_response['web_url']).to eq(group1.web_url)
+ expect(json_response['request_access_enabled']).to eq(group1.request_access_enabled)
+ expect(json_response['full_name']).to eq(group1.full_name)
+ expect(json_response['full_path']).to eq(group1.full_path)
+ expect(json_response['parent_id']).to eq(group1.parent_id)
+ expect(json_response['projects']).to be_an Array
+ expect(json_response['projects'].length).to eq(2)
+ expect(json_response['shared_projects']).to be_an Array
+ expect(json_response['shared_projects'].length).to eq(1)
+ expect(json_response['shared_projects'][0]['id']).to eq(project.id)
+ end
+
+ it "does not return a non existing group" do
+ get v3_api("/groups/1328", user1)
+
+ expect(response).to have_http_status(404)
+ end
+
+ it "does not return a group not attached to user1" do
+ get v3_api("/groups/#{group2.id}", user1)
+
+ expect(response).to have_http_status(404)
+ end
+ end
+
+ context "when authenticated as admin" do
+ it "returns any existing group" do
+ get v3_api("/groups/#{group2.id}", admin)
+
+ expect(response).to have_http_status(200)
+ expect(json_response['name']).to eq(group2.name)
+ end
+
+ it "does not return a non existing group" do
+ get v3_api("/groups/1328", admin)
+
+ expect(response).to have_http_status(404)
+ end
+ end
+
+ context 'when using group path in URL' do
+ it 'returns any existing group' do
+ get v3_api("/groups/#{group1.path}", admin)
+
+ expect(response).to have_http_status(200)
+ expect(json_response['name']).to eq(group1.name)
+ end
+
+ it 'does not return a non existing group' do
+ get v3_api('/groups/unknown', admin)
+
+ expect(response).to have_http_status(404)
+ end
+
+ it 'does not return a group not attached to user1' do
+ get v3_api("/groups/#{group2.path}", user1)
+
+ expect(response).to have_http_status(404)
+ end
+ end
+ end
+
+ describe 'PUT /groups/:id' do
+ let(:new_group_name) { 'New Group'}
+
+ context 'when authenticated as the group owner' do
+ it 'updates the group' do
+ put v3_api("/groups/#{group1.id}", user1), name: new_group_name, request_access_enabled: true
+
+ expect(response).to have_http_status(200)
+ expect(json_response['name']).to eq(new_group_name)
+ expect(json_response['request_access_enabled']).to eq(true)
+ end
+
+ it 'returns 404 for a non existing group' do
+ put v3_api('/groups/1328', user1), name: new_group_name
+
+ expect(response).to have_http_status(404)
+ end
+ end
+
+ context 'when authenticated as the admin' do
+ it 'updates the group' do
+ put v3_api("/groups/#{group1.id}", admin), name: new_group_name
+
+ expect(response).to have_http_status(200)
+ expect(json_response['name']).to eq(new_group_name)
+ end
+ end
+
+ context 'when authenticated as an user that can see the group' do
+ it 'does not updates the group' do
+ put v3_api("/groups/#{group1.id}", user2), name: new_group_name
+
+ expect(response).to have_http_status(403)
+ end
+ end
+
+ context 'when authenticated as an user that cannot see the group' do
+ it 'returns 404 when trying to update the group' do
+ put v3_api("/groups/#{group2.id}", user1), name: new_group_name
+
+ expect(response).to have_http_status(404)
+ end
+ end
+ end
+
+ describe "GET /groups/:id/projects" do
+ context "when authenticated as user" do
+ it "returns the group's projects" do
+ get v3_api("/groups/#{group1.id}/projects", user1)
+
+ expect(response).to have_http_status(200)
+ expect(json_response.length).to eq(2)
+ project_names = json_response.map { |proj| proj['name'] }
+ expect(project_names).to match_array([project1.name, project3.name])
+ expect(json_response.first['visibility_level']).to be_present
+ end
+
+ it "returns the group's projects with simple representation" do
+ get v3_api("/groups/#{group1.id}/projects", user1), simple: true
+
+ expect(response).to have_http_status(200)
+ expect(json_response.length).to eq(2)
+ project_names = json_response.map { |proj| proj['name'] }
+ expect(project_names).to match_array([project1.name, project3.name])
+ expect(json_response.first['visibility_level']).not_to be_present
+ end
+
+ it 'filters the groups projects' do
+ public_project = create(:empty_project, :public, path: 'test1', group: group1)
+
+ get v3_api("/groups/#{group1.id}/projects", user1), visibility: 'public'
+
+ expect(response).to have_http_status(200)
+ expect(json_response).to be_an(Array)
+ expect(json_response.length).to eq(1)
+ expect(json_response.first['name']).to eq(public_project.name)
+ end
+
+ it "does not return a non existing group" do
+ get v3_api("/groups/1328/projects", user1)
+
+ expect(response).to have_http_status(404)
+ end
+
+ it "does not return a group not attached to user1" do
+ get v3_api("/groups/#{group2.id}/projects", user1)
+
+ expect(response).to have_http_status(404)
+ end
+
+ it "only returns projects to which user has access" do
+ project3.team << [user3, :developer]
+
+ get v3_api("/groups/#{group1.id}/projects", user3)
+
+ expect(response).to have_http_status(200)
+ expect(json_response.length).to eq(1)
+ expect(json_response.first['name']).to eq(project3.name)
+ end
+
+ it 'only returns the projects owned by user' do
+ project2.group.add_owner(user3)
+
+ get v3_api("/groups/#{project2.group.id}/projects", user3), owned: true
+
+ expect(response).to have_http_status(200)
+ expect(json_response.length).to eq(1)
+ expect(json_response.first['name']).to eq(project2.name)
+ end
+
+ it 'only returns the projects starred by user' do
+ user1.starred_projects = [project1]
+
+ get v3_api("/groups/#{group1.id}/projects", user1), starred: true
+
+ expect(response).to have_http_status(200)
+ expect(json_response.length).to eq(1)
+ expect(json_response.first['name']).to eq(project1.name)
+ end
+ end
+
+ context "when authenticated as admin" do
+ it "returns any existing group" do
+ get v3_api("/groups/#{group2.id}/projects", admin)
+
+ expect(response).to have_http_status(200)
+ expect(json_response.length).to eq(1)
+ expect(json_response.first['name']).to eq(project2.name)
+ end
+
+ it "does not return a non existing group" do
+ get v3_api("/groups/1328/projects", admin)
+
+ expect(response).to have_http_status(404)
+ end
+ end
+
+ context 'when using group path in URL' do
+ it 'returns any existing group' do
+ get v3_api("/groups/#{group1.path}/projects", admin)
+
+ expect(response).to have_http_status(200)
+ project_names = json_response.map { |proj| proj['name'] }
+ expect(project_names).to match_array([project1.name, project3.name])
+ end
+
+ it 'does not return a non existing group' do
+ get v3_api('/groups/unknown/projects', admin)
+
+ expect(response).to have_http_status(404)
+ end
+
+ it 'does not return a group not attached to user1' do
+ get v3_api("/groups/#{group2.path}/projects", user1)
+
+ expect(response).to have_http_status(404)
+ end
+ end
+ end
+
+ describe "POST /groups" do
+ context "when authenticated as user without group permissions" do
+ it "does not create group" do
+ post v3_api("/groups", user1), attributes_for(:group)
+
+ expect(response).to have_http_status(403)
+ end
+ end
+
+ context "when authenticated as user with group permissions" do
+ it "creates group" do
+ group = attributes_for(:group, { request_access_enabled: false })
+
+ post v3_api("/groups", user3), group
+
+ expect(response).to have_http_status(201)
+
+ expect(json_response["name"]).to eq(group[:name])
+ expect(json_response["path"]).to eq(group[:path])
+ expect(json_response["request_access_enabled"]).to eq(group[:request_access_enabled])
+ end
+
+ it "creates a nested group" do
+ parent = create(:group)
+ parent.add_owner(user3)
+ group = attributes_for(:group, { parent_id: parent.id })
+
+ post v3_api("/groups", user3), group
+
+ expect(response).to have_http_status(201)
+
+ expect(json_response["full_path"]).to eq("#{parent.path}/#{group[:path]}")
+ expect(json_response["parent_id"]).to eq(parent.id)
+ end
+
+ it "does not create group, duplicate" do
+ post v3_api("/groups", user3), { name: 'Duplicate Test', path: group2.path }
+
+ expect(response).to have_http_status(400)
+ expect(response.message).to eq("Bad Request")
+ end
+
+ it "returns 400 bad request error if name not given" do
+ post v3_api("/groups", user3), { path: group2.path }
+
+ expect(response).to have_http_status(400)
+ end
+
+ it "returns 400 bad request error if path not given" do
+ post v3_api("/groups", user3), { name: 'test' }
+
+ expect(response).to have_http_status(400)
+ end
+ end
+ end
+
+ describe "DELETE /groups/:id" do
+ context "when authenticated as user" do
+ it "removes group" do
+ delete v3_api("/groups/#{group1.id}", user1)
+
+ expect(response).to have_http_status(200)
+ end
+
+ it "does not remove a group if not an owner" do
+ user4 = create(:user)
+ group1.add_master(user4)
+
+ delete v3_api("/groups/#{group1.id}", user3)
+
+ expect(response).to have_http_status(403)
+ end
+
+ it "does not remove a non existing group" do
+ delete v3_api("/groups/1328", user1)
+
+ expect(response).to have_http_status(404)
+ end
+
+ it "does not remove a group not attached to user1" do
+ delete v3_api("/groups/#{group2.id}", user1)
+
+ expect(response).to have_http_status(404)
+ end
+ end
+
+ context "when authenticated as admin" do
+ it "removes any existing group" do
+ delete v3_api("/groups/#{group2.id}", admin)
+
+ expect(response).to have_http_status(200)
+ end
+
+ it "does not remove a non existing group" do
+ delete v3_api("/groups/1328", admin)
+
+ expect(response).to have_http_status(404)
+ end
+ end
+ end
+
+ describe "POST /groups/:id/projects/:project_id" do
+ let(:project) { create(:empty_project) }
+ let(:project_path) { "#{project.namespace.path}%2F#{project.path}" }
+
+ before(:each) do
+ allow_any_instance_of(Projects::TransferService).
+ to receive(:execute).and_return(true)
+ end
+
+ context "when authenticated as user" do
+ it "does not transfer project to group" do
+ post v3_api("/groups/#{group1.id}/projects/#{project.id}", user2)
+
+ expect(response).to have_http_status(403)
+ end
+ end
+
+ context "when authenticated as admin" do
+ it "transfers project to group" do
+ post v3_api("/groups/#{group1.id}/projects/#{project.id}", admin)
+
+ expect(response).to have_http_status(201)
+ end
+
+ context 'when using project path in URL' do
+ context 'with a valid project path' do
+ it "transfers project to group" do
+ post v3_api("/groups/#{group1.id}/projects/#{project_path}", admin)
+
+ expect(response).to have_http_status(201)
+ end
+ end
+
+ context 'with a non-existent project path' do
+ it "does not transfer project to group" do
+ post v3_api("/groups/#{group1.id}/projects/nogroup%2Fnoproject", admin)
+
+ expect(response).to have_http_status(404)
+ end
+ end
+ end
+
+ context 'when using a group path in URL' do
+ context 'with a valid group path' do
+ it "transfers project to group" do
+ post v3_api("/groups/#{group1.path}/projects/#{project_path}", admin)
+
+ expect(response).to have_http_status(201)
+ end
+ end
+
+ context 'with a non-existent group path' do
+ it "does not transfer project to group" do
+ post v3_api("/groups/noexist/projects/#{project_path}", admin)
+
+ expect(response).to have_http_status(404)
+ end
+ end
+ end
+ end
+ end
end
diff --git a/spec/requests/api/v3/settings_spec.rb b/spec/requests/api/v3/settings_spec.rb
new file mode 100644
index 00000000000..a9fa5adac17
--- /dev/null
+++ b/spec/requests/api/v3/settings_spec.rb
@@ -0,0 +1,65 @@
+require 'spec_helper'
+
+describe API::V3::Settings, 'Settings', api: true do
+ include ApiHelpers
+
+ let(:user) { create(:user) }
+ let(:admin) { create(:admin) }
+
+ describe "GET /application/settings" do
+ it "returns application settings" do
+ get v3_api("/application/settings", admin)
+ expect(response).to have_http_status(200)
+ expect(json_response).to be_an Hash
+ expect(json_response['default_projects_limit']).to eq(42)
+ expect(json_response['signin_enabled']).to be_truthy
+ expect(json_response['repository_storage']).to eq('default')
+ expect(json_response['koding_enabled']).to be_falsey
+ expect(json_response['koding_url']).to be_nil
+ expect(json_response['plantuml_enabled']).to be_falsey
+ expect(json_response['plantuml_url']).to be_nil
+ end
+ end
+
+ describe "PUT /application/settings" do
+ context "custom repository storage type set in the config" do
+ before do
+ storages = { 'custom' => 'tmp/tests/custom_repositories' }
+ allow(Gitlab.config.repositories).to receive(:storages).and_return(storages)
+ end
+
+ it "updates application settings" do
+ put v3_api("/application/settings", admin),
+ default_projects_limit: 3, signin_enabled: false, repository_storage: 'custom', koding_enabled: true, koding_url: 'http://koding.example.com',
+ plantuml_enabled: true, plantuml_url: 'http://plantuml.example.com'
+ expect(response).to have_http_status(200)
+ expect(json_response['default_projects_limit']).to eq(3)
+ expect(json_response['signin_enabled']).to be_falsey
+ expect(json_response['repository_storage']).to eq('custom')
+ expect(json_response['repository_storages']).to eq(['custom'])
+ expect(json_response['koding_enabled']).to be_truthy
+ expect(json_response['koding_url']).to eq('http://koding.example.com')
+ expect(json_response['plantuml_enabled']).to be_truthy
+ expect(json_response['plantuml_url']).to eq('http://plantuml.example.com')
+ end
+ end
+
+ context "missing koding_url value when koding_enabled is true" do
+ it "returns a blank parameter error message" do
+ put v3_api("/application/settings", admin), koding_enabled: true
+
+ expect(response).to have_http_status(400)
+ expect(json_response['error']).to eq('koding_url is missing')
+ end
+ end
+
+ context "missing plantuml_url value when plantuml_enabled is true" do
+ it "returns a blank parameter error message" do
+ put v3_api("/application/settings", admin), plantuml_enabled: true
+
+ expect(response).to have_http_status(400)
+ expect(json_response['error']).to eq('plantuml_url is missing')
+ end
+ end
+ end
+end
diff --git a/spec/requests/api/v3/snippets_spec.rb b/spec/requests/api/v3/snippets_spec.rb
new file mode 100644
index 00000000000..05653bd0d51
--- /dev/null
+++ b/spec/requests/api/v3/snippets_spec.rb
@@ -0,0 +1,187 @@
+require 'rails_helper'
+
+describe API::V3::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 v3_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 v3_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 v3_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 v3_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 v3_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: Snippet::PUBLIC
+ }
+ end
+
+ it 'creates a new snippet' do
+ expect do
+ post v3_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 v3_api("/snippets/", user), params
+
+ expect(response).to have_http_status(400)
+ end
+
+ context 'when the snippet is spam' do
+ def create_snippet(snippet_params = {})
+ post v3_api('/snippets', user), params.merge(snippet_params)
+ end
+
+ before do
+ allow_any_instance_of(AkismetService).to receive(:is_spam?).and_return(true)
+ end
+
+ context 'when the snippet is private' do
+ it 'creates the snippet' do
+ expect { create_snippet(visibility_level: Snippet::PRIVATE) }.
+ to change { Snippet.count }.by(1)
+ end
+ end
+
+ context 'when the snippet is public' do
+ it 'rejects the shippet' do
+ expect { create_snippet(visibility_level: Snippet::PUBLIC) }.
+ not_to change { Snippet.count }
+ expect(response).to have_http_status(400)
+ end
+
+ it 'creates a spam log' do
+ expect { create_snippet(visibility_level: Snippet::PUBLIC) }.
+ to change { SpamLog.count }.by(1)
+ end
+ end
+ 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 v3_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 v3_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 v3_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 v3_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 v3_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 v3_api("/snippets/1234", user)
+
+ expect(response).to have_http_status(404)
+ expect(json_response['message']).to eq('404 Snippet Not Found')
+ end
+ end
+end