summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
Diffstat (limited to 'spec')
-rw-r--r--spec/controllers/application_controller_spec.rb28
-rw-r--r--spec/controllers/groups/shared_projects_controller_spec.rb59
-rw-r--r--spec/controllers/projects/merge_requests_controller_spec.rb27
-rw-r--r--spec/factories/users.rb4
-rw-r--r--spec/features/atom/dashboard_issues_spec.rb12
-rw-r--r--spec/features/atom/dashboard_spec.rb6
-rw-r--r--spec/features/atom/issues_spec.rb13
-rw-r--r--spec/features/atom/users_spec.rb6
-rw-r--r--spec/features/dashboard/activity_spec.rb4
-rw-r--r--spec/features/dashboard/issues_filter_spec.rb6
-rw-r--r--spec/features/dashboard/issues_spec.rb4
-rw-r--r--spec/features/dashboard/projects_spec.rb2
-rw-r--r--spec/features/error_pages_spec.rb42
-rw-r--r--spec/features/groups/activity_spec.rb8
-rw-r--r--spec/features/groups/issues_spec.rb16
-rw-r--r--spec/features/groups/show_spec.rb4
-rw-r--r--spec/features/ics/dashboard_issues_spec.rb65
-rw-r--r--spec/features/ics/group_issues_spec.rb67
-rw-r--r--spec/features/ics/project_issues_spec.rb66
-rw-r--r--spec/features/issues/filtered_search/filter_issues_spec.rb4
-rw-r--r--spec/features/issues_spec.rb28
-rw-r--r--spec/features/merge_requests/user_squashes_merge_request_spec.rb124
-rw-r--r--spec/features/profile_spec.rb12
-rw-r--r--spec/features/projects/activity/rss_spec.rb4
-rw-r--r--spec/features/projects/commits/rss_spec.rb8
-rw-r--r--spec/features/projects/issues/rss_spec.rb8
-rw-r--r--spec/features/projects/milestones/milestone_spec.rb8
-rw-r--r--spec/features/projects/pipelines/pipeline_spec.rb2
-rw-r--r--spec/features/projects/services/user_activates_mattermost_slash_command_spec.rb4
-rw-r--r--spec/features/projects/show/rss_spec.rb4
-rw-r--r--spec/features/projects/tree/rss_spec.rb4
-rw-r--r--spec/features/users/rss_spec.rb4
-rw-r--r--spec/features/users/terms_spec.rb3
-rw-r--r--spec/fixtures/api/schemas/entities/merge_request_widget.json3
-rw-r--r--spec/fixtures/api/schemas/public_api/v3/issues.json78
-rw-r--r--spec/fixtures/api/schemas/public_api/v3/merge_requests.json90
-rw-r--r--spec/fixtures/api/schemas/public_api/v4/merge_requests.json3
-rw-r--r--spec/helpers/calendar_helper_spec.rb20
-rw-r--r--spec/helpers/rss_helper_spec.rb8
-rw-r--r--spec/initializers/grape_route_helpers_fix_spec.rb14
-rw-r--r--spec/javascripts/.eslintrc33
-rw-r--r--spec/javascripts/.eslintrc.yml34
-rw-r--r--spec/javascripts/blob/notebook/index_spec.js9
-rw-r--r--spec/javascripts/boards/board_blank_state_spec.js1
-rw-r--r--spec/javascripts/boards/board_card_spec.js1
-rw-r--r--spec/javascripts/boards/board_list_spec.js1
-rw-r--r--spec/javascripts/boards/board_new_issue_spec.js1
-rw-r--r--spec/javascripts/boards/boards_store_spec.js1
-rw-r--r--spec/javascripts/boards/issue_spec.js1
-rw-r--r--spec/javascripts/boards/list_spec.js1
-rw-r--r--spec/javascripts/commit/commit_pipeline_status_component_spec.js5
-rw-r--r--spec/javascripts/helpers/vue_mount_component_helper.js30
-rw-r--r--spec/javascripts/ide/components/external_link_spec.js35
-rw-r--r--spec/javascripts/ide/components/ide_file_buttons_spec.js61
-rw-r--r--spec/javascripts/sidebar/confidential_issue_sidebar_spec.js5
-rw-r--r--spec/javascripts/u2f/mock_u2f_device.js2
-rw-r--r--spec/lib/gitlab/auth/request_authenticator_spec.rb10
-rw-r--r--spec/lib/gitlab/auth/user_auth_finders_spec.rb46
-rw-r--r--spec/lib/gitlab/bitbucket_import/importer_spec.rb30
-rw-r--r--spec/lib/gitlab/git/blob_spec.rb6
-rw-r--r--spec/lib/gitlab/git/commit_spec.rb4
-rw-r--r--spec/lib/gitlab/git/repository_spec.rb4
-rw-r--r--spec/lib/gitlab/gitlab_import/importer_spec.rb4
-rw-r--r--spec/lib/gitlab/import_export/all_models.yml5
-rw-r--r--spec/lib/gitlab/import_export/relation_factory_spec.rb19
-rw-r--r--spec/lib/gitlab/import_export/safe_model_attributes.yml14
-rw-r--r--spec/lib/mattermost/command_spec.rb10
-rw-r--r--spec/lib/mattermost/session_spec.rb6
-rw-r--r--spec/lib/mattermost/team_spec.rb48
-rw-r--r--spec/migrations/migrate_remaining_mr_metrics_populating_background_migration_spec.rb36
-rw-r--r--spec/models/application_setting_spec.rb16
-rw-r--r--spec/models/concerns/token_authenticatable_spec.rb2
-rw-r--r--spec/models/merge_request_spec.rb59
-rw-r--r--spec/models/project_services/kubernetes_service_spec.rb12
-rw-r--r--spec/models/project_services/mattermost_slash_commands_service_spec.rb10
-rw-r--r--spec/models/user_spec.rb12
-rw-r--r--spec/presenters/ci/build_presenter_spec.rb4
-rw-r--r--spec/requests/api/merge_requests_spec.rb272
-rw-r--r--spec/requests/api/v3/award_emoji_spec.rb297
-rw-r--r--spec/requests/api/v3/boards_spec.rb114
-rw-r--r--spec/requests/api/v3/branches_spec.rb120
-rw-r--r--spec/requests/api/v3/broadcast_messages_spec.rb32
-rw-r--r--spec/requests/api/v3/builds_spec.rb550
-rw-r--r--spec/requests/api/v3/commits_spec.rb603
-rw-r--r--spec/requests/api/v3/deploy_keys_spec.rb179
-rw-r--r--spec/requests/api/v3/deployments_spec.rb69
-rw-r--r--spec/requests/api/v3/environments_spec.rb163
-rw-r--r--spec/requests/api/v3/files_spec.rb283
-rw-r--r--spec/requests/api/v3/groups_spec.rb566
-rw-r--r--spec/requests/api/v3/issues_spec.rb1298
-rw-r--r--spec/requests/api/v3/labels_spec.rb169
-rw-r--r--spec/requests/api/v3/members_spec.rb350
-rw-r--r--spec/requests/api/v3/merge_request_diffs_spec.rb48
-rw-r--r--spec/requests/api/v3/merge_requests_spec.rb749
-rw-r--r--spec/requests/api/v3/milestones_spec.rb238
-rw-r--r--spec/requests/api/v3/notes_spec.rb431
-rw-r--r--spec/requests/api/v3/pipelines_spec.rb201
-rw-r--r--spec/requests/api/v3/project_hooks_spec.rb219
-rw-r--r--spec/requests/api/v3/project_snippets_spec.rb226
-rw-r--r--spec/requests/api/v3/projects_spec.rb1495
-rw-r--r--spec/requests/api/v3/repositories_spec.rb366
-rw-r--r--spec/requests/api/v3/runners_spec.rb152
-rw-r--r--spec/requests/api/v3/services_spec.rb26
-rw-r--r--spec/requests/api/v3/settings_spec.rb63
-rw-r--r--spec/requests/api/v3/snippets_spec.rb186
-rw-r--r--spec/requests/api/v3/system_hooks_spec.rb56
-rw-r--r--spec/requests/api/v3/tags_spec.rb88
-rw-r--r--spec/requests/api/v3/templates_spec.rb201
-rw-r--r--spec/requests/api/v3/todos_spec.rb77
-rw-r--r--spec/requests/api/v3/triggers_spec.rb235
-rw-r--r--spec/requests/api/v3/users_spec.rb362
-rw-r--r--spec/requests/rack_attack_global_spec.rb2
-rw-r--r--spec/routing/routing_spec.rb10
-rw-r--r--spec/serializers/job_entity_spec.rb25
-rw-r--r--spec/services/merge_requests/merge_service_spec.rb60
-rw-r--r--spec/services/merge_requests/squash_service_spec.rb199
-rw-r--r--spec/support/api/v3/time_tracking_shared_examples.rb128
-rw-r--r--spec/support/features/rss_shared_examples.rb24
-rw-r--r--spec/support/gitlab-git-test.git/packed-refs1
-rw-r--r--spec/support/gitlab_stubs/project_8.json68
-rw-r--r--spec/support/gitlab_stubs/projects.json283
-rw-r--r--spec/support/gitlab_stubs/session.json18
-rw-r--r--spec/support/helpers/api_helpers.rb11
-rw-r--r--spec/support/helpers/seed_repo.rb1
-rw-r--r--spec/support/helpers/stub_gitlab_calls.rb20
-rw-r--r--spec/support/helpers/test_env.rb1
-rw-r--r--spec/support/import_export/configuration_helper.rb2
-rw-r--r--spec/support/shared_examples/requests/api/merge_requests_list.rb280
-rw-r--r--spec/tasks/gitlab/storage_rake_spec.rb104
-rw-r--r--spec/tasks/tokens_spec.rb4
-rw-r--r--spec/uploaders/object_storage_spec.rb2
-rw-r--r--spec/workers/concerns/waitable_worker_spec.rb4
132 files changed, 2001 insertions, 11180 deletions
diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb
index f0caac40afd..b048da1991c 100644
--- a/spec/controllers/application_controller_spec.rb
+++ b/spec/controllers/application_controller_spec.rb
@@ -146,35 +146,43 @@ describe ApplicationController do
end
end
- describe '#authenticate_user_from_rss_token' do
- describe "authenticating a user from an RSS token" do
+ describe '#authenticate_sessionless_user!' do
+ describe 'authenticating a user from a feed token' do
controller(described_class) do
def index
render text: 'authenticated'
end
end
- context "when the 'rss_token' param is populated with the RSS token" do
+ context "when the 'feed_token' param is populated with the feed token" do
context 'when the request format is atom' do
it "logs the user in" do
- get :index, rss_token: user.rss_token, format: :atom
+ get :index, feed_token: user.feed_token, format: :atom
expect(response).to have_gitlab_http_status 200
expect(response.body).to eq 'authenticated'
end
end
- context 'when the request format is not atom' do
+ context 'when the request format is ics' do
+ it "logs the user in" do
+ get :index, feed_token: user.feed_token, format: :ics
+ expect(response).to have_gitlab_http_status 200
+ expect(response.body).to eq 'authenticated'
+ end
+ end
+
+ context 'when the request format is neither atom nor ics' do
it "doesn't log the user in" do
- get :index, rss_token: user.rss_token
+ get :index, feed_token: user.feed_token
expect(response.status).not_to have_gitlab_http_status 200
expect(response.body).not_to eq 'authenticated'
end
end
end
- context "when the 'rss_token' param is populated with an invalid RSS token" do
+ context "when the 'feed_token' param is populated with an invalid feed token" do
it "doesn't log the user" do
- get :index, rss_token: "token"
+ get :index, feed_token: 'token', format: :atom
expect(response.status).not_to eq 200
expect(response.body).not_to eq 'authenticated'
end
@@ -454,7 +462,7 @@ describe ApplicationController do
end
it 'renders a 403 when the sessionless user did not accept the terms' do
- get :index, rss_token: user.rss_token, format: :atom
+ get :index, feed_token: user.feed_token, format: :atom
expect(response).to have_gitlab_http_status(403)
end
@@ -462,7 +470,7 @@ describe ApplicationController do
it 'renders a 200 when the sessionless user accepted the terms' do
accept_terms(user)
- get :index, rss_token: user.rss_token, format: :atom
+ get :index, feed_token: user.feed_token, format: :atom
expect(response).to have_gitlab_http_status(200)
end
diff --git a/spec/controllers/groups/shared_projects_controller_spec.rb b/spec/controllers/groups/shared_projects_controller_spec.rb
new file mode 100644
index 00000000000..d8fa41abb18
--- /dev/null
+++ b/spec/controllers/groups/shared_projects_controller_spec.rb
@@ -0,0 +1,59 @@
+require 'spec_helper'
+
+describe Groups::SharedProjectsController do
+ def get_shared_projects(params = {})
+ get :index, params.reverse_merge(format: :json, group_id: group.full_path)
+ end
+
+ def share_project(project)
+ Projects::GroupLinks::CreateService.new(
+ project,
+ user,
+ link_group_access: ProjectGroupLink::DEVELOPER
+ ).execute(group)
+ end
+
+ set(:group) { create(:group) }
+ set(:user) { create(:user) }
+ set(:shared_project) do
+ shared_project = create(:project, namespace: user.namespace)
+ share_project(shared_project)
+
+ shared_project
+ end
+
+ let(:json_project_ids) { json_response.map { |project_info| project_info['id'] } }
+
+ before do
+ sign_in(user)
+ end
+
+ describe 'GET #index' do
+ it 'returns only projects shared with the group' do
+ create(:project, namespace: group)
+
+ get_shared_projects
+
+ expect(json_project_ids).to contain_exactly(shared_project.id)
+ end
+
+ it 'allows filtering shared projects' do
+ project = create(:project, :archived, namespace: user.namespace, name: "Searching for")
+ share_project(project)
+
+ get_shared_projects(filter: 'search')
+
+ expect(json_project_ids).to contain_exactly(project.id)
+ end
+
+ it 'allows sorting projects' do
+ shared_project.update!(name: 'bbb')
+ second_project = create(:project, namespace: user.namespace, name: 'aaaa')
+ share_project(second_project)
+
+ get_shared_projects(sort: 'name_asc')
+
+ expect(json_project_ids).to eq([second_project.id, shared_project.id])
+ end
+ end
+end
diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb
index d3042be9e8b..6e8de6db9c3 100644
--- a/spec/controllers/projects/merge_requests_controller_spec.rb
+++ b/spec/controllers/projects/merge_requests_controller_spec.rb
@@ -275,6 +275,7 @@ describe Projects::MergeRequestsController do
namespace_id: project.namespace,
project_id: project,
id: merge_request.iid,
+ squash: false,
format: 'json'
}
end
@@ -315,8 +316,8 @@ describe Projects::MergeRequestsController do
end
context 'when the sha parameter matches the source SHA' do
- def merge_with_sha
- post :merge, base_params.merge(sha: merge_request.diff_head_sha)
+ def merge_with_sha(params = {})
+ post :merge, base_params.merge(sha: merge_request.diff_head_sha).merge(params)
end
it 'returns :success' do
@@ -325,12 +326,30 @@ describe Projects::MergeRequestsController do
expect(json_response).to eq('status' => 'success')
end
- it 'starts the merge immediately' do
- expect(MergeWorker).to receive(:perform_async).with(merge_request.id, anything, anything)
+ it 'starts the merge immediately with permitted params' do
+ expect(MergeWorker).to receive(:perform_async).with(merge_request.id, anything, { 'squash' => false })
merge_with_sha
end
+ context 'when squash is passed as 1' do
+ it 'updates the squash attribute on the MR to true' do
+ merge_request.update(squash: false)
+ merge_with_sha(squash: '1')
+
+ expect(merge_request.reload.squash).to be_truthy
+ end
+ end
+
+ context 'when squash is passed as 0' do
+ it 'updates the squash attribute on the MR to false' do
+ merge_request.update(squash: true)
+ merge_with_sha(squash: '0')
+
+ expect(merge_request.reload.squash).to be_falsey
+ end
+ end
+
context 'when the pipeline succeeds is passed' do
let!(:head_pipeline) do
create(:ci_empty_pipeline, project: project, sha: merge_request.diff_head_sha, ref: merge_request.source_branch, head_pipeline_of: merge_request)
diff --git a/spec/factories/users.rb b/spec/factories/users.rb
index 769fd656e7a..59db8cdc34b 100644
--- a/spec/factories/users.rb
+++ b/spec/factories/users.rb
@@ -12,10 +12,6 @@ FactoryBot.define do
user.notification_email = user.email
end
- before(:create) do |user|
- user.ensure_rss_token
- end
-
trait :admin do
admin true
end
diff --git a/spec/features/atom/dashboard_issues_spec.rb b/spec/features/atom/dashboard_issues_spec.rb
index fb6c71ce997..da7749b42d2 100644
--- a/spec/features/atom/dashboard_issues_spec.rb
+++ b/spec/features/atom/dashboard_issues_spec.rb
@@ -31,20 +31,20 @@ describe "Dashboard Issues Feed" do
expect(body).to have_selector('title', text: "#{user.name} issues")
end
- it "renders atom feed via RSS token" do
- visit issues_dashboard_path(:atom, rss_token: user.rss_token, assignee_id: user.id)
+ it "renders atom feed via feed token" do
+ visit issues_dashboard_path(:atom, feed_token: user.feed_token, assignee_id: user.id)
expect(response_headers['Content-Type']).to have_content('application/atom+xml')
expect(body).to have_selector('title', text: "#{user.name} issues")
end
it "renders atom feed with url parameters" do
- visit issues_dashboard_path(:atom, rss_token: user.rss_token, state: 'opened', assignee_id: user.id)
+ visit issues_dashboard_path(:atom, feed_token: user.feed_token, state: 'opened', assignee_id: user.id)
link = find('link[type="application/atom+xml"]')
params = CGI.parse(URI.parse(link[:href]).query)
- expect(params).to include('rss_token' => [user.rss_token])
+ expect(params).to include('feed_token' => [user.feed_token])
expect(params).to include('state' => ['opened'])
expect(params).to include('assignee_id' => [user.id.to_s])
end
@@ -53,7 +53,7 @@ describe "Dashboard Issues Feed" do
let!(:issue2) { create(:issue, author: user, assignees: [assignee], project: project2, description: 'test desc') }
it "renders issue fields" do
- visit issues_dashboard_path(:atom, rss_token: user.rss_token, assignee_id: assignee.id)
+ visit issues_dashboard_path(:atom, feed_token: user.feed_token, assignee_id: assignee.id)
entry = find(:xpath, "//feed/entry[contains(summary/text(),'#{issue2.title}')]")
@@ -76,7 +76,7 @@ describe "Dashboard Issues Feed" do
end
it "renders issue label and milestone info" do
- visit issues_dashboard_path(:atom, rss_token: user.rss_token, assignee_id: assignee.id)
+ visit issues_dashboard_path(:atom, feed_token: user.feed_token, assignee_id: assignee.id)
entry = find(:xpath, "//feed/entry[contains(summary/text(),'#{issue1.title}')]")
diff --git a/spec/features/atom/dashboard_spec.rb b/spec/features/atom/dashboard_spec.rb
index c6683bb3bc9..462eab07a75 100644
--- a/spec/features/atom/dashboard_spec.rb
+++ b/spec/features/atom/dashboard_spec.rb
@@ -13,9 +13,9 @@ describe "Dashboard Feed" do
end
end
- context "projects atom feed via RSS token" do
+ context "projects atom feed via feed token" do
it "renders projects atom feed" do
- visit dashboard_projects_path(:atom, rss_token: user.rss_token)
+ visit dashboard_projects_path(:atom, feed_token: user.feed_token)
expect(body).to have_selector('feed title')
end
end
@@ -29,7 +29,7 @@ describe "Dashboard Feed" do
project.add_master(user)
issue_event(issue, user)
note_event(note, user)
- visit dashboard_projects_path(:atom, rss_token: user.rss_token)
+ visit dashboard_projects_path(:atom, feed_token: user.feed_token)
end
it "has issue opened event" do
diff --git a/spec/features/atom/issues_spec.rb b/spec/features/atom/issues_spec.rb
index 525ce23aa56..ee3570a5b2b 100644
--- a/spec/features/atom/issues_spec.rb
+++ b/spec/features/atom/issues_spec.rb
@@ -45,10 +45,10 @@ describe 'Issues Feed' do
end
end
- context 'when authenticated via RSS token' do
+ context 'when authenticated via feed token' do
it 'renders atom feed' do
visit project_issues_path(project, :atom,
- rss_token: user.rss_token)
+ feed_token: user.feed_token)
expect(response_headers['Content-Type'])
.to have_content('application/atom+xml')
@@ -61,24 +61,23 @@ describe 'Issues Feed' do
end
it "renders atom feed with url parameters for project issues" do
- visit project_issues_path(project,
- :atom, rss_token: user.rss_token, state: 'opened', assignee_id: user.id)
+ visit project_issues_path(project, :atom, feed_token: user.feed_token, state: 'opened', assignee_id: user.id)
link = find('link[type="application/atom+xml"]')
params = CGI.parse(URI.parse(link[:href]).query)
- expect(params).to include('rss_token' => [user.rss_token])
+ expect(params).to include('feed_token' => [user.feed_token])
expect(params).to include('state' => ['opened'])
expect(params).to include('assignee_id' => [user.id.to_s])
end
it "renders atom feed with url parameters for group issues" do
- visit issues_group_path(group, :atom, rss_token: user.rss_token, state: 'opened', assignee_id: user.id)
+ visit issues_group_path(group, :atom, feed_token: user.feed_token, state: 'opened', assignee_id: user.id)
link = find('link[type="application/atom+xml"]')
params = CGI.parse(URI.parse(link[:href]).query)
- expect(params).to include('rss_token' => [user.rss_token])
+ expect(params).to include('feed_token' => [user.feed_token])
expect(params).to include('state' => ['opened'])
expect(params).to include('assignee_id' => [user.id.to_s])
end
diff --git a/spec/features/atom/users_spec.rb b/spec/features/atom/users_spec.rb
index 2d074c115dd..eeaaa40fe21 100644
--- a/spec/features/atom/users_spec.rb
+++ b/spec/features/atom/users_spec.rb
@@ -13,9 +13,9 @@ describe "User Feed" do
end
end
- context 'user atom feed via RSS token' do
+ context 'user atom feed via feed token' do
it "renders user atom feed" do
- visit user_path(user, :atom, rss_token: user.rss_token)
+ visit user_path(user, :atom, feed_token: user.feed_token)
expect(body).to have_selector('feed title')
end
end
@@ -51,7 +51,7 @@ describe "User Feed" do
issue_event(issue, user)
note_event(note, user)
merge_request_event(merge_request, user)
- visit user_path(user, :atom, rss_token: user.rss_token)
+ visit user_path(user, :atom, feed_token: user.feed_token)
end
it 'has issue opened event' do
diff --git a/spec/features/dashboard/activity_spec.rb b/spec/features/dashboard/activity_spec.rb
index a74a8aac2b2..941208fa244 100644
--- a/spec/features/dashboard/activity_spec.rb
+++ b/spec/features/dashboard/activity_spec.rb
@@ -12,8 +12,8 @@ feature 'Dashboard > Activity' do
visit activity_dashboard_path
end
- it_behaves_like "it has an RSS button with current_user's RSS token"
- it_behaves_like "an autodiscoverable RSS feed with current_user's RSS token"
+ it_behaves_like "it has an RSS button with current_user's feed token"
+ it_behaves_like "an autodiscoverable RSS feed with current_user's feed token"
end
context 'event filters', :js do
diff --git a/spec/features/dashboard/issues_filter_spec.rb b/spec/features/dashboard/issues_filter_spec.rb
index bab34ac9346..8d0b0be1bd4 100644
--- a/spec/features/dashboard/issues_filter_spec.rb
+++ b/spec/features/dashboard/issues_filter_spec.rb
@@ -47,15 +47,15 @@ feature 'Dashboard Issues filtering', :js do
it 'updates atom feed link' do
visit_issues(milestone_title: '', assignee_id: user.id)
- link = find('.nav-controls a[title="Subscribe"]')
+ link = find('.nav-controls a[title="Subscribe to RSS feed"]')
params = CGI.parse(URI.parse(link[:href]).query)
auto_discovery_link = find('link[type="application/atom+xml"]', visible: false)
auto_discovery_params = CGI.parse(URI.parse(auto_discovery_link[:href]).query)
- expect(params).to include('rss_token' => [user.rss_token])
+ expect(params).to include('feed_token' => [user.feed_token])
expect(params).to include('milestone_title' => [''])
expect(params).to include('assignee_id' => [user.id.to_s])
- expect(auto_discovery_params).to include('rss_token' => [user.rss_token])
+ expect(auto_discovery_params).to include('feed_token' => [user.feed_token])
expect(auto_discovery_params).to include('milestone_title' => [''])
expect(auto_discovery_params).to include('assignee_id' => [user.id.to_s])
end
diff --git a/spec/features/dashboard/issues_spec.rb b/spec/features/dashboard/issues_spec.rb
index e41a2e4ce09..3cc7b38550d 100644
--- a/spec/features/dashboard/issues_spec.rb
+++ b/spec/features/dashboard/issues_spec.rb
@@ -56,8 +56,8 @@ RSpec.describe 'Dashboard Issues' do
expect(page).to have_current_path(issues_dashboard_url(assignee_id: current_user.id, state: 'closed'), url: true)
end
- it_behaves_like "it has an RSS button with current_user's RSS token"
- it_behaves_like "an autodiscoverable RSS feed with current_user's RSS token"
+ it_behaves_like "it has an RSS button with current_user's feed token"
+ it_behaves_like "an autodiscoverable RSS feed with current_user's feed token"
end
describe 'new issue dropdown' do
diff --git a/spec/features/dashboard/projects_spec.rb b/spec/features/dashboard/projects_spec.rb
index 257a3822503..ef2f0b5b31a 100644
--- a/spec/features/dashboard/projects_spec.rb
+++ b/spec/features/dashboard/projects_spec.rb
@@ -10,7 +10,7 @@ feature 'Dashboard Projects' do
sign_in(user)
end
- it_behaves_like "an autodiscoverable RSS feed with current_user's RSS token" do
+ it_behaves_like "an autodiscoverable RSS feed with current_user's feed token" do
before do
visit dashboard_projects_path
end
diff --git a/spec/features/error_pages_spec.rb b/spec/features/error_pages_spec.rb
new file mode 100644
index 00000000000..cd7bcf29cc9
--- /dev/null
+++ b/spec/features/error_pages_spec.rb
@@ -0,0 +1,42 @@
+require 'spec_helper'
+
+describe 'Error Pages' do
+ let(:user) { create(:user) }
+ let(:project) { create(:project, :public) }
+
+ before do
+ sign_in(user)
+ end
+
+ shared_examples 'shows nav links' do
+ it 'shows nav links' do
+ expect(page).to have_link("Home", href: root_path)
+ expect(page).to have_link("Help", href: help_path)
+ expect(page).to have_link(nil, href: destroy_user_session_path)
+ end
+ end
+
+ describe '404' do
+ before do
+ visit '/not-a-real-page'
+ end
+
+ it 'allows user to search' do
+ fill_in 'search', with: 'something'
+ click_button 'Search'
+
+ expect(page).to have_current_path(%r{^/search\?.*search=something.*})
+ end
+
+ it_behaves_like 'shows nav links'
+ end
+
+ describe '403' do
+ before do
+ visit '/'
+ visit edit_project_path(project)
+ end
+
+ it_behaves_like 'shows nav links'
+ end
+end
diff --git a/spec/features/groups/activity_spec.rb b/spec/features/groups/activity_spec.rb
index 7bc809b3104..0d7d3771071 100644
--- a/spec/features/groups/activity_spec.rb
+++ b/spec/features/groups/activity_spec.rb
@@ -15,8 +15,8 @@ feature 'Group activity page' do
visit path
end
- it_behaves_like "it has an RSS button with current_user's RSS token"
- it_behaves_like "an autodiscoverable RSS feed with current_user's RSS token"
+ it_behaves_like "it has an RSS button with current_user's feed token"
+ it_behaves_like "an autodiscoverable RSS feed with current_user's feed token"
end
context 'when project is in the group', :js do
@@ -39,7 +39,7 @@ feature 'Group activity page' do
visit path
end
- it_behaves_like "it has an RSS button without an RSS token"
- it_behaves_like "an autodiscoverable RSS feed without an RSS token"
+ it_behaves_like "it has an RSS button without a feed token"
+ it_behaves_like "an autodiscoverable RSS feed without a feed token"
end
end
diff --git a/spec/features/groups/issues_spec.rb b/spec/features/groups/issues_spec.rb
index 90bf7ba49f6..111a24c0d94 100644
--- a/spec/features/groups/issues_spec.rb
+++ b/spec/features/groups/issues_spec.rb
@@ -16,17 +16,21 @@ feature 'Group issues page' do
let(:access_level) { ProjectFeature::ENABLED }
context 'when signed in' do
- let(:user) { user_in_group }
-
- it_behaves_like "it has an RSS button with current_user's RSS token"
- it_behaves_like "an autodiscoverable RSS feed with current_user's RSS token"
+ let(:user) do
+ user_in_group.ensure_feed_token
+ user_in_group.save!
+ user_in_group
+ end
+
+ it_behaves_like "it has an RSS button with current_user's feed token"
+ it_behaves_like "an autodiscoverable RSS feed with current_user's feed token"
end
context 'when signed out' do
let(:user) { nil }
- it_behaves_like "it has an RSS button without an RSS token"
- it_behaves_like "an autodiscoverable RSS feed without an RSS token"
+ it_behaves_like "it has an RSS button without a feed token"
+ it_behaves_like "an autodiscoverable RSS feed without a feed token"
end
end
diff --git a/spec/features/groups/show_spec.rb b/spec/features/groups/show_spec.rb
index 3a0424d60f8..b7a7aa0e174 100644
--- a/spec/features/groups/show_spec.rb
+++ b/spec/features/groups/show_spec.rb
@@ -14,7 +14,7 @@ feature 'Group show page' do
visit path
end
- it_behaves_like "an autodiscoverable RSS feed with current_user's RSS token"
+ it_behaves_like "an autodiscoverable RSS feed with current_user's feed token"
context 'when group does not exist' do
let(:path) { group_path('not-exist') }
@@ -29,7 +29,7 @@ feature 'Group show page' do
visit path
end
- it_behaves_like "an autodiscoverable RSS feed without an RSS token"
+ it_behaves_like "an autodiscoverable RSS feed without a feed token"
end
context 'when group has a public project', :js do
diff --git a/spec/features/ics/dashboard_issues_spec.rb b/spec/features/ics/dashboard_issues_spec.rb
new file mode 100644
index 00000000000..5d6cd44ad1c
--- /dev/null
+++ b/spec/features/ics/dashboard_issues_spec.rb
@@ -0,0 +1,65 @@
+require 'spec_helper'
+
+describe 'Dashboard Issues Calendar Feed' do
+ describe 'GET /issues' do
+ let!(:user) { create(:user, email: 'private1@example.com', public_email: 'public1@example.com') }
+ let!(:assignee) { create(:user, email: 'private2@example.com', public_email: 'public2@example.com') }
+ let!(:project) { create(:project) }
+
+ before do
+ project.add_master(user)
+ end
+
+ context 'when authenticated' do
+ it 'renders calendar feed' do
+ sign_in user
+ visit issues_dashboard_path(:ics)
+
+ expect(response_headers['Content-Type']).to have_content('text/calendar')
+ expect(response_headers['Content-Disposition']).to have_content('inline')
+ expect(body).to have_text('BEGIN:VCALENDAR')
+ end
+ end
+
+ context 'when authenticated via personal access token' do
+ it 'renders calendar feed' do
+ personal_access_token = create(:personal_access_token, user: user)
+
+ visit issues_dashboard_path(:ics, private_token: personal_access_token.token)
+
+ expect(response_headers['Content-Type']).to have_content('text/calendar')
+ expect(response_headers['Content-Disposition']).to have_content('inline')
+ expect(body).to have_text('BEGIN:VCALENDAR')
+ end
+ end
+
+ context 'when authenticated via feed token' do
+ it 'renders calendar feed' do
+ visit issues_dashboard_path(:ics, feed_token: user.feed_token)
+
+ expect(response_headers['Content-Type']).to have_content('text/calendar')
+ expect(response_headers['Content-Disposition']).to have_content('inline')
+ expect(body).to have_text('BEGIN:VCALENDAR')
+ end
+ end
+
+ context 'issue with due date' do
+ let!(:issue) do
+ create(:issue, author: user, assignees: [assignee], project: project, title: 'test title',
+ description: 'test desc', due_date: Date.tomorrow)
+ end
+
+ it 'renders issue fields' do
+ visit issues_dashboard_path(:ics, feed_token: user.feed_token)
+
+ expect(body).to have_text("SUMMARY:test title (in #{project.full_path})")
+ # line length for ics is 75 chars
+ expected_description = "DESCRIPTION:Find out more at #{issue_url(issue)}".insert(75, "\r\n")
+ expect(body).to have_text(expected_description)
+ expect(body).to have_text("DTSTART;VALUE=DATE:#{Date.tomorrow.strftime('%Y%m%d')}")
+ expect(body).to have_text("URL:#{issue_url(issue)}")
+ expect(body).to have_text('TRANSP:TRANSPARENT')
+ end
+ end
+ end
+end
diff --git a/spec/features/ics/group_issues_spec.rb b/spec/features/ics/group_issues_spec.rb
new file mode 100644
index 00000000000..0a049be2ffe
--- /dev/null
+++ b/spec/features/ics/group_issues_spec.rb
@@ -0,0 +1,67 @@
+require 'spec_helper'
+
+describe 'Group Issues Calendar Feed' do
+ describe 'GET /issues' do
+ let!(:user) { create(:user, email: 'private1@example.com', public_email: 'public1@example.com') }
+ let!(:assignee) { create(:user, email: 'private2@example.com', public_email: 'public2@example.com') }
+ let!(:group) { create(:group) }
+ let!(:project) { create(:project, group: group) }
+
+ before do
+ project.add_developer(user)
+ group.add_developer(user)
+ end
+
+ context 'when authenticated' do
+ it 'renders calendar feed' do
+ sign_in user
+ visit issues_group_path(group, :ics)
+
+ expect(response_headers['Content-Type']).to have_content('text/calendar')
+ expect(response_headers['Content-Disposition']).to have_content('inline')
+ expect(body).to have_text('BEGIN:VCALENDAR')
+ end
+ end
+
+ context 'when authenticated via personal access token' do
+ it 'renders calendar feed' do
+ personal_access_token = create(:personal_access_token, user: user)
+
+ visit issues_group_path(group, :ics, private_token: personal_access_token.token)
+
+ expect(response_headers['Content-Type']).to have_content('text/calendar')
+ expect(response_headers['Content-Disposition']).to have_content('inline')
+ expect(body).to have_text('BEGIN:VCALENDAR')
+ end
+ end
+
+ context 'when authenticated via feed token' do
+ it 'renders calendar feed' do
+ visit issues_group_path(group, :ics, feed_token: user.feed_token)
+
+ expect(response_headers['Content-Type']).to have_content('text/calendar')
+ expect(response_headers['Content-Disposition']).to have_content('inline')
+ expect(body).to have_text('BEGIN:VCALENDAR')
+ end
+ end
+
+ context 'issue with due date' do
+ let!(:issue) do
+ create(:issue, author: user, assignees: [assignee], project: project, title: 'test title',
+ description: 'test desc', due_date: Date.tomorrow)
+ end
+
+ it 'renders issue fields' do
+ visit issues_group_path(group, :ics, feed_token: user.feed_token)
+
+ expect(body).to have_text("SUMMARY:test title (in #{project.full_path})")
+ # line length for ics is 75 chars
+ expected_description = "DESCRIPTION:Find out more at #{issue_url(issue)}".insert(75, "\r\n")
+ expect(body).to have_text(expected_description)
+ expect(body).to have_text("DTSTART;VALUE=DATE:#{Date.tomorrow.strftime('%Y%m%d')}")
+ expect(body).to have_text("URL:#{issue_url(issue)}")
+ expect(body).to have_text('TRANSP:TRANSPARENT')
+ end
+ end
+ end
+end
diff --git a/spec/features/ics/project_issues_spec.rb b/spec/features/ics/project_issues_spec.rb
new file mode 100644
index 00000000000..b99e9607f1d
--- /dev/null
+++ b/spec/features/ics/project_issues_spec.rb
@@ -0,0 +1,66 @@
+require 'spec_helper'
+
+describe 'Project Issues Calendar Feed' do
+ describe 'GET /issues' do
+ let!(:user) { create(:user, email: 'private1@example.com', public_email: 'public1@example.com') }
+ let!(:assignee) { create(:user, email: 'private2@example.com', public_email: 'public2@example.com') }
+ let!(:project) { create(:project) }
+ let!(:issue) { create(:issue, author: user, assignees: [assignee], project: project) }
+
+ before do
+ project.add_developer(user)
+ end
+
+ context 'when authenticated' do
+ it 'renders calendar feed' do
+ sign_in user
+ visit project_issues_path(project, :ics)
+
+ expect(response_headers['Content-Type']).to have_content('text/calendar')
+ expect(response_headers['Content-Disposition']).to have_content('inline')
+ expect(body).to have_text('BEGIN:VCALENDAR')
+ end
+ end
+
+ context 'when authenticated via personal access token' do
+ it 'renders calendar feed' do
+ personal_access_token = create(:personal_access_token, user: user)
+
+ visit project_issues_path(project, :ics, private_token: personal_access_token.token)
+
+ expect(response_headers['Content-Type']).to have_content('text/calendar')
+ expect(response_headers['Content-Disposition']).to have_content('inline')
+ expect(body).to have_text('BEGIN:VCALENDAR')
+ end
+ end
+
+ context 'when authenticated via feed token' do
+ it 'renders calendar feed' do
+ visit project_issues_path(project, :ics, feed_token: user.feed_token)
+
+ expect(response_headers['Content-Type']).to have_content('text/calendar')
+ expect(response_headers['Content-Disposition']).to have_content('inline')
+ expect(body).to have_text('BEGIN:VCALENDAR')
+ end
+ end
+
+ context 'issue with due date' do
+ let!(:issue) do
+ create(:issue, author: user, assignees: [assignee], project: project, title: 'test title',
+ description: 'test desc', due_date: Date.tomorrow)
+ end
+
+ it 'renders issue fields' do
+ visit project_issues_path(project, :ics, feed_token: user.feed_token)
+
+ expect(body).to have_text("SUMMARY:test title (in #{project.full_path})")
+ # line length for ics is 75 chars
+ expected_description = "DESCRIPTION:Find out more at #{issue_url(issue)}".insert(75, "\r\n")
+ expect(body).to have_text(expected_description)
+ expect(body).to have_text("DTSTART;VALUE=DATE:#{Date.tomorrow.strftime('%Y%m%d')}")
+ expect(body).to have_text("URL:#{issue_url(issue)}")
+ expect(body).to have_text('TRANSP:TRANSPARENT')
+ end
+ end
+ end
+end
diff --git a/spec/features/issues/filtered_search/filter_issues_spec.rb b/spec/features/issues/filtered_search/filter_issues_spec.rb
index 483122ae463..bc42618306f 100644
--- a/spec/features/issues/filtered_search/filter_issues_spec.rb
+++ b/spec/features/issues/filtered_search/filter_issues_spec.rb
@@ -468,13 +468,13 @@ describe 'Filter issues', :js do
it "for #{type}" do
visit path
- link = find_link('Subscribe')
+ link = find_link('Subscribe to RSS feed')
params = CGI.parse(URI.parse(link[:href]).query)
auto_discovery_link = find('link[type="application/atom+xml"]', visible: false)
auto_discovery_params = CGI.parse(URI.parse(auto_discovery_link[:href]).query)
expected = {
- 'rss_token' => [user.rss_token],
+ 'feed_token' => [user.feed_token],
'milestone_title' => [milestone.title],
'assignee_id' => [user.id.to_s]
}
diff --git a/spec/features/issues_spec.rb b/spec/features/issues_spec.rb
index 314bd19f586..c6dcd97631d 100644
--- a/spec/features/issues_spec.rb
+++ b/spec/features/issues_spec.rb
@@ -340,6 +340,20 @@ describe 'Issues' do
expect(page).to have_content('baz')
end
end
+
+ it 'filters by due next month and previous two weeks' do
+ foo.update(due_date: Date.today - 4.weeks)
+ bar.update(due_date: (Date.today + 2.months).beginning_of_month)
+ baz.update(due_date: Date.yesterday)
+
+ visit project_issues_path(project, due_date: Issue::DueNextMonthAndPreviousTwoWeeks.name)
+
+ page.within '.issues-holder' do
+ expect(page).not_to have_content('foo')
+ expect(page).not_to have_content('bar')
+ expect(page).to have_content('baz')
+ end
+ end
end
describe 'sorting by milestone' do
@@ -591,6 +605,20 @@ describe 'Issues' do
end
end
+ it 'clears local storage after creating a new issue', :js do
+ 2.times do
+ visit new_project_issue_path(project)
+ wait_for_requests
+
+ expect(page).to have_field('Title', with: '')
+
+ fill_in 'issue_title', with: 'bug 345'
+ fill_in 'issue_description', with: 'bug description'
+
+ click_button 'Submit issue'
+ end
+ end
+
context 'dropzone upload file', :js do
before do
visit new_project_issue_path(project)
diff --git a/spec/features/merge_requests/user_squashes_merge_request_spec.rb b/spec/features/merge_requests/user_squashes_merge_request_spec.rb
new file mode 100644
index 00000000000..6c952791591
--- /dev/null
+++ b/spec/features/merge_requests/user_squashes_merge_request_spec.rb
@@ -0,0 +1,124 @@
+require 'spec_helper'
+
+feature 'User squashes a merge request', :js do
+ let(:user) { create(:user) }
+ let(:project) { create(:project, :repository) }
+ let(:source_branch) { 'csv' }
+
+ let!(:original_head) { project.repository.commit('master') }
+
+ shared_examples 'squash' do
+ it 'squashes the commits into a single commit, and adds a merge commit' do
+ expect(page).to have_content('Merged')
+
+ latest_master_commits = project.repository.commits_between(original_head.sha, 'master').map(&:raw)
+
+ squash_commit = an_object_having_attributes(sha: a_string_matching(/\h{40}/),
+ message: "Csv\n",
+ author_name: user.name,
+ committer_name: user.name)
+
+ merge_commit = an_object_having_attributes(sha: a_string_matching(/\h{40}/),
+ message: a_string_starting_with("Merge branch 'csv' into 'master'"),
+ author_name: user.name,
+ committer_name: user.name)
+
+ expect(project.repository).not_to be_merged_to_root_ref(source_branch)
+ expect(latest_master_commits).to match([squash_commit, merge_commit])
+ end
+ end
+
+ shared_examples 'no squash' do
+ it 'accepts the merge request without squashing' do
+ expect(page).to have_content('Merged')
+ expect(project.repository).to be_merged_to_root_ref(source_branch)
+ end
+ end
+
+ def accept_mr
+ expect(page).to have_button('Merge')
+
+ uncheck 'Remove source branch'
+ click_on 'Merge'
+ end
+
+ before do
+ # Prevent source branch from being removed so we can use be_merged_to_root_ref
+ # method to check if squash was performed or not
+ allow_any_instance_of(MergeRequest).to receive(:force_remove_source_branch?).and_return(false)
+ project.add_master(user)
+
+ sign_in user
+ end
+
+ context 'when the MR has only one commit' do
+ before do
+ merge_request = create(:merge_request, source_project: project, target_project: project, source_branch: 'master', target_branch: 'branch-merged')
+
+ visit project_merge_request_path(project, merge_request)
+ end
+
+ it 'does not show the squash checkbox' do
+ expect(page).not_to have_field('squash')
+ end
+ end
+
+ context 'when squash is enabled on merge request creation' do
+ before do
+ visit project_new_merge_request_path(project, merge_request: { target_branch: 'master', source_branch: source_branch })
+ check 'merge_request[squash]'
+ click_on 'Submit merge request'
+ wait_for_requests
+ end
+
+ it 'shows the squash checkbox as checked' do
+ expect(page).to have_checked_field('squash')
+ end
+
+ context 'when accepting with squash checked' do
+ before do
+ accept_mr
+ end
+
+ include_examples 'squash'
+ end
+
+ context 'when accepting and unchecking squash' do
+ before do
+ uncheck 'squash'
+ accept_mr
+ end
+
+ include_examples 'no squash'
+ end
+ end
+
+ context 'when squash is not enabled on merge request creation' do
+ before do
+ visit project_new_merge_request_path(project, merge_request: { target_branch: 'master', source_branch: source_branch })
+ click_on 'Submit merge request'
+ wait_for_requests
+ end
+
+ it 'shows the squash checkbox as unchecked' do
+ expect(page).to have_unchecked_field('squash')
+ end
+
+ context 'when accepting and checking squash' do
+ before do
+ check 'squash'
+ accept_mr
+ end
+
+ include_examples 'squash'
+ end
+
+ context 'when accepting with squash unchecked' do
+ before do
+ accept_mr
+ end
+
+ include_examples 'no squash'
+ end
+ end
+end
diff --git a/spec/features/profile_spec.rb b/spec/features/profile_spec.rb
index 15dcb30cbdd..2e0753c3bfb 100644
--- a/spec/features/profile_spec.rb
+++ b/spec/features/profile_spec.rb
@@ -56,21 +56,21 @@ describe 'Profile account page', :js do
end
end
- describe 'when I reset RSS token' do
+ describe 'when I reset feed token' do
before do
visit profile_personal_access_tokens_path
end
- it 'resets RSS token' do
- within('.rss-token-reset') do
- previous_token = find("#rss_token").value
+ it 'resets feed token' do
+ within('.feed-token-reset') do
+ previous_token = find("#feed_token").value
accept_confirm { click_link('reset it') }
- expect(find('#rss_token').value).not_to eq(previous_token)
+ expect(find('#feed_token').value).not_to eq(previous_token)
end
- expect(page).to have_content 'RSS token was successfully reset'
+ expect(page).to have_content 'Feed token was successfully reset'
end
end
diff --git a/spec/features/projects/activity/rss_spec.rb b/spec/features/projects/activity/rss_spec.rb
index cd1cfe07998..4ac34adde0e 100644
--- a/spec/features/projects/activity/rss_spec.rb
+++ b/spec/features/projects/activity/rss_spec.rb
@@ -15,7 +15,7 @@ feature 'Project Activity RSS' do
visit path
end
- it_behaves_like "it has an RSS button with current_user's RSS token"
+ it_behaves_like "it has an RSS button with current_user's feed token"
end
context 'when signed out' do
@@ -23,6 +23,6 @@ feature 'Project Activity RSS' do
visit path
end
- it_behaves_like "it has an RSS button without an RSS token"
+ it_behaves_like "it has an RSS button without a feed token"
end
end
diff --git a/spec/features/projects/commits/rss_spec.rb b/spec/features/projects/commits/rss_spec.rb
index 0d9c7355ddd..0bc207da970 100644
--- a/spec/features/projects/commits/rss_spec.rb
+++ b/spec/features/projects/commits/rss_spec.rb
@@ -12,8 +12,8 @@ feature 'Project Commits RSS' do
visit path
end
- it_behaves_like "it has an RSS button with current_user's RSS token"
- it_behaves_like "an autodiscoverable RSS feed with current_user's RSS token"
+ it_behaves_like "it has an RSS button with current_user's feed token"
+ it_behaves_like "an autodiscoverable RSS feed with current_user's feed token"
end
context 'when signed out' do
@@ -21,7 +21,7 @@ feature 'Project Commits RSS' do
visit path
end
- it_behaves_like "it has an RSS button without an RSS token"
- it_behaves_like "an autodiscoverable RSS feed without an RSS token"
+ it_behaves_like "it has an RSS button without a feed token"
+ it_behaves_like "an autodiscoverable RSS feed without a feed token"
end
end
diff --git a/spec/features/projects/issues/rss_spec.rb b/spec/features/projects/issues/rss_spec.rb
index ff91aabc311..8b1f7d432ee 100644
--- a/spec/features/projects/issues/rss_spec.rb
+++ b/spec/features/projects/issues/rss_spec.rb
@@ -17,8 +17,8 @@ feature 'Project Issues RSS' do
visit path
end
- it_behaves_like "it has an RSS button with current_user's RSS token"
- it_behaves_like "an autodiscoverable RSS feed with current_user's RSS token"
+ it_behaves_like "it has an RSS button with current_user's feed token"
+ it_behaves_like "an autodiscoverable RSS feed with current_user's feed token"
end
context 'when signed out' do
@@ -26,7 +26,7 @@ feature 'Project Issues RSS' do
visit path
end
- it_behaves_like "it has an RSS button without an RSS token"
- it_behaves_like "an autodiscoverable RSS feed without an RSS token"
+ it_behaves_like "it has an RSS button without a feed token"
+ it_behaves_like "an autodiscoverable RSS feed without a feed token"
end
end
diff --git a/spec/features/projects/milestones/milestone_spec.rb b/spec/features/projects/milestones/milestone_spec.rb
index 30de3e83fbb..20a52d6011f 100644
--- a/spec/features/projects/milestones/milestone_spec.rb
+++ b/spec/features/projects/milestones/milestone_spec.rb
@@ -17,8 +17,8 @@ feature 'Project milestone' do
it 'shows issues tab' do
within('#content-body') do
expect(page).to have_link 'Issues', href: '#tab-issues'
- expect(page).to have_selector '.nav-links li.active', count: 1
- expect(find('.nav-links li.active')).to have_content 'Issues'
+ expect(page).to have_selector '.nav-links li a.active', count: 1
+ expect(find('.nav-links li a.active')).to have_content 'Issues'
end
end
@@ -44,8 +44,8 @@ feature 'Project milestone' do
it 'hides issues tab' do
within('#content-body') do
expect(page).not_to have_link 'Issues', href: '#tab-issues'
- expect(page).to have_selector '.nav-links li.active', count: 1
- expect(find('.nav-links li.active')).to have_content 'Merge Requests'
+ expect(page).to have_selector '.nav-links li a.active', count: 1
+ expect(find('.nav-links li a.active')).to have_content 'Merge Requests'
end
end
diff --git a/spec/features/projects/pipelines/pipeline_spec.rb b/spec/features/projects/pipelines/pipeline_spec.rb
index af2a9567a47..35776a5f23b 100644
--- a/spec/features/projects/pipelines/pipeline_spec.rb
+++ b/spec/features/projects/pipelines/pipeline_spec.rb
@@ -379,7 +379,7 @@ describe 'Pipeline', :js do
end
it 'fails to access the page' do
- expect(page).to have_content('Access Denied')
+ expect(page).to have_title('Access Denied')
end
end
end
diff --git a/spec/features/projects/services/user_activates_mattermost_slash_command_spec.rb b/spec/features/projects/services/user_activates_mattermost_slash_command_spec.rb
index b2906e315f7..fce41ce347f 100644
--- a/spec/features/projects/services/user_activates_mattermost_slash_command_spec.rb
+++ b/spec/features/projects/services/user_activates_mattermost_slash_command_spec.rb
@@ -64,7 +64,7 @@ feature 'Setup Mattermost slash commands', :js do
click_link 'Add to Mattermost'
expect(page).to have_content('The team where the slash commands will be used in')
- expect(page).to have_content('This is the only available team.')
+ expect(page).to have_content('This is the only available team that you are a member of.')
end
it 'shows a disabled prefilled select if user is a member of 1 team' do
@@ -94,7 +94,7 @@ feature 'Setup Mattermost slash commands', :js do
click_link 'Add to Mattermost'
expect(page).to have_content('Select the team where the slash commands will be used in')
- expect(page).to have_content('The list shows all available teams.')
+ expect(page).to have_content('The list shows all available teams that you are a member of.')
end
it 'shows a select with team options user is a member of multiple teams' do
diff --git a/spec/features/projects/show/rss_spec.rb b/spec/features/projects/show/rss_spec.rb
index d02eaf34533..52164d30c40 100644
--- a/spec/features/projects/show/rss_spec.rb
+++ b/spec/features/projects/show/rss_spec.rb
@@ -12,7 +12,7 @@ feature 'Projects > Show > RSS' do
visit path
end
- it_behaves_like "an autodiscoverable RSS feed with current_user's RSS token"
+ it_behaves_like "an autodiscoverable RSS feed with current_user's feed token"
end
context 'when signed out' do
@@ -20,6 +20,6 @@ feature 'Projects > Show > RSS' do
visit path
end
- it_behaves_like "an autodiscoverable RSS feed without an RSS token"
+ it_behaves_like "an autodiscoverable RSS feed without a feed token"
end
end
diff --git a/spec/features/projects/tree/rss_spec.rb b/spec/features/projects/tree/rss_spec.rb
index 6407370ac0d..f52b3cc1d86 100644
--- a/spec/features/projects/tree/rss_spec.rb
+++ b/spec/features/projects/tree/rss_spec.rb
@@ -12,7 +12,7 @@ feature 'Project Tree RSS' do
visit path
end
- it_behaves_like "an autodiscoverable RSS feed with current_user's RSS token"
+ it_behaves_like "an autodiscoverable RSS feed with current_user's feed token"
end
context 'when signed out' do
@@ -20,6 +20,6 @@ feature 'Project Tree RSS' do
visit path
end
- it_behaves_like "an autodiscoverable RSS feed without an RSS token"
+ it_behaves_like "an autodiscoverable RSS feed without a feed token"
end
end
diff --git a/spec/features/users/rss_spec.rb b/spec/features/users/rss_spec.rb
index 7c5abe54d56..c3734b5c808 100644
--- a/spec/features/users/rss_spec.rb
+++ b/spec/features/users/rss_spec.rb
@@ -10,7 +10,7 @@ feature 'User RSS' do
visit path
end
- it_behaves_like "it has an RSS button with current_user's RSS token"
+ it_behaves_like "it has an RSS button with current_user's feed token"
end
context 'when signed out' do
@@ -18,6 +18,6 @@ feature 'User RSS' do
visit path
end
- it_behaves_like "it has an RSS button without an RSS token"
+ it_behaves_like "it has an RSS button without a feed token"
end
end
diff --git a/spec/features/users/terms_spec.rb b/spec/features/users/terms_spec.rb
index f9469adbfe3..1efa5cd5490 100644
--- a/spec/features/users/terms_spec.rb
+++ b/spec/features/users/terms_spec.rb
@@ -62,7 +62,8 @@ describe 'Users > Terms' do
expect(current_path).to eq(project_issues_path(project))
end
- it 'redirects back to the page the user was trying to save' do
+ # Disabled until https://gitlab.com/gitlab-org/gitlab-ce/issues/37162 is solved properly
+ xit 'redirects back to the page the user was trying to save' do
visit new_project_issue_path(project)
fill_in :issue_title, with: 'Hello world, a new issue'
diff --git a/spec/fixtures/api/schemas/entities/merge_request_widget.json b/spec/fixtures/api/schemas/entities/merge_request_widget.json
index 233102c4314..7be8c9e3e67 100644
--- a/spec/fixtures/api/schemas/entities/merge_request_widget.json
+++ b/spec/fixtures/api/schemas/entities/merge_request_widget.json
@@ -112,7 +112,8 @@
"rebase_commit_sha": { "type": ["string", "null"] },
"rebase_in_progress": { "type": "boolean" },
"can_push_to_source_branch": { "type": "boolean" },
- "rebase_path": { "type": ["string", "null"] }
+ "rebase_path": { "type": ["string", "null"] },
+ "squash": { "type": "boolean" }
},
"additionalProperties": false
}
diff --git a/spec/fixtures/api/schemas/public_api/v3/issues.json b/spec/fixtures/api/schemas/public_api/v3/issues.json
deleted file mode 100644
index 51b0822bc66..00000000000
--- a/spec/fixtures/api/schemas/public_api/v3/issues.json
+++ /dev/null
@@ -1,78 +0,0 @@
-{
- "type": "array",
- "items": {
- "type": "object",
- "properties" : {
- "id": { "type": "integer" },
- "iid": { "type": "integer" },
- "project_id": { "type": "integer" },
- "title": { "type": "string" },
- "description": { "type": ["string", "null"] },
- "state": { "type": "string" },
- "created_at": { "type": "date" },
- "updated_at": { "type": "date" },
- "labels": {
- "type": "array",
- "items": {
- "type": "string"
- }
- },
- "milestone": {
- "type": "object",
- "properties": {
- "id": { "type": "integer" },
- "iid": { "type": "integer" },
- "project_id": { "type": ["integer", "null"] },
- "group_id": { "type": ["integer", "null"] },
- "title": { "type": "string" },
- "description": { "type": ["string", "null"] },
- "state": { "type": "string" },
- "created_at": { "type": "date" },
- "updated_at": { "type": "date" },
- "due_date": { "type": "date" },
- "start_date": { "type": "date" }
- },
- "additionalProperties": false
- },
- "assignee": {
- "type": ["object", "null"],
- "properties": {
- "name": { "type": "string" },
- "username": { "type": "string" },
- "id": { "type": "integer" },
- "state": { "type": "string" },
- "avatar_url": { "type": "uri" },
- "web_url": { "type": "uri" }
- },
- "additionalProperties": false
- },
- "author": {
- "type": "object",
- "properties": {
- "name": { "type": "string" },
- "username": { "type": "string" },
- "id": { "type": "integer" },
- "state": { "type": "string" },
- "avatar_url": { "type": "uri" },
- "web_url": { "type": "uri" }
- },
- "additionalProperties": false
- },
- "user_notes_count": { "type": "integer" },
- "upvotes": { "type": "integer" },
- "downvotes": { "type": "integer" },
- "due_date": { "type": ["date", "null"] },
- "confidential": { "type": "boolean" },
- "web_url": { "type": "uri" },
- "subscribed": { "type": ["boolean"] }
- },
- "required": [
- "id", "iid", "project_id", "title", "description",
- "state", "created_at", "updated_at", "labels",
- "milestone", "assignee", "author", "user_notes_count",
- "upvotes", "downvotes", "due_date", "confidential",
- "web_url", "subscribed"
- ],
- "additionalProperties": false
- }
-}
diff --git a/spec/fixtures/api/schemas/public_api/v3/merge_requests.json b/spec/fixtures/api/schemas/public_api/v3/merge_requests.json
deleted file mode 100644
index b5c74bcc26e..00000000000
--- a/spec/fixtures/api/schemas/public_api/v3/merge_requests.json
+++ /dev/null
@@ -1,90 +0,0 @@
-{
- "type": "array",
- "items": {
- "type": "object",
- "properties" : {
- "id": { "type": "integer" },
- "iid": { "type": "integer" },
- "project_id": { "type": "integer" },
- "title": { "type": "string" },
- "description": { "type": ["string", "null"] },
- "state": { "type": "string" },
- "created_at": { "type": "date" },
- "updated_at": { "type": "date" },
- "target_branch": { "type": "string" },
- "source_branch": { "type": "string" },
- "upvotes": { "type": "integer" },
- "downvotes": { "type": "integer" },
- "author": {
- "type": "object",
- "properties": {
- "name": { "type": "string" },
- "username": { "type": "string" },
- "id": { "type": "integer" },
- "state": { "type": "string" },
- "avatar_url": { "type": "uri" },
- "web_url": { "type": "uri" }
- },
- "additionalProperties": false
- },
- "assignee": {
- "type": "object",
- "properties": {
- "name": { "type": "string" },
- "username": { "type": "string" },
- "id": { "type": "integer" },
- "state": { "type": "string" },
- "avatar_url": { "type": "uri" },
- "web_url": { "type": "uri" }
- },
- "additionalProperties": false
- },
- "source_project_id": { "type": "integer" },
- "target_project_id": { "type": "integer" },
- "labels": {
- "type": "array",
- "items": {
- "type": "string"
- }
- },
- "work_in_progress": { "type": "boolean" },
- "milestone": {
- "type": ["object", "null"],
- "properties": {
- "id": { "type": "integer" },
- "iid": { "type": "integer" },
- "project_id": { "type": ["integer", "null"] },
- "group_id": { "type": ["integer", "null"] },
- "title": { "type": "string" },
- "description": { "type": ["string", "null"] },
- "state": { "type": "string" },
- "created_at": { "type": "date" },
- "updated_at": { "type": "date" },
- "due_date": { "type": "date" },
- "start_date": { "type": "date" }
- },
- "additionalProperties": false
- },
- "merge_when_build_succeeds": { "type": "boolean" },
- "merge_status": { "type": "string" },
- "sha": { "type": "string" },
- "merge_commit_sha": { "type": ["string", "null"] },
- "user_notes_count": { "type": "integer" },
- "should_remove_source_branch": { "type": ["boolean", "null"] },
- "force_remove_source_branch": { "type": ["boolean", "null"] },
- "web_url": { "type": "uri" },
- "subscribed": { "type": ["boolean"] }
- },
- "required": [
- "id", "iid", "project_id", "title", "description",
- "state", "created_at", "updated_at", "target_branch",
- "source_branch", "upvotes", "downvotes", "author",
- "assignee", "source_project_id", "target_project_id",
- "labels", "work_in_progress", "milestone", "merge_when_build_succeeds",
- "merge_status", "sha", "merge_commit_sha", "user_notes_count",
- "should_remove_source_branch", "force_remove_source_branch",
- "web_url", "subscribed"
- ],
- "additionalProperties": false
- }
-}
diff --git a/spec/fixtures/api/schemas/public_api/v4/merge_requests.json b/spec/fixtures/api/schemas/public_api/v4/merge_requests.json
index 0dc2eabec5d..f97461ce9cc 100644
--- a/spec/fixtures/api/schemas/public_api/v4/merge_requests.json
+++ b/spec/fixtures/api/schemas/public_api/v4/merge_requests.json
@@ -75,6 +75,7 @@
"force_remove_source_branch": { "type": ["boolean", "null"] },
"discussion_locked": { "type": ["boolean", "null"] },
"web_url": { "type": "uri" },
+ "squash": { "type": "boolean" },
"time_stats": {
"time_estimate": { "type": "integer" },
"total_time_spent": { "type": "integer" },
@@ -91,7 +92,7 @@
"labels", "work_in_progress", "milestone", "merge_when_pipeline_succeeds",
"merge_status", "sha", "merge_commit_sha", "user_notes_count",
"should_remove_source_branch", "force_remove_source_branch",
- "web_url"
+ "web_url", "squash"
],
"additionalProperties": false
}
diff --git a/spec/helpers/calendar_helper_spec.rb b/spec/helpers/calendar_helper_spec.rb
new file mode 100644
index 00000000000..828a9d9fea0
--- /dev/null
+++ b/spec/helpers/calendar_helper_spec.rb
@@ -0,0 +1,20 @@
+require 'spec_helper'
+
+describe CalendarHelper do
+ describe '#calendar_url_options' do
+ context 'when signed in' do
+ it "includes the current_user's feed_token" do
+ current_user = create(:user)
+ allow(helper).to receive(:current_user).and_return(current_user)
+ expect(helper.calendar_url_options).to include feed_token: current_user.feed_token
+ end
+ end
+
+ context 'when signed out' do
+ it "does not have a feed_token" do
+ allow(helper).to receive(:current_user).and_return(nil)
+ expect(helper.calendar_url_options[:feed_token]).to be_nil
+ end
+ end
+ end
+end
diff --git a/spec/helpers/rss_helper_spec.rb b/spec/helpers/rss_helper_spec.rb
index 269e1057e8d..a7f9bdf07e4 100644
--- a/spec/helpers/rss_helper_spec.rb
+++ b/spec/helpers/rss_helper_spec.rb
@@ -3,17 +3,17 @@ require 'spec_helper'
describe RssHelper do
describe '#rss_url_options' do
context 'when signed in' do
- it "includes the current_user's rss_token" do
+ it "includes the current_user's feed_token" do
current_user = create(:user)
allow(helper).to receive(:current_user).and_return(current_user)
- expect(helper.rss_url_options).to include rss_token: current_user.rss_token
+ expect(helper.rss_url_options).to include feed_token: current_user.feed_token
end
end
context 'when signed out' do
- it "does not have an rss_token" do
+ it "does not have a feed_token" do
allow(helper).to receive(:current_user).and_return(nil)
- expect(helper.rss_url_options[:rss_token]).to be_nil
+ expect(helper.rss_url_options[:feed_token]).to be_nil
end
end
end
diff --git a/spec/initializers/grape_route_helpers_fix_spec.rb b/spec/initializers/grape_route_helpers_fix_spec.rb
deleted file mode 100644
index 2cf5924128f..00000000000
--- a/spec/initializers/grape_route_helpers_fix_spec.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-require 'spec_helper'
-require_relative '../../config/initializers/grape_route_helpers_fix'
-
-describe 'route shadowing' do
- include GrapeRouteHelpers::NamedRouteMatcher
-
- it 'does not occur' do
- path = api_v4_projects_merge_requests_path(id: 1)
- expect(path).to eq('/api/v4/projects/1/merge_requests')
-
- path = api_v4_projects_merge_requests_path(id: 1, merge_request_iid: 3)
- expect(path).to eq('/api/v4/projects/1/merge_requests/3')
- end
-end
diff --git a/spec/javascripts/.eslintrc b/spec/javascripts/.eslintrc
deleted file mode 100644
index 9eb0e732572..00000000000
--- a/spec/javascripts/.eslintrc
+++ /dev/null
@@ -1,33 +0,0 @@
-{
- "env": {
- "jasmine": true
- },
- "extends": "plugin:jasmine/recommended",
- "globals": {
- "appendLoadFixtures": false,
- "appendLoadStyleFixtures": false,
- "appendSetFixtures": false,
- "appendSetStyleFixtures": false,
- "getJSONFixture": false,
- "loadFixtures": false,
- "loadJSONFixtures": false,
- "loadStyleFixtures": false,
- "preloadFixtures": false,
- "preloadStyleFixtures": false,
- "readFixtures": false,
- "sandbox": false,
- "setFixtures": false,
- "setStyleFixtures": false,
- "spyOnDependency": false,
- "spyOnEvent": false,
- "ClassSpecHelper": false
- },
- "plugins": ["jasmine"],
- "rules": {
- "func-names": 0,
- "jasmine/no-suite-dupes": [1, "branch"],
- "jasmine/no-spec-dupes": [1, "branch"],
- "no-console": 0,
- "prefer-arrow-callback": 0
- }
-}
diff --git a/spec/javascripts/.eslintrc.yml b/spec/javascripts/.eslintrc.yml
new file mode 100644
index 00000000000..8bceb2c50fc
--- /dev/null
+++ b/spec/javascripts/.eslintrc.yml
@@ -0,0 +1,34 @@
+---
+env:
+ jasmine: true
+extends: plugin:jasmine/recommended
+globals:
+ appendLoadFixtures: false
+ appendLoadStyleFixtures: false
+ appendSetFixtures: false
+ appendSetStyleFixtures: false
+ getJSONFixture: false
+ loadFixtures: false
+ loadJSONFixtures: false
+ loadStyleFixtures: false
+ preloadFixtures: false
+ preloadStyleFixtures: false
+ readFixtures: false
+ sandbox: false
+ setFixtures: false
+ setStyleFixtures: false
+ spyOnDependency: false
+ spyOnEvent: false
+ ClassSpecHelper: false
+plugins:
+ - jasmine
+rules:
+ func-names: off
+ jasmine/no-suite-dupes:
+ - warn
+ - branch
+ jasmine/no-spec-dupes:
+ - warn
+ - branch
+ no-console: off
+ prefer-arrow-callback: off
diff --git a/spec/javascripts/blob/notebook/index_spec.js b/spec/javascripts/blob/notebook/index_spec.js
index a143fc827d5..80c09a544d6 100644
--- a/spec/javascripts/blob/notebook/index_spec.js
+++ b/spec/javascripts/blob/notebook/index_spec.js
@@ -84,9 +84,14 @@ describe('iPython notebook renderer', () => {
describe('error in JSON response', () => {
let mock;
- beforeEach((done) => {
+ beforeEach(done => {
mock = new MockAdapter(axios);
- mock.onGet('/test').reply(() => Promise.reject({ status: 200, data: '{ "cells": [{"cell_type": "markdown"} }' }));
+ mock
+ .onGet('/test')
+ .reply(() =>
+ // eslint-disable-next-line prefer-promise-reject-errors
+ Promise.reject({ status: 200, data: '{ "cells": [{"cell_type": "markdown"} }' }),
+ );
renderNotebook();
diff --git a/spec/javascripts/boards/board_blank_state_spec.js b/spec/javascripts/boards/board_blank_state_spec.js
index 664ea202e93..89a4fae4b59 100644
--- a/spec/javascripts/boards/board_blank_state_spec.js
+++ b/spec/javascripts/boards/board_blank_state_spec.js
@@ -1,4 +1,3 @@
-/* global BoardService */
import Vue from 'vue';
import '~/boards/stores/boards_store';
import BoardBlankState from '~/boards/components/board_blank_state.vue';
diff --git a/spec/javascripts/boards/board_card_spec.js b/spec/javascripts/boards/board_card_spec.js
index 13d607a06d2..9b4db774b63 100644
--- a/spec/javascripts/boards/board_card_spec.js
+++ b/spec/javascripts/boards/board_card_spec.js
@@ -1,7 +1,6 @@
/* global List */
/* global ListAssignee */
/* global ListLabel */
-/* global BoardService */
import Vue from 'vue';
import MockAdapter from 'axios-mock-adapter';
diff --git a/spec/javascripts/boards/board_list_spec.js b/spec/javascripts/boards/board_list_spec.js
index c06b2f60813..a49b190d36a 100644
--- a/spec/javascripts/boards/board_list_spec.js
+++ b/spec/javascripts/boards/board_list_spec.js
@@ -1,4 +1,3 @@
-/* global BoardService */
/* global List */
/* global ListIssue */
import Vue from 'vue';
diff --git a/spec/javascripts/boards/board_new_issue_spec.js b/spec/javascripts/boards/board_new_issue_spec.js
index d5fbfdeaa91..ee37821ad08 100644
--- a/spec/javascripts/boards/board_new_issue_spec.js
+++ b/spec/javascripts/boards/board_new_issue_spec.js
@@ -1,4 +1,3 @@
-/* global BoardService */
/* global List */
import Vue from 'vue';
diff --git a/spec/javascripts/boards/boards_store_spec.js b/spec/javascripts/boards/boards_store_spec.js
index 0cf9e4c9ba1..46fa10e1789 100644
--- a/spec/javascripts/boards/boards_store_spec.js
+++ b/spec/javascripts/boards/boards_store_spec.js
@@ -1,5 +1,4 @@
/* eslint-disable comma-dangle, one-var, no-unused-vars */
-/* global BoardService */
/* global ListIssue */
import Vue from 'vue';
diff --git a/spec/javascripts/boards/issue_spec.js b/spec/javascripts/boards/issue_spec.js
index 4a11131b55c..d90f9a41231 100644
--- a/spec/javascripts/boards/issue_spec.js
+++ b/spec/javascripts/boards/issue_spec.js
@@ -1,5 +1,4 @@
/* eslint-disable comma-dangle */
-/* global BoardService */
/* global ListIssue */
import Vue from 'vue';
diff --git a/spec/javascripts/boards/list_spec.js b/spec/javascripts/boards/list_spec.js
index d9a1d692949..d5d1139de15 100644
--- a/spec/javascripts/boards/list_spec.js
+++ b/spec/javascripts/boards/list_spec.js
@@ -1,5 +1,4 @@
/* eslint-disable comma-dangle */
-/* global BoardService */
/* global List */
/* global ListIssue */
diff --git a/spec/javascripts/commit/commit_pipeline_status_component_spec.js b/spec/javascripts/commit/commit_pipeline_status_component_spec.js
index 421fe62a1e7..d3776d0c3cf 100644
--- a/spec/javascripts/commit/commit_pipeline_status_component_spec.js
+++ b/spec/javascripts/commit/commit_pipeline_status_component_spec.js
@@ -75,10 +75,7 @@ describe('Commit pipeline status component', () => {
describe('When polling data was not succesful', () => {
beforeEach(() => {
mock = new MockAdapter(axios);
- mock.onGet('/dummy/endpoint').reply(() => {
- const res = Promise.reject([502, { }]);
- return res;
- });
+ mock.onGet('/dummy/endpoint').reply(502, {});
vm = new Component({
props: {
endpoint: '/dummy/endpoint',
diff --git a/spec/javascripts/helpers/vue_mount_component_helper.js b/spec/javascripts/helpers/vue_mount_component_helper.js
index a34a1add4e0..5ba17ecf5b5 100644
--- a/spec/javascripts/helpers/vue_mount_component_helper.js
+++ b/spec/javascripts/helpers/vue_mount_component_helper.js
@@ -1,30 +1,18 @@
-import Vue from 'vue';
-
-const mountComponent = (Component, props = {}, el = null) => new Component({
- propsData: props,
-}).$mount(el);
-
-export const createComponentWithStore = (Component, store, propsData = {}) => new Component({
- store,
- propsData,
-});
+const mountComponent = (Component, props = {}, el = null) =>
+ new Component({
+ propsData: props,
+ }).$mount(el);
-export const createComponentWithMixin = (mixins = [], state = {}, props = {}, template = '<div></div>') => {
- const Component = Vue.extend({
- template,
- mixins,
- data() {
- return props;
- },
+export const createComponentWithStore = (Component, store, propsData = {}) =>
+ new Component({
+ store,
+ propsData,
});
- return mountComponent(Component, props);
-};
-
export const mountComponentWithStore = (Component, { el, props, store }) =>
new Component({
store,
- propsData: props || { },
+ propsData: props || {},
}).$mount(el);
export default mountComponent;
diff --git a/spec/javascripts/ide/components/external_link_spec.js b/spec/javascripts/ide/components/external_link_spec.js
new file mode 100644
index 00000000000..b3d94c041fa
--- /dev/null
+++ b/spec/javascripts/ide/components/external_link_spec.js
@@ -0,0 +1,35 @@
+import Vue from 'vue';
+import externalLink from '~/ide/components/external_link.vue';
+import createVueComponent from '../../helpers/vue_mount_component_helper';
+import { file } from '../helpers';
+
+describe('ExternalLink', () => {
+ const activeFile = file();
+ let vm;
+
+ function createComponent() {
+ const ExternalLink = Vue.extend(externalLink);
+
+ activeFile.permalink = 'test';
+
+ return createVueComponent(ExternalLink, {
+ file: activeFile,
+ });
+ }
+
+ afterEach(() => {
+ vm.$destroy();
+ });
+
+ it('renders the external link with the correct href', done => {
+ activeFile.binary = true;
+ vm = createComponent();
+
+ vm.$nextTick(() => {
+ const openLink = vm.$el.querySelector('a');
+
+ expect(openLink.href).toMatch(`/${activeFile.permalink}`);
+ done();
+ });
+ });
+});
diff --git a/spec/javascripts/ide/components/ide_file_buttons_spec.js b/spec/javascripts/ide/components/ide_file_buttons_spec.js
deleted file mode 100644
index 8ac8d1b2acf..00000000000
--- a/spec/javascripts/ide/components/ide_file_buttons_spec.js
+++ /dev/null
@@ -1,61 +0,0 @@
-import Vue from 'vue';
-import repoFileButtons from '~/ide/components/ide_file_buttons.vue';
-import createVueComponent from '../../helpers/vue_mount_component_helper';
-import { file } from '../helpers';
-
-describe('RepoFileButtons', () => {
- const activeFile = file();
- let vm;
-
- function createComponent() {
- const RepoFileButtons = Vue.extend(repoFileButtons);
-
- activeFile.rawPath = 'test';
- activeFile.blamePath = 'test';
- activeFile.commitsPath = 'test';
-
- return createVueComponent(RepoFileButtons, {
- file: activeFile,
- });
- }
-
- afterEach(() => {
- vm.$destroy();
- });
-
- it('renders Raw, Blame, History and Permalink', done => {
- vm = createComponent();
-
- vm.$nextTick(() => {
- const raw = vm.$el.querySelector('.raw');
- const blame = vm.$el.querySelector('.blame');
- const history = vm.$el.querySelector('.history');
-
- expect(raw.href).toMatch(`/${activeFile.rawPath}`);
- expect(raw.getAttribute('data-original-title')).toEqual('Raw');
- expect(blame.href).toMatch(`/${activeFile.blamePath}`);
- expect(blame.getAttribute('data-original-title')).toEqual('Blame');
- expect(history.href).toMatch(`/${activeFile.commitsPath}`);
- expect(history.getAttribute('data-original-title')).toEqual('History');
- expect(vm.$el.querySelector('.permalink').getAttribute('data-original-title')).toEqual(
- 'Permalink',
- );
-
- done();
- });
- });
-
- it('renders Download', done => {
- activeFile.binary = true;
- vm = createComponent();
-
- vm.$nextTick(() => {
- const raw = vm.$el.querySelector('.raw');
-
- expect(raw.href).toMatch(`/${activeFile.rawPath}`);
- expect(raw.getAttribute('data-original-title')).toEqual('Download');
-
- done();
- });
- });
-});
diff --git a/spec/javascripts/sidebar/confidential_issue_sidebar_spec.js b/spec/javascripts/sidebar/confidential_issue_sidebar_spec.js
index 0c173062835..6110d5d89ac 100644
--- a/spec/javascripts/sidebar/confidential_issue_sidebar_spec.js
+++ b/spec/javascripts/sidebar/confidential_issue_sidebar_spec.js
@@ -8,10 +8,7 @@ describe('Confidential Issue Sidebar Block', () => {
beforeEach(() => {
const Component = Vue.extend(confidentialIssueSidebar);
const service = {
- update: () => new Promise((resolve, reject) => {
- resolve(true);
- reject('failed!');
- }),
+ update: () => Promise.resolve(true),
};
vm1 = new Component({
diff --git a/spec/javascripts/u2f/mock_u2f_device.js b/spec/javascripts/u2f/mock_u2f_device.js
index 5a1ace2b4d6..8fec6ae3fa4 100644
--- a/spec/javascripts/u2f/mock_u2f_device.js
+++ b/spec/javascripts/u2f/mock_u2f_device.js
@@ -1,5 +1,5 @@
/* eslint-disable prefer-rest-params, wrap-iife,
-no-unused-expressions, no-return-assign, no-param-reassign*/
+no-unused-expressions, no-return-assign, no-param-reassign */
export default class MockU2FDevice {
constructor() {
diff --git a/spec/lib/gitlab/auth/request_authenticator_spec.rb b/spec/lib/gitlab/auth/request_authenticator_spec.rb
index ffcd90b9fcb..242ab4a91dd 100644
--- a/spec/lib/gitlab/auth/request_authenticator_spec.rb
+++ b/spec/lib/gitlab/auth/request_authenticator_spec.rb
@@ -39,19 +39,19 @@ describe Gitlab::Auth::RequestAuthenticator do
describe '#find_sessionless_user' do
let!(:access_token_user) { build(:user) }
- let!(:rss_token_user) { build(:user) }
+ let!(:feed_token_user) { build(:user) }
it 'returns access_token user first' do
allow_any_instance_of(described_class).to receive(:find_user_from_access_token).and_return(access_token_user)
- allow_any_instance_of(described_class).to receive(:find_user_from_rss_token).and_return(rss_token_user)
+ allow_any_instance_of(described_class).to receive(:find_user_from_feed_token).and_return(feed_token_user)
expect(subject.find_sessionless_user).to eq access_token_user
end
- it 'returns rss_token user if no access_token user found' do
- allow_any_instance_of(described_class).to receive(:find_user_from_rss_token).and_return(rss_token_user)
+ it 'returns feed_token user if no access_token user found' do
+ allow_any_instance_of(described_class).to receive(:find_user_from_feed_token).and_return(feed_token_user)
- expect(subject.find_sessionless_user).to eq rss_token_user
+ expect(subject.find_sessionless_user).to eq feed_token_user
end
it 'returns nil if no user found' do
diff --git a/spec/lib/gitlab/auth/user_auth_finders_spec.rb b/spec/lib/gitlab/auth/user_auth_finders_spec.rb
index 2733eef6611..136646bd4ee 100644
--- a/spec/lib/gitlab/auth/user_auth_finders_spec.rb
+++ b/spec/lib/gitlab/auth/user_auth_finders_spec.rb
@@ -46,34 +46,54 @@ describe Gitlab::Auth::UserAuthFinders do
end
end
- describe '#find_user_from_rss_token' do
+ describe '#find_user_from_feed_token' do
context 'when the request format is atom' do
before do
env['HTTP_ACCEPT'] = 'application/atom+xml'
end
- it 'returns user if valid rss_token' do
- set_param(:rss_token, user.rss_token)
+ context 'when feed_token param is provided' do
+ it 'returns user if valid feed_token' do
+ set_param(:feed_token, user.feed_token)
- expect(find_user_from_rss_token).to eq user
- end
+ expect(find_user_from_feed_token).to eq user
+ end
+
+ it 'returns nil if feed_token is blank' do
+ expect(find_user_from_feed_token).to be_nil
+ end
+
+ it 'returns exception if invalid feed_token' do
+ set_param(:feed_token, 'invalid_token')
- it 'returns nil if rss_token is blank' do
- expect(find_user_from_rss_token).to be_nil
+ expect { find_user_from_feed_token }.to raise_error(Gitlab::Auth::UnauthorizedError)
+ end
end
- it 'returns exception if invalid rss_token' do
- set_param(:rss_token, 'invalid_token')
+ context 'when rss_token param is provided' do
+ it 'returns user if valid rssd_token' do
+ set_param(:rss_token, user.feed_token)
- expect { find_user_from_rss_token }.to raise_error(Gitlab::Auth::UnauthorizedError)
+ expect(find_user_from_feed_token).to eq user
+ end
+
+ it 'returns nil if rss_token is blank' do
+ expect(find_user_from_feed_token).to be_nil
+ end
+
+ it 'returns exception if invalid rss_token' do
+ set_param(:rss_token, 'invalid_token')
+
+ expect { find_user_from_feed_token }.to raise_error(Gitlab::Auth::UnauthorizedError)
+ end
end
end
context 'when the request format is not atom' do
it 'returns nil' do
- set_param(:rss_token, user.rss_token)
+ set_param(:feed_token, user.feed_token)
- expect(find_user_from_rss_token).to be_nil
+ expect(find_user_from_feed_token).to be_nil
end
end
@@ -81,7 +101,7 @@ describe Gitlab::Auth::UserAuthFinders do
it 'the method call does not modify the original value' do
env['action_dispatch.request.formats'] = nil
- find_user_from_rss_token
+ find_user_from_feed_token
expect(env['action_dispatch.request.formats']).to be_nil
end
diff --git a/spec/lib/gitlab/bitbucket_import/importer_spec.rb b/spec/lib/gitlab/bitbucket_import/importer_spec.rb
index c63120b0b29..05c232d22cf 100644
--- a/spec/lib/gitlab/bitbucket_import/importer_spec.rb
+++ b/spec/lib/gitlab/bitbucket_import/importer_spec.rb
@@ -19,6 +19,18 @@ describe Gitlab::BitbucketImport::Importer do
]
end
+ let(:reporters) do
+ [
+ nil,
+ { "username" => "reporter1" },
+ nil,
+ { "username" => "reporter2" },
+ { "username" => "reporter1" },
+ nil,
+ { "username" => "reporter3" }
+ ]
+ end
+
let(:sample_issues_statuses) do
issues = []
@@ -36,6 +48,10 @@ describe Gitlab::BitbucketImport::Importer do
}
end
+ reporters.map.with_index do |reporter, index|
+ issues[index]['reporter'] = reporter
+ end
+
issues
end
@@ -147,5 +163,19 @@ describe Gitlab::BitbucketImport::Importer do
expect(importer.errors).to be_empty
end
end
+
+ describe 'issue import' do
+ it 'maps reporters to anonymous if bitbucket reporter is nil' do
+ allow(importer).to receive(:import_wiki)
+ importer.execute
+
+ expect(project.issues.size).to eq(7)
+ expect(project.issues.where("description LIKE ?", '%Anonymous%').size).to eq(3)
+ expect(project.issues.where("description LIKE ?", '%reporter1%').size).to eq(2)
+ expect(project.issues.where("description LIKE ?", '%reporter2%').size).to eq(1)
+ expect(project.issues.where("description LIKE ?", '%reporter3%').size).to eq(1)
+ expect(importer.errors).to be_empty
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/git/blob_spec.rb b/spec/lib/gitlab/git/blob_spec.rb
index e2547ed0311..94eaf86ef80 100644
--- a/spec/lib/gitlab/git/blob_spec.rb
+++ b/spec/lib/gitlab/git/blob_spec.rb
@@ -22,6 +22,12 @@ describe Gitlab::Git::Blob, seed_helper: true do
it { expect(blob).to eq(nil) }
end
+ context 'utf-8 branch' do
+ let(:blob) { Gitlab::Git::Blob.find(repository, 'Ääh-test-utf-8', "files/ruby/popen.rb")}
+
+ it { expect(blob.id).to eq(SeedRepo::RubyBlob::ID) }
+ end
+
context 'blank path' do
let(:blob) { Gitlab::Git::Blob.find(repository, SeedRepo::Commit::ID, '') }
diff --git a/spec/lib/gitlab/git/commit_spec.rb b/spec/lib/gitlab/git/commit_spec.rb
index 08c6d1e55e9..89be8a1b7f2 100644
--- a/spec/lib/gitlab/git/commit_spec.rb
+++ b/spec/lib/gitlab/git/commit_spec.rb
@@ -603,8 +603,8 @@ describe Gitlab::Git::Commit, seed_helper: true do
let(:commit) { described_class.find(repository, 'master') }
subject { commit.ref_names(repository) }
- it 'has 1 element' do
- expect(subject.size).to eq(1)
+ it 'has 2 element' do
+ expect(subject.size).to eq(2)
end
it { is_expected.to include("master") }
it { is_expected.not_to include("feature") }
diff --git a/spec/lib/gitlab/git/repository_spec.rb b/spec/lib/gitlab/git/repository_spec.rb
index af6a486ab20..dd5c498706d 100644
--- a/spec/lib/gitlab/git/repository_spec.rb
+++ b/spec/lib/gitlab/git/repository_spec.rb
@@ -1374,7 +1374,7 @@ describe Gitlab::Git::Repository, seed_helper: true do
describe '#branch_count' do
it 'returns the number of branches' do
- expect(repository.branch_count).to eq(10)
+ expect(repository.branch_count).to eq(11)
end
context 'with local and remote branches' do
@@ -2248,7 +2248,7 @@ describe Gitlab::Git::Repository, seed_helper: true do
describe '#checksum' do
it 'calculates the checksum for non-empty repo' do
- expect(repository.checksum).to eq '54f21be4c32c02f6788d72207fa03ad3bce725e4'
+ expect(repository.checksum).to eq '4be7d24ce7e8d845502d599b72d567d23e6a40c0'
end
it 'returns 0000000000000000000000000000000000000000 for an empty repo' do
diff --git a/spec/lib/gitlab/gitlab_import/importer_spec.rb b/spec/lib/gitlab/gitlab_import/importer_spec.rb
index e1d935602b5..200edceca8c 100644
--- a/spec/lib/gitlab/gitlab_import/importer_spec.rb
+++ b/spec/lib/gitlab/gitlab_import/importer_spec.rb
@@ -20,7 +20,7 @@ describe Gitlab::GitlabImport::Importer do
}
}
])
- stub_request('issues/2579857/notes', [])
+ stub_request('issues/3/notes', [])
end
it 'persists issues' do
@@ -43,7 +43,7 @@ describe Gitlab::GitlabImport::Importer do
end
def stub_request(path, body)
- url = "https://gitlab.com/api/v3/projects/asd%2Fvim/#{path}?page=1&per_page=100"
+ url = "https://gitlab.com/api/v4/projects/asd%2Fvim/#{path}?page=1&per_page=100"
WebMock.stub_request(:get, url)
.to_return(
diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml
index fb5fd300dbb..a129855dbd8 100644
--- a/spec/lib/gitlab/import_export/all_models.yml
+++ b/spec/lib/gitlab/import_export/all_models.yml
@@ -310,3 +310,8 @@ lfs_file_locks:
- user
project_badges:
- project
+metrics:
+- merge_request
+- latest_closed_by
+- merged_by
+- pipeline
diff --git a/spec/lib/gitlab/import_export/relation_factory_spec.rb b/spec/lib/gitlab/import_export/relation_factory_spec.rb
index 5f0dfd64b15..cf9e0f71910 100644
--- a/spec/lib/gitlab/import_export/relation_factory_spec.rb
+++ b/spec/lib/gitlab/import_export/relation_factory_spec.rb
@@ -119,6 +119,25 @@ describe Gitlab::ImportExport::RelationFactory do
end
end
+ context 'overrided model with pluralized name' do
+ let(:relation_sym) { :metrics }
+
+ let(:relation_hash) do
+ {
+ 'id' => 99,
+ 'merge_request_id' => 99,
+ 'merged_at' => Time.now,
+ 'merged_by_id' => 99,
+ 'latest_closed_at' => nil,
+ 'latest_closed_by_id' => nil
+ }
+ end
+
+ it 'does not raise errors' do
+ expect { created_object }.not_to raise_error
+ end
+ end
+
context 'Project references' do
let(:relation_sym) { :project_foo_model }
let(:relation_hash) do
diff --git a/spec/lib/gitlab/import_export/safe_model_attributes.yml b/spec/lib/gitlab/import_export/safe_model_attributes.yml
index 2619c6a10d8..2aebdc57f7c 100644
--- a/spec/lib/gitlab/import_export/safe_model_attributes.yml
+++ b/spec/lib/gitlab/import_export/safe_model_attributes.yml
@@ -165,6 +165,7 @@ MergeRequest:
- approvals_before_merge
- rebase_commit_sha
- time_estimate
+- squash
- last_edited_at
- last_edited_by_id
- head_pipeline_id
@@ -204,6 +205,19 @@ MergeRequestDiffFile:
- b_mode
- too_large
- binary
+MergeRequest::Metrics:
+- id
+- created_at
+- updated_at
+- merge_request_id
+- pipeline_id
+- latest_closed_by_id
+- latest_closed_at
+- merged_by_id
+- merged_at
+- latest_build_started_at
+- latest_build_finished_at
+- first_deployed_to_production_at
Ci::Pipeline:
- id
- project_id
diff --git a/spec/lib/mattermost/command_spec.rb b/spec/lib/mattermost/command_spec.rb
index 8ba15ae0f38..7c194749dfb 100644
--- a/spec/lib/mattermost/command_spec.rb
+++ b/spec/lib/mattermost/command_spec.rb
@@ -21,13 +21,13 @@ describe Mattermost::Command do
context 'for valid trigger word' do
before do
- stub_request(:post, 'http://mattermost.example.com/api/v3/teams/abc/commands/create')
+ stub_request(:post, 'http://mattermost.example.com/api/v4/commands')
.with(body: {
team_id: 'abc',
trigger: 'gitlab'
}.to_json)
.to_return(
- status: 200,
+ status: 201,
headers: { 'Content-Type' => 'application/json' },
body: { token: 'token' }.to_json
)
@@ -40,16 +40,16 @@ describe Mattermost::Command do
context 'for error message' do
before do
- stub_request(:post, 'http://mattermost.example.com/api/v3/teams/abc/commands/create')
+ stub_request(:post, 'http://mattermost.example.com/api/v4/commands')
.to_return(
- status: 500,
+ status: 400,
headers: { 'Content-Type' => 'application/json' },
body: {
id: 'api.command.duplicate_trigger.app_error',
message: 'This trigger word is already in use. Please choose another word.',
detailed_error: '',
request_id: 'obc374man7bx5r3dbc1q5qhf3r',
- status_code: 500
+ status_code: 400
}.to_json
)
end
diff --git a/spec/lib/mattermost/session_spec.rb b/spec/lib/mattermost/session_spec.rb
index c855643c4d8..5410bfbeb31 100644
--- a/spec/lib/mattermost/session_spec.rb
+++ b/spec/lib/mattermost/session_spec.rb
@@ -22,8 +22,8 @@ describe Mattermost::Session, type: :request do
let(:location) { 'http://location.tld' }
let(:cookie_header) {'MMOAUTH=taskik8az7rq8k6rkpuas7htia; Path=/;'}
let!(:stub) do
- WebMock.stub_request(:get, "#{mattermost_url}/api/v3/oauth/gitlab/login")
- .to_return(headers: { 'location' => location, 'Set-Cookie' => cookie_header }, status: 307)
+ WebMock.stub_request(:get, "#{mattermost_url}/oauth/gitlab/login")
+ .to_return(headers: { 'location' => location, 'Set-Cookie' => cookie_header }, status: 302)
end
context 'without oauth uri' do
@@ -76,7 +76,7 @@ describe Mattermost::Session, type: :request do
end
end
- WebMock.stub_request(:post, "#{mattermost_url}/api/v3/users/logout")
+ WebMock.stub_request(:post, "#{mattermost_url}/api/v4/users/logout")
.to_return(headers: { Authorization: 'token thisworksnow' }, status: 200)
end
diff --git a/spec/lib/mattermost/team_spec.rb b/spec/lib/mattermost/team_spec.rb
index 2cfa6802612..030aa5d06a8 100644
--- a/spec/lib/mattermost/team_spec.rb
+++ b/spec/lib/mattermost/team_spec.rb
@@ -12,26 +12,28 @@ describe Mattermost::Team do
describe '#all' do
subject { described_class.new(nil).all }
+ let(:test_team) do
+ {
+ "id" => "xiyro8huptfhdndadpz8r3wnbo",
+ "create_at" => 1482174222155,
+ "update_at" => 1482174222155,
+ "delete_at" => 0,
+ "display_name" => "chatops",
+ "name" => "chatops",
+ "email" => "admin@example.com",
+ "type" => "O",
+ "company_name" => "",
+ "allowed_domains" => "",
+ "invite_id" => "o4utakb9jtb7imctdfzbf9r5ro",
+ "allow_open_invite" => false
+ }
+ end
+
context 'for valid request' do
- let(:response) do
- { "xiyro8huptfhdndadpz8r3wnbo" => {
- "id" => "xiyro8huptfhdndadpz8r3wnbo",
- "create_at" => 1482174222155,
- "update_at" => 1482174222155,
- "delete_at" => 0,
- "display_name" => "chatops",
- "name" => "chatops",
- "email" => "admin@example.com",
- "type" => "O",
- "company_name" => "",
- "allowed_domains" => "",
- "invite_id" => "o4utakb9jtb7imctdfzbf9r5ro",
- "allow_open_invite" => false
- } }
- end
+ let(:response) { [test_team] }
before do
- stub_request(:get, 'http://mattermost.example.com/api/v3/teams/all')
+ stub_request(:get, 'http://mattermost.example.com/api/v4/users/me/teams')
.to_return(
status: 200,
headers: { 'Content-Type' => 'application/json' },
@@ -39,14 +41,14 @@ describe Mattermost::Team do
)
end
- it 'returns a token' do
- is_expected.to eq(response.values)
+ it 'returns teams' do
+ is_expected.to eq(response)
end
end
context 'for error message' do
before do
- stub_request(:get, 'http://mattermost.example.com/api/v3/teams/all')
+ stub_request(:get, 'http://mattermost.example.com/api/v4/users/me/teams')
.to_return(
status: 500,
headers: { 'Content-Type' => 'application/json' },
@@ -89,9 +91,9 @@ describe Mattermost::Team do
end
before do
- stub_request(:post, "http://mattermost.example.com/api/v3/teams/create")
+ stub_request(:post, "http://mattermost.example.com/api/v4/teams")
.to_return(
- status: 200,
+ status: 201,
body: response.to_json,
headers: { 'Content-Type' => 'application/json' }
)
@@ -104,7 +106,7 @@ describe Mattermost::Team do
context 'for existing team' do
before do
- stub_request(:post, 'http://mattermost.example.com/api/v3/teams/create')
+ stub_request(:post, 'http://mattermost.example.com/api/v4/teams')
.to_return(
status: 400,
headers: { 'Content-Type' => 'application/json' },
diff --git a/spec/migrations/migrate_remaining_mr_metrics_populating_background_migration_spec.rb b/spec/migrations/migrate_remaining_mr_metrics_populating_background_migration_spec.rb
new file mode 100644
index 00000000000..47dab18183c
--- /dev/null
+++ b/spec/migrations/migrate_remaining_mr_metrics_populating_background_migration_spec.rb
@@ -0,0 +1,36 @@
+require 'spec_helper'
+require Rails.root.join('db', 'post_migrate', '20180521162137_migrate_remaining_mr_metrics_populating_background_migration.rb')
+
+describe MigrateRemainingMrMetricsPopulatingBackgroundMigration, :migration, :sidekiq do
+ let(:namespaces) { table(:namespaces) }
+ let(:projects) { table(:projects) }
+ let(:mrs) { table(:merge_requests) }
+
+ before do
+ namespaces.create!(id: 1, name: 'foo', path: 'foo')
+ projects.create!(id: 123, name: 'gitlab1', path: 'gitlab1', namespace_id: 1)
+ projects.create!(id: 456, name: 'gitlab2', path: 'gitlab2', namespace_id: 1)
+ projects.create!(id: 789, name: 'gitlab3', path: 'gitlab3', namespace_id: 1)
+ mrs.create!(title: 'foo', target_branch: 'target', source_branch: 'source', target_project_id: 123)
+ mrs.create!(title: 'bar', target_branch: 'target', source_branch: 'source', target_project_id: 456)
+ mrs.create!(title: 'kux', target_branch: 'target', source_branch: 'source', target_project_id: 789)
+ end
+
+ it 'correctly schedules background migrations' do
+ stub_const("#{described_class.name}::BATCH_SIZE", 2)
+
+ Sidekiq::Testing.fake! do
+ Timecop.freeze do
+ migrate!
+
+ expect(described_class::MIGRATION)
+ .to be_scheduled_delayed_migration(10.minutes, mrs.first.id, mrs.second.id)
+
+ expect(described_class::MIGRATION)
+ .to be_scheduled_delayed_migration(20.minutes, mrs.third.id, mrs.third.id)
+
+ expect(BackgroundMigrationWorker.jobs.size).to eq(2)
+ end
+ end
+ end
+end
diff --git a/spec/models/application_setting_spec.rb b/spec/models/application_setting_spec.rb
index f8f07205623..968267a6d24 100644
--- a/spec/models/application_setting_spec.rb
+++ b/spec/models/application_setting_spec.rb
@@ -195,22 +195,6 @@ describe ApplicationSetting do
expect(setting.pick_repository_storage).to eq('random')
end
-
- describe '#repository_storage' do
- it 'returns the first storage' do
- setting.repository_storages = %w(good bad)
-
- expect(setting.repository_storage).to eq('good')
- end
- end
-
- describe '#repository_storage=' do
- it 'overwrites repository_storages' do
- setting.repository_storage = 'overwritten'
-
- expect(setting.repository_storages).to eq(['overwritten'])
- end
- end
end
end
diff --git a/spec/models/concerns/token_authenticatable_spec.rb b/spec/models/concerns/token_authenticatable_spec.rb
index dfb83578fce..9b804429138 100644
--- a/spec/models/concerns/token_authenticatable_spec.rb
+++ b/spec/models/concerns/token_authenticatable_spec.rb
@@ -12,7 +12,7 @@ shared_examples 'TokenAuthenticatable' do
end
describe User, 'TokenAuthenticatable' do
- let(:token_field) { :rss_token }
+ let(:token_field) { :feed_token }
it_behaves_like 'TokenAuthenticatable'
describe 'ensures authentication token' do
diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb
index aa968dda41f..65cc9372cbe 100644
--- a/spec/models/merge_request_spec.rb
+++ b/spec/models/merge_request_spec.rb
@@ -14,6 +14,65 @@ describe MergeRequest do
it { is_expected.to have_many(:merge_request_diffs) }
end
+ describe '#squash_in_progress?' do
+ shared_examples 'checking whether a squash is in progress' do
+ let(:repo_path) { subject.source_project.repository.path }
+ let(:squash_path) { File.join(repo_path, "gitlab-worktree", "squash-#{subject.id}") }
+
+ before do
+ system(*%W(#{Gitlab.config.git.bin_path} -C #{repo_path} worktree add --detach #{squash_path} master))
+ end
+
+ it 'returns true when there is a current squash directory' do
+ expect(subject.squash_in_progress?).to be_truthy
+ end
+
+ it 'returns false when there is no squash directory' do
+ FileUtils.rm_rf(squash_path)
+
+ expect(subject.squash_in_progress?).to be_falsey
+ end
+
+ it 'returns false when the squash directory has expired' do
+ time = 20.minutes.ago.to_time
+ File.utime(time, time, squash_path)
+
+ expect(subject.squash_in_progress?).to be_falsey
+ end
+
+ it 'returns false when the source project has been removed' do
+ allow(subject).to receive(:source_project).and_return(nil)
+
+ expect(subject.squash_in_progress?).to be_falsey
+ end
+ end
+
+ context 'when Gitaly squash_in_progress is enabled' do
+ it_behaves_like 'checking whether a squash is in progress'
+ end
+
+ context 'when Gitaly squash_in_progress is disabled', :disable_gitaly do
+ it_behaves_like 'checking whether a squash is in progress'
+ end
+ end
+
+ describe '#squash?' do
+ let(:merge_request) { build(:merge_request, squash: squash) }
+ subject { merge_request.squash? }
+
+ context 'disabled in database' do
+ let(:squash) { false }
+
+ it { is_expected.to be_falsy }
+ end
+
+ context 'enabled in database' do
+ let(:squash) { true }
+
+ it { is_expected.to be_truthy }
+ end
+ end
+
describe 'modules' do
subject { described_class }
diff --git a/spec/models/project_services/kubernetes_service_spec.rb b/spec/models/project_services/kubernetes_service_spec.rb
index 3be023a48c1..68ab9fd08ec 100644
--- a/spec/models/project_services/kubernetes_service_spec.rb
+++ b/spec/models/project_services/kubernetes_service_spec.rb
@@ -65,7 +65,7 @@ describe KubernetesService, :use_clean_rails_memory_store_caching do
before do
kubernetes_service.update_attribute(:active, false)
- kubernetes_service.properties[:namespace] = "foo"
+ kubernetes_service.properties['namespace'] = "foo"
end
it 'should not update attributes' do
@@ -82,7 +82,7 @@ describe KubernetesService, :use_clean_rails_memory_store_caching do
let(:kubernetes_service) { create(:kubernetes_service) }
it 'should update attributes' do
- kubernetes_service.properties[:namespace] = 'foo'
+ kubernetes_service.properties['namespace'] = 'foo'
expect(kubernetes_service.save).to be_truthy
end
end
@@ -92,7 +92,7 @@ describe KubernetesService, :use_clean_rails_memory_store_caching do
before do
kubernetes_service.active = false
- kubernetes_service.properties[:namespace] = 'foo'
+ kubernetes_service.properties['namespace'] = 'foo'
kubernetes_service.save
end
@@ -105,7 +105,7 @@ describe KubernetesService, :use_clean_rails_memory_store_caching do
end
it 'should update attributes' do
- expect(kubernetes_service.properties[:namespace]).to eq("foo")
+ expect(kubernetes_service.properties['namespace']).to eq("foo")
end
end
@@ -113,12 +113,12 @@ describe KubernetesService, :use_clean_rails_memory_store_caching do
let(:kubernetes_service) { create(:kubernetes_service, template: true, active: false) }
before do
- kubernetes_service.properties[:namespace] = 'foo'
+ kubernetes_service.properties['namespace'] = 'foo'
end
it 'should update attributes' do
expect(kubernetes_service.save).to be_truthy
- expect(kubernetes_service.properties[:namespace]).to eq('foo')
+ expect(kubernetes_service.properties['namespace']).to eq('foo')
end
end
end
diff --git a/spec/models/project_services/mattermost_slash_commands_service_spec.rb b/spec/models/project_services/mattermost_slash_commands_service_spec.rb
index 05d33cd3874..1983e0cc967 100644
--- a/spec/models/project_services/mattermost_slash_commands_service_spec.rb
+++ b/spec/models/project_services/mattermost_slash_commands_service_spec.rb
@@ -25,7 +25,7 @@ describe MattermostSlashCommandsService do
context 'the requests succeeds' do
before do
- stub_request(:post, 'http://mattermost.example.com/api/v3/teams/abc/commands/create')
+ stub_request(:post, 'http://mattermost.example.com/api/v4/commands')
.with(body: {
team_id: 'abc',
trigger: 'gitlab',
@@ -59,7 +59,7 @@ describe MattermostSlashCommandsService do
context 'an error is received' do
before do
- stub_request(:post, 'http://mattermost.example.com/api/v3/teams/abc/commands/create')
+ stub_request(:post, 'http://mattermost.example.com/api/v4/commands')
.to_return(
status: 500,
headers: { 'Content-Type' => 'application/json' },
@@ -89,11 +89,11 @@ describe MattermostSlashCommandsService do
context 'the requests succeeds' do
before do
- stub_request(:get, 'http://mattermost.example.com/api/v3/teams/all')
+ stub_request(:get, 'http://mattermost.example.com/api/v4/users/me/teams')
.to_return(
status: 200,
headers: { 'Content-Type' => 'application/json' },
- body: { 'list' => true }.to_json
+ body: [{ id: 'test_team_id' }].to_json
)
end
@@ -104,7 +104,7 @@ describe MattermostSlashCommandsService do
context 'an error is received' do
before do
- stub_request(:get, 'http://mattermost.example.com/api/v3/teams/all')
+ stub_request(:get, 'http://mattermost.example.com/api/v4/users/me/teams')
.to_return(
status: 500,
headers: { 'Content-Type' => 'application/json' },
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index 6a2f4a39f09..16b409844fa 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -644,13 +644,13 @@ describe User do
end
end
- describe 'rss token' do
- it 'ensures an rss token on read' do
- user = create(:user, rss_token: nil)
- rss_token = user.rss_token
+ describe 'feed token' do
+ it 'ensures a feed token on read' do
+ user = create(:user, feed_token: nil)
+ feed_token = user.feed_token
- expect(rss_token).not_to be_blank
- expect(user.reload.rss_token).to eq rss_token
+ expect(feed_token).not_to be_blank
+ expect(user.reload.feed_token).to eq feed_token
end
end
diff --git a/spec/presenters/ci/build_presenter_spec.rb b/spec/presenters/ci/build_presenter_spec.rb
index efd175247b5..6dfaa3b72f7 100644
--- a/spec/presenters/ci/build_presenter_spec.rb
+++ b/spec/presenters/ci/build_presenter_spec.rb
@@ -219,11 +219,11 @@ describe Ci::BuildPresenter do
end
describe '#callout_failure_message' do
- let(:build) { create(:ci_build, :failed, :script_failure) }
+ let(:build) { create(:ci_build, :failed, :api_failure) }
it 'returns a verbose failure reason' do
description = subject.callout_failure_message
- expect(description).to eq('There has been a script failure. Check the job log for more information')
+ expect(description).to eq('There has been an API failure, please try again')
end
end
diff --git a/spec/requests/api/merge_requests_spec.rb b/spec/requests/api/merge_requests_spec.rb
index 1eeeb4f1045..605761867bf 100644
--- a/spec/requests/api/merge_requests_spec.rb
+++ b/spec/requests/api/merge_requests_spec.rb
@@ -29,6 +29,18 @@ describe API::MergeRequests do
project.add_reporter(user)
end
+ describe 'route shadowing' do
+ include GrapePathHelpers::NamedRouteMatcher
+
+ it 'does not occur' do
+ path = api_v4_projects_merge_requests_path(id: 1)
+ expect(path).to eq('/api/v4/projects/1/merge_requests')
+
+ path = api_v4_projects_merge_requests_path(id: 1, merge_request_iid: 3)
+ expect(path).to eq('/api/v4/projects/1/merge_requests/3')
+ end
+ end
+
describe 'GET /merge_requests' do
context 'when unauthenticated' do
it 'returns an array of all merge requests' do
@@ -60,12 +72,6 @@ describe API::MergeRequests do
expect(response).to have_gitlab_http_status(401)
end
-
- it "returns authentication error when scope is created_by_me" do
- get api("/merge_requests"), scope: 'created_by_me'
-
- expect(response).to have_gitlab_http_status(401)
- end
end
context 'when authenticated' do
@@ -217,223 +223,46 @@ describe API::MergeRequests do
end
describe "GET /projects/:id/merge_requests" do
- context "when unauthenticated" do
- it 'returns merge requests for public projects' do
- get api("/projects/#{project.id}/merge_requests")
-
- expect_paginated_array_response
- end
-
- it "returns 404 for non public projects" do
- project = create(:project, :private)
- get api("/projects/#{project.id}/merge_requests")
-
- expect(response).to have_gitlab_http_status(404)
- end
- end
-
- context "when authenticated" do
- it 'avoids N+1 queries' do
- control = ActiveRecord::QueryRecorder.new do
- get api("/projects/#{project.id}/merge_requests", user)
- end
-
- create(:merge_request, state: 'closed', milestone: milestone1, author: user, assignee: user, source_project: project, target_project: project, title: "Test", created_at: base_time)
-
- create(:merge_request, milestone: milestone1, author: user, assignee: user, source_project: project, target_project: project, title: "Test", created_at: base_time)
-
- expect do
- get api("/projects/#{project.id}/merge_requests", user)
- end.not_to exceed_query_limit(control)
- end
-
- it "returns an array of all merge_requests" do
- get api("/projects/#{project.id}/merge_requests", user)
-
- expect_response_ordered_exactly(merge_request_merged, merge_request_closed, merge_request)
- expect(json_response.last['title']).to eq(merge_request.title)
- expect(json_response.last).to have_key('web_url')
- expect(json_response.last['sha']).to eq(merge_request.diff_head_sha)
- expect(json_response.last['merge_commit_sha']).to be_nil
- expect(json_response.last['merge_commit_sha']).to eq(merge_request.merge_commit_sha)
- expect(json_response.last['downvotes']).to eq(1)
- expect(json_response.last['upvotes']).to eq(1)
- expect(json_response.last['labels']).to eq([label2.title, label.title])
- expect(json_response.first['title']).to eq(merge_request_merged.title)
- expect(json_response.first['sha']).to eq(merge_request_merged.diff_head_sha)
- expect(json_response.first['merge_commit_sha']).not_to be_nil
- expect(json_response.first['merge_commit_sha']).to eq(merge_request_merged.merge_commit_sha)
- end
-
- it "returns an array of all merge_requests using simple mode" do
- get api("/projects/#{project.id}/merge_requests?view=simple", user)
-
- expect_response_ordered_exactly(merge_request_merged, merge_request_closed, merge_request)
- expect(json_response.last.keys).to match_array(%w(id iid title web_url created_at description project_id state updated_at))
- expect(json_response.last['iid']).to eq(merge_request.iid)
- expect(json_response.last['title']).to eq(merge_request.title)
- expect(json_response.last).to have_key('web_url')
- expect(json_response.first['iid']).to eq(merge_request_merged.iid)
- expect(json_response.first['title']).to eq(merge_request_merged.title)
- expect(json_response.first).to have_key('web_url')
- end
-
- it "returns an array of all merge_requests" do
- get api("/projects/#{project.id}/merge_requests?state", user)
-
- expect_response_ordered_exactly(merge_request_merged, merge_request_closed, merge_request)
- expect(json_response.last['title']).to eq(merge_request.title)
- end
-
- it "returns an array of open merge_requests" do
- get api("/projects/#{project.id}/merge_requests?state=opened", user)
-
- expect_response_ordered_exactly(merge_request)
- expect(json_response.last['title']).to eq(merge_request.title)
- end
-
- it "returns an array of closed merge_requests" do
- get api("/projects/#{project.id}/merge_requests?state=closed", user)
-
- expect_response_ordered_exactly(merge_request_closed)
- expect(json_response.first['title']).to eq(merge_request_closed.title)
- end
-
- it "returns an array of merged merge_requests" do
- get api("/projects/#{project.id}/merge_requests?state=merged", user)
-
- expect_response_ordered_exactly(merge_request_merged)
- expect(json_response.first['title']).to eq(merge_request_merged.title)
- end
-
- it 'returns merge_request by "iids" array' do
- get api("/projects/#{project.id}/merge_requests", user), iids: [merge_request.iid, merge_request_closed.iid]
-
- expect_response_ordered_exactly(merge_request_closed, merge_request)
- expect(json_response.first['title']).to eq merge_request_closed.title
- end
-
- it 'matches V4 response schema' do
- get api("/projects/#{project.id}/merge_requests", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(response).to match_response_schema('public_api/v4/merge_requests')
- end
-
- it 'returns an empty array if no issue matches milestone' do
- get api("/projects/#{project.id}/merge_requests", user), milestone: '1.0.0'
-
- expect_paginated_array_response
- expect(json_response.length).to eq(0)
- end
-
- it 'returns an empty array if milestone does not exist' do
- get api("/projects/#{project.id}/merge_requests", user), milestone: 'foo'
-
- expect_paginated_array_response
- expect(json_response.length).to eq(0)
- end
-
- it 'returns an array of merge requests in given milestone' do
- get api("/projects/#{project.id}/merge_requests", user), milestone: '0.9'
-
- expect(json_response.first['title']).to eq merge_request_closed.title
- expect(json_response.first['id']).to eq merge_request_closed.id
- end
-
- it 'returns an array of merge requests matching state in milestone' do
- get api("/projects/#{project.id}/merge_requests", user), milestone: '0.9', state: 'closed'
-
- expect_response_ordered_exactly(merge_request_closed)
- end
-
- it 'returns an array of labeled merge requests' do
- get api("/projects/#{project.id}/merge_requests?labels=#{label.title}", user)
-
- expect_paginated_array_response
- expect(json_response.length).to eq(1)
- expect(json_response.first['labels']).to eq([label2.title, label.title])
- end
-
- it 'returns an array of labeled merge requests where all labels match' do
- get api("/projects/#{project.id}/merge_requests?labels=#{label.title},foo,bar", user)
-
- expect_paginated_array_response
- expect(json_response.length).to eq(0)
- end
-
- it 'returns an empty array if no merge request matches labels' do
- get api("/projects/#{project.id}/merge_requests?labels=foo,bar", user)
-
- expect_paginated_array_response
- expect(json_response.length).to eq(0)
- end
-
- it 'returns an array of labeled merge requests that are merged for a milestone' do
- bug_label = create(:label, title: 'bug', color: '#FFAABB', project: project)
-
- mr1 = create(:merge_request, state: "merged", source_project: project, target_project: project, milestone: milestone)
- mr2 = create(:merge_request, state: "merged", source_project: project, target_project: project, milestone: milestone1)
- mr3 = create(:merge_request, state: "closed", source_project: project, target_project: project, milestone: milestone1)
- _mr = create(:merge_request, state: "merged", source_project: project, target_project: project, milestone: milestone1)
+ let(:endpoint_path) { "/projects/#{project.id}/merge_requests" }
- create(:label_link, label: bug_label, target: mr1)
- create(:label_link, label: bug_label, target: mr2)
- create(:label_link, label: bug_label, target: mr3)
+ it_behaves_like 'merge requests list'
- get api("/projects/#{project.id}/merge_requests?labels=#{bug_label.title}&milestone=#{milestone1.title}&state=merged", user)
-
- expect_response_ordered_exactly(mr2)
- end
-
- context "with ordering" do
- let(:merge_requests) { [merge_request_merged, merge_request_closed, merge_request] }
-
- before do
- @mr_later = mr_with_later_created_and_updated_at_time
- @mr_earlier = mr_with_earlier_created_and_updated_at_time
- end
-
- it "returns an array of merge_requests in ascending order" do
- get api("/projects/#{project.id}/merge_requests?sort=asc", user)
-
- expect_response_ordered_exactly(*merge_requests.sort_by { |mr| mr['created_at'] })
- end
-
- it "returns an array of merge_requests in descending order" do
- get api("/projects/#{project.id}/merge_requests?sort=desc", user)
+ it "returns 404 for non public projects" do
+ project = create(:project, :private)
- expect_response_ordered_exactly(*merge_requests.sort_by { |mr| mr['created_at'] }.reverse)
- end
+ get api("/projects/#{project.id}/merge_requests")
- it "returns an array of merge_requests ordered by updated_at" do
- get api("/projects/#{project.id}/merge_requests?order_by=updated_at", user)
+ expect(response).to have_gitlab_http_status(404)
+ end
- expect_response_ordered_exactly(*merge_requests.sort_by { |mr| mr['updated_at'] }.reverse)
- end
+ it 'returns merge_request by "iids" array' do
+ get api(endpoint_path, user), iids: [merge_request.iid, merge_request_closed.iid]
- it "returns an array of merge_requests ordered by created_at" do
- get api("/projects/#{project.id}/merge_requests?order_by=created_at&sort=asc", user)
+ expect(response).to have_gitlab_http_status(200)
+ expect(json_response).to be_an Array
+ expect(json_response.length).to eq(2)
+ expect(json_response.first['title']).to eq merge_request_closed.title
+ expect(json_response.first['id']).to eq merge_request_closed.id
+ end
+ end
- expect_response_ordered_exactly(*merge_requests.sort_by { |mr| mr['created_at'] })
- end
- end
+ describe "GET /groups/:id/merge_requests" do
+ let!(:group) { create(:group, :public) }
+ let!(:project) { create(:project, :public, :repository, creator: user, namespace: group, only_allow_merge_if_pipeline_succeeds: false) }
+ let(:endpoint_path) { "/groups/#{group.id}/merge_requests" }
- context 'source_branch param' do
- it 'returns merge requests with the given source branch' do
- get api('/merge_requests', user), source_branch: merge_request_closed.source_branch, state: 'all'
+ before do
+ group.add_reporter(user)
+ end
- expect_response_contain_exactly(merge_request_closed, merge_request_merged)
- end
- end
+ it_behaves_like 'merge requests list'
- context 'target_branch param' do
- it 'returns merge requests with the given target branch' do
- get api('/merge_requests', user), target_branch: merge_request_closed.target_branch, state: 'all'
+ context 'when have subgroups', :nested_groups do
+ let!(:group) { create(:group, :public) }
+ let!(:subgroup) { create(:group, parent: group) }
+ let!(:project) { create(:project, :public, :repository, creator: user, namespace: subgroup, only_allow_merge_if_pipeline_succeeds: false) }
- expect_response_contain_exactly(merge_request_closed, merge_request_merged)
- end
- end
+ it_behaves_like 'merge requests list'
end
end
@@ -671,12 +500,14 @@ describe API::MergeRequests do
target_branch: 'master',
author: user,
labels: 'label, label2',
- milestone_id: milestone.id
+ milestone_id: milestone.id,
+ squash: true
expect(response).to have_gitlab_http_status(201)
expect(json_response['title']).to eq('Test merge_request')
expect(json_response['labels']).to eq(%w(label label2))
expect(json_response['milestone']['id']).to eq(milestone.id)
+ expect(json_response['squash']).to be_truthy
expect(json_response['force_remove_source_branch']).to be_falsy
end
@@ -965,6 +796,14 @@ describe API::MergeRequests do
expect(response).to have_gitlab_http_status(200)
end
+ it "updates the MR's squash attribute" do
+ expect do
+ put api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/merge", user), squash: true
+ end.to change { merge_request.reload.squash }
+
+ expect(response).to have_gitlab_http_status(200)
+ end
+
it "enables merge when pipeline succeeds if the pipeline is active" do
allow_any_instance_of(MergeRequest).to receive(:head_pipeline).and_return(pipeline)
allow(pipeline).to receive(:active?).and_return(true)
@@ -1029,6 +868,13 @@ describe API::MergeRequests do
expect(json_response['milestone']['id']).to eq(milestone.id)
end
+ it "updates squash and returns merge_request" do
+ put api("/projects/#{project.id}/merge_requests/#{merge_request.iid}", user), squash: true
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(json_response['squash']).to be_truthy
+ end
+
it "returns merge_request with renamed target_branch" do
put api("/projects/#{project.id}/merge_requests/#{merge_request.iid}", user), target_branch: "wiki"
expect(response).to have_gitlab_http_status(200)
diff --git a/spec/requests/api/v3/award_emoji_spec.rb b/spec/requests/api/v3/award_emoji_spec.rb
deleted file mode 100644
index 6dc430676b0..00000000000
--- a/spec/requests/api/v3/award_emoji_spec.rb
+++ /dev/null
@@ -1,297 +0,0 @@
-require 'spec_helper'
-
-describe API::V3::AwardEmoji do
- set(:user) { create(:user) }
- set(:project) { create(:project) }
- set(:issue) { create(:issue, project: project) }
- set(:award_emoji) { create(:award_emoji, awardable: issue, user: user) }
- let!(:merge_request) { create(:merge_request, source_project: project, target_project: project) }
- let!(:downvote) { create(:award_emoji, :downvote, awardable: merge_request, user: user) }
- set(:note) { create(:note, project: project, noteable: issue) }
-
- before { project.add_master(user) }
-
- describe "GET /projects/:id/awardable/:awardable_id/award_emoji" do
- context 'on an issue' do
- it "returns an array of award_emoji" do
- get v3_api("/projects/#{project.id}/issues/#{issue.id}/award_emoji", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.first['name']).to eq(award_emoji.name)
- end
-
- it "returns a 404 error when issue id not found" do
- get v3_api("/projects/#{project.id}/issues/12345/award_emoji", user)
-
- expect(response).to have_gitlab_http_status(404)
- end
- end
-
- context 'on a merge request' do
- it "returns an array of award_emoji" do
- get v3_api("/projects/#{project.id}/merge_requests/#{merge_request.id}/award_emoji", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response.first['name']).to eq(downvote.name)
- end
- end
-
- context 'on a snippet' do
- let(:snippet) { create(:project_snippet, :public, project: project) }
- let!(:award) { create(:award_emoji, awardable: snippet) }
-
- it 'returns the awarded emoji' do
- get v3_api("/projects/#{project.id}/snippets/#{snippet.id}/award_emoji", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.first['name']).to eq(award.name)
- end
- end
-
- context 'when the user has no access' do
- it 'returns a status code 404' do
- user1 = create(:user)
-
- get v3_api("/projects/#{project.id}/merge_requests/#{merge_request.id}/award_emoji", user1)
-
- expect(response).to have_gitlab_http_status(404)
- end
- end
- end
-
- describe 'GET /projects/:id/awardable/:awardable_id/notes/:note_id/award_emoji' do
- let!(:rocket) { create(:award_emoji, awardable: note, name: 'rocket') }
-
- it 'returns an array of award emoji' do
- get v3_api("/projects/#{project.id}/issues/#{issue.id}/notes/#{note.id}/award_emoji", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.first['name']).to eq(rocket.name)
- end
- end
-
- describe "GET /projects/:id/awardable/:awardable_id/award_emoji/:award_id" do
- context 'on an issue' do
- it "returns the award emoji" do
- get v3_api("/projects/#{project.id}/issues/#{issue.id}/award_emoji/#{award_emoji.id}", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['name']).to eq(award_emoji.name)
- expect(json_response['awardable_id']).to eq(issue.id)
- expect(json_response['awardable_type']).to eq("Issue")
- end
-
- it "returns a 404 error if the award is not found" do
- get v3_api("/projects/#{project.id}/issues/#{issue.id}/award_emoji/12345", user)
-
- expect(response).to have_gitlab_http_status(404)
- end
- end
-
- context 'on a merge request' do
- it 'returns the award emoji' do
- get v3_api("/projects/#{project.id}/merge_requests/#{merge_request.id}/award_emoji/#{downvote.id}", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['name']).to eq(downvote.name)
- expect(json_response['awardable_id']).to eq(merge_request.id)
- expect(json_response['awardable_type']).to eq("MergeRequest")
- end
- end
-
- context 'on a snippet' do
- let(:snippet) { create(:project_snippet, :public, project: project) }
- let!(:award) { create(:award_emoji, awardable: snippet) }
-
- it 'returns the awarded emoji' do
- get v3_api("/projects/#{project.id}/snippets/#{snippet.id}/award_emoji/#{award.id}", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['name']).to eq(award.name)
- expect(json_response['awardable_id']).to eq(snippet.id)
- expect(json_response['awardable_type']).to eq("Snippet")
- end
- end
-
- context 'when the user has no access' do
- it 'returns a status code 404' do
- user1 = create(:user)
-
- get v3_api("/projects/#{project.id}/merge_requests/#{merge_request.id}/award_emoji/#{downvote.id}", user1)
-
- expect(response).to have_gitlab_http_status(404)
- end
- end
- end
-
- describe 'GET /projects/:id/awardable/:awardable_id/notes/:note_id/award_emoji/:award_id' do
- let!(:rocket) { create(:award_emoji, awardable: note, name: 'rocket') }
-
- it 'returns an award emoji' do
- get v3_api("/projects/#{project.id}/issues/#{issue.id}/notes/#{note.id}/award_emoji/#{rocket.id}", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).not_to be_an Array
- expect(json_response['name']).to eq(rocket.name)
- end
- end
-
- describe "POST /projects/:id/awardable/:awardable_id/award_emoji" do
- let(:issue2) { create(:issue, project: project, author: user) }
-
- context "on an issue" do
- it "creates a new award emoji" do
- post v3_api("/projects/#{project.id}/issues/#{issue.id}/award_emoji", user), name: 'blowfish'
-
- expect(response).to have_gitlab_http_status(201)
- expect(json_response['name']).to eq('blowfish')
- expect(json_response['user']['username']).to eq(user.username)
- end
-
- it "returns a 400 bad request error if the name is not given" do
- post v3_api("/projects/#{project.id}/issues/#{issue.id}/award_emoji", user)
-
- expect(response).to have_gitlab_http_status(400)
- end
-
- it "returns a 401 unauthorized error if the user is not authenticated" do
- post v3_api("/projects/#{project.id}/issues/#{issue.id}/award_emoji"), name: 'thumbsup'
-
- expect(response).to have_gitlab_http_status(401)
- end
-
- it "returns a 404 error if the user authored issue" do
- post v3_api("/projects/#{project.id}/issues/#{issue2.id}/award_emoji", user), name: 'thumbsup'
-
- expect(response).to have_gitlab_http_status(404)
- end
-
- it "normalizes +1 as thumbsup award" do
- post v3_api("/projects/#{project.id}/issues/#{issue.id}/award_emoji", user), name: '+1'
-
- expect(issue.award_emoji.last.name).to eq("thumbsup")
- end
-
- context 'when the emoji already has been awarded' do
- it 'returns a 404 status code' do
- post v3_api("/projects/#{project.id}/issues/#{issue.id}/award_emoji", user), name: 'thumbsup'
- post v3_api("/projects/#{project.id}/issues/#{issue.id}/award_emoji", user), name: 'thumbsup'
-
- expect(response).to have_gitlab_http_status(404)
- expect(json_response["message"]).to match("has already been taken")
- end
- end
- end
-
- context 'on a snippet' do
- it 'creates a new award emoji' do
- snippet = create(:project_snippet, :public, project: project)
-
- post v3_api("/projects/#{project.id}/snippets/#{snippet.id}/award_emoji", user), name: 'blowfish'
-
- expect(response).to have_gitlab_http_status(201)
- expect(json_response['name']).to eq('blowfish')
- expect(json_response['user']['username']).to eq(user.username)
- end
- end
- end
-
- describe "POST /projects/:id/awardable/:awardable_id/notes/:note_id/award_emoji" do
- let(:note2) { create(:note, project: project, noteable: issue, author: user) }
-
- it 'creates a new award emoji' do
- expect do
- post v3_api("/projects/#{project.id}/issues/#{issue.id}/notes/#{note.id}/award_emoji", user), name: 'rocket'
- end.to change { note.award_emoji.count }.from(0).to(1)
-
- expect(response).to have_gitlab_http_status(201)
- expect(json_response['user']['username']).to eq(user.username)
- end
-
- it "it returns 404 error when user authored note" do
- post v3_api("/projects/#{project.id}/issues/#{issue.id}/notes/#{note2.id}/award_emoji", user), name: 'thumbsup'
-
- expect(response).to have_gitlab_http_status(404)
- end
-
- it "normalizes +1 as thumbsup award" do
- post v3_api("/projects/#{project.id}/issues/#{issue.id}/notes/#{note.id}/award_emoji", user), name: '+1'
-
- expect(note.award_emoji.last.name).to eq("thumbsup")
- end
-
- context 'when the emoji already has been awarded' do
- it 'returns a 404 status code' do
- post v3_api("/projects/#{project.id}/issues/#{issue.id}/notes/#{note.id}/award_emoji", user), name: 'rocket'
- post v3_api("/projects/#{project.id}/issues/#{issue.id}/notes/#{note.id}/award_emoji", user), name: 'rocket'
-
- expect(response).to have_gitlab_http_status(404)
- expect(json_response["message"]).to match("has already been taken")
- end
- end
- end
-
- describe 'DELETE /projects/:id/awardable/:awardable_id/award_emoji/:award_id' do
- context 'when the awardable is an Issue' do
- it 'deletes the award' do
- expect do
- delete v3_api("/projects/#{project.id}/issues/#{issue.id}/award_emoji/#{award_emoji.id}", user)
-
- expect(response).to have_gitlab_http_status(200)
- end.to change { issue.award_emoji.count }.from(1).to(0)
- end
-
- it 'returns a 404 error when the award emoji can not be found' do
- delete v3_api("/projects/#{project.id}/issues/#{issue.id}/award_emoji/12345", user)
-
- expect(response).to have_gitlab_http_status(404)
- end
- end
-
- context 'when the awardable is a Merge Request' do
- it 'deletes the award' do
- expect do
- delete v3_api("/projects/#{project.id}/merge_requests/#{merge_request.id}/award_emoji/#{downvote.id}", user)
-
- expect(response).to have_gitlab_http_status(200)
- end.to change { merge_request.award_emoji.count }.from(1).to(0)
- end
-
- it 'returns a 404 error when note id not found' do
- delete v3_api("/projects/#{project.id}/merge_requests/#{merge_request.id}/notes/12345", user)
-
- expect(response).to have_gitlab_http_status(404)
- end
- end
-
- context 'when the awardable is a Snippet' do
- let(:snippet) { create(:project_snippet, :public, project: project) }
- let!(:award) { create(:award_emoji, awardable: snippet, user: user) }
-
- it 'deletes the award' do
- expect do
- delete v3_api("/projects/#{project.id}/snippets/#{snippet.id}/award_emoji/#{award.id}", user)
-
- expect(response).to have_gitlab_http_status(200)
- end.to change { snippet.award_emoji.count }.from(1).to(0)
- end
- end
- end
-
- describe 'DELETE /projects/:id/awardable/:awardable_id/award_emoji/:award_emoji_id' do
- let!(:rocket) { create(:award_emoji, awardable: note, name: 'rocket', user: user) }
-
- it 'deletes the award' do
- expect do
- delete v3_api("/projects/#{project.id}/issues/#{issue.id}/notes/#{note.id}/award_emoji/#{rocket.id}", user)
-
- expect(response).to have_gitlab_http_status(200)
- end.to change { note.award_emoji.count }.from(1).to(0)
- end
- end
-end
diff --git a/spec/requests/api/v3/boards_spec.rb b/spec/requests/api/v3/boards_spec.rb
deleted file mode 100644
index dde4f096193..00000000000
--- a/spec/requests/api/v3/boards_spec.rb
+++ /dev/null
@@ -1,114 +0,0 @@
-require 'spec_helper'
-
-describe API::V3::Boards do
- set(:user) { create(:user) }
- set(:guest) { create(:user) }
- set(:non_member) { create(:user) }
- set(:project) { create(:project, :public, creator_id: user.id, namespace: user.namespace ) }
-
- set(:dev_label) do
- create(:label, title: 'Development', color: '#FFAABB', project: project)
- end
-
- set(:test_label) do
- create(:label, title: 'Testing', color: '#FFAACC', project: project)
- end
-
- set(:dev_list) do
- create(:list, label: dev_label, position: 1)
- end
-
- set(:test_list) do
- create(:list, label: test_label, position: 2)
- end
-
- set(:board) do
- create(:board, project: project, lists: [dev_list, test_list])
- end
-
- before do
- project.add_reporter(user)
- project.add_guest(guest)
- end
-
- describe "GET /projects/:id/boards" do
- let(:base_url) { "/projects/#{project.id}/boards" }
-
- context "when unauthenticated" do
- it "returns authentication error" do
- get v3_api(base_url)
-
- expect(response).to have_gitlab_http_status(401)
- end
- end
-
- context "when authenticated" do
- it "returns the project issue board" do
- get v3_api(base_url, user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(1)
- expect(json_response.first['id']).to eq(board.id)
- expect(json_response.first['lists']).to be_an Array
- expect(json_response.first['lists'].length).to eq(2)
- expect(json_response.first['lists'].last).to have_key('position')
- end
- end
- end
-
- describe "GET /projects/:id/boards/:board_id/lists" do
- let(:base_url) { "/projects/#{project.id}/boards/#{board.id}/lists" }
-
- it 'returns issue board lists' do
- get v3_api(base_url, user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(2)
- expect(json_response.first['label']['name']).to eq(dev_label.title)
- end
-
- it 'returns 404 if board not found' do
- get v3_api("/projects/#{project.id}/boards/22343/lists", user)
-
- expect(response).to have_gitlab_http_status(404)
- end
- end
-
- describe "DELETE /projects/:id/board/lists/:list_id" do
- let(:base_url) { "/projects/#{project.id}/boards/#{board.id}/lists" }
-
- it "rejects a non member from deleting a list" do
- delete v3_api("#{base_url}/#{dev_list.id}", non_member)
-
- expect(response).to have_gitlab_http_status(403)
- end
-
- it "rejects a user with guest role from deleting a list" do
- delete v3_api("#{base_url}/#{dev_list.id}", guest)
-
- expect(response).to have_gitlab_http_status(403)
- end
-
- it "returns 404 error if list id not found" do
- delete v3_api("#{base_url}/44444", user)
-
- expect(response).to have_gitlab_http_status(404)
- end
-
- context "when the user is project owner" do
- set(:owner) { create(:user) }
-
- before do
- project.update(namespace: owner.namespace)
- end
-
- it "deletes the list if an admin requests it" do
- delete v3_api("#{base_url}/#{dev_list.id}", owner)
-
- expect(response).to have_gitlab_http_status(200)
- end
- end
- end
-end
diff --git a/spec/requests/api/v3/branches_spec.rb b/spec/requests/api/v3/branches_spec.rb
deleted file mode 100644
index 1e038595a1f..00000000000
--- a/spec/requests/api/v3/branches_spec.rb
+++ /dev/null
@@ -1,120 +0,0 @@
-require 'spec_helper'
-require 'mime/types'
-
-describe API::V3::Branches do
- set(:user) { create(:user) }
- set(:user2) { create(:user) }
- set(:project) { create(:project, :repository, creator: user) }
- set(:master) { create(:project_member, :master, user: user, project: project) }
- set(:guest) { create(:project_member, :guest, user: user2, project: project) }
- let!(:branch_name) { 'feature' }
- let!(:branch_sha) { '0b4bc9a49b562e85de7cc9e834518ea6828729b9' }
- let!(:branch_with_dot) { CreateBranchService.new(project, user).execute("with.1.2.3", "master") }
-
- describe "GET /projects/:id/repository/branches" do
- it "returns an array of project branches" do
- project.repository.expire_all_method_caches
-
- get v3_api("/projects/#{project.id}/repository/branches", user), per_page: 100
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- branch_names = json_response.map { |x| x['name'] }
- expect(branch_names).to match_array(project.repository.branch_names)
- end
- end
-
- describe "DELETE /projects/:id/repository/branches/:branch" do
- before do
- allow_any_instance_of(Repository).to receive(:rm_branch).and_return(true)
- end
-
- it "removes branch" do
- delete v3_api("/projects/#{project.id}/repository/branches/#{branch_name}", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['branch_name']).to eq(branch_name)
- end
-
- it "removes a branch with dots in the branch name" do
- delete v3_api("/projects/#{project.id}/repository/branches/with.1.2.3", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['branch_name']).to eq("with.1.2.3")
- end
-
- it 'returns 404 if branch not exists' do
- delete v3_api("/projects/#{project.id}/repository/branches/foobar", user)
- expect(response).to have_gitlab_http_status(404)
- end
- end
-
- describe "DELETE /projects/:id/repository/merged_branches" do
- before do
- allow_any_instance_of(Repository).to receive(:rm_branch).and_return(true)
- end
-
- it 'returns 200' do
- delete v3_api("/projects/#{project.id}/repository/merged_branches", user)
-
- expect(response).to have_gitlab_http_status(200)
- end
-
- it 'returns a 403 error if guest' do
- delete v3_api("/projects/#{project.id}/repository/merged_branches", user2)
-
- expect(response).to have_gitlab_http_status(403)
- end
- end
-
- describe "POST /projects/:id/repository/branches" do
- it "creates a new branch" do
- post v3_api("/projects/#{project.id}/repository/branches", user),
- branch_name: 'feature1',
- ref: branch_sha
-
- expect(response).to have_gitlab_http_status(201)
-
- expect(json_response['name']).to eq('feature1')
- expect(json_response['commit']['id']).to eq(branch_sha)
- end
-
- it "denies for user without push access" do
- post v3_api("/projects/#{project.id}/repository/branches", user2),
- branch_name: branch_name,
- ref: branch_sha
- expect(response).to have_gitlab_http_status(403)
- end
-
- it 'returns 400 if branch name is invalid' do
- post v3_api("/projects/#{project.id}/repository/branches", user),
- branch_name: 'new design',
- ref: branch_sha
- expect(response).to have_gitlab_http_status(400)
- expect(json_response['message']).to eq('Branch name is invalid')
- end
-
- it 'returns 400 if branch already exists' do
- post v3_api("/projects/#{project.id}/repository/branches", user),
- branch_name: 'new_design1',
- ref: branch_sha
- expect(response).to have_gitlab_http_status(201)
-
- post v3_api("/projects/#{project.id}/repository/branches", user),
- branch_name: 'new_design1',
- ref: branch_sha
-
- expect(response).to have_gitlab_http_status(400)
- expect(json_response['message']).to eq('Branch already exists')
- end
-
- it 'returns 400 if ref name is invalid' do
- post v3_api("/projects/#{project.id}/repository/branches", user),
- branch_name: 'new_design3',
- ref: 'foo'
-
- expect(response).to have_gitlab_http_status(400)
- expect(json_response['message']).to eq('Invalid reference name')
- end
- end
-end
diff --git a/spec/requests/api/v3/broadcast_messages_spec.rb b/spec/requests/api/v3/broadcast_messages_spec.rb
deleted file mode 100644
index d9641011491..00000000000
--- a/spec/requests/api/v3/broadcast_messages_spec.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-require 'spec_helper'
-
-describe API::V3::BroadcastMessages do
- set(:user) { create(:user) }
- set(:admin) { create(:admin) }
-
- describe 'DELETE /broadcast_messages/:id' do
- set(:message) { create(:broadcast_message) }
-
- it 'returns a 401 for anonymous users' do
- delete v3_api("/broadcast_messages/#{message.id}"),
- attributes_for(:broadcast_message)
-
- expect(response).to have_gitlab_http_status(401)
- end
-
- it 'returns a 403 for users' do
- delete v3_api("/broadcast_messages/#{message.id}", user),
- attributes_for(:broadcast_message)
-
- expect(response).to have_gitlab_http_status(403)
- end
-
- it 'deletes the broadcast message for admins' do
- expect do
- delete v3_api("/broadcast_messages/#{message.id}", admin)
-
- expect(response).to have_gitlab_http_status(200)
- end.to change { BroadcastMessage.count }.by(-1)
- end
- end
-end
diff --git a/spec/requests/api/v3/builds_spec.rb b/spec/requests/api/v3/builds_spec.rb
deleted file mode 100644
index 485d7c2cc43..00000000000
--- a/spec/requests/api/v3/builds_spec.rb
+++ /dev/null
@@ -1,550 +0,0 @@
-require 'spec_helper'
-
-describe API::V3::Builds do
- set(:user) { create(:user) }
- let(:api_user) { user }
- set(:project) { create(:project, :repository, creator: user, public_builds: false) }
- let!(:developer) { create(:project_member, :developer, user: user, project: project) }
- let(:reporter) { create(:project_member, :reporter, project: project) }
- let(:guest) { create(:project_member, :guest, project: project) }
- let(:pipeline) { create(:ci_empty_pipeline, project: project, sha: project.commit.id, ref: project.default_branch) }
- let(:build) { create(:ci_build, pipeline: pipeline) }
-
- describe 'GET /projects/:id/builds ' do
- let(:query) { '' }
-
- before do |example|
- build
-
- create(:ci_build, :skipped, pipeline: pipeline)
-
- unless example.metadata[:skip_before_request]
- get v3_api("/projects/#{project.id}/builds?#{query}", api_user)
- end
- end
-
- context 'authorized user' do
- it 'returns project builds' do
- expect(response).to have_gitlab_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- end
-
- it 'returns correct values' do
- expect(json_response).not_to be_empty
- expect(json_response.first['commit']['id']).to eq project.commit.id
- end
-
- it 'returns pipeline data' do
- json_build = json_response.first
- expect(json_build['pipeline']).not_to be_empty
- expect(json_build['pipeline']['id']).to eq build.pipeline.id
- expect(json_build['pipeline']['ref']).to eq build.pipeline.ref
- expect(json_build['pipeline']['sha']).to eq build.pipeline.sha
- expect(json_build['pipeline']['status']).to eq build.pipeline.status
- end
-
- it 'avoids N+1 queries', :skip_before_request do
- first_build = create(:ci_build, :artifacts, pipeline: pipeline)
- first_build.runner = create(:ci_runner)
- first_build.user = create(:user)
- first_build.save
-
- control_count = ActiveRecord::QueryRecorder.new { go }.count
-
- second_pipeline = create(:ci_empty_pipeline, project: project, sha: project.commit.id, ref: project.default_branch)
- second_build = create(:ci_build, :artifacts, pipeline: second_pipeline)
- second_build.runner = create(:ci_runner)
- second_build.user = create(:user)
- second_build.save
-
- expect { go }.not_to exceed_query_limit(control_count)
- end
-
- context 'filter project with one scope element' do
- let(:query) { 'scope=pending' }
-
- it do
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- end
- end
-
- context 'filter project with scope skipped' do
- let(:query) { 'scope=skipped' }
- let(:json_build) { json_response.first }
-
- it 'return builds with status skipped' do
- expect(response).to have_gitlab_http_status 200
- expect(json_response).to be_an Array
- expect(json_response.length).to eq 1
- expect(json_build['status']).to eq 'skipped'
- end
- end
-
- context 'filter project with array of scope elements' do
- let(:query) { 'scope[0]=pending&scope[1]=running' }
-
- it do
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- end
- end
-
- context 'respond 400 when scope contains invalid state' do
- let(:query) { 'scope[0]=pending&scope[1]=unknown_status' }
-
- it { expect(response).to have_gitlab_http_status(400) }
- end
- end
-
- context 'unauthorized user' do
- let(:api_user) { nil }
-
- it 'does not return project builds' do
- expect(response).to have_gitlab_http_status(401)
- end
- end
-
- def go
- get v3_api("/projects/#{project.id}/builds?#{query}", api_user)
- end
- end
-
- describe 'GET /projects/:id/repository/commits/:sha/builds' do
- before do
- build
- end
-
- context 'when commit does not exist in repository' do
- before do
- get v3_api("/projects/#{project.id}/repository/commits/1a271fd1/builds", api_user)
- end
-
- it 'responds with 404' do
- expect(response).to have_gitlab_http_status(404)
- end
- end
-
- context 'when commit exists in repository' do
- context 'when user is authorized' do
- context 'when pipeline has jobs' do
- before do
- create(:ci_pipeline, project: project, sha: project.commit.id)
- create(:ci_build, pipeline: pipeline)
- create(:ci_build)
-
- get v3_api("/projects/#{project.id}/repository/commits/#{project.commit.id}/builds", api_user)
- end
-
- it 'returns project jobs for specific commit' do
- expect(response).to have_gitlab_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response.size).to eq 2
- end
-
- it 'returns pipeline data' do
- json_build = json_response.first
- expect(json_build['pipeline']).not_to be_empty
- expect(json_build['pipeline']['id']).to eq build.pipeline.id
- expect(json_build['pipeline']['ref']).to eq build.pipeline.ref
- expect(json_build['pipeline']['sha']).to eq build.pipeline.sha
- expect(json_build['pipeline']['status']).to eq build.pipeline.status
- end
- end
-
- context 'when pipeline has no jobs' do
- before do
- branch_head = project.commit('feature').id
- get v3_api("/projects/#{project.id}/repository/commits/#{branch_head}/builds", api_user)
- end
-
- it 'returns an empty array' do
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response).to be_empty
- end
- end
- end
-
- context 'when user is not authorized' do
- before do
- create(:ci_pipeline, project: project, sha: project.commit.id)
- create(:ci_build, pipeline: pipeline)
-
- get v3_api("/projects/#{project.id}/repository/commits/#{project.commit.id}/builds", nil)
- end
-
- it 'does not return project jobs' do
- expect(response).to have_gitlab_http_status(401)
- expect(json_response.except('message')).to be_empty
- end
- end
- end
- end
-
- describe 'GET /projects/:id/builds/:build_id' do
- before do
- get v3_api("/projects/#{project.id}/builds/#{build.id}", api_user)
- end
-
- context 'authorized user' do
- it 'returns specific job data' do
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['name']).to eq('test')
- end
-
- it 'returns pipeline data' do
- json_build = json_response
- expect(json_build['pipeline']).not_to be_empty
- expect(json_build['pipeline']['id']).to eq build.pipeline.id
- expect(json_build['pipeline']['ref']).to eq build.pipeline.ref
- expect(json_build['pipeline']['sha']).to eq build.pipeline.sha
- expect(json_build['pipeline']['status']).to eq build.pipeline.status
- end
- end
-
- context 'unauthorized user' do
- let(:api_user) { nil }
-
- it 'does not return specific job data' do
- expect(response).to have_gitlab_http_status(401)
- end
- end
- end
-
- describe 'GET /projects/:id/builds/:build_id/artifacts' do
- before do
- stub_artifacts_object_storage
- get v3_api("/projects/#{project.id}/builds/#{build.id}/artifacts", api_user)
- end
-
- context 'job with artifacts' do
- context 'when artifacts are stored locally' do
- let(:build) { create(:ci_build, :artifacts, pipeline: pipeline) }
-
- context 'authorized user' do
- let(:download_headers) do
- { 'Content-Transfer-Encoding' => 'binary',
- 'Content-Disposition' => 'attachment; filename=ci_build_artifacts.zip' }
- end
-
- it 'returns specific job artifacts' do
- expect(response).to have_http_status(200)
- expect(response.headers.to_h).to include(download_headers)
- expect(response.body).to match_file(build.artifacts_file.file.file)
- end
- end
- end
-
- context 'when artifacts are stored remotely' do
- let(:build) { create(:ci_build, pipeline: pipeline) }
- let!(:artifact) { create(:ci_job_artifact, :archive, :remote_store, job: build) }
-
- it 'returns location redirect' do
- get v3_api("/projects/#{project.id}/builds/#{build.id}/artifacts", api_user)
-
- expect(response).to have_gitlab_http_status(302)
- end
- end
-
- context 'unauthorized user' do
- let(:api_user) { nil }
-
- it 'does not return specific job artifacts' do
- expect(response).to have_gitlab_http_status(401)
- end
- end
- end
-
- it 'does not return job artifacts if not uploaded' do
- expect(response).to have_gitlab_http_status(404)
- end
- end
-
- describe 'GET /projects/:id/artifacts/:ref_name/download?job=name' do
- let(:api_user) { reporter.user }
- let(:build) { create(:ci_build, :artifacts, pipeline: pipeline) }
-
- before do
- stub_artifacts_object_storage
- build.success
- end
-
- def path_for_ref(ref = pipeline.ref, job = build.name)
- v3_api("/projects/#{project.id}/builds/artifacts/#{ref}/download?job=#{job}", api_user)
- end
-
- context 'when not logged in' do
- let(:api_user) { nil }
-
- before do
- get path_for_ref
- end
-
- it 'gives 401' do
- expect(response).to have_gitlab_http_status(401)
- end
- end
-
- context 'when logging as guest' do
- let(:api_user) { guest.user }
-
- before do
- get path_for_ref
- end
-
- it 'gives 403' do
- expect(response).to have_gitlab_http_status(403)
- end
- end
-
- context 'non-existing job' do
- shared_examples 'not found' do
- it { expect(response).to have_gitlab_http_status(:not_found) }
- end
-
- context 'has no such ref' do
- before do
- get path_for_ref('TAIL', build.name)
- end
-
- it_behaves_like 'not found'
- end
-
- context 'has no such job' do
- before do
- get path_for_ref(pipeline.ref, 'NOBUILD')
- end
-
- it_behaves_like 'not found'
- end
- end
-
- context 'find proper job' do
- shared_examples 'a valid file' do
- context 'when artifacts are stored locally' do
- let(:download_headers) do
- { 'Content-Transfer-Encoding' => 'binary',
- 'Content-Disposition' =>
- "attachment; filename=#{build.artifacts_file.filename}" }
- end
-
- it { expect(response).to have_http_status(200) }
- it { expect(response.headers.to_h).to include(download_headers) }
- end
-
- context 'when artifacts are stored remotely' do
- let(:build) { create(:ci_build, pipeline: pipeline) }
- let!(:artifact) { create(:ci_job_artifact, :archive, :remote_store, job: build) }
-
- before do
- build.reload
-
- get v3_api("/projects/#{project.id}/builds/#{build.id}/artifacts", api_user)
- end
-
- it 'returns location redirect' do
- expect(response).to have_http_status(302)
- end
- end
- end
-
- context 'with regular branch' do
- before do
- pipeline.reload
- pipeline.update(ref: 'master',
- sha: project.commit('master').sha)
-
- get path_for_ref('master')
- end
-
- it_behaves_like 'a valid file'
- end
-
- context 'with branch name containing slash' do
- before do
- pipeline.reload
- pipeline.update(ref: 'improve/awesome',
- sha: project.commit('improve/awesome').sha)
- end
-
- before do
- get path_for_ref('improve/awesome')
- end
-
- it_behaves_like 'a valid file'
- end
- end
- end
-
- describe 'GET /projects/:id/builds/:build_id/trace' do
- let(:build) { create(:ci_build, :trace_live, pipeline: pipeline) }
-
- before do
- get v3_api("/projects/#{project.id}/builds/#{build.id}/trace", api_user)
- end
-
- context 'authorized user' do
- it 'returns specific job trace' do
- expect(response).to have_gitlab_http_status(200)
- expect(response.body).to eq(build.trace.raw)
- end
- end
-
- context 'unauthorized user' do
- let(:api_user) { nil }
-
- it 'does not return specific job trace' do
- expect(response).to have_gitlab_http_status(401)
- end
- end
- end
-
- describe 'POST /projects/:id/builds/:build_id/cancel' do
- before do
- post v3_api("/projects/#{project.id}/builds/#{build.id}/cancel", api_user)
- end
-
- context 'authorized user' do
- context 'user with :update_build persmission' do
- it 'cancels running or pending job' do
- expect(response).to have_gitlab_http_status(201)
- expect(project.builds.first.status).to eq('canceled')
- end
- end
-
- context 'user without :update_build permission' do
- let(:api_user) { reporter.user }
-
- it 'does not cancel job' do
- expect(response).to have_gitlab_http_status(403)
- end
- end
- end
-
- context 'unauthorized user' do
- let(:api_user) { nil }
-
- it 'does not cancel job' do
- expect(response).to have_gitlab_http_status(401)
- end
- end
- end
-
- describe 'POST /projects/:id/builds/:build_id/retry' do
- let(:build) { create(:ci_build, :canceled, pipeline: pipeline) }
-
- before do
- post v3_api("/projects/#{project.id}/builds/#{build.id}/retry", api_user)
- end
-
- context 'authorized user' do
- context 'user with :update_build permission' do
- it 'retries non-running job' do
- expect(response).to have_gitlab_http_status(201)
- expect(project.builds.first.status).to eq('canceled')
- expect(json_response['status']).to eq('pending')
- end
- end
-
- context 'user without :update_build permission' do
- let(:api_user) { reporter.user }
-
- it 'does not retry job' do
- expect(response).to have_gitlab_http_status(403)
- end
- end
- end
-
- context 'unauthorized user' do
- let(:api_user) { nil }
-
- it 'does not retry job' do
- expect(response).to have_gitlab_http_status(401)
- end
- end
- end
-
- describe 'POST /projects/:id/builds/:build_id/erase' do
- before do
- project.add_master(user)
-
- post v3_api("/projects/#{project.id}/builds/#{build.id}/erase", user)
- end
-
- context 'job is erasable' do
- let(:build) { create(:ci_build, :trace_artifact, :artifacts, :success, project: project, pipeline: pipeline) }
-
- it 'erases job content' do
- expect(response.status).to eq 201
- expect(build).not_to have_trace
- expect(build.artifacts_file.exists?).to be_falsy
- expect(build.artifacts_metadata.exists?).to be_falsy
- end
-
- it 'updates job' do
- expect(build.reload.erased_at).to be_truthy
- expect(build.reload.erased_by).to eq user
- end
- end
-
- context 'job is not erasable' do
- let(:build) { create(:ci_build, :trace_live, project: project, pipeline: pipeline) }
-
- it 'responds with forbidden' do
- expect(response.status).to eq 403
- end
- end
- end
-
- describe 'POST /projects/:id/builds/:build_id/artifacts/keep' do
- before do
- post v3_api("/projects/#{project.id}/builds/#{build.id}/artifacts/keep", user)
- end
-
- context 'artifacts did not expire' do
- let(:build) do
- create(:ci_build, :trace_artifact, :artifacts, :success,
- project: project, pipeline: pipeline, artifacts_expire_at: Time.now + 7.days)
- end
-
- it 'keeps artifacts' do
- expect(response.status).to eq 200
- expect(build.reload.artifacts_expire_at).to be_nil
- end
- end
-
- context 'no artifacts' do
- let(:build) { create(:ci_build, project: project, pipeline: pipeline) }
-
- it 'responds with not found' do
- expect(response.status).to eq 404
- end
- end
- end
-
- describe 'POST /projects/:id/builds/:build_id/play' do
- before do
- post v3_api("/projects/#{project.id}/builds/#{build.id}/play", user)
- end
-
- context 'on an playable job' do
- let(:build) { create(:ci_build, :manual, project: project, pipeline: pipeline) }
-
- it 'plays the job' do
- expect(response).to have_gitlab_http_status 200
- expect(json_response['user']['id']).to eq(user.id)
- expect(json_response['id']).to eq(build.id)
- end
- end
-
- context 'on a non-playable job' do
- it 'returns a status code 400, Bad Request' do
- expect(response).to have_gitlab_http_status 400
- expect(response.body).to match("Unplayable Job")
- end
- end
- end
-end
diff --git a/spec/requests/api/v3/commits_spec.rb b/spec/requests/api/v3/commits_spec.rb
deleted file mode 100644
index 9ef3b859001..00000000000
--- a/spec/requests/api/v3/commits_spec.rb
+++ /dev/null
@@ -1,603 +0,0 @@
-require 'spec_helper'
-require 'mime/types'
-
-describe API::V3::Commits do
- let(:user) { create(:user) }
- let(:user2) { create(:user) }
- let!(:project) { create(:project, :repository, creator: user, namespace: user.namespace) }
- let!(:guest) { create(:project_member, :guest, user: user2, project: project) }
- let!(:note) { create(:note_on_commit, author: user, project: project, commit_id: project.repository.commit.id, note: 'a comment on a commit') }
- let!(:another_note) { create(:note_on_commit, author: user, project: project, commit_id: project.repository.commit.id, note: 'another comment on a commit') }
-
- before { project.add_reporter(user) }
-
- describe "List repository commits" do
- context "authorized user" do
- before { project.add_reporter(user2) }
-
- it "returns project commits" do
- commit = project.repository.commit
- get v3_api("/projects/#{project.id}/repository/commits", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.first['id']).to eq(commit.id)
- expect(json_response.first['committer_name']).to eq(commit.committer_name)
- expect(json_response.first['committer_email']).to eq(commit.committer_email)
- end
- end
-
- context "unauthorized user" do
- it "does not return project commits" do
- get v3_api("/projects/#{project.id}/repository/commits")
- expect(response).to have_gitlab_http_status(401)
- end
- end
-
- context "since optional parameter" do
- it "returns project commits since provided parameter" do
- commits = project.repository.commits("master", limit: 2)
- since = commits.second.created_at
-
- get v3_api("/projects/#{project.id}/repository/commits?since=#{since.utc.iso8601}", user)
-
- expect(json_response.size).to eq 2
- expect(json_response.first["id"]).to eq(commits.first.id)
- expect(json_response.second["id"]).to eq(commits.second.id)
- end
- end
-
- context "until optional parameter" do
- it "returns project commits until provided parameter" do
- commits = project.repository.commits("master", limit: 20)
- before = commits.second.created_at
-
- get v3_api("/projects/#{project.id}/repository/commits?until=#{before.utc.iso8601}", user)
-
- if commits.size == 20
- expect(json_response.size).to eq(20)
- else
- expect(json_response.size).to eq(commits.size - 1)
- end
-
- expect(json_response.first["id"]).to eq(commits.second.id)
- expect(json_response.second["id"]).to eq(commits.third.id)
- end
- end
-
- context "invalid xmlschema date parameters" do
- it "returns an invalid parameter error message" do
- get v3_api("/projects/#{project.id}/repository/commits?since=invalid-date", user)
-
- expect(response).to have_gitlab_http_status(400)
- expect(json_response['error']).to eq('since is invalid')
- end
- end
-
- context "path optional parameter" do
- it "returns project commits matching provided path parameter" do
- path = 'files/ruby/popen.rb'
-
- get v3_api("/projects/#{project.id}/repository/commits?path=#{path}", user)
-
- expect(json_response.size).to eq(3)
- expect(json_response.first["id"]).to eq("570e7b2abdd848b95f2f578043fc23bd6f6fd24d")
- end
- end
- end
-
- describe "POST /projects/:id/repository/commits" do
- let!(:url) { "/projects/#{project.id}/repository/commits" }
-
- it 'returns a 403 unauthorized for user without permissions' do
- post v3_api(url, user2)
-
- expect(response).to have_gitlab_http_status(403)
- end
-
- it 'returns a 400 bad request if no params are given' do
- post v3_api(url, user)
-
- expect(response).to have_gitlab_http_status(400)
- end
-
- describe 'create' do
- let(:message) { 'Created file' }
- let!(:invalid_c_params) do
- {
- branch_name: 'master',
- commit_message: message,
- actions: [
- {
- action: 'create',
- file_path: 'files/ruby/popen.rb',
- content: 'puts 8'
- }
- ]
- }
- end
- let!(:valid_c_params) do
- {
- branch_name: 'master',
- commit_message: message,
- actions: [
- {
- action: 'create',
- file_path: 'foo/bar/baz.txt',
- content: 'puts 8'
- }
- ]
- }
- end
-
- it 'a new file in project repo' do
- post v3_api(url, user), valid_c_params
-
- expect(response).to have_gitlab_http_status(201)
- expect(json_response['title']).to eq(message)
- expect(json_response['committer_name']).to eq(user.name)
- expect(json_response['committer_email']).to eq(user.email)
- end
-
- it 'returns a 400 bad request if file exists' do
- post v3_api(url, user), invalid_c_params
-
- expect(response).to have_gitlab_http_status(400)
- end
-
- context 'with project path containing a dot in URL' do
- let!(:user) { create(:user, username: 'foo.bar') }
- let(:url) { "/projects/#{CGI.escape(project.full_path)}/repository/commits" }
-
- it 'a new file in project repo' do
- post v3_api(url, user), valid_c_params
-
- expect(response).to have_gitlab_http_status(201)
- end
- end
- end
-
- describe 'delete' do
- let(:message) { 'Deleted file' }
- let!(:invalid_d_params) do
- {
- branch_name: 'markdown',
- commit_message: message,
- actions: [
- {
- action: 'delete',
- file_path: 'doc/api/projects.md'
- }
- ]
- }
- end
- let!(:valid_d_params) do
- {
- branch_name: 'markdown',
- commit_message: message,
- actions: [
- {
- action: 'delete',
- file_path: 'doc/api/users.md'
- }
- ]
- }
- end
-
- it 'an existing file in project repo' do
- post v3_api(url, user), valid_d_params
-
- expect(response).to have_gitlab_http_status(201)
- expect(json_response['title']).to eq(message)
- end
-
- it 'returns a 400 bad request if file does not exist' do
- post v3_api(url, user), invalid_d_params
-
- expect(response).to have_gitlab_http_status(400)
- end
- end
-
- describe 'move' do
- let(:message) { 'Moved file' }
- let!(:invalid_m_params) do
- {
- branch_name: 'feature',
- commit_message: message,
- actions: [
- {
- action: 'move',
- file_path: 'CHANGELOG',
- previous_path: 'VERSION',
- content: '6.7.0.pre'
- }
- ]
- }
- end
- let!(:valid_m_params) do
- {
- branch_name: 'feature',
- commit_message: message,
- actions: [
- {
- action: 'move',
- file_path: 'VERSION.txt',
- previous_path: 'VERSION',
- content: '6.7.0.pre'
- }
- ]
- }
- end
-
- it 'an existing file in project repo' do
- post v3_api(url, user), valid_m_params
-
- expect(response).to have_gitlab_http_status(201)
- expect(json_response['title']).to eq(message)
- end
-
- it 'returns a 400 bad request if file does not exist' do
- post v3_api(url, user), invalid_m_params
-
- expect(response).to have_gitlab_http_status(400)
- end
- end
-
- describe 'update' do
- let(:message) { 'Updated file' }
- let!(:invalid_u_params) do
- {
- branch_name: 'master',
- commit_message: message,
- actions: [
- {
- action: 'update',
- file_path: 'foo/bar.baz',
- content: 'puts 8'
- }
- ]
- }
- end
- let!(:valid_u_params) do
- {
- branch_name: 'master',
- commit_message: message,
- actions: [
- {
- action: 'update',
- file_path: 'files/ruby/popen.rb',
- content: 'puts 8'
- }
- ]
- }
- end
-
- it 'an existing file in project repo' do
- post v3_api(url, user), valid_u_params
-
- expect(response).to have_gitlab_http_status(201)
- expect(json_response['title']).to eq(message)
- end
-
- it 'returns a 400 bad request if file does not exist' do
- post v3_api(url, user), invalid_u_params
-
- expect(response).to have_gitlab_http_status(400)
- end
- end
-
- context "multiple operations" do
- let(:message) { 'Multiple actions' }
- let!(:invalid_mo_params) do
- {
- branch_name: 'master',
- commit_message: message,
- actions: [
- {
- action: 'create',
- file_path: 'files/ruby/popen.rb',
- content: 'puts 8'
- },
- {
- action: 'delete',
- file_path: 'doc/v3_api/projects.md'
- },
- {
- action: 'move',
- file_path: 'CHANGELOG',
- previous_path: 'VERSION',
- content: '6.7.0.pre'
- },
- {
- action: 'update',
- file_path: 'foo/bar.baz',
- content: 'puts 8'
- }
- ]
- }
- end
- let!(:valid_mo_params) do
- {
- branch_name: 'master',
- commit_message: message,
- actions: [
- {
- action: 'create',
- file_path: 'foo/bar/baz.txt',
- content: 'puts 8'
- },
- {
- action: 'delete',
- file_path: 'Gemfile.zip'
- },
- {
- action: 'move',
- file_path: 'VERSION.txt',
- previous_path: 'VERSION',
- content: '6.7.0.pre'
- },
- {
- action: 'update',
- file_path: 'files/ruby/popen.rb',
- content: 'puts 8'
- }
- ]
- }
- end
-
- it 'are commited as one in project repo' do
- post v3_api(url, user), valid_mo_params
-
- expect(response).to have_gitlab_http_status(201)
- expect(json_response['title']).to eq(message)
- end
-
- it 'return a 400 bad request if there are any issues' do
- post v3_api(url, user), invalid_mo_params
-
- expect(response).to have_gitlab_http_status(400)
- end
- end
- end
-
- describe "Get a single commit" do
- context "authorized user" do
- it "returns a commit by sha" do
- get v3_api("/projects/#{project.id}/repository/commits/#{project.repository.commit.id}", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['id']).to eq(project.repository.commit.id)
- expect(json_response['title']).to eq(project.repository.commit.title)
- expect(json_response['stats']['additions']).to eq(project.repository.commit.stats.additions)
- expect(json_response['stats']['deletions']).to eq(project.repository.commit.stats.deletions)
- expect(json_response['stats']['total']).to eq(project.repository.commit.stats.total)
- end
-
- it "returns a 404 error if not found" do
- get v3_api("/projects/#{project.id}/repository/commits/invalid_sha", user)
- expect(response).to have_gitlab_http_status(404)
- end
-
- it "returns nil for commit without CI" do
- get v3_api("/projects/#{project.id}/repository/commits/#{project.repository.commit.id}", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['status']).to be_nil
- end
-
- it "returns status for CI" do
- pipeline = project.pipelines.create(source: :push, ref: 'master', sha: project.repository.commit.sha, protected: false)
- pipeline.update(status: 'success')
-
- get v3_api("/projects/#{project.id}/repository/commits/#{project.repository.commit.id}", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['status']).to eq(pipeline.status)
- end
-
- it "returns status for CI when pipeline is created" do
- project.pipelines.create(source: :push, ref: 'master', sha: project.repository.commit.sha, protected: false)
-
- get v3_api("/projects/#{project.id}/repository/commits/#{project.repository.commit.id}", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['status']).to eq("created")
- end
-
- context 'when stat param' do
- let(:project_id) { project.id }
- let(:commit_id) { project.repository.commit.id }
- let(:route) { "/projects/#{project_id}/repository/commits/#{commit_id}" }
-
- it 'is not present return stats by default' do
- get v3_api(route, user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to include 'stats'
- end
-
- it "is false it does not include stats" do
- get v3_api(route, user), stats: false
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).not_to include 'stats'
- end
-
- it "is true it includes stats" do
- get v3_api(route, user), stats: true
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to include 'stats'
- end
- end
- end
-
- context "unauthorized user" do
- it "does not return the selected commit" do
- get v3_api("/projects/#{project.id}/repository/commits/#{project.repository.commit.id}")
- expect(response).to have_gitlab_http_status(401)
- end
- end
- end
-
- describe "Get the diff of a commit" do
- context "authorized user" do
- before { project.add_reporter(user2) }
-
- it "returns the diff of the selected commit" do
- get v3_api("/projects/#{project.id}/repository/commits/#{project.repository.commit.id}/diff", user)
- expect(response).to have_gitlab_http_status(200)
-
- expect(json_response).to be_an Array
- expect(json_response.length).to be >= 1
- expect(json_response.first.keys).to include "diff"
- end
-
- it "returns a 404 error if invalid commit" do
- get v3_api("/projects/#{project.id}/repository/commits/invalid_sha/diff", user)
- expect(response).to have_gitlab_http_status(404)
- end
- end
-
- context "unauthorized user" do
- it "does not return the diff of the selected commit" do
- get v3_api("/projects/#{project.id}/repository/commits/#{project.repository.commit.id}/diff")
- expect(response).to have_gitlab_http_status(401)
- end
- end
- end
-
- describe 'Get the comments of a commit' do
- context 'authorized user' do
- it 'returns merge_request comments' do
- get v3_api("/projects/#{project.id}/repository/commits/#{project.repository.commit.id}/comments", user)
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(2)
- expect(json_response.first['note']).to eq('a comment on a commit')
- expect(json_response.first['author']['id']).to eq(user.id)
- end
-
- it 'returns a 404 error if merge_request_id not found' do
- get v3_api("/projects/#{project.id}/repository/commits/1234ab/comments", user)
- expect(response).to have_gitlab_http_status(404)
- end
- end
-
- context 'unauthorized user' do
- it 'does not return the diff of the selected commit' do
- get v3_api("/projects/#{project.id}/repository/commits/1234ab/comments")
- expect(response).to have_gitlab_http_status(401)
- end
- end
- end
-
- describe 'POST :id/repository/commits/:sha/cherry_pick' do
- let(:master_pickable_commit) { project.commit('7d3b0f7cff5f37573aea97cebfd5692ea1689924') }
-
- context 'authorized user' do
- it 'cherry picks a commit' do
- post v3_api("/projects/#{project.id}/repository/commits/#{master_pickable_commit.id}/cherry_pick", user), branch: 'master'
-
- expect(response).to have_gitlab_http_status(201)
- expect(json_response['title']).to eq(master_pickable_commit.title)
- expect(json_response['message']).to eq(master_pickable_commit.cherry_pick_message(user))
- expect(json_response['author_name']).to eq(master_pickable_commit.author_name)
- expect(json_response['committer_name']).to eq(user.name)
- end
-
- it 'returns 400 if commit is already included in the target branch' do
- post v3_api("/projects/#{project.id}/repository/commits/#{master_pickable_commit.id}/cherry_pick", user), branch: 'markdown'
-
- expect(response).to have_gitlab_http_status(400)
- expect(json_response['message']).to include('Sorry, we cannot cherry-pick this commit automatically.')
- end
-
- it 'returns 400 if you are not allowed to push to the target branch' do
- project.add_developer(user2)
- protected_branch = create(:protected_branch, project: project, name: 'feature')
-
- post v3_api("/projects/#{project.id}/repository/commits/#{master_pickable_commit.id}/cherry_pick", user2), branch: protected_branch.name
-
- expect(response).to have_gitlab_http_status(400)
- expect(json_response['message']).to eq('You are not allowed to push into this branch')
- end
-
- it 'returns 400 for missing parameters' do
- post v3_api("/projects/#{project.id}/repository/commits/#{master_pickable_commit.id}/cherry_pick", user)
-
- expect(response).to have_gitlab_http_status(400)
- expect(json_response['error']).to eq('branch is missing')
- end
-
- it 'returns 404 if commit is not found' do
- post v3_api("/projects/#{project.id}/repository/commits/abcd0123/cherry_pick", user), branch: 'master'
-
- expect(response).to have_gitlab_http_status(404)
- expect(json_response['message']).to eq('404 Commit Not Found')
- end
-
- it 'returns 404 if branch is not found' do
- post v3_api("/projects/#{project.id}/repository/commits/#{master_pickable_commit.id}/cherry_pick", user), branch: 'foo'
-
- expect(response).to have_gitlab_http_status(404)
- expect(json_response['message']).to eq('404 Branch Not Found')
- end
-
- it 'returns 400 for missing parameters' do
- post v3_api("/projects/#{project.id}/repository/commits/#{master_pickable_commit.id}/cherry_pick", user)
-
- expect(response).to have_gitlab_http_status(400)
- expect(json_response['error']).to eq('branch is missing')
- end
- end
-
- context 'unauthorized user' do
- it 'does not cherry pick the commit' do
- post v3_api("/projects/#{project.id}/repository/commits/#{master_pickable_commit.id}/cherry_pick"), branch: 'master'
-
- expect(response).to have_gitlab_http_status(401)
- end
- end
- end
-
- describe 'Post comment to commit' do
- context 'authorized user' do
- it 'returns comment' do
- post v3_api("/projects/#{project.id}/repository/commits/#{project.repository.commit.id}/comments", user), note: 'My comment'
- expect(response).to have_gitlab_http_status(201)
- expect(json_response['note']).to eq('My comment')
- expect(json_response['path']).to be_nil
- expect(json_response['line']).to be_nil
- expect(json_response['line_type']).to be_nil
- end
-
- it 'returns the inline comment' do
- post v3_api("/projects/#{project.id}/repository/commits/#{project.repository.commit.id}/comments", user), note: 'My comment', path: project.repository.commit.raw_diffs.first.new_path, line: 1, line_type: 'new'
-
- expect(response).to have_gitlab_http_status(201)
- expect(json_response['note']).to eq('My comment')
- expect(json_response['path']).to eq(project.repository.commit.raw_diffs.first.new_path)
- expect(json_response['line']).to eq(1)
- expect(json_response['line_type']).to eq('new')
- end
-
- it 'returns 400 if note is missing' do
- post v3_api("/projects/#{project.id}/repository/commits/#{project.repository.commit.id}/comments", user)
- expect(response).to have_gitlab_http_status(400)
- end
-
- it 'returns 404 if note is attached to non existent commit' do
- post v3_api("/projects/#{project.id}/repository/commits/1234ab/comments", user), note: 'My comment'
- expect(response).to have_gitlab_http_status(404)
- end
- end
-
- context 'unauthorized user' do
- it 'does not return the diff of the selected commit' do
- post v3_api("/projects/#{project.id}/repository/commits/#{project.repository.commit.id}/comments")
- expect(response).to have_gitlab_http_status(401)
- end
- end
- end
-end
diff --git a/spec/requests/api/v3/deploy_keys_spec.rb b/spec/requests/api/v3/deploy_keys_spec.rb
deleted file mode 100644
index 501af587ad4..00000000000
--- a/spec/requests/api/v3/deploy_keys_spec.rb
+++ /dev/null
@@ -1,179 +0,0 @@
-require 'spec_helper'
-
-describe API::V3::DeployKeys do
- let(:user) { create(:user) }
- let(:admin) { create(:admin) }
- let(:project) { create(:project, creator_id: user.id) }
- let(:project2) { create(:project, creator_id: user.id) }
- let(:deploy_key) { create(:deploy_key, public: true) }
-
- let!(:deploy_keys_project) do
- create(:deploy_keys_project, project: project, deploy_key: deploy_key)
- end
-
- describe 'GET /deploy_keys' do
- context 'when unauthenticated' do
- it 'should return authentication error' do
- get v3_api('/deploy_keys')
-
- expect(response.status).to eq(401)
- end
- end
-
- context 'when authenticated as non-admin user' do
- it 'should return a 403 error' do
- get v3_api('/deploy_keys', user)
-
- expect(response.status).to eq(403)
- end
- end
-
- context 'when authenticated as admin' do
- it 'should return all deploy keys' do
- get v3_api('/deploy_keys', admin)
-
- expect(response.status).to eq(200)
- expect(json_response).to be_an Array
- expect(json_response.first['id']).to eq(deploy_keys_project.deploy_key.id)
- end
- end
- end
-
- %w(deploy_keys keys).each do |path|
- describe "GET /projects/:id/#{path}" do
- before { deploy_key }
-
- it 'should return array of ssh keys' do
- get v3_api("/projects/#{project.id}/#{path}", admin)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.first['title']).to eq(deploy_key.title)
- end
- end
-
- describe "GET /projects/:id/#{path}/:key_id" do
- it 'should return a single key' do
- get v3_api("/projects/#{project.id}/#{path}/#{deploy_key.id}", admin)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['title']).to eq(deploy_key.title)
- end
-
- it 'should return 404 Not Found with invalid ID' do
- get v3_api("/projects/#{project.id}/#{path}/404", admin)
-
- expect(response).to have_gitlab_http_status(404)
- end
- end
-
- describe "POST /projects/:id/deploy_keys" do
- it 'should not create an invalid ssh key' do
- post v3_api("/projects/#{project.id}/#{path}", admin), { title: 'invalid key' }
-
- expect(response).to have_gitlab_http_status(400)
- expect(json_response['error']).to eq('key is missing')
- end
-
- it 'should not create a key without title' do
- post v3_api("/projects/#{project.id}/#{path}", admin), key: 'some key'
-
- expect(response).to have_gitlab_http_status(400)
- expect(json_response['error']).to eq('title is missing')
- end
-
- it 'should create new ssh key' do
- key_attrs = attributes_for :another_key
-
- expect do
- post v3_api("/projects/#{project.id}/#{path}", admin), key_attrs
- end.to change { project.deploy_keys.count }.by(1)
- end
-
- it 'returns an existing ssh key when attempting to add a duplicate' do
- expect do
- post v3_api("/projects/#{project.id}/#{path}", admin), { key: deploy_key.key, title: deploy_key.title }
- end.not_to change { project.deploy_keys.count }
-
- expect(response).to have_gitlab_http_status(201)
- end
-
- it 'joins an existing ssh key to a new project' do
- expect do
- post v3_api("/projects/#{project2.id}/#{path}", admin), { key: deploy_key.key, title: deploy_key.title }
- end.to change { project2.deploy_keys.count }.by(1)
-
- expect(response).to have_gitlab_http_status(201)
- end
-
- it 'accepts can_push parameter' do
- key_attrs = attributes_for(:another_key).merge(can_push: true)
-
- post v3_api("/projects/#{project.id}/#{path}", admin), key_attrs
-
- expect(response).to have_gitlab_http_status(201)
- expect(json_response['can_push']).to eq(true)
- end
- end
-
- describe "DELETE /projects/:id/#{path}/:key_id" do
- before { deploy_key }
-
- it 'should delete existing key' do
- expect do
- delete v3_api("/projects/#{project.id}/#{path}/#{deploy_key.id}", admin)
- end.to change { project.deploy_keys.count }.by(-1)
- end
-
- it 'should return 404 Not Found with invalid ID' do
- delete v3_api("/projects/#{project.id}/#{path}/404", admin)
-
- expect(response).to have_gitlab_http_status(404)
- end
- end
-
- describe "POST /projects/:id/#{path}/:key_id/enable" do
- let(:project2) { create(:project) }
-
- context 'when the user can admin the project' do
- it 'enables the key' do
- expect do
- post v3_api("/projects/#{project2.id}/#{path}/#{deploy_key.id}/enable", admin)
- end.to change { project2.deploy_keys.count }.from(0).to(1)
-
- expect(response).to have_gitlab_http_status(201)
- expect(json_response['id']).to eq(deploy_key.id)
- end
- end
-
- context 'when authenticated as non-admin user' do
- it 'should return a 404 error' do
- post v3_api("/projects/#{project2.id}/#{path}/#{deploy_key.id}/enable", user)
-
- expect(response).to have_gitlab_http_status(404)
- end
- end
- end
-
- describe "DELETE /projects/:id/deploy_keys/:key_id/disable" do
- context 'when the user can admin the project' do
- it 'disables the key' do
- expect do
- delete v3_api("/projects/#{project.id}/#{path}/#{deploy_key.id}/disable", admin)
- end.to change { project.deploy_keys.count }.from(1).to(0)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['id']).to eq(deploy_key.id)
- end
- end
-
- context 'when authenticated as non-admin user' do
- it 'should return a 404 error' do
- delete v3_api("/projects/#{project.id}/#{path}/#{deploy_key.id}/disable", user)
-
- expect(response).to have_gitlab_http_status(404)
- end
- end
- end
- end
-end
diff --git a/spec/requests/api/v3/deployments_spec.rb b/spec/requests/api/v3/deployments_spec.rb
deleted file mode 100644
index ac86fbea498..00000000000
--- a/spec/requests/api/v3/deployments_spec.rb
+++ /dev/null
@@ -1,69 +0,0 @@
-require 'spec_helper'
-
-describe API::V3::Deployments do
- let(:user) { create(:user) }
- let(:non_member) { create(:user) }
- let(:project) { deployment.environment.project }
- let!(:deployment) { create(:deployment) }
-
- before do
- project.add_master(user)
- end
-
- shared_examples 'a paginated resources' do
- before do
- # Fires the request
- request
- end
-
- it 'has pagination headers' do
- expect(response).to include_pagination_headers
- end
- end
-
- describe 'GET /projects/:id/deployments' do
- context 'as member of the project' do
- it_behaves_like 'a paginated resources' do
- let(:request) { get v3_api("/projects/#{project.id}/deployments", user) }
- end
-
- it 'returns projects deployments' do
- get v3_api("/projects/#{project.id}/deployments", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.size).to eq(1)
- expect(json_response.first['iid']).to eq(deployment.iid)
- expect(json_response.first['sha']).to match /\A\h{40}\z/
- end
- end
-
- context 'as non member' do
- it 'returns a 404 status code' do
- get v3_api("/projects/#{project.id}/deployments", non_member)
-
- expect(response).to have_gitlab_http_status(404)
- end
- end
- end
-
- describe 'GET /projects/:id/deployments/:deployment_id' do
- context 'as a member of the project' do
- it 'returns the projects deployment' do
- get v3_api("/projects/#{project.id}/deployments/#{deployment.id}", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['sha']).to match /\A\h{40}\z/
- expect(json_response['id']).to eq(deployment.id)
- end
- end
-
- context 'as non member' do
- it 'returns a 404 status code' do
- get v3_api("/projects/#{project.id}/deployments/#{deployment.id}", non_member)
-
- expect(response).to have_gitlab_http_status(404)
- end
- end
- end
-end
diff --git a/spec/requests/api/v3/environments_spec.rb b/spec/requests/api/v3/environments_spec.rb
deleted file mode 100644
index 68be5256b64..00000000000
--- a/spec/requests/api/v3/environments_spec.rb
+++ /dev/null
@@ -1,163 +0,0 @@
-require 'spec_helper'
-
-describe API::V3::Environments do
- let(:user) { create(:user) }
- let(:non_member) { create(:user) }
- let(:project) { create(:project, :private, namespace: user.namespace) }
- let!(:environment) { create(:environment, project: project) }
-
- before do
- project.add_master(user)
- 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_gitlab_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_gitlab_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_gitlab_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_gitlab_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_gitlab_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_gitlab_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_gitlab_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_gitlab_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_gitlab_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_gitlab_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_gitlab_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
- delete v3_api("/projects/#{project.id}/environments/#{environment.id}", user)
-
- expect(response).to have_gitlab_http_status(200)
- end
-
- it 'returns a 404 for non existing id' do
- delete v3_api("/projects/#{project.id}/environments/12345", user)
-
- expect(response).to have_gitlab_http_status(404)
- expect(json_response['message']).to eq('404 Not found')
- end
- end
-
- context 'a non member' do
- it 'rejects the request' do
- delete v3_api("/projects/#{project.id}/environments/#{environment.id}", non_member)
-
- expect(response).to have_gitlab_http_status(404)
- end
- end
- end
-end
diff --git a/spec/requests/api/v3/files_spec.rb b/spec/requests/api/v3/files_spec.rb
deleted file mode 100644
index 26a3d8870a0..00000000000
--- a/spec/requests/api/v3/files_spec.rb
+++ /dev/null
@@ -1,283 +0,0 @@
-require 'spec_helper'
-
-describe API::V3::Files do
- # I have to remove periods from the end of the name
- # This happened when the user's name had a suffix (i.e. "Sr.")
- # This seems to be what git does under the hood. For example, this commit:
- #
- # $ git commit --author='Foo Sr. <foo@example.com>' -m 'Where's my trailing period?'
- #
- # results in this:
- #
- # $ git show --pretty
- # ...
- # Author: Foo Sr <foo@example.com>
- # ...
-
- let(:user) { create(:user) }
- let!(:project) { create(:project, :repository, namespace: user.namespace ) }
- let(:guest) { create(:user) { |u| project.add_guest(u) } }
- let(:file_path) { 'files/ruby/popen.rb' }
- let(:params) do
- {
- file_path: file_path,
- ref: 'master'
- }
- end
- let(:author_email) { 'user@example.org' }
- let(:author_name) { 'John Doe' }
-
- before { project.add_developer(user) }
-
- describe "GET /projects/:id/repository/files" do
- let(:route) { "/projects/#{project.id}/repository/files" }
-
- shared_examples_for 'repository files' do
- it "returns file info" do
- get v3_api(route, current_user), params
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['file_path']).to eq(file_path)
- expect(json_response['file_name']).to eq('popen.rb')
- expect(json_response['last_commit_id']).to eq('570e7b2abdd848b95f2f578043fc23bd6f6fd24d')
- expect(Base64.decode64(json_response['content']).lines.first).to eq("require 'fileutils'\n")
- end
-
- context 'when no params are given' do
- it_behaves_like '400 response' do
- let(:request) { get v3_api(route, current_user) }
- end
- end
-
- context 'when file_path does not exist' do
- let(:params) do
- {
- file_path: 'app/models/application.rb',
- ref: 'master'
- }
- end
-
- it_behaves_like '404 response' do
- let(:request) { get v3_api(route, current_user), params }
- let(:message) { '404 File Not Found' }
- end
- end
-
- context 'when repository is disabled' do
- include_context 'disabled repository'
-
- it_behaves_like '403 response' do
- let(:request) { get v3_api(route, current_user), params }
- end
- end
- end
-
- context 'when unauthenticated', 'and project is public' do
- it_behaves_like 'repository files' do
- let(:project) { create(:project, :public, :repository) }
- let(:current_user) { nil }
- end
- end
-
- context 'when unauthenticated', 'and project is private' do
- it_behaves_like '404 response' do
- let(:request) { get v3_api(route), params }
- let(:message) { '404 Project Not Found' }
- end
- end
-
- context 'when authenticated', 'as a developer' do
- it_behaves_like 'repository files' do
- let(:current_user) { user }
- end
- end
-
- context 'when authenticated', 'as a guest' do
- it_behaves_like '403 response' do
- let(:request) { get v3_api(route, guest), params }
- end
- end
- end
-
- describe "POST /projects/:id/repository/files" do
- let(:valid_params) do
- {
- file_path: 'newfile.rb',
- branch_name: 'master',
- content: 'puts 8',
- commit_message: 'Added newfile'
- }
- end
-
- it "creates a new file in project repo" do
- post v3_api("/projects/#{project.id}/repository/files", user), valid_params
-
- expect(response).to have_gitlab_http_status(201)
- expect(json_response['file_path']).to eq('newfile.rb')
- last_commit = project.repository.commit.raw
- expect(last_commit.author_email).to eq(user.email)
- expect(last_commit.author_name).to eq(user.name)
- end
-
- it "returns a 400 bad request if no params given" do
- post v3_api("/projects/#{project.id}/repository/files", user)
-
- expect(response).to have_gitlab_http_status(400)
- end
-
- it "returns a 400 if editor fails to create file" do
- allow_any_instance_of(Repository).to receive(:create_file)
- .and_raise(Gitlab::Git::CommitError, 'Cannot create file')
-
- post v3_api("/projects/#{project.id}/repository/files", user), valid_params
-
- expect(response).to have_gitlab_http_status(400)
- end
-
- context "when specifying an author" do
- it "creates a new file with the specified author" do
- valid_params.merge!(author_email: author_email, author_name: author_name)
-
- post v3_api("/projects/#{project.id}/repository/files", user), valid_params
-
- expect(response).to have_gitlab_http_status(201)
- last_commit = project.repository.commit.raw
- expect(last_commit.author_email).to eq(author_email)
- expect(last_commit.author_name).to eq(author_name)
- end
- end
-
- context 'when the repo is empty' do
- let!(:project) { create(:project_empty_repo, namespace: user.namespace ) }
-
- it "creates a new file in project repo" do
- post v3_api("/projects/#{project.id}/repository/files", user), valid_params
-
- expect(response).to have_gitlab_http_status(201)
- expect(json_response['file_path']).to eq('newfile.rb')
- last_commit = project.repository.commit.raw
- expect(last_commit.author_email).to eq(user.email)
- expect(last_commit.author_name).to eq(user.name)
- end
- end
- end
-
- describe "PUT /projects/:id/repository/files" do
- let(:valid_params) do
- {
- file_path: file_path,
- branch_name: 'master',
- content: 'puts 8',
- commit_message: 'Changed file'
- }
- end
-
- it "updates existing file in project repo" do
- put v3_api("/projects/#{project.id}/repository/files", user), valid_params
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['file_path']).to eq(file_path)
- last_commit = project.repository.commit.raw
- expect(last_commit.author_email).to eq(user.email)
- expect(last_commit.author_name).to eq(user.name)
- end
-
- it "returns a 400 bad request if no params given" do
- put v3_api("/projects/#{project.id}/repository/files", user)
-
- expect(response).to have_gitlab_http_status(400)
- end
-
- context "when specifying an author" do
- it "updates a file with the specified author" do
- valid_params.merge!(author_email: author_email, author_name: author_name, content: "New content")
-
- put v3_api("/projects/#{project.id}/repository/files", user), valid_params
-
- expect(response).to have_gitlab_http_status(200)
- last_commit = project.repository.commit.raw
- expect(last_commit.author_email).to eq(author_email)
- expect(last_commit.author_name).to eq(author_name)
- end
- end
- end
-
- describe "DELETE /projects/:id/repository/files" do
- let(:valid_params) do
- {
- file_path: file_path,
- branch_name: 'master',
- commit_message: 'Changed file'
- }
- end
-
- it "deletes existing file in project repo" do
- delete v3_api("/projects/#{project.id}/repository/files", user), valid_params
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['file_path']).to eq(file_path)
- last_commit = project.repository.commit.raw
- expect(last_commit.author_email).to eq(user.email)
- expect(last_commit.author_name).to eq(user.name)
- end
-
- it "returns a 400 bad request if no params given" do
- delete v3_api("/projects/#{project.id}/repository/files", user)
-
- expect(response).to have_gitlab_http_status(400)
- end
-
- it "returns a 400 if fails to delete file" do
- allow_any_instance_of(Repository).to receive(:delete_file).and_raise(Gitlab::Git::CommitError, 'Cannot delete file')
-
- delete v3_api("/projects/#{project.id}/repository/files", user), valid_params
-
- expect(response).to have_gitlab_http_status(400)
- end
-
- context "when specifying an author" do
- it "removes a file with the specified author" do
- valid_params.merge!(author_email: author_email, author_name: author_name)
-
- delete v3_api("/projects/#{project.id}/repository/files", user), valid_params
-
- expect(response).to have_gitlab_http_status(200)
- last_commit = project.repository.commit.raw
- expect(last_commit.author_email).to eq(author_email)
- expect(last_commit.author_name).to eq(author_name)
- end
- end
- end
-
- describe "POST /projects/:id/repository/files with binary file" do
- let(:file_path) { 'test.bin' }
- let(:put_params) do
- {
- file_path: file_path,
- branch_name: 'master',
- content: 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEUAAACnej3aAAAAAXRSTlMAQObYZgAAAApJREFUCNdjYAAAAAIAAeIhvDMAAAAASUVORK5CYII=',
- commit_message: 'Binary file with a \n should not be touched',
- encoding: 'base64'
- }
- end
- let(:get_params) do
- {
- file_path: file_path,
- ref: 'master'
- }
- end
-
- before do
- post v3_api("/projects/#{project.id}/repository/files", user), put_params
- end
-
- it "remains unchanged" do
- get v3_api("/projects/#{project.id}/repository/files", user), get_params
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['file_path']).to eq(file_path)
- expect(json_response['file_name']).to eq(file_path)
- expect(json_response['content']).to eq(put_params[:content])
- end
- end
-end
diff --git a/spec/requests/api/v3/groups_spec.rb b/spec/requests/api/v3/groups_spec.rb
deleted file mode 100644
index 34d4b8e9565..00000000000
--- a/spec/requests/api/v3/groups_spec.rb
+++ /dev/null
@@ -1,566 +0,0 @@
-require 'spec_helper'
-
-describe API::V3::Groups do
- 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(:project, namespace: group1) }
- let!(:project2) { create(:project, namespace: group2) }
- let!(:project3) { create(: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_gitlab_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_gitlab_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_gitlab_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_gitlab_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_gitlab_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_gitlab_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_gitlab_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_gitlab_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_gitlab_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_gitlab_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_gitlab_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
- get v3_api('/groups/owned')
-
- expect(response).to have_gitlab_http_status(401)
- end
- end
-
- context 'when authenticated as group owner' do
- it 'returns an array of groups the user owns' do
- get v3_api('/groups/owned', user2)
-
- expect(response).to have_gitlab_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response.first['name']).to eq(group2.name)
- end
- end
- end
-
- describe "GET /groups/:id" do
- context "when authenticated as user" do
- it "returns one of user1's groups" do
- project = create(:project, namespace: group2, path: 'Foo')
- create(:project_group_link, project: project, group: group1)
-
- get v3_api("/groups/#{group1.id}", user1)
-
- expect(response).to have_gitlab_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(only_path: false))
- 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_gitlab_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_gitlab_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_gitlab_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_gitlab_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_gitlab_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_gitlab_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_gitlab_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_gitlab_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_gitlab_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_gitlab_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_gitlab_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_gitlab_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_gitlab_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_gitlab_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(:project, :public, path: 'test1', group: group1)
-
- get v3_api("/groups/#{group1.id}/projects", user1), visibility: 'public'
-
- expect(response).to have_gitlab_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_gitlab_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_gitlab_http_status(404)
- end
-
- it "only returns projects to which user has access" do
- project3.add_developer(user3)
-
- get v3_api("/groups/#{group1.id}/projects", user3)
-
- expect(response).to have_gitlab_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_gitlab_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_gitlab_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_gitlab_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_gitlab_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_gitlab_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_gitlab_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_gitlab_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_gitlab_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_gitlab_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", :nested_groups 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_gitlab_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_gitlab_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_gitlab_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_gitlab_http_status(400)
- end
- end
- end
-
- describe "DELETE /groups/:id" do
- context "when authenticated as user" do
- it "removes group" do
- Sidekiq::Testing.fake! do
- expect { delete v3_api("/groups/#{group1.id}", user1) }.to change(GroupDestroyWorker.jobs, :size).by(1)
- end
-
- expect(response).to have_gitlab_http_status(202)
- 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_gitlab_http_status(403)
- end
-
- it "does not remove a non existing group" do
- delete v3_api("/groups/1328", user1)
-
- expect(response).to have_gitlab_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_gitlab_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_gitlab_http_status(202)
- end
-
- it "does not remove a non existing group" do
- delete v3_api("/groups/1328", admin)
-
- expect(response).to have_gitlab_http_status(404)
- end
- end
- end
-
- describe "POST /groups/:id/projects/:project_id" do
- let(:project) { create(:project) }
- let(:project_path) { CGI.escape(project.full_path) }
-
- before 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_gitlab_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_gitlab_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_gitlab_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_gitlab_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_gitlab_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_gitlab_http_status(404)
- end
- end
- end
- end
- end
-end
diff --git a/spec/requests/api/v3/issues_spec.rb b/spec/requests/api/v3/issues_spec.rb
deleted file mode 100644
index 11b5469be7b..00000000000
--- a/spec/requests/api/v3/issues_spec.rb
+++ /dev/null
@@ -1,1298 +0,0 @@
-require 'spec_helper'
-
-describe API::V3::Issues do
- set(:user) { create(:user) }
- set(:user2) { create(:user) }
- set(:non_member) { create(:user) }
- set(:guest) { create(:user) }
- set(:author) { create(:author) }
- set(:assignee) { create(:assignee) }
- set(:admin) { create(:user, :admin) }
- let!(:project) { create(:project, :public, creator_id: user.id, namespace: user.namespace ) }
- let!(:closed_issue) do
- create :closed_issue,
- author: user,
- assignees: [user],
- project: project,
- state: :closed,
- milestone: milestone,
- created_at: generate(:past_time),
- updated_at: 3.hours.ago
- end
- let!(:confidential_issue) do
- create :issue,
- :confidential,
- project: project,
- author: author,
- assignees: [assignee],
- created_at: generate(:past_time),
- updated_at: 2.hours.ago
- end
- let!(:issue) do
- create :issue,
- author: user,
- assignees: [user],
- project: project,
- milestone: milestone,
- created_at: generate(:past_time),
- updated_at: 1.hour.ago
- end
- let!(:label) do
- create(:label, title: 'label', color: '#FFAABB', project: project)
- end
- let!(:label_link) { create(:label_link, label: label, target: issue) }
- let!(:milestone) { create(:milestone, title: '1.0.0', project: project) }
- let!(:empty_milestone) do
- create(:milestone, title: '2.0.0', project: project)
- end
- let!(:note) { create(:note_on_issue, author: user, project: project, noteable: issue) }
-
- let(:no_milestone_title) { URI.escape(Milestone::None.title) }
-
- before do
- project.add_reporter(user)
- project.add_guest(guest)
- end
-
- describe "GET /issues" do
- context "when unauthenticated" do
- it "returns authentication error" do
- get v3_api("/issues")
-
- expect(response).to have_gitlab_http_status(401)
- end
- end
-
- context "when authenticated" do
- it "returns an array of issues" do
- get v3_api("/issues", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.first['title']).to eq(issue.title)
- expect(json_response.last).to have_key('web_url')
- end
-
- it 'returns an array of closed issues' do
- get v3_api('/issues?state=closed', user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(1)
- expect(json_response.first['id']).to eq(closed_issue.id)
- end
-
- it 'returns an array of opened issues' do
- get v3_api('/issues?state=opened', user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(1)
- expect(json_response.first['id']).to eq(issue.id)
- end
-
- it 'returns an array of all issues' do
- get v3_api('/issues?state=all', user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(2)
- expect(json_response.first['id']).to eq(issue.id)
- expect(json_response.second['id']).to eq(closed_issue.id)
- end
-
- it 'returns an array of labeled issues' do
- get v3_api("/issues?labels=#{label.title}", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(1)
- expect(json_response.first['labels']).to eq([label.title])
- end
-
- it 'returns an array of labeled issues when at least one label matches' do
- get v3_api("/issues?labels=#{label.title},foo,bar", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(1)
- expect(json_response.first['labels']).to eq([label.title])
- end
-
- it 'returns an empty array if no issue matches labels' do
- get v3_api('/issues?labels=foo,bar', user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(0)
- end
-
- it 'returns an array of labeled issues matching given state' do
- get v3_api("/issues?labels=#{label.title}&state=opened", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(1)
- expect(json_response.first['labels']).to eq([label.title])
- expect(json_response.first['state']).to eq('opened')
- end
-
- it 'returns an empty array if no issue matches labels and state filters' do
- get v3_api("/issues?labels=#{label.title}&state=closed", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(0)
- end
-
- it 'returns an empty array if no issue matches milestone' do
- get v3_api("/issues?milestone=#{empty_milestone.title}", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(0)
- end
-
- it 'returns an empty array if milestone does not exist' do
- get v3_api("/issues?milestone=foo", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(0)
- end
-
- it 'returns an array of issues in given milestone' do
- get v3_api("/issues?milestone=#{milestone.title}", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(2)
- expect(json_response.first['id']).to eq(issue.id)
- expect(json_response.second['id']).to eq(closed_issue.id)
- end
-
- it 'returns an array of issues matching state in milestone' do
- get v3_api("/issues?milestone=#{milestone.title}", user),
- '&state=closed'
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(1)
- expect(json_response.first['id']).to eq(closed_issue.id)
- end
-
- it 'returns an array of issues with no milestone' do
- get v3_api("/issues?milestone=#{no_milestone_title}", author)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(1)
- expect(json_response.first['id']).to eq(confidential_issue.id)
- end
-
- it 'sorts by created_at descending by default' do
- get v3_api('/issues', user)
-
- response_dates = json_response.map { |issue| issue['created_at'] }
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(response_dates).to eq(response_dates.sort.reverse)
- end
-
- it 'sorts ascending when requested' do
- get v3_api('/issues?sort=asc', user)
-
- response_dates = json_response.map { |issue| issue['created_at'] }
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(response_dates).to eq(response_dates.sort)
- end
-
- it 'sorts by updated_at descending when requested' do
- get v3_api('/issues?order_by=updated_at', user)
-
- response_dates = json_response.map { |issue| issue['updated_at'] }
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(response_dates).to eq(response_dates.sort.reverse)
- end
-
- it 'sorts by updated_at ascending when requested' do
- get v3_api('/issues?order_by=updated_at&sort=asc', user)
-
- response_dates = json_response.map { |issue| issue['updated_at'] }
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(response_dates).to eq(response_dates.sort)
- end
-
- it 'matches V3 response schema' do
- get v3_api('/issues', user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(response).to match_response_schema('public_api/v3/issues')
- end
- end
- end
-
- describe "GET /groups/:id/issues" do
- let!(:group) { create(:group) }
- let!(:group_project) { create(:project, :public, creator_id: user.id, namespace: group) }
- let!(:group_closed_issue) do
- create :closed_issue,
- author: user,
- assignees: [user],
- project: group_project,
- state: :closed,
- milestone: group_milestone,
- updated_at: 3.hours.ago
- end
- let!(:group_confidential_issue) do
- create :issue,
- :confidential,
- project: group_project,
- author: author,
- assignees: [assignee],
- updated_at: 2.hours.ago
- end
- let!(:group_issue) do
- create :issue,
- author: user,
- assignees: [user],
- project: group_project,
- milestone: group_milestone,
- updated_at: 1.hour.ago
- end
- let!(:group_label) do
- create(:label, title: 'group_lbl', color: '#FFAABB', project: group_project)
- end
- let!(:group_label_link) { create(:label_link, label: group_label, target: group_issue) }
- let!(:group_milestone) { create(:milestone, title: '3.0.0', project: group_project) }
- let!(:group_empty_milestone) do
- create(:milestone, title: '4.0.0', project: group_project)
- end
- let!(:group_note) { create(:note_on_issue, author: user, project: group_project, noteable: group_issue) }
-
- before do
- group_project.add_reporter(user)
- end
- let(:base_url) { "/groups/#{group.id}/issues" }
-
- it 'returns all group issues (including opened and closed)' do
- get v3_api(base_url, admin)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(3)
- end
-
- it 'returns group issues without confidential issues for non project members' do
- get v3_api("#{base_url}?state=opened", non_member)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(1)
- expect(json_response.first['title']).to eq(group_issue.title)
- end
-
- it 'returns group confidential issues for author' do
- get v3_api("#{base_url}?state=opened", author)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(2)
- end
-
- it 'returns group confidential issues for assignee' do
- get v3_api("#{base_url}?state=opened", assignee)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(2)
- end
-
- it 'returns group issues with confidential issues for project members' do
- get v3_api("#{base_url}?state=opened", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(2)
- end
-
- it 'returns group confidential issues for admin' do
- get v3_api("#{base_url}?state=opened", admin)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(2)
- end
-
- it 'returns an array of labeled group issues' do
- get v3_api("#{base_url}?labels=#{group_label.title}", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(1)
- expect(json_response.first['labels']).to eq([group_label.title])
- end
-
- it 'returns an array of labeled group issues where all labels match' do
- get v3_api("#{base_url}?labels=#{group_label.title},foo,bar", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(0)
- end
-
- it 'returns an empty array if no group issue matches labels' do
- get v3_api("#{base_url}?labels=foo,bar", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(0)
- end
-
- it 'returns an empty array if no issue matches milestone' do
- get v3_api("#{base_url}?milestone=#{group_empty_milestone.title}", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(0)
- end
-
- it 'returns an empty array if milestone does not exist' do
- get v3_api("#{base_url}?milestone=foo", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(0)
- end
-
- it 'returns an array of issues in given milestone' do
- get v3_api("#{base_url}?state=opened&milestone=#{group_milestone.title}", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(1)
- expect(json_response.first['id']).to eq(group_issue.id)
- end
-
- it 'returns an array of issues matching state in milestone' do
- get v3_api("#{base_url}?milestone=#{group_milestone.title}", user),
- '&state=closed'
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(1)
- expect(json_response.first['id']).to eq(group_closed_issue.id)
- end
-
- it 'returns an array of issues with no milestone' do
- get v3_api("#{base_url}?milestone=#{no_milestone_title}", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(1)
- expect(json_response.first['id']).to eq(group_confidential_issue.id)
- end
-
- it 'sorts by created_at descending by default' do
- get v3_api(base_url, user)
-
- response_dates = json_response.map { |issue| issue['created_at'] }
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(response_dates).to eq(response_dates.sort.reverse)
- end
-
- it 'sorts ascending when requested' do
- get v3_api("#{base_url}?sort=asc", user)
-
- response_dates = json_response.map { |issue| issue['created_at'] }
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(response_dates).to eq(response_dates.sort)
- end
-
- it 'sorts by updated_at descending when requested' do
- get v3_api("#{base_url}?order_by=updated_at", user)
-
- response_dates = json_response.map { |issue| issue['updated_at'] }
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(response_dates).to eq(response_dates.sort.reverse)
- end
-
- it 'sorts by updated_at ascending when requested' do
- get v3_api("#{base_url}?order_by=updated_at&sort=asc", user)
-
- response_dates = json_response.map { |issue| issue['updated_at'] }
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(response_dates).to eq(response_dates.sort)
- end
- end
-
- describe "GET /projects/:id/issues" do
- let(:base_url) { "/projects/#{project.id}" }
-
- it 'returns 404 when project does not exist' do
- get v3_api('/projects/1000/issues', non_member)
-
- expect(response).to have_gitlab_http_status(404)
- end
-
- it "returns 404 on private projects for other users" do
- private_project = create(:project, :private)
- create(:issue, project: private_project)
-
- get v3_api("/projects/#{private_project.id}/issues", non_member)
-
- expect(response).to have_gitlab_http_status(404)
- end
-
- it 'returns no issues when user has access to project but not issues' do
- restricted_project = create(:project, :public, issues_access_level: ProjectFeature::PRIVATE)
- create(:issue, project: restricted_project)
-
- get v3_api("/projects/#{restricted_project.id}/issues", non_member)
-
- expect(json_response).to eq([])
- end
-
- it 'returns project issues without confidential issues for non project members' do
- get v3_api("#{base_url}/issues", non_member)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(2)
- expect(json_response.first['title']).to eq(issue.title)
- end
-
- it 'returns project issues without confidential issues for project members with guest role' do
- get v3_api("#{base_url}/issues", guest)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(2)
- expect(json_response.first['title']).to eq(issue.title)
- end
-
- it 'returns project confidential issues for author' do
- get v3_api("#{base_url}/issues", author)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(3)
- expect(json_response.first['title']).to eq(issue.title)
- end
-
- it 'returns project confidential issues for assignee' do
- get v3_api("#{base_url}/issues", assignee)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(3)
- expect(json_response.first['title']).to eq(issue.title)
- end
-
- it 'returns project issues with confidential issues for project members' do
- get v3_api("#{base_url}/issues", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(3)
- expect(json_response.first['title']).to eq(issue.title)
- end
-
- it 'returns project confidential issues for admin' do
- get v3_api("#{base_url}/issues", admin)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(3)
- expect(json_response.first['title']).to eq(issue.title)
- end
-
- it 'returns an array of labeled project issues' do
- get v3_api("#{base_url}/issues?labels=#{label.title}", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(1)
- expect(json_response.first['labels']).to eq([label.title])
- end
-
- it 'returns an array of labeled project issues where all labels match' do
- get v3_api("#{base_url}/issues?labels=#{label.title},foo,bar", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(1)
- expect(json_response.first['labels']).to eq([label.title])
- end
-
- it 'returns an empty array if no project issue matches labels' do
- get v3_api("#{base_url}/issues?labels=foo,bar", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(0)
- end
-
- it 'returns an empty array if no issue matches milestone' do
- get v3_api("#{base_url}/issues?milestone=#{empty_milestone.title}", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(0)
- end
-
- it 'returns an empty array if milestone does not exist' do
- get v3_api("#{base_url}/issues?milestone=foo", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(0)
- end
-
- it 'returns an array of issues in given milestone' do
- get v3_api("#{base_url}/issues?milestone=#{milestone.title}", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(2)
- expect(json_response.first['id']).to eq(issue.id)
- expect(json_response.second['id']).to eq(closed_issue.id)
- end
-
- it 'returns an array of issues matching state in milestone' do
- get v3_api("#{base_url}/issues?milestone=#{milestone.title}", user),
- '&state=closed'
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(1)
- expect(json_response.first['id']).to eq(closed_issue.id)
- end
-
- it 'returns an array of issues with no milestone' do
- get v3_api("#{base_url}/issues?milestone=#{no_milestone_title}", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(1)
- expect(json_response.first['id']).to eq(confidential_issue.id)
- end
-
- it 'sorts by created_at descending by default' do
- get v3_api("#{base_url}/issues", user)
-
- response_dates = json_response.map { |issue| issue['created_at'] }
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(response_dates).to eq(response_dates.sort.reverse)
- end
-
- it 'sorts ascending when requested' do
- get v3_api("#{base_url}/issues?sort=asc", user)
-
- response_dates = json_response.map { |issue| issue['created_at'] }
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(response_dates).to eq(response_dates.sort)
- end
-
- it 'sorts by updated_at descending when requested' do
- get v3_api("#{base_url}/issues?order_by=updated_at", user)
-
- response_dates = json_response.map { |issue| issue['updated_at'] }
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(response_dates).to eq(response_dates.sort.reverse)
- end
-
- it 'sorts by updated_at ascending when requested' do
- get v3_api("#{base_url}/issues?order_by=updated_at&sort=asc", user)
-
- response_dates = json_response.map { |issue| issue['updated_at'] }
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(response_dates).to eq(response_dates.sort)
- end
- end
-
- describe "GET /projects/:id/issues/:issue_id" do
- it 'exposes known attributes' do
- get v3_api("/projects/#{project.id}/issues/#{issue.id}", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['id']).to eq(issue.id)
- expect(json_response['iid']).to eq(issue.iid)
- expect(json_response['project_id']).to eq(issue.project.id)
- expect(json_response['title']).to eq(issue.title)
- expect(json_response['description']).to eq(issue.description)
- expect(json_response['state']).to eq(issue.state)
- expect(json_response['created_at']).to be_present
- expect(json_response['updated_at']).to be_present
- expect(json_response['labels']).to eq(issue.label_names)
- expect(json_response['milestone']).to be_a Hash
- expect(json_response['assignee']).to be_a Hash
- expect(json_response['author']).to be_a Hash
- expect(json_response['confidential']).to be_falsy
- end
-
- it "returns a project issue by id" do
- get v3_api("/projects/#{project.id}/issues/#{issue.id}", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['title']).to eq(issue.title)
- expect(json_response['iid']).to eq(issue.iid)
- end
-
- it 'returns a project issue by iid' do
- get v3_api("/projects/#{project.id}/issues?iid=#{issue.iid}", user)
-
- expect(response.status).to eq 200
- expect(json_response.length).to eq 1
- expect(json_response.first['title']).to eq issue.title
- expect(json_response.first['id']).to eq issue.id
- expect(json_response.first['iid']).to eq issue.iid
- end
-
- it 'returns an empty array for an unknown project issue iid' do
- get v3_api("/projects/#{project.id}/issues?iid=#{issue.iid + 10}", user)
-
- expect(response.status).to eq 200
- expect(json_response.length).to eq 0
- end
-
- it "returns 404 if issue id not found" do
- get v3_api("/projects/#{project.id}/issues/54321", user)
-
- expect(response).to have_gitlab_http_status(404)
- end
-
- context 'confidential issues' do
- it "returns 404 for non project members" do
- get v3_api("/projects/#{project.id}/issues/#{confidential_issue.id}", non_member)
-
- expect(response).to have_gitlab_http_status(404)
- end
-
- it "returns 404 for project members with guest role" do
- get v3_api("/projects/#{project.id}/issues/#{confidential_issue.id}", guest)
-
- expect(response).to have_gitlab_http_status(404)
- end
-
- it "returns confidential issue for project members" do
- get v3_api("/projects/#{project.id}/issues/#{confidential_issue.id}", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['title']).to eq(confidential_issue.title)
- expect(json_response['iid']).to eq(confidential_issue.iid)
- end
-
- it "returns confidential issue for author" do
- get v3_api("/projects/#{project.id}/issues/#{confidential_issue.id}", author)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['title']).to eq(confidential_issue.title)
- expect(json_response['iid']).to eq(confidential_issue.iid)
- end
-
- it "returns confidential issue for assignee" do
- get v3_api("/projects/#{project.id}/issues/#{confidential_issue.id}", assignee)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['title']).to eq(confidential_issue.title)
- expect(json_response['iid']).to eq(confidential_issue.iid)
- end
-
- it "returns confidential issue for admin" do
- get v3_api("/projects/#{project.id}/issues/#{confidential_issue.id}", admin)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['title']).to eq(confidential_issue.title)
- expect(json_response['iid']).to eq(confidential_issue.iid)
- end
- end
- end
-
- describe "POST /projects/:id/issues" do
- it 'creates a new project issue' do
- post v3_api("/projects/#{project.id}/issues", user),
- title: 'new issue', labels: 'label, label2', assignee_id: assignee.id
-
- expect(response).to have_gitlab_http_status(201)
- expect(json_response['title']).to eq('new issue')
- expect(json_response['description']).to be_nil
- expect(json_response['labels']).to eq(%w(label label2))
- expect(json_response['confidential']).to be_falsy
- expect(json_response['assignee']['name']).to eq(assignee.name)
- end
-
- it 'creates a new confidential project issue' do
- post v3_api("/projects/#{project.id}/issues", user),
- title: 'new issue', confidential: true
-
- expect(response).to have_gitlab_http_status(201)
- expect(json_response['title']).to eq('new issue')
- expect(json_response['confidential']).to be_truthy
- end
-
- it 'creates a new confidential project issue with a different param' do
- post v3_api("/projects/#{project.id}/issues", user),
- title: 'new issue', confidential: 'y'
-
- expect(response).to have_gitlab_http_status(201)
- expect(json_response['title']).to eq('new issue')
- expect(json_response['confidential']).to be_truthy
- end
-
- it 'creates a public issue when confidential param is false' do
- post v3_api("/projects/#{project.id}/issues", user),
- title: 'new issue', confidential: false
-
- expect(response).to have_gitlab_http_status(201)
- expect(json_response['title']).to eq('new issue')
- expect(json_response['confidential']).to be_falsy
- end
-
- it 'creates a public issue when confidential param is invalid' do
- post v3_api("/projects/#{project.id}/issues", user),
- title: 'new issue', confidential: 'foo'
-
- expect(response).to have_gitlab_http_status(400)
- expect(json_response['error']).to eq('confidential is invalid')
- end
-
- it "returns a 400 bad request if title not given" do
- post v3_api("/projects/#{project.id}/issues", user), labels: 'label, label2'
-
- expect(response).to have_gitlab_http_status(400)
- end
-
- it 'allows special label names' do
- post v3_api("/projects/#{project.id}/issues", user),
- title: 'new issue',
- labels: 'label, label?, label&foo, ?, &'
-
- expect(response.status).to eq(201)
- expect(json_response['labels']).to include 'label'
- expect(json_response['labels']).to include 'label?'
- expect(json_response['labels']).to include 'label&foo'
- expect(json_response['labels']).to include '?'
- expect(json_response['labels']).to include '&'
- end
-
- it 'returns 400 if title is too long' do
- post v3_api("/projects/#{project.id}/issues", user),
- title: 'g' * 256
-
- expect(response).to have_gitlab_http_status(400)
- expect(json_response['message']['title']).to eq([
- 'is too long (maximum is 255 characters)'
- ])
- end
-
- context 'resolving issues in a merge request' do
- set(:diff_note_on_merge_request) { create(:diff_note_on_merge_request) }
- let(:discussion) { diff_note_on_merge_request.to_discussion }
- let(:merge_request) { discussion.noteable }
- let(:project) { merge_request.source_project }
- before do
- project.add_master(user)
- post v3_api("/projects/#{project.id}/issues", user),
- title: 'New Issue',
- merge_request_for_resolving_discussions: merge_request.iid
- end
-
- it 'creates a new project issue' do
- expect(response).to have_gitlab_http_status(:created)
- end
-
- it 'resolves the discussions in a merge request' do
- discussion.first_note.reload
-
- expect(discussion.resolved?).to be(true)
- end
-
- it 'assigns a description to the issue mentioning the merge request' do
- expect(json_response['description']).to include(merge_request.to_reference)
- end
- end
-
- context 'with due date' do
- it 'creates a new project issue' do
- due_date = 2.weeks.from_now.strftime('%Y-%m-%d')
-
- post v3_api("/projects/#{project.id}/issues", user),
- title: 'new issue', due_date: due_date
-
- expect(response).to have_gitlab_http_status(201)
- expect(json_response['title']).to eq('new issue')
- expect(json_response['description']).to be_nil
- expect(json_response['due_date']).to eq(due_date)
- end
- end
-
- context 'when an admin or owner makes the request' do
- it 'accepts the creation date to be set' do
- creation_time = 2.weeks.ago
- post v3_api("/projects/#{project.id}/issues", user),
- title: 'new issue', labels: 'label, label2', created_at: creation_time
-
- expect(response).to have_gitlab_http_status(201)
- expect(Time.parse(json_response['created_at'])).to be_like_time(creation_time)
- end
- end
-
- context 'the user can only read the issue' do
- it 'cannot create new labels' do
- expect do
- post v3_api("/projects/#{project.id}/issues", non_member), title: 'new issue', labels: 'label, label2'
- end.not_to change { project.labels.count }
- end
- end
- end
-
- describe 'POST /projects/:id/issues with spam filtering' do
- before do
- allow_any_instance_of(SpamService).to receive(:check_for_spam?).and_return(true)
- allow_any_instance_of(AkismetService).to receive_messages(spam?: true)
- end
-
- let(:params) do
- {
- title: 'new issue',
- description: 'content here',
- labels: 'label, label2'
- }
- end
-
- it "does not create a new project issue" do
- expect { post v3_api("/projects/#{project.id}/issues", user), params }.not_to change(Issue, :count)
-
- expect(response).to have_gitlab_http_status(400)
- expect(json_response['message']).to eq({ "error" => "Spam detected" })
-
- spam_logs = SpamLog.all
-
- expect(spam_logs.count).to eq(1)
- expect(spam_logs[0].title).to eq('new issue')
- expect(spam_logs[0].description).to eq('content here')
- expect(spam_logs[0].user).to eq(user)
- expect(spam_logs[0].noteable_type).to eq('Issue')
- end
- end
-
- describe "PUT /projects/:id/issues/:issue_id to update only title" do
- it "updates a project issue" do
- put v3_api("/projects/#{project.id}/issues/#{issue.id}", user),
- title: 'updated title'
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['title']).to eq('updated title')
- end
-
- it "returns 404 error if issue id not found" do
- put v3_api("/projects/#{project.id}/issues/44444", user),
- title: 'updated title'
-
- expect(response).to have_gitlab_http_status(404)
- end
-
- it 'allows special label names' do
- put v3_api("/projects/#{project.id}/issues/#{issue.id}", user),
- title: 'updated title',
- labels: 'label, label?, label&foo, ?, &'
-
- expect(response.status).to eq(200)
- expect(json_response['labels']).to include 'label'
- expect(json_response['labels']).to include 'label?'
- expect(json_response['labels']).to include 'label&foo'
- expect(json_response['labels']).to include '?'
- expect(json_response['labels']).to include '&'
- end
-
- context 'confidential issues' do
- it "returns 403 for non project members" do
- put v3_api("/projects/#{project.id}/issues/#{confidential_issue.id}", non_member),
- title: 'updated title'
-
- expect(response).to have_gitlab_http_status(403)
- end
-
- it "returns 403 for project members with guest role" do
- put v3_api("/projects/#{project.id}/issues/#{confidential_issue.id}", guest),
- title: 'updated title'
-
- expect(response).to have_gitlab_http_status(403)
- end
-
- it "updates a confidential issue for project members" do
- put v3_api("/projects/#{project.id}/issues/#{confidential_issue.id}", user),
- title: 'updated title'
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['title']).to eq('updated title')
- end
-
- it "updates a confidential issue for author" do
- put v3_api("/projects/#{project.id}/issues/#{confidential_issue.id}", author),
- title: 'updated title'
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['title']).to eq('updated title')
- end
-
- it "updates a confidential issue for admin" do
- put v3_api("/projects/#{project.id}/issues/#{confidential_issue.id}", admin),
- title: 'updated title'
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['title']).to eq('updated title')
- end
-
- it 'sets an issue to confidential' do
- put v3_api("/projects/#{project.id}/issues/#{issue.id}", user),
- confidential: true
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['confidential']).to be_truthy
- end
-
- it 'makes a confidential issue public' do
- put v3_api("/projects/#{project.id}/issues/#{confidential_issue.id}", user),
- confidential: false
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['confidential']).to be_falsy
- end
-
- it 'does not update a confidential issue with wrong confidential flag' do
- put v3_api("/projects/#{project.id}/issues/#{confidential_issue.id}", user),
- confidential: 'foo'
-
- expect(response).to have_gitlab_http_status(400)
- expect(json_response['error']).to eq('confidential is invalid')
- end
- end
- end
-
- describe 'PUT /projects/:id/issues/:issue_id with spam filtering' do
- let(:params) do
- {
- title: 'updated title',
- description: 'content here',
- labels: 'label, label2'
- }
- end
-
- it "does not create a new project issue" do
- allow_any_instance_of(SpamService).to receive_messages(check_for_spam?: true)
- allow_any_instance_of(AkismetService).to receive_messages(spam?: true)
-
- put v3_api("/projects/#{project.id}/issues/#{issue.id}", user), params
-
- expect(response).to have_gitlab_http_status(400)
- expect(json_response['message']).to eq({ "error" => "Spam detected" })
-
- spam_logs = SpamLog.all
- expect(spam_logs.count).to eq(1)
- expect(spam_logs[0].title).to eq('updated title')
- expect(spam_logs[0].description).to eq('content here')
- expect(spam_logs[0].user).to eq(user)
- expect(spam_logs[0].noteable_type).to eq('Issue')
- end
- end
-
- describe 'PUT /projects/:id/issues/:issue_id to update labels' do
- let!(:label) { create(:label, title: 'dummy', project: project) }
- let!(:label_link) { create(:label_link, label: label, target: issue) }
-
- it 'does not update labels if not present' do
- put v3_api("/projects/#{project.id}/issues/#{issue.id}", user),
- title: 'updated title'
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['labels']).to eq([label.title])
- end
-
- it 'removes all labels' do
- put v3_api("/projects/#{project.id}/issues/#{issue.id}", user), labels: ''
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['labels']).to eq([])
- end
-
- it 'updates labels' do
- put v3_api("/projects/#{project.id}/issues/#{issue.id}", user),
- labels: 'foo,bar'
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['labels']).to include 'foo'
- expect(json_response['labels']).to include 'bar'
- end
-
- it 'allows special label names' do
- put v3_api("/projects/#{project.id}/issues/#{issue.id}", user),
- labels: 'label:foo, label-bar,label_bar,label/bar,label?bar,label&bar,?,&'
-
- expect(response.status).to eq(200)
- expect(json_response['labels']).to include 'label:foo'
- expect(json_response['labels']).to include 'label-bar'
- expect(json_response['labels']).to include 'label_bar'
- expect(json_response['labels']).to include 'label/bar'
- expect(json_response['labels']).to include 'label?bar'
- expect(json_response['labels']).to include 'label&bar'
- expect(json_response['labels']).to include '?'
- expect(json_response['labels']).to include '&'
- end
-
- it 'returns 400 if title is too long' do
- put v3_api("/projects/#{project.id}/issues/#{issue.id}", user),
- title: 'g' * 256
-
- expect(response).to have_gitlab_http_status(400)
- expect(json_response['message']['title']).to eq([
- 'is too long (maximum is 255 characters)'
- ])
- end
- end
-
- describe "PUT /projects/:id/issues/:issue_id to update state and label" do
- it "updates a project issue" do
- put v3_api("/projects/#{project.id}/issues/#{issue.id}", user),
- labels: 'label2', state_event: "close"
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['labels']).to include 'label2'
- expect(json_response['state']).to eq "closed"
- end
-
- it 'reopens a project isssue' do
- put v3_api("/projects/#{project.id}/issues/#{closed_issue.id}", user), state_event: 'reopen'
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['state']).to eq 'opened'
- end
-
- context 'when an admin or owner makes the request' do
- it 'accepts the update date to be set' do
- update_time = 2.weeks.ago
- put v3_api("/projects/#{project.id}/issues/#{issue.id}", user),
- labels: 'label3', state_event: 'close', updated_at: update_time
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['labels']).to include 'label3'
- expect(Time.parse(json_response['updated_at'])).to be_like_time(update_time)
- end
- end
- end
-
- describe 'PUT /projects/:id/issues/:issue_id to update due date' do
- it 'creates a new project issue' do
- due_date = 2.weeks.from_now.strftime('%Y-%m-%d')
-
- put v3_api("/projects/#{project.id}/issues/#{issue.id}", user), due_date: due_date
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['due_date']).to eq(due_date)
- end
- end
-
- describe 'PUT /projects/:id/issues/:issue_id to update assignee' do
- it 'updates an issue with no assignee' do
- put v3_api("/projects/#{project.id}/issues/#{issue.id}", user), assignee_id: 0
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['assignee']).to eq(nil)
- end
-
- it 'updates an issue with assignee' do
- put v3_api("/projects/#{project.id}/issues/#{issue.id}", user), assignee_id: user2.id
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['assignee']['name']).to eq(user2.name)
- end
- end
-
- describe "DELETE /projects/:id/issues/:issue_id" do
- it "rejects a non member from deleting an issue" do
- delete v3_api("/projects/#{project.id}/issues/#{issue.id}", non_member)
-
- expect(response).to have_gitlab_http_status(403)
- end
-
- it "rejects a developer from deleting an issue" do
- delete v3_api("/projects/#{project.id}/issues/#{issue.id}", author)
-
- expect(response).to have_gitlab_http_status(403)
- end
-
- context "when the user is project owner" do
- set(:owner) { create(:user) }
- let(:project) { create(:project, namespace: owner.namespace) }
-
- it "deletes the issue if an admin requests it" do
- delete v3_api("/projects/#{project.id}/issues/#{issue.id}", owner)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['state']).to eq 'opened'
- end
- end
-
- context 'when issue does not exist' do
- it 'returns 404 when trying to move an issue' do
- delete v3_api("/projects/#{project.id}/issues/123", user)
-
- expect(response).to have_gitlab_http_status(404)
- end
- end
- end
-
- describe '/projects/:id/issues/:issue_id/move' do
- let!(:target_project) { create(:project, creator_id: user.id, namespace: user.namespace ) }
- let!(:target_project2) { create(:project, creator_id: non_member.id, namespace: non_member.namespace ) }
-
- it 'moves an issue' do
- post v3_api("/projects/#{project.id}/issues/#{issue.id}/move", user),
- to_project_id: target_project.id
-
- expect(response).to have_gitlab_http_status(201)
- expect(json_response['project_id']).to eq(target_project.id)
- end
-
- context 'when source and target projects are the same' do
- it 'returns 400 when trying to move an issue' do
- post v3_api("/projects/#{project.id}/issues/#{issue.id}/move", user),
- to_project_id: project.id
-
- expect(response).to have_gitlab_http_status(400)
- expect(json_response['message']).to eq('Cannot move issue to project it originates from!')
- end
- end
-
- context 'when the user does not have the permission to move issues' do
- it 'returns 400 when trying to move an issue' do
- post v3_api("/projects/#{project.id}/issues/#{issue.id}/move", user),
- to_project_id: target_project2.id
-
- expect(response).to have_gitlab_http_status(400)
- expect(json_response['message']).to eq('Cannot move issue due to insufficient permissions!')
- end
- end
-
- it 'moves the issue to another namespace if I am admin' do
- post v3_api("/projects/#{project.id}/issues/#{issue.id}/move", admin),
- to_project_id: target_project2.id
-
- expect(response).to have_gitlab_http_status(201)
- expect(json_response['project_id']).to eq(target_project2.id)
- end
-
- context 'when issue does not exist' do
- it 'returns 404 when trying to move an issue' do
- post v3_api("/projects/#{project.id}/issues/123/move", user),
- to_project_id: target_project.id
-
- expect(response).to have_gitlab_http_status(404)
- expect(json_response['message']).to eq('404 Issue Not Found')
- end
- end
-
- context 'when source project does not exist' do
- it 'returns 404 when trying to move an issue' do
- post v3_api("/projects/0/issues/#{issue.id}/move", user),
- to_project_id: target_project.id
-
- expect(response).to have_gitlab_http_status(404)
- expect(json_response['message']).to eq('404 Project Not Found')
- end
- end
-
- context 'when target project does not exist' do
- it 'returns 404 when trying to move an issue' do
- post v3_api("/projects/#{project.id}/issues/#{issue.id}/move", user),
- to_project_id: 0
-
- expect(response).to have_gitlab_http_status(404)
- end
- end
- end
-
- describe 'POST :id/issues/:issue_id/subscription' do
- it 'subscribes to an issue' do
- post v3_api("/projects/#{project.id}/issues/#{issue.id}/subscription", user2)
-
- expect(response).to have_gitlab_http_status(201)
- expect(json_response['subscribed']).to eq(true)
- end
-
- it 'returns 304 if already subscribed' do
- post v3_api("/projects/#{project.id}/issues/#{issue.id}/subscription", user)
-
- expect(response).to have_gitlab_http_status(304)
- end
-
- it 'returns 404 if the issue is not found' do
- post v3_api("/projects/#{project.id}/issues/123/subscription", user)
-
- expect(response).to have_gitlab_http_status(404)
- end
-
- it 'returns 404 if the issue is confidential' do
- post v3_api("/projects/#{project.id}/issues/#{confidential_issue.id}/subscription", non_member)
-
- expect(response).to have_gitlab_http_status(404)
- end
- end
-
- describe 'DELETE :id/issues/:issue_id/subscription' do
- it 'unsubscribes from an issue' do
- delete v3_api("/projects/#{project.id}/issues/#{issue.id}/subscription", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['subscribed']).to eq(false)
- end
-
- it 'returns 304 if not subscribed' do
- delete v3_api("/projects/#{project.id}/issues/#{issue.id}/subscription", user2)
-
- expect(response).to have_gitlab_http_status(304)
- end
-
- it 'returns 404 if the issue is not found' do
- delete v3_api("/projects/#{project.id}/issues/123/subscription", user)
-
- expect(response).to have_gitlab_http_status(404)
- end
-
- it 'returns 404 if the issue is confidential' do
- delete v3_api("/projects/#{project.id}/issues/#{confidential_issue.id}/subscription", non_member)
-
- expect(response).to have_gitlab_http_status(404)
- end
- end
-
- describe 'time tracking endpoints' do
- let(:issuable) { issue }
-
- include_examples 'V3 time tracking endpoints', 'issue'
- end
-end
diff --git a/spec/requests/api/v3/labels_spec.rb b/spec/requests/api/v3/labels_spec.rb
deleted file mode 100644
index cdab4d2bd73..00000000000
--- a/spec/requests/api/v3/labels_spec.rb
+++ /dev/null
@@ -1,169 +0,0 @@
-require 'spec_helper'
-
-describe API::V3::Labels do
- let(:user) { create(:user) }
- let(:project) { create(:project, creator_id: user.id, namespace: user.namespace) }
- let!(:label1) { create(:label, title: 'label1', project: project) }
- let!(:priority_label) { create(:label, title: 'bug', project: project, priority: 3) }
-
- before do
- project.add_master(user)
- end
-
- describe 'GET /projects/:id/labels' do
- it 'returns all available labels to the project' do
- group = create(:group)
- group_label = create(:group_label, title: 'feature', group: group)
- project.update(group: group)
- create(:labeled_issue, project: project, labels: [group_label], author: user)
- create(:labeled_issue, project: project, labels: [label1], author: user, state: :closed)
- create(:labeled_merge_request, labels: [priority_label], author: user, source_project: project )
-
- expected_keys = %w(
- id name color description
- open_issues_count closed_issues_count open_merge_requests_count
- subscribed priority
- )
-
- get v3_api("/projects/#{project.id}/labels", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.size).to eq(3)
- expect(json_response.first.keys).to match_array expected_keys
- expect(json_response.map { |l| l['name'] }).to match_array([group_label.name, priority_label.name, label1.name])
-
- label1_response = json_response.find { |l| l['name'] == label1.title }
- group_label_response = json_response.find { |l| l['name'] == group_label.title }
- priority_label_response = json_response.find { |l| l['name'] == priority_label.title }
-
- expect(label1_response['open_issues_count']).to eq(0)
- expect(label1_response['closed_issues_count']).to eq(1)
- expect(label1_response['open_merge_requests_count']).to eq(0)
- expect(label1_response['name']).to eq(label1.name)
- expect(label1_response['color']).to be_present
- expect(label1_response['description']).to be_nil
- expect(label1_response['priority']).to be_nil
- expect(label1_response['subscribed']).to be_falsey
-
- expect(group_label_response['open_issues_count']).to eq(1)
- expect(group_label_response['closed_issues_count']).to eq(0)
- expect(group_label_response['open_merge_requests_count']).to eq(0)
- expect(group_label_response['name']).to eq(group_label.name)
- expect(group_label_response['color']).to be_present
- expect(group_label_response['description']).to be_nil
- expect(group_label_response['priority']).to be_nil
- expect(group_label_response['subscribed']).to be_falsey
-
- expect(priority_label_response['open_issues_count']).to eq(0)
- expect(priority_label_response['closed_issues_count']).to eq(0)
- expect(priority_label_response['open_merge_requests_count']).to eq(1)
- expect(priority_label_response['name']).to eq(priority_label.name)
- expect(priority_label_response['color']).to be_present
- expect(priority_label_response['description']).to be_nil
- expect(priority_label_response['priority']).to eq(3)
- expect(priority_label_response['subscribed']).to be_falsey
- end
- end
-
- describe "POST /projects/:id/labels/:label_id/subscription" do
- context "when label_id is a label title" do
- it "subscribes to the label" do
- post v3_api("/projects/#{project.id}/labels/#{label1.title}/subscription", user)
-
- expect(response).to have_gitlab_http_status(201)
- expect(json_response["name"]).to eq(label1.title)
- expect(json_response["subscribed"]).to be_truthy
- end
- end
-
- context "when label_id is a label ID" do
- it "subscribes to the label" do
- post v3_api("/projects/#{project.id}/labels/#{label1.id}/subscription", user)
-
- expect(response).to have_gitlab_http_status(201)
- expect(json_response["name"]).to eq(label1.title)
- expect(json_response["subscribed"]).to be_truthy
- end
- end
-
- context "when user is already subscribed to label" do
- before { label1.subscribe(user, project) }
-
- it "returns 304" do
- post v3_api("/projects/#{project.id}/labels/#{label1.id}/subscription", user)
-
- expect(response).to have_gitlab_http_status(304)
- end
- end
-
- context "when label ID is not found" do
- it "returns 404 error" do
- post v3_api("/projects/#{project.id}/labels/1234/subscription", user)
-
- expect(response).to have_gitlab_http_status(404)
- end
- end
- end
-
- describe "DELETE /projects/:id/labels/:label_id/subscription" do
- before { label1.subscribe(user, project) }
-
- context "when label_id is a label title" do
- it "unsubscribes from the label" do
- delete v3_api("/projects/#{project.id}/labels/#{label1.title}/subscription", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response["name"]).to eq(label1.title)
- expect(json_response["subscribed"]).to be_falsey
- end
- end
-
- context "when label_id is a label ID" do
- it "unsubscribes from the label" do
- delete v3_api("/projects/#{project.id}/labels/#{label1.id}/subscription", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response["name"]).to eq(label1.title)
- expect(json_response["subscribed"]).to be_falsey
- end
- end
-
- context "when user is already unsubscribed from label" do
- before { label1.unsubscribe(user, project) }
-
- it "returns 304" do
- delete v3_api("/projects/#{project.id}/labels/#{label1.id}/subscription", user)
-
- expect(response).to have_gitlab_http_status(304)
- end
- end
-
- context "when label ID is not found" do
- it "returns 404 error" do
- delete v3_api("/projects/#{project.id}/labels/1234/subscription", user)
-
- expect(response).to have_gitlab_http_status(404)
- end
- end
- end
-
- describe 'DELETE /projects/:id/labels' do
- it 'returns 200 for existing label' do
- delete v3_api("/projects/#{project.id}/labels", user), name: 'label1'
-
- expect(response).to have_gitlab_http_status(200)
- end
-
- it 'returns 404 for non existing label' do
- delete v3_api("/projects/#{project.id}/labels", user), name: 'label2'
- expect(response).to have_gitlab_http_status(404)
- expect(json_response['message']).to eq('404 Label Not Found')
- end
-
- it 'returns 400 for wrong parameters' do
- delete v3_api("/projects/#{project.id}/labels", user)
- expect(response).to have_gitlab_http_status(400)
- end
- end
-end
diff --git a/spec/requests/api/v3/members_spec.rb b/spec/requests/api/v3/members_spec.rb
deleted file mode 100644
index de4339ecb8b..00000000000
--- a/spec/requests/api/v3/members_spec.rb
+++ /dev/null
@@ -1,350 +0,0 @@
-require 'spec_helper'
-
-describe API::V3::Members do
- let(:master) { create(:user, username: 'master_user') }
- let(:developer) { create(:user) }
- let(:access_requester) { create(:user) }
- let(:stranger) { create(:user) }
-
- let(:project) do
- create(:project, :public, :access_requestable, creator_id: master.id, namespace: master.namespace) do |project|
- project.add_developer(developer)
- project.add_master(master)
- project.request_access(access_requester)
- end
- end
-
- let!(:group) do
- create(:group, :public, :access_requestable) do |group|
- group.add_developer(developer)
- group.add_owner(master)
- group.request_access(access_requester)
- end
- end
-
- shared_examples 'GET /:sources/:id/members' do |source_type|
- context "with :sources == #{source_type.pluralize}" do
- it_behaves_like 'a 404 response when source is private' do
- let(:route) { get v3_api("/#{source_type.pluralize}/#{source.id}/members", stranger) }
- end
-
- %i[master developer access_requester stranger].each do |type|
- context "when authenticated as a #{type}" do
- it 'returns 200' do
- user = public_send(type)
- get v3_api("/#{source_type.pluralize}/#{source.id}/members", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response.size).to eq(2)
- expect(json_response.map { |u| u['id'] }).to match_array [master.id, developer.id]
- end
- end
- end
-
- it 'does not return invitees' do
- create(:"#{source_type}_member", invite_token: '123', invite_email: 'test@abc.com', source: source, user: nil)
-
- get v3_api("/#{source_type.pluralize}/#{source.id}/members", developer)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response.size).to eq(2)
- expect(json_response.map { |u| u['id'] }).to match_array [master.id, developer.id]
- end
-
- it 'finds members with query string' do
- get v3_api("/#{source_type.pluralize}/#{source.id}/members", developer), query: master.username
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response.count).to eq(1)
- expect(json_response.first['username']).to eq(master.username)
- end
-
- it 'finds all members with no query specified' do
- get v3_api("/#{source_type.pluralize}/#{source.id}/members", developer), query: ''
-
- expect(response).to have_gitlab_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response.count).to eq(2)
- expect(json_response.map { |u| u['id'] }).to match_array [master.id, developer.id]
- end
- end
- end
-
- shared_examples 'GET /:sources/:id/members/:user_id' do |source_type|
- context "with :sources == #{source_type.pluralize}" do
- it_behaves_like 'a 404 response when source is private' do
- let(:route) { get v3_api("/#{source_type.pluralize}/#{source.id}/members/#{developer.id}", stranger) }
- end
-
- context 'when authenticated as a non-member' do
- %i[access_requester stranger].each do |type|
- context "as a #{type}" do
- it 'returns 200' do
- user = public_send(type)
- get v3_api("/#{source_type.pluralize}/#{source.id}/members/#{developer.id}", user)
-
- expect(response).to have_gitlab_http_status(200)
- # User attributes
- expect(json_response['id']).to eq(developer.id)
- expect(json_response['name']).to eq(developer.name)
- expect(json_response['username']).to eq(developer.username)
- expect(json_response['state']).to eq(developer.state)
- expect(json_response['avatar_url']).to eq(developer.avatar_url)
- expect(json_response['web_url']).to eq(Gitlab::Routing.url_helpers.user_url(developer))
-
- # Member attributes
- expect(json_response['access_level']).to eq(Member::DEVELOPER)
- end
- end
- end
- end
- end
- end
-
- shared_examples 'POST /:sources/:id/members' do |source_type|
- context "with :sources == #{source_type.pluralize}" do
- it_behaves_like 'a 404 response when source is private' do
- let(:route) do
- post v3_api("/#{source_type.pluralize}/#{source.id}/members", stranger),
- user_id: access_requester.id, access_level: Member::MASTER
- end
- end
-
- context 'when authenticated as a non-member or member with insufficient rights' do
- %i[access_requester stranger developer].each do |type|
- context "as a #{type}" do
- it 'returns 403' do
- user = public_send(type)
- post v3_api("/#{source_type.pluralize}/#{source.id}/members", user),
- user_id: access_requester.id, access_level: Member::MASTER
-
- expect(response).to have_gitlab_http_status(403)
- end
- end
- end
- end
-
- context 'when authenticated as a master/owner' do
- context 'and new member is already a requester' do
- it 'transforms the requester into a proper member' do
- expect do
- post v3_api("/#{source_type.pluralize}/#{source.id}/members", master),
- user_id: access_requester.id, access_level: Member::MASTER
-
- expect(response).to have_gitlab_http_status(201)
- end.to change { source.members.count }.by(1)
- expect(source.requesters.count).to eq(0)
- expect(json_response['id']).to eq(access_requester.id)
- expect(json_response['access_level']).to eq(Member::MASTER)
- end
- end
-
- it 'creates a new member' do
- expect do
- post v3_api("/#{source_type.pluralize}/#{source.id}/members", master),
- user_id: stranger.id, access_level: Member::DEVELOPER, expires_at: '2016-08-05'
-
- expect(response).to have_gitlab_http_status(201)
- end.to change { source.members.count }.by(1)
- expect(json_response['id']).to eq(stranger.id)
- expect(json_response['access_level']).to eq(Member::DEVELOPER)
- expect(json_response['expires_at']).to eq('2016-08-05')
- end
- end
-
- it "returns #{source_type == 'project' ? 201 : 409} if member already exists" do
- post v3_api("/#{source_type.pluralize}/#{source.id}/members", master),
- user_id: master.id, access_level: Member::MASTER
-
- expect(response).to have_gitlab_http_status(source_type == 'project' ? 201 : 409)
- end
-
- it 'returns 400 when user_id is not given' do
- post v3_api("/#{source_type.pluralize}/#{source.id}/members", master),
- access_level: Member::MASTER
-
- expect(response).to have_gitlab_http_status(400)
- end
-
- it 'returns 400 when access_level is not given' do
- post v3_api("/#{source_type.pluralize}/#{source.id}/members", master),
- user_id: stranger.id
-
- expect(response).to have_gitlab_http_status(400)
- end
-
- it 'returns 422 when access_level is not valid' do
- post v3_api("/#{source_type.pluralize}/#{source.id}/members", master),
- user_id: stranger.id, access_level: 1234
-
- expect(response).to have_gitlab_http_status(422)
- end
- end
- end
-
- shared_examples 'PUT /:sources/:id/members/:user_id' do |source_type|
- context "with :sources == #{source_type.pluralize}" do
- it_behaves_like 'a 404 response when source is private' do
- let(:route) do
- put v3_api("/#{source_type.pluralize}/#{source.id}/members/#{developer.id}", stranger),
- access_level: Member::MASTER
- end
- end
-
- context 'when authenticated as a non-member or member with insufficient rights' do
- %i[access_requester stranger developer].each do |type|
- context "as a #{type}" do
- it 'returns 403' do
- user = public_send(type)
- put v3_api("/#{source_type.pluralize}/#{source.id}/members/#{developer.id}", user),
- access_level: Member::MASTER
-
- expect(response).to have_gitlab_http_status(403)
- end
- end
- end
- end
-
- context 'when authenticated as a master/owner' do
- it 'updates the member' do
- put v3_api("/#{source_type.pluralize}/#{source.id}/members/#{developer.id}", master),
- access_level: Member::MASTER, expires_at: '2016-08-05'
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['id']).to eq(developer.id)
- expect(json_response['access_level']).to eq(Member::MASTER)
- expect(json_response['expires_at']).to eq('2016-08-05')
- end
- end
-
- it 'returns 409 if member does not exist' do
- put v3_api("/#{source_type.pluralize}/#{source.id}/members/123", master),
- access_level: Member::MASTER
-
- expect(response).to have_gitlab_http_status(404)
- end
-
- it 'returns 400 when access_level is not given' do
- put v3_api("/#{source_type.pluralize}/#{source.id}/members/#{developer.id}", master)
-
- expect(response).to have_gitlab_http_status(400)
- end
-
- it 'returns 422 when access level is not valid' do
- put v3_api("/#{source_type.pluralize}/#{source.id}/members/#{developer.id}", master),
- access_level: 1234
-
- expect(response).to have_gitlab_http_status(422)
- end
- end
- end
-
- shared_examples 'DELETE /:sources/:id/members/:user_id' do |source_type|
- context "with :sources == #{source_type.pluralize}" do
- it_behaves_like 'a 404 response when source is private' do
- let(:route) { delete v3_api("/#{source_type.pluralize}/#{source.id}/members/#{developer.id}", stranger) }
- end
-
- context 'when authenticated as a non-member or member with insufficient rights' do
- %i[access_requester stranger].each do |type|
- context "as a #{type}" do
- it 'returns 403' do
- user = public_send(type)
- delete v3_api("/#{source_type.pluralize}/#{source.id}/members/#{developer.id}", user)
-
- expect(response).to have_gitlab_http_status(403)
- end
- end
- end
- end
-
- context 'when authenticated as a member and deleting themself' do
- it 'deletes the member' do
- expect do
- delete v3_api("/#{source_type.pluralize}/#{source.id}/members/#{developer.id}", developer)
-
- expect(response).to have_gitlab_http_status(200)
- end.to change { source.members.count }.by(-1)
- end
- end
-
- context 'when authenticated as a master/owner' do
- context 'and member is a requester' do
- it "returns #{source_type == 'project' ? 200 : 404}" do
- expect do
- delete v3_api("/#{source_type.pluralize}/#{source.id}/members/#{access_requester.id}", master)
-
- expect(response).to have_gitlab_http_status(source_type == 'project' ? 200 : 404)
- end.not_to change { source.requesters.count }
- end
- end
-
- it 'deletes the member' do
- expect do
- delete v3_api("/#{source_type.pluralize}/#{source.id}/members/#{developer.id}", master)
-
- expect(response).to have_gitlab_http_status(200)
- end.to change { source.members.count }.by(-1)
- end
- end
-
- it "returns #{source_type == 'project' ? 200 : 404} if member does not exist" do
- delete v3_api("/#{source_type.pluralize}/#{source.id}/members/123", master)
-
- expect(response).to have_gitlab_http_status(source_type == 'project' ? 200 : 404)
- end
- end
- end
-
- it_behaves_like 'GET /:sources/:id/members', 'project' do
- let(:source) { project }
- end
-
- it_behaves_like 'GET /:sources/:id/members', 'group' do
- let(:source) { group }
- end
-
- it_behaves_like 'GET /:sources/:id/members/:user_id', 'project' do
- let(:source) { project }
- end
-
- it_behaves_like 'GET /:sources/:id/members/:user_id', 'group' do
- let(:source) { group }
- end
-
- it_behaves_like 'POST /:sources/:id/members', 'project' do
- let(:source) { project }
- end
-
- it_behaves_like 'POST /:sources/:id/members', 'group' do
- let(:source) { group }
- end
-
- it_behaves_like 'PUT /:sources/:id/members/:user_id', 'project' do
- let(:source) { project }
- end
-
- it_behaves_like 'PUT /:sources/:id/members/:user_id', 'group' do
- let(:source) { group }
- end
-
- it_behaves_like 'DELETE /:sources/:id/members/:user_id', 'project' do
- let(:source) { project }
- end
-
- it_behaves_like 'DELETE /:sources/:id/members/:user_id', 'group' do
- let(:source) { group }
- end
-
- context 'Adding owner to project' do
- it 'returns 403' do
- expect do
- post v3_api("/projects/#{project.id}/members", master),
- user_id: stranger.id, access_level: Member::OWNER
-
- expect(response).to have_gitlab_http_status(422)
- end.to change { project.members.count }.by(0)
- end
- end
-end
diff --git a/spec/requests/api/v3/merge_request_diffs_spec.rb b/spec/requests/api/v3/merge_request_diffs_spec.rb
deleted file mode 100644
index 547c066fadc..00000000000
--- a/spec/requests/api/v3/merge_request_diffs_spec.rb
+++ /dev/null
@@ -1,48 +0,0 @@
-require "spec_helper"
-
-describe API::V3::MergeRequestDiffs, 'MergeRequestDiffs' do
- let!(:user) { create(:user) }
- let!(:merge_request) { create(:merge_request, importing: true) }
- let!(:project) { merge_request.target_project }
-
- before do
- merge_request.merge_request_diffs.create(head_commit_sha: '6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9')
- merge_request.merge_request_diffs.create(head_commit_sha: '5937ac0a7beb003549fc5fd26fc247adbce4a52e')
- project.add_master(user)
- end
-
- describe 'GET /projects/:id/merge_requests/:merge_request_id/versions' do
- it 'returns 200 for a valid merge request' do
- get v3_api("/projects/#{project.id}/merge_requests/#{merge_request.id}/versions", user)
- merge_request_diff = merge_request.merge_request_diffs.last
-
- expect(response.status).to eq 200
- expect(json_response.size).to eq(merge_request.merge_request_diffs.size)
- expect(json_response.first['id']).to eq(merge_request_diff.id)
- expect(json_response.first['head_commit_sha']).to eq(merge_request_diff.head_commit_sha)
- end
-
- it 'returns a 404 when merge_request_id not found' do
- get v3_api("/projects/#{project.id}/merge_requests/999/versions", user)
- expect(response).to have_gitlab_http_status(404)
- end
- end
-
- describe 'GET /projects/:id/merge_requests/:merge_request_id/versions/:version_id' do
- it 'returns a 200 for a valid merge request' do
- merge_request_diff = merge_request.merge_request_diffs.first
- get v3_api("/projects/#{project.id}/merge_requests/#{merge_request.id}/versions/#{merge_request_diff.id}", user)
-
- expect(response.status).to eq 200
- expect(json_response['id']).to eq(merge_request_diff.id)
- expect(json_response['head_commit_sha']).to eq(merge_request_diff.head_commit_sha)
- expect(json_response['diffs'].size).to eq(merge_request_diff.diffs.size)
- end
-
- it 'returns a 404 when merge_request_id not found' do
- get v3_api("/projects/#{project.id}/merge_requests/#{merge_request.id}/versions/999", user)
-
- expect(response).to have_gitlab_http_status(404)
- end
- end
-end
diff --git a/spec/requests/api/v3/merge_requests_spec.rb b/spec/requests/api/v3/merge_requests_spec.rb
deleted file mode 100644
index be70cb24dce..00000000000
--- a/spec/requests/api/v3/merge_requests_spec.rb
+++ /dev/null
@@ -1,749 +0,0 @@
-require "spec_helper"
-
-describe API::MergeRequests do
- include ProjectForksHelper
-
- let(:base_time) { Time.now }
- let(:user) { create(:user) }
- let(:admin) { create(:user, :admin) }
- let(:non_member) { create(:user) }
- let!(:project) { create(:project, :public, :repository, creator: user, namespace: user.namespace) }
- let!(:merge_request) { create(:merge_request, :simple, author: user, assignee: user, source_project: project, title: "Test", created_at: base_time) }
- let!(:merge_request_closed) { create(:merge_request, state: "closed", author: user, assignee: user, source_project: project, title: "Closed test", created_at: base_time + 1.second) }
- let!(:merge_request_merged) { create(:merge_request, state: "merged", author: user, assignee: user, source_project: project, title: "Merged test", created_at: base_time + 2.seconds, merge_commit_sha: '9999999999999999999999999999999999999999') }
- let(:milestone) { create(:milestone, title: '1.0.0', project: project) }
-
- before do
- project.add_reporter(user)
- end
-
- describe "GET /projects/:id/merge_requests" do
- context "when unauthenticated" do
- it "returns authentication error" do
- get v3_api("/projects/#{project.id}/merge_requests")
- expect(response).to have_gitlab_http_status(401)
- end
- end
-
- context "when authenticated" do
- it "returns an array of all merge_requests" do
- get v3_api("/projects/#{project.id}/merge_requests", user)
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(3)
- expect(json_response.last['title']).to eq(merge_request.title)
- expect(json_response.last).to have_key('web_url')
- expect(json_response.last['sha']).to eq(merge_request.diff_head_sha)
- expect(json_response.last['merge_commit_sha']).to be_nil
- expect(json_response.last['merge_commit_sha']).to eq(merge_request.merge_commit_sha)
- expect(json_response.first['title']).to eq(merge_request_merged.title)
- expect(json_response.first['sha']).to eq(merge_request_merged.diff_head_sha)
- expect(json_response.first['merge_commit_sha']).not_to be_nil
- expect(json_response.first['merge_commit_sha']).to eq(merge_request_merged.merge_commit_sha)
- end
-
- it "returns an array of all merge_requests" do
- get v3_api("/projects/#{project.id}/merge_requests?state", user)
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(3)
- expect(json_response.last['title']).to eq(merge_request.title)
- end
-
- it "returns an array of open merge_requests" do
- get v3_api("/projects/#{project.id}/merge_requests?state=opened", user)
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(1)
- expect(json_response.last['title']).to eq(merge_request.title)
- end
-
- it "returns an array of closed merge_requests" do
- get v3_api("/projects/#{project.id}/merge_requests?state=closed", user)
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(1)
- expect(json_response.first['title']).to eq(merge_request_closed.title)
- end
-
- it "returns an array of merged merge_requests" do
- get v3_api("/projects/#{project.id}/merge_requests?state=merged", user)
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(1)
- expect(json_response.first['title']).to eq(merge_request_merged.title)
- end
-
- it 'matches V3 response schema' do
- get v3_api("/projects/#{project.id}/merge_requests", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(response).to match_response_schema('public_api/v3/merge_requests')
- end
-
- context "with ordering" do
- before do
- @mr_later = mr_with_later_created_and_updated_at_time
- @mr_earlier = mr_with_earlier_created_and_updated_at_time
- end
-
- it "returns an array of merge_requests in ascending order" do
- get v3_api("/projects/#{project.id}/merge_requests?sort=asc", user)
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(3)
- response_dates = json_response.map { |merge_request| merge_request['created_at'] }
- expect(response_dates).to eq(response_dates.sort)
- end
-
- it "returns an array of merge_requests in descending order" do
- get v3_api("/projects/#{project.id}/merge_requests?sort=desc", user)
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(3)
- response_dates = json_response.map { |merge_request| merge_request['created_at'] }
- expect(response_dates).to eq(response_dates.sort.reverse)
- end
-
- it "returns an array of merge_requests ordered by updated_at" do
- get v3_api("/projects/#{project.id}/merge_requests?order_by=updated_at", user)
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(3)
- response_dates = json_response.map { |merge_request| merge_request['updated_at'] }
- expect(response_dates).to eq(response_dates.sort.reverse)
- end
-
- it "returns an array of merge_requests ordered by created_at" do
- get v3_api("/projects/#{project.id}/merge_requests?order_by=created_at&sort=asc", user)
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(3)
- response_dates = json_response.map { |merge_request| merge_request['created_at'] }
- expect(response_dates).to eq(response_dates.sort)
- end
- end
- end
- end
-
- describe "GET /projects/:id/merge_requests/:merge_request_id" do
- it 'exposes known attributes' do
- get v3_api("/projects/#{project.id}/merge_requests/#{merge_request.id}", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['id']).to eq(merge_request.id)
- expect(json_response['iid']).to eq(merge_request.iid)
- expect(json_response['project_id']).to eq(merge_request.project.id)
- expect(json_response['title']).to eq(merge_request.title)
- expect(json_response['description']).to eq(merge_request.description)
- expect(json_response['state']).to eq(merge_request.state)
- expect(json_response['created_at']).to be_present
- expect(json_response['updated_at']).to be_present
- expect(json_response['labels']).to eq(merge_request.label_names)
- expect(json_response['milestone']).to be_nil
- expect(json_response['assignee']).to be_a Hash
- expect(json_response['author']).to be_a Hash
- expect(json_response['target_branch']).to eq(merge_request.target_branch)
- expect(json_response['source_branch']).to eq(merge_request.source_branch)
- expect(json_response['upvotes']).to eq(0)
- expect(json_response['downvotes']).to eq(0)
- expect(json_response['source_project_id']).to eq(merge_request.source_project.id)
- expect(json_response['target_project_id']).to eq(merge_request.target_project.id)
- expect(json_response['work_in_progress']).to be_falsy
- expect(json_response['merge_when_build_succeeds']).to be_falsy
- expect(json_response['merge_status']).to eq('can_be_merged')
- expect(json_response['should_close_merge_request']).to be_falsy
- expect(json_response['force_close_merge_request']).to be_falsy
- end
-
- it "returns merge_request" do
- get v3_api("/projects/#{project.id}/merge_requests/#{merge_request.id}", user)
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['title']).to eq(merge_request.title)
- expect(json_response['iid']).to eq(merge_request.iid)
- expect(json_response['work_in_progress']).to eq(false)
- expect(json_response['merge_status']).to eq('can_be_merged')
- expect(json_response['should_close_merge_request']).to be_falsy
- expect(json_response['force_close_merge_request']).to be_falsy
- end
-
- it 'returns merge_request by iid' do
- url = "/projects/#{project.id}/merge_requests?iid=#{merge_request.iid}"
- get v3_api(url, user)
- expect(response.status).to eq 200
- expect(json_response.first['title']).to eq merge_request.title
- expect(json_response.first['id']).to eq merge_request.id
- end
-
- it 'returns merge_request by iid array' do
- get v3_api("/projects/#{project.id}/merge_requests", user), iid: [merge_request.iid, merge_request_closed.iid]
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(2)
- expect(json_response.first['title']).to eq merge_request_closed.title
- expect(json_response.first['id']).to eq merge_request_closed.id
- end
-
- it "returns a 404 error if merge_request_id not found" do
- get v3_api("/projects/#{project.id}/merge_requests/999", user)
- expect(response).to have_gitlab_http_status(404)
- end
-
- context 'Work in Progress' do
- let!(:merge_request_wip) { create(:merge_request, author: user, assignee: user, source_project: project, target_project: project, title: "WIP: Test", created_at: base_time + 1.second) }
-
- it "returns merge_request" do
- get v3_api("/projects/#{project.id}/merge_requests/#{merge_request_wip.id}", user)
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['work_in_progress']).to eq(true)
- end
- end
- end
-
- describe 'GET /projects/:id/merge_requests/:merge_request_id/commits' do
- it 'returns a 200 when merge request is valid' do
- get v3_api("/projects/#{project.id}/merge_requests/#{merge_request.id}/commits", user)
- commit = merge_request.commits.first
-
- expect(response.status).to eq 200
- expect(json_response.size).to eq(merge_request.commits.size)
- expect(json_response.first['id']).to eq(commit.id)
- expect(json_response.first['title']).to eq(commit.title)
- end
-
- it 'returns a 404 when merge_request_id not found' do
- get v3_api("/projects/#{project.id}/merge_requests/999/commits", user)
- expect(response).to have_gitlab_http_status(404)
- end
- end
-
- describe 'GET /projects/:id/merge_requests/:merge_request_id/changes' do
- it 'returns the change information of the merge_request' do
- get v3_api("/projects/#{project.id}/merge_requests/#{merge_request.id}/changes", user)
- expect(response.status).to eq 200
- expect(json_response['changes'].size).to eq(merge_request.diffs.size)
- end
-
- it 'returns a 404 when merge_request_id not found' do
- get v3_api("/projects/#{project.id}/merge_requests/999/changes", user)
- expect(response).to have_gitlab_http_status(404)
- end
- end
-
- describe "POST /projects/:id/merge_requests" do
- context 'between branches projects' do
- it "returns merge_request" do
- post v3_api("/projects/#{project.id}/merge_requests", user),
- title: 'Test merge_request',
- source_branch: 'feature_conflict',
- target_branch: 'master',
- author: user,
- labels: 'label, label2',
- milestone_id: milestone.id,
- remove_source_branch: true
-
- expect(response).to have_gitlab_http_status(201)
- expect(json_response['title']).to eq('Test merge_request')
- expect(json_response['labels']).to eq(%w(label label2))
- expect(json_response['milestone']['id']).to eq(milestone.id)
- expect(json_response['force_remove_source_branch']).to be_truthy
- end
-
- it "returns 422 when source_branch equals target_branch" do
- post v3_api("/projects/#{project.id}/merge_requests", user),
- title: "Test merge_request", source_branch: "master", target_branch: "master", author: user
- expect(response).to have_gitlab_http_status(422)
- end
-
- it "returns 400 when source_branch is missing" do
- post v3_api("/projects/#{project.id}/merge_requests", user),
- title: "Test merge_request", target_branch: "master", author: user
- expect(response).to have_gitlab_http_status(400)
- end
-
- it "returns 400 when target_branch is missing" do
- post v3_api("/projects/#{project.id}/merge_requests", user),
- title: "Test merge_request", source_branch: "markdown", author: user
- expect(response).to have_gitlab_http_status(400)
- end
-
- it "returns 400 when title is missing" do
- post v3_api("/projects/#{project.id}/merge_requests", user),
- target_branch: 'master', source_branch: 'markdown'
- expect(response).to have_gitlab_http_status(400)
- end
-
- it 'allows special label names' do
- post v3_api("/projects/#{project.id}/merge_requests", user),
- title: 'Test merge_request',
- source_branch: 'markdown',
- target_branch: 'master',
- author: user,
- labels: 'label, label?, label&foo, ?, &'
- expect(response.status).to eq(201)
- expect(json_response['labels']).to include 'label'
- expect(json_response['labels']).to include 'label?'
- expect(json_response['labels']).to include 'label&foo'
- expect(json_response['labels']).to include '?'
- expect(json_response['labels']).to include '&'
- end
-
- context 'with existing MR' do
- before do
- post v3_api("/projects/#{project.id}/merge_requests", user),
- title: 'Test merge_request',
- source_branch: 'feature_conflict',
- target_branch: 'master',
- author: user
- @mr = MergeRequest.all.last
- end
-
- it 'returns 409 when MR already exists for source/target' do
- expect do
- post v3_api("/projects/#{project.id}/merge_requests", user),
- title: 'New test merge_request',
- source_branch: 'feature_conflict',
- target_branch: 'master',
- author: user
- end.to change { MergeRequest.count }.by(0)
- expect(response).to have_gitlab_http_status(409)
- end
- end
- end
-
- context 'forked projects' do
- let!(:user2) { create(:user) }
- let!(:forked_project) { fork_project(project, user2, repository: true) }
- let!(:unrelated_project) { create(:project, namespace: create(:user).namespace, creator_id: user2.id) }
-
- before do
- forked_project.add_reporter(user2)
- end
-
- it "returns merge_request" do
- post v3_api("/projects/#{forked_project.id}/merge_requests", user2),
- title: 'Test merge_request', source_branch: "feature_conflict", target_branch: "master",
- author: user2, target_project_id: project.id, description: 'Test description for Test merge_request'
- expect(response).to have_gitlab_http_status(201)
- expect(json_response['title']).to eq('Test merge_request')
- expect(json_response['description']).to eq('Test description for Test merge_request')
- end
-
- it "does not return 422 when source_branch equals target_branch" do
- expect(project.id).not_to eq(forked_project.id)
- expect(forked_project.forked?).to be_truthy
- expect(forked_project.forked_from_project).to eq(project)
- post v3_api("/projects/#{forked_project.id}/merge_requests", user2),
- title: 'Test merge_request', source_branch: "master", target_branch: "master", author: user2, target_project_id: project.id
- expect(response).to have_gitlab_http_status(201)
- expect(json_response['title']).to eq('Test merge_request')
- end
-
- it "returns 403 when target project has disabled merge requests" do
- project.project_feature.update(merge_requests_access_level: 0)
-
- post v3_api("/projects/#{forked_project.id}/merge_requests", user2),
- title: 'Test',
- target_branch: "master",
- source_branch: 'markdown',
- author: user2,
- target_project_id: project.id
-
- expect(response).to have_gitlab_http_status(403)
- end
-
- it "returns 400 when source_branch is missing" do
- post v3_api("/projects/#{forked_project.id}/merge_requests", user2),
- title: 'Test merge_request', target_branch: "master", author: user2, target_project_id: project.id
- expect(response).to have_gitlab_http_status(400)
- end
-
- it "returns 400 when target_branch is missing" do
- post v3_api("/projects/#{forked_project.id}/merge_requests", user2),
- title: 'Test merge_request', target_branch: "master", author: user2, target_project_id: project.id
- expect(response).to have_gitlab_http_status(400)
- end
-
- it "returns 400 when title is missing" do
- post v3_api("/projects/#{forked_project.id}/merge_requests", user2),
- target_branch: 'master', source_branch: 'markdown', author: user2, target_project_id: project.id
- expect(response).to have_gitlab_http_status(400)
- end
-
- context 'when target_branch and target_project_id is specified' do
- let(:params) do
- { title: 'Test merge_request',
- target_branch: 'master',
- source_branch: 'markdown',
- author: user2,
- target_project_id: unrelated_project.id }
- end
-
- it 'returns 422 if targeting a different fork' do
- unrelated_project.add_developer(user2)
-
- post v3_api("/projects/#{forked_project.id}/merge_requests", user2), params
-
- expect(response).to have_gitlab_http_status(422)
- end
-
- it 'returns 403 if targeting a different fork which user can not access' do
- post v3_api("/projects/#{forked_project.id}/merge_requests", user2), params
-
- expect(response).to have_gitlab_http_status(403)
- end
- end
-
- it "returns 201 when target_branch is specified and for the same project" do
- post v3_api("/projects/#{forked_project.id}/merge_requests", user2),
- title: 'Test merge_request', target_branch: 'master', source_branch: 'markdown', author: user2, target_project_id: forked_project.id
- expect(response).to have_gitlab_http_status(201)
- end
- end
- end
-
- describe "DELETE /projects/:id/merge_requests/:merge_request_id" do
- context "when the user is developer" do
- let(:developer) { create(:user) }
-
- before do
- project.add_developer(developer)
- end
-
- it "denies the deletion of the merge request" do
- delete v3_api("/projects/#{project.id}/merge_requests/#{merge_request.id}", developer)
- expect(response).to have_gitlab_http_status(403)
- end
- end
-
- context "when the user is project owner" do
- it "destroys the merge request owners can destroy" do
- delete v3_api("/projects/#{project.id}/merge_requests/#{merge_request.id}", user)
-
- expect(response).to have_gitlab_http_status(200)
- end
- end
- end
-
- describe "PUT /projects/:id/merge_requests/:merge_request_id/merge" do
- let(:pipeline) { create(:ci_pipeline_without_jobs) }
-
- it "returns merge_request in case of success" do
- put v3_api("/projects/#{project.id}/merge_requests/#{merge_request.id}/merge", user)
-
- expect(response).to have_gitlab_http_status(200)
- end
-
- it "returns 406 if branch can't be merged" do
- allow_any_instance_of(MergeRequest)
- .to receive(:can_be_merged?).and_return(false)
-
- put v3_api("/projects/#{project.id}/merge_requests/#{merge_request.id}/merge", user)
-
- expect(response).to have_gitlab_http_status(406)
- expect(json_response['message']).to eq('Branch cannot be merged')
- end
-
- it "returns 405 if merge_request is not open" do
- merge_request.close
- put v3_api("/projects/#{project.id}/merge_requests/#{merge_request.id}/merge", user)
- expect(response).to have_gitlab_http_status(405)
- expect(json_response['message']).to eq('405 Method Not Allowed')
- end
-
- it "returns 405 if merge_request is a work in progress" do
- merge_request.update_attribute(:title, "WIP: #{merge_request.title}")
- put v3_api("/projects/#{project.id}/merge_requests/#{merge_request.id}/merge", user)
- expect(response).to have_gitlab_http_status(405)
- expect(json_response['message']).to eq('405 Method Not Allowed')
- end
-
- it 'returns 405 if the build failed for a merge request that requires success' do
- allow_any_instance_of(MergeRequest).to receive(:mergeable_ci_state?).and_return(false)
-
- put v3_api("/projects/#{project.id}/merge_requests/#{merge_request.id}/merge", user)
-
- expect(response).to have_gitlab_http_status(405)
- expect(json_response['message']).to eq('405 Method Not Allowed')
- end
-
- it "returns 401 if user has no permissions to merge" do
- user2 = create(:user)
- project.add_reporter(user2)
- put v3_api("/projects/#{project.id}/merge_requests/#{merge_request.id}/merge", user2)
- expect(response).to have_gitlab_http_status(401)
- expect(json_response['message']).to eq('401 Unauthorized')
- end
-
- it "returns 409 if the SHA parameter doesn't match" do
- put v3_api("/projects/#{project.id}/merge_requests/#{merge_request.id}/merge", user), sha: merge_request.diff_head_sha.reverse
-
- expect(response).to have_gitlab_http_status(409)
- expect(json_response['message']).to start_with('SHA does not match HEAD of source branch')
- end
-
- it "succeeds if the SHA parameter matches" do
- put v3_api("/projects/#{project.id}/merge_requests/#{merge_request.id}/merge", user), sha: merge_request.diff_head_sha
-
- expect(response).to have_gitlab_http_status(200)
- end
-
- it "enables merge when pipeline succeeds if the pipeline is active" do
- allow_any_instance_of(MergeRequest).to receive(:head_pipeline).and_return(pipeline)
- allow(pipeline).to receive(:active?).and_return(true)
-
- put v3_api("/projects/#{project.id}/merge_requests/#{merge_request.id}/merge", user), merge_when_build_succeeds: true
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['title']).to eq('Test')
- expect(json_response['merge_when_build_succeeds']).to eq(true)
- end
- end
-
- describe "PUT /projects/:id/merge_requests/:merge_request_id" do
- context "to close a MR" do
- it "returns merge_request" do
- put v3_api("/projects/#{project.id}/merge_requests/#{merge_request.id}", user), state_event: "close"
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['state']).to eq('closed')
- end
- end
-
- it "updates title and returns merge_request" do
- put v3_api("/projects/#{project.id}/merge_requests/#{merge_request.id}", user), title: "New title"
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['title']).to eq('New title')
- end
-
- it "updates description and returns merge_request" do
- put v3_api("/projects/#{project.id}/merge_requests/#{merge_request.id}", user), description: "New description"
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['description']).to eq('New description')
- end
-
- it "updates milestone_id and returns merge_request" do
- put v3_api("/projects/#{project.id}/merge_requests/#{merge_request.id}", user), milestone_id: milestone.id
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['milestone']['id']).to eq(milestone.id)
- end
-
- it "returns merge_request with renamed target_branch" do
- put v3_api("/projects/#{project.id}/merge_requests/#{merge_request.id}", user), target_branch: "wiki"
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['target_branch']).to eq('wiki')
- end
-
- it "returns merge_request that removes the source branch" do
- put v3_api("/projects/#{project.id}/merge_requests/#{merge_request.id}", user), remove_source_branch: true
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['force_remove_source_branch']).to be_truthy
- end
-
- it 'allows special label names' do
- put v3_api("/projects/#{project.id}/merge_requests/#{merge_request.id}", user),
- title: 'new issue',
- labels: 'label, label?, label&foo, ?, &'
-
- expect(response.status).to eq(200)
- expect(json_response['labels']).to include 'label'
- expect(json_response['labels']).to include 'label?'
- expect(json_response['labels']).to include 'label&foo'
- expect(json_response['labels']).to include '?'
- expect(json_response['labels']).to include '&'
- end
-
- it 'does not update state when title is empty' do
- put v3_api("/projects/#{project.id}/merge_requests/#{merge_request.id}", user), state_event: 'close', title: nil
-
- merge_request.reload
- expect(response).to have_gitlab_http_status(400)
- expect(merge_request.state).to eq('opened')
- end
-
- it 'does not update state when target_branch is empty' do
- put v3_api("/projects/#{project.id}/merge_requests/#{merge_request.id}", user), state_event: 'close', target_branch: nil
-
- merge_request.reload
- expect(response).to have_gitlab_http_status(400)
- expect(merge_request.state).to eq('opened')
- end
- end
-
- describe "POST /projects/:id/merge_requests/:merge_request_id/comments" do
- it "returns comment" do
- original_count = merge_request.notes.size
-
- post v3_api("/projects/#{project.id}/merge_requests/#{merge_request.id}/comments", user), note: "My comment"
-
- expect(response).to have_gitlab_http_status(201)
- expect(json_response['note']).to eq('My comment')
- expect(json_response['author']['name']).to eq(user.name)
- expect(json_response['author']['username']).to eq(user.username)
- expect(merge_request.reload.notes.size).to eq(original_count + 1)
- end
-
- it "returns 400 if note is missing" do
- post v3_api("/projects/#{project.id}/merge_requests/#{merge_request.id}/comments", user)
- expect(response).to have_gitlab_http_status(400)
- end
-
- it "returns 404 if note is attached to non existent merge request" do
- post v3_api("/projects/#{project.id}/merge_requests/404/comments", user),
- note: 'My comment'
- expect(response).to have_gitlab_http_status(404)
- end
- end
-
- describe "GET :id/merge_requests/:merge_request_id/comments" do
- let!(:note) { create(:note_on_merge_request, author: user, project: project, noteable: merge_request, note: "a comment on a MR") }
- let!(:note2) { create(:note_on_merge_request, author: user, project: project, noteable: merge_request, note: "another comment on a MR") }
-
- it "returns merge_request comments ordered by created_at" do
- get v3_api("/projects/#{project.id}/merge_requests/#{merge_request.id}/comments", user)
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(2)
- expect(json_response.first['note']).to eq("a comment on a MR")
- expect(json_response.first['author']['id']).to eq(user.id)
- expect(json_response.last['note']).to eq("another comment on a MR")
- end
-
- it "returns a 404 error if merge_request_id not found" do
- get v3_api("/projects/#{project.id}/merge_requests/999/comments", user)
- expect(response).to have_gitlab_http_status(404)
- end
- end
-
- describe 'GET :id/merge_requests/:merge_request_id/closes_issues' do
- it 'returns the issue that will be closed on merge' do
- issue = create(:issue, project: project)
- mr = merge_request.tap do |mr|
- mr.update_attribute(:description, "Closes #{issue.to_reference(mr.project)}")
- end
-
- get v3_api("/projects/#{project.id}/merge_requests/#{mr.id}/closes_issues", user)
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(1)
- expect(json_response.first['id']).to eq(issue.id)
- end
-
- it 'returns an empty array when there are no issues to be closed' do
- get v3_api("/projects/#{project.id}/merge_requests/#{merge_request.id}/closes_issues", user)
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(0)
- end
-
- it 'handles external issues' do
- jira_project = create(:jira_project, :public, :repository, name: 'JIR_EXT1')
- issue = ExternalIssue.new("#{jira_project.name}-123", jira_project)
- merge_request = create(:merge_request, :simple, author: user, assignee: user, source_project: jira_project)
- merge_request.update_attribute(:description, "Closes #{issue.to_reference(jira_project)}")
-
- get v3_api("/projects/#{jira_project.id}/merge_requests/#{merge_request.id}/closes_issues", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(1)
- expect(json_response.first['title']).to eq(issue.title)
- expect(json_response.first['id']).to eq(issue.id)
- end
-
- it 'returns 403 if the user has no access to the merge request' do
- project = create(:project, :private, :repository)
- merge_request = create(:merge_request, :simple, source_project: project)
- guest = create(:user)
- project.add_guest(guest)
-
- get v3_api("/projects/#{project.id}/merge_requests/#{merge_request.id}/closes_issues", guest)
-
- expect(response).to have_gitlab_http_status(403)
- end
- end
-
- describe 'POST :id/merge_requests/:merge_request_id/subscription' do
- it 'subscribes to a merge request' do
- post v3_api("/projects/#{project.id}/merge_requests/#{merge_request.id}/subscription", admin)
-
- expect(response).to have_gitlab_http_status(201)
- expect(json_response['subscribed']).to eq(true)
- end
-
- it 'returns 304 if already subscribed' do
- post v3_api("/projects/#{project.id}/merge_requests/#{merge_request.id}/subscription", user)
-
- expect(response).to have_gitlab_http_status(304)
- end
-
- it 'returns 404 if the merge request is not found' do
- post v3_api("/projects/#{project.id}/merge_requests/123/subscription", user)
-
- expect(response).to have_gitlab_http_status(404)
- end
-
- it 'returns 403 if user has no access to read code' do
- guest = create(:user)
- project.add_guest(guest)
-
- post v3_api("/projects/#{project.id}/merge_requests/#{merge_request.id}/subscription", guest)
-
- expect(response).to have_gitlab_http_status(403)
- end
- end
-
- describe 'DELETE :id/merge_requests/:merge_request_id/subscription' do
- it 'unsubscribes from a merge request' do
- delete v3_api("/projects/#{project.id}/merge_requests/#{merge_request.id}/subscription", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['subscribed']).to eq(false)
- end
-
- it 'returns 304 if not subscribed' do
- delete v3_api("/projects/#{project.id}/merge_requests/#{merge_request.id}/subscription", admin)
-
- expect(response).to have_gitlab_http_status(304)
- end
-
- it 'returns 404 if the merge request is not found' do
- post v3_api("/projects/#{project.id}/merge_requests/123/subscription", user)
-
- expect(response).to have_gitlab_http_status(404)
- end
-
- it 'returns 403 if user has no access to read code' do
- guest = create(:user)
- project.add_guest(guest)
-
- delete v3_api("/projects/#{project.id}/merge_requests/#{merge_request.id}/subscription", guest)
-
- expect(response).to have_gitlab_http_status(403)
- end
- end
-
- describe 'Time tracking' do
- let(:issuable) { merge_request }
-
- include_examples 'V3 time tracking endpoints', 'merge_request'
- end
-
- def mr_with_later_created_and_updated_at_time
- merge_request
- merge_request.created_at += 1.hour
- merge_request.updated_at += 30.minutes
- merge_request.save
- merge_request
- end
-
- def mr_with_earlier_created_and_updated_at_time
- merge_request_closed
- merge_request_closed.created_at -= 1.hour
- merge_request_closed.updated_at -= 30.minutes
- merge_request_closed.save
- merge_request_closed
- end
-end
diff --git a/spec/requests/api/v3/milestones_spec.rb b/spec/requests/api/v3/milestones_spec.rb
deleted file mode 100644
index 6021600e09c..00000000000
--- a/spec/requests/api/v3/milestones_spec.rb
+++ /dev/null
@@ -1,238 +0,0 @@
-require 'spec_helper'
-
-describe API::V3::Milestones do
- let(:user) { create(:user) }
- let!(:project) { create(:project, namespace: user.namespace ) }
- let!(:closed_milestone) { create(:closed_milestone, project: project) }
- let!(:milestone) { create(:milestone, project: project) }
-
- before { project.add_developer(user) }
-
- describe 'GET /projects/:id/milestones' do
- it 'returns project milestones' do
- get v3_api("/projects/#{project.id}/milestones", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.first['title']).to eq(milestone.title)
- end
-
- it 'returns a 401 error if user not authenticated' do
- get v3_api("/projects/#{project.id}/milestones")
-
- expect(response).to have_gitlab_http_status(401)
- end
-
- it 'returns an array of active milestones' do
- get v3_api("/projects/#{project.id}/milestones?state=active", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(1)
- expect(json_response.first['id']).to eq(milestone.id)
- end
-
- it 'returns an array of closed milestones' do
- get v3_api("/projects/#{project.id}/milestones?state=closed", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(1)
- expect(json_response.first['id']).to eq(closed_milestone.id)
- end
- end
-
- describe 'GET /projects/:id/milestones/:milestone_id' do
- it 'returns a project milestone by id' do
- get v3_api("/projects/#{project.id}/milestones/#{milestone.id}", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['title']).to eq(milestone.title)
- expect(json_response['iid']).to eq(milestone.iid)
- end
-
- it 'returns a project milestone by iid' do
- get v3_api("/projects/#{project.id}/milestones?iid=#{closed_milestone.iid}", user)
-
- expect(response.status).to eq 200
- expect(json_response.size).to eq(1)
- expect(json_response.first['title']).to eq closed_milestone.title
- expect(json_response.first['id']).to eq closed_milestone.id
- end
-
- it 'returns a project milestone by iid array' do
- get v3_api("/projects/#{project.id}/milestones", user), iid: [milestone.iid, closed_milestone.iid]
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response.size).to eq(2)
- expect(json_response.first['title']).to eq milestone.title
- expect(json_response.first['id']).to eq milestone.id
- end
-
- it 'returns 401 error if user not authenticated' do
- get v3_api("/projects/#{project.id}/milestones/#{milestone.id}")
-
- expect(response).to have_gitlab_http_status(401)
- end
-
- it 'returns a 404 error if milestone id not found' do
- get v3_api("/projects/#{project.id}/milestones/1234", user)
-
- expect(response).to have_gitlab_http_status(404)
- end
- end
-
- describe 'POST /projects/:id/milestones' do
- it 'creates a new project milestone' do
- post v3_api("/projects/#{project.id}/milestones", user), title: 'new milestone'
-
- expect(response).to have_gitlab_http_status(201)
- expect(json_response['title']).to eq('new milestone')
- expect(json_response['description']).to be_nil
- end
-
- it 'creates a new project milestone with description and dates' do
- post v3_api("/projects/#{project.id}/milestones", user),
- title: 'new milestone', description: 'release', due_date: '2013-03-02', start_date: '2013-02-02'
-
- expect(response).to have_gitlab_http_status(201)
- expect(json_response['description']).to eq('release')
- expect(json_response['due_date']).to eq('2013-03-02')
- expect(json_response['start_date']).to eq('2013-02-02')
- end
-
- it 'returns a 400 error if title is missing' do
- post v3_api("/projects/#{project.id}/milestones", user)
-
- expect(response).to have_gitlab_http_status(400)
- end
-
- it 'returns a 400 error if params are invalid (duplicate title)' do
- post v3_api("/projects/#{project.id}/milestones", user),
- title: milestone.title, description: 'release', due_date: '2013-03-02'
-
- expect(response).to have_gitlab_http_status(400)
- end
-
- it 'creates a new project with reserved html characters' do
- post v3_api("/projects/#{project.id}/milestones", user), title: 'foo & bar 1.1 -> 2.2'
-
- expect(response).to have_gitlab_http_status(201)
- expect(json_response['title']).to eq('foo & bar 1.1 -> 2.2')
- expect(json_response['description']).to be_nil
- end
- end
-
- describe 'PUT /projects/:id/milestones/:milestone_id' do
- it 'updates a project milestone' do
- put v3_api("/projects/#{project.id}/milestones/#{milestone.id}", user),
- title: 'updated title'
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['title']).to eq('updated title')
- end
-
- it 'removes a due date if nil is passed' do
- milestone.update!(due_date: "2016-08-05")
-
- put v3_api("/projects/#{project.id}/milestones/#{milestone.id}", user), due_date: nil
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['due_date']).to be_nil
- end
-
- it 'returns a 404 error if milestone id not found' do
- put v3_api("/projects/#{project.id}/milestones/1234", user),
- title: 'updated title'
-
- expect(response).to have_gitlab_http_status(404)
- end
- end
-
- describe 'PUT /projects/:id/milestones/:milestone_id to close milestone' do
- it 'updates a project milestone' do
- put v3_api("/projects/#{project.id}/milestones/#{milestone.id}", user),
- state_event: 'close'
- expect(response).to have_gitlab_http_status(200)
-
- expect(json_response['state']).to eq('closed')
- end
- end
-
- describe 'PUT /projects/:id/milestones/:milestone_id to test observer on close' do
- it 'creates an activity event when an milestone is closed' do
- expect(Event).to receive(:create!)
-
- put v3_api("/projects/#{project.id}/milestones/#{milestone.id}", user),
- state_event: 'close'
- end
- end
-
- describe 'GET /projects/:id/milestones/:milestone_id/issues' do
- before do
- milestone.issues << create(:issue, project: project)
- end
- it 'returns project issues for a particular milestone' do
- get v3_api("/projects/#{project.id}/milestones/#{milestone.id}/issues", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.first['milestone']['title']).to eq(milestone.title)
- end
-
- it 'matches V3 response schema for a list of issues' do
- get v3_api("/projects/#{project.id}/milestones/#{milestone.id}/issues", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(response).to match_response_schema('public_api/v3/issues')
- end
-
- it 'returns a 401 error if user not authenticated' do
- get v3_api("/projects/#{project.id}/milestones/#{milestone.id}/issues")
-
- expect(response).to have_gitlab_http_status(401)
- end
-
- describe 'confidential issues' do
- let(:public_project) { create(:project, :public) }
- let(:milestone) { create(:milestone, project: public_project) }
- let(:issue) { create(:issue, project: public_project) }
- let(:confidential_issue) { create(:issue, confidential: true, project: public_project) }
-
- before do
- public_project.add_developer(user)
- milestone.issues << issue << confidential_issue
- end
-
- it 'returns confidential issues to team members' do
- get v3_api("/projects/#{public_project.id}/milestones/#{milestone.id}/issues", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.size).to eq(2)
- expect(json_response.map { |issue| issue['id'] }).to include(issue.id, confidential_issue.id)
- end
-
- it 'does not return confidential issues to team members with guest role' do
- member = create(:user)
- project.add_guest(member)
-
- get v3_api("/projects/#{public_project.id}/milestones/#{milestone.id}/issues", member)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.size).to eq(1)
- expect(json_response.map { |issue| issue['id'] }).to include(issue.id)
- end
-
- it 'does not return confidential issues to regular users' do
- get v3_api("/projects/#{public_project.id}/milestones/#{milestone.id}/issues", create(:user))
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.size).to eq(1)
- expect(json_response.map { |issue| issue['id'] }).to include(issue.id)
- end
- end
- end
-end
diff --git a/spec/requests/api/v3/notes_spec.rb b/spec/requests/api/v3/notes_spec.rb
deleted file mode 100644
index 5532795ab02..00000000000
--- a/spec/requests/api/v3/notes_spec.rb
+++ /dev/null
@@ -1,431 +0,0 @@
-require 'spec_helper'
-
-describe API::V3::Notes do
- let(:user) { create(:user) }
- let!(:project) { create(:project, :public, namespace: user.namespace) }
- let!(:issue) { create(:issue, project: project, author: user) }
- let!(:merge_request) { create(:merge_request, source_project: project, target_project: project, author: user) }
- let!(:snippet) { create(:project_snippet, project: project, author: user) }
- let!(:issue_note) { create(:note, noteable: issue, project: project, author: user) }
- let!(:merge_request_note) { create(:note, noteable: merge_request, project: project, author: user) }
- let!(:snippet_note) { create(:note, noteable: snippet, project: project, author: user) }
-
- # For testing the cross-reference of a private issue in a public issue
- let(:private_user) { create(:user) }
- let(:private_project) do
- create(:project, namespace: private_user.namespace)
- .tap { |p| p.add_master(private_user) }
- end
- let(:private_issue) { create(:issue, project: private_project) }
-
- let(:ext_proj) { create(:project, :public) }
- let(:ext_issue) { create(:issue, project: ext_proj) }
-
- let!(:cross_reference_note) do
- create :note,
- noteable: ext_issue, project: ext_proj,
- note: "mentioned in issue #{private_issue.to_reference(ext_proj)}",
- system: true
- end
-
- before { project.add_reporter(user) }
-
- describe "GET /projects/:id/noteable/:noteable_id/notes" do
- context "when noteable is an Issue" do
- it "returns an array of issue notes" do
- get v3_api("/projects/#{project.id}/issues/#{issue.id}/notes", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response.first['body']).to eq(issue_note.note)
- expect(json_response.first['upvote']).to be_falsey
- expect(json_response.first['downvote']).to be_falsey
- end
-
- it "returns a 404 error when issue id not found" do
- get v3_api("/projects/#{project.id}/issues/12345/notes", user)
-
- expect(response).to have_gitlab_http_status(404)
- end
-
- context "and current user cannot view the notes" do
- it "returns an empty array" do
- get v3_api("/projects/#{ext_proj.id}/issues/#{ext_issue.id}/notes", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response).to be_empty
- end
-
- context "and issue is confidential" do
- before { ext_issue.update_attributes(confidential: true) }
-
- it "returns 404" do
- get v3_api("/projects/#{ext_proj.id}/issues/#{ext_issue.id}/notes", user)
-
- expect(response).to have_gitlab_http_status(404)
- end
- end
-
- context "and current user can view the note" do
- it "returns an empty array" do
- get v3_api("/projects/#{ext_proj.id}/issues/#{ext_issue.id}/notes", private_user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response.first['body']).to eq(cross_reference_note.note)
- end
- end
- end
- end
-
- context "when noteable is a Snippet" do
- it "returns an array of snippet notes" do
- get v3_api("/projects/#{project.id}/snippets/#{snippet.id}/notes", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response.first['body']).to eq(snippet_note.note)
- end
-
- it "returns a 404 error when snippet id not found" do
- get v3_api("/projects/#{project.id}/snippets/42/notes", user)
-
- expect(response).to have_gitlab_http_status(404)
- end
-
- it "returns 404 when not authorized" do
- get v3_api("/projects/#{project.id}/snippets/#{snippet.id}/notes", private_user)
-
- expect(response).to have_gitlab_http_status(404)
- end
- end
-
- context "when noteable is a Merge Request" do
- it "returns an array of merge_requests notes" do
- get v3_api("/projects/#{project.id}/merge_requests/#{merge_request.id}/notes", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response.first['body']).to eq(merge_request_note.note)
- end
-
- it "returns a 404 error if merge request id not found" do
- get v3_api("/projects/#{project.id}/merge_requests/4444/notes", user)
-
- expect(response).to have_gitlab_http_status(404)
- end
-
- it "returns 404 when not authorized" do
- get v3_api("/projects/#{project.id}/merge_requests/4444/notes", private_user)
-
- expect(response).to have_gitlab_http_status(404)
- end
- end
- end
-
- describe "GET /projects/:id/noteable/:noteable_id/notes/:note_id" do
- context "when noteable is an Issue" do
- it "returns an issue note by id" do
- get v3_api("/projects/#{project.id}/issues/#{issue.id}/notes/#{issue_note.id}", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['body']).to eq(issue_note.note)
- end
-
- it "returns a 404 error if issue note not found" do
- get v3_api("/projects/#{project.id}/issues/#{issue.id}/notes/12345", user)
-
- expect(response).to have_gitlab_http_status(404)
- end
-
- context "and current user cannot view the note" do
- it "returns a 404 error" do
- get v3_api("/projects/#{ext_proj.id}/issues/#{ext_issue.id}/notes/#{cross_reference_note.id}", user)
-
- expect(response).to have_gitlab_http_status(404)
- end
-
- context "when issue is confidential" do
- before { issue.update_attributes(confidential: true) }
-
- it "returns 404" do
- get v3_api("/projects/#{project.id}/issues/#{issue.id}/notes/#{issue_note.id}", private_user)
-
- expect(response).to have_gitlab_http_status(404)
- end
- end
-
- context "and current user can view the note" do
- it "returns an issue note by id" do
- get v3_api("/projects/#{ext_proj.id}/issues/#{ext_issue.id}/notes/#{cross_reference_note.id}", private_user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['body']).to eq(cross_reference_note.note)
- end
- end
- end
- end
-
- context "when noteable is a Snippet" do
- it "returns a snippet note by id" do
- get v3_api("/projects/#{project.id}/snippets/#{snippet.id}/notes/#{snippet_note.id}", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['body']).to eq(snippet_note.note)
- end
-
- it "returns a 404 error if snippet note not found" do
- get v3_api("/projects/#{project.id}/snippets/#{snippet.id}/notes/12345", user)
-
- expect(response).to have_gitlab_http_status(404)
- end
- end
- end
-
- describe "POST /projects/:id/noteable/:noteable_id/notes" do
- context "when noteable is an Issue" do
- it "creates a new issue note" do
- post v3_api("/projects/#{project.id}/issues/#{issue.id}/notes", user), body: 'hi!'
-
- expect(response).to have_gitlab_http_status(201)
- expect(json_response['body']).to eq('hi!')
- expect(json_response['author']['username']).to eq(user.username)
- end
-
- it "returns a 400 bad request error if body not given" do
- post v3_api("/projects/#{project.id}/issues/#{issue.id}/notes", user)
-
- expect(response).to have_gitlab_http_status(400)
- end
-
- it "returns a 401 unauthorized error if user not authenticated" do
- post v3_api("/projects/#{project.id}/issues/#{issue.id}/notes"), body: 'hi!'
-
- expect(response).to have_gitlab_http_status(401)
- end
-
- context 'when an admin or owner makes the request' do
- it 'accepts the creation date to be set' do
- creation_time = 2.weeks.ago
- post v3_api("/projects/#{project.id}/issues/#{issue.id}/notes", user),
- body: 'hi!', created_at: creation_time
-
- expect(response).to have_gitlab_http_status(201)
- expect(json_response['body']).to eq('hi!')
- expect(json_response['author']['username']).to eq(user.username)
- expect(Time.parse(json_response['created_at'])).to be_like_time(creation_time)
- end
- end
-
- context 'when the user is posting an award emoji on an issue created by someone else' do
- let(:issue2) { create(:issue, project: project) }
-
- it 'creates a new issue note' do
- post v3_api("/projects/#{project.id}/issues/#{issue2.id}/notes", user), body: ':+1:'
-
- expect(response).to have_gitlab_http_status(201)
- expect(json_response['body']).to eq(':+1:')
- end
- end
-
- context 'when the user is posting an award emoji on his/her own issue' do
- it 'creates a new issue note' do
- post v3_api("/projects/#{project.id}/issues/#{issue.id}/notes", user), body: ':+1:'
-
- expect(response).to have_gitlab_http_status(201)
- expect(json_response['body']).to eq(':+1:')
- end
- end
- end
-
- context "when noteable is a Snippet" do
- it "creates a new snippet note" do
- post v3_api("/projects/#{project.id}/snippets/#{snippet.id}/notes", user), body: 'hi!'
-
- expect(response).to have_gitlab_http_status(201)
- expect(json_response['body']).to eq('hi!')
- expect(json_response['author']['username']).to eq(user.username)
- end
-
- it "returns a 400 bad request error if body not given" do
- post v3_api("/projects/#{project.id}/snippets/#{snippet.id}/notes", user)
-
- expect(response).to have_gitlab_http_status(400)
- end
-
- it "returns a 401 unauthorized error if user not authenticated" do
- post v3_api("/projects/#{project.id}/snippets/#{snippet.id}/notes"), body: 'hi!'
-
- expect(response).to have_gitlab_http_status(401)
- end
- end
-
- context 'when user does not have access to read the noteable' do
- it 'responds with 404' do
- project = create(:project, :private) { |p| p.add_guest(user) }
- issue = create(:issue, :confidential, project: project)
-
- post v3_api("/projects/#{project.id}/issues/#{issue.id}/notes", user),
- body: 'Foo'
-
- expect(response).to have_gitlab_http_status(404)
- end
- end
-
- context 'when user does not have access to create noteable' do
- let(:private_issue) { create(:issue, project: create(:project, :private)) }
-
- ##
- # We are posting to project user has access to, but we use issue id
- # from a different project, see #15577
- #
- before do
- post v3_api("/projects/#{project.id}/issues/#{private_issue.id}/notes", user),
- body: 'Hi!'
- end
-
- it 'responds with resource not found error' do
- expect(response.status).to eq 404
- end
-
- it 'does not create new note' do
- expect(private_issue.notes.reload).to be_empty
- end
- end
- end
-
- describe "POST /projects/:id/noteable/:noteable_id/notes to test observer on create" do
- it "creates an activity event when an issue note is created" do
- expect(Event).to receive(:create!)
-
- post v3_api("/projects/#{project.id}/issues/#{issue.id}/notes", user), body: 'hi!'
- end
- end
-
- describe 'PUT /projects/:id/noteable/:noteable_id/notes/:note_id' do
- context 'when noteable is an Issue' do
- it 'returns modified note' do
- put v3_api("/projects/#{project.id}/issues/#{issue.id}/"\
- "notes/#{issue_note.id}", user), body: 'Hello!'
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['body']).to eq('Hello!')
- end
-
- it 'returns a 404 error when note id not found' do
- put v3_api("/projects/#{project.id}/issues/#{issue.id}/notes/12345", user),
- body: 'Hello!'
-
- expect(response).to have_gitlab_http_status(404)
- end
-
- it 'returns a 400 bad request error if body not given' do
- put v3_api("/projects/#{project.id}/issues/#{issue.id}/"\
- "notes/#{issue_note.id}", user)
-
- expect(response).to have_gitlab_http_status(400)
- end
- end
-
- context 'when noteable is a Snippet' do
- it 'returns modified note' do
- put v3_api("/projects/#{project.id}/snippets/#{snippet.id}/"\
- "notes/#{snippet_note.id}", user), body: 'Hello!'
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['body']).to eq('Hello!')
- end
-
- it 'returns a 404 error when note id not found' do
- put v3_api("/projects/#{project.id}/snippets/#{snippet.id}/"\
- "notes/12345", user), body: "Hello!"
-
- expect(response).to have_gitlab_http_status(404)
- end
- end
-
- context 'when noteable is a Merge Request' do
- it 'returns modified note' do
- put v3_api("/projects/#{project.id}/merge_requests/#{merge_request.id}/"\
- "notes/#{merge_request_note.id}", user), body: 'Hello!'
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['body']).to eq('Hello!')
- end
-
- it 'returns a 404 error when note id not found' do
- put v3_api("/projects/#{project.id}/merge_requests/#{merge_request.id}/"\
- "notes/12345", user), body: "Hello!"
-
- expect(response).to have_gitlab_http_status(404)
- end
- end
- end
-
- describe 'DELETE /projects/:id/noteable/:noteable_id/notes/:note_id' do
- context 'when noteable is an Issue' do
- it 'deletes a note' do
- delete v3_api("/projects/#{project.id}/issues/#{issue.id}/"\
- "notes/#{issue_note.id}", user)
-
- expect(response).to have_gitlab_http_status(200)
- # Check if note is really deleted
- delete v3_api("/projects/#{project.id}/issues/#{issue.id}/"\
- "notes/#{issue_note.id}", user)
- expect(response).to have_gitlab_http_status(404)
- end
-
- it 'returns a 404 error when note id not found' do
- delete v3_api("/projects/#{project.id}/issues/#{issue.id}/notes/12345", user)
-
- expect(response).to have_gitlab_http_status(404)
- end
- end
-
- context 'when noteable is a Snippet' do
- it 'deletes a note' do
- delete v3_api("/projects/#{project.id}/snippets/#{snippet.id}/"\
- "notes/#{snippet_note.id}", user)
-
- expect(response).to have_gitlab_http_status(200)
- # Check if note is really deleted
- delete v3_api("/projects/#{project.id}/snippets/#{snippet.id}/"\
- "notes/#{snippet_note.id}", user)
- expect(response).to have_gitlab_http_status(404)
- end
-
- it 'returns a 404 error when note id not found' do
- delete v3_api("/projects/#{project.id}/snippets/#{snippet.id}/"\
- "notes/12345", user)
-
- expect(response).to have_gitlab_http_status(404)
- end
- end
-
- context 'when noteable is a Merge Request' do
- it 'deletes a note' do
- delete v3_api("/projects/#{project.id}/merge_requests/"\
- "#{merge_request.id}/notes/#{merge_request_note.id}", user)
-
- expect(response).to have_gitlab_http_status(200)
- # Check if note is really deleted
- delete v3_api("/projects/#{project.id}/merge_requests/"\
- "#{merge_request.id}/notes/#{merge_request_note.id}", user)
- expect(response).to have_gitlab_http_status(404)
- end
-
- it 'returns a 404 error when note id not found' do
- delete v3_api("/projects/#{project.id}/merge_requests/"\
- "#{merge_request.id}/notes/12345", user)
-
- expect(response).to have_gitlab_http_status(404)
- end
- end
- end
-end
diff --git a/spec/requests/api/v3/pipelines_spec.rb b/spec/requests/api/v3/pipelines_spec.rb
deleted file mode 100644
index ea943f22c41..00000000000
--- a/spec/requests/api/v3/pipelines_spec.rb
+++ /dev/null
@@ -1,201 +0,0 @@
-require 'spec_helper'
-
-describe API::V3::Pipelines do
- let(:user) { create(:user) }
- let(:non_member) { create(:user) }
- let(:project) { create(:project, :repository, creator: user) }
-
- let!(:pipeline) do
- create(:ci_empty_pipeline, project: project, sha: project.commit.id,
- ref: project.default_branch)
- end
-
- before { project.add_master(user) }
-
- shared_examples 'a paginated resources' do
- before do
- # Fires the request
- request
- end
-
- it 'has pagination headers' do
- expect(response).to include_pagination_headers
- end
- end
-
- describe 'GET /projects/:id/pipelines ' do
- it_behaves_like 'a paginated resources' do
- let(:request) { get v3_api("/projects/#{project.id}/pipelines", user) }
- end
-
- context 'authorized user' do
- it 'returns project pipelines' do
- get v3_api("/projects/#{project.id}/pipelines", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.first['sha']).to match(/\A\h{40}\z/)
- expect(json_response.first['id']).to eq pipeline.id
- expect(json_response.first.keys).to contain_exactly(*%w[id sha ref status before_sha tag yaml_errors user created_at updated_at started_at finished_at committed_at duration coverage])
- end
- end
-
- context 'unauthorized user' do
- it 'does not return project pipelines' do
- get v3_api("/projects/#{project.id}/pipelines", non_member)
-
- expect(response).to have_gitlab_http_status(404)
- expect(json_response['message']).to eq '404 Project Not Found'
- expect(json_response).not_to be_an Array
- end
- end
- end
-
- describe 'POST /projects/:id/pipeline ' do
- context 'authorized user' do
- context 'with gitlab-ci.yml' do
- before { stub_ci_pipeline_to_return_yaml_file }
-
- it 'creates and returns a new pipeline' do
- expect do
- post v3_api("/projects/#{project.id}/pipeline", user), ref: project.default_branch
- end.to change { Ci::Pipeline.count }.by(1)
-
- expect(response).to have_gitlab_http_status(201)
- expect(json_response).to be_a Hash
- expect(json_response['sha']).to eq project.commit.id
- end
-
- it 'fails when using an invalid ref' do
- post v3_api("/projects/#{project.id}/pipeline", user), ref: 'invalid_ref'
-
- expect(response).to have_gitlab_http_status(400)
- expect(json_response['message']['base'].first).to eq 'Reference not found'
- expect(json_response).not_to be_an Array
- end
- end
-
- context 'without gitlab-ci.yml' do
- it 'fails to create pipeline' do
- post v3_api("/projects/#{project.id}/pipeline", user), ref: project.default_branch
-
- expect(response).to have_gitlab_http_status(400)
- expect(json_response['message']['base'].first).to eq 'Missing .gitlab-ci.yml file'
- expect(json_response).not_to be_an Array
- end
- end
- end
-
- context 'unauthorized user' do
- it 'does not create pipeline' do
- post v3_api("/projects/#{project.id}/pipeline", non_member), ref: project.default_branch
-
- expect(response).to have_gitlab_http_status(404)
- expect(json_response['message']).to eq '404 Project Not Found'
- expect(json_response).not_to be_an Array
- end
- end
- end
-
- describe 'GET /projects/:id/pipelines/:pipeline_id' do
- context 'authorized user' do
- it 'returns project pipelines' do
- get v3_api("/projects/#{project.id}/pipelines/#{pipeline.id}", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['sha']).to match /\A\h{40}\z/
- end
-
- it 'returns 404 when it does not exist' do
- get v3_api("/projects/#{project.id}/pipelines/123456", user)
-
- expect(response).to have_gitlab_http_status(404)
- expect(json_response['message']).to eq '404 Not found'
- expect(json_response['id']).to be nil
- end
-
- context 'with coverage' do
- before do
- create(:ci_build, coverage: 30, pipeline: pipeline)
- end
-
- it 'exposes the coverage' do
- get v3_api("/projects/#{project.id}/pipelines/#{pipeline.id}", user)
-
- expect(json_response["coverage"].to_i).to eq(30)
- end
- end
- end
-
- context 'unauthorized user' do
- it 'should not return a project pipeline' do
- get v3_api("/projects/#{project.id}/pipelines/#{pipeline.id}", non_member)
-
- expect(response).to have_gitlab_http_status(404)
- expect(json_response['message']).to eq '404 Project Not Found'
- expect(json_response['id']).to be nil
- end
- end
- end
-
- describe 'POST /projects/:id/pipelines/:pipeline_id/retry' do
- context 'authorized user' do
- let!(:pipeline) do
- create(:ci_pipeline, project: project, sha: project.commit.id,
- ref: project.default_branch)
- end
-
- let!(:build) { create(:ci_build, :failed, pipeline: pipeline) }
-
- it 'retries failed builds' do
- expect do
- post v3_api("/projects/#{project.id}/pipelines/#{pipeline.id}/retry", user)
- end.to change { pipeline.builds.count }.from(1).to(2)
-
- expect(response).to have_gitlab_http_status(201)
- expect(build.reload.retried?).to be true
- end
- end
-
- context 'unauthorized user' do
- it 'should not return a project pipeline' do
- post v3_api("/projects/#{project.id}/pipelines/#{pipeline.id}/retry", non_member)
-
- expect(response).to have_gitlab_http_status(404)
- expect(json_response['message']).to eq '404 Project Not Found'
- expect(json_response['id']).to be nil
- end
- end
- end
-
- describe 'POST /projects/:id/pipelines/:pipeline_id/cancel' do
- let!(:pipeline) do
- create(:ci_empty_pipeline, project: project, sha: project.commit.id,
- ref: project.default_branch)
- end
-
- let!(:build) { create(:ci_build, :running, pipeline: pipeline) }
-
- context 'authorized user' do
- it 'retries failed builds' do
- post v3_api("/projects/#{project.id}/pipelines/#{pipeline.id}/cancel", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['status']).to eq('canceled')
- end
- end
-
- context 'user without proper access rights' do
- let!(:reporter) { create(:user) }
-
- before { project.add_reporter(reporter) }
-
- it 'rejects the action' do
- post v3_api("/projects/#{project.id}/pipelines/#{pipeline.id}/cancel", reporter)
-
- expect(response).to have_gitlab_http_status(403)
- expect(pipeline.reload.status).to eq('pending')
- end
- end
- end
-end
diff --git a/spec/requests/api/v3/project_hooks_spec.rb b/spec/requests/api/v3/project_hooks_spec.rb
deleted file mode 100644
index 8f6a2330d25..00000000000
--- a/spec/requests/api/v3/project_hooks_spec.rb
+++ /dev/null
@@ -1,219 +0,0 @@
-require 'spec_helper'
-
-describe API::ProjectHooks, 'ProjectHooks' do
- let(:user) { create(:user) }
- let(:user3) { create(:user) }
- let!(:project) { create(:project, creator_id: user.id, namespace: user.namespace) }
- let!(:hook) do
- create(:project_hook,
- :all_events_enabled,
- project: project,
- url: 'http://example.com',
- enable_ssl_verification: true)
- end
-
- before do
- project.add_master(user)
- project.add_developer(user3)
- end
-
- describe "GET /projects/:id/hooks" do
- context "authorized user" do
- it "returns project hooks" do
- get v3_api("/projects/#{project.id}/hooks", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.count).to eq(1)
- expect(json_response.first['url']).to eq("http://example.com")
- expect(json_response.first['issues_events']).to eq(true)
- expect(json_response.first['confidential_issues_events']).to eq(true)
- expect(json_response.first['push_events']).to eq(true)
- expect(json_response.first['merge_requests_events']).to eq(true)
- expect(json_response.first['tag_push_events']).to eq(true)
- expect(json_response.first['note_events']).to eq(true)
- expect(json_response.first['build_events']).to eq(true)
- expect(json_response.first['pipeline_events']).to eq(true)
- expect(json_response.first['wiki_page_events']).to eq(true)
- expect(json_response.first['enable_ssl_verification']).to eq(true)
- end
- end
-
- context "unauthorized user" do
- it "does not access project hooks" do
- get v3_api("/projects/#{project.id}/hooks", user3)
-
- expect(response).to have_gitlab_http_status(403)
- end
- end
- end
-
- describe "GET /projects/:id/hooks/:hook_id" do
- context "authorized user" do
- it "returns a project hook" do
- get v3_api("/projects/#{project.id}/hooks/#{hook.id}", user)
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['url']).to eq(hook.url)
- expect(json_response['issues_events']).to eq(hook.issues_events)
- expect(json_response['confidential_issues_events']).to eq(hook.confidential_issues_events)
- expect(json_response['push_events']).to eq(hook.push_events)
- expect(json_response['merge_requests_events']).to eq(hook.merge_requests_events)
- expect(json_response['tag_push_events']).to eq(hook.tag_push_events)
- expect(json_response['note_events']).to eq(hook.note_events)
- expect(json_response['build_events']).to eq(hook.job_events)
- expect(json_response['pipeline_events']).to eq(hook.pipeline_events)
- expect(json_response['wiki_page_events']).to eq(hook.wiki_page_events)
- expect(json_response['enable_ssl_verification']).to eq(hook.enable_ssl_verification)
- end
-
- it "returns a 404 error if hook id is not available" do
- get v3_api("/projects/#{project.id}/hooks/1234", user)
- expect(response).to have_gitlab_http_status(404)
- end
- end
-
- context "unauthorized user" do
- it "does not access an existing hook" do
- get v3_api("/projects/#{project.id}/hooks/#{hook.id}", user3)
- expect(response).to have_gitlab_http_status(403)
- end
- end
-
- it "returns a 404 error if hook id is not available" do
- get v3_api("/projects/#{project.id}/hooks/1234", user)
- expect(response).to have_gitlab_http_status(404)
- end
- end
-
- describe "POST /projects/:id/hooks" do
- it "adds hook to project" do
- expect do
- post v3_api("/projects/#{project.id}/hooks", user),
- url: "http://example.com", issues_events: true, confidential_issues_events: true, wiki_page_events: true, build_events: true
- end.to change {project.hooks.count}.by(1)
-
- expect(response).to have_gitlab_http_status(201)
- expect(json_response['url']).to eq('http://example.com')
- expect(json_response['issues_events']).to eq(true)
- expect(json_response['confidential_issues_events']).to eq(true)
- expect(json_response['push_events']).to eq(true)
- expect(json_response['merge_requests_events']).to eq(false)
- expect(json_response['tag_push_events']).to eq(false)
- expect(json_response['note_events']).to eq(false)
- expect(json_response['build_events']).to eq(true)
- expect(json_response['pipeline_events']).to eq(false)
- expect(json_response['wiki_page_events']).to eq(true)
- expect(json_response['enable_ssl_verification']).to eq(true)
- expect(json_response).not_to include('token')
- end
-
- it "adds the token without including it in the response" do
- token = "secret token"
-
- expect do
- post v3_api("/projects/#{project.id}/hooks", user), url: "http://example.com", token: token
- end.to change {project.hooks.count}.by(1)
-
- expect(response).to have_gitlab_http_status(201)
- expect(json_response["url"]).to eq("http://example.com")
- expect(json_response).not_to include("token")
-
- hook = project.hooks.find(json_response["id"])
-
- expect(hook.url).to eq("http://example.com")
- expect(hook.token).to eq(token)
- end
-
- it "returns a 400 error if url not given" do
- post v3_api("/projects/#{project.id}/hooks", user)
- expect(response).to have_gitlab_http_status(400)
- end
-
- it "returns a 422 error if url not valid" do
- post v3_api("/projects/#{project.id}/hooks", user), "url" => "ftp://example.com"
- expect(response).to have_gitlab_http_status(422)
- end
- end
-
- describe "PUT /projects/:id/hooks/:hook_id" do
- it "updates an existing project hook" do
- put v3_api("/projects/#{project.id}/hooks/#{hook.id}", user),
- url: 'http://example.org', push_events: false, build_events: true
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['url']).to eq('http://example.org')
- expect(json_response['issues_events']).to eq(hook.issues_events)
- expect(json_response['confidential_issues_events']).to eq(hook.confidential_issues_events)
- expect(json_response['push_events']).to eq(false)
- expect(json_response['merge_requests_events']).to eq(hook.merge_requests_events)
- expect(json_response['tag_push_events']).to eq(hook.tag_push_events)
- expect(json_response['note_events']).to eq(hook.note_events)
- expect(json_response['build_events']).to eq(hook.job_events)
- expect(json_response['pipeline_events']).to eq(hook.pipeline_events)
- expect(json_response['wiki_page_events']).to eq(hook.wiki_page_events)
- expect(json_response['enable_ssl_verification']).to eq(hook.enable_ssl_verification)
- end
-
- it "adds the token without including it in the response" do
- token = "secret token"
-
- put v3_api("/projects/#{project.id}/hooks/#{hook.id}", user), url: "http://example.org", token: token
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response["url"]).to eq("http://example.org")
- expect(json_response).not_to include("token")
-
- expect(hook.reload.url).to eq("http://example.org")
- expect(hook.reload.token).to eq(token)
- end
-
- it "returns 404 error if hook id not found" do
- put v3_api("/projects/#{project.id}/hooks/1234", user), url: 'http://example.org'
- expect(response).to have_gitlab_http_status(404)
- end
-
- it "returns 400 error if url is not given" do
- put v3_api("/projects/#{project.id}/hooks/#{hook.id}", user)
- expect(response).to have_gitlab_http_status(400)
- end
-
- it "returns a 422 error if url is not valid" do
- put v3_api("/projects/#{project.id}/hooks/#{hook.id}", user), url: 'ftp://example.com'
- expect(response).to have_gitlab_http_status(422)
- end
- end
-
- describe "DELETE /projects/:id/hooks/:hook_id" do
- it "deletes hook from project" do
- expect do
- delete v3_api("/projects/#{project.id}/hooks/#{hook.id}", user)
- end.to change {project.hooks.count}.by(-1)
- expect(response).to have_gitlab_http_status(200)
- end
-
- it "returns success when deleting hook" do
- delete v3_api("/projects/#{project.id}/hooks/#{hook.id}", user)
- expect(response).to have_gitlab_http_status(200)
- end
-
- it "returns a 404 error when deleting non existent hook" do
- delete v3_api("/projects/#{project.id}/hooks/42", user)
- expect(response).to have_gitlab_http_status(404)
- end
-
- it "returns a 404 error if hook id not given" do
- delete v3_api("/projects/#{project.id}/hooks", user)
-
- expect(response).to have_gitlab_http_status(404)
- end
-
- it "returns a 404 if a user attempts to delete project hooks he/she does not own" do
- test_user = create(:user)
- other_project = create(:project)
- other_project.add_master(test_user)
-
- delete v3_api("/projects/#{other_project.id}/hooks/#{hook.id}", test_user)
- expect(response).to have_gitlab_http_status(404)
- expect(WebHook.exists?(hook.id)).to be_truthy
- end
- end
-end
diff --git a/spec/requests/api/v3/project_snippets_spec.rb b/spec/requests/api/v3/project_snippets_spec.rb
deleted file mode 100644
index 2ed31b99516..00000000000
--- a/spec/requests/api/v3/project_snippets_spec.rb
+++ /dev/null
@@ -1,226 +0,0 @@
-require 'rails_helper'
-
-describe API::ProjectSnippets do
- let(:project) { create(:project, :public) }
- let(:user) { create(:user) }
- let(:admin) { create(:admin) }
-
- describe 'GET /projects/:project_id/snippets/:id' do
- # TODO (rspeicher): Deprecated; remove in 9.0
- it 'always exposes expires_at as nil' do
- snippet = create(:project_snippet, author: admin)
-
- get v3_api("/projects/#{snippet.project.id}/snippets/#{snippet.id}", admin)
-
- expect(json_response).to have_key('expires_at')
- expect(json_response['expires_at']).to be_nil
- end
- end
-
- describe 'GET /projects/:project_id/snippets/' do
- let(:user) { create(:user) }
-
- it 'returns all snippets available to team member' do
- project.add_developer(user)
- public_snippet = create(:project_snippet, :public, project: project)
- internal_snippet = create(:project_snippet, :internal, project: project)
- private_snippet = create(:project_snippet, :private, project: project)
-
- get v3_api("/projects/#{project.id}/snippets/", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response.size).to eq(3)
- expect(json_response.map { |snippet| snippet['id']} ).to include(public_snippet.id, internal_snippet.id, private_snippet.id)
- expect(json_response.last).to have_key('web_url')
- end
-
- it 'hides private snippets from regular user' do
- create(:project_snippet, :private, project: project)
-
- get v3_api("/projects/#{project.id}/snippets/", user)
- expect(response).to have_gitlab_http_status(200)
- expect(json_response.size).to eq(0)
- end
- end
-
- describe 'POST /projects/:project_id/snippets/' do
- let(:params) do
- {
- title: 'Test Title',
- file_name: 'test.rb',
- code: 'puts "hello world"',
- visibility_level: Snippet::PUBLIC
- }
- end
-
- it 'creates a new snippet' do
- post v3_api("/projects/#{project.id}/snippets/", admin), params
-
- expect(response).to have_gitlab_http_status(201)
- snippet = ProjectSnippet.find(json_response['id'])
- 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])
- end
-
- it 'returns 400 for missing parameters' do
- params.delete(:title)
-
- post v3_api("/projects/#{project.id}/snippets/", admin), params
-
- expect(response).to have_gitlab_http_status(400)
- end
-
- context 'when the snippet is spam' do
- def create_snippet(project, snippet_params = {})
- project.add_developer(user)
-
- post v3_api("/projects/#{project.id}/snippets", user), params.merge(snippet_params)
- end
-
- before do
- allow_any_instance_of(AkismetService).to receive(:spam?).and_return(true)
- end
-
- context 'when the snippet is private' do
- it 'creates the snippet' do
- expect { create_snippet(project, 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(project, visibility_level: Snippet::PUBLIC) }
- .not_to change { Snippet.count }
-
- expect(response).to have_gitlab_http_status(400)
- expect(json_response['message']).to eq({ "error" => "Spam detected" })
- end
-
- it 'creates a spam log' do
- expect { create_snippet(project, visibility_level: Snippet::PUBLIC) }
- .to change { SpamLog.count }.by(1)
- end
- end
- end
- end
-
- describe 'PUT /projects/:project_id/snippets/:id/' do
- let(:visibility_level) { Snippet::PUBLIC }
- let(:snippet) { create(:project_snippet, author: admin, visibility_level: visibility_level) }
-
- it 'updates snippet' do
- new_content = 'New content'
-
- put v3_api("/projects/#{snippet.project.id}/snippets/#{snippet.id}/", admin), code: new_content
-
- expect(response).to have_gitlab_http_status(200)
- snippet.reload
- expect(snippet.content).to eq(new_content)
- end
-
- it 'returns 404 for invalid snippet id' do
- put v3_api("/projects/#{snippet.project.id}/snippets/1234", admin), title: 'foo'
-
- expect(response).to have_gitlab_http_status(404)
- expect(json_response['message']).to eq('404 Snippet Not Found')
- end
-
- it 'returns 400 for missing parameters' do
- put v3_api("/projects/#{project.id}/snippets/1234", admin)
-
- expect(response).to have_gitlab_http_status(400)
- end
-
- context 'when the snippet is spam' do
- def update_snippet(snippet_params = {})
- put v3_api("/projects/#{snippet.project.id}/snippets/#{snippet.id}", admin), snippet_params
- end
-
- before do
- allow_any_instance_of(AkismetService).to receive(:spam?).and_return(true)
- end
-
- context 'when the snippet is private' do
- let(:visibility_level) { Snippet::PRIVATE }
-
- it 'creates the snippet' do
- expect { update_snippet(title: 'Foo') }
- .to change { snippet.reload.title }.to('Foo')
- end
- end
-
- context 'when the snippet is public' do
- let(:visibility_level) { Snippet::PUBLIC }
-
- it 'rejects the snippet' do
- expect { update_snippet(title: 'Foo') }
- .not_to change { snippet.reload.title }
- end
-
- it 'creates a spam log' do
- expect { update_snippet(title: 'Foo') }
- .to change { SpamLog.count }.by(1)
- end
- end
-
- context 'when the private snippet is made public' do
- let(:visibility_level) { Snippet::PRIVATE }
-
- it 'rejects the snippet' do
- expect { update_snippet(title: 'Foo', visibility_level: Snippet::PUBLIC) }
- .not_to change { snippet.reload.title }
-
- expect(response).to have_gitlab_http_status(400)
- expect(json_response['message']).to eq({ "error" => "Spam detected" })
- end
-
- it 'creates a spam log' do
- expect { update_snippet(title: 'Foo', visibility_level: Snippet::PUBLIC) }
- .to change { SpamLog.count }.by(1)
- end
- end
- end
- end
-
- describe 'DELETE /projects/:project_id/snippets/:id/' do
- let(:snippet) { create(:project_snippet, author: admin) }
-
- it 'deletes snippet' do
- admin = create(:admin)
- snippet = create(:project_snippet, author: admin)
-
- delete v3_api("/projects/#{snippet.project.id}/snippets/#{snippet.id}/", admin)
-
- expect(response).to have_gitlab_http_status(200)
- end
-
- it 'returns 404 for invalid snippet id' do
- delete v3_api("/projects/#{snippet.project.id}/snippets/1234", admin)
-
- expect(response).to have_gitlab_http_status(404)
- expect(json_response['message']).to eq('404 Snippet Not Found')
- end
- end
-
- describe 'GET /projects/:project_id/snippets/:id/raw' do
- let(:snippet) { create(:project_snippet, author: admin) }
-
- it 'returns raw text' do
- get v3_api("/projects/#{snippet.project.id}/snippets/#{snippet.id}/raw", admin)
-
- expect(response).to have_gitlab_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("/projects/#{snippet.project.id}/snippets/1234", admin)
-
- expect(response).to have_gitlab_http_status(404)
- expect(json_response['message']).to eq('404 Snippet Not Found')
- end
- end
-end
diff --git a/spec/requests/api/v3/projects_spec.rb b/spec/requests/api/v3/projects_spec.rb
deleted file mode 100644
index 158ddf171bc..00000000000
--- a/spec/requests/api/v3/projects_spec.rb
+++ /dev/null
@@ -1,1495 +0,0 @@
-require 'spec_helper'
-
-describe API::V3::Projects do
- let(:user) { create(:user) }
- let(:user2) { create(:user) }
- let(:user3) { create(:user) }
- let(:admin) { create(:admin) }
- let(:project) { create(:project, creator_id: user.id, namespace: user.namespace) }
- let(:project2) { create(:project, creator_id: user.id, namespace: user.namespace) }
- let(:snippet) { create(:project_snippet, :public, author: user, project: project, title: 'example') }
- let(:project_member) { create(:project_member, :developer, user: user3, project: project) }
- let(:user4) { create(:user) }
- let(:project3) do
- create(:project,
- :private,
- :repository,
- name: 'second_project',
- path: 'second_project',
- creator_id: user.id,
- namespace: user.namespace,
- merge_requests_enabled: false,
- issues_enabled: false, wiki_enabled: false,
- snippets_enabled: false)
- end
- let(:project_member2) do
- create(:project_member,
- user: user4,
- project: project3,
- access_level: ProjectMember::MASTER)
- end
- let(:project4) do
- create(:project,
- name: 'third_project',
- path: 'third_project',
- creator_id: user4.id,
- namespace: user4.namespace)
- end
-
- describe 'GET /projects' do
- before { project }
-
- context 'when unauthenticated' do
- it 'returns authentication error' do
- get v3_api('/projects')
- expect(response).to have_gitlab_http_status(401)
- end
- end
-
- context 'when authenticated as regular user' do
- it 'returns an array of projects' do
- get v3_api('/projects', user)
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.first['name']).to eq(project.name)
- expect(json_response.first['owner']['username']).to eq(user.username)
- end
-
- it 'includes the project labels as the tag_list' do
- get v3_api('/projects', user)
- expect(response.status).to eq 200
- expect(json_response).to be_an Array
- expect(json_response.first.keys).to include('tag_list')
- end
-
- it 'includes open_issues_count' do
- get v3_api('/projects', user)
- expect(response.status).to eq 200
- expect(json_response).to be_an Array
- expect(json_response.first.keys).to include('open_issues_count')
- end
-
- it 'does not include open_issues_count' do
- project.project_feature.update_attribute(:issues_access_level, ProjectFeature::DISABLED)
-
- get v3_api('/projects', user)
- expect(response.status).to eq 200
- expect(json_response).to be_an Array
- expect(json_response.first.keys).not_to include('open_issues_count')
- end
-
- context 'GET /projects?simple=true' do
- it 'returns a simplified version of all the projects' do
- expected_keys = %w(
- id description default_branch tag_list
- ssh_url_to_repo http_url_to_repo web_url readme_url
- name name_with_namespace
- path path_with_namespace
- star_count forks_count
- created_at last_activity_at
- avatar_url
- )
-
- get v3_api('/projects?simple=true', user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.first.keys).to match_array expected_keys
- end
- end
-
- context 'and using search' do
- it 'returns searched project' do
- get v3_api('/projects', user), { search: project.name }
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(1)
- end
- end
-
- context 'and using the visibility filter' do
- it 'filters based on private visibility param' do
- get v3_api('/projects', user), { visibility: 'private' }
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(user.namespace.projects.where(visibility_level: Gitlab::VisibilityLevel::PRIVATE).count)
- end
-
- it 'filters based on internal visibility param' do
- get v3_api('/projects', user), { visibility: 'internal' }
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(user.namespace.projects.where(visibility_level: Gitlab::VisibilityLevel::INTERNAL).count)
- end
-
- it 'filters based on public visibility param' do
- get v3_api('/projects', user), { visibility: 'public' }
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(user.namespace.projects.where(visibility_level: Gitlab::VisibilityLevel::PUBLIC).count)
- end
- end
-
- context 'and using archived' do
- let!(:archived_project) { create(:project, creator_id: user.id, namespace: user.namespace, archived: true) }
-
- it 'returns archived project' do
- get v3_api('/projects?archived=true', user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(1)
- expect(json_response.first['id']).to eq(archived_project.id)
- end
-
- it 'returns non-archived project' do
- get v3_api('/projects?archived=false', user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(1)
- expect(json_response.first['id']).to eq(project.id)
- end
-
- it 'returns all project' do
- get v3_api('/projects', user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(2)
- end
- end
-
- context 'and using sorting' do
- before do
- project2
- project3
- end
-
- it 'returns the correct order when sorted by id' do
- get v3_api('/projects', user), { order_by: 'id', sort: 'desc' }
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.first['id']).to eq(project3.id)
- end
- end
- end
- end
-
- describe 'GET /projects/all' do
- before { project }
-
- context 'when unauthenticated' do
- it 'returns authentication error' do
- get v3_api('/projects/all')
- expect(response).to have_gitlab_http_status(401)
- end
- end
-
- context 'when authenticated as regular user' do
- it 'returns authentication error' do
- get v3_api('/projects/all', user)
- expect(response).to have_gitlab_http_status(403)
- end
- end
-
- context 'when authenticated as admin' do
- it 'returns an array of all projects' do
- get v3_api('/projects/all', admin)
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
-
- expect(json_response).to satisfy do |response|
- response.one? do |entry|
- entry.key?('permissions') &&
- entry['name'] == project.name &&
- entry['owner']['username'] == user.username
- end
- end
- end
-
- it "does not include statistics by default" do
- get v3_api('/projects/all', admin)
-
- expect(response).to have_gitlab_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
- get v3_api('/projects/all', admin), statistics: true
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.first).to include 'statistics'
- end
- end
- end
-
- describe 'GET /projects/owned' do
- before do
- project3
- project4
- end
-
- context 'when unauthenticated' do
- it 'returns authentication error' do
- get v3_api('/projects/owned')
- expect(response).to have_gitlab_http_status(401)
- end
- end
-
- context 'when authenticated as project owner' do
- it 'returns an array of projects the user owns' do
- get v3_api('/projects/owned', user4)
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.first['name']).to eq(project4.name)
- expect(json_response.first['owner']['username']).to eq(user4.username)
- end
-
- it "does not include statistics by default" do
- get v3_api('/projects/owned', user4)
-
- expect(response).to have_gitlab_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 = {
- commit_count: 23,
- storage_size: 702,
- repository_size: 123,
- lfs_objects_size: 234,
- build_artifacts_size: 345
- }
-
- project4.statistics.update!(attributes)
-
- get v3_api('/projects/owned', user4), statistics: true
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.first['statistics']).to eq attributes.stringify_keys
- end
- end
- end
-
- describe 'GET /projects/visible' do
- shared_examples_for 'visible projects response' do
- it 'returns the visible projects' do
- get v3_api('/projects/visible', current_user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.map { |p| p['id'] }).to contain_exactly(*projects.map(&:id))
- end
- end
-
- let!(:public_project) { create(:project, :public) }
- before do
- project
- project2
- project3
- project4
- end
-
- context 'when unauthenticated' do
- it_behaves_like 'visible projects response' do
- let(:current_user) { nil }
- let(:projects) { [public_project] }
- end
- end
-
- context 'when authenticated' do
- it_behaves_like 'visible projects response' do
- let(:current_user) { user }
- let(:projects) { [public_project, project, project2, project3] }
- end
- end
-
- context 'when authenticated as a different user' do
- it_behaves_like 'visible projects response' do
- let(:current_user) { user2 }
- let(:projects) { [public_project] }
- end
- end
- end
-
- describe 'GET /projects/starred' do
- let(:public_project) { create(:project, :public) }
-
- before do
- project_member
- user3.update_attributes(starred_projects: [project, project2, project3, public_project])
- end
-
- it 'returns the starred projects viewable by the user' do
- get v3_api('/projects/starred', user3)
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.map { |project| project['id'] }).to contain_exactly(project.id, public_project.id)
- end
- end
-
- describe 'POST /projects' do
- context 'maximum number of projects reached' do
- it 'does not create new project and respond with 403' do
- allow_any_instance_of(User).to receive(:projects_limit_left).and_return(0)
- expect { post v3_api('/projects', user2), name: 'foo' }
- .to change {Project.count}.by(0)
- expect(response).to have_gitlab_http_status(403)
- end
- end
-
- it 'creates new project without path but with name and returns 201' do
- expect { post v3_api('/projects', user), name: 'Foo Project' }
- .to change { Project.count }.by(1)
- expect(response).to have_gitlab_http_status(201)
-
- project = Project.first
-
- expect(project.name).to eq('Foo Project')
- expect(project.path).to eq('foo-project')
- end
-
- it 'creates new project without name but with path and returns 201' do
- expect { post v3_api('/projects', user), path: 'foo_project' }
- .to change { Project.count }.by(1)
- expect(response).to have_gitlab_http_status(201)
-
- project = Project.first
-
- expect(project.name).to eq('foo_project')
- expect(project.path).to eq('foo_project')
- end
-
- it 'creates new project name and path and returns 201' do
- expect { post v3_api('/projects', user), path: 'foo-Project', name: 'Foo Project' }
- .to change { Project.count }.by(1)
- expect(response).to have_gitlab_http_status(201)
-
- project = Project.first
-
- expect(project.name).to eq('Foo Project')
- expect(project.path).to eq('foo-Project')
- end
-
- it 'creates last project before reaching project limit' do
- allow_any_instance_of(User).to receive(:projects_limit_left).and_return(1)
- post v3_api('/projects', user2), name: 'foo'
- expect(response).to have_gitlab_http_status(201)
- end
-
- it 'does not create new project without name or path and return 400' do
- expect { post v3_api('/projects', user) }.not_to change { Project.count }
- expect(response).to have_gitlab_http_status(400)
- end
-
- it "assigns attributes to project" do
- project = attributes_for(:project, {
- path: 'camelCasePath',
- issues_enabled: false,
- merge_requests_enabled: false,
- wiki_enabled: false,
- only_allow_merge_if_build_succeeds: false,
- request_access_enabled: true,
- only_allow_merge_if_all_discussions_are_resolved: false
- })
-
- post v3_api('/projects', user), project
-
- project.each_pair do |k, v|
- next if %i[storage_version has_external_issue_tracker issues_enabled merge_requests_enabled wiki_enabled].include?(k)
-
- expect(json_response[k.to_s]).to eq(v)
- end
-
- # Check feature permissions attributes
- project = Project.find_by_path(project[:path])
- expect(project.project_feature.issues_access_level).to eq(ProjectFeature::DISABLED)
- expect(project.project_feature.merge_requests_access_level).to eq(ProjectFeature::DISABLED)
- expect(project.project_feature.wiki_access_level).to eq(ProjectFeature::DISABLED)
- end
-
- it 'sets a project as public' do
- project = attributes_for(:project, :public)
- post v3_api('/projects', user), project
- expect(json_response['public']).to be_truthy
- expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::PUBLIC)
- end
-
- it 'sets a project as public using :public' do
- project = attributes_for(:project, { public: true })
- post v3_api('/projects', user), project
- expect(json_response['public']).to be_truthy
- expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::PUBLIC)
- end
-
- it 'sets a project as internal' do
- project = attributes_for(:project, :internal)
- post v3_api('/projects', user), project
- expect(json_response['public']).to be_falsey
- expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::INTERNAL)
- end
-
- it 'sets a project as internal overriding :public' do
- project = attributes_for(:project, :internal, { public: true })
- post v3_api('/projects', user), project
- expect(json_response['public']).to be_falsey
- expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::INTERNAL)
- end
-
- it 'sets a project as private' do
- project = attributes_for(:project, :private)
- post v3_api('/projects', user), project
- expect(json_response['public']).to be_falsey
- expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::PRIVATE)
- end
-
- it 'sets a project as private using :public' do
- project = attributes_for(:project, { public: false })
- post v3_api('/projects', user), project
- expect(json_response['public']).to be_falsey
- expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::PRIVATE)
- end
-
- it 'sets a project as allowing merge even if build fails' do
- project = attributes_for(:project, { only_allow_merge_if_build_succeeds: false })
- post v3_api('/projects', user), project
- expect(json_response['only_allow_merge_if_build_succeeds']).to be_falsey
- end
-
- it 'sets a project as allowing merge only if merge_when_pipeline_succeeds' do
- project = attributes_for(:project, { only_allow_merge_if_build_succeeds: true })
- post v3_api('/projects', user), project
- expect(json_response['only_allow_merge_if_build_succeeds']).to be_truthy
- end
-
- it 'sets a project as allowing merge even if discussions are unresolved' do
- project = attributes_for(:project, { only_allow_merge_if_all_discussions_are_resolved: false })
-
- post v3_api('/projects', user), project
-
- expect(json_response['only_allow_merge_if_all_discussions_are_resolved']).to be_falsey
- end
-
- it 'sets a project as allowing merge if only_allow_merge_if_all_discussions_are_resolved is nil' do
- project = attributes_for(:project, only_allow_merge_if_all_discussions_are_resolved: nil)
-
- post v3_api('/projects', user), project
-
- expect(json_response['only_allow_merge_if_all_discussions_are_resolved']).to be_falsey
- end
-
- it 'sets a project as allowing merge only if all discussions are resolved' do
- project = attributes_for(:project, { only_allow_merge_if_all_discussions_are_resolved: true })
-
- post v3_api('/projects', user), project
-
- expect(json_response['only_allow_merge_if_all_discussions_are_resolved']).to be_truthy
- end
-
- context 'when a visibility level is restricted' do
- before do
- @project = attributes_for(:project, { public: true })
- stub_application_setting(restricted_visibility_levels: [Gitlab::VisibilityLevel::PUBLIC])
- end
-
- it 'does not allow a non-admin to use a restricted visibility level' do
- post v3_api('/projects', user), @project
-
- expect(response).to have_gitlab_http_status(400)
- expect(json_response['message']['visibility_level'].first).to(
- match('restricted by your GitLab administrator')
- )
- end
-
- it 'allows an admin to override restricted visibility settings' do
- post v3_api('/projects', admin), @project
- expect(json_response['public']).to be_truthy
- expect(json_response['visibility_level']).to(
- eq(Gitlab::VisibilityLevel::PUBLIC)
- )
- end
- end
- end
-
- describe 'POST /projects/user/:id' do
- before { project }
- before { admin }
-
- it 'should create new project without path and return 201' do
- expect { post v3_api("/projects/user/#{user.id}", admin), name: 'foo' }.to change {Project.count}.by(1)
- expect(response).to have_gitlab_http_status(201)
- end
-
- it 'responds with 400 on failure and not project' do
- expect { post v3_api("/projects/user/#{user.id}", admin) }
- .not_to change { Project.count }
-
- expect(response).to have_gitlab_http_status(400)
- expect(json_response['error']).to eq('name is missing')
- end
-
- it 'assigns attributes to project' do
- project = attributes_for(:project, {
- issues_enabled: false,
- merge_requests_enabled: false,
- wiki_enabled: false,
- request_access_enabled: true
- })
-
- post v3_api("/projects/user/#{user.id}", admin), project
-
- expect(response).to have_gitlab_http_status(201)
- project.each_pair do |k, v|
- next if %i[storage_version has_external_issue_tracker path].include?(k)
-
- expect(json_response[k.to_s]).to eq(v)
- end
- end
-
- it 'sets a project as public' do
- project = attributes_for(:project, :public)
- post v3_api("/projects/user/#{user.id}", admin), project
-
- expect(response).to have_gitlab_http_status(201)
- expect(json_response['public']).to be_truthy
- expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::PUBLIC)
- end
-
- it 'sets a project as public using :public' do
- project = attributes_for(:project, { public: true })
- post v3_api("/projects/user/#{user.id}", admin), project
-
- expect(response).to have_gitlab_http_status(201)
- expect(json_response['public']).to be_truthy
- expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::PUBLIC)
- end
-
- it 'sets a project as internal' do
- project = attributes_for(:project, :internal)
- post v3_api("/projects/user/#{user.id}", admin), project
-
- expect(response).to have_gitlab_http_status(201)
- expect(json_response['public']).to be_falsey
- expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::INTERNAL)
- end
-
- it 'sets a project as internal overriding :public' do
- project = attributes_for(:project, :internal, { public: true })
- post v3_api("/projects/user/#{user.id}", admin), project
- expect(response).to have_gitlab_http_status(201)
- expect(json_response['public']).to be_falsey
- expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::INTERNAL)
- end
-
- it 'sets a project as private' do
- project = attributes_for(:project, :private)
- post v3_api("/projects/user/#{user.id}", admin), project
- expect(json_response['public']).to be_falsey
- expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::PRIVATE)
- end
-
- it 'sets a project as private using :public' do
- project = attributes_for(:project, { public: false })
- post v3_api("/projects/user/#{user.id}", admin), project
- expect(json_response['public']).to be_falsey
- expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::PRIVATE)
- end
-
- it 'sets a project as allowing merge even if build fails' do
- project = attributes_for(:project, { only_allow_merge_if_build_succeeds: false })
- post v3_api("/projects/user/#{user.id}", admin), project
- expect(json_response['only_allow_merge_if_build_succeeds']).to be_falsey
- end
-
- it 'sets a project as allowing merge only if merge_when_pipeline_succeeds' do
- project = attributes_for(:project, { only_allow_merge_if_build_succeeds: true })
- post v3_api("/projects/user/#{user.id}", admin), project
- expect(json_response['only_allow_merge_if_build_succeeds']).to be_truthy
- end
-
- it 'sets a project as allowing merge even if discussions are unresolved' do
- project = attributes_for(:project, { only_allow_merge_if_all_discussions_are_resolved: false })
-
- post v3_api("/projects/user/#{user.id}", admin), project
-
- expect(json_response['only_allow_merge_if_all_discussions_are_resolved']).to be_falsey
- end
-
- it 'sets a project as allowing merge only if all discussions are resolved' do
- project = attributes_for(:project, { only_allow_merge_if_all_discussions_are_resolved: true })
-
- post v3_api("/projects/user/#{user.id}", admin), project
-
- expect(json_response['only_allow_merge_if_all_discussions_are_resolved']).to be_truthy
- end
- end
-
- describe "POST /projects/:id/uploads" do
- before { project }
-
- it "uploads the file and returns its info" do
- post v3_api("/projects/#{project.id}/uploads", user), file: fixture_file_upload(Rails.root + "spec/fixtures/dk.png", "image/png")
-
- expect(response).to have_gitlab_http_status(201)
- expect(json_response['alt']).to eq("dk")
- expect(json_response['url']).to start_with("/uploads/")
- expect(json_response['url']).to end_with("/dk.png")
- end
- end
-
- describe 'GET /projects/:id' do
- context 'when unauthenticated' do
- it 'returns the public projects' do
- public_project = create(:project, :public)
-
- get v3_api("/projects/#{public_project.id}")
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['id']).to eq(public_project.id)
- expect(json_response['description']).to eq(public_project.description)
- expect(json_response['default_branch']).to eq(public_project.default_branch)
- expect(json_response.keys).not_to include('permissions')
- end
- end
-
- context 'when authenticated' do
- before do
- project
- end
-
- it 'returns a project by id' do
- group = create(:group)
- link = create(:project_group_link, project: project, group: group)
-
- get v3_api("/projects/#{project.id}", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['id']).to eq(project.id)
- 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['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
- expect(json_response['owner']).to be_a Hash
- expect(json_response['owner']).to be_a Hash
- expect(json_response['name']).to eq(project.name)
- expect(json_response['path']).to be_present
- expect(json_response['issues_enabled']).to be_present
- expect(json_response['merge_requests_enabled']).to be_present
- expect(json_response['wiki_enabled']).to be_present
- expect(json_response['builds_enabled']).to be_present
- expect(json_response['snippets_enabled']).to be_present
- expect(json_response['resolve_outdated_diff_discussions']).to eq(project.resolve_outdated_diff_discussions)
- expect(json_response['container_registry_enabled']).to be_present
- expect(json_response['created_at']).to be_present
- expect(json_response['last_activity_at']).to be_present
- expect(json_response['shared_runners_enabled']).to be_present
- expect(json_response['creator_id']).to be_present
- expect(json_response['namespace']).to be_present
- expect(json_response['avatar_url']).to be_nil
- expect(json_response['star_count']).to be_present
- expect(json_response['forks_count']).to be_present
- expect(json_response['public_builds']).to be_present
- expect(json_response['shared_with_groups']).to be_an Array
- expect(json_response['shared_with_groups'].length).to eq(1)
- expect(json_response['shared_with_groups'][0]['group_id']).to eq(group.id)
- expect(json_response['shared_with_groups'][0]['group_name']).to eq(group.name)
- expect(json_response['shared_with_groups'][0]['group_access_level']).to eq(link.group_access)
- expect(json_response['only_allow_merge_if_build_succeeds']).to eq(project.only_allow_merge_if_pipeline_succeeds)
- expect(json_response['only_allow_merge_if_all_discussions_are_resolved']).to eq(project.only_allow_merge_if_all_discussions_are_resolved)
- end
-
- it 'returns a project by path name' do
- get v3_api("/projects/#{project.id}", user)
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['name']).to eq(project.name)
- end
-
- it 'returns a 404 error if not found' do
- get v3_api('/projects/42', user)
- expect(response).to have_gitlab_http_status(404)
- expect(json_response['message']).to eq('404 Project Not Found')
- end
-
- it 'returns a 404 error if user is not a member' do
- other_user = create(:user)
- get v3_api("/projects/#{project.id}", other_user)
- expect(response).to have_gitlab_http_status(404)
- end
-
- it 'handles users with dots' do
- dot_user = create(:user, username: 'dot.user')
- project = create(:project, creator_id: dot_user.id, namespace: dot_user.namespace)
-
- get v3_api("/projects/#{CGI.escape(project.full_path)}", dot_user)
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['name']).to eq(project.name)
- end
-
- it 'exposes namespace fields' do
- get v3_api("/projects/#{project.id}", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['namespace']).to eq({
- 'id' => user.namespace.id,
- 'name' => user.namespace.name,
- 'path' => user.namespace.path,
- 'kind' => user.namespace.kind,
- 'full_path' => user.namespace.full_path,
- 'parent_id' => nil
- })
- end
-
- describe 'permissions' do
- context 'all projects' do
- before { project.add_master(user) }
-
- it 'contains permission information' do
- get v3_api("/projects", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response.first['permissions']['project_access']['access_level'])
- .to eq(Gitlab::Access::MASTER)
- expect(json_response.first['permissions']['group_access']).to be_nil
- end
- end
-
- context 'personal project' do
- it 'sets project access and returns 200' do
- project.add_master(user)
- get v3_api("/projects/#{project.id}", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['permissions']['project_access']['access_level'])
- .to eq(Gitlab::Access::MASTER)
- expect(json_response['permissions']['group_access']).to be_nil
- end
- end
-
- context 'group project' do
- let(:project2) { create(:project, group: create(:group)) }
-
- before { project2.group.add_owner(user) }
-
- it 'sets the owner and return 200' do
- get v3_api("/projects/#{project2.id}", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['permissions']['project_access']).to be_nil
- expect(json_response['permissions']['group_access']['access_level'])
- .to eq(Gitlab::Access::OWNER)
- end
- end
- end
- end
- end
-
- describe 'GET /projects/:id/events' do
- shared_examples_for 'project events response' do
- it 'returns the project events' do
- member = create(:user)
- create(:project_member, :developer, user: member, project: project)
- note = create(:note_on_issue, note: 'What an awesome day!', project: project)
- EventCreateService.new.leave_note(note, note.author)
-
- get v3_api("/projects/#{project.id}/events", current_user)
-
- expect(response).to have_gitlab_http_status(200)
-
- first_event = json_response.first
-
- expect(first_event['action_name']).to eq('commented on')
- expect(first_event['note']['body']).to eq('What an awesome day!')
-
- last_event = json_response.last
-
- expect(last_event['action_name']).to eq('joined')
- expect(last_event['project_id'].to_i).to eq(project.id)
- expect(last_event['author_username']).to eq(member.username)
- expect(last_event['author']['name']).to eq(member.name)
- end
- end
-
- context 'when unauthenticated' do
- it_behaves_like 'project events response' do
- let(:project) { create(:project, :public) }
- let(:current_user) { nil }
- end
- end
-
- context 'when authenticated' do
- context 'valid request' do
- it_behaves_like 'project events response' do
- let(:current_user) { user }
- end
- end
-
- it 'returns a 404 error if not found' do
- get v3_api('/projects/42/events', user)
-
- expect(response).to have_gitlab_http_status(404)
- expect(json_response['message']).to eq('404 Project Not Found')
- end
-
- it 'returns a 404 error if user is not a member' do
- other_user = create(:user)
-
- get v3_api("/projects/#{project.id}/events", other_user)
-
- expect(response).to have_gitlab_http_status(404)
- end
- end
- end
-
- describe 'GET /projects/:id/users' do
- shared_examples_for 'project users response' do
- it 'returns the project users' do
- member = project.owner
-
- get v3_api("/projects/#{project.id}/users", current_user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.size).to eq(1)
-
- first_user = json_response.first
-
- expect(first_user['username']).to eq(member.username)
- expect(first_user['name']).to eq(member.name)
- expect(first_user.keys).to contain_exactly(*%w[name username id state avatar_url web_url])
- end
- end
-
- context 'when unauthenticated' do
- it_behaves_like 'project users response' do
- let(:project) { create(:project, :public) }
- let(:current_user) { nil }
- end
- end
-
- context 'when authenticated' do
- context 'valid request' do
- it_behaves_like 'project users response' do
- let(:current_user) { user }
- end
- end
-
- it 'returns a 404 error if not found' do
- get v3_api('/projects/42/users', user)
-
- expect(response).to have_gitlab_http_status(404)
- expect(json_response['message']).to eq('404 Project Not Found')
- end
-
- it 'returns a 404 error if user is not a member' do
- other_user = create(:user)
-
- get v3_api("/projects/#{project.id}/users", other_user)
-
- expect(response).to have_gitlab_http_status(404)
- end
- end
- end
-
- describe 'GET /projects/:id/snippets' do
- before { snippet }
-
- it 'returns an array of project snippets' do
- get v3_api("/projects/#{project.id}/snippets", user)
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.first['title']).to eq(snippet.title)
- end
- end
-
- describe 'GET /projects/:id/snippets/:snippet_id' do
- it 'returns a project snippet' do
- get v3_api("/projects/#{project.id}/snippets/#{snippet.id}", user)
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['title']).to eq(snippet.title)
- end
-
- it 'returns a 404 error if snippet id not found' do
- get v3_api("/projects/#{project.id}/snippets/1234", user)
- expect(response).to have_gitlab_http_status(404)
- end
- end
-
- describe 'POST /projects/:id/snippets' do
- it 'creates a new project snippet' do
- post v3_api("/projects/#{project.id}/snippets", user),
- title: 'v3_api test', file_name: 'sample.rb', code: 'test',
- visibility_level: '0'
- expect(response).to have_gitlab_http_status(201)
- expect(json_response['title']).to eq('v3_api test')
- end
-
- it 'returns a 400 error if invalid snippet is given' do
- post v3_api("/projects/#{project.id}/snippets", user)
- expect(status).to eq(400)
- end
- end
-
- describe 'PUT /projects/:id/snippets/:snippet_id' do
- it 'updates an existing project snippet' do
- put v3_api("/projects/#{project.id}/snippets/#{snippet.id}", user),
- code: 'updated code'
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['title']).to eq('example')
- expect(snippet.reload.content).to eq('updated code')
- end
-
- it 'updates an existing project snippet with new title' do
- put v3_api("/projects/#{project.id}/snippets/#{snippet.id}", user),
- title: 'other v3_api test'
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['title']).to eq('other v3_api test')
- end
- end
-
- describe 'DELETE /projects/:id/snippets/:snippet_id' do
- before { snippet }
-
- it 'deletes existing project snippet' do
- expect do
- delete v3_api("/projects/#{project.id}/snippets/#{snippet.id}", user)
- end.to change { Snippet.count }.by(-1)
- expect(response).to have_gitlab_http_status(200)
- end
-
- it 'returns 404 when deleting unknown snippet id' do
- delete v3_api("/projects/#{project.id}/snippets/1234", user)
- expect(response).to have_gitlab_http_status(404)
- end
- end
-
- describe 'GET /projects/:id/snippets/:snippet_id/raw' do
- it 'gets a raw project snippet' do
- get v3_api("/projects/#{project.id}/snippets/#{snippet.id}/raw", user)
- expect(response).to have_gitlab_http_status(200)
- end
-
- it 'returns a 404 error if raw project snippet not found' do
- get v3_api("/projects/#{project.id}/snippets/5555/raw", user)
- expect(response).to have_gitlab_http_status(404)
- end
- end
-
- describe 'fork management' do
- let(:project_fork_target) { create(:project) }
- let(:project_fork_source) { create(:project, :public) }
-
- describe 'POST /projects/:id/fork/:forked_from_id' do
- let(:new_project_fork_source) { create(:project, :public) }
-
- it "is not available for non admin users" do
- post v3_api("/projects/#{project_fork_target.id}/fork/#{project_fork_source.id}", user)
- expect(response).to have_gitlab_http_status(403)
- end
-
- it 'allows project to be forked from an existing project' do
- expect(project_fork_target.forked?).not_to be_truthy
- post v3_api("/projects/#{project_fork_target.id}/fork/#{project_fork_source.id}", admin)
- expect(response).to have_gitlab_http_status(201)
- project_fork_target.reload
- expect(project_fork_target.forked_from_project.id).to eq(project_fork_source.id)
- expect(project_fork_target.forked_project_link).not_to be_nil
- expect(project_fork_target.forked?).to be_truthy
- end
-
- it 'refreshes the forks count cachce' do
- expect(project_fork_source.forks_count).to be_zero
-
- post v3_api("/projects/#{project_fork_target.id}/fork/#{project_fork_source.id}", admin)
-
- expect(project_fork_source.forks_count).to eq(1)
- end
-
- it 'fails if forked_from project which does not exist' do
- post v3_api("/projects/#{project_fork_target.id}/fork/9999", admin)
- expect(response).to have_gitlab_http_status(404)
- end
-
- it 'fails with 409 if already forked' do
- post v3_api("/projects/#{project_fork_target.id}/fork/#{project_fork_source.id}", admin)
- project_fork_target.reload
- expect(project_fork_target.forked_from_project.id).to eq(project_fork_source.id)
- post v3_api("/projects/#{project_fork_target.id}/fork/#{new_project_fork_source.id}", admin)
- expect(response).to have_gitlab_http_status(409)
- project_fork_target.reload
- expect(project_fork_target.forked_from_project.id).to eq(project_fork_source.id)
- expect(project_fork_target.forked?).to be_truthy
- end
- end
-
- describe 'DELETE /projects/:id/fork' do
- it "is not visible to users outside group" do
- delete v3_api("/projects/#{project_fork_target.id}/fork", user)
- expect(response).to have_gitlab_http_status(404)
- end
-
- context 'when users belong to project group' do
- let(:project_fork_target) { create(:project, group: create(:group)) }
-
- before do
- project_fork_target.group.add_owner user
- project_fork_target.group.add_developer user2
- end
-
- it 'is forbidden to non-owner users' do
- delete v3_api("/projects/#{project_fork_target.id}/fork", user2)
- expect(response).to have_gitlab_http_status(403)
- end
-
- it 'makes forked project unforked' do
- post v3_api("/projects/#{project_fork_target.id}/fork/#{project_fork_source.id}", admin)
- project_fork_target.reload
- expect(project_fork_target.forked_from_project).not_to be_nil
- expect(project_fork_target.forked?).to be_truthy
- delete v3_api("/projects/#{project_fork_target.id}/fork", admin)
- expect(response).to have_gitlab_http_status(200)
- project_fork_target.reload
- expect(project_fork_target.forked_from_project).to be_nil
- expect(project_fork_target.forked?).not_to be_truthy
- end
-
- it 'is idempotent if not forked' do
- expect(project_fork_target.forked_from_project).to be_nil
- delete v3_api("/projects/#{project_fork_target.id}/fork", admin)
- expect(response).to have_gitlab_http_status(304)
- expect(project_fork_target.reload.forked_from_project).to be_nil
- end
- end
- end
- end
-
- describe "POST /projects/:id/share" do
- let(:group) { create(:group) }
-
- it "shares project with group" do
- expires_at = 10.days.from_now.to_date
-
- expect do
- post v3_api("/projects/#{project.id}/share", user), group_id: group.id, group_access: Gitlab::Access::DEVELOPER, expires_at: expires_at
- end.to change { ProjectGroupLink.count }.by(1)
-
- expect(response).to have_gitlab_http_status(201)
- expect(json_response['group_id']).to eq(group.id)
- expect(json_response['group_access']).to eq(Gitlab::Access::DEVELOPER)
- expect(json_response['expires_at']).to eq(expires_at.to_s)
- end
-
- it "returns a 400 error when group id is not given" do
- post v3_api("/projects/#{project.id}/share", user), group_access: Gitlab::Access::DEVELOPER
- expect(response).to have_gitlab_http_status(400)
- end
-
- it "returns a 400 error when access level is not given" do
- post v3_api("/projects/#{project.id}/share", user), group_id: group.id
- expect(response).to have_gitlab_http_status(400)
- end
-
- it "returns a 400 error when sharing is disabled" do
- project.namespace.update(share_with_group_lock: true)
- post v3_api("/projects/#{project.id}/share", user), group_id: group.id, group_access: Gitlab::Access::DEVELOPER
- expect(response).to have_gitlab_http_status(400)
- end
-
- it 'returns a 404 error when user cannot read group' do
- private_group = create(:group, :private)
-
- post v3_api("/projects/#{project.id}/share", user), group_id: private_group.id, group_access: Gitlab::Access::DEVELOPER
-
- expect(response).to have_gitlab_http_status(404)
- end
-
- it 'returns a 404 error when group does not exist' do
- post v3_api("/projects/#{project.id}/share", user), group_id: 1234, group_access: Gitlab::Access::DEVELOPER
-
- expect(response).to have_gitlab_http_status(404)
- end
-
- it "returns a 400 error when wrong params passed" do
- post v3_api("/projects/#{project.id}/share", user), group_id: group.id, group_access: 1234
-
- expect(response).to have_gitlab_http_status(400)
- expect(json_response['error']).to eq 'group_access does not have a valid value'
- end
- end
-
- describe 'DELETE /projects/:id/share/:group_id' do
- it 'returns 204 when deleting a group share' do
- group = create(:group, :public)
- create(:project_group_link, group: group, project: project)
-
- delete v3_api("/projects/#{project.id}/share/#{group.id}", user)
-
- expect(response).to have_gitlab_http_status(204)
- expect(project.project_group_links).to be_empty
- end
-
- it 'returns a 400 when group id is not an integer' do
- delete v3_api("/projects/#{project.id}/share/foo", user)
-
- expect(response).to have_gitlab_http_status(400)
- end
-
- it 'returns a 404 error when group link does not exist' do
- delete v3_api("/projects/#{project.id}/share/1234", user)
-
- expect(response).to have_gitlab_http_status(404)
- end
-
- it 'returns a 404 error when project does not exist' do
- delete v3_api("/projects/123/share/1234", user)
-
- expect(response).to have_gitlab_http_status(404)
- end
- end
-
- describe 'GET /projects/search/:query' do
- let!(:query) { 'query'}
- let!(:search) { create(:project, name: query, creator_id: user.id, namespace: user.namespace) }
- let!(:pre) { create(:project, name: "pre_#{query}", creator_id: user.id, namespace: user.namespace) }
- let!(:post) { create(:project, name: "#{query}_post", creator_id: user.id, namespace: user.namespace) }
- let!(:pre_post) { create(:project, name: "pre_#{query}_post", creator_id: user.id, namespace: user.namespace) }
- let!(:unfound) { create(:project, name: 'unfound', creator_id: user.id, namespace: user.namespace) }
- let!(:internal) { create(:project, :internal, name: "internal #{query}") }
- let!(:unfound_internal) { create(:project, :internal, name: 'unfound internal') }
- let!(:public) { create(:project, :public, name: "public #{query}") }
- let!(:unfound_public) { create(:project, :public, name: 'unfound public') }
- let!(:one_dot_two) { create(:project, :public, name: "one.dot.two") }
-
- shared_examples_for 'project search response' do |args = {}|
- it 'returns project search responses' do
- get v3_api("/projects/search/#{args[:query]}", current_user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.size).to eq(args[:results])
- json_response.each { |project| expect(project['name']).to match(args[:match_regex] || /.*#{args[:query]}.*/) }
- end
- end
-
- context 'when unauthenticated' do
- it_behaves_like 'project search response', query: 'query', results: 1 do
- let(:current_user) { nil }
- end
- end
-
- context 'when authenticated' do
- it_behaves_like 'project search response', query: 'query', results: 6 do
- let(:current_user) { user }
- end
- it_behaves_like 'project search response', query: 'one.dot.two', results: 1 do
- let(:current_user) { user }
- end
- end
-
- context 'when authenticated as a different user' do
- it_behaves_like 'project search response', query: 'query', results: 2, match_regex: /(internal|public) query/ do
- let(:current_user) { user2 }
- end
- end
- end
-
- describe 'PUT /projects/:id' do
- before { project }
- before { user }
- before { user3 }
- before { user4 }
- before { project3 }
- before { project4 }
- before { project_member2 }
- before { project_member }
-
- context 'when unauthenticated' do
- it 'returns authentication error' do
- project_param = { name: 'bar' }
- put v3_api("/projects/#{project.id}"), project_param
- expect(response).to have_gitlab_http_status(401)
- end
- end
-
- context 'when authenticated as project owner' do
- it 'updates name' do
- project_param = { name: 'bar' }
- put v3_api("/projects/#{project.id}", user), project_param
- expect(response).to have_gitlab_http_status(200)
- project_param.each_pair do |k, v|
- expect(json_response[k.to_s]).to eq(v)
- end
- end
-
- it 'updates visibility_level' do
- project_param = { visibility_level: 20 }
- put v3_api("/projects/#{project3.id}", user), project_param
- expect(response).to have_gitlab_http_status(200)
- project_param.each_pair do |k, v|
- expect(json_response[k.to_s]).to eq(v)
- end
- end
-
- it 'updates visibility_level from public to private' do
- project3.update_attributes({ visibility_level: Gitlab::VisibilityLevel::PUBLIC })
- project_param = { public: false }
- put v3_api("/projects/#{project3.id}", user), project_param
- expect(response).to have_gitlab_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)
- end
-
- it 'does not update name to existing name' do
- project_param = { name: project3.name }
- put v3_api("/projects/#{project.id}", user), project_param
- expect(response).to have_gitlab_http_status(400)
- expect(json_response['message']['name']).to eq(['has already been taken'])
- end
-
- it 'updates request_access_enabled' do
- project_param = { request_access_enabled: false }
-
- put v3_api("/projects/#{project.id}", user), project_param
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['request_access_enabled']).to eq(false)
- end
-
- it 'updates path & name to existing path & name in different namespace' do
- project_param = { path: project4.path, name: project4.name }
- put v3_api("/projects/#{project3.id}", user), project_param
- expect(response).to have_gitlab_http_status(200)
- project_param.each_pair do |k, v|
- expect(json_response[k.to_s]).to eq(v)
- end
- end
- end
-
- context 'when authenticated as project master' do
- it 'updates path' do
- project_param = { path: 'bar' }
- put v3_api("/projects/#{project3.id}", user4), project_param
- expect(response).to have_gitlab_http_status(200)
- project_param.each_pair do |k, v|
- expect(json_response[k.to_s]).to eq(v)
- end
- end
-
- it 'updates other attributes' do
- project_param = { issues_enabled: true,
- wiki_enabled: true,
- snippets_enabled: true,
- merge_requests_enabled: true,
- description: 'new description' }
-
- put v3_api("/projects/#{project3.id}", user4), project_param
- expect(response).to have_gitlab_http_status(200)
- project_param.each_pair do |k, v|
- expect(json_response[k.to_s]).to eq(v)
- end
- end
-
- it 'does not update path to existing path' do
- project_param = { path: project.path }
- put v3_api("/projects/#{project3.id}", user4), project_param
- expect(response).to have_gitlab_http_status(400)
- expect(json_response['message']['path']).to eq(['has already been taken'])
- end
-
- it 'does not update name' do
- project_param = { name: 'bar' }
- put v3_api("/projects/#{project3.id}", user4), project_param
- expect(response).to have_gitlab_http_status(403)
- end
-
- it 'does not update visibility_level' do
- project_param = { visibility_level: 20 }
- put v3_api("/projects/#{project3.id}", user4), project_param
- expect(response).to have_gitlab_http_status(403)
- end
- end
-
- context 'when authenticated as project developer' do
- it 'does not update other attributes' do
- project_param = { path: 'bar',
- issues_enabled: true,
- wiki_enabled: true,
- snippets_enabled: true,
- merge_requests_enabled: true,
- description: 'new description',
- request_access_enabled: true }
- put v3_api("/projects/#{project.id}", user3), project_param
- expect(response).to have_gitlab_http_status(403)
- end
- end
- end
-
- describe 'POST /projects/:id/archive' do
- context 'on an unarchived project' do
- it 'archives the project' do
- post v3_api("/projects/#{project.id}/archive", user)
-
- expect(response).to have_gitlab_http_status(201)
- expect(json_response['archived']).to be_truthy
- end
- end
-
- context 'on an archived project' do
- before do
- project.archive!
- end
-
- it 'remains archived' do
- post v3_api("/projects/#{project.id}/archive", user)
-
- expect(response).to have_gitlab_http_status(201)
- expect(json_response['archived']).to be_truthy
- end
- end
-
- context 'user without archiving rights to the project' do
- before do
- project.add_developer(user3)
- end
-
- it 'rejects the action' do
- post v3_api("/projects/#{project.id}/archive", user3)
-
- expect(response).to have_gitlab_http_status(403)
- end
- end
- end
-
- describe 'POST /projects/:id/unarchive' do
- context 'on an unarchived project' do
- it 'remains unarchived' do
- post v3_api("/projects/#{project.id}/unarchive", user)
-
- expect(response).to have_gitlab_http_status(201)
- expect(json_response['archived']).to be_falsey
- end
- end
-
- context 'on an archived project' do
- before do
- project.archive!
- end
-
- it 'unarchives the project' do
- post v3_api("/projects/#{project.id}/unarchive", user)
-
- expect(response).to have_gitlab_http_status(201)
- expect(json_response['archived']).to be_falsey
- end
- end
-
- context 'user without archiving rights to the project' do
- before do
- project.add_developer(user3)
- end
-
- it 'rejects the action' do
- post v3_api("/projects/#{project.id}/unarchive", user3)
-
- expect(response).to have_gitlab_http_status(403)
- end
- end
- end
-
- describe 'POST /projects/:id/star' do
- context 'on an unstarred project' do
- it 'stars the project' do
- expect { post v3_api("/projects/#{project.id}/star", user) }.to change { project.reload.star_count }.by(1)
-
- expect(response).to have_gitlab_http_status(201)
- expect(json_response['star_count']).to eq(1)
- end
- end
-
- context 'on a starred project' do
- before do
- user.toggle_star(project)
- project.reload
- end
-
- it 'does not modify the star count' do
- expect { post v3_api("/projects/#{project.id}/star", user) }.not_to change { project.reload.star_count }
-
- expect(response).to have_gitlab_http_status(304)
- end
- end
- end
-
- describe 'DELETE /projects/:id/star' do
- context 'on a starred project' do
- before do
- user.toggle_star(project)
- project.reload
- end
-
- it 'unstars the project' do
- expect { delete v3_api("/projects/#{project.id}/star", user) }.to change { project.reload.star_count }.by(-1)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['star_count']).to eq(0)
- end
- end
-
- context 'on an unstarred project' do
- it 'does not modify the star count' do
- expect { delete v3_api("/projects/#{project.id}/star", user) }.not_to change { project.reload.star_count }
-
- expect(response).to have_gitlab_http_status(304)
- end
- end
- end
-
- describe 'DELETE /projects/:id' do
- context 'when authenticated as user' do
- it 'removes project' do
- delete v3_api("/projects/#{project.id}", user)
- expect(response).to have_gitlab_http_status(200)
- end
-
- it 'does not remove a project if not an owner' do
- user3 = create(:user)
- project.add_developer(user3)
- delete v3_api("/projects/#{project.id}", user3)
- expect(response).to have_gitlab_http_status(403)
- end
-
- it 'does not remove a non existing project' do
- delete v3_api('/projects/1328', user)
- expect(response).to have_gitlab_http_status(404)
- end
-
- it 'does not remove a project not attached to user' do
- delete v3_api("/projects/#{project.id}", user2)
- expect(response).to have_gitlab_http_status(404)
- end
- end
-
- context 'when authenticated as admin' do
- it 'removes any existing project' do
- delete v3_api("/projects/#{project.id}", admin)
- expect(response).to have_gitlab_http_status(200)
- end
-
- it 'does not remove a non existing project' do
- delete v3_api('/projects/1328', admin)
- expect(response).to have_gitlab_http_status(404)
- end
- end
- end
-end
diff --git a/spec/requests/api/v3/repositories_spec.rb b/spec/requests/api/v3/repositories_spec.rb
deleted file mode 100644
index 0167eb2c4f6..00000000000
--- a/spec/requests/api/v3/repositories_spec.rb
+++ /dev/null
@@ -1,366 +0,0 @@
-require 'spec_helper'
-require 'mime/types'
-
-describe API::V3::Repositories do
- include RepoHelpers
- include WorkhorseHelpers
-
- let(:user) { create(:user) }
- let(:guest) { create(:user).tap { |u| create(:project_member, :guest, user: u, project: project) } }
- let!(:project) { create(:project, :repository, creator: user) }
- let!(:master) { create(:project_member, :master, user: user, project: project) }
-
- describe "GET /projects/:id/repository/tree" do
- let(:route) { "/projects/#{project.id}/repository/tree" }
-
- shared_examples_for 'repository tree' do
- it 'returns the repository tree' do
- get v3_api(route, current_user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
-
- first_commit = json_response.first
- expect(first_commit['name']).to eq('bar')
- expect(first_commit['type']).to eq('tree')
- expect(first_commit['mode']).to eq('040000')
- end
-
- context 'when ref does not exist' do
- it_behaves_like '404 response' do
- let(:request) { get v3_api("#{route}?ref_name=foo", current_user) }
- let(:message) { '404 Tree Not Found' }
- end
- end
-
- context 'when repository is disabled' do
- include_context 'disabled repository'
-
- it_behaves_like '403 response' do
- let(:request) { get v3_api(route, current_user) }
- end
- end
-
- context 'with recursive=1' do
- it 'returns recursive project paths tree' do
- get v3_api("#{route}?recursive=1", current_user)
-
- expect(response.status).to eq(200)
- expect(json_response).to be_an Array
- expect(json_response[4]['name']).to eq('html')
- expect(json_response[4]['path']).to eq('files/html')
- expect(json_response[4]['type']).to eq('tree')
- expect(json_response[4]['mode']).to eq('040000')
- end
-
- context 'when repository is disabled' do
- include_context 'disabled repository'
-
- it_behaves_like '403 response' do
- let(:request) { get v3_api(route, current_user) }
- end
- end
-
- context 'when ref does not exist' do
- it_behaves_like '404 response' do
- let(:request) { get v3_api("#{route}?recursive=1&ref_name=foo", current_user) }
- let(:message) { '404 Tree Not Found' }
- end
- end
- end
- end
-
- context 'when unauthenticated', 'and project is public' do
- it_behaves_like 'repository tree' do
- let(:project) { create(:project, :public, :repository) }
- let(:current_user) { nil }
- end
- end
-
- context 'when unauthenticated', 'and project is private' do
- it_behaves_like '404 response' do
- let(:request) { get v3_api(route) }
- let(:message) { '404 Project Not Found' }
- end
- end
-
- context 'when authenticated', 'as a developer' do
- it_behaves_like 'repository tree' do
- let(:current_user) { user }
- end
- end
-
- context 'when authenticated', 'as a guest' do
- it_behaves_like '403 response' do
- let(:request) { get v3_api(route, guest) }
- end
- end
- end
-
- [
- ['blobs/:sha', 'blobs/master'],
- ['blobs/:sha', 'blobs/v1.1.0'],
- ['commits/:sha/blob', 'commits/master/blob']
- ].each do |desc_path, example_path|
- describe "GET /projects/:id/repository/#{desc_path}" do
- let(:route) { "/projects/#{project.id}/repository/#{example_path}?filepath=README.md" }
- shared_examples_for 'repository blob' do
- it 'returns the repository blob' do
- get v3_api(route, current_user)
- expect(response).to have_gitlab_http_status(200)
- end
- context 'when sha does not exist' do
- it_behaves_like '404 response' do
- let(:request) { get v3_api("/projects/#{project.id}/repository/#{desc_path.sub(':sha', 'invalid_branch_name')}?filepath=README.md", current_user) }
- let(:message) { '404 Commit Not Found' }
- end
- end
- context 'when filepath does not exist' do
- it_behaves_like '404 response' do
- let(:request) { get v3_api(route.sub('README.md', 'README.invalid'), current_user) }
- let(:message) { '404 File Not Found' }
- end
- end
- context 'when no filepath is given' do
- it_behaves_like '400 response' do
- let(:request) { get v3_api(route.sub('?filepath=README.md', ''), current_user) }
- end
- end
- context 'when repository is disabled' do
- include_context 'disabled repository'
- it_behaves_like '403 response' do
- let(:request) { get v3_api(route, current_user) }
- end
- end
- end
- context 'when unauthenticated', 'and project is public' do
- it_behaves_like 'repository blob' do
- let(:project) { create(:project, :public, :repository) }
- let(:current_user) { nil }
- end
- end
- context 'when unauthenticated', 'and project is private' do
- it_behaves_like '404 response' do
- let(:request) { get v3_api(route) }
- let(:message) { '404 Project Not Found' }
- end
- end
- context 'when authenticated', 'as a developer' do
- it_behaves_like 'repository blob' do
- let(:current_user) { user }
- end
- end
- context 'when authenticated', 'as a guest' do
- it_behaves_like '403 response' do
- let(:request) { get v3_api(route, guest) }
- end
- end
- end
- end
- describe "GET /projects/:id/repository/raw_blobs/:sha" do
- let(:route) { "/projects/#{project.id}/repository/raw_blobs/#{sample_blob.oid}" }
- shared_examples_for 'repository raw blob' do
- it 'returns the repository raw blob' do
- get v3_api(route, current_user)
- expect(response).to have_gitlab_http_status(200)
- end
- context 'when sha does not exist' do
- it_behaves_like '404 response' do
- let(:request) { get v3_api(route.sub(sample_blob.oid, '123456'), current_user) }
- let(:message) { '404 Blob Not Found' }
- end
- end
- context 'when repository is disabled' do
- include_context 'disabled repository'
- it_behaves_like '403 response' do
- let(:request) { get v3_api(route, current_user) }
- end
- end
- end
- context 'when unauthenticated', 'and project is public' do
- it_behaves_like 'repository raw blob' do
- let(:project) { create(:project, :public, :repository) }
- let(:current_user) { nil }
- end
- end
- context 'when unauthenticated', 'and project is private' do
- it_behaves_like '404 response' do
- let(:request) { get v3_api(route) }
- let(:message) { '404 Project Not Found' }
- end
- end
- context 'when authenticated', 'as a developer' do
- it_behaves_like 'repository raw blob' do
- let(:current_user) { user }
- end
- end
- context 'when authenticated', 'as a guest' do
- it_behaves_like '403 response' do
- let(:request) { get v3_api(route, guest) }
- end
- end
- end
- describe "GET /projects/:id/repository/archive(.:format)?:sha" do
- let(:route) { "/projects/#{project.id}/repository/archive" }
- shared_examples_for 'repository archive' do
- it 'returns the repository archive' do
- get v3_api(route, current_user)
- expect(response).to have_gitlab_http_status(200)
- repo_name = project.repository.name.gsub("\.git", "")
- type, params = workhorse_send_data
- expect(type).to eq('git-archive')
- expect(params['ArchivePath']).to match(/#{repo_name}\-[^\.]+\.tar.gz/)
- end
- it 'returns the repository archive archive.zip' do
- get v3_api("/projects/#{project.id}/repository/archive.zip", user)
- expect(response).to have_gitlab_http_status(200)
- repo_name = project.repository.name.gsub("\.git", "")
- type, params = workhorse_send_data
- expect(type).to eq('git-archive')
- expect(params['ArchivePath']).to match(/#{repo_name}\-[^\.]+\.zip/)
- end
- it 'returns the repository archive archive.tar.bz2' do
- get v3_api("/projects/#{project.id}/repository/archive.tar.bz2", user)
- expect(response).to have_gitlab_http_status(200)
- repo_name = project.repository.name.gsub("\.git", "")
- type, params = workhorse_send_data
- expect(type).to eq('git-archive')
- expect(params['ArchivePath']).to match(/#{repo_name}\-[^\.]+\.tar.bz2/)
- end
- context 'when sha does not exist' do
- it_behaves_like '404 response' do
- let(:request) { get v3_api("#{route}?sha=xxx", current_user) }
- let(:message) { '404 File Not Found' }
- end
- end
- end
- context 'when unauthenticated', 'and project is public' do
- it_behaves_like 'repository archive' do
- let(:project) { create(:project, :public, :repository) }
- let(:current_user) { nil }
- end
- end
- context 'when unauthenticated', 'and project is private' do
- it_behaves_like '404 response' do
- let(:request) { get v3_api(route) }
- let(:message) { '404 Project Not Found' }
- end
- end
- context 'when authenticated', 'as a developer' do
- it_behaves_like 'repository archive' do
- let(:current_user) { user }
- end
- end
- context 'when authenticated', 'as a guest' do
- it_behaves_like '403 response' do
- let(:request) { get v3_api(route, guest) }
- end
- end
- end
-
- describe 'GET /projects/:id/repository/compare' do
- let(:route) { "/projects/#{project.id}/repository/compare" }
- shared_examples_for 'repository compare' do
- it "compares branches" do
- get v3_api(route, current_user), from: 'master', to: 'feature'
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['commits']).to be_present
- expect(json_response['diffs']).to be_present
- end
- it "compares tags" do
- get v3_api(route, current_user), from: 'v1.0.0', to: 'v1.1.0'
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['commits']).to be_present
- expect(json_response['diffs']).to be_present
- end
- it "compares commits" do
- get v3_api(route, current_user), from: sample_commit.id, to: sample_commit.parent_id
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['commits']).to be_empty
- expect(json_response['diffs']).to be_empty
- expect(json_response['compare_same_ref']).to be_falsey
- end
- it "compares commits in reverse order" do
- get v3_api(route, current_user), from: sample_commit.parent_id, to: sample_commit.id
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['commits']).to be_present
- expect(json_response['diffs']).to be_present
- end
- it "compares same refs" do
- get v3_api(route, current_user), from: 'master', to: 'master'
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['commits']).to be_empty
- expect(json_response['diffs']).to be_empty
- expect(json_response['compare_same_ref']).to be_truthy
- end
- end
- context 'when unauthenticated', 'and project is public' do
- it_behaves_like 'repository compare' do
- let(:project) { create(:project, :public, :repository) }
- let(:current_user) { nil }
- end
- end
- context 'when unauthenticated', 'and project is private' do
- it_behaves_like '404 response' do
- let(:request) { get v3_api(route) }
- let(:message) { '404 Project Not Found' }
- end
- end
- context 'when authenticated', 'as a developer' do
- it_behaves_like 'repository compare' do
- let(:current_user) { user }
- end
- end
- context 'when authenticated', 'as a guest' do
- it_behaves_like '403 response' do
- let(:request) { get v3_api(route, guest) }
- end
- end
- end
-
- describe 'GET /projects/:id/repository/contributors' do
- let(:route) { "/projects/#{project.id}/repository/contributors" }
-
- shared_examples_for 'repository contributors' do
- it 'returns valid data' do
- get v3_api(route, current_user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
-
- first_contributor = json_response.first
- expect(first_contributor['email']).to eq('tiagonbotelho@hotmail.com')
- expect(first_contributor['name']).to eq('tiagonbotelho')
- expect(first_contributor['commits']).to eq(1)
- expect(first_contributor['additions']).to eq(0)
- expect(first_contributor['deletions']).to eq(0)
- end
- end
-
- context 'when unauthenticated', 'and project is public' do
- it_behaves_like 'repository contributors' do
- let(:project) { create(:project, :public, :repository) }
- let(:current_user) { nil }
- end
- end
-
- context 'when unauthenticated', 'and project is private' do
- it_behaves_like '404 response' do
- let(:request) { get v3_api(route) }
- let(:message) { '404 Project Not Found' }
- end
- end
-
- context 'when authenticated', 'as a developer' do
- it_behaves_like 'repository contributors' do
- let(:current_user) { user }
- end
- end
-
- context 'when authenticated', 'as a guest' do
- it_behaves_like '403 response' do
- let(:request) { get v3_api(route, guest) }
- end
- end
- end
-end
diff --git a/spec/requests/api/v3/runners_spec.rb b/spec/requests/api/v3/runners_spec.rb
deleted file mode 100644
index c91b097a3c7..00000000000
--- a/spec/requests/api/v3/runners_spec.rb
+++ /dev/null
@@ -1,152 +0,0 @@
-require 'spec_helper'
-
-describe API::V3::Runners do
- let(:admin) { create(:user, :admin) }
- let(:user) { create(:user) }
- let(:user2) { create(:user) }
-
- let(:project) { create(:project, creator_id: user.id) }
- let(:project2) { create(:project, creator_id: user.id) }
-
- let!(:shared_runner) { create(:ci_runner, :shared) }
- let!(:unused_specific_runner) { create(:ci_runner) }
-
- let!(:specific_runner) do
- create(:ci_runner).tap do |runner|
- create(:ci_runner_project, runner: runner, project: project)
- end
- end
-
- let!(:two_projects_runner) do
- create(:ci_runner).tap do |runner|
- create(:ci_runner_project, runner: runner, project: project)
- create(:ci_runner_project, runner: runner, project: project2)
- end
- end
-
- before do
- # Set project access for users
- create(:project_member, :master, user: user, project: project)
- create(:project_member, :reporter, user: user2, project: project)
- end
-
- describe 'DELETE /runners/:id' do
- context 'admin user' do
- context 'when runner is shared' do
- it 'deletes runner' do
- expect do
- delete v3_api("/runners/#{shared_runner.id}", admin)
-
- expect(response).to have_gitlab_http_status(200)
- end.to change { Ci::Runner.shared.count }.by(-1)
- end
- end
-
- context 'when runner is not shared' do
- it 'deletes unused runner' do
- expect do
- delete v3_api("/runners/#{unused_specific_runner.id}", admin)
-
- expect(response).to have_gitlab_http_status(200)
- end.to change { Ci::Runner.specific.count }.by(-1)
- end
-
- it 'deletes used runner' do
- expect do
- delete v3_api("/runners/#{specific_runner.id}", admin)
-
- expect(response).to have_gitlab_http_status(200)
- end.to change { Ci::Runner.specific.count }.by(-1)
- end
- end
-
- it 'returns 404 if runner does not exists' do
- delete v3_api('/runners/9999', admin)
-
- expect(response).to have_gitlab_http_status(404)
- end
- end
-
- context 'authorized user' do
- context 'when runner is shared' do
- it 'does not delete runner' do
- delete v3_api("/runners/#{shared_runner.id}", user)
- expect(response).to have_gitlab_http_status(403)
- end
- end
-
- context 'when runner is not shared' do
- it 'does not delete runner without access to it' do
- delete v3_api("/runners/#{specific_runner.id}", user2)
- expect(response).to have_gitlab_http_status(403)
- end
-
- it 'does not delete runner with more than one associated project' do
- delete v3_api("/runners/#{two_projects_runner.id}", user)
- expect(response).to have_gitlab_http_status(403)
- end
-
- it 'deletes runner for one owned project' do
- expect do
- delete v3_api("/runners/#{specific_runner.id}", user)
-
- expect(response).to have_gitlab_http_status(200)
- end.to change { Ci::Runner.specific.count }.by(-1)
- end
- end
- end
-
- context 'unauthorized user' do
- it 'does not delete runner' do
- delete v3_api("/runners/#{specific_runner.id}")
-
- expect(response).to have_gitlab_http_status(401)
- end
- end
- end
-
- describe 'DELETE /projects/:id/runners/:runner_id' do
- context 'authorized user' do
- context 'when runner have more than one associated projects' do
- it "disables project's runner" do
- expect do
- delete v3_api("/projects/#{project.id}/runners/#{two_projects_runner.id}", user)
-
- expect(response).to have_gitlab_http_status(200)
- end.to change { project.runners.count }.by(-1)
- end
- end
-
- context 'when runner have one associated projects' do
- it "does not disable project's runner" do
- expect do
- delete v3_api("/projects/#{project.id}/runners/#{specific_runner.id}", user)
- end.to change { project.runners.count }.by(0)
- expect(response).to have_gitlab_http_status(403)
- end
- end
-
- it 'returns 404 is runner is not found' do
- delete v3_api("/projects/#{project.id}/runners/9999", user)
-
- expect(response).to have_gitlab_http_status(404)
- end
- end
-
- context 'authorized user without permissions' do
- it "does not disable project's runner" do
- delete v3_api("/projects/#{project.id}/runners/#{specific_runner.id}", user2)
-
- expect(response).to have_gitlab_http_status(403)
- end
- end
-
- context 'unauthorized user' do
- it "does not disable project's runner" do
- delete v3_api("/projects/#{project.id}/runners/#{specific_runner.id}")
-
- expect(response).to have_gitlab_http_status(401)
- end
- end
- end
-end
diff --git a/spec/requests/api/v3/services_spec.rb b/spec/requests/api/v3/services_spec.rb
deleted file mode 100644
index c69a7d58ca6..00000000000
--- a/spec/requests/api/v3/services_spec.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-require "spec_helper"
-
-describe API::V3::Services do
- let(:user) { create(:user) }
- let(:project) { create(:project, creator_id: user.id, namespace: user.namespace) }
-
- available_services = Service.available_services_names
- available_services.delete('prometheus')
- available_services.each do |service|
- describe "DELETE /projects/:id/services/#{service.dasherize}" do
- include_context service
-
- before do
- initialize_service(service)
- end
-
- it "deletes #{service}" do
- delete v3_api("/projects/#{project.id}/services/#{dashed_service}", user)
-
- expect(response).to have_gitlab_http_status(200)
- project.send(service_method).reload
- expect(project.send(service_method).activated?).to be_falsey
- end
- end
- end
-end
diff --git a/spec/requests/api/v3/settings_spec.rb b/spec/requests/api/v3/settings_spec.rb
deleted file mode 100644
index 985bfbfa09c..00000000000
--- a/spec/requests/api/v3/settings_spec.rb
+++ /dev/null
@@ -1,63 +0,0 @@
-require 'spec_helper'
-
-describe API::V3::Settings, 'Settings' do
- 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_gitlab_http_status(200)
- expect(json_response).to be_an Hash
- expect(json_response['default_projects_limit']).to eq(42)
- expect(json_response['password_authentication_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, password_authentication_enabled_for_web: 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_gitlab_http_status(200)
- expect(json_response['default_projects_limit']).to eq(3)
- expect(json_response['password_authentication_enabled_for_web']).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_gitlab_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_gitlab_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
deleted file mode 100644
index e8913039194..00000000000
--- a/spec/requests/api/v3/snippets_spec.rb
+++ /dev/null
@@ -1,186 +0,0 @@
-require 'rails_helper'
-
-describe API::V3::Snippets do
- 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_gitlab_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_gitlab_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_gitlab_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_gitlab_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_gitlab_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_gitlab_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_gitlab_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(: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_gitlab_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_gitlab_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_gitlab_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_gitlab_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_gitlab_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_gitlab_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_gitlab_http_status(404)
- expect(json_response['message']).to eq('404 Snippet Not Found')
- end
- end
-end
diff --git a/spec/requests/api/v3/system_hooks_spec.rb b/spec/requests/api/v3/system_hooks_spec.rb
deleted file mode 100644
index 30711c60faa..00000000000
--- a/spec/requests/api/v3/system_hooks_spec.rb
+++ /dev/null
@@ -1,56 +0,0 @@
-require 'spec_helper'
-
-describe API::V3::SystemHooks do
- let(:user) { create(:user) }
- let(:admin) { create(:admin) }
- let!(:hook) { create(:system_hook, url: "http://example.com") }
-
- before { stub_request(:post, hook.url) }
-
- describe "GET /hooks" do
- context "when no user" do
- it "returns authentication error" do
- get v3_api("/hooks")
-
- expect(response).to have_gitlab_http_status(401)
- end
- end
-
- context "when not an admin" do
- it "returns forbidden error" do
- get v3_api("/hooks", user)
-
- expect(response).to have_gitlab_http_status(403)
- end
- end
-
- context "when authenticated as admin" do
- it "returns an array of hooks" do
- get v3_api("/hooks", admin)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.first['url']).to eq(hook.url)
- expect(json_response.first['push_events']).to be false
- expect(json_response.first['tag_push_events']).to be false
- expect(json_response.first['repository_update_events']).to be true
- end
- end
- end
-
- describe "DELETE /hooks/:id" do
- it "deletes a hook" do
- expect do
- delete v3_api("/hooks/#{hook.id}", admin)
-
- expect(response).to have_gitlab_http_status(200)
- end.to change { SystemHook.count }.by(-1)
- end
-
- it 'returns 404 if the system hook does not exist' do
- delete v3_api('/hooks/12345', admin)
-
- expect(response).to have_gitlab_http_status(404)
- end
- end
-end
diff --git a/spec/requests/api/v3/tags_spec.rb b/spec/requests/api/v3/tags_spec.rb
deleted file mode 100644
index e6ad005fa87..00000000000
--- a/spec/requests/api/v3/tags_spec.rb
+++ /dev/null
@@ -1,88 +0,0 @@
-require 'spec_helper'
-require 'mime/types'
-
-describe API::V3::Tags do
- include RepoHelpers
-
- let(:user) { create(:user) }
- let(:user2) { create(:user) }
- let!(:project) { create(:project, :repository, creator: user) }
- let!(:master) { create(:project_member, :master, user: user, project: project) }
-
- describe "GET /projects/:id/repository/tags" do
- let(:tag_name) { project.repository.tag_names.sort.reverse.first }
- let(:description) { 'Awesome release!' }
-
- shared_examples_for 'repository tags' do
- it 'returns the repository tags' do
- get v3_api("/projects/#{project.id}/repository/tags", current_user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.first['name']).to eq(tag_name)
- end
- end
-
- context 'when unauthenticated' do
- it_behaves_like 'repository tags' do
- let(:project) { create(:project, :public, :repository) }
- let(:current_user) { nil }
- end
- end
-
- context 'when authenticated' do
- it_behaves_like 'repository tags' do
- let(:current_user) { user }
- end
- end
-
- context 'without releases' do
- it "returns an array of project tags" do
- get v3_api("/projects/#{project.id}/repository/tags", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.first['name']).to eq(tag_name)
- end
- end
-
- context 'with releases' do
- before do
- release = project.releases.find_or_initialize_by(tag: tag_name)
- release.update_attributes(description: description)
- end
-
- it "returns an array of project tags with release info" do
- get v3_api("/projects/#{project.id}/repository/tags", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.first['name']).to eq(tag_name)
- expect(json_response.first['message']).to eq('Version 1.1.0')
- expect(json_response.first['release']['description']).to eq(description)
- end
- end
- end
-
- describe 'DELETE /projects/:id/repository/tags/:tag_name' do
- let(:tag_name) { project.repository.tag_names.sort.reverse.first }
-
- before do
- allow_any_instance_of(Repository).to receive(:rm_tag).and_return(true)
- end
-
- context 'delete tag' do
- it 'deletes an existing tag' do
- delete v3_api("/projects/#{project.id}/repository/tags/#{tag_name}", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['tag_name']).to eq(tag_name)
- end
-
- it 'raises 404 if the tag does not exist' do
- delete v3_api("/projects/#{project.id}/repository/tags/foobar", user)
- expect(response).to have_gitlab_http_status(404)
- end
- end
- end
-end
diff --git a/spec/requests/api/v3/templates_spec.rb b/spec/requests/api/v3/templates_spec.rb
deleted file mode 100644
index 1a637f3cf96..00000000000
--- a/spec/requests/api/v3/templates_spec.rb
+++ /dev/null
@@ -1,201 +0,0 @@
-require 'spec_helper'
-
-describe API::V3::Templates do
- shared_examples_for 'the Template Entity' do |path|
- before { get v3_api(path) }
-
- it { expect(json_response['name']).to eq('Ruby') }
- it { expect(json_response['content']).to include('*.gem') }
- end
-
- shared_examples_for 'the TemplateList Entity' do |path|
- before { get v3_api(path) }
-
- it { expect(json_response.first['name']).not_to be_nil }
- it { expect(json_response.first['content']).to be_nil }
- end
-
- shared_examples_for 'requesting gitignores' do |path|
- it 'returns a list of available gitignore templates' do
- get v3_api(path)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.size).to be > 15
- end
- end
-
- shared_examples_for 'requesting gitlab-ci-ymls' do |path|
- it 'returns a list of available gitlab_ci_ymls' do
- get v3_api(path)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.first['name']).not_to be_nil
- end
- end
-
- shared_examples_for 'requesting gitlab-ci-yml for Ruby' do |path|
- it 'adds a disclaimer on the top' do
- get v3_api(path)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['content']).to start_with("# This file is a template,")
- end
- end
-
- shared_examples_for 'the License Template Entity' do |path|
- before { get v3_api(path) }
-
- it 'returns a license template' do
- expect(json_response['key']).to eq('mit')
- expect(json_response['name']).to eq('MIT License')
- expect(json_response['nickname']).to be_nil
- expect(json_response['popular']).to be true
- expect(json_response['html_url']).to eq('http://choosealicense.com/licenses/mit/')
- expect(json_response['source_url']).to eq('https://opensource.org/licenses/MIT')
- expect(json_response['description']).to include('A short and simple permissive license with conditions')
- expect(json_response['conditions']).to eq(%w[include-copyright])
- expect(json_response['permissions']).to eq(%w[commercial-use modifications distribution private-use])
- expect(json_response['limitations']).to eq(%w[liability warranty])
- expect(json_response['content']).to include('MIT License')
- end
- end
-
- shared_examples_for 'GET licenses' do |path|
- it 'returns a list of available license templates' do
- get v3_api(path)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.size).to eq(12)
- expect(json_response.map { |l| l['key'] }).to include('agpl-3.0')
- end
-
- describe 'the popular parameter' do
- context 'with popular=1' do
- it 'returns a list of available popular license templates' do
- get v3_api("#{path}?popular=1")
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.size).to eq(3)
- expect(json_response.map { |l| l['key'] }).to include('apache-2.0')
- end
- end
- end
- end
-
- shared_examples_for 'GET licenses/:name' do |path|
- context 'with :project and :fullname given' do
- before do
- get v3_api("#{path}/#{license_type}?project=My+Awesome+Project&fullname=Anton+#{license_type.upcase}")
- end
-
- context 'for the mit license' do
- let(:license_type) { 'mit' }
-
- it 'returns the license text' do
- expect(json_response['content']).to include('MIT License')
- end
-
- it 'replaces placeholder values' do
- expect(json_response['content']).to include("Copyright (c) #{Time.now.year} Anton")
- end
- end
-
- context 'for the agpl-3.0 license' do
- let(:license_type) { 'agpl-3.0' }
-
- it 'returns the license text' do
- expect(json_response['content']).to include('GNU AFFERO GENERAL PUBLIC LICENSE')
- end
-
- it 'replaces placeholder values' do
- expect(json_response['content']).to include('My Awesome Project')
- expect(json_response['content']).to include("Copyright (C) #{Time.now.year} Anton")
- end
- end
-
- context 'for the gpl-3.0 license' do
- let(:license_type) { 'gpl-3.0' }
-
- it 'returns the license text' do
- expect(json_response['content']).to include('GNU GENERAL PUBLIC LICENSE')
- end
-
- it 'replaces placeholder values' do
- expect(json_response['content']).to include('My Awesome Project')
- expect(json_response['content']).to include("Copyright (C) #{Time.now.year} Anton")
- end
- end
-
- context 'for the gpl-2.0 license' do
- let(:license_type) { 'gpl-2.0' }
-
- it 'returns the license text' do
- expect(json_response['content']).to include('GNU GENERAL PUBLIC LICENSE')
- end
-
- it 'replaces placeholder values' do
- expect(json_response['content']).to include('My Awesome Project')
- expect(json_response['content']).to include("Copyright (C) #{Time.now.year} Anton")
- end
- end
-
- context 'for the apache-2.0 license' do
- let(:license_type) { 'apache-2.0' }
-
- it 'returns the license text' do
- expect(json_response['content']).to include('Apache License')
- end
-
- it 'replaces placeholder values' do
- expect(json_response['content']).to include("Copyright #{Time.now.year} Anton")
- end
- end
-
- context 'for an uknown license' do
- let(:license_type) { 'muth-over9000' }
-
- it 'returns a 404' do
- expect(response).to have_gitlab_http_status(404)
- end
- end
- end
-
- context 'with no :fullname given' do
- context 'with an authenticated user' do
- let(:user) { create(:user) }
-
- it 'replaces the copyright owner placeholder with the name of the current user' do
- get v3_api('/templates/licenses/mit', user)
-
- expect(json_response['content']).to include("Copyright (c) #{Time.now.year} #{user.name}")
- end
- end
- end
- end
-
- describe 'with /templates namespace' do
- it_behaves_like 'the Template Entity', '/templates/gitignores/Ruby'
- it_behaves_like 'the TemplateList Entity', '/templates/gitignores'
- it_behaves_like 'requesting gitignores', '/templates/gitignores'
- it_behaves_like 'requesting gitlab-ci-ymls', '/templates/gitlab_ci_ymls'
- it_behaves_like 'requesting gitlab-ci-yml for Ruby', '/templates/gitlab_ci_ymls/Ruby'
- it_behaves_like 'the License Template Entity', '/templates/licenses/mit'
- it_behaves_like 'GET licenses', '/templates/licenses'
- it_behaves_like 'GET licenses/:name', '/templates/licenses'
- end
-
- describe 'without /templates namespace' do
- it_behaves_like 'the Template Entity', '/gitignores/Ruby'
- it_behaves_like 'the TemplateList Entity', '/gitignores'
- it_behaves_like 'requesting gitignores', '/gitignores'
- it_behaves_like 'requesting gitlab-ci-ymls', '/gitlab_ci_ymls'
- it_behaves_like 'requesting gitlab-ci-yml for Ruby', '/gitlab_ci_ymls/Ruby'
- it_behaves_like 'the License Template Entity', '/licenses/mit'
- it_behaves_like 'GET licenses', '/licenses'
- it_behaves_like 'GET licenses/:name', '/licenses'
- end
-end
diff --git a/spec/requests/api/v3/todos_spec.rb b/spec/requests/api/v3/todos_spec.rb
deleted file mode 100644
index ea648e3917f..00000000000
--- a/spec/requests/api/v3/todos_spec.rb
+++ /dev/null
@@ -1,77 +0,0 @@
-require 'spec_helper'
-
-describe API::V3::Todos do
- let(:project_1) { create(:project) }
- let(:project_2) { create(:project) }
- let(:author_1) { create(:user) }
- let(:author_2) { create(:user) }
- let(:john_doe) { create(:user, username: 'john_doe') }
- let!(:pending_1) { create(:todo, :mentioned, project: project_1, author: author_1, user: john_doe) }
- let!(:pending_2) { create(:todo, project: project_2, author: author_2, user: john_doe) }
- let!(:pending_3) { create(:todo, project: project_1, author: author_2, user: john_doe) }
- let!(:done) { create(:todo, :done, project: project_1, author: author_1, user: john_doe) }
-
- before do
- project_1.add_developer(john_doe)
- project_2.add_developer(john_doe)
- end
-
- describe 'DELETE /todos/:id' do
- context 'when unauthenticated' do
- it 'returns authentication error' do
- delete v3_api("/todos/#{pending_1.id}")
-
- expect(response.status).to eq(401)
- end
- end
-
- context 'when authenticated' do
- it 'marks a todo as done' do
- delete v3_api("/todos/#{pending_1.id}", john_doe)
-
- expect(response.status).to eq(200)
- expect(pending_1.reload).to be_done
- end
-
- it 'updates todos cache' do
- expect_any_instance_of(User).to receive(:update_todos_count_cache).and_call_original
-
- delete v3_api("/todos/#{pending_1.id}", john_doe)
- end
-
- it 'returns 404 if the todo does not belong to the current user' do
- delete v3_api("/todos/#{pending_1.id}", author_1)
-
- expect(response.status).to eq(404)
- end
- end
- end
-
- describe 'DELETE /todos' do
- context 'when unauthenticated' do
- it 'returns authentication error' do
- delete v3_api('/todos')
-
- expect(response.status).to eq(401)
- end
- end
-
- context 'when authenticated' do
- it 'marks all todos as done' do
- delete v3_api('/todos', john_doe)
-
- expect(response.status).to eq(200)
- expect(response.body).to eq('3')
- expect(pending_1.reload).to be_done
- expect(pending_2.reload).to be_done
- expect(pending_3.reload).to be_done
- end
-
- it 'updates todos cache' do
- expect_any_instance_of(User).to receive(:update_todos_count_cache).and_call_original
-
- delete v3_api("/todos", john_doe)
- end
- end
- end
-end
diff --git a/spec/requests/api/v3/triggers_spec.rb b/spec/requests/api/v3/triggers_spec.rb
deleted file mode 100644
index e8e2f49d7a0..00000000000
--- a/spec/requests/api/v3/triggers_spec.rb
+++ /dev/null
@@ -1,235 +0,0 @@
-require 'spec_helper'
-
-describe API::V3::Triggers do
- let(:user) { create(:user) }
- let(:user2) { create(:user) }
- let!(:trigger_token) { 'secure_token' }
- let!(:project) { create(:project, :repository, creator: user) }
- let!(:master) { create(:project_member, :master, user: user, project: project) }
- let!(:developer) { create(:project_member, :developer, user: user2, project: project) }
-
- let!(:trigger) do
- create(:ci_trigger, project: project, token: trigger_token, owner: user)
- end
-
- describe 'POST /projects/:project_id/trigger' do
- let!(:project2) { create(:project) }
- let(:options) do
- {
- token: trigger_token
- }
- end
-
- before do
- stub_ci_pipeline_to_return_yaml_file
- end
-
- context 'Handles errors' do
- it 'returns bad request if token is missing' do
- post v3_api("/projects/#{project.id}/trigger/builds"), ref: 'master'
- expect(response).to have_gitlab_http_status(400)
- end
-
- it 'returns not found if project is not found' do
- post v3_api('/projects/0/trigger/builds'), options.merge(ref: 'master')
- expect(response).to have_gitlab_http_status(404)
- end
-
- it 'returns unauthorized if token is for different project' do
- post v3_api("/projects/#{project2.id}/trigger/builds"), options.merge(ref: 'master')
- expect(response).to have_gitlab_http_status(404)
- end
- end
-
- context 'Have a commit' do
- let(:pipeline) { project.pipelines.last }
-
- it 'creates builds' do
- post v3_api("/projects/#{project.id}/trigger/builds"), options.merge(ref: 'master')
- expect(response).to have_gitlab_http_status(201)
- pipeline.builds.reload
- expect(pipeline.builds.pending.size).to eq(2)
- expect(pipeline.builds.size).to eq(5)
- end
-
- it 'returns bad request with no builds created if there\'s no commit for that ref' do
- post v3_api("/projects/#{project.id}/trigger/builds"), options.merge(ref: 'other-branch')
- expect(response).to have_gitlab_http_status(400)
- expect(json_response['message']['base'])
- .to contain_exactly('Reference not found')
- end
-
- context 'Validates variables' do
- let(:variables) do
- { 'TRIGGER_KEY' => 'TRIGGER_VALUE' }
- end
-
- it 'validates variables to be a hash' do
- post v3_api("/projects/#{project.id}/trigger/builds"), options.merge(variables: 'value', ref: 'master')
- expect(response).to have_gitlab_http_status(400)
- expect(json_response['error']).to eq('variables is invalid')
- end
-
- it 'validates variables needs to be a map of key-valued strings' do
- post v3_api("/projects/#{project.id}/trigger/builds"), options.merge(variables: { key: %w(1 2) }, ref: 'master')
- expect(response).to have_gitlab_http_status(400)
- expect(json_response['message']).to eq('variables needs to be a map of key-valued strings')
- end
-
- it 'creates trigger request with variables' do
- post v3_api("/projects/#{project.id}/trigger/builds"), options.merge(variables: variables, ref: 'master')
- expect(response).to have_gitlab_http_status(201)
- pipeline.builds.reload
- expect(pipeline.variables.map { |v| { v.key => v.value } }.first).to eq(variables)
- expect(json_response['variables']).to eq(variables)
- end
- end
- end
-
- context 'when triggering a pipeline from a trigger token' do
- it 'creates builds from the ref given in the URL, not in the body' do
- expect do
- post v3_api("/projects/#{project.id}/ref/master/trigger/builds?token=#{trigger_token}"), { ref: 'refs/heads/other-branch' }
- end.to change(project.builds, :count).by(5)
- expect(response).to have_gitlab_http_status(201)
- end
-
- context 'when ref contains a dot' do
- it 'creates builds from the ref given in the URL, not in the body' do
- project.repository.create_file(user, '.gitlab/gitlabhq/new_feature.md', 'something valid', message: 'new_feature', branch_name: 'v.1-branch')
-
- expect do
- post v3_api("/projects/#{project.id}/ref/v.1-branch/trigger/builds?token=#{trigger_token}"), { ref: 'refs/heads/other-branch' }
- end.to change(project.builds, :count).by(4)
-
- expect(response).to have_gitlab_http_status(201)
- end
- end
- end
- end
-
- describe 'GET /projects/:id/triggers' do
- context 'authenticated user with valid permissions' do
- it 'returns list of triggers' do
- get v3_api("/projects/#{project.id}/triggers", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_a(Array)
- expect(json_response[0]).to have_key('token')
- end
- end
-
- context 'authenticated user with invalid permissions' do
- it 'does not return triggers list' do
- get v3_api("/projects/#{project.id}/triggers", user2)
-
- expect(response).to have_gitlab_http_status(403)
- end
- end
-
- context 'unauthenticated user' do
- it 'does not return triggers list' do
- get v3_api("/projects/#{project.id}/triggers")
-
- expect(response).to have_gitlab_http_status(401)
- end
- end
- end
-
- describe 'GET /projects/:id/triggers/:token' do
- context 'authenticated user with valid permissions' do
- it 'returns trigger details' do
- get v3_api("/projects/#{project.id}/triggers/#{trigger.token}", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_a(Hash)
- end
-
- it 'responds with 404 Not Found if requesting non-existing trigger' do
- get v3_api("/projects/#{project.id}/triggers/abcdef012345", user)
-
- expect(response).to have_gitlab_http_status(404)
- end
- end
-
- context 'authenticated user with invalid permissions' do
- it 'does not return triggers list' do
- get v3_api("/projects/#{project.id}/triggers/#{trigger.token}", user2)
-
- expect(response).to have_gitlab_http_status(403)
- end
- end
-
- context 'unauthenticated user' do
- it 'does not return triggers list' do
- get v3_api("/projects/#{project.id}/triggers/#{trigger.token}")
-
- expect(response).to have_gitlab_http_status(401)
- end
- end
- end
-
- describe 'POST /projects/:id/triggers' do
- context 'authenticated user with valid permissions' do
- it 'creates trigger' do
- expect do
- post v3_api("/projects/#{project.id}/triggers", user)
- end.to change {project.triggers.count}.by(1)
-
- expect(response).to have_gitlab_http_status(201)
- expect(json_response).to be_a(Hash)
- end
- end
-
- context 'authenticated user with invalid permissions' do
- it 'does not create trigger' do
- post v3_api("/projects/#{project.id}/triggers", user2)
-
- expect(response).to have_gitlab_http_status(403)
- end
- end
-
- context 'unauthenticated user' do
- it 'does not create trigger' do
- post v3_api("/projects/#{project.id}/triggers")
-
- expect(response).to have_gitlab_http_status(401)
- end
- end
- end
-
- describe 'DELETE /projects/:id/triggers/:token' do
- context 'authenticated user with valid permissions' do
- it 'deletes trigger' do
- expect do
- delete v3_api("/projects/#{project.id}/triggers/#{trigger.token}", user)
-
- expect(response).to have_gitlab_http_status(200)
- end.to change {project.triggers.count}.by(-1)
- end
-
- it 'responds with 404 Not Found if requesting non-existing trigger' do
- delete v3_api("/projects/#{project.id}/triggers/abcdef012345", user)
-
- expect(response).to have_gitlab_http_status(404)
- end
- end
-
- context 'authenticated user with invalid permissions' do
- it 'does not delete trigger' do
- delete v3_api("/projects/#{project.id}/triggers/#{trigger.token}", user2)
-
- expect(response).to have_gitlab_http_status(403)
- end
- end
-
- context 'unauthenticated user' do
- it 'does not delete trigger' do
- delete v3_api("/projects/#{project.id}/triggers/#{trigger.token}")
-
- expect(response).to have_gitlab_http_status(401)
- end
- end
- end
-end
diff --git a/spec/requests/api/v3/users_spec.rb b/spec/requests/api/v3/users_spec.rb
deleted file mode 100644
index bbd05f240d2..00000000000
--- a/spec/requests/api/v3/users_spec.rb
+++ /dev/null
@@ -1,362 +0,0 @@
-require 'spec_helper'
-
-describe API::V3::Users do
- let(:user) { create(:user) }
- let(:admin) { create(:admin) }
- let(:key) { create(:key, user: user) }
- let(:email) { create(:email, user: user) }
- let(:ldap_blocked_user) { create(:omniauth_user, provider: 'ldapmain', state: 'ldap_blocked') }
-
- describe 'GET /users' do
- context 'when authenticated' do
- it 'returns an array of users' do
- get v3_api('/users', user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- username = user.username
- expect(json_response.detect do |user|
- user['username'] == username
- end['username']).to eq(username)
- end
- end
-
- context 'when authenticated as user' do
- it 'does not reveal the `is_admin` flag of the user' do
- get v3_api('/users', user)
-
- expect(json_response.first.keys).not_to include 'is_admin'
- end
- end
-
- context 'when authenticated as admin' do
- it 'reveals the `is_admin` flag of the user' do
- get v3_api('/users', admin)
-
- expect(json_response.first.keys).to include 'is_admin'
- end
- end
- end
-
- describe 'GET /user/:id/keys' do
- before { admin }
-
- context 'when unauthenticated' do
- it 'returns authentication error' do
- get v3_api("/users/#{user.id}/keys")
- expect(response).to have_gitlab_http_status(401)
- end
- end
-
- context 'when authenticated' do
- it 'returns 404 for non-existing user' do
- get v3_api('/users/999999/keys', admin)
- expect(response).to have_gitlab_http_status(404)
- expect(json_response['message']).to eq('404 User Not Found')
- end
-
- it 'returns array of ssh keys' do
- user.keys << key
- user.save
-
- get v3_api("/users/#{user.id}/keys", admin)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.first['title']).to eq(key.title)
- end
- end
-
- context "scopes" do
- let(:user) { admin }
- let(:path) { "/users/#{user.id}/keys" }
- let(:api_call) { method(:v3_api) }
-
- before do
- user.keys << key
- user.save
- end
-
- include_examples 'allows the "read_user" scope'
- end
- end
-
- describe 'GET /user/:id/emails' do
- before { admin }
-
- context 'when unauthenticated' do
- it 'returns authentication error' do
- get v3_api("/users/#{user.id}/emails")
- expect(response).to have_gitlab_http_status(401)
- end
- end
-
- context 'when authenticated' do
- it 'returns 404 for non-existing user' do
- get v3_api('/users/999999/emails', admin)
- expect(response).to have_gitlab_http_status(404)
- expect(json_response['message']).to eq('404 User Not Found')
- end
-
- it 'returns array of emails' do
- user.emails << email
- user.save
-
- get v3_api("/users/#{user.id}/emails", admin)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.first['email']).to eq(email.email)
- end
-
- it "returns a 404 for invalid ID" do
- put v3_api("/users/ASDF/emails", admin)
-
- expect(response).to have_gitlab_http_status(404)
- end
- end
- end
-
- describe "GET /user/keys" do
- context "when unauthenticated" do
- it "returns authentication error" do
- get v3_api("/user/keys")
- expect(response).to have_gitlab_http_status(401)
- end
- end
-
- context "when authenticated" do
- it "returns array of ssh keys" do
- user.keys << key
- user.save
-
- get v3_api("/user/keys", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.first["title"]).to eq(key.title)
- end
- end
- end
-
- describe "GET /user/emails" do
- context "when unauthenticated" do
- it "returns authentication error" do
- get v3_api("/user/emails")
- expect(response).to have_gitlab_http_status(401)
- end
- end
-
- context "when authenticated" do
- it "returns array of emails" do
- user.emails << email
- user.save
-
- get v3_api("/user/emails", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.first["email"]).to eq(email.email)
- end
- end
- end
-
- describe 'PUT /users/:id/block' do
- before { admin }
- it 'blocks existing user' do
- put v3_api("/users/#{user.id}/block", admin)
- expect(response).to have_gitlab_http_status(200)
- expect(user.reload.state).to eq('blocked')
- end
-
- it 'does not re-block ldap blocked users' do
- put v3_api("/users/#{ldap_blocked_user.id}/block", admin)
- expect(response).to have_gitlab_http_status(403)
- expect(ldap_blocked_user.reload.state).to eq('ldap_blocked')
- end
-
- it 'does not be available for non admin users' do
- put v3_api("/users/#{user.id}/block", user)
- expect(response).to have_gitlab_http_status(403)
- expect(user.reload.state).to eq('active')
- end
-
- it 'returns a 404 error if user id not found' do
- put v3_api('/users/9999/block', admin)
- expect(response).to have_gitlab_http_status(404)
- expect(json_response['message']).to eq('404 User Not Found')
- end
- end
-
- describe 'PUT /users/:id/unblock' do
- let(:blocked_user) { create(:user, state: 'blocked') }
- before { admin }
-
- it 'unblocks existing user' do
- put v3_api("/users/#{user.id}/unblock", admin)
- expect(response).to have_gitlab_http_status(200)
- expect(user.reload.state).to eq('active')
- end
-
- it 'unblocks a blocked user' do
- put v3_api("/users/#{blocked_user.id}/unblock", admin)
- expect(response).to have_gitlab_http_status(200)
- expect(blocked_user.reload.state).to eq('active')
- end
-
- it 'does not unblock ldap blocked users' do
- put v3_api("/users/#{ldap_blocked_user.id}/unblock", admin)
- expect(response).to have_gitlab_http_status(403)
- expect(ldap_blocked_user.reload.state).to eq('ldap_blocked')
- end
-
- it 'does not be available for non admin users' do
- put v3_api("/users/#{user.id}/unblock", user)
- expect(response).to have_gitlab_http_status(403)
- expect(user.reload.state).to eq('active')
- end
-
- it 'returns a 404 error if user id not found' do
- put v3_api('/users/9999/block', admin)
- expect(response).to have_gitlab_http_status(404)
- expect(json_response['message']).to eq('404 User Not Found')
- end
-
- it "returns a 404 for invalid ID" do
- put v3_api("/users/ASDF/block", admin)
-
- expect(response).to have_gitlab_http_status(404)
- end
- end
-
- describe 'GET /users/:id/events' do
- let(:user) { create(:user) }
- let(:project) { create(:project) }
- let(:note) { create(:note_on_issue, note: 'What an awesome day!', project: project) }
-
- before do
- project.add_user(user, :developer)
- EventCreateService.new.leave_note(note, user)
- end
-
- context "as a user than cannot see the event's project" do
- it 'returns no events' do
- other_user = create(:user)
-
- get api("/users/#{user.id}/events", other_user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_empty
- end
- end
-
- context "as a user than can see the event's project" do
- context 'when the list of events includes push events' do
- let(:event) { create(:push_event, author: user, project: project) }
- let!(:payload) { create(:push_event_payload, event: event) }
- let(:payload_hash) { json_response[0]['push_data'] }
-
- before do
- get api("/users/#{user.id}/events?action=pushed", user)
- end
-
- it 'responds with HTTP 200 OK' do
- expect(response).to have_gitlab_http_status(200)
- end
-
- it 'includes the push payload as a Hash' do
- expect(payload_hash).to be_an_instance_of(Hash)
- end
-
- it 'includes the push payload details' do
- expect(payload_hash['commit_count']).to eq(payload.commit_count)
- expect(payload_hash['action']).to eq(payload.action)
- expect(payload_hash['ref_type']).to eq(payload.ref_type)
- expect(payload_hash['commit_to']).to eq(payload.commit_to)
- end
- end
-
- context 'joined event' do
- it 'returns the "joined" event' do
- get v3_api("/users/#{user.id}/events", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
-
- comment_event = json_response.find { |e| e['action_name'] == 'commented on' }
-
- expect(comment_event['project_id'].to_i).to eq(project.id)
- expect(comment_event['author_username']).to eq(user.username)
- expect(comment_event['note']['id']).to eq(note.id)
- expect(comment_event['note']['body']).to eq('What an awesome day!')
-
- joined_event = json_response.find { |e| e['action_name'] == 'joined' }
-
- expect(joined_event['project_id'].to_i).to eq(project.id)
- expect(joined_event['author_username']).to eq(user.username)
- expect(joined_event['author']['name']).to eq(user.name)
- end
- end
-
- context 'when there are multiple events from different projects' do
- let(:second_note) { create(:note_on_issue, project: create(:project)) }
- let(:third_note) { create(:note_on_issue, project: project) }
-
- before do
- second_note.project.add_user(user, :developer)
-
- [second_note, third_note].each do |note|
- EventCreateService.new.leave_note(note, user)
- end
- end
-
- it 'returns events in the correct order (from newest to oldest)' do
- get v3_api("/users/#{user.id}/events", user)
-
- comment_events = json_response.select { |e| e['action_name'] == 'commented on' }
-
- expect(comment_events[0]['target_id']).to eq(third_note.id)
- expect(comment_events[1]['target_id']).to eq(second_note.id)
- expect(comment_events[2]['target_id']).to eq(note.id)
- end
- end
- end
-
- it 'returns a 404 error if not found' do
- get v3_api('/users/420/events', user)
-
- expect(response).to have_gitlab_http_status(404)
- expect(json_response['message']).to eq('404 User Not Found')
- end
- end
-
- describe 'POST /users' do
- it 'creates confirmed user when confirm parameter is false' do
- optional_attributes = { confirm: false }
- attributes = attributes_for(:user).merge(optional_attributes)
-
- post v3_api('/users', admin), attributes
-
- user_id = json_response['id']
- new_user = User.find(user_id)
-
- expect(new_user).to be_confirmed
- end
-
- it 'does not reveal the `is_admin` flag of the user' do
- post v3_api('/users', admin), attributes_for(:user)
-
- expect(json_response['is_admin']).to be_nil
- end
-
- context "scopes" do
- let(:user) { admin }
- let(:path) { '/users' }
- let(:api_call) { method(:v3_api) }
-
- include_examples 'does not allow the "read_user" scope'
- end
- end
-end
diff --git a/spec/requests/rack_attack_global_spec.rb b/spec/requests/rack_attack_global_spec.rb
index b18e922b063..c0a3ea397df 100644
--- a/spec/requests/rack_attack_global_spec.rb
+++ b/spec/requests/rack_attack_global_spec.rb
@@ -349,7 +349,7 @@ describe 'Rack Attack global throttles' do
end
def rss_url(user)
- "/dashboard/projects.atom?rss_token=#{user.rss_token}"
+ "/dashboard/projects.atom?feed_token=#{user.feed_token}"
end
def private_token_headers(user)
diff --git a/spec/routing/routing_spec.rb b/spec/routing/routing_spec.rb
index 9345671a1a7..dd8f6239587 100644
--- a/spec/routing/routing_spec.rb
+++ b/spec/routing/routing_spec.rb
@@ -162,8 +162,8 @@ describe ProfilesController, "routing" do
expect(get("/profile/audit_log")).to route_to('profiles#audit_log')
end
- it "to #reset_rss_token" do
- expect(put("/profile/reset_rss_token")).to route_to('profiles#reset_rss_token')
+ it "to #reset_feed_token" do
+ expect(put("/profile/reset_feed_token")).to route_to('profiles#reset_feed_token')
end
it "to #show" do
@@ -249,7 +249,11 @@ describe DashboardController, "routing" do
end
it "to #issues" do
- expect(get("/dashboard/issues")).to route_to('dashboard#issues')
+ expect(get("/dashboard/issues.html")).to route_to('dashboard#issues', format: 'html')
+ end
+
+ it "to #calendar_issues" do
+ expect(get("/dashboard/issues.ics")).to route_to('dashboard#issues_calendar', format: 'ics')
end
it "to #merge_requests" do
diff --git a/spec/serializers/job_entity_spec.rb b/spec/serializers/job_entity_spec.rb
index c90396ebb28..a5581a34517 100644
--- a/spec/serializers/job_entity_spec.rb
+++ b/spec/serializers/job_entity_spec.rb
@@ -131,7 +131,7 @@ describe JobEntity do
end
context 'when job failed' do
- let(:job) { create(:ci_build, :script_failure) }
+ let(:job) { create(:ci_build, :api_failure) }
it 'contains details' do
expect(subject[:status]).to include :icon, :favicon, :text, :label, :tooltip
@@ -142,20 +142,20 @@ describe JobEntity do
end
it 'should indicate the failure reason on tooltip' do
- expect(subject[:status][:tooltip]).to eq('failed <br> (script failure)')
+ expect(subject[:status][:tooltip]).to eq('failed <br> (API failure)')
end
it 'should include a callout message with a verbose output' do
- expect(subject[:callout_message]).to eq('There has been a script failure. Check the job log for more information')
+ expect(subject[:callout_message]).to eq('There has been an API failure, please try again')
end
it 'should state that it is not recoverable' do
- expect(subject[:recoverable]).to be_falsy
+ expect(subject[:recoverable]).to be_truthy
end
end
context 'when job is allowed to fail' do
- let(:job) { create(:ci_build, :allowed_to_fail, :script_failure) }
+ let(:job) { create(:ci_build, :allowed_to_fail, :api_failure) }
it 'contains details' do
expect(subject[:status]).to include :icon, :favicon, :text, :label, :tooltip
@@ -166,15 +166,24 @@ describe JobEntity do
end
it 'should indicate the failure reason on tooltip' do
- expect(subject[:status][:tooltip]).to eq('failed <br> (script failure) (allowed to fail)')
+ expect(subject[:status][:tooltip]).to eq('failed <br> (API failure) (allowed to fail)')
end
it 'should include a callout message with a verbose output' do
- expect(subject[:callout_message]).to eq('There has been a script failure. Check the job log for more information')
+ expect(subject[:callout_message]).to eq('There has been an API failure, please try again')
end
it 'should state that it is not recoverable' do
- expect(subject[:recoverable]).to be_falsy
+ expect(subject[:recoverable]).to be_truthy
+ end
+ end
+
+ context 'when the job failed with a script failure' do
+ let(:job) { create(:ci_build, :failed, :script_failure) }
+
+ it 'should not include callout message or recoverable keys' do
+ expect(subject).not_to include('callout_message')
+ expect(subject).not_to include('recoverable')
end
end
diff --git a/spec/services/merge_requests/merge_service_spec.rb b/spec/services/merge_requests/merge_service_spec.rb
index e8568bf8bb3..dc30a9bccc1 100644
--- a/spec/services/merge_requests/merge_service_spec.rb
+++ b/spec/services/merge_requests/merge_service_spec.rb
@@ -249,24 +249,58 @@ describe MergeRequests::MergeService do
expect(Rails.logger).to have_received(:error).with(a_string_matching(error_message))
end
- context "when fast-forward merge is not allowed" do
+ context 'when squashing' do
before do
- allow_any_instance_of(Repository).to receive(:ancestor?).and_return(nil)
+ merge_request.update!(source_branch: 'master', target_branch: 'feature')
end
- %w(semi-linear ff).each do |merge_method|
- it "logs and saves error if merge is #{merge_method} only" do
- merge_method = 'rebase_merge' if merge_method == 'semi-linear'
- merge_request.project.update(merge_method: merge_method)
- error_message = 'Only fast-forward merge is allowed for your project. Please update your source branch'
- allow(service).to receive(:execute_hooks)
+ it 'logs and saves error if there is an error when squashing' do
+ error_message = 'Failed to squash. Should be done manually'
- service.execute(merge_request)
+ allow_any_instance_of(MergeRequests::SquashService).to receive(:squash).and_return(nil)
+ merge_request.update(squash: true)
+
+ service.execute(merge_request)
+
+ expect(merge_request).to be_open
+ expect(merge_request.merge_commit_sha).to be_nil
+ expect(merge_request.merge_error).to include(error_message)
+ expect(Rails.logger).to have_received(:error).with(a_string_matching(error_message))
+ end
+
+ it 'logs and saves error if there is a squash in progress' do
+ error_message = 'another squash is already in progress'
+
+ allow_any_instance_of(MergeRequest).to receive(:squash_in_progress?).and_return(true)
+ merge_request.update(squash: true)
+
+ service.execute(merge_request)
- expect(merge_request).to be_open
- expect(merge_request.merge_commit_sha).to be_nil
- expect(merge_request.merge_error).to include(error_message)
- expect(Rails.logger).to have_received(:error).with(a_string_matching(error_message))
+ expect(merge_request).to be_open
+ expect(merge_request.merge_commit_sha).to be_nil
+ expect(merge_request.merge_error).to include(error_message)
+ expect(Rails.logger).to have_received(:error).with(a_string_matching(error_message))
+ end
+
+ context "when fast-forward merge is not allowed" do
+ before do
+ allow_any_instance_of(Repository).to receive(:ancestor?).and_return(nil)
+ end
+
+ %w(semi-linear ff).each do |merge_method|
+ it "logs and saves error if merge is #{merge_method} only" do
+ merge_method = 'rebase_merge' if merge_method == 'semi-linear'
+ merge_request.project.update(merge_method: merge_method)
+ error_message = 'Only fast-forward merge is allowed for your project. Please update your source branch'
+ allow(service).to receive(:execute_hooks)
+
+ service.execute(merge_request)
+
+ expect(merge_request).to be_open
+ expect(merge_request.merge_commit_sha).to be_nil
+ expect(merge_request.merge_error).to include(error_message)
+ expect(Rails.logger).to have_received(:error).with(a_string_matching(error_message))
+ end
end
end
end
diff --git a/spec/services/merge_requests/squash_service_spec.rb b/spec/services/merge_requests/squash_service_spec.rb
new file mode 100644
index 00000000000..bd884787425
--- /dev/null
+++ b/spec/services/merge_requests/squash_service_spec.rb
@@ -0,0 +1,199 @@
+require 'spec_helper'
+
+describe MergeRequests::SquashService do
+ let(:service) { described_class.new(project, user, {}) }
+ let(:user) { project.owner }
+ let(:project) { create(:project, :repository) }
+ let(:repository) { project.repository.raw }
+ let(:log_error) { "Failed to squash merge request #{merge_request.to_reference(full: true)}:" }
+ let(:squash_dir_path) do
+ File.join(Gitlab.config.shared.path, 'tmp/squash', repository.gl_repository, merge_request.id.to_s)
+ end
+ let(:merge_request_with_one_commit) do
+ create(:merge_request,
+ source_branch: 'feature', source_project: project,
+ target_branch: 'master', target_project: project)
+ end
+
+ let(:merge_request_with_only_new_files) do
+ create(:merge_request,
+ source_branch: 'video', source_project: project,
+ target_branch: 'master', target_project: project)
+ end
+
+ let(:merge_request_with_large_files) do
+ create(:merge_request,
+ source_branch: 'squash-large-files', source_project: project,
+ target_branch: 'master', target_project: project)
+ end
+
+ shared_examples 'the squash succeeds' do
+ it 'returns the squashed commit SHA' do
+ result = service.execute(merge_request)
+
+ expect(result).to match(status: :success, squash_sha: a_string_matching(/\h{40}/))
+ expect(result[:squash_sha]).not_to eq(merge_request.diff_head_sha)
+ end
+
+ it 'cleans up the temporary directory' do
+ service.execute(merge_request)
+
+ expect(File.exist?(squash_dir_path)).to be(false)
+ end
+
+ it 'does not keep the branch push event' do
+ expect { service.execute(merge_request) }.not_to change { Event.count }
+ end
+
+ context 'the squashed commit' do
+ let(:squash_sha) { service.execute(merge_request)[:squash_sha] }
+ let(:squash_commit) { project.repository.commit(squash_sha) }
+
+ it 'copies the author info and message from the merge request' do
+ expect(squash_commit.author_name).to eq(merge_request.author.name)
+ expect(squash_commit.author_email).to eq(merge_request.author.email)
+
+ # Commit messages have a trailing newline, but titles don't.
+ expect(squash_commit.message.chomp).to eq(merge_request.title)
+ end
+
+ it 'sets the current user as the committer' do
+ expect(squash_commit.committer_name).to eq(user.name.chomp('.'))
+ expect(squash_commit.committer_email).to eq(user.email)
+ end
+
+ it 'has the same diff as the merge request, but a different SHA' do
+ rugged = project.repository.rugged
+ mr_diff = rugged.diff(merge_request.diff_base_sha, merge_request.diff_head_sha)
+ squash_diff = rugged.diff(merge_request.diff_start_sha, squash_sha)
+
+ expect(squash_diff.patch.length).to eq(mr_diff.patch.length)
+ expect(squash_commit.sha).not_to eq(merge_request.diff_head_sha)
+ end
+ end
+ end
+
+ describe '#execute' do
+ context 'when there is only one commit in the merge request' do
+ it 'returns that commit SHA' do
+ result = service.execute(merge_request_with_one_commit)
+
+ expect(result).to match(status: :success, squash_sha: merge_request_with_one_commit.diff_head_sha)
+ end
+
+ it 'does not perform any git actions' do
+ expect(repository).not_to receive(:popen)
+
+ service.execute(merge_request_with_one_commit)
+ end
+ end
+
+ context 'when squashing only new files' do
+ let(:merge_request) { merge_request_with_only_new_files }
+
+ include_examples 'the squash succeeds'
+ end
+
+ context 'when squashing with files too large to display' do
+ let(:merge_request) { merge_request_with_large_files }
+
+ include_examples 'the squash succeeds'
+ end
+
+ context 'git errors' do
+ let(:merge_request) { merge_request_with_only_new_files }
+ let(:error) { 'A test error' }
+
+ context 'with gitaly enabled' do
+ before do
+ allow(repository.gitaly_operation_client).to receive(:user_squash)
+ .and_raise(Gitlab::Git::Repository::GitError, error)
+ end
+
+ it 'logs the stage and output' do
+ expect(service).to receive(:log_error).with(log_error)
+ expect(service).to receive(:log_error).with(error)
+
+ service.execute(merge_request)
+ end
+
+ it 'returns an error' do
+ expect(service.execute(merge_request)).to match(status: :error,
+ message: a_string_including('squash'))
+ end
+ end
+
+ context 'with Gitaly disabled', :skip_gitaly_mock do
+ stages = {
+ 'add worktree for squash' => 'worktree',
+ 'configure sparse checkout' => 'config',
+ 'get files in diff' => 'diff --name-only',
+ 'check out target branch' => 'checkout',
+ 'apply patch' => 'diff --binary',
+ 'commit squashed changes' => 'commit',
+ 'get SHA of squashed commit' => 'rev-parse'
+ }
+
+ stages.each do |stage, command|
+ context "when the #{stage} stage fails" do
+ before do
+ git_command = a_collection_containing_exactly(
+ a_string_starting_with("#{Gitlab.config.git.bin_path} #{command}")
+ ).or(
+ a_collection_starting_with([Gitlab.config.git.bin_path] + command.split)
+ )
+
+ allow(repository).to receive(:popen).and_return(['', 0])
+ allow(repository).to receive(:popen).with(git_command, anything, anything, anything).and_return([error, 1])
+ end
+
+ it 'logs the stage and output' do
+ expect(service).to receive(:log_error).with(log_error)
+ expect(service).to receive(:log_error).with(error)
+
+ service.execute(merge_request)
+ end
+
+ it 'returns an error' do
+ expect(service.execute(merge_request)).to match(status: :error,
+ message: a_string_including('squash'))
+ end
+
+ it 'cleans up the temporary directory' do
+ expect(File.exist?(squash_dir_path)).to be(false)
+
+ service.execute(merge_request)
+ end
+ end
+ end
+ end
+ end
+
+ context 'when any other exception is thrown' do
+ let(:merge_request) { merge_request_with_only_new_files }
+ let(:error) { 'A test error' }
+
+ before do
+ allow(merge_request).to receive(:commits_count).and_raise(error)
+ end
+
+ it 'logs the MR reference and exception' do
+ expect(service).to receive(:log_error).with(a_string_including("#{project.full_path}#{merge_request.to_reference}"))
+ expect(service).to receive(:log_error).with(error)
+
+ service.execute(merge_request)
+ end
+
+ it 'returns an error' do
+ expect(service.execute(merge_request)).to match(status: :error,
+ message: a_string_including('squash'))
+ end
+
+ it 'cleans up the temporary directory' do
+ service.execute(merge_request)
+
+ expect(File.exist?(squash_dir_path)).to be(false)
+ end
+ end
+ end
+end
diff --git a/spec/support/api/v3/time_tracking_shared_examples.rb b/spec/support/api/v3/time_tracking_shared_examples.rb
deleted file mode 100644
index f27a2d06c83..00000000000
--- a/spec/support/api/v3/time_tracking_shared_examples.rb
+++ /dev/null
@@ -1,128 +0,0 @@
-shared_examples 'V3 time tracking endpoints' do |issuable_name|
- issuable_collection_name = issuable_name.pluralize
-
- describe "POST /projects/:id/#{issuable_collection_name}/:#{issuable_name}_id/time_estimate" do
- context 'with an unauthorized user' do
- subject { post(v3_api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.id}/time_estimate", non_member), duration: '1w') }
-
- it_behaves_like 'an unauthorized API user'
- end
-
- it "sets the time estimate for #{issuable_name}" do
- post v3_api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.id}/time_estimate", user), duration: '1w'
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['human_time_estimate']).to eq('1w')
- end
-
- describe 'updating the current estimate' do
- before do
- post v3_api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.id}/time_estimate", user), duration: '1w'
- end
-
- context 'when duration has a bad format' do
- it 'does not modify the original estimate' do
- post v3_api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.id}/time_estimate", user), duration: 'foo'
-
- expect(response).to have_gitlab_http_status(400)
- expect(issuable.reload.human_time_estimate).to eq('1w')
- end
- end
-
- context 'with a valid duration' do
- it 'updates the estimate' do
- post v3_api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.id}/time_estimate", user), duration: '3w1h'
-
- expect(response).to have_gitlab_http_status(200)
- expect(issuable.reload.human_time_estimate).to eq('3w 1h')
- end
- end
- end
- end
-
- describe "POST /projects/:id/#{issuable_collection_name}/:#{issuable_name}_id/reset_time_estimate" do
- context 'with an unauthorized user' do
- subject { post(v3_api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.id}/reset_time_estimate", non_member)) }
-
- it_behaves_like 'an unauthorized API user'
- end
-
- it "resets the time estimate for #{issuable_name}" do
- post v3_api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.id}/reset_time_estimate", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['time_estimate']).to eq(0)
- end
- end
-
- describe "POST /projects/:id/#{issuable_collection_name}/:#{issuable_name}_id/add_spent_time" do
- context 'with an unauthorized user' do
- subject do
- post v3_api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.id}/add_spent_time", non_member),
- duration: '2h'
- end
-
- it_behaves_like 'an unauthorized API user'
- end
-
- it "add spent time for #{issuable_name}" do
- post v3_api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.id}/add_spent_time", user),
- duration: '2h'
-
- expect(response).to have_gitlab_http_status(201)
- expect(json_response['human_total_time_spent']).to eq('2h')
- end
-
- context 'when subtracting time' do
- it 'subtracts time of the total spent time' do
- issuable.update_attributes!(spend_time: { duration: 7200, user_id: user.id })
-
- post v3_api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.id}/add_spent_time", user),
- duration: '-1h'
-
- expect(response).to have_gitlab_http_status(201)
- expect(json_response['total_time_spent']).to eq(3600)
- end
- end
-
- context 'when time to subtract is greater than the total spent time' do
- it 'does not modify the total time spent' do
- issuable.update_attributes!(spend_time: { duration: 7200, user_id: user.id })
-
- post v3_api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.id}/add_spent_time", user),
- duration: '-1w'
-
- expect(response).to have_gitlab_http_status(400)
- expect(json_response['message']['time_spent'].first).to match(/exceeds the total time spent/)
- end
- end
- end
-
- describe "POST /projects/:id/#{issuable_collection_name}/:#{issuable_name}_id/reset_spent_time" do
- context 'with an unauthorized user' do
- subject { post(v3_api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.id}/reset_spent_time", non_member)) }
-
- it_behaves_like 'an unauthorized API user'
- end
-
- it "resets spent time for #{issuable_name}" do
- post v3_api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.id}/reset_spent_time", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['total_time_spent']).to eq(0)
- end
- end
-
- describe "GET /projects/:id/#{issuable_collection_name}/:#{issuable_name}_id/time_stats" do
- it "returns the time stats for #{issuable_name}" do
- issuable.update_attributes!(spend_time: { duration: 1800, user_id: user.id },
- time_estimate: 3600)
-
- get v3_api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.id}/time_stats", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['total_time_spent']).to eq(1800)
- expect(json_response['time_estimate']).to eq(3600)
- end
- end
-end
diff --git a/spec/support/features/rss_shared_examples.rb b/spec/support/features/rss_shared_examples.rb
index 50fbbc7f55b..0de92aedba5 100644
--- a/spec/support/features/rss_shared_examples.rb
+++ b/spec/support/features/rss_shared_examples.rb
@@ -1,23 +1,23 @@
-shared_examples "an autodiscoverable RSS feed with current_user's RSS token" do
- it "has an RSS autodiscovery link tag with current_user's RSS token" do
- expect(page).to have_css("link[type*='atom+xml'][href*='rss_token=#{user.rss_token}']", visible: false)
+shared_examples "an autodiscoverable RSS feed with current_user's feed token" do
+ it "has an RSS autodiscovery link tag with current_user's feed token" do
+ expect(page).to have_css("link[type*='atom+xml'][href*='feed_token=#{user.feed_token}']", visible: false)
end
end
-shared_examples "it has an RSS button with current_user's RSS token" do
- it "shows the RSS button with current_user's RSS token" do
- expect(page).to have_css("a:has(.fa-rss)[href*='rss_token=#{user.rss_token}']")
+shared_examples "it has an RSS button with current_user's feed token" do
+ it "shows the RSS button with current_user's feed token" do
+ expect(page).to have_css("a:has(.fa-rss)[href*='feed_token=#{user.feed_token}']")
end
end
-shared_examples "an autodiscoverable RSS feed without an RSS token" do
- it "has an RSS autodiscovery link tag without an RSS token" do
- expect(page).to have_css("link[type*='atom+xml']:not([href*='rss_token'])", visible: false)
+shared_examples "an autodiscoverable RSS feed without a feed token" do
+ it "has an RSS autodiscovery link tag without a feed token" do
+ expect(page).to have_css("link[type*='atom+xml']:not([href*='feed_token'])", visible: false)
end
end
-shared_examples "it has an RSS button without an RSS token" do
- it "shows the RSS button without an RSS token" do
- expect(page).to have_css("a:has(.fa-rss):not([href*='rss_token'])")
+shared_examples "it has an RSS button without a feed token" do
+ it "shows the RSS button without a feed token" do
+ expect(page).to have_css("a:has(.fa-rss):not([href*='feed_token'])")
end
end
diff --git a/spec/support/gitlab-git-test.git/packed-refs b/spec/support/gitlab-git-test.git/packed-refs
index ea50e4ad3f6..6a61e5df267 100644
--- a/spec/support/gitlab-git-test.git/packed-refs
+++ b/spec/support/gitlab-git-test.git/packed-refs
@@ -9,6 +9,7 @@
4b4918a572fa86f9771e5ba40fbd48e1eb03e2c6 refs/heads/master
5937ac0a7beb003549fc5fd26fc247adbce4a52e refs/heads/merge-test
9596bc54a6f0c0c98248fe97077eb5ccf48a98d0 refs/heads/missing-gitmodules
+4b4918a572fa86f9771e5ba40fbd48e1eb03e2c6 refs/heads/Ääh-test-utf-8
f4e6814c3e4e7a0de82a9e7cd20c626cc963a2f8 refs/tags/v1.0.0
^6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
8a2a6eb295bb170b34c24c76c49ed0e9b2eaf34b refs/tags/v1.1.0
diff --git a/spec/support/gitlab_stubs/project_8.json b/spec/support/gitlab_stubs/project_8.json
index f0a9fce859c..81b08ab8288 100644
--- a/spec/support/gitlab_stubs/project_8.json
+++ b/spec/support/gitlab_stubs/project_8.json
@@ -1,38 +1,38 @@
{
- "id":8,
- "description":"ssh access and repository management app for GitLab",
- "default_branch":"master",
- "public":false,
- "visibility_level":0,
- "ssh_url_to_repo":"git@demo.gitlab.com:gitlab/gitlab-shell.git",
- "http_url_to_repo":"http://demo.gitlab.com/gitlab/gitlab-shell.git",
- "web_url":"http://demo.gitlab.com/gitlab/gitlab-shell",
- "owner": {
- "id":4,
- "name":"GitLab",
- "created_at":"2012-12-21T13:03:05Z"
- },
- "name":"gitlab-shell",
- "name_with_namespace":"GitLab / gitlab-shell",
- "path":"gitlab-shell",
- "path_with_namespace":"gitlab/gitlab-shell",
- "issues_enabled":true,
- "merge_requests_enabled":true,
- "wall_enabled":false,
- "wiki_enabled":true,
- "snippets_enabled":false,
- "created_at":"2013-03-20T13:28:53Z",
- "last_activity_at":"2013-11-30T00:11:17Z",
- "namespace":{
- "created_at":"2012-12-21T13:03:05Z",
- "description":"Self hosted Git management software",
- "id":4,
- "name":"GitLab",
- "owner_id":1,
- "path":"gitlab",
- "updated_at":"2013-03-20T13:29:13Z"
+ "id": 8,
+ "description": "ssh access and repository management app for GitLab",
+ "default_branch": "master",
+ "visibility": "private",
+ "ssh_url_to_repo": "git@demo.gitlab.com:gitlab/gitlab-shell.git",
+ "http_url_to_repo": "http://demo.gitlab.com/gitlab/gitlab-shell.git",
+ "web_url": "http://demo.gitlab.com/gitlab/gitlab-shell",
+ "owner": {
+ "id": 4,
+ "name": "GitLab",
+ "username": "gitlab",
+ "state": "active",
+ "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61",
+ "web_url": "http://demo.gitlab.com/gitlab"
},
- "permissions":{
+ "name": "gitlab-shell",
+ "name_with_namespace": "GitLab / gitlab-shell",
+ "path": "gitlab-shell",
+ "path_with_namespace": "gitlab/gitlab-shell",
+ "issues_enabled": true,
+ "merge_requests_enabled": true,
+ "wiki_enabled": true,
+ "snippets_enabled": false,
+ "created_at": "2013-03-20T13:28:53Z",
+ "last_activity_at": "2013-11-30T00:11:17Z",
+ "namespace": {
+ "id": 4,
+ "name": "GitLab",
+ "path": "gitlab",
+ "kind": "group",
+ "full_path": "gitlab",
+ "parent_id": null
+ },
+ "permissions": {
"project_access": {
"access_level": 10,
"notification_level": 3
@@ -42,4 +42,4 @@
"notification_level": 3
}
}
-} \ No newline at end of file
+}
diff --git a/spec/support/gitlab_stubs/projects.json b/spec/support/gitlab_stubs/projects.json
index ca42c14c5d8..67ce1acca2c 100644
--- a/spec/support/gitlab_stubs/projects.json
+++ b/spec/support/gitlab_stubs/projects.json
@@ -1 +1,282 @@
-[{"id":3,"description":"GitLab is open source software to collaborate on code. Create projects and repositories, manage access and do code reviews.","default_branch":"master","public":true,"visibility_level":20,"ssh_url_to_repo":"git@demo.gitlab.com:gitlab/gitlabhq.git","http_url_to_repo":"http://demo.gitlab.com/gitlab/gitlabhq.git","web_url":"http://demo.gitlab.com/gitlab/gitlabhq","owner":{"id":4,"name":"GitLab","created_at":"2012-12-21T13:03:05Z"},"name":"gitlabhq","name_with_namespace":"GitLab / gitlabhq","path":"gitlabhq","path_with_namespace":"gitlab/gitlabhq","issues_enabled":true,"merge_requests_enabled":true,"wall_enabled":true,"wiki_enabled":true,"snippets_enabled":true,"created_at":"2012-12-21T13:06:34Z","last_activity_at":"2013-12-02T19:10:10Z","namespace":{"created_at":"2012-12-21T13:03:05Z","description":"Self hosted Git management software","id":4,"name":"GitLab","owner_id":1,"path":"gitlab","updated_at":"2013-03-20T13:29:13Z"}},{"id":4,"description":"Component of GitLab CI. Web application","default_branch":"master","public":false,"visibility_level":0,"ssh_url_to_repo":"git@demo.gitlab.com:gitlab/gitlab-ci.git","http_url_to_repo":"http://demo.gitlab.com/gitlab/gitlab-ci.git","web_url":"http://demo.gitlab.com/gitlab/gitlab-ci","owner":{"id":4,"name":"GitLab","created_at":"2012-12-21T13:03:05Z"},"name":"gitlab-ci","name_with_namespace":"GitLab / gitlab-ci","path":"gitlab-ci","path_with_namespace":"gitlab/gitlab-ci","issues_enabled":true,"merge_requests_enabled":true,"wall_enabled":true,"wiki_enabled":true,"snippets_enabled":true,"created_at":"2012-12-21T13:06:50Z","last_activity_at":"2013-11-28T19:26:54Z","namespace":{"created_at":"2012-12-21T13:03:05Z","description":"Self hosted Git management software","id":4,"name":"GitLab","owner_id":1,"path":"gitlab","updated_at":"2013-03-20T13:29:13Z"}},{"id":5,"description":"","default_branch":"master","public":true,"visibility_level":20,"ssh_url_to_repo":"git@demo.gitlab.com:gitlab/gitlab-recipes.git","http_url_to_repo":"http://demo.gitlab.com/gitlab/gitlab-recipes.git","web_url":"http://demo.gitlab.com/gitlab/gitlab-recipes","owner":{"id":4,"name":"GitLab","created_at":"2012-12-21T13:03:05Z"},"name":"gitlab-recipes","name_with_namespace":"GitLab / gitlab-recipes","path":"gitlab-recipes","path_with_namespace":"gitlab/gitlab-recipes","issues_enabled":true,"merge_requests_enabled":true,"wall_enabled":true,"wiki_enabled":true,"snippets_enabled":true,"created_at":"2012-12-21T13:07:02Z","last_activity_at":"2013-12-02T13:54:10Z","namespace":{"created_at":"2012-12-21T13:03:05Z","description":"Self hosted Git management software","id":4,"name":"GitLab","owner_id":1,"path":"gitlab","updated_at":"2013-03-20T13:29:13Z"}},{"id":8,"description":"ssh access and repository management app for GitLab","default_branch":"master","public":false,"visibility_level":0,"ssh_url_to_repo":"git@demo.gitlab.com:gitlab/gitlab-shell.git","http_url_to_repo":"http://demo.gitlab.com/gitlab/gitlab-shell.git","web_url":"http://demo.gitlab.com/gitlab/gitlab-shell","owner":{"id":4,"name":"GitLab","created_at":"2012-12-21T13:03:05Z"},"name":"gitlab-shell","name_with_namespace":"GitLab / gitlab-shell","path":"gitlab-shell","path_with_namespace":"gitlab/gitlab-shell","issues_enabled":true,"merge_requests_enabled":true,"wall_enabled":false,"wiki_enabled":true,"snippets_enabled":false,"created_at":"2013-03-20T13:28:53Z","last_activity_at":"2013-11-30T00:11:17Z","namespace":{"created_at":"2012-12-21T13:03:05Z","description":"Self hosted Git management software","id":4,"name":"GitLab","owner_id":1,"path":"gitlab","updated_at":"2013-03-20T13:29:13Z"}},{"id":9,"description":null,"default_branch":"master","public":false,"visibility_level":0,"ssh_url_to_repo":"git@demo.gitlab.com:gitlab/gitlab_git.git","http_url_to_repo":"http://demo.gitlab.com/gitlab/gitlab_git.git","web_url":"http://demo.gitlab.com/gitlab/gitlab_git","owner":{"id":4,"name":"GitLab","created_at":"2012-12-21T13:03:05Z"},"name":"gitlab_git","name_with_namespace":"GitLab / gitlab_git","path":"gitlab_git","path_with_namespace":"gitlab/gitlab_git","issues_enabled":true,"merge_requests_enabled":true,"wall_enabled":false,"wiki_enabled":true,"snippets_enabled":false,"created_at":"2013-04-28T19:15:08Z","last_activity_at":"2013-12-02T13:07:13Z","namespace":{"created_at":"2012-12-21T13:03:05Z","description":"Self hosted Git management software","id":4,"name":"GitLab","owner_id":1,"path":"gitlab","updated_at":"2013-03-20T13:29:13Z"}},{"id":10,"description":"ultra lite authorization library http://randx.github.com/six/\\r\\n ","default_branch":"master","public":true,"visibility_level":20,"ssh_url_to_repo":"git@demo.gitlab.com:sandbox/six.git","http_url_to_repo":"http://demo.gitlab.com/sandbox/six.git","web_url":"http://demo.gitlab.com/sandbox/six","owner":{"id":8,"name":"Sandbox","created_at":"2013-08-01T16:44:17Z"},"name":"Six","name_with_namespace":"Sandbox / Six","path":"six","path_with_namespace":"sandbox/six","issues_enabled":true,"merge_requests_enabled":true,"wall_enabled":false,"wiki_enabled":true,"snippets_enabled":false,"created_at":"2013-08-01T16:45:02Z","last_activity_at":"2013-11-29T11:30:56Z","namespace":{"created_at":"2013-08-01T16:44:17Z","description":"","id":8,"name":"Sandbox","owner_id":1,"path":"sandbox","updated_at":"2013-08-01T16:44:17Z"}},{"id":11,"description":"Simple HTML5 Charts using the <canvas> tag ","default_branch":"master","public":false,"visibility_level":0,"ssh_url_to_repo":"git@demo.gitlab.com:sandbox/charts-js.git","http_url_to_repo":"http://demo.gitlab.com/sandbox/charts-js.git","web_url":"http://demo.gitlab.com/sandbox/charts-js","owner":{"id":8,"name":"Sandbox","created_at":"2013-08-01T16:44:17Z"},"name":"Charts.js","name_with_namespace":"Sandbox / Charts.js","path":"charts-js","path_with_namespace":"sandbox/charts-js","issues_enabled":true,"merge_requests_enabled":true,"wall_enabled":false,"wiki_enabled":true,"snippets_enabled":false,"created_at":"2013-08-01T16:47:29Z","last_activity_at":"2013-12-02T15:18:11Z","namespace":{"created_at":"2013-08-01T16:44:17Z","description":"","id":8,"name":"Sandbox","owner_id":1,"path":"sandbox","updated_at":"2013-08-01T16:44:17Z"}},{"id":13,"description":"","default_branch":"master","public":false,"visibility_level":0,"ssh_url_to_repo":"git@demo.gitlab.com:sandbox/afro.git","http_url_to_repo":"http://demo.gitlab.com/sandbox/afro.git","web_url":"http://demo.gitlab.com/sandbox/afro","owner":{"id":8,"name":"Sandbox","created_at":"2013-08-01T16:44:17Z"},"name":"Afro","name_with_namespace":"Sandbox / Afro","path":"afro","path_with_namespace":"sandbox/afro","issues_enabled":true,"merge_requests_enabled":true,"wall_enabled":false,"wiki_enabled":true,"snippets_enabled":false,"created_at":"2013-11-14T17:45:19Z","last_activity_at":"2013-12-02T17:41:45Z","namespace":{"created_at":"2013-08-01T16:44:17Z","description":"","id":8,"name":"Sandbox","owner_id":1,"path":"sandbox","updated_at":"2013-08-01T16:44:17Z"}}] \ No newline at end of file
+[
+ {
+ "id": 3,
+ "description": "GitLab is open source software to collaborate on code. Create projects and repositories, manage access and do code reviews.",
+ "default_branch": "master",
+ "visibility": "public",
+ "ssh_url_to_repo": "git@demo.gitlab.com:gitlab/gitlabhq.git",
+ "http_url_to_repo": "http://demo.gitlab.com/gitlab/gitlabhq.git",
+ "web_url": "http://demo.gitlab.com/gitlab/gitlabhq",
+ "owner": {
+ "id": 4,
+ "name": "GitLab",
+ "username": "gitlab",
+ "state": "active",
+ "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61",
+ "web_url": "http://demo.gitlab.com/gitlab"
+ },
+ "name": "gitlabhq",
+ "name_with_namespace": "GitLab / gitlabhq",
+ "path": "gitlabhq",
+ "path_with_namespace": "gitlab/gitlabhq",
+ "issues_enabled": true,
+ "merge_requests_enabled": true,
+ "wiki_enabled": true,
+ "snippets_enabled": true,
+ "created_at": "2012-12-21T13:06:34Z",
+ "last_activity_at": "2013-12-02T19:10:10Z",
+ "namespace": {
+ "id": 4,
+ "name": "GitLab",
+ "path": "gitlab",
+ "kind": "group",
+ "full_path": "gitlab",
+ "parent_id": null
+ }
+ },
+ {
+ "id": 4,
+ "description": "Component of GitLab CI. Web application",
+ "default_branch": "master",
+ "visibility": "private",
+ "ssh_url_to_repo": "git@demo.gitlab.com:gitlab/gitlab-ci.git",
+ "http_url_to_repo": "http://demo.gitlab.com/gitlab/gitlab-ci.git",
+ "web_url": "http://demo.gitlab.com/gitlab/gitlab-ci",
+ "owner": {
+ "id": 4,
+ "name": "GitLab",
+ "username": "gitlab",
+ "state": "active",
+ "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61",
+ "web_url": "http://demo.gitlab.com/gitlab"
+ },
+ "name": "gitlab-ci",
+ "name_with_namespace": "GitLab / gitlab-ci",
+ "path": "gitlab-ci",
+ "path_with_namespace": "gitlab/gitlab-ci",
+ "issues_enabled": true,
+ "merge_requests_enabled": true,
+ "wiki_enabled": true,
+ "snippets_enabled": true,
+ "created_at": "2012-12-21T13:06:50Z",
+ "last_activity_at": "2013-11-28T19:26:54Z",
+ "namespace": {
+ "id": 4,
+ "name": "GitLab",
+ "path": "gitlab",
+ "kind": "group",
+ "full_path": "gitlab",
+ "parent_id": null
+ }
+ },
+ {
+ "id": 5,
+ "description": "",
+ "default_branch": "master",
+ "visibility": "public",
+ "ssh_url_to_repo": "git@demo.gitlab.com:gitlab/gitlab-recipes.git",
+ "http_url_to_repo": "http://demo.gitlab.com/gitlab/gitlab-recipes.git",
+ "web_url": "http://demo.gitlab.com/gitlab/gitlab-recipes",
+ "owner": {
+ "id": 4,
+ "name": "GitLab",
+ "username": "gitlab",
+ "state": "active",
+ "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61",
+ "web_url": "http://demo.gitlab.com/gitlab"
+ },
+ "name": "gitlab-recipes",
+ "name_with_namespace": "GitLab / gitlab-recipes",
+ "path": "gitlab-recipes",
+ "path_with_namespace": "gitlab/gitlab-recipes",
+ "issues_enabled": true,
+ "merge_requests_enabled": true,
+ "wiki_enabled": true,
+ "snippets_enabled": true,
+ "created_at": "2012-12-21T13:07:02Z",
+ "last_activity_at": "2013-12-02T13:54:10Z",
+ "namespace": {
+ "id": 4,
+ "name": "GitLab",
+ "path": "gitlab",
+ "kind": "group",
+ "full_path": "gitlab",
+ "parent_id": null
+ }
+ },
+ {
+ "id": 8,
+ "description": "ssh access and repository management app for GitLab",
+ "default_branch": "master",
+ "visibility": "private",
+ "ssh_url_to_repo": "git@demo.gitlab.com:gitlab/gitlab-shell.git",
+ "http_url_to_repo": "http://demo.gitlab.com/gitlab/gitlab-shell.git",
+ "web_url": "http://demo.gitlab.com/gitlab/gitlab-shell",
+ "owner": {
+ "id": 4,
+ "name": "GitLab",
+ "username": "gitlab",
+ "state": "active",
+ "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61",
+ "web_url": "http://demo.gitlab.com/gitlab"
+ },
+ "name": "gitlab-shell",
+ "name_with_namespace": "GitLab / gitlab-shell",
+ "path": "gitlab-shell",
+ "path_with_namespace": "gitlab/gitlab-shell",
+ "issues_enabled": true,
+ "merge_requests_enabled": true,
+ "wiki_enabled": true,
+ "snippets_enabled": false,
+ "created_at": "2013-03-20T13:28:53Z",
+ "last_activity_at": "2013-11-30T00:11:17Z",
+ "namespace": {
+ "id": 4,
+ "name": "GitLab",
+ "path": "gitlab",
+ "kind": "group",
+ "full_path": "gitlab",
+ "parent_id": null
+ }
+ },
+ {
+ "id": 9,
+ "description": null,
+ "default_branch": "master",
+ "visibility": "private",
+ "ssh_url_to_repo": "git@demo.gitlab.com:gitlab/gitlab_git.git",
+ "http_url_to_repo": "http://demo.gitlab.com/gitlab/gitlab_git.git",
+ "web_url": "http://demo.gitlab.com/gitlab/gitlab_git",
+ "owner": {
+ "id": 4,
+ "name": "GitLab",
+ "username": "gitlab",
+ "state": "active",
+ "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61",
+ "web_url": "http://demo.gitlab.com/gitlab"
+ },
+ "name": "gitlab_git",
+ "name_with_namespace": "GitLab / gitlab_git",
+ "path": "gitlab_git",
+ "path_with_namespace": "gitlab/gitlab_git",
+ "issues_enabled": true,
+ "merge_requests_enabled": true,
+ "wiki_enabled": true,
+ "snippets_enabled": false,
+ "created_at": "2013-04-28T19:15:08Z",
+ "last_activity_at": "2013-12-02T13:07:13Z",
+ "namespace": {
+ "id": 4,
+ "name": "GitLab",
+ "path": "gitlab",
+ "kind": "group",
+ "full_path": "gitlab",
+ "parent_id": null
+ }
+ },
+ {
+ "id": 10,
+ "description": "ultra lite authorization library http://randx.github.com/six/\\r\\n ",
+ "default_branch": "master",
+ "visibility": "public",
+ "ssh_url_to_repo": "git@demo.gitlab.com:sandbox/six.git",
+ "http_url_to_repo": "http://demo.gitlab.com/sandbox/six.git",
+ "web_url": "http://demo.gitlab.com/sandbox/six",
+ "owner": {
+ "id": 4,
+ "name": "GitLab",
+ "username": "gitlab",
+ "state": "active",
+ "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61",
+ "web_url": "http://demo.gitlab.com/gitlab"
+ },
+ "name": "Six",
+ "name_with_namespace": "Sandbox / Six",
+ "path": "six",
+ "path_with_namespace": "sandbox/six",
+ "issues_enabled": true,
+ "merge_requests_enabled": true,
+ "wiki_enabled": true,
+ "snippets_enabled": false,
+ "created_at": "2013-08-01T16:45:02Z",
+ "last_activity_at": "2013-11-29T11:30:56Z",
+ "namespace": {
+ "id": 4,
+ "name": "GitLab",
+ "path": "gitlab",
+ "kind": "group",
+ "full_path": "gitlab",
+ "parent_id": null
+ }
+ },
+ {
+ "id": 11,
+ "description": "Simple HTML5 Charts using the <canvas> tag ",
+ "default_branch": "master",
+ "visibility": "private",
+ "ssh_url_to_repo": "git@demo.gitlab.com:sandbox/charts-js.git",
+ "http_url_to_repo": "http://demo.gitlab.com/sandbox/charts-js.git",
+ "web_url": "http://demo.gitlab.com/sandbox/charts-js",
+ "owner": {
+ "id": 4,
+ "name": "GitLab",
+ "username": "gitlab",
+ "state": "active",
+ "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61",
+ "web_url": "http://demo.gitlab.com/gitlab"
+ },
+ "name": "Charts.js",
+ "name_with_namespace": "Sandbox / Charts.js",
+ "path": "charts-js",
+ "path_with_namespace": "sandbox/charts-js",
+ "issues_enabled": true,
+ "merge_requests_enabled": true,
+ "wiki_enabled": true,
+ "snippets_enabled": false,
+ "created_at": "2013-08-01T16:47:29Z",
+ "last_activity_at": "2013-12-02T15:18:11Z",
+ "namespace": {
+ "id": 4,
+ "name": "GitLab",
+ "path": "gitlab",
+ "kind": "group",
+ "full_path": "gitlab",
+ "parent_id": null
+ }
+ },
+ {
+ "id": 13,
+ "description": "",
+ "default_branch": "master",
+ "visibility": "private",
+ "ssh_url_to_repo": "git@demo.gitlab.com:sandbox/afro.git",
+ "http_url_to_repo": "http://demo.gitlab.com/sandbox/afro.git",
+ "web_url": "http://demo.gitlab.com/sandbox/afro",
+ "owner": {
+ "id": 4,
+ "name": "GitLab",
+ "username": "gitlab",
+ "state": "active",
+ "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61",
+ "web_url": "http://demo.gitlab.com/gitlab"
+ },
+ "name": "Afro",
+ "name_with_namespace": "Sandbox / Afro",
+ "path": "afro",
+ "path_with_namespace": "sandbox/afro",
+ "issues_enabled": true,
+ "merge_requests_enabled": true,
+ "wiki_enabled": true,
+ "snippets_enabled": false,
+ "created_at": "2013-11-14T17:45:19Z",
+ "last_activity_at": "2013-12-02T17:41:45Z",
+ "namespace": {
+ "id": 4,
+ "name": "GitLab",
+ "path": "gitlab",
+ "kind": "group",
+ "full_path": "gitlab",
+ "parent_id": null
+ }
+ }
+]
diff --git a/spec/support/gitlab_stubs/session.json b/spec/support/gitlab_stubs/session.json
deleted file mode 100644
index 658ff5871b0..00000000000
--- a/spec/support/gitlab_stubs/session.json
+++ /dev/null
@@ -1,18 +0,0 @@
-{
- "id":2,
- "username":"jsmith",
- "email":"test@test.com",
- "name":"John Smith",
- "bio":"",
- "skype":"aertert",
- "linkedin":"",
- "twitter":"",
- "theme_id":2,"color_scheme_id":2,
- "state":"active",
- "created_at":"2012-12-21T13:02:20Z",
- "extern_uid":null,
- "provider":null,
- "is_admin":false,
- "can_create_group":false,
- "can_create_project":false
-}
diff --git a/spec/support/helpers/api_helpers.rb b/spec/support/helpers/api_helpers.rb
index ac0c7a9b493..a57a3b2cf34 100644
--- a/spec/support/helpers/api_helpers.rb
+++ b/spec/support/helpers/api_helpers.rb
@@ -36,15 +36,4 @@ module ApiHelpers
full_path
end
-
- # Temporary helper method for simplifying V3 exclusive API specs
- def v3_api(path, user = nil, personal_access_token: nil, oauth_access_token: nil)
- api(
- path,
- user,
- version: 'v3',
- personal_access_token: personal_access_token,
- oauth_access_token: oauth_access_token
- )
- end
end
diff --git a/spec/support/helpers/seed_repo.rb b/spec/support/helpers/seed_repo.rb
index b4868e82cd7..71f1a86b0c1 100644
--- a/spec/support/helpers/seed_repo.rb
+++ b/spec/support/helpers/seed_repo.rb
@@ -98,6 +98,7 @@ module SeedRepo
master
merge-test
missing-gitmodules
+ Ääh-test-utf-8
].freeze
TAGS = %w[
v1.0.0
diff --git a/spec/support/helpers/stub_gitlab_calls.rb b/spec/support/helpers/stub_gitlab_calls.rb
index c1618f5086c..2933f2c78dc 100644
--- a/spec/support/helpers/stub_gitlab_calls.rb
+++ b/spec/support/helpers/stub_gitlab_calls.rb
@@ -1,6 +1,5 @@
module StubGitlabCalls
def stub_gitlab_calls
- stub_session
stub_user
stub_project_8
stub_project_8_hooks
@@ -71,23 +70,14 @@ module StubGitlabCalls
Gitlab.config.gitlab.url
end
- def stub_session
- f = File.read(Rails.root.join('spec/support/gitlab_stubs/session.json'))
-
- stub_request(:post, "#{gitlab_url}api/v3/session.json")
- .with(body: "{\"email\":\"test@test.com\",\"password\":\"123456\"}",
- headers: { 'Content-Type' => 'application/json' })
- .to_return(status: 201, body: f, headers: { 'Content-Type' => 'application/json' })
- end
-
def stub_user
f = File.read(Rails.root.join('spec/support/gitlab_stubs/user.json'))
- stub_request(:get, "#{gitlab_url}api/v3/user?private_token=Wvjy2Krpb7y8xi93owUz")
+ stub_request(:get, "#{gitlab_url}api/v4/user?private_token=Wvjy2Krpb7y8xi93owUz")
.with(headers: { 'Content-Type' => 'application/json' })
.to_return(status: 200, body: f, headers: { 'Content-Type' => 'application/json' })
- stub_request(:get, "#{gitlab_url}api/v3/user?access_token=some_token")
+ stub_request(:get, "#{gitlab_url}api/v4/user?access_token=some_token")
.with(headers: { 'Content-Type' => 'application/json' })
.to_return(status: 200, body: f, headers: { 'Content-Type' => 'application/json' })
end
@@ -105,19 +95,19 @@ module StubGitlabCalls
def stub_projects
f = File.read(Rails.root.join('spec/support/gitlab_stubs/projects.json'))
- stub_request(:get, "#{gitlab_url}api/v3/projects.json?archived=false&ci_enabled_first=true&private_token=Wvjy2Krpb7y8xi93owUz")
+ stub_request(:get, "#{gitlab_url}api/v4/projects.json?archived=false&ci_enabled_first=true&private_token=Wvjy2Krpb7y8xi93owUz")
.with(headers: { 'Content-Type' => 'application/json' })
.to_return(status: 200, body: f, headers: { 'Content-Type' => 'application/json' })
end
def stub_projects_owned
- stub_request(:get, "#{gitlab_url}api/v3/projects/owned.json?archived=false&ci_enabled_first=true&private_token=Wvjy2Krpb7y8xi93owUz")
+ stub_request(:get, "#{gitlab_url}api/v4/projects?owned=true&archived=false&ci_enabled_first=true&private_token=Wvjy2Krpb7y8xi93owUz")
.with(headers: { 'Content-Type' => 'application/json' })
.to_return(status: 200, body: "", headers: {})
end
def stub_ci_enable
- stub_request(:put, "#{gitlab_url}api/v3/projects/2/services/gitlab-ci.json?private_token=Wvjy2Krpb7y8xi93owUz")
+ stub_request(:put, "#{gitlab_url}api/v4/projects/2/services/gitlab-ci.json?private_token=Wvjy2Krpb7y8xi93owUz")
.with(headers: { 'Content-Type' => 'application/json' })
.to_return(status: 200, body: "", headers: {})
end
diff --git a/spec/support/helpers/test_env.rb b/spec/support/helpers/test_env.rb
index 57aa07cf4fa..1fef50a52ec 100644
--- a/spec/support/helpers/test_env.rb
+++ b/spec/support/helpers/test_env.rb
@@ -47,6 +47,7 @@ module TestEnv
'v1.1.0' => 'b83d6e3',
'add-ipython-files' => '93ee732',
'add-pdf-file' => 'e774ebd',
+ 'squash-large-files' => '54cec52',
'add-pdf-text-binary' => '79faa7b',
'add_images_and_changes' => '010d106'
}.freeze
diff --git a/spec/support/import_export/configuration_helper.rb b/spec/support/import_export/configuration_helper.rb
index f752508d48c..bbac6ca6a9c 100644
--- a/spec/support/import_export/configuration_helper.rb
+++ b/spec/support/import_export/configuration_helper.rb
@@ -10,7 +10,7 @@ module ConfigurationHelper
def relation_class_for_name(relation_name)
relation_name = Gitlab::ImportExport::RelationFactory::OVERRIDES[relation_name.to_sym] || relation_name
- relation_name.to_s.classify.constantize
+ Gitlab::ImportExport::RelationFactory.relation_class(relation_name)
end
def parsed_attributes(relation_name, attributes)
diff --git a/spec/support/shared_examples/requests/api/merge_requests_list.rb b/spec/support/shared_examples/requests/api/merge_requests_list.rb
new file mode 100644
index 00000000000..d5e22b8cb56
--- /dev/null
+++ b/spec/support/shared_examples/requests/api/merge_requests_list.rb
@@ -0,0 +1,280 @@
+shared_examples 'merge requests list' do
+ context 'when unauthenticated' do
+ it 'returns merge requests for public projects' do
+ get api(endpoint_path)
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(json_response).to be_an Array
+ end
+ end
+
+ context 'when authenticated' do
+ it 'avoids N+1 queries' do
+ control = ActiveRecord::QueryRecorder.new do
+ get api(endpoint_path, user)
+ end
+
+ create(:merge_request, state: 'closed', milestone: milestone1, author: user, assignee: user, source_project: project, target_project: project, title: 'Test', created_at: base_time)
+
+ create(:merge_request, milestone: milestone1, author: user, assignee: user, source_project: project, target_project: project, title: 'Test', created_at: base_time)
+
+ expect do
+ get api(endpoint_path, user)
+ end.not_to exceed_query_limit(control)
+ end
+
+ it 'returns an array of all merge_requests' do
+ get api(endpoint_path, user)
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response).to include_pagination_headers
+ expect(json_response).to be_an Array
+ expect(json_response.length).to eq(3)
+ expect(json_response.last['title']).to eq(merge_request.title)
+ expect(json_response.last).to have_key('web_url')
+ expect(json_response.last['sha']).to eq(merge_request.diff_head_sha)
+ expect(json_response.last['merge_commit_sha']).to be_nil
+ expect(json_response.last['merge_commit_sha']).to eq(merge_request.merge_commit_sha)
+ expect(json_response.last['downvotes']).to eq(1)
+ expect(json_response.last['upvotes']).to eq(1)
+ expect(json_response.last['labels']).to eq([label2.title, label.title])
+ expect(json_response.first['title']).to eq(merge_request_merged.title)
+ expect(json_response.first['sha']).to eq(merge_request_merged.diff_head_sha)
+ expect(json_response.first['merge_commit_sha']).not_to be_nil
+ expect(json_response.first['merge_commit_sha']).to eq(merge_request_merged.merge_commit_sha)
+ end
+
+ it 'returns an array of all merge_requests using simple mode' do
+ path = endpoint_path + '?view=simple'
+
+ get api(path, user)
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response).to include_pagination_headers
+ expect(json_response.last.keys).to match_array(%w(id iid title web_url created_at description project_id state updated_at))
+ expect(json_response).to be_an Array
+ expect(json_response.length).to eq(3)
+ expect(json_response.last['iid']).to eq(merge_request.iid)
+ expect(json_response.last['title']).to eq(merge_request.title)
+ expect(json_response.last).to have_key('web_url')
+ expect(json_response.first['iid']).to eq(merge_request_merged.iid)
+ expect(json_response.first['title']).to eq(merge_request_merged.title)
+ expect(json_response.first).to have_key('web_url')
+ end
+
+ it 'returns an array of all merge_requests' do
+ path = endpoint_path + '?state'
+
+ get api(path, user)
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response).to include_pagination_headers
+ expect(json_response).to be_an Array
+ expect(json_response.length).to eq(3)
+ expect(json_response.last['title']).to eq(merge_request.title)
+ end
+
+ it 'returns an array of open merge_requests' do
+ path = endpoint_path + '?state=opened'
+
+ get api(path, user)
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response).to include_pagination_headers
+ expect(json_response).to be_an Array
+ expect(json_response.length).to eq(1)
+ expect(json_response.last['title']).to eq(merge_request.title)
+ end
+
+ it 'returns an array of closed merge_requests' do
+ path = endpoint_path + '?state=closed'
+
+ get api(path, user)
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response).to include_pagination_headers
+ expect(json_response).to be_an Array
+ expect(json_response.length).to eq(1)
+ expect(json_response.first['title']).to eq(merge_request_closed.title)
+ end
+
+ it 'returns an array of merged merge_requests' do
+ path = endpoint_path + '?state=merged'
+
+ get api(path, user)
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response).to include_pagination_headers
+ expect(json_response).to be_an Array
+ expect(json_response.length).to eq(1)
+ expect(json_response.first['title']).to eq(merge_request_merged.title)
+ end
+
+ it 'matches V4 response schema' do
+ get api(endpoint_path, user)
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response).to match_response_schema('public_api/v4/merge_requests')
+ end
+
+ it 'returns an empty array if no issue matches milestone' do
+ get api(endpoint_path, user), milestone: '1.0.0'
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(json_response).to be_an Array
+ expect(json_response.length).to eq(0)
+ end
+
+ it 'returns an empty array if milestone does not exist' do
+ get api(endpoint_path, user), milestone: 'foo'
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(json_response).to be_an Array
+ expect(json_response.length).to eq(0)
+ end
+
+ it 'returns an array of merge requests in given milestone' do
+ get api(endpoint_path, user), milestone: '0.9'
+
+ expect(json_response.first['title']).to eq merge_request_closed.title
+ expect(json_response.first['id']).to eq merge_request_closed.id
+ end
+
+ it 'returns an array of merge requests matching state in milestone' do
+ get api(endpoint_path, user), milestone: '0.9', state: 'closed'
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(json_response).to be_an Array
+ expect(json_response.length).to eq(1)
+ expect(json_response.first['id']).to eq(merge_request_closed.id)
+ end
+
+ it 'returns an array of labeled merge requests' do
+ path = endpoint_path + "?labels=#{label.title}"
+
+ get api(path, user)
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(json_response).to be_an Array
+ expect(json_response.length).to eq(1)
+ expect(json_response.first['labels']).to eq([label2.title, label.title])
+ end
+
+ it 'returns an array of labeled merge requests where all labels match' do
+ path = endpoint_path + "?labels=#{label.title},foo,bar"
+
+ get api(path, user)
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(json_response).to be_an Array
+ expect(json_response.length).to eq(0)
+ end
+
+ it 'returns an empty array if no merge request matches labels' do
+ path = endpoint_path + '?labels=foo,bar'
+
+ get api(path, user)
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(json_response).to be_an Array
+ expect(json_response.length).to eq(0)
+ end
+
+ it 'returns an array of labeled merge requests that are merged for a milestone' do
+ bug_label = create(:label, title: 'bug', color: '#FFAABB', project: project)
+
+ mr1 = create(:merge_request, state: 'merged', source_project: project, target_project: project, milestone: milestone)
+ mr2 = create(:merge_request, state: 'merged', source_project: project, target_project: project, milestone: milestone1)
+ mr3 = create(:merge_request, state: 'closed', source_project: project, target_project: project, milestone: milestone1)
+ _mr = create(:merge_request, state: 'merged', source_project: project, target_project: project, milestone: milestone1)
+
+ create(:label_link, label: bug_label, target: mr1)
+ create(:label_link, label: bug_label, target: mr2)
+ create(:label_link, label: bug_label, target: mr3)
+
+ path = endpoint_path + "?labels=#{bug_label.title}&milestone=#{milestone1.title}&state=merged"
+
+ get api(path, user)
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(json_response).to be_an Array
+ expect(json_response.length).to eq(1)
+ expect(json_response.first['id']).to eq(mr2.id)
+ end
+
+ context 'with ordering' do
+ before do
+ @mr_later = mr_with_later_created_and_updated_at_time
+ @mr_earlier = mr_with_earlier_created_and_updated_at_time
+ end
+
+ it 'returns an array of merge_requests in ascending order' do
+ path = endpoint_path + '?sort=asc'
+
+ get api(path, user)
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response).to include_pagination_headers
+ expect(json_response).to be_an Array
+ expect(json_response.length).to eq(3)
+ response_dates = json_response.map { |merge_request| merge_request['created_at'] }
+ expect(response_dates).to eq(response_dates.sort)
+ end
+
+ it 'returns an array of merge_requests in descending order' do
+ path = endpoint_path + '?sort=desc'
+
+ get api(path, user)
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response).to include_pagination_headers
+ expect(json_response).to be_an Array
+ expect(json_response.length).to eq(3)
+ response_dates = json_response.map { |merge_request| merge_request['created_at'] }
+ expect(response_dates).to eq(response_dates.sort.reverse)
+ end
+
+ it 'returns an array of merge_requests ordered by updated_at' do
+ path = endpoint_path + '?order_by=updated_at'
+
+ get api(path, user)
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response).to include_pagination_headers
+ expect(json_response).to be_an Array
+ expect(json_response.length).to eq(3)
+ response_dates = json_response.map { |merge_request| merge_request['updated_at'] }
+ expect(response_dates).to eq(response_dates.sort.reverse)
+ end
+
+ it 'returns an array of merge_requests ordered by created_at' do
+ path = endpoint_path + '?order_by=created_at&sort=asc'
+
+ get api(path, user)
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response).to include_pagination_headers
+ expect(json_response).to be_an Array
+ expect(json_response.length).to eq(3)
+ response_dates = json_response.map { |merge_request| merge_request['created_at'] }
+ expect(response_dates).to eq(response_dates.sort)
+ end
+ end
+
+ context 'source_branch param' do
+ it 'returns merge requests with the given source branch' do
+ get api(endpoint_path, user), source_branch: merge_request_closed.source_branch, state: 'all'
+
+ expect_response_contain_exactly(merge_request_closed, merge_request_merged)
+ end
+ end
+
+ context 'target_branch param' do
+ it 'returns merge requests with the given target branch' do
+ get api(endpoint_path, user), target_branch: merge_request_closed.target_branch, state: 'all'
+
+ expect_response_contain_exactly(merge_request_closed, merge_request_merged)
+ end
+ end
+ end
+end
diff --git a/spec/tasks/gitlab/storage_rake_spec.rb b/spec/tasks/gitlab/storage_rake_spec.rb
index f59792c3d36..35e451b2f9a 100644
--- a/spec/tasks/gitlab/storage_rake_spec.rb
+++ b/spec/tasks/gitlab/storage_rake_spec.rb
@@ -1,13 +1,49 @@
require 'rake_helper'
-describe 'gitlab:storage rake tasks' do
+describe 'gitlab:storage:*' do
before do
Rake.application.rake_require 'tasks/gitlab/storage'
stub_warn_user_is_not_gitlab
end
- describe 'migrate_to_hashed rake task' do
+ shared_examples "rake listing entities" do |entity_name, storage_type|
+ context 'limiting to 2' do
+ before do
+ stub_env('LIMIT' => 2)
+ end
+
+ it "lists 2 out of 3 #{storage_type.downcase} #{entity_name}" do
+ create_collection
+
+ expect { run_rake_task(task) }.to output(/Found 3 #{entity_name} using #{storage_type} Storage.*Displaying first 2 #{entity_name}/m).to_stdout
+ end
+ end
+
+ context "without any #{storage_type.downcase} #{entity_name.singularize}" do
+ it 'displays message for empty results' do
+ expect { run_rake_task(task) }.to output(/Found 0 #{entity_name} using #{storage_type} Storage/).to_stdout
+ end
+ end
+ end
+
+ shared_examples "rake entities summary" do |entity_name, storage_type|
+ context "with existing 3 #{storage_type.downcase} #{entity_name}" do
+ it "reports 3 #{storage_type.downcase} #{entity_name}" do
+ create_collection
+
+ expect { run_rake_task(task) }.to output(/Found 3 #{entity_name} using #{storage_type} Storage/).to_stdout
+ end
+ end
+
+ context "without any #{storage_type.downcase} #{entity_name.singularize}" do
+ it 'displays message for empty results' do
+ expect { run_rake_task(task) }.to output(/Found 0 #{entity_name} using #{storage_type} Storage/).to_stdout
+ end
+ end
+ end
+
+ describe 'gitlab:storage:migrate_to_hashed' do
context '0 legacy projects' do
it 'does nothing' do
expect(StorageMigratorWorker).not_to receive(:perform_async)
@@ -16,8 +52,8 @@ describe 'gitlab:storage rake tasks' do
end
end
- context '5 legacy projects' do
- let(:projects) { create_list(:project, 5, storage_version: 0) }
+ context '3 legacy projects' do
+ let(:projects) { create_list(:project, 3, storage_version: 0) }
context 'in batches of 1' do
before do
@@ -49,4 +85,64 @@ describe 'gitlab:storage rake tasks' do
end
end
end
+
+ describe 'gitlab:storage:legacy_projects' do
+ it_behaves_like 'rake entities summary', 'projects', 'Legacy' do
+ let(:task) { 'gitlab:storage:legacy_projects' }
+ let(:create_collection) { create_list(:project, 3, storage_version: 0) }
+ end
+ end
+
+ describe 'gitlab:storage:list_legacy_projects' do
+ it_behaves_like 'rake listing entities', 'projects', 'Legacy' do
+ let(:task) { 'gitlab:storage:list_legacy_projects' }
+ let(:create_collection) { create_list(:project, 3, storage_version: 0) }
+ end
+ end
+
+ describe 'gitlab:storage:hashed_projects' do
+ it_behaves_like 'rake entities summary', 'projects', 'Hashed' do
+ let(:task) { 'gitlab:storage:hashed_projects' }
+ let(:create_collection) { create_list(:project, 3, storage_version: 1) }
+ end
+ end
+
+ describe 'gitlab:storage:list_hashed_projects' do
+ it_behaves_like 'rake listing entities', 'projects', 'Hashed' do
+ let(:task) { 'gitlab:storage:list_hashed_projects' }
+ let(:create_collection) { create_list(:project, 3, storage_version: 1) }
+ end
+ end
+
+ describe 'gitlab:storage:legacy_attachments' do
+ it_behaves_like 'rake entities summary', 'attachments', 'Legacy' do
+ let(:task) { 'gitlab:storage:legacy_attachments' }
+ let(:project) { create(:project, storage_version: 1) }
+ let(:create_collection) { create_list(:upload, 3, model: project) }
+ end
+ end
+
+ describe 'gitlab:storage:list_legacy_attachments' do
+ it_behaves_like 'rake listing entities', 'attachments', 'Legacy' do
+ let(:task) { 'gitlab:storage:list_legacy_attachments' }
+ let(:project) { create(:project, storage_version: 1) }
+ let(:create_collection) { create_list(:upload, 3, model: project) }
+ end
+ end
+
+ describe 'gitlab:storage:hashed_attachments' do
+ it_behaves_like 'rake entities summary', 'attachments', 'Hashed' do
+ let(:task) { 'gitlab:storage:hashed_attachments' }
+ let(:project) { create(:project, storage_version: 2) }
+ let(:create_collection) { create_list(:upload, 3, model: project) }
+ end
+ end
+
+ describe 'gitlab:storage:list_hashed_attachments' do
+ it_behaves_like 'rake listing entities', 'attachments', 'Hashed' do
+ let(:task) { 'gitlab:storage:list_hashed_attachments' }
+ let(:project) { create(:project, storage_version: 2) }
+ let(:create_collection) { create_list(:upload, 3, model: project) }
+ end
+ end
end
diff --git a/spec/tasks/tokens_spec.rb b/spec/tasks/tokens_spec.rb
index 51f7a536cbb..555a58e9aa1 100644
--- a/spec/tasks/tokens_spec.rb
+++ b/spec/tasks/tokens_spec.rb
@@ -13,9 +13,9 @@ describe 'tokens rake tasks' do
end
end
- describe 'reset_all_rss task' do
+ describe 'reset_all_feed task' do
it 'invokes create_hooks task' do
- expect { run_rake_task('tokens:reset_all_rss') }.to change { user.reload.rss_token }
+ expect { run_rake_task('tokens:reset_all_feed') }.to change { user.reload.feed_token }
end
end
end
diff --git a/spec/uploaders/object_storage_spec.rb b/spec/uploaders/object_storage_spec.rb
index 4165a005063..2dd0925a8e6 100644
--- a/spec/uploaders/object_storage_spec.rb
+++ b/spec/uploaders/object_storage_spec.rb
@@ -382,6 +382,8 @@ describe ObjectStorage do
is_expected.to have_key(:RemoteObject)
expect(subject[:RemoteObject]).to have_key(:ID)
+ expect(subject[:RemoteObject]).to include(Timeout: a_kind_of(Integer))
+ expect(subject[:RemoteObject][:Timeout]).to be(ObjectStorage::DIRECT_UPLOAD_TIMEOUT)
expect(subject[:RemoteObject]).to have_key(:GetURL)
expect(subject[:RemoteObject]).to have_key(:DeleteURL)
expect(subject[:RemoteObject]).to have_key(:StoreURL)
diff --git a/spec/workers/concerns/waitable_worker_spec.rb b/spec/workers/concerns/waitable_worker_spec.rb
index 54ab07981a4..199825b5097 100644
--- a/spec/workers/concerns/waitable_worker_spec.rb
+++ b/spec/workers/concerns/waitable_worker_spec.rb
@@ -7,9 +7,7 @@ describe WaitableWorker do
'Gitlab::Foo::Bar::DummyWorker'
end
- class << self
- cattr_accessor(:counter) { 0 }
- end
+ cattr_accessor(:counter) { 0 }
include ApplicationWorker
prepend WaitableWorker